xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 30715)
1*30715Sbostic /*
2*30715Sbostic  * Copyright (c) 1987 Regents of the University of California.
3*30715Sbostic  * All rights reserved.  The Berkeley software License Agreement
4*30715Sbostic  * specifies the terms and conditions for redistribution.
5*30715Sbostic  */
6*30715Sbostic 
730418Skarels #ifndef lint
8*30715Sbostic static char sccsid[] = "@(#)disklabel.c	5.4 (Berkeley) 04/01/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>
15*30715Sbostic #include <sys/signal.h>
1630418Skarels #include <sys/errno.h>
1730418Skarels #include <sys/file.h>
18*30715Sbostic #include <sys/ioctl.h>
1930677Skarels #include <sys/fs.h>
20*30715Sbostic #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 
52*30715Sbostic #define	DEFEDITOR	"/usr/ucb/vi"
53*30715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
54*30715Sbostic 
5530418Skarels char	*dkname;
56*30715Sbostic #ifdef BOOT
5730418Skarels char	*xxboot;
5830418Skarels char	*bootxx;
59*30715Sbostic #endif
6030418Skarels char	*specname;
61*30715Sbostic 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 
70*30715Sbostic enum	{ READ, WRITE, EDIT, RESTORE } op = READ;
7130418Skarels 
7230677Skarels int	rflag;
7330677Skarels 
7430418Skarels main(argc, argv)
7530418Skarels 	int argc;
7630418Skarels 	char *argv[];
7730418Skarels {
78*30715Sbostic 	extern int	optind;
7930418Skarels 	register struct disklabel *lp;
80*30715Sbostic 	FILE	*t;
81*30715Sbostic 	int	ch, f;
82*30715Sbostic 	char *name = 0, *type;
8330418Skarels 
84*30715Sbostic 	while ((ch = getopt(argc, argv, "Rerw")) != EOF)
85*30715Sbostic 		switch((char)ch) {
86*30715Sbostic 			case 'R':
87*30715Sbostic 				op = RESTORE;
88*30715Sbostic 				break;
89*30715Sbostic 			case 'e':
90*30715Sbostic 				op = EDIT;
91*30715Sbostic 				break;
92*30715Sbostic 			case 'r':
93*30715Sbostic 				++rflag;
94*30715Sbostic 				break;
95*30715Sbostic 			case 'w':
96*30715Sbostic 				op = WRITE;
97*30715Sbostic 				break;
98*30715Sbostic 			case '?':
99*30715Sbostic 			default:
100*30715Sbostic 				usage();
101*30715Sbostic 		}
102*30715Sbostic 	argc -= optind;
103*30715Sbostic 	argv += optind;
104*30715Sbostic 	if (argc < 1)
105*30715Sbostic 		usage();
106*30715Sbostic 
107*30715Sbostic 	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 
123*30715Sbostic 	switch(op) {
124*30715Sbostic 	case EDIT:
125*30715Sbostic 		if (argc != 1)
126*30715Sbostic 			usage();
127*30715Sbostic 		lp = readlabel(f, bootarea);
128*30715Sbostic 		if (edit(lp))
129*30715Sbostic 			writelabel(f, bootarea, lp);
130*30715Sbostic 		break;
13130418Skarels 	case READ:
132*30715Sbostic 		if (argc != 1)
133*30715Sbostic 			usage();
134*30715Sbostic 		lp = readlabel(f, (char *)0);
13530418Skarels 		display(stdout, lp);
136*30715Sbostic 		(void) checklabel(lp);
13730418Skarels 		break;
138*30715Sbostic 	case RESTORE:
139*30715Sbostic #ifdef BOOT
140*30715Sbostic 		if (argc == 4) {
141*30715Sbostic 			xxboot = argv[2];
142*30715Sbostic 			bootxx = argv[3];
143*30715Sbostic 		}
144*30715Sbostic 		else
145*30715Sbostic #else
146*30715Sbostic 		if (argc != 2)
147*30715Sbostic 			usage();
148*30715Sbostic #endif
149*30715Sbostic 		lab.d_secsize = DEV_BSIZE;			/* XXX */
150*30715Sbostic 		lab.d_bbsize = BBSIZE;				/* XXX */
151*30715Sbostic 		lp = getbootarea(bootarea, &lab);
152*30715Sbostic 		if (!(t = fopen(argv[1],"r")))
153*30715Sbostic 			Perror(argv[1]);
154*30715Sbostic 		if (getasciilabel(t, lp))
155*30715Sbostic 			writelabel(f, bootarea, lp);
15630418Skarels 		break;
15730418Skarels 	case WRITE:
158*30715Sbostic 		type = argv[1];
159*30715Sbostic #ifdef BOOT
160*30715Sbostic 		if (argc > 5 || argc < 2)
161*30715Sbostic 			usage();
162*30715Sbostic 		if (argc > 3) {
163*30715Sbostic 			bootxx = argv[--argc];
164*30715Sbostic 			xxboot = argv[--argc];
165*30715Sbostic 		}
166*30715Sbostic #else
167*30715Sbostic #ifdef FIX_FOR_LATER
168*30715Sbostic 		if (argc > 3 || argc < 2)
169*30715Sbostic #endif
170*30715Sbostic 			usage();
171*30715Sbostic #endif
172*30715Sbostic 		if (argc > 2)
173*30715Sbostic 			name = argv[--argc];
17430418Skarels 		makelabel(type, name, &lab);
17530418Skarels 		lp = getbootarea(bootarea, &lab);
17630418Skarels 		*lp = lab;
177*30715Sbostic 		if (checklabel(lp) == 0)
178*30715Sbostic 			writelabel(f, bootarea, lp);
17930418Skarels 		break;
18030418Skarels 	}
18130418Skarels 	exit(0);
18230418Skarels }
18330418Skarels 
18430418Skarels makelabel(type, name, lp)
18530418Skarels 	char *type, *name;
18630418Skarels 	register struct disklabel *lp;
18730418Skarels {
18830418Skarels 	register struct disklabel *dp;
18930418Skarels 
19030418Skarels 	dp = getdiskbyname(type);
19130418Skarels 	if (dp == NULL) {
19230418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
19330418Skarels 		exit(1);
19430418Skarels 	}
19530418Skarels 	*lp = *dp;
19630418Skarels 	if (name)
197*30715Sbostic 		(void)strncpy(lp->d_name, name, sizeof(lp->d_name));
19830418Skarels }
19930418Skarels 
20030418Skarels writelabel(f, boot, lp)
20130418Skarels 	int f;
20230418Skarels 	char *boot;
20330418Skarels 	register struct disklabel *lp;
20430418Skarels {
205*30715Sbostic 	register int i;
206*30715Sbostic 	long	lseek();
20730418Skarels 
20830418Skarels 	lp->d_magic = DISKMAGIC;
20930418Skarels 	lp->d_magic2 = DISKMAGIC;
21030418Skarels 	lp->d_checksum = 0;
21130418Skarels 	lp->d_checksum = dkcksum(lp);
212*30715Sbostic 	(void)lseek(f, (off_t)0, L_SET);
21330677Skarels 	if (rflag) {
21430677Skarels 		if (write(f, boot, lp->d_bbsize) < lp->d_bbsize)
21530677Skarels 			Perror("write");
21630677Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0)
21730677Skarels 			Perror("ioctl DIOCSDINFO");
21830677Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0)
21930677Skarels 		Perror("ioctl DIOCWDINFO");
22030419Skarels #if vax
22130677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
22230677Skarels 		daddr_t alt;
22330677Skarels 
22430677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
22530677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
226*30715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
22730677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
22830677Skarels 				int oerrno = errno;
22930677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
23030677Skarels 				errno = oerrno;
23130677Skarels 				perror("write");
23230677Skarels 			}
23330418Skarels 		}
23430418Skarels 	}
23530419Skarels #endif
23630418Skarels }
23730418Skarels 
23830418Skarels /*
23930418Skarels  * Read disklabel from disk.
24030418Skarels  * If boot is given, need bootstrap too.
24130677Skarels  * If boot not needed, use ioctl to get label
24230677Skarels  * unless -r flag is given.
24330418Skarels  */
24430418Skarels struct disklabel *
24530418Skarels readlabel(f, boot)
24630418Skarels 	int f;
24730418Skarels 	char *boot;
24830418Skarels {
24930418Skarels 	register struct disklabel *lp;
25030677Skarels 	register char *buf;
25130418Skarels 
25230677Skarels 	if (boot)
25330677Skarels 		buf = boot;
25430677Skarels 	else
25530677Skarels 		buf = bootarea;
25630677Skarels 	lp = (struct disklabel *)(buf + LABELOFFSET);
25730677Skarels 	if (rflag == 0 && boot == 0) {
25830677Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
25930677Skarels 			Perror("ioctl DIOCGDINFO");
26030677Skarels 	} else {
26130677Skarels 		if (read(f, buf, BBSIZE) < BBSIZE)
26230677Skarels 			Perror(specname);
26330677Skarels 		for (lp = (struct disklabel *)buf;
26430677Skarels 		    lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp));
26530677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
26630677Skarels 			if (lp->d_magic == DISKMAGIC &&
26730677Skarels 			    lp->d_magic2 == DISKMAGIC)
26830677Skarels 				break;
26930677Skarels 		if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) ||
27030677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
27130677Skarels 		    dkcksum(lp) != 0) {
27230677Skarels 			fprintf(stderr,
27330418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
27430677Skarels 			exit(1);
27530677Skarels 		}
27630418Skarels 	}
27730418Skarels 	return (lp);
27830418Skarels }
27930418Skarels 
28030418Skarels struct disklabel *
28130418Skarels getbootarea(boot, dp)
28230418Skarels 	char *boot;
28330418Skarels 	register struct disklabel *dp;
28430418Skarels {
28530418Skarels 	struct disklabel *lp;
28630418Skarels 	register char *p;
28730418Skarels 	int b;
28830418Skarels 
28930418Skarels #ifdef BOOT
290*30715Sbostic 	char	*dkbasename;
291*30715Sbostic 
29230418Skarels 	if (xxboot == NULL) {
29330418Skarels 		dkbasename = np;
29430418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
29530418Skarels 			p = dkname;
29630418Skarels 		else
29730418Skarels 			p++;
29830418Skarels 		while (*p && !isdigit(*p))
29930418Skarels 			*np++ = *p++;
30030418Skarels 		*np++ = '\0';
30130418Skarels 
30230418Skarels 		sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
30330418Skarels 		if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
30430418Skarels 			dkbasename++;
30530418Skarels 		xxboot = np;
30630418Skarels 		sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
30730418Skarels 		np += strlen(xxboot) + 1;
30830418Skarels 
30930418Skarels 		bootxx = np;
31030418Skarels 		sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
31130418Skarels 		np += strlen(bootxx) + 1;
31230418Skarels 	}
31330418Skarels 
31430418Skarels 	b = open(xxboot, O_RDONLY);
31530418Skarels 	if (b < 0)
31630418Skarels 		Perror(xxboot);
317*30715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
31830418Skarels 		Perror(xxboot);
31930418Skarels 	close(b);
32030418Skarels 	b = open(bootxx, O_RDONLY);
32130418Skarels 	if (b < 0)
32230418Skarels 		Perror(bootxx);
323*30715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
32430418Skarels 		Perror(bootxx);
325*30715Sbostic 	(void)close(b);
32630418Skarels #endif
32730418Skarels 
32830418Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
32930418Skarels 	    LABELOFFSET);
33030418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
33130418Skarels 		if (*p) {
33230418Skarels 			fprintf(stderr,
33330418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
33430418Skarels 			exit(2);
33530418Skarels 		}
33630418Skarels 	return (lp);
33730418Skarels }
33830418Skarels 
33930418Skarels display(f, lp)
34030418Skarels 	FILE *f;
34130418Skarels 	register struct disklabel *lp;
34230418Skarels {
343*30715Sbostic 	register int i, j;
34430418Skarels 	register struct partition *pp;
34530418Skarels 
34630418Skarels 	fprintf(f, "# %s:\n", specname);
34730418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
34830418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
34930418Skarels 	else
35030418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
35130418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
35230418Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name);
35330418Skarels 	fprintf(f, "flags: ");
35430418Skarels 	if (lp->d_flags & D_REMOVABLE)
35530418Skarels 		fprintf(f, "removeable ");
35630418Skarels 	if (lp->d_flags & D_ECC)
35730418Skarels 		fprintf(f, "ecc ");
35830418Skarels 	if (lp->d_flags & D_BADSECT)
35930418Skarels 		fprintf(f, "badsect ");
36030418Skarels 	fprintf(f, "\n");
36130418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
36230418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
36330418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
36430418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
365*30715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
36630418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
36730418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
36830418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
36930418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
37030418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
37130418Skarels 	fprintf(f, "drivedata: ");
37230418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
37330418Skarels 		if (lp->d_drivedata[i])
37430418Skarels 			break;
37530418Skarels 	if (i < 0)
37630418Skarels 		i = 0;
37730418Skarels 	for (j = 0; j <= i; j++)
37830418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
37930418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
38030418Skarels 	fprintf(f, "#\t       size    offset     fstype\n");
38130418Skarels 	pp = lp->d_partitions;
38230418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
38330418Skarels 		fprintf(f, "\t%c: %8d %8d    ", 'a' + i,
38430418Skarels 		   pp->p_size, pp->p_offset);
38530418Skarels 		if (pp->p_size) {
38630418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
38730418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
38830418Skarels 			else
38930418Skarels 				fprintf(f, "%8d", pp->p_fstype);
39030418Skarels 			fprintf(f, "\t# (Cyl. %4d",
39130418Skarels 			    pp->p_offset / lp->d_secpercyl);
39230418Skarels 			if (pp->p_offset % lp->d_secpercyl)
39330418Skarels 			    putc('*', f);
39430418Skarels 			else
39530418Skarels 			    putc(' ', f);
39630418Skarels 			fprintf(f, "- %d",
39730418Skarels 			    (pp->p_offset +
39830418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
39930418Skarels 			    lp->d_secpercyl - 1);
40030418Skarels 			if (pp->p_size % lp->d_secpercyl)
40130418Skarels 			    putc('*', f);
40230418Skarels 			putc(')', f);
40330418Skarels 		}
40430418Skarels 		fprintf(f, "\n");
40530418Skarels 	}
40630418Skarels }
40730418Skarels 
408*30715Sbostic edit(lp)
409*30715Sbostic 	struct disklabel *lp;
41030418Skarels {
411*30715Sbostic 	register int c;
412*30715Sbostic 	struct disklabel label;
413*30715Sbostic 	FILE *fd;
414*30715Sbostic 	char *mktemp();
415*30715Sbostic 
416*30715Sbostic 	(void) mktemp(tmpfil);
417*30715Sbostic 	fd = fopen(tmpfil, "w");
418*30715Sbostic 	if (fd == NULL) {
419*30715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
420*30715Sbostic 		return (0);
421*30715Sbostic 	}
422*30715Sbostic 	(void)fchmod(fd, 0600);
423*30715Sbostic 	display(fd, lp);
424*30715Sbostic 	fclose(fd);
425*30715Sbostic 	for (;;) {
426*30715Sbostic 		if (!editit())
427*30715Sbostic 			break;
428*30715Sbostic 		fd = fopen(tmpfil, "r");
429*30715Sbostic 		if (fd == NULL) {
430*30715Sbostic 			fprintf(stderr, "%s: Can't reopen for reading\n");
431*30715Sbostic 			break;
432*30715Sbostic 		}
433*30715Sbostic 		label = *lp;
434*30715Sbostic 		if (getasciilabel(fd, &label)) {
435*30715Sbostic 			*lp = label;
436*30715Sbostic 			(void) unlink(tmpfil);
437*30715Sbostic 			return (1);
438*30715Sbostic 		}
439*30715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
440*30715Sbostic 		c = getchar();
441*30715Sbostic 		if (c != EOF && c != (int)'\n')
442*30715Sbostic 			while (getchar() != (int)'\n')
443*30715Sbostic 				;
444*30715Sbostic 		if  (c == (int)'n')
445*30715Sbostic 			break;
446*30715Sbostic 	}
447*30715Sbostic 	(void) unlink(tmpfil);
448*30715Sbostic 	return (0);
44930418Skarels }
45030418Skarels 
451*30715Sbostic editit()
452*30715Sbostic {
453*30715Sbostic 	register int pid, xpid;
454*30715Sbostic 	int stat, omask;
455*30715Sbostic 	extern char *getenv();
45630418Skarels 
457*30715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
458*30715Sbostic 	while ((pid = fork()) < 0) {
459*30715Sbostic 		extern int errno;
460*30715Sbostic 
461*30715Sbostic 		if (errno == EPROCLIM) {
462*30715Sbostic 			fprintf(stderr, "You have too many processes\n");
463*30715Sbostic 			return(0);
464*30715Sbostic 		}
465*30715Sbostic 		if (errno != EAGAIN) {
466*30715Sbostic 			perror("fork");
467*30715Sbostic 			return(0);
468*30715Sbostic 		}
469*30715Sbostic 		sleep(1);
470*30715Sbostic 	}
471*30715Sbostic 	if (pid == 0) {
472*30715Sbostic 		register char *ed;
473*30715Sbostic 
474*30715Sbostic 		sigsetmask(omask);
475*30715Sbostic 		setgid(getgid());
476*30715Sbostic 		setuid(getuid());
477*30715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
478*30715Sbostic 			ed = DEFEDITOR;
479*30715Sbostic 		execlp(ed, ed, tmpfil, 0);
480*30715Sbostic 		perror(ed);
481*30715Sbostic 		exit(1);
482*30715Sbostic 	}
483*30715Sbostic 	while ((xpid = wait(&stat)) >= 0)
484*30715Sbostic 		if (xpid == pid)
485*30715Sbostic 			break;
486*30715Sbostic 	sigsetmask(omask);
487*30715Sbostic 	return(!stat);
488*30715Sbostic }
489*30715Sbostic 
490*30715Sbostic char *
491*30715Sbostic skip(cp)
492*30715Sbostic 	register char *cp;
493*30715Sbostic {
494*30715Sbostic 
495*30715Sbostic 	while (*cp != '\0' && isspace(*cp))
496*30715Sbostic 		cp++;
497*30715Sbostic 	if (*cp == '\0' || *cp == '#')
498*30715Sbostic 		return ((char *)NULL);
499*30715Sbostic 	return (cp);
500*30715Sbostic }
501*30715Sbostic 
502*30715Sbostic char *
503*30715Sbostic word(cp)
504*30715Sbostic 	register char *cp;
505*30715Sbostic {
506*30715Sbostic 	register char c;
507*30715Sbostic 
508*30715Sbostic 	while (*cp != '\0' && !isspace(*cp))
509*30715Sbostic 		if (*cp++ == '#')
510*30715Sbostic 			break;
511*30715Sbostic 	if ((c = *cp) != '\0') {
512*30715Sbostic 		*cp++ = '\0';
513*30715Sbostic 		if (c != '#')
514*30715Sbostic 			return (skip(cp));
515*30715Sbostic 	}
516*30715Sbostic 	return ((char *)NULL);
517*30715Sbostic }
518*30715Sbostic 
51930418Skarels /*
52030418Skarels  * Read an ascii label in from fd f,
52130418Skarels  * in the same format as that put out by display(),
52230418Skarels  * and fill in lp.
52330418Skarels  */
52430418Skarels getasciilabel(f, lp)
525*30715Sbostic 	FILE	*f;
52630418Skarels 	register struct disklabel *lp;
52730418Skarels {
528*30715Sbostic 	register char **cpp, *cp;
529*30715Sbostic 	char *tp, *s, line[BUFSIZ];
530*30715Sbostic 	int v, lineno = 0, errors = 0;
531*30715Sbostic 
532*30715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
533*30715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
534*30715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
535*30715Sbostic 		lineno++;
536*30715Sbostic 		if (cp = index(line,'\n'))
537*30715Sbostic 			*cp = '\0';
538*30715Sbostic 		cp = skip(line);
539*30715Sbostic 		if (cp == NULL)
540*30715Sbostic 			continue;
541*30715Sbostic 		tp = index(cp, ':');
542*30715Sbostic 		if (tp == NULL) {
543*30715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
544*30715Sbostic 			errors++;
545*30715Sbostic 			continue;
546*30715Sbostic 		}
547*30715Sbostic 		*tp++ = '\0', tp = skip(tp);
548*30715Sbostic 		if (streq(cp, "type")) {
549*30715Sbostic 			if (tp == NULL)
550*30715Sbostic 				tp = "unknown";
551*30715Sbostic 			cpp = dktypenames;
552*30715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
553*30715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
554*30715Sbostic 					lp->d_type = cpp - dktypenames;
555*30715Sbostic 					goto next;
556*30715Sbostic 				}
557*30715Sbostic 			v = atoi(tp);
558*30715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
559*30715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
560*30715Sbostic 				    "Warning, unknown disk type", v);
561*30715Sbostic 			lp->d_type = v;
562*30715Sbostic 			continue;
563*30715Sbostic 		}
564*30715Sbostic 		if (streq(cp, "flags")) {
565*30715Sbostic 			v = 0;
566*30715Sbostic 			while ((cp = tp) && *cp != '\0') {
567*30715Sbostic 				if (tp = skip(cp)) {
568*30715Sbostic 					*tp++ = '\0';
569*30715Sbostic 					while (*tp && isspace(*tp))
570*30715Sbostic 						tp++;
571*30715Sbostic 				}
572*30715Sbostic 				if (streq(cp, "removeable"))
573*30715Sbostic 					v |= D_REMOVABLE;
574*30715Sbostic 				else if (streq(cp, "ecc"))
575*30715Sbostic 					v |= D_ECC;
576*30715Sbostic 				else if (streq(cp, "badsect"))
577*30715Sbostic 					v |= D_BADSECT;
578*30715Sbostic 				else {
579*30715Sbostic 					fprintf(stderr,
580*30715Sbostic 					    "line %d: %s: bad flag\n",
581*30715Sbostic 					    lineno, cp);
582*30715Sbostic 					errors++;
583*30715Sbostic 				}
584*30715Sbostic 			}
585*30715Sbostic 			lp->d_flags = v;
586*30715Sbostic 			continue;
587*30715Sbostic 		}
588*30715Sbostic 		if (streq(cp, "drivedata")) {
589*30715Sbostic 			register int i;
590*30715Sbostic 
591*30715Sbostic 			for (i = 0;(cp = tp) && *cp != '\0'  && i < NDDATA;) {
592*30715Sbostic 				if (tp = skip(cp)) {
593*30715Sbostic 					*tp++ = '\0';
594*30715Sbostic 					while (*tp != '\0' && isspace(*tp))
595*30715Sbostic 						tp++;
596*30715Sbostic 				}
597*30715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
598*30715Sbostic 			}
599*30715Sbostic 			continue;
600*30715Sbostic 		}
601*30715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
602*30715Sbostic 			if (v == 0 || (unsigned)v > MAXPARTITIONS)
603*30715Sbostic 				fprintf(stderr,
604*30715Sbostic 				    "line %d: bad # of partitions\n", lineno);
605*30715Sbostic 			else
606*30715Sbostic 				lp->d_npartitions = v;
607*30715Sbostic 			continue;
608*30715Sbostic 		}
609*30715Sbostic 		if (tp == NULL)
610*30715Sbostic 			tp = "";
611*30715Sbostic 		if (streq(cp, "disk")) {
612*30715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
613*30715Sbostic 			continue;
614*30715Sbostic 		}
615*30715Sbostic 		if (streq(cp, "label")) {
616*30715Sbostic 			strncpy(lp->d_name, tp, sizeof (lp->d_name));
617*30715Sbostic 			continue;
618*30715Sbostic 		}
619*30715Sbostic 		if (streq(cp, "bytes/sector")) {
620*30715Sbostic 			v = atoi(tp);
621*30715Sbostic 			if (v <= 0 || (v % 512) != 0) {
622*30715Sbostic 				fprintf(stderr,
623*30715Sbostic 				    "line %d: %s: bad sector size\n",
624*30715Sbostic 				    lineno, tp);
625*30715Sbostic 				errors++;
626*30715Sbostic 			} else
627*30715Sbostic 				lp->d_secsize = v;
628*30715Sbostic 			continue;
629*30715Sbostic 		}
630*30715Sbostic 		if (streq(cp, "sectors/track")) {
631*30715Sbostic 			v = atoi(tp);
632*30715Sbostic 			if (v <= 0) {
633*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
634*30715Sbostic 				    lineno, tp, cp);
635*30715Sbostic 				errors++;
636*30715Sbostic 			} else
637*30715Sbostic 				lp->d_nsectors = v;
638*30715Sbostic 			continue;
639*30715Sbostic 		}
640*30715Sbostic 		if (streq(cp, "tracks/cylinder")) {
641*30715Sbostic 			v = atoi(tp);
642*30715Sbostic 			if (v <= 0) {
643*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
644*30715Sbostic 				    lineno, tp, cp);
645*30715Sbostic 				errors++;
646*30715Sbostic 			} else
647*30715Sbostic 				lp->d_ntracks = v;
648*30715Sbostic 			continue;
649*30715Sbostic 		}
650*30715Sbostic 		if (streq(cp, "cylinders")) {
651*30715Sbostic 			v = atoi(tp);
652*30715Sbostic 			if (v <= 0) {
653*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
654*30715Sbostic 				    lineno, tp, cp);
655*30715Sbostic 				errors++;
656*30715Sbostic 			} else
657*30715Sbostic 				lp->d_ncylinders = v;
658*30715Sbostic 			continue;
659*30715Sbostic 		}
660*30715Sbostic 		if (streq(cp, "rpm")) {
661*30715Sbostic 			v = atoi(tp);
662*30715Sbostic 			if (v <= 0) {
663*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
664*30715Sbostic 				    lineno, tp, cp);
665*30715Sbostic 				errors++;
666*30715Sbostic 			} else
667*30715Sbostic 				lp->d_rpm = v;
668*30715Sbostic 			continue;
669*30715Sbostic 		}
670*30715Sbostic 		if (streq(cp, "interleave")) {
671*30715Sbostic 			v = atoi(tp);
672*30715Sbostic 			if (v <= 0) {
673*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
674*30715Sbostic 				    lineno, tp, cp);
675*30715Sbostic 				errors++;
676*30715Sbostic 			} else
677*30715Sbostic 				lp->d_interleave = v;
678*30715Sbostic 			continue;
679*30715Sbostic 		}
680*30715Sbostic 		if (streq(cp, "trackskew")) {
681*30715Sbostic 			v = atoi(tp);
682*30715Sbostic 			if (v < 0) {
683*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
684*30715Sbostic 				    lineno, tp, cp);
685*30715Sbostic 				errors++;
686*30715Sbostic 			} else
687*30715Sbostic 				lp->d_trackskew = v;
688*30715Sbostic 			continue;
689*30715Sbostic 		}
690*30715Sbostic 		if (streq(cp, "cylinderskew")) {
691*30715Sbostic 			v = atoi(tp);
692*30715Sbostic 			if (v < 0) {
693*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
694*30715Sbostic 				    lineno, tp, cp);
695*30715Sbostic 				errors++;
696*30715Sbostic 			} else
697*30715Sbostic 				lp->d_cylskew = v;
698*30715Sbostic 			continue;
699*30715Sbostic 		}
700*30715Sbostic 		if (streq(cp, "headswitch")) {
701*30715Sbostic 			v = atoi(tp);
702*30715Sbostic 			if (v < 0) {
703*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
704*30715Sbostic 				    lineno, tp, cp);
705*30715Sbostic 				errors++;
706*30715Sbostic 			} else
707*30715Sbostic 				lp->d_headswitch = v;
708*30715Sbostic 			continue;
709*30715Sbostic 		}
710*30715Sbostic 		if (streq(cp, "track-to-track seek")) {
711*30715Sbostic 			v = atoi(tp);
712*30715Sbostic 			if (v < 0) {
713*30715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
714*30715Sbostic 				    lineno, tp, cp);
715*30715Sbostic 				errors++;
716*30715Sbostic 			} else
717*30715Sbostic 				lp->d_trkseek = v;
718*30715Sbostic 			continue;
719*30715Sbostic 		}
720*30715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
721*30715Sbostic 			int part = *cp - 'a';
722*30715Sbostic 
723*30715Sbostic 			if ((unsigned)part > MAXPARTITIONS) {
724*30715Sbostic 				fprintf(stderr,
725*30715Sbostic 				    "line %d: bad partition name\n", lineno);
726*30715Sbostic 				errors++;
727*30715Sbostic 				continue;
728*30715Sbostic 			}
729*30715Sbostic 			cp = tp, tp = word(cp);
730*30715Sbostic 			if (tp == NULL)
731*30715Sbostic 				tp = cp;
732*30715Sbostic 			v = atoi(cp);
733*30715Sbostic 			if (v < 0) {
734*30715Sbostic 				fprintf(stderr,
735*30715Sbostic 				    "line %d: %s: bad partition size\n",
736*30715Sbostic 				    lineno, cp);
737*30715Sbostic 				errors++;
738*30715Sbostic 			} else
739*30715Sbostic 				lp->d_partitions[part].p_size = v;
740*30715Sbostic 			cp = tp, tp = word(cp);
741*30715Sbostic 			if (tp == NULL)
742*30715Sbostic 				tp = cp;
743*30715Sbostic 			v = atoi(cp);
744*30715Sbostic 			if (v < 0) {
745*30715Sbostic 				fprintf(stderr,
746*30715Sbostic 				    "line %d: %s: bad partition offset\n",
747*30715Sbostic 				    lineno, cp);
748*30715Sbostic 				errors++;
749*30715Sbostic 			} else
750*30715Sbostic 				lp->d_partitions[part].p_offset = v;
751*30715Sbostic 			cp = tp, tp = word(cp);
752*30715Sbostic 			cpp = fstypenames;
753*30715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
754*30715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
755*30715Sbostic 					lp->d_partitions[part].p_fstype =
756*30715Sbostic 					    cpp - fstypenames;
757*30715Sbostic 					goto next;
758*30715Sbostic 				}
759*30715Sbostic 			v = atoi(cp);
760*30715Sbostic 			if ((unsigned)v >= FSMAXTYPES)
761*30715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
762*30715Sbostic 				    "Warning, unknown filesystem type", cp);
763*30715Sbostic 			lp->d_partitions[part].p_fstype = v;
764*30715Sbostic 			continue;
765*30715Sbostic 		}
766*30715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
767*30715Sbostic 		    lineno, cp);
768*30715Sbostic 		errors++;
769*30715Sbostic 	next:
770*30715Sbostic 		;
771*30715Sbostic 	}
772*30715Sbostic 	errors += checklabel(lp);
773*30715Sbostic 	return (errors == 0);
77430418Skarels }
77530418Skarels 
776*30715Sbostic /*
777*30715Sbostic  * Check disklabel for errors and fill in
778*30715Sbostic  * derived fields according to supplied values.
779*30715Sbostic  */
780*30715Sbostic checklabel(lp)
781*30715Sbostic 	register struct disklabel *lp;
78230418Skarels {
783*30715Sbostic 	register struct partition *pp;
784*30715Sbostic 	int i, errors = 0;
785*30715Sbostic 	char part;
78630418Skarels 
787*30715Sbostic 	if (lp->d_secsize == 0) {
788*30715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
789*30715Sbostic 		return (1);
790*30715Sbostic 	}
791*30715Sbostic 	if (lp->d_nsectors == 0) {
792*30715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
793*30715Sbostic 		return (1);
794*30715Sbostic 	}
795*30715Sbostic 	if (lp->d_ntracks == 0) {
796*30715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
797*30715Sbostic 		return (1);
798*30715Sbostic 	}
799*30715Sbostic 	if  (lp->d_ncylinders == 0) {
800*30715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
801*30715Sbostic 		errors++;
802*30715Sbostic 	}
803*30715Sbostic 	if (lp->d_rpm == 0)
804*30715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
805*30715Sbostic 	if (lp->d_secpercyl == 0)
806*30715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
807*30715Sbostic 	if (lp->d_secperunit == 0)
808*30715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
809*30715Sbostic 	if (lp->d_bbsize == 0) {
810*30715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
811*30715Sbostic 		errors++;
812*30715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
813*30715Sbostic 		Warning("boot block size %% sector-size != 0\n");
814*30715Sbostic 	if (lp->d_sbsize == 0) {
815*30715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
816*30715Sbostic 		errors++;
817*30715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
818*30715Sbostic 		Warning("super block size %% sector-size != 0\n");
819*30715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
820*30715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
821*30715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
822*30715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
823*30715Sbostic 		part = 'a' + i;
824*30715Sbostic 		pp = &lp->d_partitions[i];
825*30715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
826*30715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
827*30715Sbostic 			    part, pp->p_offset);
828*30715Sbostic #ifdef notdef
829*30715Sbostic 		if (pp->p_size % lp->d_secpercyl)
830*30715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
831*30715Sbostic 			    part);
832*30715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
833*30715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
834*30715Sbostic 			    part);
835*30715Sbostic #endif
836*30715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
837*30715Sbostic 			fprintf(stderr,
838*30715Sbostic 			    "partition %c: offset past end of unit\n", part);
839*30715Sbostic 			errors++;
840*30715Sbostic 		}
841*30715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
842*30715Sbostic 			fprintf(stderr,
843*30715Sbostic 			    "partition %c: partition extends past end of unit\n",
844*30715Sbostic 			    part);
845*30715Sbostic 			errors++;
846*30715Sbostic 		}
847*30715Sbostic 	}
848*30715Sbostic 	for (; i < MAXPARTITIONS; i++) {
849*30715Sbostic 		part = 'a' + i;
850*30715Sbostic 		pp = &lp->d_partitions[i];
851*30715Sbostic 		if (pp->p_size || pp->p_offset)
852*30715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
853*30715Sbostic 			    pp->p_size, pp->p_offset);
854*30715Sbostic 	}
855*30715Sbostic 	return (errors);
856*30715Sbostic }
857*30715Sbostic 
858*30715Sbostic /*VARARGS1*/
859*30715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
860*30715Sbostic 	char *fmt;
861*30715Sbostic {
862*30715Sbostic 
863*30715Sbostic 	fprintf(stderr, "Warning, ");
864*30715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
865*30715Sbostic 	fprintf(stderr, "\n");
866*30715Sbostic }
867*30715Sbostic 
868*30715Sbostic Perror(str)
869*30715Sbostic 	char *str;
870*30715Sbostic {
871*30715Sbostic 	fputs("disklabel: ", stderr); perror(str);
87230418Skarels 	exit(4);
87330418Skarels }
874*30715Sbostic 
875*30715Sbostic usage()
876*30715Sbostic {
877*30715Sbostic #ifdef BOOT
878*30715Sbostic 	fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n",
879*30715Sbostic "usage: disklabel [-r] disk", "(to read label)",
880*30715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
881*30715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
882*30715Sbostic "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)");
883*30715Sbostic #else
884*30715Sbostic 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
885*30715Sbostic "usage: disklabel [-r] disk", "(to read label)",
886*30715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
887*30715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
888*30715Sbostic "or disklabel -R [-r] disk protofile", "(to restore label)");
889*30715Sbostic #endif
890*30715Sbostic 	exit(1);
891*30715Sbostic }
892