📄 fdisk.c
字号:
/* * 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 + -