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

📄 fdisk.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * fdisk - edit dos disk partition table */#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#include <disk.h>#include "edit.h"typedef struct Dospart	Dospart;enum {	NTentry = 4,	Mpart = 64,};static void rdpart(Edit*, ulong, ulong);static void findmbr(Edit*);static void autopart(Edit*);static void wrpart(Edit*);static void blankpart(Edit*);static void cmdnamectl(Edit*);static void recover(Edit*);static int Dfmt(Fmt*);static int blank;static int dowrite;static int file;static int rdonly;static int doauto;static vlong mbroffset;static int printflag;static int printchs;static int sec2cyl;static int written;static void 	cmdsum(Edit*, Part*, vlong, vlong);static char 	*cmdadd(Edit*, char*, vlong, vlong);static char 	*cmddel(Edit*, Part*);static char 	*cmdext(Edit*, int, char**);static char 	*cmdhelp(Edit*);static char 	*cmdokname(Edit*, char*);static char 	*cmdwrite(Edit*);static void	cmdprintctl(Edit*, int);#pragma varargck type "D" uchar*Edit edit = {	.add=	cmdadd,	.del=		cmddel,	.ext=		cmdext,	.help=	cmdhelp,	.okname=	cmdokname,	.sum=	cmdsum,	.write=	cmdwrite,	.printctl=	cmdprintctl,	.unit=	"cylinder",};/* * Catch the obvious error routines to fix up the disk. */voidsysfatal(char *fmt, ...){	char buf[1024];	va_list arg;	va_start(arg, fmt);	vseprint(buf, buf+sizeof(buf), fmt, arg);	va_end(arg);	if(argv0)		fprint(2, "%s: %s\n", argv0, buf);	else		fprint(2, "%s\n", buf);	if(written)		recover(&edit);	exits(buf);}voidabort(void){	fprint(2, "abort\n");	recover(&edit);}voidusage(void){	fprint(2, "usage: disk/fdisk [-abfprvw] [-s sectorsize] /dev/sdC0/data\n");	exits("usage");}voidmain(int argc, char **argv){	vlong secsize;	secsize = 0;	ARGBEGIN{	case 'a':		doauto++;		break;	case 'b':		blank++;		break;	case 'f':		file++;		break;	case 'p':		printflag++;		break;	case 'r':		rdonly++;		break;	case 's':		secsize = atoi(ARGF());		break;	case 'v':		printchs++;		break;	case 'w':		dowrite++;		break;	}ARGEND;	fmtinstall('D', Dfmt);	if(argc != 1)		usage();	edit.disk = opendisk(argv[0], rdonly, file);	if(edit.disk == nil) {		fprint(2, "cannot open disk: %r\n");		exits("opendisk");	}	if(secsize != 0) {		edit.disk->secsize = secsize;		edit.disk->secs = edit.disk->size / secsize;	}	sec2cyl = edit.disk->h * edit.disk->s;	edit.end = edit.disk->secs / sec2cyl;	findmbr(&edit);	if(blank)		blankpart(&edit);	else		rdpart(&edit, 0, 0);	if(doauto)		autopart(&edit);	if(dowrite)		runcmd(&edit, "w");	if(printflag)		runcmd(&edit, "P");	if(dowrite || printflag)		exits(0);	fprint(2, "cylinder = %lld bytes\n", sec2cyl*edit.disk->secsize);	runcmd(&edit, "p");	for(;;) {		fprint(2, ">>> ");		runcmd(&edit, getline(&edit));	}}typedef struct Tentry	Tentry;typedef struct Table	Table;typedef struct Type	Type;typedef struct Tab	Tab;typedef struct Recover Recover;struct Tentry {	uchar	active;			/* active flag */	uchar	starth;			/* starting head */	uchar	starts;			/* starting sector */	uchar	startc;			/* starting cylinder */	uchar	type;			/* partition type */	uchar	endh;			/* ending head */	uchar	ends;			/* ending sector */	uchar	endc;			/* ending cylinder */	uchar	xlba[4];		/* starting LBA from beginning of disc or ext. partition */	uchar	xsize[4];		/* size in sectors */};enum {	Active		= 0x80,		/* partition is active */	Primary		= 0x01,		/* internal flag */	TypeBB		= 0xFF,	TypeEMPTY	= 0x00,	TypeFAT12	= 0x01,	TypeXENIX	= 0x02,		/* root */	TypeXENIXUSR	= 0x03,		/* usr */	TypeFAT16	= 0x04,	TypeEXTENDED	= 0x05,	TypeFATHUGE	= 0x06,	TypeHPFS	= 0x07,	TypeAIXBOOT	= 0x08,	TypeAIXDATA	= 0x09,	TypeOS2BOOT	= 0x0A,		/* OS/2 Boot Manager */	TypeFAT32	= 0x0B,		/* FAT 32 */	TypeFAT32LBA	= 0x0C,		/* FAT 32 needing LBA support */	TypeFAT16X	= 0x0E,		/* FAT 16 needing LBA support */	TypeEXTHUGE	= 0x0F,		/* FAT 32 extended partition */	TypeUNFORMATTED	= 0x16,		/* unformatted primary partition (OS/2 FDISK)? */	TypeHPFS2	= 0x17,	TypeIBMRecovery = 0x1C,		/* really hidden fat */	TypeCPM0	= 0x52,	TypeDMDDO	= 0x54,		/* Disk Manager Dynamic Disk Overlay */	TypeGB		= 0x56,		/* ???? */	TypeSPEEDSTOR	= 0x61,	TypeSYSV386	= 0x63,		/* also HURD? */	TypeNETWARE	= 0x64,	TypePCIX	= 0x75,	TypeMINIX13	= 0x80,		/* Minix v1.3 and below */	TypeMINIX	= 0x81,		/* Minix v1.5+ */	TypeLINUXSWAP	= 0x82,	TypeLINUX	= 0x83,	TypeLINUXEXT	= 0x85,	TypeAMOEBA	= 0x93,	TypeAMOEBABB	= 0x94,	TypeBSD386	= 0xA5,	TypeBSDI	= 0xB7,	TypeBSDISWAP	= 0xB8,	TypeOTHER	= 0xDA,	TypeCPM		= 0xDB,	TypeDellRecovery= 0xDE,	TypeSPEEDSTOR12	= 0xE1,	TypeSPEEDSTOR16	= 0xE4,	TypeLANSTEP	= 0xFE,	Type9		= 0x39,	Toffset		= 446,		/* offset of partition table in sector */	Magic0		= 0x55,	Magic1		= 0xAA,};struct Table {	Tentry	entry[NTentry];	uchar	magic[2];};struct Type {	char *desc;	char *name;};struct Dospart {	Part;	Tentry;	u32int	lba;	u32int	size;	int		primary;};struct Recover {	Table	table;	ulong	lba;};static Type types[256] = {	[TypeEMPTY]		{ "EMPTY", "" },	[TypeFAT12]		{ "FAT12", "dos" },	[TypeFAT16]		{ "FAT16", "dos" },	[TypeFAT32]		{ "FAT32", "dos" },	[TypeFAT32LBA]		{ "FAT32LBA", "dos" },	[TypeFAT16X]		{ "FAT16X", "dos" },	[TypeEXTHUGE]		{ "EXTHUGE", "" },	[TypeIBMRecovery]	{ "IBMRECOVERY", "ibm" },	[TypeEXTENDED]		{ "EXTENDED", "" },	[TypeFATHUGE]		{ "FATHUGE", "dos" },	[TypeBB]		{ "BB", "bb" },	[TypeXENIX]		{ "XENIX", "xenix" },	[TypeXENIXUSR]		{ "XENIX USR", "xenixusr" },	[TypeHPFS]		{ "HPFS", "ntfs" },	[TypeAIXBOOT]		{ "AIXBOOT", "aixboot" },	[TypeAIXDATA]		{ "AIXDATA", "aixdata" },	[TypeOS2BOOT]		{ "OS/2BOOT", "os2boot" },	[TypeUNFORMATTED]	{ "UNFORMATTED", "" },	[TypeHPFS2]		{ "HPFS2", "hpfs2" },	[TypeCPM0]		{ "CPM0", "cpm0" },	[TypeDMDDO]		{ "DMDDO", "dmdd0" },	[TypeGB]		{ "GB", "gb" },	[TypeSPEEDSTOR]		{ "SPEEDSTOR", "speedstor" },	[TypeSYSV386]		{ "SYSV386", "sysv386" },	[TypeNETWARE]		{ "NETWARE", "netware" },	[TypePCIX]		{ "PCIX", "pcix" },	[TypeMINIX13]		{ "MINIXV1.3", "minix13" },	[TypeMINIX]		{ "MINIXV1.5", "minix15" },	[TypeLINUXSWAP]		{ "LINUXSWAP", "linuxswap" },	[TypeLINUX]		{ "LINUX", "linux" },	[TypeLINUXEXT]		{ "LINUXEXTENDED", "" },	[TypeAMOEBA]		{ "AMOEBA", "amoeba" },	[TypeAMOEBABB]		{ "AMOEBABB", "amoebaboot" },	[TypeBSD386]		{ "BSD386", "bsd386" },	[TypeBSDI]		{ "BSDI", "bsdi" },	[TypeBSDISWAP]		{ "BSDISWAP", "bsdiswap" },	[TypeOTHER]		{ "OTHER", "other" },	[TypeCPM]		{ "CPM", "cpm" },	[TypeDellRecovery]	{ "DELLRECOVERY", "dell" },	[TypeSPEEDSTOR12]	{ "SPEEDSTOR12", "speedstor" },	[TypeSPEEDSTOR16]	{ "SPEEDSTOR16", "speedstor" },	[TypeLANSTEP]		{ "LANSTEP", "lanstep" },	[Type9]			{ "PLAN9", "plan9" },};static Dospart	part[Mpart];static int		npart;static char*typestr0(int type){	static char buf[100];	sprint(buf, "type %d", type);	if(type < 0 || type >= 256)		return buf;	if(types[type].desc == nil)		return buf;	return types[type].desc;}static u32intgetle32(void* v){	uchar *p;	p = v;	return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0];}static voidputle32(void* v, u32int i){	uchar *p;	p = v;	p[0] = i;	p[1] = i>>8;	p[2] = i>>16;	p[3] = i>>24;}static voiddiskread(Disk *disk, void *data, int ndata, u32int sec, u32int off){	if(seek(disk->fd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)		sysfatal("diskread seek %lud.%lud: %r", (ulong)sec, (ulong)off);	if(readn(disk->fd, data, ndata) != ndata)		sysfatal("diskread %lud at %lud.%lud: %r", (ulong)ndata, (ulong)sec, (ulong)off);}static intdiskwrite(Disk *disk, void *data, int ndata, u32int sec, u32int off){	written = 1;	if(seek(disk->wfd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)		goto Error;	if(write(disk->wfd, data, ndata) != ndata)		goto Error;	return 0;Error:	fprint(2, "write %d bytes at %lud.%lud failed: %r\n", ndata, (ulong)sec, (ulong)off);	return -1;}static Dospart*mkpart(char *name, int primary, u32int lba, u32int size, Tentry *t){	static int n;	Dospart *p;	p = emalloc(sizeof(*p));	if(name)		p->name = estrdup(name);	else{		p->name = emalloc(20);		sprint(p->name, "%c%d", primary ? 'p' : 's', ++n);	}	if(t)		p->Tentry = *t;	else		memset(&p->Tentry, 0, sizeof(Tentry));	p->changed = 0;	p->start = lba/sec2cyl;	p->end = (lba+size)/sec2cyl;	p->ctlstart = lba;	p->ctlend = lba+size;	p->lba = lba;	p->size = size;	p->primary = primary;	return p;}/* * Recovery takes care of remembering what the various tables * looked like when we started, attempting to restore them when * we are finished. */static Recover	*rtab;static int		nrtab;static voidaddrecover(Table t, ulong lba){	if((nrtab%8) == 0) {		rtab = realloc(rtab, (nrtab+8)*sizeof(rtab[0]));		if(rtab == nil)			sysfatal("out of memory");	}	rtab[nrtab] = (Recover){t, lba};	nrtab++;}static voidrecover(Edit *edit){	int err, i, ctlfd;	vlong offset;	err = 0;	for(i=0; i<nrtab; i++)		if(diskwrite(edit->disk, &rtab[i].table, sizeof(Table), rtab[i].lba, Toffset) < 0)			err = 1;	if(err) {		fprint(2, "warning: some writes failed during restoration of old partition tables\n");		exits("inconsistent");	} else {		fprint(2, "restored old partition tables\n");	}	ctlfd = edit->disk->ctlfd;	offset = edit->disk->offset;	if(ctlfd >= 0){		for(i=0; i<edit->npart; i++)			if(edit->part[i]->ctlname && fprint(ctlfd, "delpart %s", edit->part[i]->ctlname)<0)				fprint(2, "delpart failed: %s: %r", edit->part[i]->ctlname);		for(i=0; i<edit->nctlpart; i++)			if(edit->part[i]->name && fprint(ctlfd, "delpart %s", edit->ctlpart[i]->name)<0)				fprint(2, "delpart failed: %s: %r", edit->ctlpart[i]->name);		for(i=0; i<edit->nctlpart; i++){			if(fprint(ctlfd, "part %s %lld %lld", edit->ctlpart[i]->name,				edit->ctlpart[i]->start+offset, edit->ctlpart[i]->end+offset) < 0){				fprint(2, "restored disk partition table but not kernel; reboot\n");				exits("inconsistent");			}		}	}	exits("restored");}/* * Read the partition table (including extended partition tables) * from the disk into the part array. */static voidrdpart(Edit *edit, ulong lba, ulong xbase){	char *err;	Table table;	Tentry *tp, *ep;	Dospart *p;	if(xbase == 0)		xbase = lba;	diskread(edit->disk, &table, sizeof table, mbroffset+lba, Toffset);	addrecover(table, mbroffset+lba);	if(table.magic[0] != Magic0 || table.magic[1] != Magic1) {		assert(lba != 0);		return;	}	for(tp=table.entry, ep=tp+NTentry; tp<ep && npart < Mpart; tp++) {		switch(tp->type) {		case TypeEMPTY:			break;		case TypeEXTENDED:		case TypeEXTHUGE:		case TypeLINUXEXT:			rdpart(edit, xbase+getle32(tp->xlba), xbase);			break;		default:			p = mkpart(nil, lba==0, lba+getle32(tp->xlba), getle32(tp->xsize), tp);			if(err = addpart(edit, p))				fprint(2, "adding partition: %s\n", err);			break;		}	}}static voidblankpart(Edit *edit){	edit->changed = 1;}static voidfindmbr(Edit *edit){	Table table;	Tentry *tp;	diskread(edit->disk, &table, sizeof(Table), 0, Toffset);	if(table.magic[0] != Magic0 || table.magic[1] != Magic1)		sysfatal("did not find master boot record");	for(tp = table.entry; tp < &table.entry[NTentry]; tp++)		if(tp->type == TypeDMDDO)			mbroffset = edit->disk->s;}static inthaveroom(Edit *edit, int primary, vlong start){	int i, lastsec, n;	Dospart *p, *q;	ulong pend, qstart;	if(primary) {		/*		 * must be open primary slot.		 * primary slots are taken by primary partitions		 * and runs of secondary partitions.		 */		n = 0;		lastsec = 0;		for(i=0; i<edit->npart; i++) {			p = (Dospart*)edit->part[i];			if(p->primary)				n++, lastsec=0;			else if(!lastsec)				n++, lastsec=1;		}

⌨️ 快捷键说明

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