xref: /plan9/sys/src/cmd/disk/prep/fdisk.c (revision 65fa3f8b9a469d1a1f534b0eb39ee25caab832bb)
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 
179a747e4fSDavid du Colombier static void rdpart(Edit*, ulong, ulong);
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 */
2147dd7cddfSDavid du Colombier 	TypeEXTHUGE	= 0x0F,		/* FAT 32 extended partition */
2157dd7cddfSDavid du Colombier 	TypeUNFORMATTED	= 0x16,		/* unformatted primary partition (OS/2 FDISK)? */
2167dd7cddfSDavid du Colombier 	TypeHPFS2	= 0x17,
2176b6b9ac8SDavid du Colombier 	TypeIBMRecovery = 0x1C,	/* really hidden fat */
2187dd7cddfSDavid du Colombier 	TypeCPM0	= 0x52,
2197dd7cddfSDavid du Colombier 	TypeDMDDO	= 0x54,		/* Disk Manager Dynamic Disk Overlay */
2207dd7cddfSDavid du Colombier 	TypeGB		= 0x56,		/* ???? */
2217dd7cddfSDavid du Colombier 	TypeSPEEDSTOR	= 0x61,
2227dd7cddfSDavid du Colombier 	TypeSYSV386	= 0x63,		/* also HURD? */
2237dd7cddfSDavid du Colombier 	TypeNETWARE	= 0x64,
2247dd7cddfSDavid du Colombier 	TypePCIX	= 0x75,
2257dd7cddfSDavid du Colombier 	TypeMINIX13	= 0x80,		/* Minix v1.3 and below */
2267dd7cddfSDavid du Colombier 	TypeMINIX	= 0x81,		/* Minix v1.5+ */
2277dd7cddfSDavid du Colombier 	TypeLINUXSWAP	= 0x82,
2287dd7cddfSDavid du Colombier 	TypeLINUX	= 0x83,
2299a747e4fSDavid du Colombier 	TypeLINUXEXT	= 0x85,
2307dd7cddfSDavid du Colombier 	TypeAMOEBA	= 0x93,
2317dd7cddfSDavid du Colombier 	TypeAMOEBABB	= 0x94,
2327dd7cddfSDavid du Colombier 	TypeBSD386	= 0xA5,
2337dd7cddfSDavid du Colombier 	TypeBSDI	= 0xB7,
2347dd7cddfSDavid du Colombier 	TypeBSDISWAP	= 0xB8,
23580ee5cbfSDavid du Colombier 	TypeOTHER	= 0xDA,
2367dd7cddfSDavid du Colombier 	TypeCPM		= 0xDB,
237*65fa3f8bSDavid du Colombier 	TypeDellRecovery	= 0xDE,
2387dd7cddfSDavid du Colombier 	TypeSPEEDSTOR12	= 0xE1,
2397dd7cddfSDavid du Colombier 	TypeSPEEDSTOR16	= 0xE4,
2407dd7cddfSDavid du Colombier 	TypeLANSTEP	= 0xFE,
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier 	Type9		= 0x39,
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier 	Toffset		= 446,		/* offset of partition table in sector */
2457dd7cddfSDavid du Colombier 	Magic0		= 0x55,
2467dd7cddfSDavid du Colombier 	Magic1		= 0xAA,
2477dd7cddfSDavid du Colombier };
2487dd7cddfSDavid du Colombier 
2497dd7cddfSDavid du Colombier struct Table {
2507dd7cddfSDavid du Colombier 	Tentry	entry[NTentry];
2517dd7cddfSDavid du Colombier 	uchar	magic[2];
2527dd7cddfSDavid du Colombier };
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier struct Type {
2557dd7cddfSDavid du Colombier 	char *desc;
2567dd7cddfSDavid du Colombier 	char *name;
2577dd7cddfSDavid du Colombier };
2587dd7cddfSDavid du Colombier 
25980ee5cbfSDavid du Colombier struct Dospart {
26080ee5cbfSDavid du Colombier 	Part;
2617dd7cddfSDavid du Colombier 	Tentry;
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier 	u32int	lba;
2647dd7cddfSDavid du Colombier 	u32int	size;
26580ee5cbfSDavid du Colombier 	int		primary;
2667dd7cddfSDavid du Colombier };
2677dd7cddfSDavid du Colombier 
26880ee5cbfSDavid du Colombier struct Recover {
26980ee5cbfSDavid du Colombier 	Table	table;
27080ee5cbfSDavid du Colombier 	ulong	lba;
2717dd7cddfSDavid du Colombier };
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier static Type types[256] = {
2747dd7cddfSDavid du Colombier 	[TypeEMPTY]		{ "EMPTY", "" },
2757dd7cddfSDavid du Colombier 	[TypeFAT12]		{ "FAT12", "dos" },
2767dd7cddfSDavid du Colombier 	[TypeFAT16]		{ "FAT16", "dos" },
2777dd7cddfSDavid du Colombier 	[TypeFAT32]		{ "FAT32", "dos" },
2787dd7cddfSDavid du Colombier 	[TypeFAT32LBA]		{ "FAT32LBA", "dos" },
2797dd7cddfSDavid du Colombier 	[TypeEXTHUGE]		{ "EXTHUGE", "" },
2806b6b9ac8SDavid du Colombier 	[TypeIBMRecovery]	{ "IBMRECOVERY", "ibm" },
2817dd7cddfSDavid du Colombier 	[TypeEXTENDED]		{ "EXTENDED", "" },
2827dd7cddfSDavid du Colombier 	[TypeFATHUGE]		{ "FATHUGE", "dos" },
2837dd7cddfSDavid du Colombier 	[TypeBB]		{ "BB", "bb" },
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier 	[TypeXENIX]		{ "XENIX", "xenix" },
2867dd7cddfSDavid du Colombier 	[TypeXENIXUSR]		{ "XENIX USR", "xenixusr" },
2877dd7cddfSDavid du Colombier 	[TypeHPFS]		{ "HPFS", "ntfs" },
2887dd7cddfSDavid du Colombier 	[TypeAIXBOOT]		{ "AIXBOOT", "aixboot" },
2897dd7cddfSDavid du Colombier 	[TypeAIXDATA]		{ "AIXDATA", "aixdata" },
2907dd7cddfSDavid du Colombier 	[TypeOS2BOOT]		{ "OS/2BOOT", "os2boot" },
2917dd7cddfSDavid du Colombier 	[TypeUNFORMATTED]	{ "UNFORMATTED", "" },
2927dd7cddfSDavid du Colombier 	[TypeHPFS2]		{ "HPFS2", "hpfs2" },
2937dd7cddfSDavid du Colombier 	[TypeCPM0]		{ "CPM0", "cpm0" },
2947dd7cddfSDavid du Colombier 	[TypeDMDDO]		{ "DMDDO", "dmdd0" },
2957dd7cddfSDavid du Colombier 	[TypeGB]		{ "GB", "gb" },
2967dd7cddfSDavid du Colombier 	[TypeSPEEDSTOR]		{ "SPEEDSTOR", "speedstor" },
2977dd7cddfSDavid du Colombier 	[TypeSYSV386]		{ "SYSV386", "sysv386" },
2987dd7cddfSDavid du Colombier 	[TypeNETWARE]		{ "NETWARE", "netware" },
2997dd7cddfSDavid du Colombier 	[TypePCIX]		{ "PCIX", "pcix" },
3007dd7cddfSDavid du Colombier 	[TypeMINIX13]		{ "MINIXV1.3", "minix13" },
3017dd7cddfSDavid du Colombier 	[TypeMINIX]		{ "MINIXV1.5", "minix15" },
3027dd7cddfSDavid du Colombier 	[TypeLINUXSWAP]		{ "LINUXSWAP", "linuxswap" },
3037dd7cddfSDavid du Colombier 	[TypeLINUX]		{ "LINUX", "linux" },
3049a747e4fSDavid du Colombier 	[TypeLINUXEXT]		{ "LINUXEXTENDED", "" },
3057dd7cddfSDavid du Colombier 	[TypeAMOEBA]		{ "AMOEBA", "amoeba" },
3067dd7cddfSDavid du Colombier 	[TypeAMOEBABB]		{ "AMOEBABB", "amoebaboot" },
3077dd7cddfSDavid du Colombier 	[TypeBSD386]		{ "BSD386", "bsd386" },
3087dd7cddfSDavid du Colombier 	[TypeBSDI]		{ "BSDI", "bsdi" },
3097dd7cddfSDavid du Colombier 	[TypeBSDISWAP]		{ "BSDISWAP", "bsdiswap" },
31080ee5cbfSDavid du Colombier 	[TypeOTHER]		{ "OTHER", "other" },
3117dd7cddfSDavid du Colombier 	[TypeCPM]		{ "CPM", "cpm" },
312*65fa3f8bSDavid du Colombier 	[TypeDellRecovery]	{ "DELLRECOVERY", "dell" },
3137dd7cddfSDavid du Colombier 	[TypeSPEEDSTOR12]	{ "SPEEDSTOR12", "speedstor" },
3147dd7cddfSDavid du Colombier 	[TypeSPEEDSTOR16]	{ "SPEEDSTOR16", "speedstor" },
3157dd7cddfSDavid du Colombier 	[TypeLANSTEP]		{ "LANSTEP", "lanstep" },
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	[Type9]			{ "PLAN9", "plan9" },
3187dd7cddfSDavid du Colombier };
3197dd7cddfSDavid du Colombier 
32080ee5cbfSDavid du Colombier static Dospart	part[Mpart];
32180ee5cbfSDavid du Colombier static int		npart;
32280ee5cbfSDavid du Colombier 
3237dd7cddfSDavid du Colombier static char*
32480ee5cbfSDavid du Colombier typestr0(int type)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier 	static char buf[100];
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier 	sprint(buf, "type %d", type);
3297dd7cddfSDavid du Colombier 	if(type < 0 || type >= 256)
3307dd7cddfSDavid du Colombier 		return buf;
3317dd7cddfSDavid du Colombier 	if(types[type].desc == nil)
3327dd7cddfSDavid du Colombier 		return buf;
3337dd7cddfSDavid du Colombier 	return types[type].desc;
3347dd7cddfSDavid du Colombier }
3357dd7cddfSDavid du Colombier 
3367dd7cddfSDavid du Colombier static u32int
3377dd7cddfSDavid du Colombier getle32(void* v)
3387dd7cddfSDavid du Colombier {
3397dd7cddfSDavid du Colombier 	uchar *p;
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 	p = v;
3427dd7cddfSDavid du Colombier 	return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0];
3437dd7cddfSDavid du Colombier }
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier static void
3467dd7cddfSDavid du Colombier putle32(void* v, u32int i)
3477dd7cddfSDavid du Colombier {
3487dd7cddfSDavid du Colombier 	uchar *p;
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier 	p = v;
3517dd7cddfSDavid du Colombier 	p[0] = i;
3527dd7cddfSDavid du Colombier 	p[1] = i>>8;
3537dd7cddfSDavid du Colombier 	p[2] = i>>16;
3547dd7cddfSDavid du Colombier 	p[3] = i>>24;
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier 
35780ee5cbfSDavid du Colombier static void
35880ee5cbfSDavid du Colombier diskread(Disk *disk, void *data, int ndata, u32int sec, u32int off)
3597dd7cddfSDavid du Colombier {
3609a747e4fSDavid du Colombier 	if(seek(disk->fd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)
36180ee5cbfSDavid du Colombier 		sysfatal("diskread seek %lud.%lud: %r", (ulong)sec, (ulong)off);
36280ee5cbfSDavid du Colombier 	if(readn(disk->fd, data, ndata) != ndata)
36380ee5cbfSDavid du Colombier 		sysfatal("diskread %lud at %lud.%lud: %r", (ulong)ndata, (ulong)sec, (ulong)off);
36480ee5cbfSDavid du Colombier }
3657dd7cddfSDavid du Colombier 
36680ee5cbfSDavid du Colombier static int
36780ee5cbfSDavid du Colombier diskwrite(Disk *disk, void *data, int ndata, u32int sec, u32int off)
36880ee5cbfSDavid du Colombier {
36980ee5cbfSDavid du Colombier 	written = 1;
3709a747e4fSDavid du Colombier 	if(seek(disk->wfd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)
37180ee5cbfSDavid du Colombier 		goto Error;
37280ee5cbfSDavid du Colombier 	if(write(disk->wfd, data, ndata) != ndata)
37380ee5cbfSDavid du Colombier 		goto Error;
37480ee5cbfSDavid du Colombier 	return 0;
3757dd7cddfSDavid du Colombier 
37680ee5cbfSDavid du Colombier Error:
37780ee5cbfSDavid du Colombier 	fprint(2, "write %d bytes at %lud.%lud failed: %r\n", ndata, (ulong)sec, (ulong)off);
37880ee5cbfSDavid du Colombier 	return -1;
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier 
3817dd7cddfSDavid du Colombier static Dospart*
38280ee5cbfSDavid du Colombier mkpart(char *name, int primary, u32int lba, u32int size, Tentry *t)
3837dd7cddfSDavid du Colombier {
38480ee5cbfSDavid du Colombier 	static int n;
3857dd7cddfSDavid du Colombier 	Dospart *p;
3867dd7cddfSDavid du Colombier 
38780ee5cbfSDavid du Colombier 	p = emalloc(sizeof(*p));
38880ee5cbfSDavid du Colombier 	if(name)
3899a747e4fSDavid du Colombier 		p->name = estrdup(name);
3909a747e4fSDavid du Colombier 	else{
3919a747e4fSDavid du Colombier 		p->name = emalloc(20);
39280ee5cbfSDavid du Colombier 		sprint(p->name, "%c%d", primary ? 'p' : 's', ++n);
3939a747e4fSDavid du Colombier 	}
39480ee5cbfSDavid du Colombier 
39580ee5cbfSDavid du Colombier 	if(t)
39680ee5cbfSDavid du Colombier 		p->Tentry = *t;
39780ee5cbfSDavid du Colombier 	else
39880ee5cbfSDavid du Colombier 		memset(&p->Tentry, 0, sizeof(Tentry));
39980ee5cbfSDavid du Colombier 
4007dd7cddfSDavid du Colombier 	p->changed = 0;
40180ee5cbfSDavid du Colombier 	p->start = lba/sec2cyl;
40280ee5cbfSDavid du Colombier 	p->end = (lba+size)/sec2cyl;
40380ee5cbfSDavid du Colombier 	p->ctlstart = lba;
40480ee5cbfSDavid du Colombier 	p->ctlend = lba+size;
40580ee5cbfSDavid du Colombier 	p->lba = lba;
40680ee5cbfSDavid du Colombier 	p->size = size;
40780ee5cbfSDavid du Colombier 	p->primary = primary;
4087dd7cddfSDavid du Colombier 	return p;
4097dd7cddfSDavid du Colombier }
4107dd7cddfSDavid du Colombier 
41180ee5cbfSDavid du Colombier /*
41280ee5cbfSDavid du Colombier  * Recovery takes care of remembering what the various tables
41380ee5cbfSDavid du Colombier  * looked like when we started, attempting to restore them when
41480ee5cbfSDavid du Colombier  * we are finished.
41580ee5cbfSDavid du Colombier  */
41680ee5cbfSDavid du Colombier static Recover	*rtab;
41780ee5cbfSDavid du Colombier static int		nrtab;
4187dd7cddfSDavid du Colombier 
41980ee5cbfSDavid du Colombier static void
42080ee5cbfSDavid du Colombier addrecover(Table t, ulong lba)
42180ee5cbfSDavid du Colombier {
42280ee5cbfSDavid du Colombier 	if((nrtab%8) == 0) {
42380ee5cbfSDavid du Colombier 		rtab = realloc(rtab, (nrtab+8)*sizeof(rtab[0]));
42480ee5cbfSDavid du Colombier 		if(rtab == nil)
42580ee5cbfSDavid du Colombier 			sysfatal("out of memory");
4267dd7cddfSDavid du Colombier 	}
42780ee5cbfSDavid du Colombier 	rtab[nrtab] = (Recover){t, lba};
42880ee5cbfSDavid du Colombier 	nrtab++;
42980ee5cbfSDavid du Colombier }
43080ee5cbfSDavid du Colombier 
43180ee5cbfSDavid du Colombier static void
43280ee5cbfSDavid du Colombier recover(Edit *edit)
43380ee5cbfSDavid du Colombier {
43480ee5cbfSDavid du Colombier 	int err, i, ctlfd;
43580ee5cbfSDavid du Colombier 	vlong offset;
43680ee5cbfSDavid du Colombier 
43780ee5cbfSDavid du Colombier 	err = 0;
43880ee5cbfSDavid du Colombier 	for(i=0; i<nrtab; i++)
43980ee5cbfSDavid du Colombier 		if(diskwrite(edit->disk, &rtab[i].table, sizeof(Table), rtab[i].lba, Toffset) < 0)
44080ee5cbfSDavid du Colombier 			err = 1;
44180ee5cbfSDavid du Colombier 	if(err) {
44280ee5cbfSDavid du Colombier 		fprint(2, "warning: some writes failed during restoration of old partition tables\n");
44380ee5cbfSDavid du Colombier 		exits("inconsistent");
44480ee5cbfSDavid du Colombier 	} else {
44580ee5cbfSDavid du Colombier 		fprint(2, "restored old partition tables\n");
44680ee5cbfSDavid du Colombier 	}
44780ee5cbfSDavid du Colombier 
44880ee5cbfSDavid du Colombier 	ctlfd = edit->disk->ctlfd;
44980ee5cbfSDavid du Colombier 	offset = edit->disk->offset;
45080ee5cbfSDavid du Colombier 	if(ctlfd >= 0){
45180ee5cbfSDavid du Colombier 		for(i=0; i<edit->npart; i++)
4526b6b9ac8SDavid du Colombier 			if(edit->part[i]->ctlname && fprint(ctlfd, "delpart %s", edit->part[i]->ctlname)<0)
45380ee5cbfSDavid du Colombier 				fprint(2, "delpart failed: %s: %r", edit->part[i]->ctlname);
45480ee5cbfSDavid du Colombier 		for(i=0; i<edit->nctlpart; i++)
4556b6b9ac8SDavid du Colombier 			if(edit->part[i]->name && fprint(ctlfd, "delpart %s", edit->ctlpart[i]->name)<0)
45680ee5cbfSDavid du Colombier 				fprint(2, "delpart failed: %s: %r", edit->ctlpart[i]->name);
45780ee5cbfSDavid du Colombier 		for(i=0; i<edit->nctlpart; i++){
45880ee5cbfSDavid du Colombier 			if(fprint(ctlfd, "part %s %lld %lld", edit->ctlpart[i]->name,
45980ee5cbfSDavid du Colombier 				edit->ctlpart[i]->start+offset, edit->ctlpart[i]->end+offset) < 0){
46080ee5cbfSDavid du Colombier 				fprint(2, "restored disk partition table but not kernel; reboot\n");
46180ee5cbfSDavid du Colombier 				exits("inconsistent");
46280ee5cbfSDavid du Colombier 			}
46380ee5cbfSDavid du Colombier 		}
46480ee5cbfSDavid du Colombier 	}
46580ee5cbfSDavid du Colombier 	exits("restored");
46680ee5cbfSDavid du Colombier 
46780ee5cbfSDavid du Colombier }
46880ee5cbfSDavid du Colombier 
46980ee5cbfSDavid du Colombier /*
47080ee5cbfSDavid du Colombier  * Read the partition table (including extended partition tables)
47180ee5cbfSDavid du Colombier  * from the disk into the part array.
47280ee5cbfSDavid du Colombier  */
47380ee5cbfSDavid du Colombier static void
4749a747e4fSDavid du Colombier rdpart(Edit *edit, ulong lba, ulong xbase)
47580ee5cbfSDavid du Colombier {
47680ee5cbfSDavid du Colombier 	char *err;
47780ee5cbfSDavid du Colombier 	Table table;
47880ee5cbfSDavid du Colombier 	Tentry *tp, *ep;
47980ee5cbfSDavid du Colombier 	Dospart *p;
48080ee5cbfSDavid du Colombier 
4819a747e4fSDavid du Colombier 	if(xbase == 0)
4829a747e4fSDavid du Colombier 		xbase = lba;
4839a747e4fSDavid du Colombier 
48480ee5cbfSDavid du Colombier 	diskread(edit->disk, &table, sizeof table, mbroffset+lba, Toffset);
48580ee5cbfSDavid du Colombier 	addrecover(table, mbroffset+lba);
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier 	if(table.magic[0] != Magic0 || table.magic[1] != Magic1) {
48880ee5cbfSDavid du Colombier 		assert(lba != 0);
4897dd7cddfSDavid du Colombier 		return;
4907dd7cddfSDavid du Colombier 	}
4917dd7cddfSDavid du Colombier 
49280ee5cbfSDavid du Colombier 	for(tp=table.entry, ep=tp+NTentry; tp<ep && npart < Mpart; tp++) {
49380ee5cbfSDavid du Colombier 		switch(tp->type) {
4947dd7cddfSDavid du Colombier 		case TypeEMPTY:
4957dd7cddfSDavid du Colombier 			break;
4967dd7cddfSDavid du Colombier 		case TypeEXTENDED:
4977dd7cddfSDavid du Colombier 		case TypeEXTHUGE:
4989a747e4fSDavid du Colombier 		case TypeLINUXEXT:
4999a747e4fSDavid du Colombier 			rdpart(edit, xbase+getle32(tp->xlba), xbase);
5007dd7cddfSDavid du Colombier 			break;
5017dd7cddfSDavid du Colombier 		default:
50280ee5cbfSDavid du Colombier 			p = mkpart(nil, lba==0, lba+getle32(tp->xlba), getle32(tp->xsize), tp);
5037dd7cddfSDavid du Colombier 			if(err = addpart(edit, p))
50480ee5cbfSDavid du Colombier 				fprint(2, "adding partition: %s\n", err);
50580ee5cbfSDavid du Colombier 			break;
50680ee5cbfSDavid du Colombier 		}
5077dd7cddfSDavid du Colombier 	}
5087dd7cddfSDavid du Colombier }
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier static void
5117dd7cddfSDavid du Colombier blankpart(Edit *edit)
5127dd7cddfSDavid du Colombier {
5137dd7cddfSDavid du Colombier 	edit->changed = 1;
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier 
5167dd7cddfSDavid du Colombier static void
5177dd7cddfSDavid du Colombier findmbr(Edit *edit)
5187dd7cddfSDavid du Colombier {
5197dd7cddfSDavid du Colombier 	Table table;
5207dd7cddfSDavid du Colombier 	Tentry *tp;
5217dd7cddfSDavid du Colombier 
52280ee5cbfSDavid du Colombier 	diskread(edit->disk, &table, sizeof(Table), 0, Toffset);
5237dd7cddfSDavid du Colombier 	if(table.magic[0] != Magic0 || table.magic[1] != Magic1)
5247dd7cddfSDavid du Colombier 		sysfatal("did not find master boot record");
5257dd7cddfSDavid du Colombier 
5267dd7cddfSDavid du Colombier 	for(tp = table.entry; tp < &table.entry[NTentry]; tp++)
5277dd7cddfSDavid du Colombier 		if(tp->type == TypeDMDDO)
52880ee5cbfSDavid du Colombier 			mbroffset = edit->disk->s;
5297dd7cddfSDavid du Colombier }
5307dd7cddfSDavid du Colombier 
53180ee5cbfSDavid du Colombier static int
53280ee5cbfSDavid du Colombier haveroom(Edit *edit, int primary, vlong start)
5337dd7cddfSDavid du Colombier {
5349a747e4fSDavid du Colombier 	int i, lastsec, n;
5359a747e4fSDavid du Colombier 	Dospart *p, *q;
5369a747e4fSDavid du Colombier 	ulong pend, qstart;
53780ee5cbfSDavid du Colombier 
53880ee5cbfSDavid du Colombier 	if(primary) {
53980ee5cbfSDavid du Colombier 		/*
54080ee5cbfSDavid du Colombier 		 * must be open primary slot.
54180ee5cbfSDavid du Colombier 		 * primary slots are taken by primary partitions
54280ee5cbfSDavid du Colombier 		 * and runs of secondary partitions.
54380ee5cbfSDavid du Colombier 		 */
54480ee5cbfSDavid du Colombier 		n = 0;
54580ee5cbfSDavid du Colombier 		lastsec = 0;
54680ee5cbfSDavid du Colombier 		for(i=0; i<edit->npart; i++) {
54780ee5cbfSDavid du Colombier 			p = (Dospart*)edit->part[i];
54880ee5cbfSDavid du Colombier 			if(p->primary)
54980ee5cbfSDavid du Colombier 				n++, lastsec=0;
5509a747e4fSDavid du Colombier 			else if(!lastsec)
55180ee5cbfSDavid du Colombier 				n++, lastsec=1;
5527dd7cddfSDavid du Colombier 		}
55380ee5cbfSDavid du Colombier 		return n<4;
5547dd7cddfSDavid du Colombier 	}
5557dd7cddfSDavid du Colombier 
55680ee5cbfSDavid du Colombier 	/*
55780ee5cbfSDavid du Colombier 	 * secondary partitions can be inserted between two primary
55880ee5cbfSDavid du Colombier 	 * partitions only if there is an empty primary slot.
55980ee5cbfSDavid du Colombier 	 * otherwise, we can put a new secondary partition next
56080ee5cbfSDavid du Colombier 	 * to a secondary partition no problem.
56180ee5cbfSDavid du Colombier 	 */
56280ee5cbfSDavid du Colombier 	n = 0;
5636b6b9ac8SDavid du Colombier 	for(i=0; i<edit->npart; i++){
56480ee5cbfSDavid du Colombier 		p = (Dospart*)edit->part[i];
56580ee5cbfSDavid du Colombier 		if(p->primary)
5669a747e4fSDavid du Colombier 			n++;
5679a747e4fSDavid du Colombier 		pend = p->end;
5689a747e4fSDavid du Colombier 		if(i+1<edit->npart){
5699a747e4fSDavid du Colombier 			q = (Dospart*)edit->part[i+1];
5709a747e4fSDavid du Colombier 			qstart = q->start;
5719a747e4fSDavid du Colombier 		}else{
5729a747e4fSDavid du Colombier 			qstart = edit->end;
5739a747e4fSDavid du Colombier 			q = nil;
5747dd7cddfSDavid du Colombier 		}
5759a747e4fSDavid du Colombier 		if(start < pend || start >= qstart)
5769a747e4fSDavid du Colombier 			continue;
5779a747e4fSDavid du Colombier 		/* we go between these two */
5789a747e4fSDavid du Colombier 		if(p->primary==0 || (q && q->primary==0))
5799a747e4fSDavid du Colombier 			return 1;
5807dd7cddfSDavid du Colombier 	}
58180ee5cbfSDavid du Colombier 	/* not next to a secondary, need a new primary */
58280ee5cbfSDavid du Colombier 	return n<4;
5837dd7cddfSDavid du Colombier }
5847dd7cddfSDavid du Colombier 
5857dd7cddfSDavid du Colombier static void
5867dd7cddfSDavid du Colombier autopart(Edit *edit)
5877dd7cddfSDavid du Colombier {
58880ee5cbfSDavid du Colombier 	char *err;
58980ee5cbfSDavid du Colombier 	int active, i;
59080ee5cbfSDavid du Colombier 	vlong bigstart, bigsize, start;
59180ee5cbfSDavid du Colombier 	Dospart *p;
5927dd7cddfSDavid du Colombier 
59380ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
59480ee5cbfSDavid du Colombier 		if(((Dospart*)edit->part[i])->type == Type9)
5957dd7cddfSDavid du Colombier 			return;
5967dd7cddfSDavid du Colombier 
59780ee5cbfSDavid du Colombier 	/* look for the biggest gap in which we can put a primary partition */
59880ee5cbfSDavid du Colombier 	start = 0;
5997dd7cddfSDavid du Colombier 	bigsize = 0;
6007dd7cddfSDavid du Colombier 	SET(bigstart);
6017dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
60280ee5cbfSDavid du Colombier 		p = (Dospart*)edit->part[i];
60380ee5cbfSDavid du Colombier 		if(p->start > start && p->start - start > bigsize && haveroom(edit, 1, start)) {
6047dd7cddfSDavid du Colombier 			bigsize = p->start - start;
6057dd7cddfSDavid du Colombier 			bigstart = start;
6067dd7cddfSDavid du Colombier 		}
6077dd7cddfSDavid du Colombier 		start = p->end;
6087dd7cddfSDavid du Colombier 	}
6097dd7cddfSDavid du Colombier 
61080ee5cbfSDavid du Colombier 	if(edit->end - start > bigsize && haveroom(edit, 1, start)) {
61180ee5cbfSDavid du Colombier 		bigsize = edit->end - start;
6127dd7cddfSDavid du Colombier 		bigstart = start;
6137dd7cddfSDavid du Colombier 	}
61480ee5cbfSDavid du Colombier 	if(bigsize < 1) {
61580ee5cbfSDavid du Colombier 		fprint(2, "couldn't find space or partition slot for plan 9 partition\n");
6167dd7cddfSDavid du Colombier 		return;
6177dd7cddfSDavid du Colombier 	}
6187dd7cddfSDavid du Colombier 
61980ee5cbfSDavid du Colombier 	/* set new partition active only if no others are */
6207dd7cddfSDavid du Colombier 	active = Active;
62180ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
62280ee5cbfSDavid du Colombier 		if(((Dospart*)edit->part[i])->primary && (((Dospart*)edit->part[i])->active & Active))
6237dd7cddfSDavid du Colombier 			active = 0;
6247dd7cddfSDavid du Colombier 
62580ee5cbfSDavid du Colombier 	/* add new plan 9 partition */
62680ee5cbfSDavid du Colombier 	bigsize *= sec2cyl;
62780ee5cbfSDavid du Colombier 	bigstart *= sec2cyl;
62880ee5cbfSDavid du Colombier 	if(bigstart == 0) {
62980ee5cbfSDavid du Colombier 		bigstart += edit->disk->s;
63080ee5cbfSDavid du Colombier 		bigsize -= edit->disk->s;
6317dd7cddfSDavid du Colombier 	}
63280ee5cbfSDavid du Colombier 	p = mkpart(nil, 1, bigstart, bigsize, nil);
63380ee5cbfSDavid du Colombier 	p->active = active;
63480ee5cbfSDavid du Colombier 	p->changed = 1;
63580ee5cbfSDavid du Colombier 	p->type = Type9;
63680ee5cbfSDavid du Colombier 	edit->changed = 1;
63780ee5cbfSDavid du Colombier 	if(err = addpart(edit, p)) {
63880ee5cbfSDavid du Colombier 		fprint(2, "error adding plan9 partition: %s\n", err);
6397dd7cddfSDavid du Colombier 		return;
6407dd7cddfSDavid du Colombier 	}
6417dd7cddfSDavid du Colombier }
6427dd7cddfSDavid du Colombier 
6437dd7cddfSDavid du Colombier typedef struct Name Name;
6447dd7cddfSDavid du Colombier struct Name {
6459a747e4fSDavid du Colombier 	char *name;
6467dd7cddfSDavid du Colombier 	Name *link;
6477dd7cddfSDavid du Colombier };
6487dd7cddfSDavid du Colombier Name *namelist;
6497dd7cddfSDavid du Colombier static void
65080ee5cbfSDavid du Colombier plan9print(Dospart *part, int fd)
6517dd7cddfSDavid du Colombier {
6527dd7cddfSDavid du Colombier 	int i, ok;
6539a747e4fSDavid du Colombier 	char *name, *vname;
6547dd7cddfSDavid du Colombier 	Name *n;
65580ee5cbfSDavid du Colombier 	vlong start, end;
65680ee5cbfSDavid du Colombier 	char *sep;
65780ee5cbfSDavid du Colombier 
65880ee5cbfSDavid du Colombier 	vname = types[part->type].name;
6599a747e4fSDavid du Colombier 	if(vname==nil || strcmp(vname, "")==0) {
6609a747e4fSDavid du Colombier 		part->ctlname = "";
66180ee5cbfSDavid du Colombier 		return;
66280ee5cbfSDavid du Colombier 	}
66380ee5cbfSDavid du Colombier 
66480ee5cbfSDavid du Colombier 	start = mbroffset+part->lba;
66580ee5cbfSDavid du Colombier 	end = start+part->size;
66680ee5cbfSDavid du Colombier 
66780ee5cbfSDavid du Colombier 	/* avoid names like plan90 */
66880ee5cbfSDavid du Colombier 	i = strlen(vname) - 1;
66980ee5cbfSDavid du Colombier 	if(vname[i] >= '0' && vname[i] <= '9')
67080ee5cbfSDavid du Colombier 		sep = ".";
67180ee5cbfSDavid du Colombier 	else
67280ee5cbfSDavid du Colombier 		sep = "";
6737dd7cddfSDavid du Colombier 
6747dd7cddfSDavid du Colombier 	i = 0;
6759a747e4fSDavid du Colombier 	name = emalloc(strlen(vname)+10);
6769a747e4fSDavid du Colombier 
67780ee5cbfSDavid du Colombier 	sprint(name, "%s", vname);
6787dd7cddfSDavid du Colombier 	do {
6797dd7cddfSDavid du Colombier 		ok = 1;
6807dd7cddfSDavid du Colombier 		for(n=namelist; n; n=n->link) {
6817dd7cddfSDavid du Colombier 			if(strcmp(name, n->name) == 0) {
6827dd7cddfSDavid du Colombier 				i++;
68380ee5cbfSDavid du Colombier 				sprint(name, "%s%s%d", vname, sep, i);
6847dd7cddfSDavid du Colombier 				ok = 0;
6857dd7cddfSDavid du Colombier 			}
6867dd7cddfSDavid du Colombier 		}
6877dd7cddfSDavid du Colombier 	} while(ok == 0);
6887dd7cddfSDavid du Colombier 
6899a747e4fSDavid du Colombier 	n = emalloc(sizeof(*n));
6909a747e4fSDavid du Colombier 	n->name = name;
6917dd7cddfSDavid du Colombier 	n->link = namelist;
6927dd7cddfSDavid du Colombier 	namelist = n;
6939a747e4fSDavid du Colombier 	part->ctlname = name;
6947dd7cddfSDavid du Colombier 
6957dd7cddfSDavid du Colombier 	if(fd >= 0)
6967dd7cddfSDavid du Colombier 		print("part %s %lld %lld\n", name, start, end);
6977dd7cddfSDavid du Colombier }
6987dd7cddfSDavid du Colombier 
6997dd7cddfSDavid du Colombier static void
7007dd7cddfSDavid du Colombier freenamelist(void)
7017dd7cddfSDavid du Colombier {
7027dd7cddfSDavid du Colombier 	Name *n, *next;
7037dd7cddfSDavid du Colombier 
7047dd7cddfSDavid du Colombier 	for(n=namelist; n; n=next) {
7057dd7cddfSDavid du Colombier 		next = n->link;
7067dd7cddfSDavid du Colombier 		free(n);
7077dd7cddfSDavid du Colombier 	}
7087dd7cddfSDavid du Colombier 	namelist = nil;
7097dd7cddfSDavid du Colombier }
7107dd7cddfSDavid du Colombier 
7117dd7cddfSDavid du Colombier static void
7127dd7cddfSDavid du Colombier cmdprintctl(Edit *edit, int ctlfd)
7137dd7cddfSDavid du Colombier {
7147dd7cddfSDavid du Colombier 	int i;
7157dd7cddfSDavid du Colombier 
7167dd7cddfSDavid du Colombier 	freenamelist();
7177dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
71880ee5cbfSDavid du Colombier 		plan9print((Dospart*)edit->part[i], -1);
7197dd7cddfSDavid du Colombier 	ctldiff(edit, ctlfd);
7207dd7cddfSDavid du Colombier }
7217dd7cddfSDavid du Colombier 
7227dd7cddfSDavid du Colombier static char*
7237dd7cddfSDavid du Colombier cmdokname(Edit*, char *name)
7247dd7cddfSDavid du Colombier {
72580ee5cbfSDavid du Colombier 	char *q;
72680ee5cbfSDavid du Colombier 
72780ee5cbfSDavid du Colombier 	if(name[0] != 'p' && name[0] != 's')
72880ee5cbfSDavid du Colombier 		return "name must be pN or sN";
72980ee5cbfSDavid du Colombier 
73080ee5cbfSDavid du Colombier 	strtol(name+1, &q, 10);
73180ee5cbfSDavid du Colombier 	if(*q != '\0')
73280ee5cbfSDavid du Colombier 		return "name must be pN or sN";
73380ee5cbfSDavid du Colombier 
7347dd7cddfSDavid du Colombier 	return nil;
7357dd7cddfSDavid du Colombier }
7367dd7cddfSDavid du Colombier 
7377dd7cddfSDavid du Colombier #define GB (1024*1024*1024)
7387dd7cddfSDavid du Colombier #define MB (1024*1024)
7397dd7cddfSDavid du Colombier #define KB (1024)
7407dd7cddfSDavid du Colombier 
7417dd7cddfSDavid du Colombier static void
7427dd7cddfSDavid du Colombier cmdsum(Edit *edit, Part *vp, vlong a, vlong b)
7437dd7cddfSDavid du Colombier {
7447dd7cddfSDavid du Colombier 	char *name, *ty;
7457dd7cddfSDavid du Colombier 	char buf[3];
74680ee5cbfSDavid du Colombier 	char *suf;
7477dd7cddfSDavid du Colombier 	Dospart *p;
74880ee5cbfSDavid du Colombier 	vlong sz, div;
7497dd7cddfSDavid du Colombier 
7507dd7cddfSDavid du Colombier 	p = (Dospart*)vp;
7517dd7cddfSDavid du Colombier 
7527dd7cddfSDavid du Colombier 	buf[0] = p && p->changed ? '\'' : ' ';
7537dd7cddfSDavid du Colombier 	buf[1] = p && (p->active & Active) ? '*' : ' ';
7547dd7cddfSDavid du Colombier 	buf[2] = '\0';
7557dd7cddfSDavid du Colombier 
7567dd7cddfSDavid du Colombier 	name = p ? p->name : "empty";
75780ee5cbfSDavid du Colombier 	ty = p ? typestr0(p->type) : "";
7587dd7cddfSDavid du Colombier 
75980ee5cbfSDavid du Colombier 	sz = (b-a)*edit->disk->secsize*sec2cyl;
76080ee5cbfSDavid du Colombier 	if(sz >= 1*GB){
76180ee5cbfSDavid du Colombier 		suf = "GB";
76280ee5cbfSDavid du Colombier 		div = GB;
76380ee5cbfSDavid du Colombier 	}else if(sz >= 1*MB){
76480ee5cbfSDavid du Colombier 		suf = "MB";
76580ee5cbfSDavid du Colombier 		div = MB;
76680ee5cbfSDavid du Colombier 	}else if(sz >= 1*KB){
76780ee5cbfSDavid du Colombier 		suf = "KB";
76880ee5cbfSDavid du Colombier 		div = KB;
76980ee5cbfSDavid du Colombier 	}else{
77080ee5cbfSDavid du Colombier 		suf = "B ";
77180ee5cbfSDavid du Colombier 		div = 1;
77280ee5cbfSDavid du Colombier 	}
77380ee5cbfSDavid du Colombier 
77480ee5cbfSDavid du Colombier 	if(div == 1)
77580ee5cbfSDavid du Colombier 		print("%s %-12s %*lld %-*lld (%lld cylinders, %lld %s) %s\n", buf, name,
77680ee5cbfSDavid du Colombier 			edit->disk->width, a, edit->disk->width, b, b-a, sz, suf, ty);
77780ee5cbfSDavid du Colombier 	else
77880ee5cbfSDavid du Colombier 		print("%s %-12s %*lld %-*lld (%lld cylinders, %lld.%.2d %s) %s\n", buf, name,
77980ee5cbfSDavid du Colombier 			edit->disk->width, a, edit->disk->width, b,  b-a,
78080ee5cbfSDavid du Colombier 			sz/div, (int)(((sz%div)*100)/div), suf, ty);
7817dd7cddfSDavid du Colombier }
7827dd7cddfSDavid du Colombier 
7837dd7cddfSDavid du Colombier static char*
7847dd7cddfSDavid du Colombier cmdadd(Edit *edit, char *name, vlong start, vlong end)
7857dd7cddfSDavid du Colombier {
78680ee5cbfSDavid du Colombier 	Dospart *p;
7877dd7cddfSDavid du Colombier 
78880ee5cbfSDavid du Colombier 	if(!haveroom(edit, name[0]=='p', start))
78980ee5cbfSDavid du Colombier 		return "no room for partition";
7909a747e4fSDavid du Colombier 	start *= sec2cyl;
7919a747e4fSDavid du Colombier 	end *= sec2cyl;
7926b6b9ac8SDavid du Colombier 	if(start == 0 || name[0] != 'p')
7936b6b9ac8SDavid du Colombier 		start += edit->disk->s;
7949a747e4fSDavid du Colombier 	p = mkpart(name, name[0]=='p', start, end-start, nil);
79580ee5cbfSDavid du Colombier 	p->changed = 1;
79680ee5cbfSDavid du Colombier 	return addpart(edit, p);
7977dd7cddfSDavid du Colombier }
7987dd7cddfSDavid du Colombier 
7997dd7cddfSDavid du Colombier static char*
8007dd7cddfSDavid du Colombier cmddel(Edit *edit, Part *p)
8017dd7cddfSDavid du Colombier {
80280ee5cbfSDavid du Colombier 	return delpart(edit, p);
8037dd7cddfSDavid du Colombier }
8047dd7cddfSDavid du Colombier 
8057dd7cddfSDavid du Colombier static char*
8067dd7cddfSDavid du Colombier cmdwrite(Edit *edit)
8077dd7cddfSDavid du Colombier {
8087dd7cddfSDavid du Colombier 	wrpart(edit);
8097dd7cddfSDavid du Colombier 	return nil;
8107dd7cddfSDavid du Colombier }
8117dd7cddfSDavid du Colombier 
8127dd7cddfSDavid du Colombier static char *help =
8137dd7cddfSDavid du Colombier 	"A name - set partition active\n"
8147dd7cddfSDavid du Colombier 	"P - print table in ctl format\n"
8156b6b9ac8SDavid du Colombier 	"R - restore disk back to initial configuration and exit\n"
8167dd7cddfSDavid du Colombier 	"e - show empty dos partitions\n"
8177dd7cddfSDavid du Colombier 	"t name [type] - set partition type\n";
8187dd7cddfSDavid du Colombier 
8197dd7cddfSDavid du Colombier static char*
8207dd7cddfSDavid du Colombier cmdhelp(Edit*)
8217dd7cddfSDavid du Colombier {
8227dd7cddfSDavid du Colombier 	print("%s\n", help);
8237dd7cddfSDavid du Colombier 	return nil;
8247dd7cddfSDavid du Colombier }
8257dd7cddfSDavid du Colombier 
8267dd7cddfSDavid du Colombier static char*
8277dd7cddfSDavid du Colombier cmdactive(Edit *edit, int nf, char **f)
8287dd7cddfSDavid du Colombier {
8297dd7cddfSDavid du Colombier 	int i;
83080ee5cbfSDavid du Colombier 	Dospart *p, *ip;
8317dd7cddfSDavid du Colombier 
8327dd7cddfSDavid du Colombier 	if(nf != 2)
8337dd7cddfSDavid du Colombier 		return "args";
8347dd7cddfSDavid du Colombier 
8359a747e4fSDavid du Colombier 	if(f[1][0] != 'p')
8369a747e4fSDavid du Colombier 		return "cannot set secondary partition active";
8379a747e4fSDavid du Colombier 
83880ee5cbfSDavid du Colombier 	if((p = (Dospart*)findpart(edit, f[1])) == nil)
83980ee5cbfSDavid du Colombier 		return "unknown partition";
8407dd7cddfSDavid du Colombier 
84180ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
84280ee5cbfSDavid du Colombier 		ip = (Dospart*)edit->part[i];
84380ee5cbfSDavid du Colombier 		if(ip->active & Active) {
84480ee5cbfSDavid du Colombier 			ip->active &= ~Active;
84580ee5cbfSDavid du Colombier 			ip->changed = 1;
8467dd7cddfSDavid du Colombier 			edit->changed = 1;
8477dd7cddfSDavid du Colombier 		}
8487dd7cddfSDavid du Colombier 	}
84980ee5cbfSDavid du Colombier 
8507dd7cddfSDavid du Colombier 	if((p->active & Active) == 0) {
8517dd7cddfSDavid du Colombier 		p->active |= Active;
8527dd7cddfSDavid du Colombier 		p->changed = 1;
8537dd7cddfSDavid du Colombier 		edit->changed = 1;
8547dd7cddfSDavid du Colombier 	}
8557dd7cddfSDavid du Colombier 
8567dd7cddfSDavid du Colombier 	return nil;
8577dd7cddfSDavid du Colombier }
8587dd7cddfSDavid du Colombier 
8597dd7cddfSDavid du Colombier static char*
8607dd7cddfSDavid du Colombier strupr(char *s)
8617dd7cddfSDavid du Colombier {
8627dd7cddfSDavid du Colombier 	char *p;
8637dd7cddfSDavid du Colombier 
8647dd7cddfSDavid du Colombier 	for(p=s; *p; p++)
8657dd7cddfSDavid du Colombier 		*p = toupper(*p);
8667dd7cddfSDavid du Colombier 	return s;
8677dd7cddfSDavid du Colombier }
8687dd7cddfSDavid du Colombier 
8697dd7cddfSDavid du Colombier static void
8707dd7cddfSDavid du Colombier dumplist(void)
8717dd7cddfSDavid du Colombier {
8727dd7cddfSDavid du Colombier 	int i, n;
8737dd7cddfSDavid du Colombier 
8747dd7cddfSDavid du Colombier 	n = 0;
8757dd7cddfSDavid du Colombier 	for(i=0; i<256; i++) {
8767dd7cddfSDavid du Colombier 		if(types[i].desc) {
8777dd7cddfSDavid du Colombier 			print("%-16s", types[i].desc);
8787dd7cddfSDavid du Colombier 			if(n++%4 == 3)
8797dd7cddfSDavid du Colombier 				print("\n");
8807dd7cddfSDavid du Colombier 		}
8817dd7cddfSDavid du Colombier 	}
8827dd7cddfSDavid du Colombier 	if(n%4)
8837dd7cddfSDavid du Colombier 		print("\n");
8847dd7cddfSDavid du Colombier }
8857dd7cddfSDavid du Colombier 
8867dd7cddfSDavid du Colombier static char*
8877dd7cddfSDavid du Colombier cmdtype(Edit *edit, int nf, char **f)
8887dd7cddfSDavid du Colombier {
8897dd7cddfSDavid du Colombier 	char *q;
8907dd7cddfSDavid du Colombier 	Dospart *p;
8917dd7cddfSDavid du Colombier 	int i;
8927dd7cddfSDavid du Colombier 
8937dd7cddfSDavid du Colombier 	if(nf < 2)
8947dd7cddfSDavid du Colombier 		return "args";
8957dd7cddfSDavid du Colombier 
8967dd7cddfSDavid du Colombier 	if((p = (Dospart*)findpart(edit, f[1])) == nil)
8977dd7cddfSDavid du Colombier 		return "unknown partition";
8987dd7cddfSDavid du Colombier 
8997dd7cddfSDavid du Colombier 	if(nf == 2) {
9007dd7cddfSDavid du Colombier 		for(;;) {
9017dd7cddfSDavid du Colombier 			fprint(2, "new partition type [? for list]: ");
9027dd7cddfSDavid du Colombier 			q = getline(edit);
9037dd7cddfSDavid du Colombier 			if(q[0] == '?')
9047dd7cddfSDavid du Colombier 				dumplist();
9057dd7cddfSDavid du Colombier 			else
9067dd7cddfSDavid du Colombier 				break;
9077dd7cddfSDavid du Colombier 		}
9087dd7cddfSDavid du Colombier 	} else
9097dd7cddfSDavid du Colombier 		q = f[2];
9107dd7cddfSDavid du Colombier 
9117dd7cddfSDavid du Colombier 	strupr(q);
9127dd7cddfSDavid du Colombier 	for(i=0; i<256; i++)
9137dd7cddfSDavid du Colombier 		if(types[i].desc && strcmp(types[i].desc, q) == 0)
9147dd7cddfSDavid du Colombier 			break;
9157dd7cddfSDavid du Colombier 	if(i < 256 && p->type != i) {
9167dd7cddfSDavid du Colombier 		p->type = i;
9177dd7cddfSDavid du Colombier 		p->changed = 1;
9187dd7cddfSDavid du Colombier 		edit->changed = 1;
9197dd7cddfSDavid du Colombier 	}
9207dd7cddfSDavid du Colombier 	return nil;
9217dd7cddfSDavid du Colombier }
9227dd7cddfSDavid du Colombier 
9237dd7cddfSDavid du Colombier static char*
9247dd7cddfSDavid du Colombier cmdext(Edit *edit, int nf, char **f)
9257dd7cddfSDavid du Colombier {
9267dd7cddfSDavid du Colombier 	switch(f[0][0]) {
9277dd7cddfSDavid du Colombier 	case 'A':
9287dd7cddfSDavid du Colombier 		return cmdactive(edit, nf, f);
9297dd7cddfSDavid du Colombier 	case 't':
9307dd7cddfSDavid du Colombier 		return cmdtype(edit, nf, f);
93180ee5cbfSDavid du Colombier 	case 'R':
93280ee5cbfSDavid du Colombier 		recover(edit);
93380ee5cbfSDavid du Colombier 		return nil;
9347dd7cddfSDavid du Colombier 	default:
9357dd7cddfSDavid du Colombier 		return "unknown command";
9367dd7cddfSDavid du Colombier 	}
9377dd7cddfSDavid du Colombier }
9387dd7cddfSDavid du Colombier 
93980ee5cbfSDavid du Colombier static int
9409a747e4fSDavid du Colombier Dfmt(Fmt *f)
94180ee5cbfSDavid du Colombier {
94280ee5cbfSDavid du Colombier 	char buf[60];
94380ee5cbfSDavid du Colombier 	uchar *p;
94480ee5cbfSDavid du Colombier 	int c, h, s;
94580ee5cbfSDavid du Colombier 
9469a747e4fSDavid du Colombier 	p = va_arg(f->args, uchar*);
94780ee5cbfSDavid du Colombier 	h = p[0];
94880ee5cbfSDavid du Colombier 	c = p[2];
94980ee5cbfSDavid du Colombier 	c |= (p[1]&0xC0)<<2;
95080ee5cbfSDavid du Colombier 	s = (p[1] & 0x3F);
95180ee5cbfSDavid du Colombier 
95280ee5cbfSDavid du Colombier 	sprint(buf, "%d/%d/%d", c, h, s);
9539a747e4fSDavid du Colombier 	return fmtstrcpy(f, buf);
95480ee5cbfSDavid du Colombier }
95580ee5cbfSDavid du Colombier 
95680ee5cbfSDavid du Colombier static void
95780ee5cbfSDavid du Colombier writechs(Disk *disk, uchar *p, vlong lba)
95880ee5cbfSDavid du Colombier {
95980ee5cbfSDavid du Colombier 	int c, h, s;
96080ee5cbfSDavid du Colombier 
96180ee5cbfSDavid du Colombier 	s = lba % disk->s;
96280ee5cbfSDavid du Colombier 	h = (lba / disk->s) % disk->h;
96380ee5cbfSDavid du Colombier 	c = lba / (disk->s * disk->h);
96480ee5cbfSDavid du Colombier 
96580ee5cbfSDavid du Colombier 	if(c >= 1024) {
96680ee5cbfSDavid du Colombier 		c = 1023;
96780ee5cbfSDavid du Colombier 		h = disk->h - 1;
96880ee5cbfSDavid du Colombier 		s = disk->s - 1;
96980ee5cbfSDavid du Colombier 	}
97080ee5cbfSDavid du Colombier 
97180ee5cbfSDavid du Colombier 	p[0] = h;
97280ee5cbfSDavid du Colombier 	p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0);
97380ee5cbfSDavid du Colombier 	p[2] = c;
97480ee5cbfSDavid du Colombier }
97580ee5cbfSDavid du Colombier 
97680ee5cbfSDavid du Colombier static void
9779a747e4fSDavid du Colombier wrtentry(Disk *disk, Tentry *tp, int type, u32int xbase, u32int lba, u32int end)
97880ee5cbfSDavid du Colombier {
97980ee5cbfSDavid du Colombier 	tp->type = type;
9809a747e4fSDavid du Colombier 	writechs(disk, &tp->starth, lba);
9819a747e4fSDavid du Colombier 	writechs(disk, &tp->endh, end-1);
9829a747e4fSDavid du Colombier 	putle32(tp->xlba, lba-xbase);
9839a747e4fSDavid du Colombier 	putle32(tp->xsize, end-lba);
98480ee5cbfSDavid du Colombier }
98580ee5cbfSDavid du Colombier 
98680ee5cbfSDavid du Colombier static int
9879a747e4fSDavid du Colombier wrextend(Edit *edit, int i, vlong xbase, vlong startlba, vlong *endlba)
98880ee5cbfSDavid du Colombier {
98980ee5cbfSDavid du Colombier 	int ni;
99080ee5cbfSDavid du Colombier 	Table table;
99180ee5cbfSDavid du Colombier 	Tentry *tp, *ep;
99280ee5cbfSDavid du Colombier 	Dospart *p;
99380ee5cbfSDavid du Colombier 	Disk *disk;
99480ee5cbfSDavid du Colombier 
9959a747e4fSDavid du Colombier 	if(i == edit->npart){
9969a747e4fSDavid du Colombier 		*endlba = edit->disk->secs;
9979a747e4fSDavid du Colombier 	Finish:
9989a747e4fSDavid du Colombier 		if(startlba < *endlba){
9999a747e4fSDavid du Colombier 			disk = edit->disk;
10009a747e4fSDavid du Colombier 			diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset);
10019a747e4fSDavid du Colombier 			tp = table.entry;
10029a747e4fSDavid du Colombier 			ep = tp+NTentry;
10039a747e4fSDavid du Colombier 			for(; tp<ep; tp++)
10049a747e4fSDavid du Colombier 				memset(tp, 0, sizeof *tp);
10059a747e4fSDavid du Colombier 			table.magic[0] = Magic0;
10069a747e4fSDavid du Colombier 			table.magic[1] = Magic1;
10079a747e4fSDavid du Colombier 
10089a747e4fSDavid du Colombier 			if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0)
10099a747e4fSDavid du Colombier 				recover(edit);
10109a747e4fSDavid du Colombier 		}
101180ee5cbfSDavid du Colombier 		return i;
10129a747e4fSDavid du Colombier 	}
101380ee5cbfSDavid du Colombier 
101480ee5cbfSDavid du Colombier 	p = (Dospart*)edit->part[i];
10159a747e4fSDavid du Colombier 	if(p->primary){
10169a747e4fSDavid du Colombier 		*endlba = (vlong)p->start*sec2cyl;
10179a747e4fSDavid du Colombier 		goto Finish;
10189a747e4fSDavid du Colombier 	}
101980ee5cbfSDavid du Colombier 
102080ee5cbfSDavid du Colombier 	disk = edit->disk;
10219a747e4fSDavid du Colombier 	diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset);
102280ee5cbfSDavid du Colombier 	tp = table.entry;
102380ee5cbfSDavid du Colombier 	ep = tp+NTentry;
102480ee5cbfSDavid du Colombier 
10259a747e4fSDavid du Colombier 	ni = wrextend(edit, i+1, xbase, p->end*sec2cyl, endlba);
102680ee5cbfSDavid du Colombier 
102780ee5cbfSDavid du Colombier 	*tp = p->Tentry;
10289a747e4fSDavid du Colombier 	wrtentry(disk, tp, p->type, startlba, startlba+disk->s, p->end*sec2cyl);
102980ee5cbfSDavid du Colombier 	tp++;
103080ee5cbfSDavid du Colombier 
10319a747e4fSDavid du Colombier 	if(p->end*sec2cyl != *endlba){
103280ee5cbfSDavid du Colombier 		memset(tp, 0, sizeof *tp);
10339a747e4fSDavid du Colombier 		wrtentry(disk, tp, TypeEXTENDED, xbase, p->end*sec2cyl, *endlba);
103480ee5cbfSDavid du Colombier 		tp++;
103580ee5cbfSDavid du Colombier 	}
103680ee5cbfSDavid du Colombier 
103780ee5cbfSDavid du Colombier 	for(; tp<ep; tp++)
103880ee5cbfSDavid du Colombier 		memset(tp, 0, sizeof *tp);
103980ee5cbfSDavid du Colombier 
104080ee5cbfSDavid du Colombier 	table.magic[0] = Magic0;
104180ee5cbfSDavid du Colombier 	table.magic[1] = Magic1;
104280ee5cbfSDavid du Colombier 
10439a747e4fSDavid du Colombier 	if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0)
104480ee5cbfSDavid du Colombier 		recover(edit);
104580ee5cbfSDavid du Colombier 	return ni;
104680ee5cbfSDavid du Colombier }
104780ee5cbfSDavid du Colombier 
104880ee5cbfSDavid du Colombier static void
104980ee5cbfSDavid du Colombier wrpart(Edit *edit)
105080ee5cbfSDavid du Colombier {
10519a747e4fSDavid du Colombier 	int i, ni, t;
105280ee5cbfSDavid du Colombier 	Table table;
105380ee5cbfSDavid du Colombier 	Tentry *tp, *ep;
105480ee5cbfSDavid du Colombier 	Disk *disk;
105580ee5cbfSDavid du Colombier 	vlong s, endlba;
105680ee5cbfSDavid du Colombier 	Dospart *p;
105780ee5cbfSDavid du Colombier 
105880ee5cbfSDavid du Colombier 	disk = edit->disk;
105980ee5cbfSDavid du Colombier 
106080ee5cbfSDavid du Colombier 	diskread(disk, &table, sizeof table, mbroffset, Toffset);
106180ee5cbfSDavid du Colombier 
106280ee5cbfSDavid du Colombier 	tp = table.entry;
106380ee5cbfSDavid du Colombier 	ep = tp+NTentry;
106480ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart && tp<ep; ) {
106580ee5cbfSDavid du Colombier 		p = (Dospart*)edit->part[i];
106680ee5cbfSDavid du Colombier 		if(p->start == 0)
106780ee5cbfSDavid du Colombier 			s = disk->s;
106880ee5cbfSDavid du Colombier 		else
106980ee5cbfSDavid du Colombier 			s = p->start*sec2cyl;
107080ee5cbfSDavid du Colombier 		if(p->primary) {
107180ee5cbfSDavid du Colombier 			*tp = p->Tentry;
10729a747e4fSDavid du Colombier 			wrtentry(disk, tp, p->type, 0, s, p->end*sec2cyl);
107380ee5cbfSDavid du Colombier 			tp++;
107480ee5cbfSDavid du Colombier 			i++;
107580ee5cbfSDavid du Colombier 		} else {
10769a747e4fSDavid du Colombier 			ni = wrextend(edit, i, p->start*sec2cyl, p->start*sec2cyl, &endlba);
107780ee5cbfSDavid du Colombier 			memset(tp, 0, sizeof *tp);
10789a747e4fSDavid du Colombier 			if(endlba >= 1024*sec2cyl)
10799a747e4fSDavid du Colombier 				t = TypeEXTHUGE;
10809a747e4fSDavid du Colombier 			else
10819a747e4fSDavid du Colombier 				t = TypeEXTENDED;
10829a747e4fSDavid du Colombier 			wrtentry(disk, tp, t, 0, s, endlba);
108380ee5cbfSDavid du Colombier 			tp++;
108480ee5cbfSDavid du Colombier 			i = ni;
108580ee5cbfSDavid du Colombier 		}
108680ee5cbfSDavid du Colombier 	}
108780ee5cbfSDavid du Colombier 	for(; tp<ep; tp++)
108880ee5cbfSDavid du Colombier 		memset(tp, 0, sizeof(*tp));
108980ee5cbfSDavid du Colombier 
109080ee5cbfSDavid du Colombier 	if(i != edit->npart)
109180ee5cbfSDavid du Colombier 		sysfatal("cannot happen #1");
109280ee5cbfSDavid du Colombier 
109380ee5cbfSDavid du Colombier 	if(diskwrite(disk, &table, sizeof table, mbroffset, Toffset) < 0)
109480ee5cbfSDavid du Colombier 		recover(edit);
109580ee5cbfSDavid du Colombier 
109680ee5cbfSDavid du Colombier 	/* bring parts up to date */
109780ee5cbfSDavid du Colombier 	freenamelist();
109880ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
109980ee5cbfSDavid du Colombier 		plan9print((Dospart*)edit->part[i], -1);
110080ee5cbfSDavid du Colombier 
110180ee5cbfSDavid du Colombier 	if(ctldiff(edit, disk->ctlfd) < 0)
110280ee5cbfSDavid du Colombier 		fprint(2, "?warning: partitions could not be updated in devsd\n");
110380ee5cbfSDavid du Colombier }
1104