xref: /plan9/sys/src/cmd/disk/prep/prep.c (revision b07b71ebe52f4a564e6465b57855883deaa66b1e)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * prep - prepare plan9 disk partition
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 <disk.h>
87dd7cddfSDavid du Colombier #include "edit.h"
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier enum {
119a747e4fSDavid du Colombier 	Maxpath = 128,
127dd7cddfSDavid du Colombier };
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier static int	blank;
157dd7cddfSDavid du Colombier static int	file;
16dc5a79c1SDavid du Colombier static int	doautox;
177dd7cddfSDavid du Colombier static int	printflag;
187dd7cddfSDavid du Colombier static Part	**opart;
197dd7cddfSDavid du Colombier static int	nopart;
207dd7cddfSDavid du Colombier static char	*osecbuf;
217dd7cddfSDavid du Colombier static char	*secbuf;
227dd7cddfSDavid du Colombier static int	rdonly;
237dd7cddfSDavid du Colombier static int	dowrite;
247dd7cddfSDavid du Colombier static int	docache;
2559cc4ca5SDavid du Colombier static int	donvram;
267dd7cddfSDavid du Colombier 
27dc5a79c1SDavid du Colombier static void	autoxpart(Edit*);
287dd7cddfSDavid du Colombier static Part	*mkpart(char*, vlong, vlong, int);
297dd7cddfSDavid du Colombier static void	rdpart(Edit*);
307dd7cddfSDavid du Colombier static void	wrpart(Edit*);
317dd7cddfSDavid du Colombier static void	checkfat(Disk*);
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier static void 	cmdsum(Edit*, Part*, vlong, vlong);
347dd7cddfSDavid du Colombier static char 	*cmdadd(Edit*, char*, vlong, vlong);
357dd7cddfSDavid du Colombier static char 	*cmddel(Edit*, Part*);
367dd7cddfSDavid du Colombier static char 	*cmdokname(Edit*, char*);
377dd7cddfSDavid du Colombier static char 	*cmdwrite(Edit*);
387dd7cddfSDavid du Colombier static char	*cmdctlprint(Edit*, int, char**);
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier Edit edit = {
417dd7cddfSDavid du Colombier 	.add=	cmdadd,
427dd7cddfSDavid du Colombier 	.del=	cmddel,
437dd7cddfSDavid du Colombier 	.okname=cmdokname,
447dd7cddfSDavid du Colombier 	.sum=	cmdsum,
457dd7cddfSDavid du Colombier 	.write=	cmdwrite,
4680ee5cbfSDavid du Colombier 
4780ee5cbfSDavid du Colombier 	.unit=	"sector",
487dd7cddfSDavid du Colombier };
497dd7cddfSDavid du Colombier 
50dc5a79c1SDavid du Colombier typedef struct Auto Auto;
51dc5a79c1SDavid du Colombier struct Auto
52dc5a79c1SDavid du Colombier {
53dc5a79c1SDavid du Colombier 	char	*name;
54dc5a79c1SDavid du Colombier 	uvlong	min;
55dc5a79c1SDavid du Colombier 	uvlong	max;
56dc5a79c1SDavid du Colombier 	uint	weight;
57dc5a79c1SDavid du Colombier 	uchar	alloc;
58dc5a79c1SDavid du Colombier 	uvlong	size;
59dc5a79c1SDavid du Colombier };
60dc5a79c1SDavid du Colombier 
61eba00c11SDavid du Colombier #define TB (1024LL*GB)
62dc5a79c1SDavid du Colombier #define GB (1024*1024*1024)
63dc5a79c1SDavid du Colombier #define MB (1024*1024)
64dc5a79c1SDavid du Colombier #define KB (1024)
65dc5a79c1SDavid du Colombier 
66dc5a79c1SDavid du Colombier /*
67dc5a79c1SDavid du Colombier  * Order matters -- this is the layout order on disk.
68dc5a79c1SDavid du Colombier  */
69dc5a79c1SDavid du Colombier Auto autox[] =
70dc5a79c1SDavid du Colombier {
71dc5a79c1SDavid du Colombier 	{	"9fat",		10*MB,	100*MB,	10,	},
72dc5a79c1SDavid du Colombier 	{	"nvram",	512,	512,	1,	},
73*b07b71ebSDavid du Colombier 	{	"fscfg",	1024,	8192,	1,	},
74dc5a79c1SDavid du Colombier 	{	"fs",		200*MB,	0,	10,	},
75dc5a79c1SDavid du Colombier 	{	"fossil",	200*MB,	0,	4,	},
76dc5a79c1SDavid du Colombier 	{	"arenas",	500*MB,	0,	20,	},
77dc5a79c1SDavid du Colombier 	{	"isect",	25*MB,	0,	1,	},
7846dd08baSDavid du Colombier 	{	"bloom",	4*MB,	512*MB,	1,	},
7946dd08baSDavid du Colombier 
80dc5a79c1SDavid du Colombier 	{	"other",	200*MB,	0,	4,	},
81dc5a79c1SDavid du Colombier 	{	"swap",		100*MB,	512*MB,	1,	},
82dc5a79c1SDavid du Colombier 	{	"cache",	50*MB,	1*GB,	2,	},
83dc5a79c1SDavid du Colombier };
84dc5a79c1SDavid du Colombier 
857dd7cddfSDavid du Colombier void
usage(void)867dd7cddfSDavid du Colombier usage(void)
877dd7cddfSDavid du Colombier {
88c39c2eb3SDavid du Colombier 	fprint(2, "usage: disk/prep [-bcfprw] [-a partname]... [-s sectorsize] /dev/sdC0/plan9\n");
897dd7cddfSDavid du Colombier 	exits("usage");
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier void
main(int argc,char ** argv)937dd7cddfSDavid du Colombier main(int argc, char **argv)
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier 	int i;
96dc5a79c1SDavid du Colombier 	char *p;
977dd7cddfSDavid du Colombier 	Disk *disk;
987dd7cddfSDavid du Colombier 	vlong secsize;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	secsize = 0;
1017dd7cddfSDavid du Colombier 	ARGBEGIN{
1027dd7cddfSDavid du Colombier 	case 'a':
103dc5a79c1SDavid du Colombier 		p = EARGF(usage());
104dc5a79c1SDavid du Colombier 		for(i=0; i<nelem(autox); i++){
105dc5a79c1SDavid du Colombier 			if(strcmp(p, autox[i].name) == 0){
106dc5a79c1SDavid du Colombier 				if(autox[i].alloc){
107dc5a79c1SDavid du Colombier 					fprint(2, "you said -a %s more than once.\n", p);
108dc5a79c1SDavid du Colombier 					usage();
109dc5a79c1SDavid du Colombier 				}
110dc5a79c1SDavid du Colombier 				autox[i].alloc = 1;
111dc5a79c1SDavid du Colombier 				break;
112dc5a79c1SDavid du Colombier 			}
113dc5a79c1SDavid du Colombier 		}
114dc5a79c1SDavid du Colombier 		if(i == nelem(autox)){
115c39c2eb3SDavid du Colombier 			fprint(2, "don't know how to create automatic partition %s\n", p);
116dc5a79c1SDavid du Colombier 			usage();
117dc5a79c1SDavid du Colombier 		}
118dc5a79c1SDavid du Colombier 		doautox = 1;
1197dd7cddfSDavid du Colombier 		break;
1207dd7cddfSDavid du Colombier 	case 'b':
1217dd7cddfSDavid du Colombier 		blank++;
1227dd7cddfSDavid du Colombier 		break;
1237dd7cddfSDavid du Colombier 	case 'c':
1247dd7cddfSDavid du Colombier 		docache++;
1257dd7cddfSDavid du Colombier 		break;
1267dd7cddfSDavid du Colombier 	case 'f':
1277dd7cddfSDavid du Colombier 		file++;
1287dd7cddfSDavid du Colombier 		break;
12959cc4ca5SDavid du Colombier 	case 'n':
13059cc4ca5SDavid du Colombier 		donvram++;
13159cc4ca5SDavid du Colombier 		break;
1327dd7cddfSDavid du Colombier 	case 'p':
1337dd7cddfSDavid du Colombier 		printflag++;
1347dd7cddfSDavid du Colombier 		rdonly++;
1357dd7cddfSDavid du Colombier 		break;
1367dd7cddfSDavid du Colombier 	case 'r':
1377dd7cddfSDavid du Colombier 		rdonly++;
1387dd7cddfSDavid du Colombier 		break;
1397dd7cddfSDavid du Colombier 	case 's':
1407dd7cddfSDavid du Colombier 		secsize = atoi(ARGF());
1417dd7cddfSDavid du Colombier 		break;
1427dd7cddfSDavid du Colombier 	case 'w':
1437dd7cddfSDavid du Colombier 		dowrite++;
1447dd7cddfSDavid du Colombier 		break;
1457dd7cddfSDavid du Colombier 	default:
1467dd7cddfSDavid du Colombier 		usage();
1477dd7cddfSDavid du Colombier 	}ARGEND;
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 	if(argc != 1)
1507dd7cddfSDavid du Colombier 		usage();
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier 	disk = opendisk(argv[0], rdonly, file);
153c39c2eb3SDavid du Colombier 	if(disk == nil)
154c39c2eb3SDavid du Colombier 		sysfatal("cannot open disk: %r");
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	if(secsize != 0) {
1577dd7cddfSDavid du Colombier 		disk->secsize = secsize;
1587dd7cddfSDavid du Colombier 		disk->secs = disk->size / secsize;
1597dd7cddfSDavid du Colombier 	}
16080ee5cbfSDavid du Colombier 	edit.end = disk->secs;
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier 	checkfat(disk);
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier 	secbuf = emalloc(disk->secsize+1);
1657dd7cddfSDavid du Colombier 	osecbuf = emalloc(disk->secsize+1);
1667dd7cddfSDavid du Colombier 	edit.disk = disk;
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 	if(blank == 0)
1697dd7cddfSDavid du Colombier 		rdpart(&edit);
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier 	opart = emalloc(edit.npart*sizeof(opart[0]));
1727dd7cddfSDavid du Colombier 
1737dd7cddfSDavid du Colombier 	/* save old partition table */
1747dd7cddfSDavid du Colombier 	for(i=0; i<edit.npart; i++)
1757dd7cddfSDavid du Colombier 		opart[i] = edit.part[i];
1767dd7cddfSDavid du Colombier 	nopart = edit.npart;
1777dd7cddfSDavid du Colombier 
1787dd7cddfSDavid du Colombier 	if(printflag) {
1797dd7cddfSDavid du Colombier 		runcmd(&edit, "P");
1807dd7cddfSDavid du Colombier 		exits(0);
1817dd7cddfSDavid du Colombier 	}
1827dd7cddfSDavid du Colombier 
183dc5a79c1SDavid du Colombier 	if(doautox)
184dc5a79c1SDavid du Colombier 		autoxpart(&edit);
1857dd7cddfSDavid du Colombier 
1867dd7cddfSDavid du Colombier 	if(dowrite) {
18780ee5cbfSDavid du Colombier 		runcmd(&edit, "w");
1887dd7cddfSDavid du Colombier 		exits(0);
1897dd7cddfSDavid du Colombier 	}
1907dd7cddfSDavid du Colombier 
1917dd7cddfSDavid du Colombier 	runcmd(&edit, "p");
1927dd7cddfSDavid du Colombier 	for(;;) {
1937dd7cddfSDavid du Colombier 		fprint(2, ">>> ");
1947dd7cddfSDavid du Colombier 		runcmd(&edit, getline(&edit));
1957dd7cddfSDavid du Colombier 	}
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier static void
cmdsum(Edit * edit,Part * p,vlong a,vlong b)1997dd7cddfSDavid du Colombier cmdsum(Edit *edit, Part *p, vlong a, vlong b)
2007dd7cddfSDavid du Colombier {
2017dd7cddfSDavid du Colombier 	vlong sz, div;
2027dd7cddfSDavid du Colombier 	char *suf, *name;
2037dd7cddfSDavid du Colombier 	char c;
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	c = p && p->changed ? '\'' : ' ';
2067dd7cddfSDavid du Colombier 	name = p ? p->name : "empty";
2077dd7cddfSDavid du Colombier 
2087dd7cddfSDavid du Colombier 	sz = (b-a)*edit->disk->secsize;
209eba00c11SDavid du Colombier 	if(sz >= 1*TB){
210eba00c11SDavid du Colombier 		suf = "TB";
211eba00c11SDavid du Colombier 		div = TB;
212eba00c11SDavid du Colombier 	}else if(sz >= 1*GB){
2137dd7cddfSDavid du Colombier 		suf = "GB";
2147dd7cddfSDavid du Colombier 		div = GB;
21580ee5cbfSDavid du Colombier 	}else if(sz >= 1*MB){
2167dd7cddfSDavid du Colombier 		suf = "MB";
2177dd7cddfSDavid du Colombier 		div = MB;
21880ee5cbfSDavid du Colombier 	}else if(sz >= 1*KB){
2197dd7cddfSDavid du Colombier 		suf = "KB";
2207dd7cddfSDavid du Colombier 		div = KB;
2217dd7cddfSDavid du Colombier 	}else{
222c39c2eb3SDavid du Colombier 		if (sz < 0)
223c39c2eb3SDavid du Colombier 			fprint(2, "%s: negative size!\n", argv0);
2247dd7cddfSDavid du Colombier 		suf = "B ";
2257dd7cddfSDavid du Colombier 		div = 1;
2267dd7cddfSDavid du Colombier 	}
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier 	if(div == 1)
2297dd7cddfSDavid du Colombier 		print("%c %-12s %*lld %-*lld (%lld sectors, %lld %s)\n", c, name,
2307dd7cddfSDavid du Colombier 			edit->disk->width, a, edit->disk->width, b, b-a, sz, suf);
2317dd7cddfSDavid du Colombier 	else
2327dd7cddfSDavid du Colombier 		print("%c %-12s %*lld %-*lld (%lld sectors, %lld.%.2d %s)\n", c, name,
2337dd7cddfSDavid du Colombier 			edit->disk->width, a, edit->disk->width, b, b-a,
23480ee5cbfSDavid du Colombier 			sz/div, (int)(((sz%div)*100)/div), suf);
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier static char*
cmdadd(Edit * edit,char * name,vlong start,vlong end)2387dd7cddfSDavid du Colombier cmdadd(Edit *edit, char *name, vlong start, vlong end)
2397dd7cddfSDavid du Colombier {
24080ee5cbfSDavid du Colombier 	if(start < 2 && strcmp(name, "9fat") != 0)
24180ee5cbfSDavid du Colombier 		return "overlaps with the pbs and/or the partition table";
24280ee5cbfSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	return addpart(edit, mkpart(name, start, end, 1));
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier static char*
cmddel(Edit * edit,Part * p)2477dd7cddfSDavid du Colombier cmddel(Edit *edit, Part *p)
2487dd7cddfSDavid du Colombier {
2497dd7cddfSDavid du Colombier 	return delpart(edit, p);
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier static char*
cmdwrite(Edit * edit)2537dd7cddfSDavid du Colombier cmdwrite(Edit *edit)
2547dd7cddfSDavid du Colombier {
2557dd7cddfSDavid du Colombier 	wrpart(edit);
2567dd7cddfSDavid du Colombier 	return nil;
2577dd7cddfSDavid du Colombier }
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier static char isfrog[256]={
2607dd7cddfSDavid du Colombier 	/*NUL*/	1, 1, 1, 1, 1, 1, 1, 1,
2617dd7cddfSDavid du Colombier 	/*BKS*/	1, 1, 1, 1, 1, 1, 1, 1,
2627dd7cddfSDavid du Colombier 	/*DLE*/	1, 1, 1, 1, 1, 1, 1, 1,
2637dd7cddfSDavid du Colombier 	/*CAN*/	1, 1, 1, 1, 1, 1, 1, 1,
2647dd7cddfSDavid du Colombier 	[' ']	1,
2657dd7cddfSDavid du Colombier 	['/']	1,
2667dd7cddfSDavid du Colombier 	[0x7f]	1,
2677dd7cddfSDavid du Colombier };
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier static char*
cmdokname(Edit *,char * elem)2707dd7cddfSDavid du Colombier cmdokname(Edit*, char *elem)
2717dd7cddfSDavid du Colombier {
2729a747e4fSDavid du Colombier 	for(; *elem; elem++)
2737dd7cddfSDavid du Colombier 		if(isfrog[*(uchar*)elem])
2747dd7cddfSDavid du Colombier 			return "bad character in name";
2757dd7cddfSDavid du Colombier 	return nil;
2767dd7cddfSDavid du Colombier }
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier static Part*
mkpart(char * name,vlong start,vlong end,int changed)2797dd7cddfSDavid du Colombier mkpart(char *name, vlong start, vlong end, int changed)
2807dd7cddfSDavid du Colombier {
2817dd7cddfSDavid du Colombier 	Part *p;
2827dd7cddfSDavid du Colombier 
2837dd7cddfSDavid du Colombier 	p = emalloc(sizeof(*p));
2849a747e4fSDavid du Colombier 	p->name = estrdup(name);
2859a747e4fSDavid du Colombier 	p->ctlname = estrdup(name);
2867dd7cddfSDavid du Colombier 	p->start = start;
2877dd7cddfSDavid du Colombier 	p->end = end;
2887dd7cddfSDavid du Colombier 	p->changed = changed;
2897dd7cddfSDavid du Colombier 	return p;
2907dd7cddfSDavid du Colombier }
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier /* plan9 partition is first sector of the disk */
2937dd7cddfSDavid du Colombier static void
rdpart(Edit * edit)2947dd7cddfSDavid du Colombier rdpart(Edit *edit)
2957dd7cddfSDavid du Colombier {
2967dd7cddfSDavid du Colombier 	int i, nline, nf, waserr;
2977dd7cddfSDavid du Colombier 	vlong a, b;
298eba00c11SDavid du Colombier 	char *line[128];
2997dd7cddfSDavid du Colombier 	char *f[5];
3007dd7cddfSDavid du Colombier 	char *err;
3017dd7cddfSDavid du Colombier 	Disk *disk;
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier 	disk = edit->disk;
3047dd7cddfSDavid du Colombier 	seek(disk->fd, disk->secsize, 0);
3057dd7cddfSDavid du Colombier 	if(readn(disk->fd, osecbuf, disk->secsize) != disk->secsize)
3067dd7cddfSDavid du Colombier 		return;
3077dd7cddfSDavid du Colombier 	osecbuf[disk->secsize] = '\0';
3087dd7cddfSDavid du Colombier 	memmove(secbuf, osecbuf, disk->secsize+1);
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier 	if(strncmp(secbuf, "part", 4) != 0){
3117dd7cddfSDavid du Colombier 		fprint(2, "no plan9 partition table found\n");
3127dd7cddfSDavid du Colombier 		return;
3137dd7cddfSDavid du Colombier 	}
3147dd7cddfSDavid du Colombier 
3157dd7cddfSDavid du Colombier 	waserr = 0;
3167dd7cddfSDavid du Colombier 	nline = getfields(secbuf, line, nelem(line), 1, "\n");
3177dd7cddfSDavid du Colombier 	for(i=0; i<nline; i++){
3187dd7cddfSDavid du Colombier 		if(strncmp(line[i], "part", 4) != 0) {
3197dd7cddfSDavid du Colombier 		Error:
3207dd7cddfSDavid du Colombier 			if(waserr == 0)
3217dd7cddfSDavid du Colombier 				fprint(2, "syntax error reading partition\n");
3227dd7cddfSDavid du Colombier 			waserr = 1;
3237dd7cddfSDavid du Colombier 			continue;
3247dd7cddfSDavid du Colombier 		}
3257dd7cddfSDavid du Colombier 
3267dd7cddfSDavid du Colombier 		nf = getfields(line[i], f, nelem(f), 1, " \t\r");
3277dd7cddfSDavid du Colombier 		if(nf != 4 || strcmp(f[0], "part") != 0)
3287dd7cddfSDavid du Colombier 			goto Error;
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 		a = strtoll(f[2], 0, 0);
3317dd7cddfSDavid du Colombier 		b = strtoll(f[3], 0, 0);
3327dd7cddfSDavid du Colombier 		if(a >= b)
3337dd7cddfSDavid du Colombier 			goto Error;
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier 		if(err = addpart(edit, mkpart(f[1], a, b, 0))) {
3367dd7cddfSDavid du Colombier 			fprint(2, "?%s: not continuing\n", err);
3377dd7cddfSDavid du Colombier 			exits("partition");
3387dd7cddfSDavid du Colombier 		}
3397dd7cddfSDavid du Colombier 	}
3407dd7cddfSDavid du Colombier }
3417dd7cddfSDavid du Colombier 
3427dd7cddfSDavid du Colombier static vlong
min(vlong a,vlong b)3437dd7cddfSDavid du Colombier min(vlong a, vlong b)
3447dd7cddfSDavid du Colombier {
3457dd7cddfSDavid du Colombier 	if(a < b)
3467dd7cddfSDavid du Colombier 		return a;
3477dd7cddfSDavid du Colombier 	return b;
3487dd7cddfSDavid du Colombier }
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier static void
autoxpart(Edit * edit)351dc5a79c1SDavid du Colombier autoxpart(Edit *edit)
3527dd7cddfSDavid du Colombier {
353dc5a79c1SDavid du Colombier 	int i, totw, futz;
354dc5a79c1SDavid du Colombier 	vlong secs, secsize, s;
3557dd7cddfSDavid du Colombier 	char *err;
3567dd7cddfSDavid du Colombier 
3577dd7cddfSDavid du Colombier 	if(edit->npart > 0) {
358dc5a79c1SDavid du Colombier 		if(doautox)
3597dd7cddfSDavid du Colombier 			fprint(2, "partitions already exist; not repartitioning\n");
3607dd7cddfSDavid du Colombier 		return;
3617dd7cddfSDavid du Colombier 	}
3627dd7cddfSDavid du Colombier 
3637dd7cddfSDavid du Colombier 	secs = edit->disk->secs;
3647dd7cddfSDavid du Colombier 	secsize = edit->disk->secsize;
365dc5a79c1SDavid du Colombier 	for(;;){
366dc5a79c1SDavid du Colombier 		/* compute total weights */
367dc5a79c1SDavid du Colombier 		totw = 0;
368dc5a79c1SDavid du Colombier 		for(i=0; i<nelem(autox); i++){
369dc5a79c1SDavid du Colombier 			if(autox[i].alloc==0 || autox[i].size)
370dc5a79c1SDavid du Colombier 				continue;
371dc5a79c1SDavid du Colombier 			totw += autox[i].weight;
372dc5a79c1SDavid du Colombier 		}
373dc5a79c1SDavid du Colombier 		if(totw == 0)
374dc5a79c1SDavid du Colombier 			break;
3757dd7cddfSDavid du Colombier 
376dc5a79c1SDavid du Colombier 		if(secs <= 0){
377dc5a79c1SDavid du Colombier 			fprint(2, "ran out of disk space during autoxpartition.\n");
378dc5a79c1SDavid du Colombier 			return;
379dc5a79c1SDavid du Colombier 		}
3807dd7cddfSDavid du Colombier 
381dc5a79c1SDavid du Colombier 		/* assign any minimums for small disks */
382dc5a79c1SDavid du Colombier 		futz = 0;
383dc5a79c1SDavid du Colombier 		for(i=0; i<nelem(autox); i++){
384dc5a79c1SDavid du Colombier 			if(autox[i].alloc==0 || autox[i].size)
385dc5a79c1SDavid du Colombier 				continue;
386dc5a79c1SDavid du Colombier 			s = (secs*autox[i].weight)/totw;
387dc5a79c1SDavid du Colombier 			if(s < autox[i].min/secsize){
388dc5a79c1SDavid du Colombier 				autox[i].size = autox[i].min/secsize;
389dc5a79c1SDavid du Colombier 				secs -= autox[i].size;
390dc5a79c1SDavid du Colombier 				futz = 1;
391dc5a79c1SDavid du Colombier 				break;
392dc5a79c1SDavid du Colombier 			}
393dc5a79c1SDavid du Colombier 		}
394dc5a79c1SDavid du Colombier 		if(futz)
395dc5a79c1SDavid du Colombier 			continue;
396dc5a79c1SDavid du Colombier 
397dc5a79c1SDavid du Colombier 		/* assign any maximums for big disks */
398dc5a79c1SDavid du Colombier 		futz = 0;
399dc5a79c1SDavid du Colombier 		for(i=0; i<nelem(autox); i++){
400dc5a79c1SDavid du Colombier 			if(autox[i].alloc==0 || autox[i].size)
401dc5a79c1SDavid du Colombier 				continue;
402dc5a79c1SDavid du Colombier 			s = (secs*autox[i].weight)/totw;
403dc5a79c1SDavid du Colombier 			if(autox[i].max && s > autox[i].max/secsize){
404dc5a79c1SDavid du Colombier 				autox[i].size = autox[i].max/secsize;
405dc5a79c1SDavid du Colombier 				secs -= autox[i].size;
406dc5a79c1SDavid du Colombier 				futz = 1;
407dc5a79c1SDavid du Colombier 				break;
408dc5a79c1SDavid du Colombier 			}
409dc5a79c1SDavid du Colombier 		}
410dc5a79c1SDavid du Colombier 		if(futz)
411dc5a79c1SDavid du Colombier 			continue;
412dc5a79c1SDavid du Colombier 
413dc5a79c1SDavid du Colombier 		/* finally, assign partition sizes according to weights */
414dc5a79c1SDavid du Colombier 		for(i=0; i<nelem(autox); i++){
415dc5a79c1SDavid du Colombier 			if(autox[i].alloc==0 || autox[i].size)
416dc5a79c1SDavid du Colombier 				continue;
417dc5a79c1SDavid du Colombier 			s = (secs*autox[i].weight)/totw;
418dc5a79c1SDavid du Colombier 			autox[i].size = s;
419dc5a79c1SDavid du Colombier 
420dc5a79c1SDavid du Colombier 			/* use entire disk even in face of rounding errors */
421dc5a79c1SDavid du Colombier 			secs -= autox[i].size;
422dc5a79c1SDavid du Colombier 			totw -= autox[i].weight;
423dc5a79c1SDavid du Colombier 		}
424dc5a79c1SDavid du Colombier 	}
425dc5a79c1SDavid du Colombier 
426dc5a79c1SDavid du Colombier 	for(i=0; i<nelem(autox); i++)
427f2baf03bSDavid du Colombier 		if(autox[i].alloc)
428f2baf03bSDavid du Colombier 			print("%s %llud\n", autox[i].name, autox[i].size);
429dc5a79c1SDavid du Colombier 
430dc5a79c1SDavid du Colombier 	s = 0;
431dc5a79c1SDavid du Colombier 	for(i=0; i<nelem(autox); i++){
432dc5a79c1SDavid du Colombier 		if(autox[i].alloc == 0)
433dc5a79c1SDavid du Colombier 			continue;
434dc5a79c1SDavid du Colombier 		if(err = addpart(edit, mkpart(autox[i].name, s, s+autox[i].size, 1)))
435dc5a79c1SDavid du Colombier 			fprint(2, "addpart %s: %s\n", autox[i].name, err);
436dc5a79c1SDavid du Colombier 		s += autox[i].size;
437dc5a79c1SDavid du Colombier 	}
4387dd7cddfSDavid du Colombier }
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier static void
restore(Edit * edit,int ctlfd)4417dd7cddfSDavid du Colombier restore(Edit *edit, int ctlfd)
4427dd7cddfSDavid du Colombier {
4437dd7cddfSDavid du Colombier 	int i;
4447dd7cddfSDavid du Colombier 	vlong offset;
4457dd7cddfSDavid du Colombier 
4467dd7cddfSDavid du Colombier 	offset = edit->disk->offset;
4477dd7cddfSDavid du Colombier 	fprint(2, "attempting to restore partitions to previous state\n");
4487dd7cddfSDavid du Colombier 	if(seek(edit->disk->wfd, edit->disk->secsize, 0) != 0){
4497dd7cddfSDavid du Colombier 		fprint(2, "cannot restore: error seeking on disk\n");
4507dd7cddfSDavid du Colombier 		exits("inconsistent");
4517dd7cddfSDavid du Colombier 	}
4527dd7cddfSDavid du Colombier 
4537dd7cddfSDavid du Colombier 	if(write(edit->disk->wfd, osecbuf, edit->disk->secsize) != edit->disk->secsize){
4547dd7cddfSDavid du Colombier 		fprint(2, "cannot restore: couldn't write old partition table to disk\n");
4557dd7cddfSDavid du Colombier 		exits("inconsistent");
4567dd7cddfSDavid du Colombier 	}
4577dd7cddfSDavid du Colombier 
4587dd7cddfSDavid du Colombier 	if(ctlfd >= 0){
4597dd7cddfSDavid du Colombier 		for(i=0; i<edit->npart; i++)
4607dd7cddfSDavid du Colombier 			fprint(ctlfd, "delpart %s", edit->part[i]->name);
4617dd7cddfSDavid du Colombier 		for(i=0; i<nopart; i++){
4627dd7cddfSDavid du Colombier 			if(fprint(ctlfd, "part %s %lld %lld", opart[i]->name, opart[i]->start+offset, opart[i]->end+offset) < 0){
4637dd7cddfSDavid du Colombier 				fprint(2, "restored disk partition table but not kernel; reboot\n");
4647dd7cddfSDavid du Colombier 				exits("inconsistent");
4657dd7cddfSDavid du Colombier 			}
4667dd7cddfSDavid du Colombier 		}
4677dd7cddfSDavid du Colombier 	}
4687dd7cddfSDavid du Colombier 	exits("restored");
4697dd7cddfSDavid du Colombier }
4707dd7cddfSDavid du Colombier 
4717dd7cddfSDavid du Colombier static void
wrpart(Edit * edit)4727dd7cddfSDavid du Colombier wrpart(Edit *edit)
4737dd7cddfSDavid du Colombier {
4747dd7cddfSDavid du Colombier 	int i, n;
4757dd7cddfSDavid du Colombier 	Disk *disk;
4767dd7cddfSDavid du Colombier 
4777dd7cddfSDavid du Colombier 	disk = edit->disk;
4787dd7cddfSDavid du Colombier 
4797dd7cddfSDavid du Colombier 	memset(secbuf, 0, disk->secsize);
4807dd7cddfSDavid du Colombier 	n = 0;
4817dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
4827dd7cddfSDavid du Colombier 		n += snprint(secbuf+n, disk->secsize-n, "part %s %lld %lld\n",
4837dd7cddfSDavid du Colombier 			edit->part[i]->name, edit->part[i]->start, edit->part[i]->end);
4847dd7cddfSDavid du Colombier 
4857dd7cddfSDavid du Colombier 	if(seek(disk->wfd, disk->secsize, 0) != disk->secsize){
4867dd7cddfSDavid du Colombier 		fprint(2, "error seeking %d %lld on disk: %r\n", disk->wfd, disk->secsize);
4877dd7cddfSDavid du Colombier 		exits("seek");
4887dd7cddfSDavid du Colombier 	}
4897dd7cddfSDavid du Colombier 
4907dd7cddfSDavid du Colombier 	if(write(disk->wfd, secbuf, disk->secsize) != disk->secsize){
4917dd7cddfSDavid du Colombier 		fprint(2, "error writing partition table to disk\n");
4927dd7cddfSDavid du Colombier 		restore(edit, -1);
4937dd7cddfSDavid du Colombier 	}
4947dd7cddfSDavid du Colombier 
4957dd7cddfSDavid du Colombier 	if(ctldiff(edit, disk->ctlfd) < 0)
4967dd7cddfSDavid du Colombier 		fprint(2, "?warning: partitions could not be updated in devsd\n");
4977dd7cddfSDavid du Colombier }
4987dd7cddfSDavid du Colombier 
4997dd7cddfSDavid du Colombier /*
5007dd7cddfSDavid du Colombier  * Look for a boot sector in sector 1, as would be
5017dd7cddfSDavid du Colombier  * the case if editing /dev/sdC0/data when that
5027dd7cddfSDavid du Colombier  * was really a bootable disk.
5037dd7cddfSDavid du Colombier  */
5047dd7cddfSDavid du Colombier static void
checkfat(Disk * disk)5057dd7cddfSDavid du Colombier checkfat(Disk *disk)
5067dd7cddfSDavid du Colombier {
5077dd7cddfSDavid du Colombier 	uchar buf[32];
5087dd7cddfSDavid du Colombier 
5097dd7cddfSDavid du Colombier 	if(seek(disk->fd, disk->secsize, 0) < 0
5107dd7cddfSDavid du Colombier 	|| read(disk->fd, buf, sizeof(buf)) < sizeof(buf))
5117dd7cddfSDavid du Colombier 		return;
5127dd7cddfSDavid du Colombier 
5137dd7cddfSDavid du Colombier 	if(buf[0] != 0xEB || buf[1] != 0x3C || buf[2] != 0x90)
5147dd7cddfSDavid du Colombier 		return;
5157dd7cddfSDavid du Colombier 
5167dd7cddfSDavid du Colombier 	fprint(2,
5177dd7cddfSDavid du Colombier 		"there's a fat partition where the\n"
5187dd7cddfSDavid du Colombier 		"plan9 partition table would go.\n"
5197dd7cddfSDavid du Colombier 		"if you really want to overwrite it, zero\n"
5207dd7cddfSDavid du Colombier 		"the second sector of the disk and try again\n");
5217dd7cddfSDavid du Colombier 
5227dd7cddfSDavid du Colombier 	exits("fat partition");
5237dd7cddfSDavid du Colombier }
524