fdisksunlabel.c

来自「Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分」· C语言 代码 · 共 747 行 · 第 1/2 页

C
747
字号
/* * fdisksunlabel.c * * I think this is mostly, or entirely, due to * 	Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996 * * Merged with fdisk for other architectures, aeb, June 1998. * * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> *      Internationalization */#include <stdio.h>		/* stderr */#include <stdlib.h>		/* qsort */#include <string.h>		/* strstr */#include <unistd.h>		/* write */#include <sys/ioctl.h>		/* ioctl */#include <sys/stat.h>		/* stat */#include <sys/sysmacros.h>	/* major */#include "nls.h"#include <endian.h>#include "../defines.h"		/* for HAVE_scsi_h */#ifdef HAVE_scsi_h#define u_char	unsigned char#include <scsi/scsi.h>		/* SCSI_IOCTL_GET_IDLUN */#undef u_char#endif#include <linux/major.h>	/* FLOPPY_MAJOR */#include "common.h"#include "fdisk.h"#include "fdisksunlabel.h"static int     other_endian = 0;static int     scsi_disk = 0;static int     floppy = 0;#define LINUX_SWAP      0x82#define LINUX_NATIVE    0x83struct systypes sun_sys_types[] = {	{0, N_("Empty")},	{1, N_("Boot")},	{2, N_("SunOS root")},	{SUNOS_SWAP, N_("SunOS swap")},	{4, N_("SunOS usr")},	{WHOLE_DISK, N_("Whole disk")},	{6, N_("SunOS stand")},	{7, N_("SunOS var")},	{8, N_("SunOS home")},	{LINUX_SWAP, N_("Linux swap")},	{LINUX_NATIVE, N_("Linux native")},	{0x8e, N_("Linux LVM")},	{0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition					       with autodetect using					       persistent superblock */	{ 0, NULL }};static inline unsigned short __swap16(unsigned short x) {        return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);}static inline __u32 __swap32(__u32 x) {        return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);}intget_num_sectors(struct sun_partition p) {	return SSWAP32(p.num_sectors);}#ifndef IDE0_MAJOR#define IDE0_MAJOR 3#endif#ifndef IDE1_MAJOR#define IDE1_MAJOR 22#endifvoid guess_device_type(int fd) {	struct stat bootstat;	if (fstat (fd, &bootstat) < 0) {                scsi_disk = 0;                floppy = 0;	} else if (S_ISBLK(bootstat.st_mode)		   && (major(bootstat.st_rdev) == IDE0_MAJOR ||		       major(bootstat.st_rdev) == IDE1_MAJOR)) {                scsi_disk = 0;                floppy = 0;	} else if (S_ISBLK(bootstat.st_mode)		   && major(bootstat.st_rdev) == FLOPPY_MAJOR) {                scsi_disk = 0;                floppy = 1;	} else {                scsi_disk = 1;                floppy = 0;	}}static voidset_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) {	sunlabel->infos[i].id = sysid;	sunlabel->partitions[i].start_cylinder =		SSWAP32(start / (heads * sectors));	sunlabel->partitions[i].num_sectors =		SSWAP32(stop - start);	set_changed(i);}voidsun_nolabel(void) {	sun_label = 0;	sunlabel->magic = 0;	partitions = 4;}intcheck_sun_label(void) {	unsigned short *ush;	int csum;	if (sunlabel->magic != SUN_LABEL_MAGIC &&	    sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {		sun_label = 0;		other_endian = 0;		return 0;	}	other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);	ush = ((unsigned short *) (sunlabel + 1)) - 1;	for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;	if (csum) {		fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"				"Probably you'll have to set all the values,\n"				"e.g. heads, sectors, cylinders and partitions\n"				"or force a fresh label (s command in main menu)\n"));	} else {		heads = SSWAP16(sunlabel->ntrks);		cylinders = SSWAP16(sunlabel->ncyl);		sectors = SSWAP16(sunlabel->nsect);	}	update_units();	sun_label = 1;	partitions = 8;	return 1;}struct sun_predefined_drives {	char *vendor;	char *model;	unsigned short sparecyl;	unsigned short ncyl;	unsigned short nacyl;	unsigned short pcylcount;	unsigned short ntrks;	unsigned short nsect;	unsigned short rspeed;} sun_drives[] = {{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},{"IBM","DPES-31080",0,4901,2,4903,4,108,5400},{"IBM","DORS-32160",0,1015,2,1017,67,62,5400},{"IBM","DNES-318350",0,11199,2,11474,10,320,7200},{"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},{"","SUN0104",1,974,2,1019,6,35,3662},{"","SUN0207",4,1254,2,1272,9,36,3600},{"","SUN0327",3,1545,2,1549,9,46,3600},{"","SUN0340",0,1538,2,1544,6,72,4200},{"","SUN0424",2,1151,2,2500,9,80,4400},{"","SUN0535",0,1866,2,2500,7,80,5400},{"","SUN0669",5,1614,2,1632,15,54,3600},{"","SUN1.0G",5,1703,2,1931,15,80,3597},{"","SUN1.05",0,2036,2,2038,14,72,5400},{"","SUN1.3G",6,1965,2,3500,17,80,5400},{"","SUN2.1G",0,2733,2,3500,19,80,5400},{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},};static struct sun_predefined_drives *sun_autoconfigure_scsi(void) {    struct sun_predefined_drives *p = NULL;#ifdef SCSI_IOCTL_GET_IDLUN    unsigned int id[2];    char buffer[2048];    char buffer2[2048];    FILE *pfd;    char *vendor;    char *model;    char *q;    int i;    if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {        sprintf(buffer,            "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",#if 0                                ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,#else            /* This is very wrong (works only if you have one HBA),               but I haven't found a way how to get hostno               from the current kernel */            0,#endif                                    (id[0]>>16)&0xff,            id[0]&0xff,            (id[0]>>8)&0xff);        pfd = fopen("/proc/scsi/scsi","r");        if (pfd) {            while (fgets(buffer2,2048,pfd)) {		if (!strcmp(buffer, buffer2)) {                    if (fgets(buffer2,2048,pfd)) {                        q = strstr(buffer2,"Vendor: ");                        if (q) {                            q += 8;                            vendor = q;			    q = strstr(q," ");			    *q++ = 0;	/* truncate vendor name */                            q = strstr(q,"Model: ");                            if (q) {                                *q = 0;                                q += 7;                                model = q;                                q = strstr(q," Rev: ");                                if (q) {                                    *q = 0;                                    for (i = 0; i < SIZE(sun_drives); i++) {                                        if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))                                            continue;                                        if (!strstr(model, sun_drives[i].model))                                            continue;                                        printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);                                        p = sun_drives + i;                                        break;                                    }                                }                            }                        }                    }                    break;                }            }            fclose(pfd);        }    }#endif    return p;}void create_sunlabel(void){	struct hd_geometry geometry;	unsigned int ndiv;	int i;	unsigned char c;	struct sun_predefined_drives *p = NULL;	fprintf(stderr,	_("Building a new sun disklabel. Changes will remain in memory only,\n"       	"until you decide to write them. After that, of course, the previous\n"	"content won't be recoverable.\n\n"));#if BYTE_ORDER == LITTLE_ENDIAN	other_endian = 1;#else	other_endian = 0;#endif	memset(MBRbuffer, 0, sizeof(MBRbuffer));	sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC);	if (!floppy) {	    puts(_("Drive type\n"	         "   ?   auto configure\n"	         "   0   custom (with hardware detected defaults)"));	    for (i = 0; i < SIZE(sun_drives); i++) {	        printf("   %c   %s%s%s\n",		       i + 'a', sun_drives[i].vendor,		       (*sun_drives[i].vendor) ? " " : "",		       sun_drives[i].model);	    }	    for (;;) {	        c = read_char(_("Select type (? for auto, 0 for custom): "));	        if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {	     	    p = sun_drives + c - 'a';	     	    break;	        } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {	            p = sun_drives + c - 'A';	            break;	        } else if (c == '0') {	            break;	        } else if (c == '?' && scsi_disk) {		    p = sun_autoconfigure_scsi();	            if (!p)	                printf(_("Autoconfigure failed.\n"));	            else	                break;	        }	    }	}	if (!p || floppy) {	    if (!ioctl(fd, HDIO_GETGEO, &geometry)) {	        heads = geometry.heads;	        sectors = geometry.sectors;	        cylinders = geometry.cylinders;	    } else {	        heads = 0;	        sectors = 0;	        cylinders = 0;	    }	    if (floppy) {	        sunlabel->nacyl = 0;	        sunlabel->pcylcount = SSWAP16(cylinders);	        sunlabel->rspeed = SSWAP16(300);	        sunlabel->ilfact = SSWAP16(1);	        sunlabel->sparecyl = 0;	    } else {	        heads = read_int(1,heads,1024,0,_("Heads"));		sectors = read_int(1,sectors,1024,0,_("Sectors/track"));	        if (cylinders)	            cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));	        else	            cylinders = read_int(1,0,65535,0,_("Cylinders"));	        sunlabel->nacyl =			SSWAP16(read_int(0,2,65535,0,					 _("Alternate cylinders")));	        sunlabel->pcylcount =			SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl),					 65535,0,_("Physical cylinders")));	        sunlabel->rspeed =			SSWAP16(read_int(1,5400,100000,0,					 _("Rotation speed (rpm)")));	        sunlabel->ilfact =			SSWAP16(read_int(1,1,32,0,_("Interleave factor")));	        sunlabel->sparecyl =			SSWAP16(read_int(0,0,sectors,0,					 _("Extra sectors per cylinder")));	    }	} else {	    sunlabel->sparecyl = SSWAP16(p->sparecyl);	    sunlabel->ncyl = SSWAP16(p->ncyl);	    sunlabel->nacyl = SSWAP16(p->nacyl);	    sunlabel->pcylcount = SSWAP16(p->pcylcount);	    sunlabel->ntrks = SSWAP16(p->ntrks);	    sunlabel->nsect = SSWAP16(p->nsect);	    sunlabel->rspeed = SSWAP16(p->rspeed);	    sunlabel->ilfact = SSWAP16(1);	    cylinders = p->ncyl;	    heads = p->ntrks;	    sectors = p->nsect;	    puts(_("You may change all the disk params from the x menu"));	}	snprintf(sunlabel->info, sizeof(sunlabel->info),		 "%s%s%s cyl %d alt %d hd %d sec %d", 		 p ? p->vendor : "", (p && *p->vendor) ? " " : "",		 p ? p->model		   : (floppy ? _("3,5\" floppy") : _("Linux custom")),		cylinders, SSWAP16(sunlabel->nacyl), heads, sectors);	sunlabel->ntrks = SSWAP16(heads);	sunlabel->nsect = SSWAP16(sectors);	sunlabel->ncyl = SSWAP16(cylinders);	if (floppy)	    set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);	else {	    if (cylinders * heads * sectors >= 150 * 2048) {	        ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */	    } else	        ndiv = cylinders * 2 / 3;	    set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);	    set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);	    sunlabel->infos[1].flags |= 0x01; /* Not mountable */	}	set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);	{		unsigned short *ush = (unsigned short *)sunlabel;

⌨️ 快捷键说明

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