/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * 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*, uvlong, uvlong);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 */}; struct Table { Tentry entry[NTentry]; uchar magic[2]; uchar size[];}; 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, TypeLINUXLVM = 0x8E, /* logical volume manager */ TypeAMOEBA = 0x93, TypeAMOEBABB = 0x94, TypeBSD386 = 0xA5, TypeNETBSD = 0xA9, TypeBSDI = 0xB7, TypeBSDISWAP = 0xB8, TypeOTHER = 0xDA, TypeCPM = 0xDB, TypeDellRecovery= 0xDE, TypeSPEEDSTOR12 = 0xE1, TypeSPEEDSTOR16 = 0xE4, TypeEFIProtect = 0xEE, TypeEFI = 0xEF, TypeLANSTEP = 0xFE, Type9 = 0x39, Toffset = 446, /* offset of partition table in sector */ Magic0 = 0x55, Magic1 = 0xAA, Tablesz = offsetof(Table, size[0]),}; 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", "" }, [TypeLINUXLVM] { "LINUXLVM", "linuxlvm" }, [TypeAMOEBA] { "AMOEBA", "amoeba" }, [TypeAMOEBABB] { "AMOEBABB", "amoebaboot" }, [TypeBSD386] { "BSD386", "bsd386" }, [TypeNETBSD] { "NETBSD", "netbsd" }, [TypeBSDI] { "BSDI", "bsdi" }, [TypeBSDISWAP] { "BSDISWAP", "bsdiswap" }, [TypeOTHER] { "OTHER", "other" }, [TypeCPM] { "CPM", "cpm" }, [TypeDellRecovery] { "DELLRECOVERY", "dell" }, [TypeSPEEDSTOR12] { "SPEEDSTOR12", "speedstor" }, [TypeSPEEDSTOR16] { "SPEEDSTOR16", "speedstor" }, [TypeEFIProtect] { "EFIPROTECT", "efiprotect" }, [TypeEFI] { "EFI", "efi" }, [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, vlong lba, vlong 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; if (p->lba != lba) fprint(2, "%s: start of partition (%lld) won't fit in MBR table\n", argv0, lba); p->size = size; if (p->size != size) fprint(2, "%s: size of partition (%lld) won't fit in MBR table\n", argv0, 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, Tablesz, 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, uvlong lba, uvlong xbase)Lines 1–500 of 1134. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * 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*, uvlong, uvlong); 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. */ void sysfatal(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); } void abort(void) { fprint(2, "abort\n"); recover(&edit); } void usage(void) { fprint(2, "usage: disk/fdisk [-abfprvw] [-s sectorsize] /dev/sdC0/data\n"); exits("usage"); } void main(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 */ }; struct Table { Tentry entry[NTentry]; uchar magic[2]; uchar size[]; }; 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, TypeLINUXLVM = 0x8E, /* logical volume manager */ TypeAMOEBA = 0x93, TypeAMOEBABB = 0x94, TypeBSD386 = 0xA5, TypeNETBSD = 0xA9, TypeBSDI = 0xB7, TypeBSDISWAP = 0xB8, TypeOTHER = 0xDA, TypeCPM = 0xDB, TypeDellRecovery= 0xDE, TypeSPEEDSTOR12 = 0xE1, TypeSPEEDSTOR16 = 0xE4, TypeEFIProtect = 0xEE, TypeEFI = 0xEF, TypeLANSTEP = 0xFE, Type9 = 0x39, Toffset = 446, /* offset of partition table in sector */ Magic0 = 0x55, Magic1 = 0xAA, Tablesz = offsetof(Table, size[0]), }; 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", "" }, [TypeLINUXLVM] { "LINUXLVM", "linuxlvm" }, [TypeAMOEBA] { "AMOEBA", "amoeba" }, [TypeAMOEBABB] { "AMOEBABB", "amoebaboot" }, [TypeBSD386] { "BSD386", "bsd386" }, [TypeNETBSD] { "NETBSD", "netbsd" }, [TypeBSDI] { "BSDI", "bsdi" }, [TypeBSDISWAP] { "BSDISWAP", "bsdiswap" }, [TypeOTHER] { "OTHER", "other" }, [TypeCPM] { "CPM", "cpm" }, [TypeDellRecovery] { "DELLRECOVERY", "dell" }, [TypeSPEEDSTOR12] { "SPEEDSTOR12", "speedstor" }, [TypeSPEEDSTOR16] { "SPEEDSTOR16", "speedstor" }, [TypeEFIProtect] { "EFIPROTECT", "efiprotect" }, [TypeEFI] { "EFI", "efi" }, [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 u32int getle32(void* v) { uchar *p; p = v; return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]; } static void putle32(void* v, u32int i) { uchar *p; p = v; p[0] = i; p[1] = i>>8; p[2] = i>>16; p[3] = i>>24; } static void diskread(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 int diskwrite(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, vlong lba, vlong 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; if (p->lba != lba) fprint(2, "%s: start of partition (%lld) won't fit in MBR table\n", argv0, lba); p->size = size; if (p->size != size) fprint(2, "%s: size of partition (%lld) won't fit in MBR table\n", argv0, 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 void addrecover(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 void recover(Edit *edit) { int err, i, ctlfd; vlong offset; err = 0; for(i=0; i<nrtab; i++) if(diskwrite(edit->disk, &rtab[i].table, Tablesz, 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 void rdpart(Edit *edit, uvlong lba, uvlong xbase)