17dd7cddfSDavid du Colombier /* 27dd7cddfSDavid du Colombier * fdisk - edit dos disk partition table 37dd7cddfSDavid du Colombier */ 47dd7cddfSDavid du Colombier #include <u.h> 57dd7cddfSDavid du Colombier #include <libc.h> 67dd7cddfSDavid du Colombier #include <bio.h> 77dd7cddfSDavid du Colombier #include <ctype.h> 87dd7cddfSDavid du Colombier #include <disk.h> 97dd7cddfSDavid du Colombier #include "edit.h" 107dd7cddfSDavid du Colombier 117dd7cddfSDavid du Colombier typedef struct Dospart Dospart; 127dd7cddfSDavid du Colombier enum { 1380ee5cbfSDavid du Colombier NTentry = 4, 1480ee5cbfSDavid du Colombier Mpart = 64, 157dd7cddfSDavid du Colombier }; 167dd7cddfSDavid du Colombier 17*eba00c11SDavid du Colombier static void rdpart(Edit*, uvlong, uvlong); 187dd7cddfSDavid du Colombier static void findmbr(Edit*); 197dd7cddfSDavid du Colombier static void autopart(Edit*); 207dd7cddfSDavid du Colombier static void wrpart(Edit*); 217dd7cddfSDavid du Colombier static void blankpart(Edit*); 227dd7cddfSDavid du Colombier static void cmdnamectl(Edit*); 2380ee5cbfSDavid du Colombier static void recover(Edit*); 249a747e4fSDavid du Colombier static int Dfmt(Fmt*); 257dd7cddfSDavid du Colombier static int blank; 267dd7cddfSDavid du Colombier static int dowrite; 277dd7cddfSDavid du Colombier static int file; 287dd7cddfSDavid du Colombier static int rdonly; 297dd7cddfSDavid du Colombier static int doauto; 307dd7cddfSDavid du Colombier static vlong mbroffset; 317dd7cddfSDavid du Colombier static int printflag; 327dd7cddfSDavid du Colombier static int printchs; 3380ee5cbfSDavid du Colombier static int sec2cyl; 3480ee5cbfSDavid du Colombier static int written; 357dd7cddfSDavid du Colombier 367dd7cddfSDavid du Colombier static void cmdsum(Edit*, Part*, vlong, vlong); 377dd7cddfSDavid du Colombier static char *cmdadd(Edit*, char*, vlong, vlong); 387dd7cddfSDavid du Colombier static char *cmddel(Edit*, Part*); 397dd7cddfSDavid du Colombier static char *cmdext(Edit*, int, char**); 407dd7cddfSDavid du Colombier static char *cmdhelp(Edit*); 417dd7cddfSDavid du Colombier static char *cmdokname(Edit*, char*); 427dd7cddfSDavid du Colombier static char *cmdwrite(Edit*); 437dd7cddfSDavid du Colombier static void cmdprintctl(Edit*, int); 447dd7cddfSDavid du Colombier 4580ee5cbfSDavid du Colombier #pragma varargck type "D" uchar* 4680ee5cbfSDavid du Colombier 477dd7cddfSDavid du Colombier Edit edit = { 487dd7cddfSDavid du Colombier .add= cmdadd, 497dd7cddfSDavid du Colombier .del= cmddel, 507dd7cddfSDavid du Colombier .ext= cmdext, 517dd7cddfSDavid du Colombier .help= cmdhelp, 527dd7cddfSDavid du Colombier .okname= cmdokname, 537dd7cddfSDavid du Colombier .sum= cmdsum, 547dd7cddfSDavid du Colombier .write= cmdwrite, 557dd7cddfSDavid du Colombier .printctl= cmdprintctl, 5680ee5cbfSDavid du Colombier 5780ee5cbfSDavid du Colombier .unit= "cylinder", 587dd7cddfSDavid du Colombier }; 597dd7cddfSDavid du Colombier 6080ee5cbfSDavid du Colombier /* 6180ee5cbfSDavid du Colombier * Catch the obvious error routines to fix up the disk. 6280ee5cbfSDavid du Colombier */ 6380ee5cbfSDavid du Colombier void 6480ee5cbfSDavid du Colombier sysfatal(char *fmt, ...) 6580ee5cbfSDavid du Colombier { 6680ee5cbfSDavid du Colombier char buf[1024]; 6780ee5cbfSDavid du Colombier va_list arg; 6880ee5cbfSDavid du Colombier 6980ee5cbfSDavid du Colombier va_start(arg, fmt); 709a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg); 7180ee5cbfSDavid du Colombier va_end(arg); 7280ee5cbfSDavid du Colombier if(argv0) 7380ee5cbfSDavid du Colombier fprint(2, "%s: %s\n", argv0, buf); 7480ee5cbfSDavid du Colombier else 7580ee5cbfSDavid du Colombier fprint(2, "%s\n", buf); 7680ee5cbfSDavid du Colombier 7780ee5cbfSDavid du Colombier if(written) 7880ee5cbfSDavid du Colombier recover(&edit); 7980ee5cbfSDavid du Colombier 8080ee5cbfSDavid du Colombier exits(buf); 8180ee5cbfSDavid du Colombier } 8280ee5cbfSDavid du Colombier 8380ee5cbfSDavid du Colombier void 8480ee5cbfSDavid du Colombier abort(void) 8580ee5cbfSDavid du Colombier { 8680ee5cbfSDavid du Colombier fprint(2, "abort\n"); 8780ee5cbfSDavid du Colombier recover(&edit); 8880ee5cbfSDavid du Colombier } 8980ee5cbfSDavid du Colombier 907dd7cddfSDavid du Colombier void 917dd7cddfSDavid du Colombier usage(void) 927dd7cddfSDavid du Colombier { 937dd7cddfSDavid du Colombier fprint(2, "usage: disk/fdisk [-abfprvw] [-s sectorsize] /dev/sdC0/data\n"); 947dd7cddfSDavid du Colombier exits("usage"); 957dd7cddfSDavid du Colombier } 967dd7cddfSDavid du Colombier 977dd7cddfSDavid du Colombier void 987dd7cddfSDavid du Colombier main(int argc, char **argv) 997dd7cddfSDavid du Colombier { 1007dd7cddfSDavid du Colombier vlong secsize; 1017dd7cddfSDavid du Colombier 1027dd7cddfSDavid du Colombier secsize = 0; 1037dd7cddfSDavid du Colombier ARGBEGIN{ 1047dd7cddfSDavid du Colombier case 'a': 1057dd7cddfSDavid du Colombier doauto++; 1067dd7cddfSDavid du Colombier break; 1077dd7cddfSDavid du Colombier case 'b': 1087dd7cddfSDavid du Colombier blank++; 1097dd7cddfSDavid du Colombier break; 1107dd7cddfSDavid du Colombier case 'f': 1117dd7cddfSDavid du Colombier file++; 1127dd7cddfSDavid du Colombier break; 1137dd7cddfSDavid du Colombier case 'p': 1147dd7cddfSDavid du Colombier printflag++; 1157dd7cddfSDavid du Colombier break; 1167dd7cddfSDavid du Colombier case 'r': 1177dd7cddfSDavid du Colombier rdonly++; 1187dd7cddfSDavid du Colombier break; 1197dd7cddfSDavid du Colombier case 's': 1207dd7cddfSDavid du Colombier secsize = atoi(ARGF()); 1217dd7cddfSDavid du Colombier break; 1227dd7cddfSDavid du Colombier case 'v': 1237dd7cddfSDavid du Colombier printchs++; 1247dd7cddfSDavid du Colombier break; 1257dd7cddfSDavid du Colombier case 'w': 1267dd7cddfSDavid du Colombier dowrite++; 1277dd7cddfSDavid du Colombier break; 1287dd7cddfSDavid du Colombier }ARGEND; 1297dd7cddfSDavid du Colombier 1309a747e4fSDavid du Colombier fmtinstall('D', Dfmt); 13180ee5cbfSDavid du Colombier 1327dd7cddfSDavid du Colombier if(argc != 1) 1337dd7cddfSDavid du Colombier usage(); 1347dd7cddfSDavid du Colombier 1357dd7cddfSDavid du Colombier edit.disk = opendisk(argv[0], rdonly, file); 1367dd7cddfSDavid du Colombier if(edit.disk == nil) { 1377dd7cddfSDavid du Colombier fprint(2, "cannot open disk: %r\n"); 1387dd7cddfSDavid du Colombier exits("opendisk"); 1397dd7cddfSDavid du Colombier } 1407dd7cddfSDavid du Colombier 1417dd7cddfSDavid du Colombier if(secsize != 0) { 1427dd7cddfSDavid du Colombier edit.disk->secsize = secsize; 1437dd7cddfSDavid du Colombier edit.disk->secs = edit.disk->size / secsize; 1447dd7cddfSDavid du Colombier } 1457dd7cddfSDavid du Colombier 14680ee5cbfSDavid du Colombier sec2cyl = edit.disk->h * edit.disk->s; 14780ee5cbfSDavid du Colombier edit.end = edit.disk->secs / sec2cyl; 14880ee5cbfSDavid du Colombier 1497dd7cddfSDavid du Colombier findmbr(&edit); 1507dd7cddfSDavid du Colombier 1517dd7cddfSDavid du Colombier if(blank) 1527dd7cddfSDavid du Colombier blankpart(&edit); 1537dd7cddfSDavid du Colombier else 1549a747e4fSDavid du Colombier rdpart(&edit, 0, 0); 1557dd7cddfSDavid du Colombier 1567dd7cddfSDavid du Colombier if(doauto) 1577dd7cddfSDavid du Colombier autopart(&edit); 1587dd7cddfSDavid du Colombier 1597dd7cddfSDavid du Colombier if(dowrite) 16080ee5cbfSDavid du Colombier runcmd(&edit, "w"); 1617dd7cddfSDavid du Colombier 1627dd7cddfSDavid du Colombier if(printflag) 1637dd7cddfSDavid du Colombier runcmd(&edit, "P"); 1647dd7cddfSDavid du Colombier 1657dd7cddfSDavid du Colombier if(dowrite || printflag) 1667dd7cddfSDavid du Colombier exits(0); 1677dd7cddfSDavid du Colombier 16880ee5cbfSDavid du Colombier fprint(2, "cylinder = %lld bytes\n", sec2cyl*edit.disk->secsize); 1697dd7cddfSDavid du Colombier runcmd(&edit, "p"); 1707dd7cddfSDavid du Colombier for(;;) { 1717dd7cddfSDavid du Colombier fprint(2, ">>> "); 1727dd7cddfSDavid du Colombier runcmd(&edit, getline(&edit)); 1737dd7cddfSDavid du Colombier } 1747dd7cddfSDavid du Colombier } 1757dd7cddfSDavid du Colombier 1767dd7cddfSDavid du Colombier typedef struct Tentry Tentry; 1777dd7cddfSDavid du Colombier typedef struct Table Table; 1787dd7cddfSDavid du Colombier typedef struct Type Type; 1797dd7cddfSDavid du Colombier typedef struct Tab Tab; 18080ee5cbfSDavid du Colombier typedef struct Recover Recover; 1817dd7cddfSDavid du Colombier 1827dd7cddfSDavid du Colombier struct Tentry { 1837dd7cddfSDavid du Colombier uchar active; /* active flag */ 1847dd7cddfSDavid du Colombier uchar starth; /* starting head */ 1857dd7cddfSDavid du Colombier uchar starts; /* starting sector */ 1867dd7cddfSDavid du Colombier uchar startc; /* starting cylinder */ 1877dd7cddfSDavid du Colombier uchar type; /* partition type */ 1887dd7cddfSDavid du Colombier uchar endh; /* ending head */ 1897dd7cddfSDavid du Colombier uchar ends; /* ending sector */ 1907dd7cddfSDavid du Colombier uchar endc; /* ending cylinder */ 19180ee5cbfSDavid du Colombier uchar xlba[4]; /* starting LBA from beginning of disc or ext. partition */ 1927dd7cddfSDavid du Colombier uchar xsize[4]; /* size in sectors */ 1937dd7cddfSDavid du Colombier }; 1947dd7cddfSDavid du Colombier 1957dd7cddfSDavid du Colombier enum { 1967dd7cddfSDavid du Colombier Active = 0x80, /* partition is active */ 1977dd7cddfSDavid du Colombier Primary = 0x01, /* internal flag */ 1987dd7cddfSDavid du Colombier 1997dd7cddfSDavid du Colombier TypeBB = 0xFF, 2007dd7cddfSDavid du Colombier 2017dd7cddfSDavid du Colombier TypeEMPTY = 0x00, 2027dd7cddfSDavid du Colombier TypeFAT12 = 0x01, 2037dd7cddfSDavid du Colombier TypeXENIX = 0x02, /* root */ 2047dd7cddfSDavid du Colombier TypeXENIXUSR = 0x03, /* usr */ 2057dd7cddfSDavid du Colombier TypeFAT16 = 0x04, 2067dd7cddfSDavid du Colombier TypeEXTENDED = 0x05, 2077dd7cddfSDavid du Colombier TypeFATHUGE = 0x06, 2087dd7cddfSDavid du Colombier TypeHPFS = 0x07, 2097dd7cddfSDavid du Colombier TypeAIXBOOT = 0x08, 2107dd7cddfSDavid du Colombier TypeAIXDATA = 0x09, 2117dd7cddfSDavid du Colombier TypeOS2BOOT = 0x0A, /* OS/2 Boot Manager */ 2127dd7cddfSDavid du Colombier TypeFAT32 = 0x0B, /* FAT 32 */ 2137dd7cddfSDavid du Colombier TypeFAT32LBA = 0x0C, /* FAT 32 needing LBA support */ 2144afe124fSDavid du Colombier TypeFAT16X = 0x0E, /* FAT 16 needing LBA support */ 2157dd7cddfSDavid du Colombier TypeEXTHUGE = 0x0F, /* FAT 32 extended partition */ 2167dd7cddfSDavid du Colombier TypeUNFORMATTED = 0x16, /* unformatted primary partition (OS/2 FDISK)? */ 2177dd7cddfSDavid du Colombier TypeHPFS2 = 0x17, 2186b6b9ac8SDavid du Colombier TypeIBMRecovery = 0x1C, /* really hidden fat */ 2197dd7cddfSDavid du Colombier TypeCPM0 = 0x52, 2207dd7cddfSDavid du Colombier TypeDMDDO = 0x54, /* Disk Manager Dynamic Disk Overlay */ 2217dd7cddfSDavid du Colombier TypeGB = 0x56, /* ???? */ 2227dd7cddfSDavid du Colombier TypeSPEEDSTOR = 0x61, 2237dd7cddfSDavid du Colombier TypeSYSV386 = 0x63, /* also HURD? */ 2247dd7cddfSDavid du Colombier TypeNETWARE = 0x64, 2257dd7cddfSDavid du Colombier TypePCIX = 0x75, 2267dd7cddfSDavid du Colombier TypeMINIX13 = 0x80, /* Minix v1.3 and below */ 2277dd7cddfSDavid du Colombier TypeMINIX = 0x81, /* Minix v1.5+ */ 2287dd7cddfSDavid du Colombier TypeLINUXSWAP = 0x82, 2297dd7cddfSDavid du Colombier TypeLINUX = 0x83, 2309a747e4fSDavid du Colombier TypeLINUXEXT = 0x85, 2317dd7cddfSDavid du Colombier TypeAMOEBA = 0x93, 2327dd7cddfSDavid du Colombier TypeAMOEBABB = 0x94, 2337dd7cddfSDavid du Colombier TypeBSD386 = 0xA5, 2347dd7cddfSDavid du Colombier TypeBSDI = 0xB7, 2357dd7cddfSDavid du Colombier TypeBSDISWAP = 0xB8, 23680ee5cbfSDavid du Colombier TypeOTHER = 0xDA, 2377dd7cddfSDavid du Colombier TypeCPM = 0xDB, 23865fa3f8bSDavid du Colombier TypeDellRecovery= 0xDE, 2397dd7cddfSDavid du Colombier TypeSPEEDSTOR12 = 0xE1, 2407dd7cddfSDavid du Colombier TypeSPEEDSTOR16 = 0xE4, 2417dd7cddfSDavid du Colombier TypeLANSTEP = 0xFE, 2427dd7cddfSDavid du Colombier 2437dd7cddfSDavid du Colombier Type9 = 0x39, 2447dd7cddfSDavid du Colombier 2457dd7cddfSDavid du Colombier Toffset = 446, /* offset of partition table in sector */ 2467dd7cddfSDavid du Colombier Magic0 = 0x55, 2477dd7cddfSDavid du Colombier Magic1 = 0xAA, 2487dd7cddfSDavid du Colombier }; 2497dd7cddfSDavid du Colombier 2507dd7cddfSDavid du Colombier struct Table { 2517dd7cddfSDavid du Colombier Tentry entry[NTentry]; 2527dd7cddfSDavid du Colombier uchar magic[2]; 2537dd7cddfSDavid du Colombier }; 2547dd7cddfSDavid du Colombier 2557dd7cddfSDavid du Colombier struct Type { 2567dd7cddfSDavid du Colombier char *desc; 2577dd7cddfSDavid du Colombier char *name; 2587dd7cddfSDavid du Colombier }; 2597dd7cddfSDavid du Colombier 26080ee5cbfSDavid du Colombier struct Dospart { 26180ee5cbfSDavid du Colombier Part; 2627dd7cddfSDavid du Colombier Tentry; 2637dd7cddfSDavid du Colombier 2647dd7cddfSDavid du Colombier u32int lba; 2657dd7cddfSDavid du Colombier u32int size; 26680ee5cbfSDavid du Colombier int primary; 2677dd7cddfSDavid du Colombier }; 2687dd7cddfSDavid du Colombier 26980ee5cbfSDavid du Colombier struct Recover { 27080ee5cbfSDavid du Colombier Table table; 27180ee5cbfSDavid du Colombier ulong lba; 2727dd7cddfSDavid du Colombier }; 2737dd7cddfSDavid du Colombier 2747dd7cddfSDavid du Colombier static Type types[256] = { 2757dd7cddfSDavid du Colombier [TypeEMPTY] { "EMPTY", "" }, 2767dd7cddfSDavid du Colombier [TypeFAT12] { "FAT12", "dos" }, 2777dd7cddfSDavid du Colombier [TypeFAT16] { "FAT16", "dos" }, 2787dd7cddfSDavid du Colombier [TypeFAT32] { "FAT32", "dos" }, 2797dd7cddfSDavid du Colombier [TypeFAT32LBA] { "FAT32LBA", "dos" }, 2804afe124fSDavid du Colombier [TypeFAT16X] { "FAT16X", "dos" }, 2817dd7cddfSDavid du Colombier [TypeEXTHUGE] { "EXTHUGE", "" }, 2826b6b9ac8SDavid du Colombier [TypeIBMRecovery] { "IBMRECOVERY", "ibm" }, 2837dd7cddfSDavid du Colombier [TypeEXTENDED] { "EXTENDED", "" }, 2847dd7cddfSDavid du Colombier [TypeFATHUGE] { "FATHUGE", "dos" }, 2857dd7cddfSDavid du Colombier [TypeBB] { "BB", "bb" }, 2867dd7cddfSDavid du Colombier 2877dd7cddfSDavid du Colombier [TypeXENIX] { "XENIX", "xenix" }, 2887dd7cddfSDavid du Colombier [TypeXENIXUSR] { "XENIX USR", "xenixusr" }, 2897dd7cddfSDavid du Colombier [TypeHPFS] { "HPFS", "ntfs" }, 2907dd7cddfSDavid du Colombier [TypeAIXBOOT] { "AIXBOOT", "aixboot" }, 2917dd7cddfSDavid du Colombier [TypeAIXDATA] { "AIXDATA", "aixdata" }, 2927dd7cddfSDavid du Colombier [TypeOS2BOOT] { "OS/2BOOT", "os2boot" }, 2937dd7cddfSDavid du Colombier [TypeUNFORMATTED] { "UNFORMATTED", "" }, 2947dd7cddfSDavid du Colombier [TypeHPFS2] { "HPFS2", "hpfs2" }, 2957dd7cddfSDavid du Colombier [TypeCPM0] { "CPM0", "cpm0" }, 2967dd7cddfSDavid du Colombier [TypeDMDDO] { "DMDDO", "dmdd0" }, 2977dd7cddfSDavid du Colombier [TypeGB] { "GB", "gb" }, 2987dd7cddfSDavid du Colombier [TypeSPEEDSTOR] { "SPEEDSTOR", "speedstor" }, 2997dd7cddfSDavid du Colombier [TypeSYSV386] { "SYSV386", "sysv386" }, 3007dd7cddfSDavid du Colombier [TypeNETWARE] { "NETWARE", "netware" }, 3017dd7cddfSDavid du Colombier [TypePCIX] { "PCIX", "pcix" }, 3027dd7cddfSDavid du Colombier [TypeMINIX13] { "MINIXV1.3", "minix13" }, 3037dd7cddfSDavid du Colombier [TypeMINIX] { "MINIXV1.5", "minix15" }, 3047dd7cddfSDavid du Colombier [TypeLINUXSWAP] { "LINUXSWAP", "linuxswap" }, 3057dd7cddfSDavid du Colombier [TypeLINUX] { "LINUX", "linux" }, 3069a747e4fSDavid du Colombier [TypeLINUXEXT] { "LINUXEXTENDED", "" }, 3077dd7cddfSDavid du Colombier [TypeAMOEBA] { "AMOEBA", "amoeba" }, 3087dd7cddfSDavid du Colombier [TypeAMOEBABB] { "AMOEBABB", "amoebaboot" }, 3097dd7cddfSDavid du Colombier [TypeBSD386] { "BSD386", "bsd386" }, 3107dd7cddfSDavid du Colombier [TypeBSDI] { "BSDI", "bsdi" }, 3117dd7cddfSDavid du Colombier [TypeBSDISWAP] { "BSDISWAP", "bsdiswap" }, 31280ee5cbfSDavid du Colombier [TypeOTHER] { "OTHER", "other" }, 3137dd7cddfSDavid du Colombier [TypeCPM] { "CPM", "cpm" }, 31465fa3f8bSDavid du Colombier [TypeDellRecovery] { "DELLRECOVERY", "dell" }, 3157dd7cddfSDavid du Colombier [TypeSPEEDSTOR12] { "SPEEDSTOR12", "speedstor" }, 3167dd7cddfSDavid du Colombier [TypeSPEEDSTOR16] { "SPEEDSTOR16", "speedstor" }, 3177dd7cddfSDavid du Colombier [TypeLANSTEP] { "LANSTEP", "lanstep" }, 3187dd7cddfSDavid du Colombier 3197dd7cddfSDavid du Colombier [Type9] { "PLAN9", "plan9" }, 3207dd7cddfSDavid du Colombier }; 3217dd7cddfSDavid du Colombier 32280ee5cbfSDavid du Colombier static Dospart part[Mpart]; 32380ee5cbfSDavid du Colombier static int npart; 32480ee5cbfSDavid du Colombier 3257dd7cddfSDavid du Colombier static char* 32680ee5cbfSDavid du Colombier typestr0(int type) 3277dd7cddfSDavid du Colombier { 3287dd7cddfSDavid du Colombier static char buf[100]; 3297dd7cddfSDavid du Colombier 3307dd7cddfSDavid du Colombier sprint(buf, "type %d", type); 3317dd7cddfSDavid du Colombier if(type < 0 || type >= 256) 3327dd7cddfSDavid du Colombier return buf; 3337dd7cddfSDavid du Colombier if(types[type].desc == nil) 3347dd7cddfSDavid du Colombier return buf; 3357dd7cddfSDavid du Colombier return types[type].desc; 3367dd7cddfSDavid du Colombier } 3377dd7cddfSDavid du Colombier 3387dd7cddfSDavid du Colombier static u32int 3397dd7cddfSDavid du Colombier getle32(void* v) 3407dd7cddfSDavid du Colombier { 3417dd7cddfSDavid du Colombier uchar *p; 3427dd7cddfSDavid du Colombier 3437dd7cddfSDavid du Colombier p = v; 3447dd7cddfSDavid du Colombier return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]; 3457dd7cddfSDavid du Colombier } 3467dd7cddfSDavid du Colombier 3477dd7cddfSDavid du Colombier static void 3487dd7cddfSDavid du Colombier putle32(void* v, u32int i) 3497dd7cddfSDavid du Colombier { 3507dd7cddfSDavid du Colombier uchar *p; 3517dd7cddfSDavid du Colombier 3527dd7cddfSDavid du Colombier p = v; 3537dd7cddfSDavid du Colombier p[0] = i; 3547dd7cddfSDavid du Colombier p[1] = i>>8; 3557dd7cddfSDavid du Colombier p[2] = i>>16; 3567dd7cddfSDavid du Colombier p[3] = i>>24; 3577dd7cddfSDavid du Colombier } 3587dd7cddfSDavid du Colombier 35980ee5cbfSDavid du Colombier static void 36080ee5cbfSDavid du Colombier diskread(Disk *disk, void *data, int ndata, u32int sec, u32int off) 3617dd7cddfSDavid du Colombier { 3629a747e4fSDavid du Colombier if(seek(disk->fd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off) 36380ee5cbfSDavid du Colombier sysfatal("diskread seek %lud.%lud: %r", (ulong)sec, (ulong)off); 36480ee5cbfSDavid du Colombier if(readn(disk->fd, data, ndata) != ndata) 36580ee5cbfSDavid du Colombier sysfatal("diskread %lud at %lud.%lud: %r", (ulong)ndata, (ulong)sec, (ulong)off); 36680ee5cbfSDavid du Colombier } 3677dd7cddfSDavid du Colombier 36880ee5cbfSDavid du Colombier static int 36980ee5cbfSDavid du Colombier diskwrite(Disk *disk, void *data, int ndata, u32int sec, u32int off) 37080ee5cbfSDavid du Colombier { 37180ee5cbfSDavid du Colombier written = 1; 3729a747e4fSDavid du Colombier if(seek(disk->wfd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off) 37380ee5cbfSDavid du Colombier goto Error; 37480ee5cbfSDavid du Colombier if(write(disk->wfd, data, ndata) != ndata) 37580ee5cbfSDavid du Colombier goto Error; 37680ee5cbfSDavid du Colombier return 0; 3777dd7cddfSDavid du Colombier 37880ee5cbfSDavid du Colombier Error: 37980ee5cbfSDavid du Colombier fprint(2, "write %d bytes at %lud.%lud failed: %r\n", ndata, (ulong)sec, (ulong)off); 38080ee5cbfSDavid du Colombier return -1; 3817dd7cddfSDavid du Colombier } 3827dd7cddfSDavid du Colombier 3837dd7cddfSDavid du Colombier static Dospart* 384*eba00c11SDavid du Colombier mkpart(char *name, int primary, vlong lba, vlong size, Tentry *t) 3857dd7cddfSDavid du Colombier { 38680ee5cbfSDavid du Colombier static int n; 3877dd7cddfSDavid du Colombier Dospart *p; 3887dd7cddfSDavid du Colombier 38980ee5cbfSDavid du Colombier p = emalloc(sizeof(*p)); 39080ee5cbfSDavid du Colombier if(name) 3919a747e4fSDavid du Colombier p->name = estrdup(name); 3929a747e4fSDavid du Colombier else{ 3939a747e4fSDavid du Colombier p->name = emalloc(20); 39480ee5cbfSDavid du Colombier sprint(p->name, "%c%d", primary ? 'p' : 's', ++n); 3959a747e4fSDavid du Colombier } 39680ee5cbfSDavid du Colombier 39780ee5cbfSDavid du Colombier if(t) 39880ee5cbfSDavid du Colombier p->Tentry = *t; 39980ee5cbfSDavid du Colombier else 40080ee5cbfSDavid du Colombier memset(&p->Tentry, 0, sizeof(Tentry)); 40180ee5cbfSDavid du Colombier 4027dd7cddfSDavid du Colombier p->changed = 0; 40380ee5cbfSDavid du Colombier p->start = lba/sec2cyl; 40480ee5cbfSDavid du Colombier p->end = (lba+size)/sec2cyl; 40580ee5cbfSDavid du Colombier p->ctlstart = lba; 40680ee5cbfSDavid du Colombier p->ctlend = lba+size; 40780ee5cbfSDavid du Colombier p->lba = lba; 408*eba00c11SDavid du Colombier if (p->lba != lba) 409*eba00c11SDavid du Colombier fprint(2, "%s: start of partition (%lld) won't fit in MBR table\n", argv0, lba); 41080ee5cbfSDavid du Colombier p->size = size; 411*eba00c11SDavid du Colombier if (p->size != size) 412*eba00c11SDavid du Colombier fprint(2, "%s: size of partition (%lld) won't fit in MBR table\n", argv0, size); 41380ee5cbfSDavid du Colombier p->primary = primary; 4147dd7cddfSDavid du Colombier return p; 4157dd7cddfSDavid du Colombier } 4167dd7cddfSDavid du Colombier 41780ee5cbfSDavid du Colombier /* 41880ee5cbfSDavid du Colombier * Recovery takes care of remembering what the various tables 41980ee5cbfSDavid du Colombier * looked like when we started, attempting to restore them when 42080ee5cbfSDavid du Colombier * we are finished. 42180ee5cbfSDavid du Colombier */ 42280ee5cbfSDavid du Colombier static Recover *rtab; 42380ee5cbfSDavid du Colombier static int nrtab; 4247dd7cddfSDavid du Colombier 42580ee5cbfSDavid du Colombier static void 42680ee5cbfSDavid du Colombier addrecover(Table t, ulong lba) 42780ee5cbfSDavid du Colombier { 42880ee5cbfSDavid du Colombier if((nrtab%8) == 0) { 42980ee5cbfSDavid du Colombier rtab = realloc(rtab, (nrtab+8)*sizeof(rtab[0])); 43080ee5cbfSDavid du Colombier if(rtab == nil) 43180ee5cbfSDavid du Colombier sysfatal("out of memory"); 4327dd7cddfSDavid du Colombier } 43380ee5cbfSDavid du Colombier rtab[nrtab] = (Recover){t, lba}; 43480ee5cbfSDavid du Colombier nrtab++; 43580ee5cbfSDavid du Colombier } 43680ee5cbfSDavid du Colombier 43780ee5cbfSDavid du Colombier static void 43880ee5cbfSDavid du Colombier recover(Edit *edit) 43980ee5cbfSDavid du Colombier { 44080ee5cbfSDavid du Colombier int err, i, ctlfd; 44180ee5cbfSDavid du Colombier vlong offset; 44280ee5cbfSDavid du Colombier 44380ee5cbfSDavid du Colombier err = 0; 44480ee5cbfSDavid du Colombier for(i=0; i<nrtab; i++) 44580ee5cbfSDavid du Colombier if(diskwrite(edit->disk, &rtab[i].table, sizeof(Table), rtab[i].lba, Toffset) < 0) 44680ee5cbfSDavid du Colombier err = 1; 44780ee5cbfSDavid du Colombier if(err) { 44880ee5cbfSDavid du Colombier fprint(2, "warning: some writes failed during restoration of old partition tables\n"); 44980ee5cbfSDavid du Colombier exits("inconsistent"); 45080ee5cbfSDavid du Colombier } else { 45180ee5cbfSDavid du Colombier fprint(2, "restored old partition tables\n"); 45280ee5cbfSDavid du Colombier } 45380ee5cbfSDavid du Colombier 45480ee5cbfSDavid du Colombier ctlfd = edit->disk->ctlfd; 45580ee5cbfSDavid du Colombier offset = edit->disk->offset; 45680ee5cbfSDavid du Colombier if(ctlfd >= 0){ 45780ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 4586b6b9ac8SDavid du Colombier if(edit->part[i]->ctlname && fprint(ctlfd, "delpart %s", edit->part[i]->ctlname)<0) 45980ee5cbfSDavid du Colombier fprint(2, "delpart failed: %s: %r", edit->part[i]->ctlname); 46080ee5cbfSDavid du Colombier for(i=0; i<edit->nctlpart; i++) 4616b6b9ac8SDavid du Colombier if(edit->part[i]->name && fprint(ctlfd, "delpart %s", edit->ctlpart[i]->name)<0) 46280ee5cbfSDavid du Colombier fprint(2, "delpart failed: %s: %r", edit->ctlpart[i]->name); 46380ee5cbfSDavid du Colombier for(i=0; i<edit->nctlpart; i++){ 46480ee5cbfSDavid du Colombier if(fprint(ctlfd, "part %s %lld %lld", edit->ctlpart[i]->name, 46580ee5cbfSDavid du Colombier edit->ctlpart[i]->start+offset, edit->ctlpart[i]->end+offset) < 0){ 46680ee5cbfSDavid du Colombier fprint(2, "restored disk partition table but not kernel; reboot\n"); 46780ee5cbfSDavid du Colombier exits("inconsistent"); 46880ee5cbfSDavid du Colombier } 46980ee5cbfSDavid du Colombier } 47080ee5cbfSDavid du Colombier } 47180ee5cbfSDavid du Colombier exits("restored"); 47280ee5cbfSDavid du Colombier 47380ee5cbfSDavid du Colombier } 47480ee5cbfSDavid du Colombier 47580ee5cbfSDavid du Colombier /* 47680ee5cbfSDavid du Colombier * Read the partition table (including extended partition tables) 47780ee5cbfSDavid du Colombier * from the disk into the part array. 47880ee5cbfSDavid du Colombier */ 47980ee5cbfSDavid du Colombier static void 480*eba00c11SDavid du Colombier rdpart(Edit *edit, uvlong lba, uvlong xbase) 48180ee5cbfSDavid du Colombier { 48280ee5cbfSDavid du Colombier char *err; 48380ee5cbfSDavid du Colombier Table table; 48480ee5cbfSDavid du Colombier Tentry *tp, *ep; 48580ee5cbfSDavid du Colombier Dospart *p; 48680ee5cbfSDavid du Colombier 4879a747e4fSDavid du Colombier if(xbase == 0) 4889a747e4fSDavid du Colombier xbase = lba; 4899a747e4fSDavid du Colombier 49080ee5cbfSDavid du Colombier diskread(edit->disk, &table, sizeof table, mbroffset+lba, Toffset); 49180ee5cbfSDavid du Colombier addrecover(table, mbroffset+lba); 4927dd7cddfSDavid du Colombier 4937dd7cddfSDavid du Colombier if(table.magic[0] != Magic0 || table.magic[1] != Magic1) { 49480ee5cbfSDavid du Colombier assert(lba != 0); 4957dd7cddfSDavid du Colombier return; 4967dd7cddfSDavid du Colombier } 4977dd7cddfSDavid du Colombier 49880ee5cbfSDavid du Colombier for(tp=table.entry, ep=tp+NTentry; tp<ep && npart < Mpart; tp++) { 49980ee5cbfSDavid du Colombier switch(tp->type) { 5007dd7cddfSDavid du Colombier case TypeEMPTY: 5017dd7cddfSDavid du Colombier break; 5027dd7cddfSDavid du Colombier case TypeEXTENDED: 5037dd7cddfSDavid du Colombier case TypeEXTHUGE: 5049a747e4fSDavid du Colombier case TypeLINUXEXT: 5059a747e4fSDavid du Colombier rdpart(edit, xbase+getle32(tp->xlba), xbase); 5067dd7cddfSDavid du Colombier break; 5077dd7cddfSDavid du Colombier default: 50880ee5cbfSDavid du Colombier p = mkpart(nil, lba==0, lba+getle32(tp->xlba), getle32(tp->xsize), tp); 5097dd7cddfSDavid du Colombier if(err = addpart(edit, p)) 51080ee5cbfSDavid du Colombier fprint(2, "adding partition: %s\n", err); 51180ee5cbfSDavid du Colombier break; 51280ee5cbfSDavid du Colombier } 5137dd7cddfSDavid du Colombier } 5147dd7cddfSDavid du Colombier } 5157dd7cddfSDavid du Colombier 5167dd7cddfSDavid du Colombier static void 5177dd7cddfSDavid du Colombier blankpart(Edit *edit) 5187dd7cddfSDavid du Colombier { 5197dd7cddfSDavid du Colombier edit->changed = 1; 5207dd7cddfSDavid du Colombier } 5217dd7cddfSDavid du Colombier 5227dd7cddfSDavid du Colombier static void 5237dd7cddfSDavid du Colombier findmbr(Edit *edit) 5247dd7cddfSDavid du Colombier { 5257dd7cddfSDavid du Colombier Table table; 5267dd7cddfSDavid du Colombier Tentry *tp; 5277dd7cddfSDavid du Colombier 52880ee5cbfSDavid du Colombier diskread(edit->disk, &table, sizeof(Table), 0, Toffset); 5297dd7cddfSDavid du Colombier if(table.magic[0] != Magic0 || table.magic[1] != Magic1) 5307dd7cddfSDavid du Colombier sysfatal("did not find master boot record"); 5317dd7cddfSDavid du Colombier 5327dd7cddfSDavid du Colombier for(tp = table.entry; tp < &table.entry[NTentry]; tp++) 5337dd7cddfSDavid du Colombier if(tp->type == TypeDMDDO) 53480ee5cbfSDavid du Colombier mbroffset = edit->disk->s; 5357dd7cddfSDavid du Colombier } 5367dd7cddfSDavid du Colombier 53780ee5cbfSDavid du Colombier static int 53880ee5cbfSDavid du Colombier haveroom(Edit *edit, int primary, vlong start) 5397dd7cddfSDavid du Colombier { 5409a747e4fSDavid du Colombier int i, lastsec, n; 5419a747e4fSDavid du Colombier Dospart *p, *q; 5429a747e4fSDavid du Colombier ulong pend, qstart; 54380ee5cbfSDavid du Colombier 54480ee5cbfSDavid du Colombier if(primary) { 54580ee5cbfSDavid du Colombier /* 54680ee5cbfSDavid du Colombier * must be open primary slot. 54780ee5cbfSDavid du Colombier * primary slots are taken by primary partitions 54880ee5cbfSDavid du Colombier * and runs of secondary partitions. 54980ee5cbfSDavid du Colombier */ 55080ee5cbfSDavid du Colombier n = 0; 55180ee5cbfSDavid du Colombier lastsec = 0; 55280ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) { 55380ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 55480ee5cbfSDavid du Colombier if(p->primary) 55580ee5cbfSDavid du Colombier n++, lastsec=0; 5569a747e4fSDavid du Colombier else if(!lastsec) 55780ee5cbfSDavid du Colombier n++, lastsec=1; 5587dd7cddfSDavid du Colombier } 55980ee5cbfSDavid du Colombier return n<4; 5607dd7cddfSDavid du Colombier } 5617dd7cddfSDavid du Colombier 56280ee5cbfSDavid du Colombier /* 56380ee5cbfSDavid du Colombier * secondary partitions can be inserted between two primary 56480ee5cbfSDavid du Colombier * partitions only if there is an empty primary slot. 56580ee5cbfSDavid du Colombier * otherwise, we can put a new secondary partition next 56680ee5cbfSDavid du Colombier * to a secondary partition no problem. 56780ee5cbfSDavid du Colombier */ 56880ee5cbfSDavid du Colombier n = 0; 5696b6b9ac8SDavid du Colombier for(i=0; i<edit->npart; i++){ 57080ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 57180ee5cbfSDavid du Colombier if(p->primary) 5729a747e4fSDavid du Colombier n++; 5739a747e4fSDavid du Colombier pend = p->end; 5749a747e4fSDavid du Colombier if(i+1<edit->npart){ 5759a747e4fSDavid du Colombier q = (Dospart*)edit->part[i+1]; 5769a747e4fSDavid du Colombier qstart = q->start; 5779a747e4fSDavid du Colombier }else{ 5789a747e4fSDavid du Colombier qstart = edit->end; 5799a747e4fSDavid du Colombier q = nil; 5807dd7cddfSDavid du Colombier } 5819a747e4fSDavid du Colombier if(start < pend || start >= qstart) 5829a747e4fSDavid du Colombier continue; 5839a747e4fSDavid du Colombier /* we go between these two */ 5849a747e4fSDavid du Colombier if(p->primary==0 || (q && q->primary==0)) 5859a747e4fSDavid du Colombier return 1; 5867dd7cddfSDavid du Colombier } 58780ee5cbfSDavid du Colombier /* not next to a secondary, need a new primary */ 58880ee5cbfSDavid du Colombier return n<4; 5897dd7cddfSDavid du Colombier } 5907dd7cddfSDavid du Colombier 5917dd7cddfSDavid du Colombier static void 5927dd7cddfSDavid du Colombier autopart(Edit *edit) 5937dd7cddfSDavid du Colombier { 59480ee5cbfSDavid du Colombier char *err; 59580ee5cbfSDavid du Colombier int active, i; 59680ee5cbfSDavid du Colombier vlong bigstart, bigsize, start; 59780ee5cbfSDavid du Colombier Dospart *p; 5987dd7cddfSDavid du Colombier 59980ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 60080ee5cbfSDavid du Colombier if(((Dospart*)edit->part[i])->type == Type9) 6017dd7cddfSDavid du Colombier return; 6027dd7cddfSDavid du Colombier 60380ee5cbfSDavid du Colombier /* look for the biggest gap in which we can put a primary partition */ 60480ee5cbfSDavid du Colombier start = 0; 6057dd7cddfSDavid du Colombier bigsize = 0; 6067dd7cddfSDavid du Colombier SET(bigstart); 6077dd7cddfSDavid du Colombier for(i=0; i<edit->npart; i++) { 60880ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 60980ee5cbfSDavid du Colombier if(p->start > start && p->start - start > bigsize && haveroom(edit, 1, start)) { 6107dd7cddfSDavid du Colombier bigsize = p->start - start; 6117dd7cddfSDavid du Colombier bigstart = start; 6127dd7cddfSDavid du Colombier } 6137dd7cddfSDavid du Colombier start = p->end; 6147dd7cddfSDavid du Colombier } 6157dd7cddfSDavid du Colombier 61680ee5cbfSDavid du Colombier if(edit->end - start > bigsize && haveroom(edit, 1, start)) { 61780ee5cbfSDavid du Colombier bigsize = edit->end - start; 6187dd7cddfSDavid du Colombier bigstart = start; 6197dd7cddfSDavid du Colombier } 62080ee5cbfSDavid du Colombier if(bigsize < 1) { 62180ee5cbfSDavid du Colombier fprint(2, "couldn't find space or partition slot for plan 9 partition\n"); 6227dd7cddfSDavid du Colombier return; 6237dd7cddfSDavid du Colombier } 6247dd7cddfSDavid du Colombier 62580ee5cbfSDavid du Colombier /* set new partition active only if no others are */ 6267dd7cddfSDavid du Colombier active = Active; 62780ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 62880ee5cbfSDavid du Colombier if(((Dospart*)edit->part[i])->primary && (((Dospart*)edit->part[i])->active & Active)) 6297dd7cddfSDavid du Colombier active = 0; 6307dd7cddfSDavid du Colombier 63180ee5cbfSDavid du Colombier /* add new plan 9 partition */ 63280ee5cbfSDavid du Colombier bigsize *= sec2cyl; 63380ee5cbfSDavid du Colombier bigstart *= sec2cyl; 63480ee5cbfSDavid du Colombier if(bigstart == 0) { 63580ee5cbfSDavid du Colombier bigstart += edit->disk->s; 63680ee5cbfSDavid du Colombier bigsize -= edit->disk->s; 6377dd7cddfSDavid du Colombier } 63880ee5cbfSDavid du Colombier p = mkpart(nil, 1, bigstart, bigsize, nil); 63980ee5cbfSDavid du Colombier p->active = active; 64080ee5cbfSDavid du Colombier p->changed = 1; 64180ee5cbfSDavid du Colombier p->type = Type9; 64280ee5cbfSDavid du Colombier edit->changed = 1; 64380ee5cbfSDavid du Colombier if(err = addpart(edit, p)) { 64480ee5cbfSDavid du Colombier fprint(2, "error adding plan9 partition: %s\n", err); 6457dd7cddfSDavid du Colombier return; 6467dd7cddfSDavid du Colombier } 6477dd7cddfSDavid du Colombier } 6487dd7cddfSDavid du Colombier 6497dd7cddfSDavid du Colombier typedef struct Name Name; 6507dd7cddfSDavid du Colombier struct Name { 6519a747e4fSDavid du Colombier char *name; 6527dd7cddfSDavid du Colombier Name *link; 6537dd7cddfSDavid du Colombier }; 6547dd7cddfSDavid du Colombier Name *namelist; 6557dd7cddfSDavid du Colombier static void 65680ee5cbfSDavid du Colombier plan9print(Dospart *part, int fd) 6577dd7cddfSDavid du Colombier { 6587dd7cddfSDavid du Colombier int i, ok; 6599a747e4fSDavid du Colombier char *name, *vname; 6607dd7cddfSDavid du Colombier Name *n; 66180ee5cbfSDavid du Colombier vlong start, end; 66280ee5cbfSDavid du Colombier char *sep; 66380ee5cbfSDavid du Colombier 66480ee5cbfSDavid du Colombier vname = types[part->type].name; 6659a747e4fSDavid du Colombier if(vname==nil || strcmp(vname, "")==0) { 6669a747e4fSDavid du Colombier part->ctlname = ""; 66780ee5cbfSDavid du Colombier return; 66880ee5cbfSDavid du Colombier } 66980ee5cbfSDavid du Colombier 67080ee5cbfSDavid du Colombier start = mbroffset+part->lba; 67180ee5cbfSDavid du Colombier end = start+part->size; 67280ee5cbfSDavid du Colombier 67380ee5cbfSDavid du Colombier /* avoid names like plan90 */ 67480ee5cbfSDavid du Colombier i = strlen(vname) - 1; 67580ee5cbfSDavid du Colombier if(vname[i] >= '0' && vname[i] <= '9') 67680ee5cbfSDavid du Colombier sep = "."; 67780ee5cbfSDavid du Colombier else 67880ee5cbfSDavid du Colombier sep = ""; 6797dd7cddfSDavid du Colombier 6807dd7cddfSDavid du Colombier i = 0; 6819a747e4fSDavid du Colombier name = emalloc(strlen(vname)+10); 6829a747e4fSDavid du Colombier 68380ee5cbfSDavid du Colombier sprint(name, "%s", vname); 6847dd7cddfSDavid du Colombier do { 6857dd7cddfSDavid du Colombier ok = 1; 6867dd7cddfSDavid du Colombier for(n=namelist; n; n=n->link) { 6877dd7cddfSDavid du Colombier if(strcmp(name, n->name) == 0) { 6887dd7cddfSDavid du Colombier i++; 68980ee5cbfSDavid du Colombier sprint(name, "%s%s%d", vname, sep, i); 6907dd7cddfSDavid du Colombier ok = 0; 6917dd7cddfSDavid du Colombier } 6927dd7cddfSDavid du Colombier } 6937dd7cddfSDavid du Colombier } while(ok == 0); 6947dd7cddfSDavid du Colombier 6959a747e4fSDavid du Colombier n = emalloc(sizeof(*n)); 6969a747e4fSDavid du Colombier n->name = name; 6977dd7cddfSDavid du Colombier n->link = namelist; 6987dd7cddfSDavid du Colombier namelist = n; 6999a747e4fSDavid du Colombier part->ctlname = name; 7007dd7cddfSDavid du Colombier 7017dd7cddfSDavid du Colombier if(fd >= 0) 7027dd7cddfSDavid du Colombier print("part %s %lld %lld\n", name, start, end); 7037dd7cddfSDavid du Colombier } 7047dd7cddfSDavid du Colombier 7057dd7cddfSDavid du Colombier static void 7067dd7cddfSDavid du Colombier freenamelist(void) 7077dd7cddfSDavid du Colombier { 7087dd7cddfSDavid du Colombier Name *n, *next; 7097dd7cddfSDavid du Colombier 7107dd7cddfSDavid du Colombier for(n=namelist; n; n=next) { 7117dd7cddfSDavid du Colombier next = n->link; 7127dd7cddfSDavid du Colombier free(n); 7137dd7cddfSDavid du Colombier } 7147dd7cddfSDavid du Colombier namelist = nil; 7157dd7cddfSDavid du Colombier } 7167dd7cddfSDavid du Colombier 7177dd7cddfSDavid du Colombier static void 7187dd7cddfSDavid du Colombier cmdprintctl(Edit *edit, int ctlfd) 7197dd7cddfSDavid du Colombier { 7207dd7cddfSDavid du Colombier int i; 7217dd7cddfSDavid du Colombier 7227dd7cddfSDavid du Colombier freenamelist(); 7237dd7cddfSDavid du Colombier for(i=0; i<edit->npart; i++) 72480ee5cbfSDavid du Colombier plan9print((Dospart*)edit->part[i], -1); 7257dd7cddfSDavid du Colombier ctldiff(edit, ctlfd); 7267dd7cddfSDavid du Colombier } 7277dd7cddfSDavid du Colombier 7287dd7cddfSDavid du Colombier static char* 7297dd7cddfSDavid du Colombier cmdokname(Edit*, char *name) 7307dd7cddfSDavid du Colombier { 73180ee5cbfSDavid du Colombier char *q; 73280ee5cbfSDavid du Colombier 73380ee5cbfSDavid du Colombier if(name[0] != 'p' && name[0] != 's') 73480ee5cbfSDavid du Colombier return "name must be pN or sN"; 73580ee5cbfSDavid du Colombier 73680ee5cbfSDavid du Colombier strtol(name+1, &q, 10); 73780ee5cbfSDavid du Colombier if(*q != '\0') 73880ee5cbfSDavid du Colombier return "name must be pN or sN"; 73980ee5cbfSDavid du Colombier 7407dd7cddfSDavid du Colombier return nil; 7417dd7cddfSDavid du Colombier } 7427dd7cddfSDavid du Colombier 743*eba00c11SDavid du Colombier #define TB (1024LL*GB) 7447dd7cddfSDavid du Colombier #define GB (1024*1024*1024) 7457dd7cddfSDavid du Colombier #define MB (1024*1024) 7467dd7cddfSDavid du Colombier #define KB (1024) 7477dd7cddfSDavid du Colombier 7487dd7cddfSDavid du Colombier static void 7497dd7cddfSDavid du Colombier cmdsum(Edit *edit, Part *vp, vlong a, vlong b) 7507dd7cddfSDavid du Colombier { 7517dd7cddfSDavid du Colombier char *name, *ty; 7527dd7cddfSDavid du Colombier char buf[3]; 75380ee5cbfSDavid du Colombier char *suf; 7547dd7cddfSDavid du Colombier Dospart *p; 75580ee5cbfSDavid du Colombier vlong sz, div; 7567dd7cddfSDavid du Colombier 7577dd7cddfSDavid du Colombier p = (Dospart*)vp; 7587dd7cddfSDavid du Colombier 7597dd7cddfSDavid du Colombier buf[0] = p && p->changed ? '\'' : ' '; 7607dd7cddfSDavid du Colombier buf[1] = p && (p->active & Active) ? '*' : ' '; 7617dd7cddfSDavid du Colombier buf[2] = '\0'; 7627dd7cddfSDavid du Colombier 7637dd7cddfSDavid du Colombier name = p ? p->name : "empty"; 76480ee5cbfSDavid du Colombier ty = p ? typestr0(p->type) : ""; 7657dd7cddfSDavid du Colombier 76680ee5cbfSDavid du Colombier sz = (b-a)*edit->disk->secsize*sec2cyl; 767*eba00c11SDavid du Colombier if(sz >= 1*TB){ 768*eba00c11SDavid du Colombier suf = "TB"; 769*eba00c11SDavid du Colombier div = TB; 770*eba00c11SDavid du Colombier }else if(sz >= 1*GB){ 77180ee5cbfSDavid du Colombier suf = "GB"; 77280ee5cbfSDavid du Colombier div = GB; 77380ee5cbfSDavid du Colombier }else if(sz >= 1*MB){ 77480ee5cbfSDavid du Colombier suf = "MB"; 77580ee5cbfSDavid du Colombier div = MB; 77680ee5cbfSDavid du Colombier }else if(sz >= 1*KB){ 77780ee5cbfSDavid du Colombier suf = "KB"; 77880ee5cbfSDavid du Colombier div = KB; 77980ee5cbfSDavid du Colombier }else{ 78080ee5cbfSDavid du Colombier suf = "B "; 78180ee5cbfSDavid du Colombier div = 1; 78280ee5cbfSDavid du Colombier } 78380ee5cbfSDavid du Colombier 78480ee5cbfSDavid du Colombier if(div == 1) 78580ee5cbfSDavid du Colombier print("%s %-12s %*lld %-*lld (%lld cylinders, %lld %s) %s\n", buf, name, 78680ee5cbfSDavid du Colombier edit->disk->width, a, edit->disk->width, b, b-a, sz, suf, ty); 78780ee5cbfSDavid du Colombier else 78880ee5cbfSDavid du Colombier print("%s %-12s %*lld %-*lld (%lld cylinders, %lld.%.2d %s) %s\n", buf, name, 78980ee5cbfSDavid du Colombier edit->disk->width, a, edit->disk->width, b, b-a, 79080ee5cbfSDavid du Colombier sz/div, (int)(((sz%div)*100)/div), suf, ty); 7917dd7cddfSDavid du Colombier } 7927dd7cddfSDavid du Colombier 7937dd7cddfSDavid du Colombier static char* 7947dd7cddfSDavid du Colombier cmdadd(Edit *edit, char *name, vlong start, vlong end) 7957dd7cddfSDavid du Colombier { 79680ee5cbfSDavid du Colombier Dospart *p; 7977dd7cddfSDavid du Colombier 79880ee5cbfSDavid du Colombier if(!haveroom(edit, name[0]=='p', start)) 79980ee5cbfSDavid du Colombier return "no room for partition"; 8009a747e4fSDavid du Colombier start *= sec2cyl; 8019a747e4fSDavid du Colombier end *= sec2cyl; 8026b6b9ac8SDavid du Colombier if(start == 0 || name[0] != 'p') 8036b6b9ac8SDavid du Colombier start += edit->disk->s; 8049a747e4fSDavid du Colombier p = mkpart(name, name[0]=='p', start, end-start, nil); 80580ee5cbfSDavid du Colombier p->changed = 1; 806d9dc5dd1SDavid du Colombier p->type = Type9; 80780ee5cbfSDavid du Colombier return addpart(edit, p); 8087dd7cddfSDavid du Colombier } 8097dd7cddfSDavid du Colombier 8107dd7cddfSDavid du Colombier static char* 8117dd7cddfSDavid du Colombier cmddel(Edit *edit, Part *p) 8127dd7cddfSDavid du Colombier { 81380ee5cbfSDavid du Colombier return delpart(edit, p); 8147dd7cddfSDavid du Colombier } 8157dd7cddfSDavid du Colombier 8167dd7cddfSDavid du Colombier static char* 8177dd7cddfSDavid du Colombier cmdwrite(Edit *edit) 8187dd7cddfSDavid du Colombier { 8197dd7cddfSDavid du Colombier wrpart(edit); 8207dd7cddfSDavid du Colombier return nil; 8217dd7cddfSDavid du Colombier } 8227dd7cddfSDavid du Colombier 8237dd7cddfSDavid du Colombier static char *help = 8247dd7cddfSDavid du Colombier "A name - set partition active\n" 8257dd7cddfSDavid du Colombier "P - print table in ctl format\n" 8266b6b9ac8SDavid du Colombier "R - restore disk back to initial configuration and exit\n" 8277dd7cddfSDavid du Colombier "e - show empty dos partitions\n" 8287dd7cddfSDavid du Colombier "t name [type] - set partition type\n"; 8297dd7cddfSDavid du Colombier 8307dd7cddfSDavid du Colombier static char* 8317dd7cddfSDavid du Colombier cmdhelp(Edit*) 8327dd7cddfSDavid du Colombier { 8337dd7cddfSDavid du Colombier print("%s\n", help); 8347dd7cddfSDavid du Colombier return nil; 8357dd7cddfSDavid du Colombier } 8367dd7cddfSDavid du Colombier 8377dd7cddfSDavid du Colombier static char* 8387dd7cddfSDavid du Colombier cmdactive(Edit *edit, int nf, char **f) 8397dd7cddfSDavid du Colombier { 8407dd7cddfSDavid du Colombier int i; 84180ee5cbfSDavid du Colombier Dospart *p, *ip; 8427dd7cddfSDavid du Colombier 8437dd7cddfSDavid du Colombier if(nf != 2) 8447dd7cddfSDavid du Colombier return "args"; 8457dd7cddfSDavid du Colombier 8469a747e4fSDavid du Colombier if(f[1][0] != 'p') 8479a747e4fSDavid du Colombier return "cannot set secondary partition active"; 8489a747e4fSDavid du Colombier 84980ee5cbfSDavid du Colombier if((p = (Dospart*)findpart(edit, f[1])) == nil) 85080ee5cbfSDavid du Colombier return "unknown partition"; 8517dd7cddfSDavid du Colombier 85280ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) { 85380ee5cbfSDavid du Colombier ip = (Dospart*)edit->part[i]; 85480ee5cbfSDavid du Colombier if(ip->active & Active) { 85580ee5cbfSDavid du Colombier ip->active &= ~Active; 85680ee5cbfSDavid du Colombier ip->changed = 1; 8577dd7cddfSDavid du Colombier edit->changed = 1; 8587dd7cddfSDavid du Colombier } 8597dd7cddfSDavid du Colombier } 86080ee5cbfSDavid du Colombier 8617dd7cddfSDavid du Colombier if((p->active & Active) == 0) { 8627dd7cddfSDavid du Colombier p->active |= Active; 8637dd7cddfSDavid du Colombier p->changed = 1; 8647dd7cddfSDavid du Colombier edit->changed = 1; 8657dd7cddfSDavid du Colombier } 8667dd7cddfSDavid du Colombier 8677dd7cddfSDavid du Colombier return nil; 8687dd7cddfSDavid du Colombier } 8697dd7cddfSDavid du Colombier 8707dd7cddfSDavid du Colombier static char* 8717dd7cddfSDavid du Colombier strupr(char *s) 8727dd7cddfSDavid du Colombier { 8737dd7cddfSDavid du Colombier char *p; 8747dd7cddfSDavid du Colombier 8757dd7cddfSDavid du Colombier for(p=s; *p; p++) 8767dd7cddfSDavid du Colombier *p = toupper(*p); 8777dd7cddfSDavid du Colombier return s; 8787dd7cddfSDavid du Colombier } 8797dd7cddfSDavid du Colombier 8807dd7cddfSDavid du Colombier static void 8817dd7cddfSDavid du Colombier dumplist(void) 8827dd7cddfSDavid du Colombier { 8837dd7cddfSDavid du Colombier int i, n; 8847dd7cddfSDavid du Colombier 8857dd7cddfSDavid du Colombier n = 0; 8867dd7cddfSDavid du Colombier for(i=0; i<256; i++) { 8877dd7cddfSDavid du Colombier if(types[i].desc) { 8887dd7cddfSDavid du Colombier print("%-16s", types[i].desc); 8897dd7cddfSDavid du Colombier if(n++%4 == 3) 8907dd7cddfSDavid du Colombier print("\n"); 8917dd7cddfSDavid du Colombier } 8927dd7cddfSDavid du Colombier } 8937dd7cddfSDavid du Colombier if(n%4) 8947dd7cddfSDavid du Colombier print("\n"); 8957dd7cddfSDavid du Colombier } 8967dd7cddfSDavid du Colombier 8977dd7cddfSDavid du Colombier static char* 8987dd7cddfSDavid du Colombier cmdtype(Edit *edit, int nf, char **f) 8997dd7cddfSDavid du Colombier { 9007dd7cddfSDavid du Colombier char *q; 9017dd7cddfSDavid du Colombier Dospart *p; 9027dd7cddfSDavid du Colombier int i; 9037dd7cddfSDavid du Colombier 9047dd7cddfSDavid du Colombier if(nf < 2) 9057dd7cddfSDavid du Colombier return "args"; 9067dd7cddfSDavid du Colombier 9077dd7cddfSDavid du Colombier if((p = (Dospart*)findpart(edit, f[1])) == nil) 9087dd7cddfSDavid du Colombier return "unknown partition"; 9097dd7cddfSDavid du Colombier 9107dd7cddfSDavid du Colombier if(nf == 2) { 9117dd7cddfSDavid du Colombier for(;;) { 9127dd7cddfSDavid du Colombier fprint(2, "new partition type [? for list]: "); 9137dd7cddfSDavid du Colombier q = getline(edit); 9147dd7cddfSDavid du Colombier if(q[0] == '?') 9157dd7cddfSDavid du Colombier dumplist(); 9167dd7cddfSDavid du Colombier else 9177dd7cddfSDavid du Colombier break; 9187dd7cddfSDavid du Colombier } 9197dd7cddfSDavid du Colombier } else 9207dd7cddfSDavid du Colombier q = f[2]; 9217dd7cddfSDavid du Colombier 9227dd7cddfSDavid du Colombier strupr(q); 9237dd7cddfSDavid du Colombier for(i=0; i<256; i++) 9247dd7cddfSDavid du Colombier if(types[i].desc && strcmp(types[i].desc, q) == 0) 9257dd7cddfSDavid du Colombier break; 9267dd7cddfSDavid du Colombier if(i < 256 && p->type != i) { 9277dd7cddfSDavid du Colombier p->type = i; 9287dd7cddfSDavid du Colombier p->changed = 1; 9297dd7cddfSDavid du Colombier edit->changed = 1; 9307dd7cddfSDavid du Colombier } 9317dd7cddfSDavid du Colombier return nil; 9327dd7cddfSDavid du Colombier } 9337dd7cddfSDavid du Colombier 9347dd7cddfSDavid du Colombier static char* 9357dd7cddfSDavid du Colombier cmdext(Edit *edit, int nf, char **f) 9367dd7cddfSDavid du Colombier { 9377dd7cddfSDavid du Colombier switch(f[0][0]) { 9387dd7cddfSDavid du Colombier case 'A': 9397dd7cddfSDavid du Colombier return cmdactive(edit, nf, f); 9407dd7cddfSDavid du Colombier case 't': 9417dd7cddfSDavid du Colombier return cmdtype(edit, nf, f); 94280ee5cbfSDavid du Colombier case 'R': 94380ee5cbfSDavid du Colombier recover(edit); 94480ee5cbfSDavid du Colombier return nil; 9457dd7cddfSDavid du Colombier default: 9467dd7cddfSDavid du Colombier return "unknown command"; 9477dd7cddfSDavid du Colombier } 9487dd7cddfSDavid du Colombier } 9497dd7cddfSDavid du Colombier 95080ee5cbfSDavid du Colombier static int 9519a747e4fSDavid du Colombier Dfmt(Fmt *f) 95280ee5cbfSDavid du Colombier { 95380ee5cbfSDavid du Colombier char buf[60]; 95480ee5cbfSDavid du Colombier uchar *p; 95580ee5cbfSDavid du Colombier int c, h, s; 95680ee5cbfSDavid du Colombier 9579a747e4fSDavid du Colombier p = va_arg(f->args, uchar*); 95880ee5cbfSDavid du Colombier h = p[0]; 95980ee5cbfSDavid du Colombier c = p[2]; 96080ee5cbfSDavid du Colombier c |= (p[1]&0xC0)<<2; 96180ee5cbfSDavid du Colombier s = (p[1] & 0x3F); 96280ee5cbfSDavid du Colombier 96380ee5cbfSDavid du Colombier sprint(buf, "%d/%d/%d", c, h, s); 9649a747e4fSDavid du Colombier return fmtstrcpy(f, buf); 96580ee5cbfSDavid du Colombier } 96680ee5cbfSDavid du Colombier 96780ee5cbfSDavid du Colombier static void 96880ee5cbfSDavid du Colombier writechs(Disk *disk, uchar *p, vlong lba) 96980ee5cbfSDavid du Colombier { 97080ee5cbfSDavid du Colombier int c, h, s; 97180ee5cbfSDavid du Colombier 97280ee5cbfSDavid du Colombier s = lba % disk->s; 97380ee5cbfSDavid du Colombier h = (lba / disk->s) % disk->h; 97480ee5cbfSDavid du Colombier c = lba / (disk->s * disk->h); 97580ee5cbfSDavid du Colombier 97680ee5cbfSDavid du Colombier if(c >= 1024) { 97780ee5cbfSDavid du Colombier c = 1023; 97880ee5cbfSDavid du Colombier h = disk->h - 1; 97980ee5cbfSDavid du Colombier s = disk->s - 1; 98080ee5cbfSDavid du Colombier } 98180ee5cbfSDavid du Colombier 98280ee5cbfSDavid du Colombier p[0] = h; 98380ee5cbfSDavid du Colombier p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0); 98480ee5cbfSDavid du Colombier p[2] = c; 98580ee5cbfSDavid du Colombier } 98680ee5cbfSDavid du Colombier 98780ee5cbfSDavid du Colombier static void 9889a747e4fSDavid du Colombier wrtentry(Disk *disk, Tentry *tp, int type, u32int xbase, u32int lba, u32int end) 98980ee5cbfSDavid du Colombier { 99080ee5cbfSDavid du Colombier tp->type = type; 9919a747e4fSDavid du Colombier writechs(disk, &tp->starth, lba); 9929a747e4fSDavid du Colombier writechs(disk, &tp->endh, end-1); 9939a747e4fSDavid du Colombier putle32(tp->xlba, lba-xbase); 9949a747e4fSDavid du Colombier putle32(tp->xsize, end-lba); 99580ee5cbfSDavid du Colombier } 99680ee5cbfSDavid du Colombier 99780ee5cbfSDavid du Colombier static int 9989a747e4fSDavid du Colombier wrextend(Edit *edit, int i, vlong xbase, vlong startlba, vlong *endlba) 99980ee5cbfSDavid du Colombier { 100080ee5cbfSDavid du Colombier int ni; 100180ee5cbfSDavid du Colombier Table table; 100280ee5cbfSDavid du Colombier Tentry *tp, *ep; 100380ee5cbfSDavid du Colombier Dospart *p; 100480ee5cbfSDavid du Colombier Disk *disk; 100580ee5cbfSDavid du Colombier 10069a747e4fSDavid du Colombier if(i == edit->npart){ 10079a747e4fSDavid du Colombier *endlba = edit->disk->secs; 10089a747e4fSDavid du Colombier Finish: 10099a747e4fSDavid du Colombier if(startlba < *endlba){ 10109a747e4fSDavid du Colombier disk = edit->disk; 10119a747e4fSDavid du Colombier diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset); 10129a747e4fSDavid du Colombier tp = table.entry; 10139a747e4fSDavid du Colombier ep = tp+NTentry; 10149a747e4fSDavid du Colombier for(; tp<ep; tp++) 10159a747e4fSDavid du Colombier memset(tp, 0, sizeof *tp); 10169a747e4fSDavid du Colombier table.magic[0] = Magic0; 10179a747e4fSDavid du Colombier table.magic[1] = Magic1; 10189a747e4fSDavid du Colombier 10199a747e4fSDavid du Colombier if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0) 10209a747e4fSDavid du Colombier recover(edit); 10219a747e4fSDavid du Colombier } 102280ee5cbfSDavid du Colombier return i; 10239a747e4fSDavid du Colombier } 102480ee5cbfSDavid du Colombier 102580ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 10269a747e4fSDavid du Colombier if(p->primary){ 10279a747e4fSDavid du Colombier *endlba = (vlong)p->start*sec2cyl; 10289a747e4fSDavid du Colombier goto Finish; 10299a747e4fSDavid du Colombier } 103080ee5cbfSDavid du Colombier 103180ee5cbfSDavid du Colombier disk = edit->disk; 10329a747e4fSDavid du Colombier diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset); 103380ee5cbfSDavid du Colombier tp = table.entry; 103480ee5cbfSDavid du Colombier ep = tp+NTentry; 103580ee5cbfSDavid du Colombier 10369a747e4fSDavid du Colombier ni = wrextend(edit, i+1, xbase, p->end*sec2cyl, endlba); 103780ee5cbfSDavid du Colombier 103880ee5cbfSDavid du Colombier *tp = p->Tentry; 10399a747e4fSDavid du Colombier wrtentry(disk, tp, p->type, startlba, startlba+disk->s, p->end*sec2cyl); 104080ee5cbfSDavid du Colombier tp++; 104180ee5cbfSDavid du Colombier 10429a747e4fSDavid du Colombier if(p->end*sec2cyl != *endlba){ 104380ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp); 10449a747e4fSDavid du Colombier wrtentry(disk, tp, TypeEXTENDED, xbase, p->end*sec2cyl, *endlba); 104580ee5cbfSDavid du Colombier tp++; 104680ee5cbfSDavid du Colombier } 104780ee5cbfSDavid du Colombier 104880ee5cbfSDavid du Colombier for(; tp<ep; tp++) 104980ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp); 105080ee5cbfSDavid du Colombier 105180ee5cbfSDavid du Colombier table.magic[0] = Magic0; 105280ee5cbfSDavid du Colombier table.magic[1] = Magic1; 105380ee5cbfSDavid du Colombier 10549a747e4fSDavid du Colombier if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0) 105580ee5cbfSDavid du Colombier recover(edit); 105680ee5cbfSDavid du Colombier return ni; 105780ee5cbfSDavid du Colombier } 105880ee5cbfSDavid du Colombier 105980ee5cbfSDavid du Colombier static void 106080ee5cbfSDavid du Colombier wrpart(Edit *edit) 106180ee5cbfSDavid du Colombier { 10629a747e4fSDavid du Colombier int i, ni, t; 106380ee5cbfSDavid du Colombier Table table; 106480ee5cbfSDavid du Colombier Tentry *tp, *ep; 106580ee5cbfSDavid du Colombier Disk *disk; 106680ee5cbfSDavid du Colombier vlong s, endlba; 106780ee5cbfSDavid du Colombier Dospart *p; 106880ee5cbfSDavid du Colombier 106980ee5cbfSDavid du Colombier disk = edit->disk; 107080ee5cbfSDavid du Colombier 107180ee5cbfSDavid du Colombier diskread(disk, &table, sizeof table, mbroffset, Toffset); 107280ee5cbfSDavid du Colombier 107380ee5cbfSDavid du Colombier tp = table.entry; 107480ee5cbfSDavid du Colombier ep = tp+NTentry; 107580ee5cbfSDavid du Colombier for(i=0; i<edit->npart && tp<ep; ) { 107680ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 107780ee5cbfSDavid du Colombier if(p->start == 0) 107880ee5cbfSDavid du Colombier s = disk->s; 107980ee5cbfSDavid du Colombier else 108080ee5cbfSDavid du Colombier s = p->start*sec2cyl; 108180ee5cbfSDavid du Colombier if(p->primary) { 108280ee5cbfSDavid du Colombier *tp = p->Tentry; 10839a747e4fSDavid du Colombier wrtentry(disk, tp, p->type, 0, s, p->end*sec2cyl); 108480ee5cbfSDavid du Colombier tp++; 108580ee5cbfSDavid du Colombier i++; 108680ee5cbfSDavid du Colombier } else { 10879a747e4fSDavid du Colombier ni = wrextend(edit, i, p->start*sec2cyl, p->start*sec2cyl, &endlba); 108880ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp); 10899a747e4fSDavid du Colombier if(endlba >= 1024*sec2cyl) 10909a747e4fSDavid du Colombier t = TypeEXTHUGE; 10919a747e4fSDavid du Colombier else 10929a747e4fSDavid du Colombier t = TypeEXTENDED; 10939a747e4fSDavid du Colombier wrtentry(disk, tp, t, 0, s, endlba); 109480ee5cbfSDavid du Colombier tp++; 109580ee5cbfSDavid du Colombier i = ni; 109680ee5cbfSDavid du Colombier } 109780ee5cbfSDavid du Colombier } 109880ee5cbfSDavid du Colombier for(; tp<ep; tp++) 109980ee5cbfSDavid du Colombier memset(tp, 0, sizeof(*tp)); 110080ee5cbfSDavid du Colombier 110180ee5cbfSDavid du Colombier if(i != edit->npart) 110280ee5cbfSDavid du Colombier sysfatal("cannot happen #1"); 110380ee5cbfSDavid du Colombier 110480ee5cbfSDavid du Colombier if(diskwrite(disk, &table, sizeof table, mbroffset, Toffset) < 0) 110580ee5cbfSDavid du Colombier recover(edit); 110680ee5cbfSDavid du Colombier 110780ee5cbfSDavid du Colombier /* bring parts up to date */ 110880ee5cbfSDavid du Colombier freenamelist(); 110980ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 111080ee5cbfSDavid du Colombier plan9print((Dospart*)edit->part[i], -1); 111180ee5cbfSDavid du Colombier 111280ee5cbfSDavid du Colombier if(ctldiff(edit, disk->ctlfd) < 0) 111380ee5cbfSDavid du Colombier fprint(2, "?warning: partitions could not be updated in devsd\n"); 111480ee5cbfSDavid du Colombier } 1115