xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 31401)
130715Sbostic /*
230715Sbostic  * Copyright (c) 1987 Regents of the University of California.
330715Sbostic  * All rights reserved.  The Berkeley software License Agreement
430715Sbostic  * specifies the terms and conditions for redistribution.
530715Sbostic  */
630715Sbostic 
730418Skarels #ifndef lint
8*31401Skarels static char sccsid[] = "@(#)disklabel.c	5.8 (Berkeley) 06/04/87";
930418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
1030418Skarels #endif
1130418Skarels 
1230418Skarels #include <stdio.h>
1330418Skarels #include <ctype.h>
1430418Skarels #include <sys/param.h>
1530715Sbostic #include <sys/signal.h>
1630418Skarels #include <sys/errno.h>
1730418Skarels #include <sys/file.h>
1830715Sbostic #include <sys/ioctl.h>
1930677Skarels #include <sys/fs.h>
2030715Sbostic #include <strings.h>
2130418Skarels #define DKTYPENAMES
2230418Skarels #include <sys/disklabel.h>
2330418Skarels 
2430418Skarels /*
2530418Skarels  * Disklabel: read and write disklabels.
2630418Skarels  * The label is usually placed on one of the first sectors of the disk.
2730418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
2830418Skarels  * in which case the label is embedded in the bootstrap.
2930418Skarels  * The bootstrap source must leave space at the proper offset
3030418Skarels  * for the label on such machines.
3130418Skarels  */
3230418Skarels 
3330677Skarels #ifdef vax
3430677Skarels #define RAWPARTITION	'c'
3530677Skarels #else
3630677Skarels #define RAWPARTITION	'a'
3730677Skarels #endif
3830677Skarels 
3930677Skarels #ifndef BBSIZE
4030418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
4130677Skarels #endif
4230418Skarels 
4330418Skarels #ifdef vax
4430418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
4530418Skarels #define	BOOTDIR	"/usr/mdec"		/* source of boot binaries */
4630677Skarels #else
4730677Skarels #ifdef lint
4830677Skarels #define	BOOT
4930418Skarels #endif
5030677Skarels #endif
5130418Skarels 
5230715Sbostic #define	DEFEDITOR	"/usr/ucb/vi"
5330715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
5430715Sbostic 
5530418Skarels char	*dkname;
5630715Sbostic #ifdef BOOT
5730418Skarels char	*xxboot;
5830418Skarels char	*bootxx;
5930715Sbostic #endif
6030418Skarels char	*specname;
6130715Sbostic char	tmpfil[] = "/tmp/EdDk.aXXXXXX";
6230418Skarels char	*sprintf();
6330418Skarels 
6430418Skarels extern	int errno;
6530418Skarels char	namebuf[BBSIZE], *np = namebuf;
6630418Skarels char	bootarea[BBSIZE];
6730418Skarels struct	disklabel lab;
6830418Skarels struct	disklabel *readlabel(), *getbootarea();
6930418Skarels 
7030715Sbostic enum	{ READ, WRITE, EDIT, RESTORE } op = READ;
7130418Skarels 
7230677Skarels int	rflag;
7330677Skarels 
7430418Skarels main(argc, argv)
7530418Skarels 	int argc;
7630418Skarels 	char *argv[];
7730418Skarels {
7830715Sbostic 	extern int	optind;
7930418Skarels 	register struct disklabel *lp;
8030715Sbostic 	FILE	*t;
8130715Sbostic 	int	ch, f;
8230715Sbostic 	char *name = 0, *type;
8330418Skarels 
8430715Sbostic 	while ((ch = getopt(argc, argv, "Rerw")) != EOF)
8530715Sbostic 		switch((char)ch) {
8630715Sbostic 			case 'R':
8730715Sbostic 				op = RESTORE;
8830715Sbostic 				break;
8930715Sbostic 			case 'e':
9030715Sbostic 				op = EDIT;
9130715Sbostic 				break;
9230715Sbostic 			case 'r':
9330715Sbostic 				++rflag;
9430715Sbostic 				break;
9530715Sbostic 			case 'w':
9630715Sbostic 				op = WRITE;
9730715Sbostic 				break;
9830715Sbostic 			case '?':
9930715Sbostic 			default:
10030715Sbostic 				usage();
10130715Sbostic 		}
10230715Sbostic 	argc -= optind;
10330715Sbostic 	argv += optind;
10430715Sbostic 	if (argc < 1)
10530715Sbostic 		usage();
10630715Sbostic 
10730715Sbostic 	dkname = argv[0];
10830418Skarels 	if (dkname[0] != '/') {
10930677Skarels 		sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION);
11030418Skarels 		specname = np;
11130418Skarels 		np += strlen(specname) + 1;
11230418Skarels 	} else
11330418Skarels 		specname = dkname;
11430418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
11530418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
11630418Skarels 		sprintf(specname, "/dev/r%s", dkname);
11730418Skarels 		np = namebuf + strlen(specname) + 1;
11830418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
11930418Skarels 	}
12030418Skarels 	if (f < 0)
12130418Skarels 		Perror(specname);
12230418Skarels 
12330715Sbostic 	switch(op) {
12430715Sbostic 	case EDIT:
12530715Sbostic 		if (argc != 1)
12630715Sbostic 			usage();
12730715Sbostic 		lp = readlabel(f, bootarea);
12830715Sbostic 		if (edit(lp))
12930715Sbostic 			writelabel(f, bootarea, lp);
13030715Sbostic 		break;
13130418Skarels 	case READ:
13230715Sbostic 		if (argc != 1)
13330715Sbostic 			usage();
13430715Sbostic 		lp = readlabel(f, (char *)0);
13530418Skarels 		display(stdout, lp);
13630715Sbostic 		(void) checklabel(lp);
13730418Skarels 		break;
13830715Sbostic 	case RESTORE:
13930715Sbostic #ifdef BOOT
14030715Sbostic 		if (argc == 4) {
14130715Sbostic 			xxboot = argv[2];
14230715Sbostic 			bootxx = argv[3];
14330715Sbostic 		}
14430715Sbostic 		else
14530715Sbostic #else
14630715Sbostic 		if (argc != 2)
14730715Sbostic 			usage();
14830715Sbostic #endif
14930715Sbostic 		lab.d_secsize = DEV_BSIZE;			/* XXX */
15030715Sbostic 		lab.d_bbsize = BBSIZE;				/* XXX */
15130715Sbostic 		lp = getbootarea(bootarea, &lab);
15230715Sbostic 		if (!(t = fopen(argv[1],"r")))
15330715Sbostic 			Perror(argv[1]);
154*31401Skarels #ifdef BOOT
155*31401Skarels 		rflag = 1;		/* force bootstrap to be written */
156*31401Skarels #endif
15730715Sbostic 		if (getasciilabel(t, lp))
15830715Sbostic 			writelabel(f, bootarea, lp);
15930418Skarels 		break;
16030418Skarels 	case WRITE:
16130715Sbostic 		type = argv[1];
16230715Sbostic #ifdef BOOT
16330715Sbostic 		if (argc > 5 || argc < 2)
16430715Sbostic 			usage();
16530715Sbostic 		if (argc > 3) {
16630715Sbostic 			bootxx = argv[--argc];
16730715Sbostic 			xxboot = argv[--argc];
16830715Sbostic 		}
16930715Sbostic #else
17030715Sbostic 		if (argc > 3 || argc < 2)
17130715Sbostic 			usage();
17230715Sbostic #endif
17330715Sbostic 		if (argc > 2)
17430715Sbostic 			name = argv[--argc];
17530418Skarels 		makelabel(type, name, &lab);
17630418Skarels 		lp = getbootarea(bootarea, &lab);
17730418Skarels 		*lp = lab;
178*31401Skarels #ifdef BOOT
179*31401Skarels 		rflag = 1;		/* force bootstrap to be written */
180*31401Skarels #endif
18130715Sbostic 		if (checklabel(lp) == 0)
18230715Sbostic 			writelabel(f, bootarea, lp);
18330418Skarels 		break;
18430418Skarels 	}
18530418Skarels 	exit(0);
18630418Skarels }
18730418Skarels 
18830418Skarels makelabel(type, name, lp)
18930418Skarels 	char *type, *name;
19030418Skarels 	register struct disklabel *lp;
19130418Skarels {
19230418Skarels 	register struct disklabel *dp;
19330418Skarels 
19430418Skarels 	dp = getdiskbyname(type);
19530418Skarels 	if (dp == NULL) {
19630418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
19730418Skarels 		exit(1);
19830418Skarels 	}
19930418Skarels 	*lp = *dp;
20030418Skarels 	if (name)
20130715Sbostic 		(void)strncpy(lp->d_name, name, sizeof(lp->d_name));
20230418Skarels }
20330418Skarels 
20430418Skarels writelabel(f, boot, lp)
20530418Skarels 	int f;
20630418Skarels 	char *boot;
20730418Skarels 	register struct disklabel *lp;
20830418Skarels {
20930715Sbostic 	register int i;
21030715Sbostic 	long	lseek();
21130418Skarels 
21230418Skarels 	lp->d_magic = DISKMAGIC;
21330418Skarels 	lp->d_magic2 = DISKMAGIC;
21430418Skarels 	lp->d_checksum = 0;
21530418Skarels 	lp->d_checksum = dkcksum(lp);
21630715Sbostic 	(void)lseek(f, (off_t)0, L_SET);
21730677Skarels 	if (rflag) {
21830677Skarels 		if (write(f, boot, lp->d_bbsize) < lp->d_bbsize)
21930677Skarels 			Perror("write");
22030677Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0)
22130677Skarels 			Perror("ioctl DIOCSDINFO");
22230677Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0)
22330677Skarels 		Perror("ioctl DIOCWDINFO");
22430419Skarels #if vax
22530677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
22630677Skarels 		daddr_t alt;
22730677Skarels 
22830677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
22930677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
23030715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
23130677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
23230677Skarels 				int oerrno = errno;
23330677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
23430677Skarels 				errno = oerrno;
23530677Skarels 				perror("write");
23630677Skarels 			}
23730418Skarels 		}
23830418Skarels 	}
23930419Skarels #endif
24030418Skarels }
24130418Skarels 
24230418Skarels /*
24330418Skarels  * Read disklabel from disk.
24430418Skarels  * If boot is given, need bootstrap too.
24530677Skarels  * If boot not needed, use ioctl to get label
24630677Skarels  * unless -r flag is given.
24730418Skarels  */
24830418Skarels struct disklabel *
24930418Skarels readlabel(f, boot)
25030418Skarels 	int f;
25130418Skarels 	char *boot;
25230418Skarels {
25330418Skarels 	register struct disklabel *lp;
25430677Skarels 	register char *buf;
25530418Skarels 
25630677Skarels 	if (boot)
25730677Skarels 		buf = boot;
25830677Skarels 	else
25930677Skarels 		buf = bootarea;
26030677Skarels 	lp = (struct disklabel *)(buf + LABELOFFSET);
261*31401Skarels 	if (boot || rflag)
262*31401Skarels 		if (read(f, buf, BBSIZE) < BBSIZE)
263*31401Skarels 			Perror(specname);
264*31401Skarels 	if (rflag == 0) {
26530677Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
26630677Skarels 			Perror("ioctl DIOCGDINFO");
26730677Skarels 	} else {
26830677Skarels 		for (lp = (struct disklabel *)buf;
26930677Skarels 		    lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp));
27030677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
27130677Skarels 			if (lp->d_magic == DISKMAGIC &&
27230677Skarels 			    lp->d_magic2 == DISKMAGIC)
27330677Skarels 				break;
27430677Skarels 		if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) ||
27530677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
27630677Skarels 		    dkcksum(lp) != 0) {
27730677Skarels 			fprintf(stderr,
27830418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
27930677Skarels 			exit(1);
28030677Skarels 		}
28130418Skarels 	}
28230418Skarels 	return (lp);
28330418Skarels }
28430418Skarels 
28530418Skarels struct disklabel *
28630418Skarels getbootarea(boot, dp)
28730418Skarels 	char *boot;
28830418Skarels 	register struct disklabel *dp;
28930418Skarels {
29030418Skarels 	struct disklabel *lp;
29130418Skarels 	register char *p;
29230418Skarels 	int b;
29330418Skarels 
29430418Skarels #ifdef BOOT
29530715Sbostic 	char	*dkbasename;
29630715Sbostic 
29730418Skarels 	if (xxboot == NULL) {
29830418Skarels 		dkbasename = np;
29930418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
30030418Skarels 			p = dkname;
30130418Skarels 		else
30230418Skarels 			p++;
30330418Skarels 		while (*p && !isdigit(*p))
30430418Skarels 			*np++ = *p++;
30530418Skarels 		*np++ = '\0';
30630418Skarels 
30730418Skarels 		sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
30830418Skarels 		if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
30930418Skarels 			dkbasename++;
31030418Skarels 		xxboot = np;
31130418Skarels 		sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
31230418Skarels 		np += strlen(xxboot) + 1;
31330418Skarels 
31430418Skarels 		bootxx = np;
31530418Skarels 		sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
31630418Skarels 		np += strlen(bootxx) + 1;
31730418Skarels 	}
31830418Skarels 
31930418Skarels 	b = open(xxboot, O_RDONLY);
32030418Skarels 	if (b < 0)
32130418Skarels 		Perror(xxboot);
32230715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
32330418Skarels 		Perror(xxboot);
32430418Skarels 	close(b);
32530418Skarels 	b = open(bootxx, O_RDONLY);
32630418Skarels 	if (b < 0)
32730418Skarels 		Perror(bootxx);
32830715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
32930418Skarels 		Perror(bootxx);
33030715Sbostic 	(void)close(b);
33130418Skarels #endif
33230418Skarels 
33330418Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
33430418Skarels 	    LABELOFFSET);
33530418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
33630418Skarels 		if (*p) {
33730418Skarels 			fprintf(stderr,
33830418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
33930418Skarels 			exit(2);
34030418Skarels 		}
34130418Skarels 	return (lp);
34230418Skarels }
34330418Skarels 
34430418Skarels display(f, lp)
34530418Skarels 	FILE *f;
34630418Skarels 	register struct disklabel *lp;
34730418Skarels {
34830715Sbostic 	register int i, j;
34930418Skarels 	register struct partition *pp;
35030418Skarels 
35130418Skarels 	fprintf(f, "# %s:\n", specname);
35230418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
35330418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
35430418Skarels 	else
35530418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
35630418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
35730418Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name);
358*31401Skarels 	fprintf(f, "flags:");
35930418Skarels 	if (lp->d_flags & D_REMOVABLE)
360*31401Skarels 		fprintf(f, " removeable");
36130418Skarels 	if (lp->d_flags & D_ECC)
362*31401Skarels 		fprintf(f, " ecc");
36330418Skarels 	if (lp->d_flags & D_BADSECT)
364*31401Skarels 		fprintf(f, " badsect");
36530418Skarels 	fprintf(f, "\n");
36630418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
36730418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
36830418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
36931386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
37030418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
37130715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
37230418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
37330418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
37430418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
37530418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
37630418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
37730418Skarels 	fprintf(f, "drivedata: ");
37830418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
37930418Skarels 		if (lp->d_drivedata[i])
38030418Skarels 			break;
38130418Skarels 	if (i < 0)
38230418Skarels 		i = 0;
38330418Skarels 	for (j = 0; j <= i; j++)
38430418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
38530418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
38630863Skarels 	fprintf(f,
38730863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
38830418Skarels 	pp = lp->d_partitions;
38930418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
39030418Skarels 		if (pp->p_size) {
39130863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
39230863Skarels 			   pp->p_size, pp->p_offset);
39330418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
39430418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
39530418Skarels 			else
39630418Skarels 				fprintf(f, "%8d", pp->p_fstype);
39730863Skarels 			switch (pp->p_fstype) {
39830863Skarels 
39930863Skarels 			case FS_UNUSED:				/* XXX */
40030863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
40130863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
40230863Skarels 				break;
40330863Skarels 
40430863Skarels 			case FS_BSDFFS:
40530863Skarels 				fprintf(f, "    %5d %5d %5d ",
40630863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
40730863Skarels 				    pp->p_cpg);
40830863Skarels 				break;
40930863Skarels 
41030863Skarels 			default:
41130863Skarels 				fprintf(f, "%20.20s", "");
41230863Skarels 				break;
41330863Skarels 			}
41430418Skarels 			fprintf(f, "\t# (Cyl. %4d",
41530418Skarels 			    pp->p_offset / lp->d_secpercyl);
41630418Skarels 			if (pp->p_offset % lp->d_secpercyl)
41730418Skarels 			    putc('*', f);
41830418Skarels 			else
41930418Skarels 			    putc(' ', f);
42030418Skarels 			fprintf(f, "- %d",
42130418Skarels 			    (pp->p_offset +
42230418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
42330418Skarels 			    lp->d_secpercyl - 1);
42430418Skarels 			if (pp->p_size % lp->d_secpercyl)
42530418Skarels 			    putc('*', f);
42630863Skarels 			fprintf(f, ")\n");
42730418Skarels 		}
42830418Skarels 	}
42930418Skarels }
43030418Skarels 
43130715Sbostic edit(lp)
43230715Sbostic 	struct disklabel *lp;
43330418Skarels {
43430715Sbostic 	register int c;
43530715Sbostic 	struct disklabel label;
43630715Sbostic 	FILE *fd;
43730715Sbostic 	char *mktemp();
43830715Sbostic 
43930715Sbostic 	(void) mktemp(tmpfil);
44030715Sbostic 	fd = fopen(tmpfil, "w");
44130715Sbostic 	if (fd == NULL) {
44230715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
44330715Sbostic 		return (0);
44430715Sbostic 	}
44530715Sbostic 	(void)fchmod(fd, 0600);
44630715Sbostic 	display(fd, lp);
44730715Sbostic 	fclose(fd);
44830715Sbostic 	for (;;) {
44930715Sbostic 		if (!editit())
45030715Sbostic 			break;
45130715Sbostic 		fd = fopen(tmpfil, "r");
45230715Sbostic 		if (fd == NULL) {
45330715Sbostic 			fprintf(stderr, "%s: Can't reopen for reading\n");
45430715Sbostic 			break;
45530715Sbostic 		}
45630863Skarels 		bzero((char *)&label, sizeof(label));
45730715Sbostic 		if (getasciilabel(fd, &label)) {
45830715Sbostic 			*lp = label;
45930715Sbostic 			(void) unlink(tmpfil);
46030715Sbostic 			return (1);
46130715Sbostic 		}
46230715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
46330715Sbostic 		c = getchar();
46430715Sbostic 		if (c != EOF && c != (int)'\n')
46530715Sbostic 			while (getchar() != (int)'\n')
46630715Sbostic 				;
46730715Sbostic 		if  (c == (int)'n')
46830715Sbostic 			break;
46930715Sbostic 	}
47030715Sbostic 	(void) unlink(tmpfil);
47130715Sbostic 	return (0);
47230418Skarels }
47330418Skarels 
47430715Sbostic editit()
47530715Sbostic {
47630715Sbostic 	register int pid, xpid;
47730715Sbostic 	int stat, omask;
47830715Sbostic 	extern char *getenv();
47930418Skarels 
48030715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
48130715Sbostic 	while ((pid = fork()) < 0) {
48230715Sbostic 		extern int errno;
48330715Sbostic 
48430715Sbostic 		if (errno == EPROCLIM) {
48530715Sbostic 			fprintf(stderr, "You have too many processes\n");
48630715Sbostic 			return(0);
48730715Sbostic 		}
48830715Sbostic 		if (errno != EAGAIN) {
48930715Sbostic 			perror("fork");
49030715Sbostic 			return(0);
49130715Sbostic 		}
49230715Sbostic 		sleep(1);
49330715Sbostic 	}
49430715Sbostic 	if (pid == 0) {
49530715Sbostic 		register char *ed;
49630715Sbostic 
49730715Sbostic 		sigsetmask(omask);
49830715Sbostic 		setgid(getgid());
49930715Sbostic 		setuid(getuid());
50030715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
50130715Sbostic 			ed = DEFEDITOR;
50230715Sbostic 		execlp(ed, ed, tmpfil, 0);
50330715Sbostic 		perror(ed);
50430715Sbostic 		exit(1);
50530715Sbostic 	}
50630715Sbostic 	while ((xpid = wait(&stat)) >= 0)
50730715Sbostic 		if (xpid == pid)
50830715Sbostic 			break;
50930715Sbostic 	sigsetmask(omask);
51030715Sbostic 	return(!stat);
51130715Sbostic }
51230715Sbostic 
51330715Sbostic char *
51430715Sbostic skip(cp)
51530715Sbostic 	register char *cp;
51630715Sbostic {
51730715Sbostic 
51830715Sbostic 	while (*cp != '\0' && isspace(*cp))
51930715Sbostic 		cp++;
52030715Sbostic 	if (*cp == '\0' || *cp == '#')
52130715Sbostic 		return ((char *)NULL);
52230715Sbostic 	return (cp);
52330715Sbostic }
52430715Sbostic 
52530715Sbostic char *
52630715Sbostic word(cp)
52730715Sbostic 	register char *cp;
52830715Sbostic {
52930715Sbostic 	register char c;
53030715Sbostic 
531*31401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
532*31401Skarels 		cp++;
53330715Sbostic 	if ((c = *cp) != '\0') {
53430715Sbostic 		*cp++ = '\0';
53530715Sbostic 		if (c != '#')
53630715Sbostic 			return (skip(cp));
53730715Sbostic 	}
53830715Sbostic 	return ((char *)NULL);
53930715Sbostic }
54030715Sbostic 
54130418Skarels /*
54230418Skarels  * Read an ascii label in from fd f,
54330418Skarels  * in the same format as that put out by display(),
54430418Skarels  * and fill in lp.
54530418Skarels  */
54630418Skarels getasciilabel(f, lp)
54730715Sbostic 	FILE	*f;
54830418Skarels 	register struct disklabel *lp;
54930418Skarels {
55030715Sbostic 	register char **cpp, *cp;
55130863Skarels 	register struct partition *pp;
55230715Sbostic 	char *tp, *s, line[BUFSIZ];
55330715Sbostic 	int v, lineno = 0, errors = 0;
55430715Sbostic 
55530715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
55630715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
55730715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
55830715Sbostic 		lineno++;
55930715Sbostic 		if (cp = index(line,'\n'))
56030715Sbostic 			*cp = '\0';
56130715Sbostic 		cp = skip(line);
56230715Sbostic 		if (cp == NULL)
56330715Sbostic 			continue;
56430715Sbostic 		tp = index(cp, ':');
56530715Sbostic 		if (tp == NULL) {
56630715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
56730715Sbostic 			errors++;
56830715Sbostic 			continue;
56930715Sbostic 		}
57030715Sbostic 		*tp++ = '\0', tp = skip(tp);
57130715Sbostic 		if (streq(cp, "type")) {
57230715Sbostic 			if (tp == NULL)
57330715Sbostic 				tp = "unknown";
57430715Sbostic 			cpp = dktypenames;
57530715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
57630715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
57730715Sbostic 					lp->d_type = cpp - dktypenames;
57830715Sbostic 					goto next;
57930715Sbostic 				}
58030715Sbostic 			v = atoi(tp);
58130715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
58230715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
58330715Sbostic 				    "Warning, unknown disk type", v);
58430715Sbostic 			lp->d_type = v;
58530715Sbostic 			continue;
58630715Sbostic 		}
58730715Sbostic 		if (streq(cp, "flags")) {
58831386Skarels 			for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) {
58930715Sbostic 				if (streq(cp, "removeable"))
59030715Sbostic 					v |= D_REMOVABLE;
59130715Sbostic 				else if (streq(cp, "ecc"))
59230715Sbostic 					v |= D_ECC;
59330715Sbostic 				else if (streq(cp, "badsect"))
59430715Sbostic 					v |= D_BADSECT;
59530715Sbostic 				else {
59630715Sbostic 					fprintf(stderr,
59730715Sbostic 					    "line %d: %s: bad flag\n",
59830715Sbostic 					    lineno, cp);
59930715Sbostic 					errors++;
60030715Sbostic 				}
60130715Sbostic 			}
60230715Sbostic 			lp->d_flags = v;
60330715Sbostic 			continue;
60430715Sbostic 		}
60530715Sbostic 		if (streq(cp, "drivedata")) {
60630715Sbostic 			register int i;
60730715Sbostic 
60831386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
60930715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
61031386Skarels 				tp = word(cp);
61130715Sbostic 			}
61230715Sbostic 			continue;
61330715Sbostic 		}
61430715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
61530863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
61630715Sbostic 				fprintf(stderr,
61730715Sbostic 				    "line %d: bad # of partitions\n", lineno);
61830863Skarels 				lp->d_npartitions = MAXPARTITIONS;
61930863Skarels 				errors++;
62030863Skarels 			} else
62130715Sbostic 				lp->d_npartitions = v;
62230715Sbostic 			continue;
62330715Sbostic 		}
62430715Sbostic 		if (tp == NULL)
62530715Sbostic 			tp = "";
62630715Sbostic 		if (streq(cp, "disk")) {
62730715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
62830715Sbostic 			continue;
62930715Sbostic 		}
63030715Sbostic 		if (streq(cp, "label")) {
63130715Sbostic 			strncpy(lp->d_name, tp, sizeof (lp->d_name));
63230715Sbostic 			continue;
63330715Sbostic 		}
63430715Sbostic 		if (streq(cp, "bytes/sector")) {
63530715Sbostic 			v = atoi(tp);
63630715Sbostic 			if (v <= 0 || (v % 512) != 0) {
63730715Sbostic 				fprintf(stderr,
63830715Sbostic 				    "line %d: %s: bad sector size\n",
63930715Sbostic 				    lineno, tp);
64030715Sbostic 				errors++;
64130715Sbostic 			} else
64230715Sbostic 				lp->d_secsize = v;
64330715Sbostic 			continue;
64430715Sbostic 		}
64530715Sbostic 		if (streq(cp, "sectors/track")) {
64630715Sbostic 			v = atoi(tp);
64730715Sbostic 			if (v <= 0) {
64830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
64930715Sbostic 				    lineno, tp, cp);
65030715Sbostic 				errors++;
65130715Sbostic 			} else
65230715Sbostic 				lp->d_nsectors = v;
65330715Sbostic 			continue;
65430715Sbostic 		}
65531386Skarels 		if (streq(cp, "sectors/cylinder")) {
65631386Skarels 			v = atoi(tp);
65731386Skarels 			if (v <= 0) {
65831386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
65931386Skarels 				    lineno, tp, cp);
66031386Skarels 				errors++;
66131386Skarels 			} else
66231386Skarels 				lp->d_secpercyl = v;
66331386Skarels 			continue;
66431386Skarels 		}
66530715Sbostic 		if (streq(cp, "tracks/cylinder")) {
66630715Sbostic 			v = atoi(tp);
66730715Sbostic 			if (v <= 0) {
66830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
66930715Sbostic 				    lineno, tp, cp);
67030715Sbostic 				errors++;
67130715Sbostic 			} else
67230715Sbostic 				lp->d_ntracks = v;
67330715Sbostic 			continue;
67430715Sbostic 		}
67530715Sbostic 		if (streq(cp, "cylinders")) {
67630715Sbostic 			v = atoi(tp);
67730715Sbostic 			if (v <= 0) {
67830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
67930715Sbostic 				    lineno, tp, cp);
68030715Sbostic 				errors++;
68130715Sbostic 			} else
68230715Sbostic 				lp->d_ncylinders = v;
68330715Sbostic 			continue;
68430715Sbostic 		}
68530715Sbostic 		if (streq(cp, "rpm")) {
68630715Sbostic 			v = atoi(tp);
68730715Sbostic 			if (v <= 0) {
68830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
68930715Sbostic 				    lineno, tp, cp);
69030715Sbostic 				errors++;
69130715Sbostic 			} else
69230715Sbostic 				lp->d_rpm = v;
69330715Sbostic 			continue;
69430715Sbostic 		}
69530715Sbostic 		if (streq(cp, "interleave")) {
69630715Sbostic 			v = atoi(tp);
69730715Sbostic 			if (v <= 0) {
69830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
69930715Sbostic 				    lineno, tp, cp);
70030715Sbostic 				errors++;
70130715Sbostic 			} else
70230715Sbostic 				lp->d_interleave = v;
70330715Sbostic 			continue;
70430715Sbostic 		}
70530715Sbostic 		if (streq(cp, "trackskew")) {
70630715Sbostic 			v = atoi(tp);
70730715Sbostic 			if (v < 0) {
70830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
70930715Sbostic 				    lineno, tp, cp);
71030715Sbostic 				errors++;
71130715Sbostic 			} else
71230715Sbostic 				lp->d_trackskew = v;
71330715Sbostic 			continue;
71430715Sbostic 		}
71530715Sbostic 		if (streq(cp, "cylinderskew")) {
71630715Sbostic 			v = atoi(tp);
71730715Sbostic 			if (v < 0) {
71830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
71930715Sbostic 				    lineno, tp, cp);
72030715Sbostic 				errors++;
72130715Sbostic 			} else
72230715Sbostic 				lp->d_cylskew = v;
72330715Sbostic 			continue;
72430715Sbostic 		}
72530715Sbostic 		if (streq(cp, "headswitch")) {
72630715Sbostic 			v = atoi(tp);
72730715Sbostic 			if (v < 0) {
72830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
72930715Sbostic 				    lineno, tp, cp);
73030715Sbostic 				errors++;
73130715Sbostic 			} else
73230715Sbostic 				lp->d_headswitch = v;
73330715Sbostic 			continue;
73430715Sbostic 		}
73530715Sbostic 		if (streq(cp, "track-to-track seek")) {
73630715Sbostic 			v = atoi(tp);
73730715Sbostic 			if (v < 0) {
73830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
73930715Sbostic 				    lineno, tp, cp);
74030715Sbostic 				errors++;
74130715Sbostic 			} else
74230715Sbostic 				lp->d_trkseek = v;
74330715Sbostic 			continue;
74430715Sbostic 		}
74530715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
74630863Skarels 			unsigned part = *cp - 'a';
74730715Sbostic 
74830863Skarels 			if (part > lp->d_npartitions) {
74930715Sbostic 				fprintf(stderr,
75030715Sbostic 				    "line %d: bad partition name\n", lineno);
75130715Sbostic 				errors++;
75230715Sbostic 				continue;
75330715Sbostic 			}
75430863Skarels 			pp = &lp->d_partitions[part];
75530863Skarels #define NXTNUM(n) { \
75630863Skarels 	cp = tp, tp = word(cp); \
75730863Skarels 	if (tp == NULL) \
75830863Skarels 		tp = cp; \
75930863Skarels 	(n) = atoi(cp); \
76030863Skarels      }
76130863Skarels 
76230863Skarels 			NXTNUM(v);
76330715Sbostic 			if (v < 0) {
76430715Sbostic 				fprintf(stderr,
76530715Sbostic 				    "line %d: %s: bad partition size\n",
76630715Sbostic 				    lineno, cp);
76730715Sbostic 				errors++;
76830715Sbostic 			} else
76930863Skarels 				pp->p_size = v;
77030863Skarels 			NXTNUM(v);
77130715Sbostic 			if (v < 0) {
77230715Sbostic 				fprintf(stderr,
77330715Sbostic 				    "line %d: %s: bad partition offset\n",
77430715Sbostic 				    lineno, cp);
77530715Sbostic 				errors++;
77630715Sbostic 			} else
77730863Skarels 				pp->p_offset = v;
77830715Sbostic 			cp = tp, tp = word(cp);
77930715Sbostic 			cpp = fstypenames;
78030715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
78130715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
78230863Skarels 					pp->p_fstype = cpp - fstypenames;
78330863Skarels 					goto gottype;
78430715Sbostic 				}
78530715Sbostic 			v = atoi(cp);
78630715Sbostic 			if ((unsigned)v >= FSMAXTYPES)
78730715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
78830715Sbostic 				    "Warning, unknown filesystem type", cp);
78930863Skarels 			pp->p_fstype = v;
79030863Skarels 	gottype:
79130863Skarels 
79230863Skarels 			switch (pp->p_fstype) {
79330863Skarels 
79430863Skarels 			case FS_UNUSED:				/* XXX */
79530863Skarels 				NXTNUM(pp->p_fsize);
79630863Skarels 				if (pp->p_fsize == 0)
79730863Skarels 					break;
79830863Skarels 				NXTNUM(v);
79930863Skarels 				pp->p_frag = v / pp->p_fsize;
80030863Skarels 				break;
80130863Skarels 
80230863Skarels 			case FS_BSDFFS:
80330863Skarels 				NXTNUM(pp->p_fsize);
80430863Skarels 				if (pp->p_fsize == 0)
80530863Skarels 					break;
80630863Skarels 				NXTNUM(v);
80730863Skarels 				pp->p_frag = v / pp->p_fsize;
80830863Skarels 				NXTNUM(pp->p_cpg);
80930863Skarels 				break;
81030863Skarels 
81130863Skarels 			default:
81230863Skarels 				break;
81330863Skarels 			}
81430715Sbostic 			continue;
81530715Sbostic 		}
81630715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
81730715Sbostic 		    lineno, cp);
81830715Sbostic 		errors++;
81930715Sbostic 	next:
82030715Sbostic 		;
82130715Sbostic 	}
82230715Sbostic 	errors += checklabel(lp);
82330715Sbostic 	return (errors == 0);
82430418Skarels }
82530418Skarels 
82630715Sbostic /*
82730715Sbostic  * Check disklabel for errors and fill in
82830715Sbostic  * derived fields according to supplied values.
82930715Sbostic  */
83030715Sbostic checklabel(lp)
83130715Sbostic 	register struct disklabel *lp;
83230418Skarels {
83330715Sbostic 	register struct partition *pp;
83430715Sbostic 	int i, errors = 0;
83530715Sbostic 	char part;
83630418Skarels 
83730715Sbostic 	if (lp->d_secsize == 0) {
83830715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
83930715Sbostic 		return (1);
84030715Sbostic 	}
84130715Sbostic 	if (lp->d_nsectors == 0) {
84230715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
84330715Sbostic 		return (1);
84430715Sbostic 	}
84530715Sbostic 	if (lp->d_ntracks == 0) {
84630715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
84730715Sbostic 		return (1);
84830715Sbostic 	}
84930715Sbostic 	if  (lp->d_ncylinders == 0) {
85030715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
85130715Sbostic 		errors++;
85230715Sbostic 	}
85330715Sbostic 	if (lp->d_rpm == 0)
85430715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
85530715Sbostic 	if (lp->d_secpercyl == 0)
85630715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
85730715Sbostic 	if (lp->d_secperunit == 0)
85830715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
85930715Sbostic 	if (lp->d_bbsize == 0) {
86030715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
86130715Sbostic 		errors++;
86230715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
86330715Sbostic 		Warning("boot block size %% sector-size != 0\n");
86430715Sbostic 	if (lp->d_sbsize == 0) {
86530715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
86630715Sbostic 		errors++;
86730715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
86830715Sbostic 		Warning("super block size %% sector-size != 0\n");
86930715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
87030715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
87130715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
87230715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
87330715Sbostic 		part = 'a' + i;
87430715Sbostic 		pp = &lp->d_partitions[i];
87530715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
87630715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
87730715Sbostic 			    part, pp->p_offset);
87830715Sbostic #ifdef notdef
87930715Sbostic 		if (pp->p_size % lp->d_secpercyl)
88030715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
88130715Sbostic 			    part);
88230715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
88330715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
88430715Sbostic 			    part);
88530715Sbostic #endif
88630715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
88730715Sbostic 			fprintf(stderr,
88830715Sbostic 			    "partition %c: offset past end of unit\n", part);
88930715Sbostic 			errors++;
89030715Sbostic 		}
89130715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
89230715Sbostic 			fprintf(stderr,
89330715Sbostic 			    "partition %c: partition extends past end of unit\n",
89430715Sbostic 			    part);
89530715Sbostic 			errors++;
89630715Sbostic 		}
89730715Sbostic 	}
89830715Sbostic 	for (; i < MAXPARTITIONS; i++) {
89930715Sbostic 		part = 'a' + i;
90030715Sbostic 		pp = &lp->d_partitions[i];
90130715Sbostic 		if (pp->p_size || pp->p_offset)
90230715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
90330715Sbostic 			    pp->p_size, pp->p_offset);
90430715Sbostic 	}
90530715Sbostic 	return (errors);
90630715Sbostic }
90730715Sbostic 
90830715Sbostic /*VARARGS1*/
90930715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
91030715Sbostic 	char *fmt;
91130715Sbostic {
91230715Sbostic 
91330715Sbostic 	fprintf(stderr, "Warning, ");
91430715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
91530715Sbostic 	fprintf(stderr, "\n");
91630715Sbostic }
91730715Sbostic 
91830715Sbostic Perror(str)
91930715Sbostic 	char *str;
92030715Sbostic {
92130715Sbostic 	fputs("disklabel: ", stderr); perror(str);
92230418Skarels 	exit(4);
92330418Skarels }
92430715Sbostic 
92530715Sbostic usage()
92630715Sbostic {
92730715Sbostic #ifdef BOOT
92830715Sbostic 	fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n",
92930715Sbostic "usage: disklabel [-r] disk", "(to read label)",
93030715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
93130715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
93230715Sbostic "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)");
93330715Sbostic #else
93430715Sbostic 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
93530715Sbostic "usage: disklabel [-r] disk", "(to read label)",
93630715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
93730715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
93830715Sbostic "or disklabel -R [-r] disk protofile", "(to restore label)");
93930715Sbostic #endif
94030715Sbostic 	exit(1);
94130715Sbostic }
942