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