xref: /plan9/sys/src/cmd/disk/prep/edit.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * disk partition editor
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 char*
127dd7cddfSDavid du Colombier getline(Edit *edit)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier 	static char line[100];
157dd7cddfSDavid du Colombier 	char *p;
167dd7cddfSDavid du Colombier 	int n;
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier 	n = read(0, line, sizeof(line)-1);
197dd7cddfSDavid du Colombier 	if(n <= 0) {
207dd7cddfSDavid du Colombier 		if(edit->changed)
217dd7cddfSDavid du Colombier 			fprint(2, "?warning: changes not written\n");
227dd7cddfSDavid du Colombier 		exits(0);
237dd7cddfSDavid du Colombier 	}
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier 	line[n-1] = '\0';
267dd7cddfSDavid du Colombier 	p = line;
277dd7cddfSDavid du Colombier 	while(isspace(*p))
287dd7cddfSDavid du Colombier 		p++;
297dd7cddfSDavid du Colombier 	return p;
307dd7cddfSDavid du Colombier }
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier Part*
337dd7cddfSDavid du Colombier findpart(Edit *edit, char *name)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier 	int i;
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
387dd7cddfSDavid du Colombier 		if(strcmp(edit->part[i]->name, name) == 0)
397dd7cddfSDavid du Colombier 			return edit->part[i];
407dd7cddfSDavid du Colombier 	return nil;
417dd7cddfSDavid du Colombier }
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier static char*
447dd7cddfSDavid du Colombier okname(Edit *edit, char *name)
457dd7cddfSDavid du Colombier {
467dd7cddfSDavid du Colombier 	int i;
477dd7cddfSDavid du Colombier 	static char msg[100];
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier 	if(name[0] == '\0')
507dd7cddfSDavid du Colombier 		return "partition has no name";
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier 	if(strlen(name) >= NAMELEN)
537dd7cddfSDavid du Colombier 		return "name too long";
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
567dd7cddfSDavid du Colombier 		if(strcmp(name, edit->part[i]->name) == 0) {
577dd7cddfSDavid du Colombier 			sprint(msg, "already have partition with name \"%s\"", name);
587dd7cddfSDavid du Colombier 			return msg;
597dd7cddfSDavid du Colombier 		}
607dd7cddfSDavid du Colombier 	}
617dd7cddfSDavid du Colombier 	return nil;
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier 
647dd7cddfSDavid du Colombier char*
657dd7cddfSDavid du Colombier addpart(Edit *edit, Part *p)
667dd7cddfSDavid du Colombier {
677dd7cddfSDavid du Colombier 	int i;
687dd7cddfSDavid du Colombier 	static char msg[100];
697dd7cddfSDavid du Colombier 	char *err;
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier 	if(err = okname(edit, p->name))
727dd7cddfSDavid du Colombier 		return err;
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
757dd7cddfSDavid du Colombier 		if(p->start < edit->part[i]->end && edit->part[i]->start < p->end) {
767dd7cddfSDavid du Colombier 			sprint(msg, "\"%s\" overlaps with \"%s\"", p->name, edit->part[i]->name);
777dd7cddfSDavid du Colombier 			return msg;
787dd7cddfSDavid du Colombier 		}
797dd7cddfSDavid du Colombier 	}
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	if(edit->npart >= nelem(edit->part))
827dd7cddfSDavid du Colombier 		return "too many partitions";
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier 	edit->part[i=edit->npart++] = p;
857dd7cddfSDavid du Colombier 	for(; i > 0 && p->start < edit->part[i-1]->start; i--) {
867dd7cddfSDavid du Colombier 		edit->part[i] = edit->part[i-1];
877dd7cddfSDavid du Colombier 		edit->part[i-1] = p;
887dd7cddfSDavid du Colombier 	}
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier 	if(p->changed)
917dd7cddfSDavid du Colombier 		edit->changed = 1;
927dd7cddfSDavid du Colombier 	return nil;
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier char*
967dd7cddfSDavid du Colombier delpart(Edit *edit, Part *p)
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier 	int i;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
1017dd7cddfSDavid du Colombier 		if(edit->part[i] == p)
1027dd7cddfSDavid du Colombier 			break;
1037dd7cddfSDavid du Colombier 	assert(i < edit->npart);
1047dd7cddfSDavid du Colombier 	edit->npart--;
1057dd7cddfSDavid du Colombier 	for(; i<edit->npart; i++)
1067dd7cddfSDavid du Colombier 		edit->part[i] = edit->part[i+1];
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier 	edit->changed = 1;
1097dd7cddfSDavid du Colombier 	return nil;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier static char*
1137dd7cddfSDavid du Colombier editdot(Edit *edit, int argc, char **argv)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier 	char *err;
1167dd7cddfSDavid du Colombier 	vlong ndot;
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier 	if(argc == 1) {
1197dd7cddfSDavid du Colombier 		print("\t. %lld\n", edit->dot);
1207dd7cddfSDavid du Colombier 		return nil;
1217dd7cddfSDavid du Colombier 	}
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier 	if(argc > 2)
1247dd7cddfSDavid du Colombier 		return "args";
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier 	if(err = parseexpr(argv[1], edit->dot, edit->disk->secs, edit->disk->secs, &ndot))
1277dd7cddfSDavid du Colombier 		return err;
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier 	edit->dot = ndot;
1307dd7cddfSDavid du Colombier 	return nil;
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier static char*
1347dd7cddfSDavid du Colombier editadd(Edit *edit, int argc, char **argv)
1357dd7cddfSDavid du Colombier {
1367dd7cddfSDavid du Colombier 	char *name, *err, *q;
1377dd7cddfSDavid du Colombier 	static char msg[100];
1387dd7cddfSDavid du Colombier 	vlong start, end, maxend;
1397dd7cddfSDavid du Colombier 	int i;
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier 	if(argc < 2)
1427dd7cddfSDavid du Colombier 		return "args";
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	name = estrdup(argv[1]);
1457dd7cddfSDavid du Colombier 	if((err = okname(edit, name)) || (err = edit->okname(edit, name)))
1467dd7cddfSDavid du Colombier 		return err;
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 	if(argc >= 3)
1497dd7cddfSDavid du Colombier 		q = argv[2];
1507dd7cddfSDavid du Colombier 	else {
1517dd7cddfSDavid du Colombier 		fprint(2, "start sector: ");
1527dd7cddfSDavid du Colombier 		q = getline(edit);
1537dd7cddfSDavid du Colombier 	}
1547dd7cddfSDavid du Colombier 	if(err = parseexpr(q, edit->dot, edit->disk->secs, edit->disk->secs, &start))
1557dd7cddfSDavid du Colombier 		return err;
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier 	if(start < 0 || start >= edit->disk->secs)
1587dd7cddfSDavid du Colombier 		return "start sector out of range";
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier 	for(i=0; i < edit->npart; i++) {
1617dd7cddfSDavid du Colombier 		if(edit->part[i]->start <= start && start < edit->part[i]->end) {
1627dd7cddfSDavid du Colombier 			sprint(msg, "start sector in partition \"%s\"", edit->part[i]->name);
1637dd7cddfSDavid du Colombier 			return msg;
1647dd7cddfSDavid du Colombier 		}
1657dd7cddfSDavid du Colombier 	}
1667dd7cddfSDavid du Colombier 
1677dd7cddfSDavid du Colombier 	maxend = edit->disk->secs;
1687dd7cddfSDavid du Colombier 	for(i=0; i < edit->npart; i++)
1697dd7cddfSDavid du Colombier 		if(start < edit->part[i]->start && edit->part[i]->start < maxend)
1707dd7cddfSDavid du Colombier 			maxend = edit->part[i]->start;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 	if(argc >= 4)
1737dd7cddfSDavid du Colombier 		q = argv[3];
1747dd7cddfSDavid du Colombier 	else {
1757dd7cddfSDavid du Colombier 		fprint(2, "end [%lld..%lld] ", start, maxend);
1767dd7cddfSDavid du Colombier 		q = getline(edit);
1777dd7cddfSDavid du Colombier 	}
1787dd7cddfSDavid du Colombier 	if(err = parseexpr(q, edit->dot, maxend, edit->disk->secs, &end))
1797dd7cddfSDavid du Colombier 		return err;
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier 	if(start == end)
1827dd7cddfSDavid du Colombier 		return "size zero partition";
1837dd7cddfSDavid du Colombier 
1847dd7cddfSDavid du Colombier 	if(end <= start || end > maxend)
1857dd7cddfSDavid du Colombier 		return "end sector out of range";
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	if(err = edit->add(edit, name, start, end))
1887dd7cddfSDavid du Colombier 		return err;
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier 	edit->dot = end;
1917dd7cddfSDavid du Colombier 	return nil;
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier static char*
1957dd7cddfSDavid du Colombier editdel(Edit *edit, int argc, char **argv)
1967dd7cddfSDavid du Colombier {
1977dd7cddfSDavid du Colombier 	Part *p;
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier 	if(argc != 2)
2007dd7cddfSDavid du Colombier 		return "args";
2017dd7cddfSDavid du Colombier 
2027dd7cddfSDavid du Colombier 	if((p = findpart(edit, argv[1])) == nil)
2037dd7cddfSDavid du Colombier 		return "no such partition";
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	return edit->del(edit, p);
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier 
2087dd7cddfSDavid du Colombier static char *helptext =
2097dd7cddfSDavid du Colombier 	". [newdot] - display or set value of dot\n"
210223a736eSDavid du Colombier 	"a name [start [end]] - add partition\n"
2117dd7cddfSDavid du Colombier 	"d name - delete partition\n"
2127dd7cddfSDavid du Colombier 	"h - print help message\n"
2137dd7cddfSDavid du Colombier 	"p - print partition table\n"
2147dd7cddfSDavid du Colombier 	"P - print commands to update sd(3) device\n"
2157dd7cddfSDavid du Colombier 	"w - write partition table\n"
2167dd7cddfSDavid du Colombier 	"q - quit\n";
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier static char*
2197dd7cddfSDavid du Colombier edithelp(Edit *edit, int, char**)
2207dd7cddfSDavid du Colombier {
2217dd7cddfSDavid du Colombier 	print("%s", helptext);
2227dd7cddfSDavid du Colombier 	if(edit->help)
2237dd7cddfSDavid du Colombier 		return edit->help(edit);
2247dd7cddfSDavid du Colombier 	return nil;
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier 
2277dd7cddfSDavid du Colombier static char*
2287dd7cddfSDavid du Colombier editprint(Edit *edit, int argc, char**)
2297dd7cddfSDavid du Colombier {
2307dd7cddfSDavid du Colombier 	vlong lastend;
2317dd7cddfSDavid du Colombier 	int i;
2327dd7cddfSDavid du Colombier 	Part **part;
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier 	if(argc != 1)
2357dd7cddfSDavid du Colombier 		return "args";
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier 	lastend = 0;
2387dd7cddfSDavid du Colombier 	part = edit->part;
2397dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
2407dd7cddfSDavid du Colombier 		if(lastend < part[i]->start)
2417dd7cddfSDavid du Colombier 			edit->sum(edit, nil, lastend, part[i]->start);
2427dd7cddfSDavid du Colombier 		edit->sum(edit, part[i], part[i]->start, part[i]->end);
2437dd7cddfSDavid du Colombier 		lastend = part[i]->end;
2447dd7cddfSDavid du Colombier 	}
2457dd7cddfSDavid du Colombier 	if(lastend < edit->disk->secs)
2467dd7cddfSDavid du Colombier 		edit->sum(edit, nil, lastend, edit->disk->secs);
2477dd7cddfSDavid du Colombier 	return nil;
2487dd7cddfSDavid du Colombier }
2497dd7cddfSDavid du Colombier 
2507dd7cddfSDavid du Colombier char*
2517dd7cddfSDavid du Colombier editwrite(Edit *edit, int argc, char**)
2527dd7cddfSDavid du Colombier {
2537dd7cddfSDavid du Colombier 	int i;
2547dd7cddfSDavid du Colombier 	char *err;
2557dd7cddfSDavid du Colombier 
2567dd7cddfSDavid du Colombier 	if(argc != 1)
2577dd7cddfSDavid du Colombier 		return "args";
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier 	if(edit->disk->rdonly)
2607dd7cddfSDavid du Colombier 		return "read only";
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier 	err = edit->write(edit);
2637dd7cddfSDavid du Colombier 	if(err)
2647dd7cddfSDavid du Colombier 		return err;
2657dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
2667dd7cddfSDavid du Colombier 		edit->part[i]->changed = 0;
2677dd7cddfSDavid du Colombier 	edit->changed = 0;
2687dd7cddfSDavid du Colombier 	return nil;
2697dd7cddfSDavid du Colombier }
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier static char*
2727dd7cddfSDavid du Colombier editquit(Edit *edit, int argc, char**)
2737dd7cddfSDavid du Colombier {
2747dd7cddfSDavid du Colombier 	static int warned;
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 	if(argc != 1) {
2777dd7cddfSDavid du Colombier 		warned = 0;
2787dd7cddfSDavid du Colombier 		return "args";
2797dd7cddfSDavid du Colombier 	}
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier 	if(edit->changed && (!edit->warned || edit->lastcmd != 'q')) {
2827dd7cddfSDavid du Colombier 		edit->warned = 1;
2837dd7cddfSDavid du Colombier 		return "changes unwritten";
2847dd7cddfSDavid du Colombier 	}
2857dd7cddfSDavid du Colombier 
2867dd7cddfSDavid du Colombier 	exits(0);
2877dd7cddfSDavid du Colombier 	return nil;	/* not reached */
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier 
2907dd7cddfSDavid du Colombier char*
2917dd7cddfSDavid du Colombier editctlprint(Edit *edit, int argc, char **)
2927dd7cddfSDavid du Colombier {
2937dd7cddfSDavid du Colombier 	if(argc != 1)
2947dd7cddfSDavid du Colombier 		return "args";
2957dd7cddfSDavid du Colombier 
2967dd7cddfSDavid du Colombier 	if(edit->printctl)
2977dd7cddfSDavid du Colombier 		edit->printctl(edit, 1);
2987dd7cddfSDavid du Colombier 	else
2997dd7cddfSDavid du Colombier 		ctldiff(edit, 1);
3007dd7cddfSDavid du Colombier 	return nil;
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier typedef struct Cmd Cmd;
3047dd7cddfSDavid du Colombier struct Cmd {
3057dd7cddfSDavid du Colombier 	char c;
3067dd7cddfSDavid du Colombier 	char *(*fn)(Edit*, int ,char**);
3077dd7cddfSDavid du Colombier };
3087dd7cddfSDavid du Colombier 
3097dd7cddfSDavid du Colombier Cmd cmds[] = {
3107dd7cddfSDavid du Colombier 	'.',	editdot,
3117dd7cddfSDavid du Colombier 	'a',	editadd,
3127dd7cddfSDavid du Colombier 	'd',	editdel,
3137dd7cddfSDavid du Colombier 	'?',	edithelp,
3147dd7cddfSDavid du Colombier 	'h',	edithelp,
3157dd7cddfSDavid du Colombier 	'P',	editctlprint,
3167dd7cddfSDavid du Colombier 	'p',	editprint,
3177dd7cddfSDavid du Colombier 	'w',	editwrite,
3187dd7cddfSDavid du Colombier 	'q',	editquit,
3197dd7cddfSDavid du Colombier };
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier void
3227dd7cddfSDavid du Colombier runcmd(Edit *edit, char *cmd)
3237dd7cddfSDavid du Colombier {
3247dd7cddfSDavid du Colombier 	char *f[10], *err;
3257dd7cddfSDavid du Colombier 	int i, nf;
3267dd7cddfSDavid du Colombier 
3277dd7cddfSDavid du Colombier 	while(*cmd && isspace(*cmd))
3287dd7cddfSDavid du Colombier 		cmd++;
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 	nf = tokenize(cmd, f, nelem(f));
3317dd7cddfSDavid du Colombier 	if(nf >= 10) {
3327dd7cddfSDavid du Colombier 		fprint(2, "?\n");
3337dd7cddfSDavid du Colombier 		return;
3347dd7cddfSDavid du Colombier 	}
3357dd7cddfSDavid du Colombier 
3367dd7cddfSDavid du Colombier 	if(strlen(f[0]) != 1) {
3377dd7cddfSDavid du Colombier 		fprint(2, "?\n");
3387dd7cddfSDavid du Colombier 		return;
3397dd7cddfSDavid du Colombier 	}
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 	err = nil;
3427dd7cddfSDavid du Colombier 	for(i=0; i<nelem(cmds); i++) {
3437dd7cddfSDavid du Colombier 		if(cmds[i].c == f[0][0]) {
3447dd7cddfSDavid du Colombier 			err = cmds[i].fn(edit, nf, f);
3457dd7cddfSDavid du Colombier 			break;
3467dd7cddfSDavid du Colombier 		}
3477dd7cddfSDavid du Colombier 	}
3487dd7cddfSDavid du Colombier 	if(i == nelem(cmds))
3497dd7cddfSDavid du Colombier 		err = edit->ext(edit, nf, f);
3507dd7cddfSDavid du Colombier 	if(err)
3517dd7cddfSDavid du Colombier 		fprint(2, "?%s\n", err);
3527dd7cddfSDavid du Colombier 	edit->lastcmd = f[0][0];
3537dd7cddfSDavid du Colombier }
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier static Part*
3567dd7cddfSDavid du Colombier ctlmkpart(char *name, vlong start, vlong end, int changed)
3577dd7cddfSDavid du Colombier {
3587dd7cddfSDavid du Colombier 	Part *p;
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier 	p = emalloc(sizeof(*p));
3617dd7cddfSDavid du Colombier 	strcpy(p->name, name);
3627dd7cddfSDavid du Colombier 	strcpy(p->ctlname, name);
3637dd7cddfSDavid du Colombier 	p->start = start;
3647dd7cddfSDavid du Colombier 	p->end = end;
3657dd7cddfSDavid du Colombier 	p->changed = changed;
3667dd7cddfSDavid du Colombier 	return p;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier 
3697dd7cddfSDavid du Colombier static void
3707dd7cddfSDavid du Colombier rdctlpart(Edit *edit)
3717dd7cddfSDavid du Colombier {
3727dd7cddfSDavid du Colombier 	int i, nline, nf;
3737dd7cddfSDavid du Colombier 	char *line[128];
3747dd7cddfSDavid du Colombier 	char buf[4096];
3757dd7cddfSDavid du Colombier 	vlong a, b;
3767dd7cddfSDavid du Colombier 	char *f[5];
3777dd7cddfSDavid du Colombier 	Disk *disk;
3787dd7cddfSDavid du Colombier 
3797dd7cddfSDavid du Colombier 	disk = edit->disk;
3807dd7cddfSDavid du Colombier 	edit->nctlpart = 0;
3817dd7cddfSDavid du Colombier 	seek(disk->ctlfd, 0, 0);
3827dd7cddfSDavid du Colombier 	if(readn(disk->ctlfd, buf, sizeof buf) <= 0) {
3837dd7cddfSDavid du Colombier 		return;
3847dd7cddfSDavid du Colombier 	}
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier 	nline = getfields(buf, line, nelem(line), 1, "\n");
3877dd7cddfSDavid du Colombier 	for(i=0; i<nline; i++){
3887dd7cddfSDavid du Colombier 		if(strncmp(line[i], "part ", 5) != 0)
3897dd7cddfSDavid du Colombier 			continue;
3907dd7cddfSDavid du Colombier 
3917dd7cddfSDavid du Colombier 		nf = getfields(line[i], f, nelem(f), 1, " \t\r");
3927dd7cddfSDavid du Colombier 		if(nf != 4 || strcmp(f[0], "part") != 0)
3937dd7cddfSDavid du Colombier 			break;
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier 		a = strtoll(f[2], 0, 0);
3967dd7cddfSDavid du Colombier 		b = strtoll(f[3], 0, 0);
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier 		if(a >= b)
3997dd7cddfSDavid du Colombier 			break;
4007dd7cddfSDavid du Colombier 
4017dd7cddfSDavid du Colombier 		/* only gather partitions contained in the disk partition we are editing */
4027dd7cddfSDavid du Colombier 		if(a < disk->offset ||  disk->offset+disk->secs < b)
4037dd7cddfSDavid du Colombier 			continue;
4047dd7cddfSDavid du Colombier 
4057dd7cddfSDavid du Colombier 		a -= disk->offset;
4067dd7cddfSDavid du Colombier 		b -= disk->offset;
4077dd7cddfSDavid du Colombier 
4087dd7cddfSDavid du Colombier 		/* the partition we are editing does not count */
4097dd7cddfSDavid du Colombier 		if(strcmp(f[1], disk->part) == 0)
4107dd7cddfSDavid du Colombier 			continue;
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier 		if(edit->nctlpart >= nelem(edit->ctlpart)) {
4137dd7cddfSDavid du Colombier 			fprint(2, "?too many partitions in ctl file\n");
4147dd7cddfSDavid du Colombier 			exits("ctlpart");
4157dd7cddfSDavid du Colombier 		}
4167dd7cddfSDavid du Colombier 		edit->ctlpart[edit->nctlpart++] = ctlmkpart(f[1], a, b, 0);
4177dd7cddfSDavid du Colombier 	}
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier 
4207dd7cddfSDavid du Colombier static int
4217dd7cddfSDavid du Colombier areequiv(Part *p, Part *q)
4227dd7cddfSDavid du Colombier {
4237dd7cddfSDavid du Colombier 	return strcmp(p->ctlname, q->ctlname) == 0
4247dd7cddfSDavid du Colombier 			&& p->start == q->start && p->end == q->end;
4257dd7cddfSDavid du Colombier }
4267dd7cddfSDavid du Colombier 
4277dd7cddfSDavid du Colombier static void
4287dd7cddfSDavid du Colombier unchange(Edit *edit, Part *p)
4297dd7cddfSDavid du Colombier {
4307dd7cddfSDavid du Colombier 	int i;
4317dd7cddfSDavid du Colombier 	Part *q;
4327dd7cddfSDavid du Colombier 
4337dd7cddfSDavid du Colombier 	for(i=0; i<edit->nctlpart; i++) {
4347dd7cddfSDavid du Colombier 		q = edit->ctlpart[i];
4357dd7cddfSDavid du Colombier 		if(p->start <= q->start && q->end <= p->end) {
4367dd7cddfSDavid du Colombier 			q->changed = 0;
4377dd7cddfSDavid du Colombier 		}
4387dd7cddfSDavid du Colombier 	}
4397dd7cddfSDavid du Colombier assert(p->changed == 0);
4407dd7cddfSDavid du Colombier }
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier int
4437dd7cddfSDavid du Colombier ctldiff(Edit *edit, int ctlfd)
4447dd7cddfSDavid du Colombier {
4457dd7cddfSDavid du Colombier 	int i, j, waserr;
4467dd7cddfSDavid du Colombier 	Part *p;
4477dd7cddfSDavid du Colombier 	vlong offset;
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier 	rdctlpart(edit);
4507dd7cddfSDavid du Colombier 
4517dd7cddfSDavid du Colombier 	/* everything is bogus until we prove otherwise */
4527dd7cddfSDavid du Colombier 	for(i=0; i<edit->nctlpart; i++)
4537dd7cddfSDavid du Colombier 		edit->ctlpart[i]->changed = 1;
4547dd7cddfSDavid du Colombier 
4557dd7cddfSDavid du Colombier 	/*
4567dd7cddfSDavid du Colombier 	 * partitions with same info have not changed,
4577dd7cddfSDavid du Colombier 	 * and neither have partitions inside them.
4587dd7cddfSDavid du Colombier 	 */
4597dd7cddfSDavid du Colombier 	for(i=0; i<edit->nctlpart; i++)
4607dd7cddfSDavid du Colombier 		for(j=0; j<edit->npart; j++)
4617dd7cddfSDavid du Colombier 			if(areequiv(edit->ctlpart[i], edit->part[j])) {
4627dd7cddfSDavid du Colombier 				unchange(edit, edit->ctlpart[i]);
4637dd7cddfSDavid du Colombier 				break;
4647dd7cddfSDavid du Colombier 			}
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier 	/*
4677dd7cddfSDavid du Colombier 	 * delete all the changed partitions except data (we'll add them back if necessary)
4687dd7cddfSDavid du Colombier 	 */
4697dd7cddfSDavid du Colombier 	for(i=0; i<edit->nctlpart; i++) {
4707dd7cddfSDavid du Colombier 		p = edit->ctlpart[i];
4717dd7cddfSDavid du Colombier 		if(p->changed)
4727dd7cddfSDavid du Colombier 			fprint(ctlfd, "delpart %s\n", p->ctlname);
4737dd7cddfSDavid du Colombier 	}
4747dd7cddfSDavid du Colombier 
4757dd7cddfSDavid du Colombier 	/*
4767dd7cddfSDavid du Colombier 	 * add all the partitions from the real list;
4777dd7cddfSDavid du Colombier 	 * this is okay since adding a parition with
4787dd7cddfSDavid du Colombier 	 * information identical to what is there is a no-op.
4797dd7cddfSDavid du Colombier 	 */
4807dd7cddfSDavid du Colombier 	waserr = 0;
4817dd7cddfSDavid du Colombier 	offset = edit->disk->offset;
4827dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
4837dd7cddfSDavid du Colombier 		p = edit->part[i];
4847dd7cddfSDavid du Colombier 		if(p->ctlname[0])
4857dd7cddfSDavid du Colombier 			if(fprint(ctlfd, "part %s %lld %lld\n", p->ctlname, offset+p->start, offset+p->end) < 0)
4867dd7cddfSDavid du Colombier 				waserr = -1;
4877dd7cddfSDavid du Colombier 	}
4887dd7cddfSDavid du Colombier 	return waserr;
4897dd7cddfSDavid du Colombier }
490*59cc4ca5SDavid du Colombier 
491*59cc4ca5SDavid du Colombier void*
492*59cc4ca5SDavid du Colombier emalloc(ulong sz)
493*59cc4ca5SDavid du Colombier {
494*59cc4ca5SDavid du Colombier 	void *v;
495*59cc4ca5SDavid du Colombier 
496*59cc4ca5SDavid du Colombier 	v = malloc(sz);
497*59cc4ca5SDavid du Colombier 	if(v == nil)
498*59cc4ca5SDavid du Colombier 		sysfatal("malloc %lud fails\n", sz);
499*59cc4ca5SDavid du Colombier 	memset(v, 0, sz);
500*59cc4ca5SDavid du Colombier 	return v;
501*59cc4ca5SDavid du Colombier }
502*59cc4ca5SDavid du Colombier 
503*59cc4ca5SDavid du Colombier char*
504*59cc4ca5SDavid du Colombier estrdup(char *s)
505*59cc4ca5SDavid du Colombier {
506*59cc4ca5SDavid du Colombier 	s = strdup(s);
507*59cc4ca5SDavid du Colombier 	if(s == nil)
508*59cc4ca5SDavid du Colombier 		sysfatal("strdup (%.10s) fails\n", s);
509*59cc4ca5SDavid du Colombier 	return s;
510*59cc4ca5SDavid du Colombier }
511*59cc4ca5SDavid du Colombier 
512