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
17eba00c11SDavid 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
sysfatal(char * fmt,...)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
abort(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
usage(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
main(int argc,char ** argv)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
195*9e732705SDavid du Colombier struct Table {
196*9e732705SDavid du Colombier Tentry entry[NTentry];
197*9e732705SDavid du Colombier uchar magic[2];
198*9e732705SDavid du Colombier uchar size[];
199*9e732705SDavid du Colombier };
200*9e732705SDavid du Colombier
2017dd7cddfSDavid du Colombier enum {
2027dd7cddfSDavid du Colombier Active = 0x80, /* partition is active */
2037dd7cddfSDavid du Colombier Primary = 0x01, /* internal flag */
2047dd7cddfSDavid du Colombier
2057dd7cddfSDavid du Colombier TypeBB = 0xFF,
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier TypeEMPTY = 0x00,
2087dd7cddfSDavid du Colombier TypeFAT12 = 0x01,
2097dd7cddfSDavid du Colombier TypeXENIX = 0x02, /* root */
2107dd7cddfSDavid du Colombier TypeXENIXUSR = 0x03, /* usr */
2117dd7cddfSDavid du Colombier TypeFAT16 = 0x04,
2127dd7cddfSDavid du Colombier TypeEXTENDED = 0x05,
2137dd7cddfSDavid du Colombier TypeFATHUGE = 0x06,
2147dd7cddfSDavid du Colombier TypeHPFS = 0x07,
2157dd7cddfSDavid du Colombier TypeAIXBOOT = 0x08,
2167dd7cddfSDavid du Colombier TypeAIXDATA = 0x09,
2177dd7cddfSDavid du Colombier TypeOS2BOOT = 0x0A, /* OS/2 Boot Manager */
2187dd7cddfSDavid du Colombier TypeFAT32 = 0x0B, /* FAT 32 */
2197dd7cddfSDavid du Colombier TypeFAT32LBA = 0x0C, /* FAT 32 needing LBA support */
2204afe124fSDavid du Colombier TypeFAT16X = 0x0E, /* FAT 16 needing LBA support */
2217dd7cddfSDavid du Colombier TypeEXTHUGE = 0x0F, /* FAT 32 extended partition */
2227dd7cddfSDavid du Colombier TypeUNFORMATTED = 0x16, /* unformatted primary partition (OS/2 FDISK)? */
2237dd7cddfSDavid du Colombier TypeHPFS2 = 0x17,
2246b6b9ac8SDavid du Colombier TypeIBMRecovery = 0x1C, /* really hidden fat */
2257dd7cddfSDavid du Colombier TypeCPM0 = 0x52,
2267dd7cddfSDavid du Colombier TypeDMDDO = 0x54, /* Disk Manager Dynamic Disk Overlay */
2277dd7cddfSDavid du Colombier TypeGB = 0x56, /* ???? */
2287dd7cddfSDavid du Colombier TypeSPEEDSTOR = 0x61,
2297dd7cddfSDavid du Colombier TypeSYSV386 = 0x63, /* also HURD? */
2307dd7cddfSDavid du Colombier TypeNETWARE = 0x64,
2317dd7cddfSDavid du Colombier TypePCIX = 0x75,
2327dd7cddfSDavid du Colombier TypeMINIX13 = 0x80, /* Minix v1.3 and below */
2337dd7cddfSDavid du Colombier TypeMINIX = 0x81, /* Minix v1.5+ */
2347dd7cddfSDavid du Colombier TypeLINUXSWAP = 0x82,
2357dd7cddfSDavid du Colombier TypeLINUX = 0x83,
2369a747e4fSDavid du Colombier TypeLINUXEXT = 0x85,
237c39c2eb3SDavid du Colombier TypeLINUXLVM = 0x8E, /* logical volume manager */
2387dd7cddfSDavid du Colombier TypeAMOEBA = 0x93,
2397dd7cddfSDavid du Colombier TypeAMOEBABB = 0x94,
2407dd7cddfSDavid du Colombier TypeBSD386 = 0xA5,
241*9e732705SDavid du Colombier TypeNETBSD = 0xA9,
2427dd7cddfSDavid du Colombier TypeBSDI = 0xB7,
2437dd7cddfSDavid du Colombier TypeBSDISWAP = 0xB8,
24480ee5cbfSDavid du Colombier TypeOTHER = 0xDA,
2457dd7cddfSDavid du Colombier TypeCPM = 0xDB,
24665fa3f8bSDavid du Colombier TypeDellRecovery= 0xDE,
2477dd7cddfSDavid du Colombier TypeSPEEDSTOR12 = 0xE1,
2487dd7cddfSDavid du Colombier TypeSPEEDSTOR16 = 0xE4,
249*9e732705SDavid du Colombier TypeEFIProtect = 0xEE,
250*9e732705SDavid du Colombier TypeEFI = 0xEF,
2517dd7cddfSDavid du Colombier TypeLANSTEP = 0xFE,
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier Type9 = 0x39,
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier Toffset = 446, /* offset of partition table in sector */
2567dd7cddfSDavid du Colombier Magic0 = 0x55,
2577dd7cddfSDavid du Colombier Magic1 = 0xAA,
2587dd7cddfSDavid du Colombier
259*9e732705SDavid du Colombier Tablesz = offsetof(Table, size[0]),
2607dd7cddfSDavid du Colombier };
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier struct Type {
2637dd7cddfSDavid du Colombier char *desc;
2647dd7cddfSDavid du Colombier char *name;
2657dd7cddfSDavid du Colombier };
2667dd7cddfSDavid du Colombier
26780ee5cbfSDavid du Colombier struct Dospart {
26880ee5cbfSDavid du Colombier Part;
2697dd7cddfSDavid du Colombier Tentry;
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier u32int lba;
2727dd7cddfSDavid du Colombier u32int size;
27380ee5cbfSDavid du Colombier int primary;
2747dd7cddfSDavid du Colombier };
2757dd7cddfSDavid du Colombier
27680ee5cbfSDavid du Colombier struct Recover {
27780ee5cbfSDavid du Colombier Table table;
27880ee5cbfSDavid du Colombier ulong lba;
2797dd7cddfSDavid du Colombier };
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier static Type types[256] = {
2827dd7cddfSDavid du Colombier [TypeEMPTY] { "EMPTY", "" },
2837dd7cddfSDavid du Colombier [TypeFAT12] { "FAT12", "dos" },
2847dd7cddfSDavid du Colombier [TypeFAT16] { "FAT16", "dos" },
2857dd7cddfSDavid du Colombier [TypeFAT32] { "FAT32", "dos" },
2867dd7cddfSDavid du Colombier [TypeFAT32LBA] { "FAT32LBA", "dos" },
2874afe124fSDavid du Colombier [TypeFAT16X] { "FAT16X", "dos" },
2887dd7cddfSDavid du Colombier [TypeEXTHUGE] { "EXTHUGE", "" },
2896b6b9ac8SDavid du Colombier [TypeIBMRecovery] { "IBMRECOVERY", "ibm" },
2907dd7cddfSDavid du Colombier [TypeEXTENDED] { "EXTENDED", "" },
2917dd7cddfSDavid du Colombier [TypeFATHUGE] { "FATHUGE", "dos" },
2927dd7cddfSDavid du Colombier [TypeBB] { "BB", "bb" },
2937dd7cddfSDavid du Colombier
2947dd7cddfSDavid du Colombier [TypeXENIX] { "XENIX", "xenix" },
2957dd7cddfSDavid du Colombier [TypeXENIXUSR] { "XENIX USR", "xenixusr" },
2967dd7cddfSDavid du Colombier [TypeHPFS] { "HPFS", "ntfs" },
2977dd7cddfSDavid du Colombier [TypeAIXBOOT] { "AIXBOOT", "aixboot" },
2987dd7cddfSDavid du Colombier [TypeAIXDATA] { "AIXDATA", "aixdata" },
2997dd7cddfSDavid du Colombier [TypeOS2BOOT] { "OS/2BOOT", "os2boot" },
3007dd7cddfSDavid du Colombier [TypeUNFORMATTED] { "UNFORMATTED", "" },
3017dd7cddfSDavid du Colombier [TypeHPFS2] { "HPFS2", "hpfs2" },
3027dd7cddfSDavid du Colombier [TypeCPM0] { "CPM0", "cpm0" },
3037dd7cddfSDavid du Colombier [TypeDMDDO] { "DMDDO", "dmdd0" },
3047dd7cddfSDavid du Colombier [TypeGB] { "GB", "gb" },
3057dd7cddfSDavid du Colombier [TypeSPEEDSTOR] { "SPEEDSTOR", "speedstor" },
3067dd7cddfSDavid du Colombier [TypeSYSV386] { "SYSV386", "sysv386" },
3077dd7cddfSDavid du Colombier [TypeNETWARE] { "NETWARE", "netware" },
3087dd7cddfSDavid du Colombier [TypePCIX] { "PCIX", "pcix" },
3097dd7cddfSDavid du Colombier [TypeMINIX13] { "MINIXV1.3", "minix13" },
3107dd7cddfSDavid du Colombier [TypeMINIX] { "MINIXV1.5", "minix15" },
3117dd7cddfSDavid du Colombier [TypeLINUXSWAP] { "LINUXSWAP", "linuxswap" },
3127dd7cddfSDavid du Colombier [TypeLINUX] { "LINUX", "linux" },
3139a747e4fSDavid du Colombier [TypeLINUXEXT] { "LINUXEXTENDED", "" },
314c39c2eb3SDavid du Colombier [TypeLINUXLVM] { "LINUXLVM", "linuxlvm" },
3157dd7cddfSDavid du Colombier [TypeAMOEBA] { "AMOEBA", "amoeba" },
3167dd7cddfSDavid du Colombier [TypeAMOEBABB] { "AMOEBABB", "amoebaboot" },
3177dd7cddfSDavid du Colombier [TypeBSD386] { "BSD386", "bsd386" },
3184af5a9a1SDavid du Colombier [TypeNETBSD] { "NETBSD", "netbsd" },
3197dd7cddfSDavid du Colombier [TypeBSDI] { "BSDI", "bsdi" },
3207dd7cddfSDavid du Colombier [TypeBSDISWAP] { "BSDISWAP", "bsdiswap" },
32180ee5cbfSDavid du Colombier [TypeOTHER] { "OTHER", "other" },
3227dd7cddfSDavid du Colombier [TypeCPM] { "CPM", "cpm" },
32365fa3f8bSDavid du Colombier [TypeDellRecovery] { "DELLRECOVERY", "dell" },
3247dd7cddfSDavid du Colombier [TypeSPEEDSTOR12] { "SPEEDSTOR12", "speedstor" },
3257dd7cddfSDavid du Colombier [TypeSPEEDSTOR16] { "SPEEDSTOR16", "speedstor" },
326*9e732705SDavid du Colombier [TypeEFIProtect] { "EFIPROTECT", "efiprotect" },
327*9e732705SDavid du Colombier [TypeEFI] { "EFI", "efi" },
3287dd7cddfSDavid du Colombier [TypeLANSTEP] { "LANSTEP", "lanstep" },
3297dd7cddfSDavid du Colombier
3307dd7cddfSDavid du Colombier [Type9] { "PLAN9", "plan9" },
3317dd7cddfSDavid du Colombier };
3327dd7cddfSDavid du Colombier
33380ee5cbfSDavid du Colombier static Dospart part[Mpart];
33480ee5cbfSDavid du Colombier static int npart;
33580ee5cbfSDavid du Colombier
3367dd7cddfSDavid du Colombier static char*
typestr0(int type)33780ee5cbfSDavid du Colombier typestr0(int type)
3387dd7cddfSDavid du Colombier {
3397dd7cddfSDavid du Colombier static char buf[100];
3407dd7cddfSDavid du Colombier
3417dd7cddfSDavid du Colombier sprint(buf, "type %d", type);
3427dd7cddfSDavid du Colombier if(type < 0 || type >= 256)
3437dd7cddfSDavid du Colombier return buf;
3447dd7cddfSDavid du Colombier if(types[type].desc == nil)
3457dd7cddfSDavid du Colombier return buf;
3467dd7cddfSDavid du Colombier return types[type].desc;
3477dd7cddfSDavid du Colombier }
3487dd7cddfSDavid du Colombier
3497dd7cddfSDavid du Colombier static u32int
getle32(void * v)3507dd7cddfSDavid du Colombier getle32(void* v)
3517dd7cddfSDavid du Colombier {
3527dd7cddfSDavid du Colombier uchar *p;
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier p = v;
3557dd7cddfSDavid du Colombier return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0];
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
3587dd7cddfSDavid du Colombier static void
putle32(void * v,u32int i)3597dd7cddfSDavid du Colombier putle32(void* v, u32int i)
3607dd7cddfSDavid du Colombier {
3617dd7cddfSDavid du Colombier uchar *p;
3627dd7cddfSDavid du Colombier
3637dd7cddfSDavid du Colombier p = v;
3647dd7cddfSDavid du Colombier p[0] = i;
3657dd7cddfSDavid du Colombier p[1] = i>>8;
3667dd7cddfSDavid du Colombier p[2] = i>>16;
3677dd7cddfSDavid du Colombier p[3] = i>>24;
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier
37080ee5cbfSDavid du Colombier static void
diskread(Disk * disk,void * data,int ndata,u32int sec,u32int off)37180ee5cbfSDavid du Colombier diskread(Disk *disk, void *data, int ndata, u32int sec, u32int off)
3727dd7cddfSDavid du Colombier {
3739a747e4fSDavid du Colombier if(seek(disk->fd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)
37480ee5cbfSDavid du Colombier sysfatal("diskread seek %lud.%lud: %r", (ulong)sec, (ulong)off);
37580ee5cbfSDavid du Colombier if(readn(disk->fd, data, ndata) != ndata)
37680ee5cbfSDavid du Colombier sysfatal("diskread %lud at %lud.%lud: %r", (ulong)ndata, (ulong)sec, (ulong)off);
37780ee5cbfSDavid du Colombier }
3787dd7cddfSDavid du Colombier
37980ee5cbfSDavid du Colombier static int
diskwrite(Disk * disk,void * data,int ndata,u32int sec,u32int off)38080ee5cbfSDavid du Colombier diskwrite(Disk *disk, void *data, int ndata, u32int sec, u32int off)
38180ee5cbfSDavid du Colombier {
38280ee5cbfSDavid du Colombier written = 1;
3839a747e4fSDavid du Colombier if(seek(disk->wfd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)
38480ee5cbfSDavid du Colombier goto Error;
38580ee5cbfSDavid du Colombier if(write(disk->wfd, data, ndata) != ndata)
38680ee5cbfSDavid du Colombier goto Error;
38780ee5cbfSDavid du Colombier return 0;
3887dd7cddfSDavid du Colombier
38980ee5cbfSDavid du Colombier Error:
39080ee5cbfSDavid du Colombier fprint(2, "write %d bytes at %lud.%lud failed: %r\n", ndata, (ulong)sec, (ulong)off);
39180ee5cbfSDavid du Colombier return -1;
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier static Dospart*
mkpart(char * name,int primary,vlong lba,vlong size,Tentry * t)395eba00c11SDavid du Colombier mkpart(char *name, int primary, vlong lba, vlong size, Tentry *t)
3967dd7cddfSDavid du Colombier {
39780ee5cbfSDavid du Colombier static int n;
3987dd7cddfSDavid du Colombier Dospart *p;
3997dd7cddfSDavid du Colombier
40080ee5cbfSDavid du Colombier p = emalloc(sizeof(*p));
40180ee5cbfSDavid du Colombier if(name)
4029a747e4fSDavid du Colombier p->name = estrdup(name);
4039a747e4fSDavid du Colombier else{
4049a747e4fSDavid du Colombier p->name = emalloc(20);
40580ee5cbfSDavid du Colombier sprint(p->name, "%c%d", primary ? 'p' : 's', ++n);
4069a747e4fSDavid du Colombier }
40780ee5cbfSDavid du Colombier
40880ee5cbfSDavid du Colombier if(t)
40980ee5cbfSDavid du Colombier p->Tentry = *t;
41080ee5cbfSDavid du Colombier else
41180ee5cbfSDavid du Colombier memset(&p->Tentry, 0, sizeof(Tentry));
41280ee5cbfSDavid du Colombier
4137dd7cddfSDavid du Colombier p->changed = 0;
41480ee5cbfSDavid du Colombier p->start = lba/sec2cyl;
41580ee5cbfSDavid du Colombier p->end = (lba+size)/sec2cyl;
41680ee5cbfSDavid du Colombier p->ctlstart = lba;
41780ee5cbfSDavid du Colombier p->ctlend = lba+size;
41880ee5cbfSDavid du Colombier p->lba = lba;
419eba00c11SDavid du Colombier if (p->lba != lba)
420eba00c11SDavid du Colombier fprint(2, "%s: start of partition (%lld) won't fit in MBR table\n", argv0, lba);
42180ee5cbfSDavid du Colombier p->size = size;
422eba00c11SDavid du Colombier if (p->size != size)
423eba00c11SDavid du Colombier fprint(2, "%s: size of partition (%lld) won't fit in MBR table\n", argv0, size);
42480ee5cbfSDavid du Colombier p->primary = primary;
4257dd7cddfSDavid du Colombier return p;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier
42880ee5cbfSDavid du Colombier /*
42980ee5cbfSDavid du Colombier * Recovery takes care of remembering what the various tables
43080ee5cbfSDavid du Colombier * looked like when we started, attempting to restore them when
43180ee5cbfSDavid du Colombier * we are finished.
43280ee5cbfSDavid du Colombier */
43380ee5cbfSDavid du Colombier static Recover *rtab;
43480ee5cbfSDavid du Colombier static int nrtab;
4357dd7cddfSDavid du Colombier
43680ee5cbfSDavid du Colombier static void
addrecover(Table t,ulong lba)43780ee5cbfSDavid du Colombier addrecover(Table t, ulong lba)
43880ee5cbfSDavid du Colombier {
43980ee5cbfSDavid du Colombier if((nrtab%8) == 0) {
44080ee5cbfSDavid du Colombier rtab = realloc(rtab, (nrtab+8)*sizeof(rtab[0]));
44180ee5cbfSDavid du Colombier if(rtab == nil)
44280ee5cbfSDavid du Colombier sysfatal("out of memory");
4437dd7cddfSDavid du Colombier }
44480ee5cbfSDavid du Colombier rtab[nrtab] = (Recover){t, lba};
44580ee5cbfSDavid du Colombier nrtab++;
44680ee5cbfSDavid du Colombier }
44780ee5cbfSDavid du Colombier
44880ee5cbfSDavid du Colombier static void
recover(Edit * edit)44980ee5cbfSDavid du Colombier recover(Edit *edit)
45080ee5cbfSDavid du Colombier {
45180ee5cbfSDavid du Colombier int err, i, ctlfd;
45280ee5cbfSDavid du Colombier vlong offset;
45380ee5cbfSDavid du Colombier
45480ee5cbfSDavid du Colombier err = 0;
45580ee5cbfSDavid du Colombier for(i=0; i<nrtab; i++)
456*9e732705SDavid du Colombier if(diskwrite(edit->disk, &rtab[i].table, Tablesz, rtab[i].lba, Toffset) < 0)
45780ee5cbfSDavid du Colombier err = 1;
45880ee5cbfSDavid du Colombier if(err) {
45980ee5cbfSDavid du Colombier fprint(2, "warning: some writes failed during restoration of old partition tables\n");
46080ee5cbfSDavid du Colombier exits("inconsistent");
46180ee5cbfSDavid du Colombier } else {
46280ee5cbfSDavid du Colombier fprint(2, "restored old partition tables\n");
46380ee5cbfSDavid du Colombier }
46480ee5cbfSDavid du Colombier
46580ee5cbfSDavid du Colombier ctlfd = edit->disk->ctlfd;
46680ee5cbfSDavid du Colombier offset = edit->disk->offset;
46780ee5cbfSDavid du Colombier if(ctlfd >= 0){
46880ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++)
4696b6b9ac8SDavid du Colombier if(edit->part[i]->ctlname && fprint(ctlfd, "delpart %s", edit->part[i]->ctlname)<0)
47080ee5cbfSDavid du Colombier fprint(2, "delpart failed: %s: %r", edit->part[i]->ctlname);
47180ee5cbfSDavid du Colombier for(i=0; i<edit->nctlpart; i++)
4726b6b9ac8SDavid du Colombier if(edit->part[i]->name && fprint(ctlfd, "delpart %s", edit->ctlpart[i]->name)<0)
47380ee5cbfSDavid du Colombier fprint(2, "delpart failed: %s: %r", edit->ctlpart[i]->name);
47480ee5cbfSDavid du Colombier for(i=0; i<edit->nctlpart; i++){
47580ee5cbfSDavid du Colombier if(fprint(ctlfd, "part %s %lld %lld", edit->ctlpart[i]->name,
47680ee5cbfSDavid du Colombier edit->ctlpart[i]->start+offset, edit->ctlpart[i]->end+offset) < 0){
47780ee5cbfSDavid du Colombier fprint(2, "restored disk partition table but not kernel; reboot\n");
47880ee5cbfSDavid du Colombier exits("inconsistent");
47980ee5cbfSDavid du Colombier }
48080ee5cbfSDavid du Colombier }
48180ee5cbfSDavid du Colombier }
48280ee5cbfSDavid du Colombier exits("restored");
48380ee5cbfSDavid du Colombier
48480ee5cbfSDavid du Colombier }
48580ee5cbfSDavid du Colombier
48680ee5cbfSDavid du Colombier /*
48780ee5cbfSDavid du Colombier * Read the partition table (including extended partition tables)
48880ee5cbfSDavid du Colombier * from the disk into the part array.
48980ee5cbfSDavid du Colombier */
49080ee5cbfSDavid du Colombier static void
rdpart(Edit * edit,uvlong lba,uvlong xbase)491eba00c11SDavid du Colombier rdpart(Edit *edit, uvlong lba, uvlong xbase)
49280ee5cbfSDavid du Colombier {
49380ee5cbfSDavid du Colombier char *err;
49480ee5cbfSDavid du Colombier Table table;
49580ee5cbfSDavid du Colombier Tentry *tp, *ep;
49680ee5cbfSDavid du Colombier Dospart *p;
49780ee5cbfSDavid du Colombier
4989a747e4fSDavid du Colombier if(xbase == 0)
4999a747e4fSDavid du Colombier xbase = lba;
5009a747e4fSDavid du Colombier
501*9e732705SDavid du Colombier diskread(edit->disk, &table, Tablesz, mbroffset+lba, Toffset);
50280ee5cbfSDavid du Colombier addrecover(table, mbroffset+lba);
5037dd7cddfSDavid du Colombier
5047dd7cddfSDavid du Colombier if(table.magic[0] != Magic0 || table.magic[1] != Magic1) {
50580ee5cbfSDavid du Colombier assert(lba != 0);
5067dd7cddfSDavid du Colombier return;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier
50980ee5cbfSDavid du Colombier for(tp=table.entry, ep=tp+NTentry; tp<ep && npart < Mpart; tp++) {
51080ee5cbfSDavid du Colombier switch(tp->type) {
5117dd7cddfSDavid du Colombier case TypeEMPTY:
5127dd7cddfSDavid du Colombier break;
5137dd7cddfSDavid du Colombier case TypeEXTENDED:
5147dd7cddfSDavid du Colombier case TypeEXTHUGE:
5159a747e4fSDavid du Colombier case TypeLINUXEXT:
5169a747e4fSDavid du Colombier rdpart(edit, xbase+getle32(tp->xlba), xbase);
5177dd7cddfSDavid du Colombier break;
5187dd7cddfSDavid du Colombier default:
51980ee5cbfSDavid du Colombier p = mkpart(nil, lba==0, lba+getle32(tp->xlba), getle32(tp->xsize), tp);
5207dd7cddfSDavid du Colombier if(err = addpart(edit, p))
52180ee5cbfSDavid du Colombier fprint(2, "adding partition: %s\n", err);
52280ee5cbfSDavid du Colombier break;
52380ee5cbfSDavid du Colombier }
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier }
5267dd7cddfSDavid du Colombier
5277dd7cddfSDavid du Colombier static void
blankpart(Edit * edit)5287dd7cddfSDavid du Colombier blankpart(Edit *edit)
5297dd7cddfSDavid du Colombier {
5307dd7cddfSDavid du Colombier edit->changed = 1;
5317dd7cddfSDavid du Colombier }
5327dd7cddfSDavid du Colombier
5337dd7cddfSDavid du Colombier static void
findmbr(Edit * edit)5347dd7cddfSDavid du Colombier findmbr(Edit *edit)
5357dd7cddfSDavid du Colombier {
5367dd7cddfSDavid du Colombier Table table;
5377dd7cddfSDavid du Colombier Tentry *tp;
5387dd7cddfSDavid du Colombier
539*9e732705SDavid du Colombier diskread(edit->disk, &table, Tablesz, 0, Toffset);
5407dd7cddfSDavid du Colombier if(table.magic[0] != Magic0 || table.magic[1] != Magic1)
5417dd7cddfSDavid du Colombier sysfatal("did not find master boot record");
5427dd7cddfSDavid du Colombier
5437dd7cddfSDavid du Colombier for(tp = table.entry; tp < &table.entry[NTentry]; tp++)
5447dd7cddfSDavid du Colombier if(tp->type == TypeDMDDO)
54580ee5cbfSDavid du Colombier mbroffset = edit->disk->s;
5467dd7cddfSDavid du Colombier }
5477dd7cddfSDavid du Colombier
54880ee5cbfSDavid du Colombier static int
haveroom(Edit * edit,int primary,vlong start)54980ee5cbfSDavid du Colombier haveroom(Edit *edit, int primary, vlong start)
5507dd7cddfSDavid du Colombier {
5519a747e4fSDavid du Colombier int i, lastsec, n;
5529a747e4fSDavid du Colombier Dospart *p, *q;
5539a747e4fSDavid du Colombier ulong pend, qstart;
55480ee5cbfSDavid du Colombier
55580ee5cbfSDavid du Colombier if(primary) {
55680ee5cbfSDavid du Colombier /*
55780ee5cbfSDavid du Colombier * must be open primary slot.
55880ee5cbfSDavid du Colombier * primary slots are taken by primary partitions
55980ee5cbfSDavid du Colombier * and runs of secondary partitions.
56080ee5cbfSDavid du Colombier */
56180ee5cbfSDavid du Colombier n = 0;
56280ee5cbfSDavid du Colombier lastsec = 0;
56380ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) {
56480ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i];
56580ee5cbfSDavid du Colombier if(p->primary)
56680ee5cbfSDavid du Colombier n++, lastsec=0;
5679a747e4fSDavid du Colombier else if(!lastsec)
56880ee5cbfSDavid du Colombier n++, lastsec=1;
5697dd7cddfSDavid du Colombier }
57080ee5cbfSDavid du Colombier return n<4;
5717dd7cddfSDavid du Colombier }
5727dd7cddfSDavid du Colombier
57380ee5cbfSDavid du Colombier /*
57480ee5cbfSDavid du Colombier * secondary partitions can be inserted between two primary
57580ee5cbfSDavid du Colombier * partitions only if there is an empty primary slot.
57680ee5cbfSDavid du Colombier * otherwise, we can put a new secondary partition next
57780ee5cbfSDavid du Colombier * to a secondary partition no problem.
57880ee5cbfSDavid du Colombier */
57980ee5cbfSDavid du Colombier n = 0;
5806b6b9ac8SDavid du Colombier for(i=0; i<edit->npart; i++){
58180ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i];
58280ee5cbfSDavid du Colombier if(p->primary)
5839a747e4fSDavid du Colombier n++;
5849a747e4fSDavid du Colombier pend = p->end;
5859a747e4fSDavid du Colombier if(i+1<edit->npart){
5869a747e4fSDavid du Colombier q = (Dospart*)edit->part[i+1];
5879a747e4fSDavid du Colombier qstart = q->start;
5889a747e4fSDavid du Colombier }else{
5899a747e4fSDavid du Colombier qstart = edit->end;
5909a747e4fSDavid du Colombier q = nil;
5917dd7cddfSDavid du Colombier }
5929a747e4fSDavid du Colombier if(start < pend || start >= qstart)
5939a747e4fSDavid du Colombier continue;
5949a747e4fSDavid du Colombier /* we go between these two */
5959a747e4fSDavid du Colombier if(p->primary==0 || (q && q->primary==0))
5969a747e4fSDavid du Colombier return 1;
5977dd7cddfSDavid du Colombier }
59880ee5cbfSDavid du Colombier /* not next to a secondary, need a new primary */
59980ee5cbfSDavid du Colombier return n<4;
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier
6027dd7cddfSDavid du Colombier static void
autopart(Edit * edit)6037dd7cddfSDavid du Colombier autopart(Edit *edit)
6047dd7cddfSDavid du Colombier {
60580ee5cbfSDavid du Colombier char *err;
60680ee5cbfSDavid du Colombier int active, i;
60780ee5cbfSDavid du Colombier vlong bigstart, bigsize, start;
60880ee5cbfSDavid du Colombier Dospart *p;
6097dd7cddfSDavid du Colombier
61080ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++)
61180ee5cbfSDavid du Colombier if(((Dospart*)edit->part[i])->type == Type9)
6127dd7cddfSDavid du Colombier return;
6137dd7cddfSDavid du Colombier
61480ee5cbfSDavid du Colombier /* look for the biggest gap in which we can put a primary partition */
61580ee5cbfSDavid du Colombier start = 0;
6167dd7cddfSDavid du Colombier bigsize = 0;
6177dd7cddfSDavid du Colombier SET(bigstart);
6187dd7cddfSDavid du Colombier for(i=0; i<edit->npart; i++) {
61980ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i];
62080ee5cbfSDavid du Colombier if(p->start > start && p->start - start > bigsize && haveroom(edit, 1, start)) {
6217dd7cddfSDavid du Colombier bigsize = p->start - start;
6227dd7cddfSDavid du Colombier bigstart = start;
6237dd7cddfSDavid du Colombier }
6247dd7cddfSDavid du Colombier start = p->end;
6257dd7cddfSDavid du Colombier }
6267dd7cddfSDavid du Colombier
62780ee5cbfSDavid du Colombier if(edit->end - start > bigsize && haveroom(edit, 1, start)) {
62880ee5cbfSDavid du Colombier bigsize = edit->end - start;
6297dd7cddfSDavid du Colombier bigstart = start;
6307dd7cddfSDavid du Colombier }
63180ee5cbfSDavid du Colombier if(bigsize < 1) {
63280ee5cbfSDavid du Colombier fprint(2, "couldn't find space or partition slot for plan 9 partition\n");
6337dd7cddfSDavid du Colombier return;
6347dd7cddfSDavid du Colombier }
6357dd7cddfSDavid du Colombier
63680ee5cbfSDavid du Colombier /* set new partition active only if no others are */
6377dd7cddfSDavid du Colombier active = Active;
63880ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++)
63980ee5cbfSDavid du Colombier if(((Dospart*)edit->part[i])->primary && (((Dospart*)edit->part[i])->active & Active))
6407dd7cddfSDavid du Colombier active = 0;
6417dd7cddfSDavid du Colombier
64280ee5cbfSDavid du Colombier /* add new plan 9 partition */
64380ee5cbfSDavid du Colombier bigsize *= sec2cyl;
64480ee5cbfSDavid du Colombier bigstart *= sec2cyl;
64580ee5cbfSDavid du Colombier if(bigstart == 0) {
64680ee5cbfSDavid du Colombier bigstart += edit->disk->s;
64780ee5cbfSDavid du Colombier bigsize -= edit->disk->s;
6487dd7cddfSDavid du Colombier }
64980ee5cbfSDavid du Colombier p = mkpart(nil, 1, bigstart, bigsize, nil);
65080ee5cbfSDavid du Colombier p->active = active;
65180ee5cbfSDavid du Colombier p->changed = 1;
65280ee5cbfSDavid du Colombier p->type = Type9;
65380ee5cbfSDavid du Colombier edit->changed = 1;
65480ee5cbfSDavid du Colombier if(err = addpart(edit, p)) {
65580ee5cbfSDavid du Colombier fprint(2, "error adding plan9 partition: %s\n", err);
6567dd7cddfSDavid du Colombier return;
6577dd7cddfSDavid du Colombier }
6587dd7cddfSDavid du Colombier }
6597dd7cddfSDavid du Colombier
6607dd7cddfSDavid du Colombier typedef struct Name Name;
6617dd7cddfSDavid du Colombier struct Name {
6629a747e4fSDavid du Colombier char *name;
6637dd7cddfSDavid du Colombier Name *link;
6647dd7cddfSDavid du Colombier };
6657dd7cddfSDavid du Colombier Name *namelist;
6667dd7cddfSDavid du Colombier static void
plan9print(Dospart * part,int fd)66780ee5cbfSDavid du Colombier plan9print(Dospart *part, int fd)
6687dd7cddfSDavid du Colombier {
6697dd7cddfSDavid du Colombier int i, ok;
6709a747e4fSDavid du Colombier char *name, *vname;
6717dd7cddfSDavid du Colombier Name *n;
67280ee5cbfSDavid du Colombier vlong start, end;
67380ee5cbfSDavid du Colombier char *sep;
67480ee5cbfSDavid du Colombier
67580ee5cbfSDavid du Colombier vname = types[part->type].name;
6769a747e4fSDavid du Colombier if(vname==nil || strcmp(vname, "")==0) {
6779a747e4fSDavid du Colombier part->ctlname = "";
67880ee5cbfSDavid du Colombier return;
67980ee5cbfSDavid du Colombier }
68080ee5cbfSDavid du Colombier
68180ee5cbfSDavid du Colombier start = mbroffset+part->lba;
68280ee5cbfSDavid du Colombier end = start+part->size;
68380ee5cbfSDavid du Colombier
68480ee5cbfSDavid du Colombier /* avoid names like plan90 */
68580ee5cbfSDavid du Colombier i = strlen(vname) - 1;
68680ee5cbfSDavid du Colombier if(vname[i] >= '0' && vname[i] <= '9')
68780ee5cbfSDavid du Colombier sep = ".";
68880ee5cbfSDavid du Colombier else
68980ee5cbfSDavid du Colombier sep = "";
6907dd7cddfSDavid du Colombier
6917dd7cddfSDavid du Colombier i = 0;
6929a747e4fSDavid du Colombier name = emalloc(strlen(vname)+10);
6939a747e4fSDavid du Colombier
69480ee5cbfSDavid du Colombier sprint(name, "%s", vname);
6957dd7cddfSDavid du Colombier do {
6967dd7cddfSDavid du Colombier ok = 1;
6977dd7cddfSDavid du Colombier for(n=namelist; n; n=n->link) {
6987dd7cddfSDavid du Colombier if(strcmp(name, n->name) == 0) {
6997dd7cddfSDavid du Colombier i++;
70080ee5cbfSDavid du Colombier sprint(name, "%s%s%d", vname, sep, i);
7017dd7cddfSDavid du Colombier ok = 0;
7027dd7cddfSDavid du Colombier }
7037dd7cddfSDavid du Colombier }
7047dd7cddfSDavid du Colombier } while(ok == 0);
7057dd7cddfSDavid du Colombier
7069a747e4fSDavid du Colombier n = emalloc(sizeof(*n));
7079a747e4fSDavid du Colombier n->name = name;
7087dd7cddfSDavid du Colombier n->link = namelist;
7097dd7cddfSDavid du Colombier namelist = n;
7109a747e4fSDavid du Colombier part->ctlname = name;
7117dd7cddfSDavid du Colombier
7127dd7cddfSDavid du Colombier if(fd >= 0)
7137dd7cddfSDavid du Colombier print("part %s %lld %lld\n", name, start, end);
7147dd7cddfSDavid du Colombier }
7157dd7cddfSDavid du Colombier
7167dd7cddfSDavid du Colombier static void
freenamelist(void)7177dd7cddfSDavid du Colombier freenamelist(void)
7187dd7cddfSDavid du Colombier {
7197dd7cddfSDavid du Colombier Name *n, *next;
7207dd7cddfSDavid du Colombier
7217dd7cddfSDavid du Colombier for(n=namelist; n; n=next) {
7227dd7cddfSDavid du Colombier next = n->link;
7237dd7cddfSDavid du Colombier free(n);
7247dd7cddfSDavid du Colombier }
7257dd7cddfSDavid du Colombier namelist = nil;
7267dd7cddfSDavid du Colombier }
7277dd7cddfSDavid du Colombier
7287dd7cddfSDavid du Colombier static void
cmdprintctl(Edit * edit,int ctlfd)7297dd7cddfSDavid du Colombier cmdprintctl(Edit *edit, int ctlfd)
7307dd7cddfSDavid du Colombier {
7317dd7cddfSDavid du Colombier int i;
7327dd7cddfSDavid du Colombier
7337dd7cddfSDavid du Colombier freenamelist();
7347dd7cddfSDavid du Colombier for(i=0; i<edit->npart; i++)
73580ee5cbfSDavid du Colombier plan9print((Dospart*)edit->part[i], -1);
7367dd7cddfSDavid du Colombier ctldiff(edit, ctlfd);
7377dd7cddfSDavid du Colombier }
7387dd7cddfSDavid du Colombier
7397dd7cddfSDavid du Colombier static char*
cmdokname(Edit *,char * name)7407dd7cddfSDavid du Colombier cmdokname(Edit*, char *name)
7417dd7cddfSDavid du Colombier {
74280ee5cbfSDavid du Colombier char *q;
74380ee5cbfSDavid du Colombier
74480ee5cbfSDavid du Colombier if(name[0] != 'p' && name[0] != 's')
74580ee5cbfSDavid du Colombier return "name must be pN or sN";
74680ee5cbfSDavid du Colombier
74780ee5cbfSDavid du Colombier strtol(name+1, &q, 10);
74880ee5cbfSDavid du Colombier if(*q != '\0')
74980ee5cbfSDavid du Colombier return "name must be pN or sN";
75080ee5cbfSDavid du Colombier
7517dd7cddfSDavid du Colombier return nil;
7527dd7cddfSDavid du Colombier }
7537dd7cddfSDavid du Colombier
754eba00c11SDavid du Colombier #define TB (1024LL*GB)
7557dd7cddfSDavid du Colombier #define GB (1024*1024*1024)
7567dd7cddfSDavid du Colombier #define MB (1024*1024)
7577dd7cddfSDavid du Colombier #define KB (1024)
7587dd7cddfSDavid du Colombier
7597dd7cddfSDavid du Colombier static void
cmdsum(Edit * edit,Part * vp,vlong a,vlong b)7607dd7cddfSDavid du Colombier cmdsum(Edit *edit, Part *vp, vlong a, vlong b)
7617dd7cddfSDavid du Colombier {
7627dd7cddfSDavid du Colombier char *name, *ty;
7637dd7cddfSDavid du Colombier char buf[3];
76480ee5cbfSDavid du Colombier char *suf;
7657dd7cddfSDavid du Colombier Dospart *p;
76680ee5cbfSDavid du Colombier vlong sz, div;
7677dd7cddfSDavid du Colombier
7687dd7cddfSDavid du Colombier p = (Dospart*)vp;
7697dd7cddfSDavid du Colombier
7707dd7cddfSDavid du Colombier buf[0] = p && p->changed ? '\'' : ' ';
7717dd7cddfSDavid du Colombier buf[1] = p && (p->active & Active) ? '*' : ' ';
7727dd7cddfSDavid du Colombier buf[2] = '\0';
7737dd7cddfSDavid du Colombier
7747dd7cddfSDavid du Colombier name = p ? p->name : "empty";
77580ee5cbfSDavid du Colombier ty = p ? typestr0(p->type) : "";
7767dd7cddfSDavid du Colombier
77780ee5cbfSDavid du Colombier sz = (b-a)*edit->disk->secsize*sec2cyl;
778eba00c11SDavid du Colombier if(sz >= 1*TB){
779eba00c11SDavid du Colombier suf = "TB";
780eba00c11SDavid du Colombier div = TB;
781eba00c11SDavid du Colombier }else if(sz >= 1*GB){
78280ee5cbfSDavid du Colombier suf = "GB";
78380ee5cbfSDavid du Colombier div = GB;
78480ee5cbfSDavid du Colombier }else if(sz >= 1*MB){
78580ee5cbfSDavid du Colombier suf = "MB";
78680ee5cbfSDavid du Colombier div = MB;
78780ee5cbfSDavid du Colombier }else if(sz >= 1*KB){
78880ee5cbfSDavid du Colombier suf = "KB";
78980ee5cbfSDavid du Colombier div = KB;
79080ee5cbfSDavid du Colombier }else{
79180ee5cbfSDavid du Colombier suf = "B ";
79280ee5cbfSDavid du Colombier div = 1;
79380ee5cbfSDavid du Colombier }
79480ee5cbfSDavid du Colombier
79580ee5cbfSDavid du Colombier if(div == 1)
79680ee5cbfSDavid du Colombier print("%s %-12s %*lld %-*lld (%lld cylinders, %lld %s) %s\n", buf, name,
79780ee5cbfSDavid du Colombier edit->disk->width, a, edit->disk->width, b, b-a, sz, suf, ty);
79880ee5cbfSDavid du Colombier else
79980ee5cbfSDavid du Colombier print("%s %-12s %*lld %-*lld (%lld cylinders, %lld.%.2d %s) %s\n", buf, name,
80080ee5cbfSDavid du Colombier edit->disk->width, a, edit->disk->width, b, b-a,
80180ee5cbfSDavid du Colombier sz/div, (int)(((sz%div)*100)/div), suf, ty);
8027dd7cddfSDavid du Colombier }
8037dd7cddfSDavid du Colombier
8047dd7cddfSDavid du Colombier static char*
cmdadd(Edit * edit,char * name,vlong start,vlong end)8057dd7cddfSDavid du Colombier cmdadd(Edit *edit, char *name, vlong start, vlong end)
8067dd7cddfSDavid du Colombier {
80780ee5cbfSDavid du Colombier Dospart *p;
8087dd7cddfSDavid du Colombier
80980ee5cbfSDavid du Colombier if(!haveroom(edit, name[0]=='p', start))
81080ee5cbfSDavid du Colombier return "no room for partition";
8119a747e4fSDavid du Colombier start *= sec2cyl;
8129a747e4fSDavid du Colombier end *= sec2cyl;
8136b6b9ac8SDavid du Colombier if(start == 0 || name[0] != 'p')
8146b6b9ac8SDavid du Colombier start += edit->disk->s;
8159a747e4fSDavid du Colombier p = mkpart(name, name[0]=='p', start, end-start, nil);
81680ee5cbfSDavid du Colombier p->changed = 1;
817d9dc5dd1SDavid du Colombier p->type = Type9;
81880ee5cbfSDavid du Colombier return addpart(edit, p);
8197dd7cddfSDavid du Colombier }
8207dd7cddfSDavid du Colombier
8217dd7cddfSDavid du Colombier static char*
cmddel(Edit * edit,Part * p)8227dd7cddfSDavid du Colombier cmddel(Edit *edit, Part *p)
8237dd7cddfSDavid du Colombier {
82480ee5cbfSDavid du Colombier return delpart(edit, p);
8257dd7cddfSDavid du Colombier }
8267dd7cddfSDavid du Colombier
8277dd7cddfSDavid du Colombier static char*
cmdwrite(Edit * edit)8287dd7cddfSDavid du Colombier cmdwrite(Edit *edit)
8297dd7cddfSDavid du Colombier {
8307dd7cddfSDavid du Colombier wrpart(edit);
8317dd7cddfSDavid du Colombier return nil;
8327dd7cddfSDavid du Colombier }
8337dd7cddfSDavid du Colombier
8347dd7cddfSDavid du Colombier static char *help =
8357dd7cddfSDavid du Colombier "A name - set partition active\n"
8367dd7cddfSDavid du Colombier "P - print table in ctl format\n"
8376b6b9ac8SDavid du Colombier "R - restore disk back to initial configuration and exit\n"
8387dd7cddfSDavid du Colombier "e - show empty dos partitions\n"
8397dd7cddfSDavid du Colombier "t name [type] - set partition type\n";
8407dd7cddfSDavid du Colombier
8417dd7cddfSDavid du Colombier static char*
cmdhelp(Edit *)8427dd7cddfSDavid du Colombier cmdhelp(Edit*)
8437dd7cddfSDavid du Colombier {
8447dd7cddfSDavid du Colombier print("%s\n", help);
8457dd7cddfSDavid du Colombier return nil;
8467dd7cddfSDavid du Colombier }
8477dd7cddfSDavid du Colombier
8487dd7cddfSDavid du Colombier static char*
cmdactive(Edit * edit,int nf,char ** f)8497dd7cddfSDavid du Colombier cmdactive(Edit *edit, int nf, char **f)
8507dd7cddfSDavid du Colombier {
8517dd7cddfSDavid du Colombier int i;
85280ee5cbfSDavid du Colombier Dospart *p, *ip;
8537dd7cddfSDavid du Colombier
8547dd7cddfSDavid du Colombier if(nf != 2)
8557dd7cddfSDavid du Colombier return "args";
8567dd7cddfSDavid du Colombier
8579a747e4fSDavid du Colombier if(f[1][0] != 'p')
8589a747e4fSDavid du Colombier return "cannot set secondary partition active";
8599a747e4fSDavid du Colombier
86080ee5cbfSDavid du Colombier if((p = (Dospart*)findpart(edit, f[1])) == nil)
86180ee5cbfSDavid du Colombier return "unknown partition";
8627dd7cddfSDavid du Colombier
86380ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) {
86480ee5cbfSDavid du Colombier ip = (Dospart*)edit->part[i];
86580ee5cbfSDavid du Colombier if(ip->active & Active) {
86680ee5cbfSDavid du Colombier ip->active &= ~Active;
86780ee5cbfSDavid du Colombier ip->changed = 1;
8687dd7cddfSDavid du Colombier edit->changed = 1;
8697dd7cddfSDavid du Colombier }
8707dd7cddfSDavid du Colombier }
87180ee5cbfSDavid du Colombier
8727dd7cddfSDavid du Colombier if((p->active & Active) == 0) {
8737dd7cddfSDavid du Colombier p->active |= Active;
8747dd7cddfSDavid du Colombier p->changed = 1;
8757dd7cddfSDavid du Colombier edit->changed = 1;
8767dd7cddfSDavid du Colombier }
8777dd7cddfSDavid du Colombier
8787dd7cddfSDavid du Colombier return nil;
8797dd7cddfSDavid du Colombier }
8807dd7cddfSDavid du Colombier
8817dd7cddfSDavid du Colombier static char*
strupr(char * s)8827dd7cddfSDavid du Colombier strupr(char *s)
8837dd7cddfSDavid du Colombier {
8847dd7cddfSDavid du Colombier char *p;
8857dd7cddfSDavid du Colombier
8867dd7cddfSDavid du Colombier for(p=s; *p; p++)
8877dd7cddfSDavid du Colombier *p = toupper(*p);
8887dd7cddfSDavid du Colombier return s;
8897dd7cddfSDavid du Colombier }
8907dd7cddfSDavid du Colombier
8917dd7cddfSDavid du Colombier static void
dumplist(void)8927dd7cddfSDavid du Colombier dumplist(void)
8937dd7cddfSDavid du Colombier {
8947dd7cddfSDavid du Colombier int i, n;
8957dd7cddfSDavid du Colombier
8967dd7cddfSDavid du Colombier n = 0;
8977dd7cddfSDavid du Colombier for(i=0; i<256; i++) {
8987dd7cddfSDavid du Colombier if(types[i].desc) {
8997dd7cddfSDavid du Colombier print("%-16s", types[i].desc);
9007dd7cddfSDavid du Colombier if(n++%4 == 3)
9017dd7cddfSDavid du Colombier print("\n");
9027dd7cddfSDavid du Colombier }
9037dd7cddfSDavid du Colombier }
9047dd7cddfSDavid du Colombier if(n%4)
9057dd7cddfSDavid du Colombier print("\n");
9067dd7cddfSDavid du Colombier }
9077dd7cddfSDavid du Colombier
9087dd7cddfSDavid du Colombier static char*
cmdtype(Edit * edit,int nf,char ** f)9097dd7cddfSDavid du Colombier cmdtype(Edit *edit, int nf, char **f)
9107dd7cddfSDavid du Colombier {
9117dd7cddfSDavid du Colombier char *q;
9127dd7cddfSDavid du Colombier Dospart *p;
9137dd7cddfSDavid du Colombier int i;
9147dd7cddfSDavid du Colombier
9157dd7cddfSDavid du Colombier if(nf < 2)
9167dd7cddfSDavid du Colombier return "args";
9177dd7cddfSDavid du Colombier
9187dd7cddfSDavid du Colombier if((p = (Dospart*)findpart(edit, f[1])) == nil)
9197dd7cddfSDavid du Colombier return "unknown partition";
9207dd7cddfSDavid du Colombier
9217dd7cddfSDavid du Colombier if(nf == 2) {
9227dd7cddfSDavid du Colombier for(;;) {
9237dd7cddfSDavid du Colombier fprint(2, "new partition type [? for list]: ");
9247dd7cddfSDavid du Colombier q = getline(edit);
9257dd7cddfSDavid du Colombier if(q[0] == '?')
9267dd7cddfSDavid du Colombier dumplist();
9277dd7cddfSDavid du Colombier else
9287dd7cddfSDavid du Colombier break;
9297dd7cddfSDavid du Colombier }
9307dd7cddfSDavid du Colombier } else
9317dd7cddfSDavid du Colombier q = f[2];
9327dd7cddfSDavid du Colombier
9337dd7cddfSDavid du Colombier strupr(q);
9347dd7cddfSDavid du Colombier for(i=0; i<256; i++)
9357dd7cddfSDavid du Colombier if(types[i].desc && strcmp(types[i].desc, q) == 0)
9367dd7cddfSDavid du Colombier break;
9377dd7cddfSDavid du Colombier if(i < 256 && p->type != i) {
9387dd7cddfSDavid du Colombier p->type = i;
9397dd7cddfSDavid du Colombier p->changed = 1;
9407dd7cddfSDavid du Colombier edit->changed = 1;
9417dd7cddfSDavid du Colombier }
9427dd7cddfSDavid du Colombier return nil;
9437dd7cddfSDavid du Colombier }
9447dd7cddfSDavid du Colombier
9457dd7cddfSDavid du Colombier static char*
cmdext(Edit * edit,int nf,char ** f)9467dd7cddfSDavid du Colombier cmdext(Edit *edit, int nf, char **f)
9477dd7cddfSDavid du Colombier {
9487dd7cddfSDavid du Colombier switch(f[0][0]) {
9497dd7cddfSDavid du Colombier case 'A':
9507dd7cddfSDavid du Colombier return cmdactive(edit, nf, f);
9517dd7cddfSDavid du Colombier case 't':
9527dd7cddfSDavid du Colombier return cmdtype(edit, nf, f);
95380ee5cbfSDavid du Colombier case 'R':
95480ee5cbfSDavid du Colombier recover(edit);
95580ee5cbfSDavid du Colombier return nil;
9567dd7cddfSDavid du Colombier default:
9577dd7cddfSDavid du Colombier return "unknown command";
9587dd7cddfSDavid du Colombier }
9597dd7cddfSDavid du Colombier }
9607dd7cddfSDavid du Colombier
96180ee5cbfSDavid du Colombier static int
Dfmt(Fmt * f)9629a747e4fSDavid du Colombier Dfmt(Fmt *f)
96380ee5cbfSDavid du Colombier {
96480ee5cbfSDavid du Colombier char buf[60];
96580ee5cbfSDavid du Colombier uchar *p;
96680ee5cbfSDavid du Colombier int c, h, s;
96780ee5cbfSDavid du Colombier
9689a747e4fSDavid du Colombier p = va_arg(f->args, uchar*);
96980ee5cbfSDavid du Colombier h = p[0];
97080ee5cbfSDavid du Colombier c = p[2];
97180ee5cbfSDavid du Colombier c |= (p[1]&0xC0)<<2;
97280ee5cbfSDavid du Colombier s = (p[1] & 0x3F);
97380ee5cbfSDavid du Colombier
97480ee5cbfSDavid du Colombier sprint(buf, "%d/%d/%d", c, h, s);
9759a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
97680ee5cbfSDavid du Colombier }
97780ee5cbfSDavid du Colombier
97880ee5cbfSDavid du Colombier static void
writechs(Disk * disk,uchar * p,vlong lba)97980ee5cbfSDavid du Colombier writechs(Disk *disk, uchar *p, vlong lba)
98080ee5cbfSDavid du Colombier {
98180ee5cbfSDavid du Colombier int c, h, s;
98280ee5cbfSDavid du Colombier
98380ee5cbfSDavid du Colombier s = lba % disk->s;
98480ee5cbfSDavid du Colombier h = (lba / disk->s) % disk->h;
98580ee5cbfSDavid du Colombier c = lba / (disk->s * disk->h);
98680ee5cbfSDavid du Colombier
98780ee5cbfSDavid du Colombier if(c >= 1024) {
98880ee5cbfSDavid du Colombier c = 1023;
98980ee5cbfSDavid du Colombier h = disk->h - 1;
99080ee5cbfSDavid du Colombier s = disk->s - 1;
99180ee5cbfSDavid du Colombier }
99280ee5cbfSDavid du Colombier
99380ee5cbfSDavid du Colombier p[0] = h;
99480ee5cbfSDavid du Colombier p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0);
99580ee5cbfSDavid du Colombier p[2] = c;
99680ee5cbfSDavid du Colombier }
99780ee5cbfSDavid du Colombier
99880ee5cbfSDavid du Colombier static void
wrtentry(Disk * disk,Tentry * tp,int type,u32int xbase,u32int lba,u32int end)9999a747e4fSDavid du Colombier wrtentry(Disk *disk, Tentry *tp, int type, u32int xbase, u32int lba, u32int end)
100080ee5cbfSDavid du Colombier {
100180ee5cbfSDavid du Colombier tp->type = type;
10029a747e4fSDavid du Colombier writechs(disk, &tp->starth, lba);
10039a747e4fSDavid du Colombier writechs(disk, &tp->endh, end-1);
10049a747e4fSDavid du Colombier putle32(tp->xlba, lba-xbase);
10059a747e4fSDavid du Colombier putle32(tp->xsize, end-lba);
100680ee5cbfSDavid du Colombier }
100780ee5cbfSDavid du Colombier
100880ee5cbfSDavid du Colombier static int
wrextend(Edit * edit,int i,vlong xbase,vlong startlba,vlong * endlba)10099a747e4fSDavid du Colombier wrextend(Edit *edit, int i, vlong xbase, vlong startlba, vlong *endlba)
101080ee5cbfSDavid du Colombier {
101180ee5cbfSDavid du Colombier int ni;
101280ee5cbfSDavid du Colombier Table table;
101380ee5cbfSDavid du Colombier Tentry *tp, *ep;
101480ee5cbfSDavid du Colombier Dospart *p;
101580ee5cbfSDavid du Colombier Disk *disk;
101680ee5cbfSDavid du Colombier
10179a747e4fSDavid du Colombier if(i == edit->npart){
10189a747e4fSDavid du Colombier *endlba = edit->disk->secs;
10199a747e4fSDavid du Colombier Finish:
10209a747e4fSDavid du Colombier if(startlba < *endlba){
10219a747e4fSDavid du Colombier disk = edit->disk;
1022*9e732705SDavid du Colombier diskread(disk, &table, Tablesz, mbroffset+startlba, Toffset);
10239a747e4fSDavid du Colombier tp = table.entry;
10249a747e4fSDavid du Colombier ep = tp+NTentry;
10259a747e4fSDavid du Colombier for(; tp<ep; tp++)
10269a747e4fSDavid du Colombier memset(tp, 0, sizeof *tp);
10279a747e4fSDavid du Colombier table.magic[0] = Magic0;
10289a747e4fSDavid du Colombier table.magic[1] = Magic1;
10299a747e4fSDavid du Colombier
1030*9e732705SDavid du Colombier if(diskwrite(edit->disk, &table, Tablesz, mbroffset+startlba, Toffset) < 0)
10319a747e4fSDavid du Colombier recover(edit);
10329a747e4fSDavid du Colombier }
103380ee5cbfSDavid du Colombier return i;
10349a747e4fSDavid du Colombier }
103580ee5cbfSDavid du Colombier
103680ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i];
10379a747e4fSDavid du Colombier if(p->primary){
10389a747e4fSDavid du Colombier *endlba = (vlong)p->start*sec2cyl;
10399a747e4fSDavid du Colombier goto Finish;
10409a747e4fSDavid du Colombier }
104180ee5cbfSDavid du Colombier
104280ee5cbfSDavid du Colombier disk = edit->disk;
1043*9e732705SDavid du Colombier diskread(disk, &table, Tablesz, mbroffset+startlba, Toffset);
104480ee5cbfSDavid du Colombier tp = table.entry;
104580ee5cbfSDavid du Colombier ep = tp+NTentry;
104680ee5cbfSDavid du Colombier
10479a747e4fSDavid du Colombier ni = wrextend(edit, i+1, xbase, p->end*sec2cyl, endlba);
104880ee5cbfSDavid du Colombier
104980ee5cbfSDavid du Colombier *tp = p->Tentry;
10509a747e4fSDavid du Colombier wrtentry(disk, tp, p->type, startlba, startlba+disk->s, p->end*sec2cyl);
105180ee5cbfSDavid du Colombier tp++;
105280ee5cbfSDavid du Colombier
10539a747e4fSDavid du Colombier if(p->end*sec2cyl != *endlba){
105480ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp);
10559a747e4fSDavid du Colombier wrtentry(disk, tp, TypeEXTENDED, xbase, p->end*sec2cyl, *endlba);
105680ee5cbfSDavid du Colombier tp++;
105780ee5cbfSDavid du Colombier }
105880ee5cbfSDavid du Colombier
105980ee5cbfSDavid du Colombier for(; tp<ep; tp++)
106080ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp);
106180ee5cbfSDavid du Colombier
106280ee5cbfSDavid du Colombier table.magic[0] = Magic0;
106380ee5cbfSDavid du Colombier table.magic[1] = Magic1;
106480ee5cbfSDavid du Colombier
1065*9e732705SDavid du Colombier if(diskwrite(edit->disk, &table, Tablesz, mbroffset+startlba, Toffset) < 0)
106680ee5cbfSDavid du Colombier recover(edit);
106780ee5cbfSDavid du Colombier return ni;
106880ee5cbfSDavid du Colombier }
106980ee5cbfSDavid du Colombier
107080ee5cbfSDavid du Colombier static void
wrpart(Edit * edit)107180ee5cbfSDavid du Colombier wrpart(Edit *edit)
107280ee5cbfSDavid du Colombier {
10739a747e4fSDavid du Colombier int i, ni, t;
107480ee5cbfSDavid du Colombier Table table;
107580ee5cbfSDavid du Colombier Tentry *tp, *ep;
107680ee5cbfSDavid du Colombier Disk *disk;
107780ee5cbfSDavid du Colombier vlong s, endlba;
107880ee5cbfSDavid du Colombier Dospart *p;
107980ee5cbfSDavid du Colombier
108080ee5cbfSDavid du Colombier disk = edit->disk;
108180ee5cbfSDavid du Colombier
1082*9e732705SDavid du Colombier diskread(disk, &table, Tablesz, mbroffset, Toffset);
108380ee5cbfSDavid du Colombier
108480ee5cbfSDavid du Colombier tp = table.entry;
108580ee5cbfSDavid du Colombier ep = tp+NTentry;
108680ee5cbfSDavid du Colombier for(i=0; i<edit->npart && tp<ep; ) {
108780ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i];
108880ee5cbfSDavid du Colombier if(p->start == 0)
108980ee5cbfSDavid du Colombier s = disk->s;
109080ee5cbfSDavid du Colombier else
109180ee5cbfSDavid du Colombier s = p->start*sec2cyl;
109280ee5cbfSDavid du Colombier if(p->primary) {
109380ee5cbfSDavid du Colombier *tp = p->Tentry;
10949a747e4fSDavid du Colombier wrtentry(disk, tp, p->type, 0, s, p->end*sec2cyl);
109580ee5cbfSDavid du Colombier tp++;
109680ee5cbfSDavid du Colombier i++;
109780ee5cbfSDavid du Colombier } else {
10989a747e4fSDavid du Colombier ni = wrextend(edit, i, p->start*sec2cyl, p->start*sec2cyl, &endlba);
109980ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp);
11009a747e4fSDavid du Colombier if(endlba >= 1024*sec2cyl)
11019a747e4fSDavid du Colombier t = TypeEXTHUGE;
11029a747e4fSDavid du Colombier else
11039a747e4fSDavid du Colombier t = TypeEXTENDED;
11049a747e4fSDavid du Colombier wrtentry(disk, tp, t, 0, s, endlba);
110580ee5cbfSDavid du Colombier tp++;
110680ee5cbfSDavid du Colombier i = ni;
110780ee5cbfSDavid du Colombier }
110880ee5cbfSDavid du Colombier }
110980ee5cbfSDavid du Colombier for(; tp<ep; tp++)
111080ee5cbfSDavid du Colombier memset(tp, 0, sizeof(*tp));
111180ee5cbfSDavid du Colombier
111280ee5cbfSDavid du Colombier if(i != edit->npart)
111380ee5cbfSDavid du Colombier sysfatal("cannot happen #1");
111480ee5cbfSDavid du Colombier
1115*9e732705SDavid du Colombier if(diskwrite(disk, &table, Tablesz, mbroffset, Toffset) < 0)
111680ee5cbfSDavid du Colombier recover(edit);
111780ee5cbfSDavid du Colombier
111880ee5cbfSDavid du Colombier /* bring parts up to date */
111980ee5cbfSDavid du Colombier freenamelist();
112080ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++)
112180ee5cbfSDavid du Colombier plan9print((Dospart*)edit->part[i], -1);
112280ee5cbfSDavid du Colombier
112380ee5cbfSDavid du Colombier if(ctldiff(edit, disk->ctlfd) < 0)
112480ee5cbfSDavid du Colombier fprint(2, "?warning: partitions could not be updated in devsd\n");
112580ee5cbfSDavid du Colombier }
1126