⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.c

📁 fdisk 实现源码,可以查询Linux下系统的分区信息
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    GNU fdisk - a clone of Linux fdisk.    Copyright (C) 2006    Free Software Foundation, Inc.    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 3 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA*/#include "../config.h"#include "strlist.h"#define N_(String) String#if ENABLE_NLS#  include <libintl.h>#  include <locale.h>#  define _(String) dgettext (PACKAGE, String)#  define P_(String) dgettext ("parted", String)#else#  define _(String) (String)#  define P_(String) (String)#endif /* ENABLE_NLS */#include <parted/parted.h>#include <parted/debug.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "common.h"#define SMALLBUF 256/* Here we store the struct with interface functions */static UICalls *uiquery;static int MEGABYTE_SECTORS (PedDevice* dev){        return PED_MEGABYTE_SIZE / dev->sector_size;}/* TODO: Decide if these should be moved to UICalls */StrList *disk_type_list;StrList *fs_type_list;//StrList *fs_type_resize;StrList *fs_type_mkfs;StrList *flag_name_list;intinit_flag_str (){	PedPartitionFlag walk;	flag_name_list = NULL;	for (walk = ped_partition_flag_next(0); walk; walk =ped_partition_flag_next(walk)) {		flag_name_list = str_list_append(flag_name_list, ped_partition_flag_get_name(walk));		if (!flag_name_list)			return 0;	}	return 1;}intinit_fs_type_str (){	PedFileSystemType*	walk;	fs_type_list = NULL;	for (walk = ped_file_system_type_get_next (NULL); walk;	     walk = ped_file_system_type_get_next (walk))	{		fs_type_list = str_list_append (fs_type_list, walk->name);		if (walk->ops->create != NULL)			fs_type_mkfs = str_list_append(fs_type_mkfs, walk->name);		//if (talk->ops->resize != NULL)		//	fs_type_resize = str_list_append(fs_type_mkfs, walk->name);		if (!fs_type_list)			return 0;	}	return 1;}intinit_disk_type_str (){	PedDiskType*	walk;	disk_type_list = NULL;	for (walk = ped_disk_type_get_next (NULL); walk;	     walk = ped_disk_type_get_next (walk))	{		disk_type_list = str_list_append (disk_type_list, walk->name);		if (!disk_type_list)			return 0;	}	return 1;}int_can_create_primary (const PedDisk* disk){	int	i;	for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) {		if (!ped_disk_get_partition (disk, i))			return 1;	}	return 0;}int_can_create_extended (const PedDisk* disk){	if (!_can_create_primary (disk))		return 0;	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))		return 0;	if (ped_disk_extended_partition (disk))		return 0;	return 1;}int_can_create_logical (const PedDisk* disk){	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))		return 0;	return ped_disk_extended_partition (disk) != 0;}static int_partition_warn_busy (PedPartition* part){	char* path = ped_partition_get_path (part);	if (ped_partition_is_busy (part)) {		ped_exception_throw (			PED_EXCEPTION_ERROR,			PED_EXCEPTION_CANCEL,			_("Partition %s is being used.  You must unmount it "			  "before you modify it."),			path);		ped_free (path);		return 0;	}	ped_free (path);	return 1;}static int_disk_warn_busy (PedDisk* disk){	if (ped_device_is_busy (disk->dev)) {		if (ped_exception_throw (			PED_EXCEPTION_WARNING,			PED_EXCEPTION_IGNORE_CANCEL,			_("Partition(s) on %s are being used."),			disk->dev->path)				!= PED_EXCEPTION_IGNORE)			return 0;	}	return 1;}static int_warn_ext_not_empty (PedPartition *part) {	/* If this is not an extended partition, it is ok */	if (!(part->type & PED_PARTITION_EXTENDED))		return 1;	for (part = part->part_list; part;	     part = part->next) {		if (part->type == PED_PARTITION_LOGICAL) {			if(ped_exception_throw (				PED_EXCEPTION_WARNING,				PED_EXCEPTION_YES_NO,				_("The extended partition is not empty. "				  "Deleting it will delete any partitions "				  "inside it. Do you want to continue?"))					== PED_EXCEPTION_NO)				return 0;			else				return 1;		}	}	return 1;}/* Get previous non-METADATA partition. */PedPartition *disk_get_prev_nmd_partition(PedDisk *disk, PedPartition *part) {	PedPartition *walk_a, *walk_b;	/* walk_a will iterate through partitions that are not METADATA, while	   walk_b will iterate through all partitions. When walk_b reaches our partition,	   walk_a is the partition we are looking for. */	walk_a = NULL;	walk_b = walk_a;	do {		if (ped_disk_next_partition(disk,walk_b) == part)			break;		walk_b = ped_disk_next_partition(disk,walk_b);		if (!walk_b || !(walk_b->type & PED_PARTITION_METADATA))			walk_a = walk_b;	} while (walk_b);	return walk_a;}/* This function returns the number of a metadata sectors, which are needed   after a partition, for example, in msdos partition table, the sector,    after a logical partition, describes the next logical partition */static PedSector metadata_tail_sectors(PedPartition *part) {	/* TODO: Make this support other partition types */	if (part == NULL || part->disk->type == NULL)		return 0;		if (!strcmp(part->disk->type->name, "msdos") 	      && part->type & PED_PARTITION_LOGICAL) {		return 1;	}	return 0;}/* This function changes "sector" to "new_sector" if the new value lies * within the required range. */static intsnap (PedSector* sector, PedSector new_sector, PedGeometry* range){        PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0);        if (!ped_geometry_test_sector_inside (range, new_sector))                return 0;        *sector = new_sector;        return 1;}typedef enum {        MOVE_NO         = 0,        MOVE_STILL      = 1,        MOVE_UP         = 2,        MOVE_DOWN       = 4} EMoves;enum { /* Don't change these values */        SECT_START      =  0,        SECT_END        = -1};/* Find the prefered way to adjust the sector s inside range. * If a move isn't allowed or is out of range it can't be selected. * what contains SECT_START if the sector to adjust is a start sector * or SECT_END if it's an end one. * The prefered move is to the nearest allowed boundary of the part * partition (if at equal distance: to start if SECT_START or to end * if SECT_END). * The distance is returned in dist. */static EMovesprefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow,             PedPartition* part, PedSector* dist){        PedSector up_dist = -1, down_dist = -1;        PedSector new_sect;        EMoves move;        PED_ASSERT (what == SECT_START || what == SECT_END, return 0);        if (!(*allow & (MOVE_UP | MOVE_DOWN))) {                *dist = 0;                return MOVE_STILL;        }        if (*allow & MOVE_UP) {                new_sect = part->geom.end + 1 + what;                if (ped_geometry_test_sector_inside (range, new_sect))                        up_dist = new_sect - s;                else                        *allow &= ~MOVE_UP;        }        if (*allow & MOVE_DOWN) {                new_sect = part->geom.start + what;                if (ped_geometry_test_sector_inside (range, new_sect))                        down_dist = s - new_sect;                else                        *allow &= ~MOVE_DOWN;        }        move = MOVE_STILL;        if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) {                if (down_dist < up_dist || (down_dist == up_dist                                            && what == SECT_START) )                        move = MOVE_DOWN;                else if (up_dist < down_dist || (down_dist == up_dist                                                 && what == SECT_END) )                        move = MOVE_UP;                else                        PED_ASSERT (0, return 0);        } else if (*allow & MOVE_UP)                move = MOVE_UP;        else if (*allow & MOVE_DOWN)                move = MOVE_DOWN;        *dist = ( move == MOVE_DOWN ? down_dist :                ( move == MOVE_UP   ? up_dist   :                  0 ) );        return move;}/* Snaps a partition to nearby partition boundaries.  This is useful for * gobbling up small amounts of free space, and also for reinterpreting small * changes to a partition as non-changes (eg: perhaps the user only wanted to * resize the end of a partition). *      Note that this isn't the end of the story... this function is * always called before the constraint solver kicks in.  So you don't need to * worry too much about inadvertantly creating overlapping partitions, etc. */static voidsnap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,                    PedDisk* disk,                    PedGeometry* start_range, PedGeometry* end_range){        PedPartition*   start_part;        PedPartition*   end_part;        PedSector       start = new_geom->start;        PedSector       end = new_geom->end;        PedSector       start_dist = -1, end_dist = -1;        EMoves          start_allow, end_allow, start_want, end_want;        int             adjacent;        start_want = end_want = MOVE_NO;        start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN;        start_part = ped_disk_get_partition_by_sector (disk, start);        end_part = ped_disk_get_partition_by_sector (disk, end);        adjacent = (start_part->geom.end + 1 == end_part->geom.start);        /* If we can snap to old_geom, then we will... */        /* and this will enforce the snapped positions  */        if (old_geom) {                if (snap (&start, old_geom->start, start_range))                        start_allow = MOVE_STILL;                if (snap (&end, old_geom->end, end_range))                        end_allow = MOVE_STILL;        }        /* If start and end are on the same partition, we */        /* don't allow them to cross. */        if (start_part == end_part) {                start_allow &= ~MOVE_UP;                end_allow &= ~MOVE_DOWN;        }        /* Let's find our way */        start_want = prefer_snap (start, SECT_START, start_range, &start_allow,                                  start_part, &start_dist );        end_want = prefer_snap (end, SECT_END, end_range, &end_allow,                                end_part, &end_dist );        PED_ASSERT (start_dist >= 0 && end_dist >= 0, return);        /* If start and end are on adjacent partitions,    */        /* and if they would prefer crossing, then refrain */        /* the farthest to do so. */        if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) {                if (end_dist < start_dist) {                        start_allow &= ~MOVE_UP;                        start_want = prefer_snap (start, SECT_START,                                                  start_range, &start_allow,                                                  start_part, &start_dist );                        PED_ASSERT (start_dist >= 0, return);                } else {                        end_allow &= ~MOVE_DOWN;                        end_want = prefer_snap (end, SECT_END,                                                end_range, &end_allow,                                                end_part, &end_dist );                        PED_ASSERT (end_dist >= 0, return);                }        }        /* New positions */        start = ( start_want == MOVE_DOWN ? start_part->geom.start :                ( start_want == MOVE_UP ? start_part->geom.end + 1 :                  start ) );        end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 :              ( end_want == MOVE_UP ? end_part->geom.end :                end ) );        PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return);        PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return);        PED_ASSERT (start <= end,                    PED_DEBUG (0, "start = %d, end = %d\n", start, end));        ped_geometry_set (new_geom, start, end - start + 1);}/* This function makes a range less strict... *//* FIXME: Make this in a better way */static voidfuzzify (PedGeometry *geom, PedDevice *dev, PedConstraint *constraint, 	 PedSector before, PedSector after) {	PedGeometry *new_geom;	if (!constraint)		constraint = ped_device_get_constraint(dev);	PedSector start = geom->start-before;	start = (start > 0 ? start : 0);	PedSector end = geom->start+after;	end = (end < dev->length-1LL ? end : dev->length-1LL);	ped_geometry_set (geom, start, end-start+1);	new_geom = ped_constraint_solve_nearest (constraint, geom);	ped_geometry_set (geom, new_geom->start, new_geom->length);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -