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

📄 hacks.c

📁 fdisk 实现源码,可以查询Linux下系统的分区信息
💻 C
字号:
/*    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 <string.h>#include <stdint.h>#include <sys/stat.h>#include <fcntl.h>#include "hacks.h"#include "sys_types.h"/* FIXME: As the file is needed for lfdisk, calling it "hacks" might * not be the greatest idea. Rename to something. *//* TODO: This might go into libparted *//* Check if it is a block device. Returns -1 if not found. */int is_blockdev(const char *file) {	struct stat file_stat;	if (stat(file,&file_stat) < 0)		return -1;	if(S_ISBLK(file_stat.st_mode))		return 1;	else		return 0;}/* We need a function to get disk type-specific info about filesystem *//* TODO: Decide if we actually need all these... I think we should leave them, at least for the    msdos partition type. *//* NOTE: We will only read the first byte of the pointer, so I don't believe this can blow up   if someone decides to change the struct, only might begin showing wrong info. */#if MSDOS_HACKtypedef struct {        unsigned char   system;        int             boot;        int             hidden;        int             raid;        int             lvm;        int             lba;        int             palo;        int             prep;        void*      orig;                   /* We don't need this */} DosPartitionData;#endif#if MAC_HACK/* FIXME: This could lead to problems. I rely on the belief that the struct will change as little as   possible. If these strings are stored in memory as I believe they are, there is almost no possibility   that it leads to crashes if the struct changes */typedef struct {	char		volume_name[33];	/* eg: "Games" */	char		system_name[33];	/* eg: "Apple_Unix_SVR2" */	char		processor_name[17];	int		is_boot;	int		is_driver;	int		is_root;	int		is_swap;	int		is_lvm;	int		is_raid;	PedSector	data_region_length;	PedSector	boot_region_length;	long long	boot_base_address;	long long	boot_entry_address;	int		boot_checksum;	uint32_t	status;	uint32_t	driver_sig;} MacPartitionData;#endif#if SUN_HACKtypedef struct {	u_int8_t		type;	int			is_boot;	int			is_root;	int			is_lvm;} SunPartitionData;#endif#if BSD_HACKtypedef struct {	uint8_t		type;} BSDPartitionData;#endif#if DVH_HACKtypedef struct  {	int	type;	//char	name[VDNAMESIZE + 1];	/* boot volumes only */	//int	real_file_size;		/* boot volumes only */} DVHPartitionData;#endif#if 0/* I don't think so... */typedef struct {        uint32_t time_low;        uint16_t time_mid;        uint16_t time_hi_and_version;        uint8_t  clock_seq_hi_and_reserved;        uint8_t  clock_seq_low;        uint8_t  node[6];} /* __attribute__ ((packed)) */ efi_guid_t;typedef struct {	efi_guid_t	type;	efi_guid_t	uuid;	char		name[37];	int		lvm;	int		raid;	int		boot;	int		hp_service;        int             hidden;        int             msftres;} GPTPartitionData;#endif#if PC98_HACKtypedef struct {	PedSector	ipl_sector;	int		system;	int		boot;	int		hidden;	char		name [17];} PC98PartitionData;#endif#if AMIGA_HACKtypedef struct {    uint32_t	pb_ID;			/* Identifier 32 bit word : 'PART' */    uint32_t	pb_SummedLongs;		/* Size of the structure for checksums */    int32_t	pb_ChkSum;		/* Checksum of the structure */    uint32_t	pb_HostID;		/* SCSI Target ID of host, not really used */    uint32_t	pb_Next;		/* Block number of the next PartitionBlock */    uint32_t	pb_Flags;		/* Part Flags (NOMOUNT and BOOTABLE) */    uint32_t	pb_Reserved1[2];    uint32_t	pb_DevFlags;		/* Preferred flags for OpenDevice */    char	pb_DriveName[32];	/* Preferred DOS device name: BSTR form */    uint32_t	pb_Reserved2[15];    uint32_t	de_TableSize;		/* Size of Environment vector */    uint32_t	de_SizeBlock;		/* Size of the blocks in 32 bit words, usually 128 */    uint32_t	de_SecOrg;	     	/* Not used; must be 0 */    uint32_t	de_Surfaces;		/* Number of heads (surfaces) */    uint32_t	de_SectorPerBlock;	/* Disk sectors per block, used with SizeBlock, usually 1 */    uint32_t	de_BlocksPerTrack;	/* Blocks per track. drive specific */    uint32_t	de_Reserved;		/* DOS reserved blocks at start of partition. */    uint32_t	de_PreAlloc;		/* DOS reserved blocks at end of partition */    uint32_t	de_Interleave;		/* Not used, usually 0 */    uint32_t	de_LowCyl;		/* First cylinder of the partition */    uint32_t	de_HighCyl;		/* Last cylinder of the partition */    uint32_t	de_NumBuffers;		/* Initial # DOS of buffers.  */    uint32_t	de_BufMemType;		/* Type of mem to allocate for buffers */    uint32_t	de_MaxTransfer;		/* Max number of bytes to transfer at a time */    uint32_t	de_Mask;		/* Address Mask to block out certain memory */    int32_t	de_BootPri;		/* Boot priority for autoboot */    uint32_t	de_DosType;		/* Dostype of the file system */    uint32_t	de_Baud;		/* Baud rate for serial handler */    uint32_t	de_Control;		/* Control word for handler/filesystem */    uint32_t	de_BootBlocks;		/* Number of blocks containing boot code */    uint32_t	pb_EReserved[12];} AmigaPartitionData;#endifSysType *get_disklabel_system_types (const PedDiskType *type) {	#if MSDOS_HACK	if (!strcmp(type->name,"msdos")) 		return msdos_systypes;	else	#endif	#if SUN_HACK	if (!strcmp(type->name,"sun"))		return sun_systypes;	else	#endif	#if BSD_HACK	if (!strcmp(type->name,"bsd"))		return bsd_systypes;	else	#endif	return NULL;	}/* FIXME: This is temporary, make it better, split data into a seperate file *//* Returns the name of the filesystem. If short is 1, it removes the   "Apple_" from the name on mac partition table */const char*get_disk_specific_system_name (const PedPartition* part, int brief) {	if (!part->disk_specific) return NULL;	#if MSDOS_HACK	if (!strcmp(part->disk->type->name,"msdos")) {		int i;		DosPartitionData *pd = (DosPartitionData *)part->disk_specific;		for (i = 0; msdos_systypes[i].name; i++) {			if(msdos_systypes[i].type == pd->system) {				return msdos_systypes[i].name;			}		}	}	else	#endif	/* I believe these should be the same, but I'm not sure */	#if SUN_HACK	if (!strcmp(part->disk->type->name,"sun")) {		int i;		SunPartitionData *pd = (SunPartitionData *)part->disk_specific;		for (i = 0; sun_systypes[i].name; i++) {			if(sun_systypes[i].type == pd->type) {				return sun_systypes[i].name;			}		}	}	else	#endif	#if BSD_HACK	if (!strcmp(part->disk->type->name,"bsd")) {		int i;		BSDPartitionData *pd = (BSDPartitionData *)part->disk_specific;		for (i = 0; bsd_systypes[i].name; i++) {			if(bsd_systypes[i].type == pd->type) {				return bsd_systypes[i].name;			}		}	}	else	#endif	#if MAC_HACK	if (!strcmp(part->disk->type->name,"mac")) {		MacPartitionData *pd = (MacPartitionData *)part->disk_specific;		const char* type = pd->system_name;		if (strncmp(type,"Apple_",6))			return NULL;		else {			if (brief)				return type+6;			else				return type;		}	}	else	#endif	return NULL;}/* I'm lazy to write */#define return_system_type(ltype,stype,type_var) \	if (!strcmp(part->disk->type->name,(ltype))) { \		stype *pd = (stype *) part->disk_specific; \		if (size) \			*size = sizeof(pd->type_var); \		return pd->type_var; \	}/* TODO: The size gets set to the size of the field storing the type. Maybe we   should make this a seperate function */unsigned intget_disk_specific_system_type (const PedPartition *part, int *size) {	if (!part || !part->disk_specific) {		if (size)			*size = 0;		return 0;	}	#if MSDOS_HACK	return_system_type("msdos",DosPartitionData,system);	#endif	#if SUN_HACK	return_system_type("sun",SunPartitionData,type);	#endif	#if BSD_HACK	return_system_type("bsd",BSDPartitionData,type);	#endif	#if DVH_HACK	/* OK, here type is int... Hope we don't break anything... */	return_system_type("dvh",DVHPartitionData,type);	#endif	#if PC98_HACK	/* OK, here type is int... Hope we don't break anything... */	return_system_type("pc98",PC98PartitionData,system);	#endif	#if AMIGA_HACK	return_system_type("amiga",AmigaPartitionData,de_DosType);	#endif	{		if (size)			*size = 0;		return 0;	}	}/* Needed for lfdisk */voidset_disk_specific_system_type (const PedPartition *part, unsigned char type) {	/* TODO: I have no idea how we actually should do this */	#if MSDOS_HACK	if (!strcmp(part->disk->type->name,"msdos")) {		DosPartitionData *pd = (DosPartitionData *)part->disk_specific;		pd->system = type;	}	else	#endif	#if SUN_HACK	if (!strcmp(part->disk->type->name,"sun")) {		SunPartitionData *pd = (SunPartitionData *)part->disk_specific;		pd->type = type;	}	else	#endif	#if BSD_HACK	if (!strcmp(part->disk->type->name,"bsd")) {		BSDPartitionData *pd = (BSDPartitionData *)part->disk_specific;		pd->type = type;	}	else	#endif	return;}intis_part_type_bsd (const PedPartition* part) {	int type = get_disk_specific_system_type(part, NULL);	/* We leave these for a reference */	if (   type == 0xa5 || type == (0xa5 ^ 0x10) /* FreeBSD */	    || type == 0xa6 || type == (0xa6 ^ 0x10) /* OpenBSD */	    || type == 0xa9 || type == (0xa9 ^ 0x10) /* NetBSD  */           ) return 1;	return 0;}intis_bsd_partition (char* device, PedSector start, PedSector s_size) {	int fd;	struct bsdlabel *lbl;	u_char bootarea[BSD_BSIZE];	if (!device)		return 0;	fd = open (device, O_RDONLY);	if (fd < 0)		return 0;  	(void)lseek (fd, (off_t)start, SEEK_SET);  	/* read in the boot block area. */	if (read (fd, bootarea, BSD_BSIZE) != BSD_BSIZE) 		return 0;	close (fd);	lbl = (struct bsdlabel *)&(bootarea[s_size]);  	if (lbl->magic != BSD_DISKMAGIC	    || lbl->magic2 != BSD_DISKMAGIC) 		return 0;	return 1;}/* Cut the number number from a devicename. Stores the name in dest and return the number. */int cut_device_partnum(char *dest, size_t n, const char *devname){	int t,s;	t = strlen(devname);	/* We count the digits at the end */	for (s = 0; s < t && isdigit(devname[t-s-1]); s++); 	/* No digits at the end */	if (s == 0) {#if NAMING_BSD		/* In BSD we have a character after the digits, specifying the partition */		for (s = 0; s < t-1 && isdigit(devname[t-s-2]); s++); 		if (s > 0) {			snprintf(dest, PED_MIN(t-1,n), "%s", devname);			return devname[t] - 'a' + 1;		}#endif		strncpy(dest,devname,n);		return 0;			}	/* For names like ad0s0, cut two chars */	if (t > 2 && (devname[t-s-1] == 's' || 		      devname[t-s-1] == 'p')		  && isdigit(devname[t-s-2]))	{		snprintf(dest, PED_MIN(t-s,n), "%s", devname);	}	/* Otherwise, cut one char */	else //if (t > 1 && !isdigit(fdisk_part_size[t-2]))	{		snprintf(dest, PED_MIN(t-s+1,n), "%s", devname);	}		/* We return the number */	return atoi(devname + t - s);}/* Store the path to device of a part in dest. bsd_offset is used when we calculate   the device path of a partition on a BSD disklabel on a GNU/Linux system,   it should be equal to the number of logical partitions in most cases. */char * get_partition_device(char *dest, size_t n, PedPartition* part, int bsd_offset){	if (!strcmp(part->disk->type->name,"bsd")) {#if NAMING_BSD		n = snprintf(dest, n, "%s%c", part->disk->dev->path, 'a' + part->num - 1);#else /* if NAMING_LINUX */	/* In GNU/Linux partitions on a BSD label appear after the ones in the extended partition */		char buf[256];		cut_device_partnum(buf, sizeof(buf), part->disk->dev->path);		n = snprintf(dest, n, isdigit(buf[strlen(buf)-1]) ? "%sp%d" : "%s%d",	                         buf, part->num+bsd_offset+4);#endif		}	else{#if NAMING_BSD		n = snprintf(dest, n, "%ss%d", part->disk->dev->path, part->num);#else /* if NAMING_LINUX */		int t = strlen(part->disk->dev->path);		n = snprintf(dest, n, isdigit(part->disk->dev->path[t-1]) ? "%sp%d" : "%s%d",	                         part->disk->dev->path, part->num);#endif	}	return n < 0 ? NULL : dest;}

⌨️ 快捷键说明

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