xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 34641)
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*34641Skarels static char sccsid[] = "@(#)disklabel.c	5.13 (Berkeley) 06/04/88";
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 
5530715Sbostic #ifdef BOOT
5630418Skarels char	*xxboot;
5730418Skarels char	*bootxx;
5830715Sbostic #endif
5931617Skarels 
6031617Skarels char	*dkname;
6130418Skarels char	*specname;
6230715Sbostic char	tmpfil[] = "/tmp/EdDk.aXXXXXX";
6330418Skarels 
6430418Skarels extern	int errno;
6530418Skarels char	namebuf[BBSIZE], *np = namebuf;
6631617Skarels struct	disklabel lab;
6731617Skarels struct	disklabel *readlabel(), *makebootarea();
6830418Skarels char	bootarea[BBSIZE];
6934032Skarels char	boot0[MAXPATHLEN];
7034032Skarels char	boot1[MAXPATHLEN];
7130418Skarels 
7234032Skarels enum	{ UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
7330418Skarels 
7430677Skarels int	rflag;
7530677Skarels 
7634032Skarels #ifdef DEBUG
7734032Skarels int	debug;
7834032Skarels #endif
7934032Skarels 
8030418Skarels main(argc, argv)
8130418Skarels 	int argc;
8230418Skarels 	char *argv[];
8330418Skarels {
8434032Skarels 	extern int optind;
8530418Skarels 	register struct disklabel *lp;
8634032Skarels 	FILE *t;
87*34641Skarels 	int ch, f, error = 0;
8830715Sbostic 	char *name = 0, *type;
8930418Skarels 
9034032Skarels 	while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
9134032Skarels 		switch (ch) {
9234032Skarels 			case 'N':
9334032Skarels 				if (op != UNSPEC)
9434032Skarels 					usage();
9534032Skarels 				op = NOWRITE;
9634032Skarels 				break;
9730715Sbostic 			case 'R':
9834032Skarels 				if (op != UNSPEC)
9934032Skarels 					usage();
10030715Sbostic 				op = RESTORE;
10130715Sbostic 				break;
10234032Skarels 			case 'W':
10334032Skarels 				if (op != UNSPEC)
10434032Skarels 					usage();
10534032Skarels 				op = WRITEABLE;
10634032Skarels 				break;
10730715Sbostic 			case 'e':
10834032Skarels 				if (op != UNSPEC)
10934032Skarels 					usage();
11030715Sbostic 				op = EDIT;
11130715Sbostic 				break;
11230715Sbostic 			case 'r':
11330715Sbostic 				++rflag;
11430715Sbostic 				break;
11530715Sbostic 			case 'w':
11634032Skarels 				if (op != UNSPEC)
11734032Skarels 					usage();
11830715Sbostic 				op = WRITE;
11930715Sbostic 				break;
12034032Skarels #ifdef DEBUG
12134032Skarels 			case 'd':
12234032Skarels 				debug++;
12334032Skarels 				break;
12434032Skarels #endif
12530715Sbostic 			case '?':
12630715Sbostic 			default:
12730715Sbostic 				usage();
12830715Sbostic 		}
12930715Sbostic 	argc -= optind;
13030715Sbostic 	argv += optind;
13134032Skarels 	if (op == UNSPEC)
13234032Skarels 		op = READ;
13330715Sbostic 	if (argc < 1)
13430715Sbostic 		usage();
13530715Sbostic 
13630715Sbostic 	dkname = argv[0];
13730418Skarels 	if (dkname[0] != '/') {
13832439Sbostic 		(void)sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION);
13930418Skarels 		specname = np;
14030418Skarels 		np += strlen(specname) + 1;
14130418Skarels 	} else
14230418Skarels 		specname = dkname;
14330418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
14430418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
14532439Sbostic 		(void)sprintf(specname, "/dev/r%s", dkname);
14630418Skarels 		np = namebuf + strlen(specname) + 1;
14730418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
14830418Skarels 	}
14930418Skarels 	if (f < 0)
15030418Skarels 		Perror(specname);
15130418Skarels 
15230715Sbostic 	switch(op) {
15330715Sbostic 	case EDIT:
15430715Sbostic 		if (argc != 1)
15530715Sbostic 			usage();
15634032Skarels 		lp = readlabel(f);
157*34641Skarels 		error = edit(lp, f);
15830715Sbostic 		break;
15934032Skarels 	case NOWRITE: {
16034032Skarels 		int flag = 0;
16134032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
16234032Skarels 			Perror("ioctl DIOCWLABEL");
16334032Skarels 		break;
16434032Skarels 	}
16530418Skarels 	case READ:
16630715Sbostic 		if (argc != 1)
16730715Sbostic 			usage();
16834032Skarels 		lp = readlabel(f);
16930418Skarels 		display(stdout, lp);
170*34641Skarels 		error = checklabel(lp);
17130418Skarels 		break;
17230715Sbostic 	case RESTORE:
17330715Sbostic #ifdef BOOT
17434032Skarels 		if (rflag) {
17534032Skarels 			if (argc == 4) {	/* [ priboot secboot ] */
17634032Skarels 				xxboot = argv[2];
17734032Skarels 				bootxx = argv[3];
17834032Skarels 				lab.d_secsize = DEV_BSIZE;	/* XXX */
17934032Skarels 				lab.d_bbsize = BBSIZE;		/* XXX */
18034032Skarels 			}
18134032Skarels 			else if (argc == 3) 	/* [ disktype ] */
18234032Skarels 				makelabel(argv[2], (char *)NULL, &lab);
18334032Skarels 			else {
18434032Skarels 				fprintf(stderr,
18534032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
18634032Skarels 				exit(1);
18734032Skarels 			}
18834032Skarels 		}
18934032Skarels 		else
19031617Skarels #endif
19130715Sbostic 		if (argc != 2)
19230715Sbostic 			usage();
19331617Skarels 		lp = makebootarea(bootarea, &lab);
19430715Sbostic 		if (!(t = fopen(argv[1],"r")))
19530715Sbostic 			Perror(argv[1]);
19630715Sbostic 		if (getasciilabel(t, lp))
197*34641Skarels 			error = writelabel(f, bootarea, lp);
19830418Skarels 		break;
19930418Skarels 	case WRITE:
20030715Sbostic 		type = argv[1];
20130715Sbostic #ifdef BOOT
20230715Sbostic 		if (argc > 5 || argc < 2)
20330715Sbostic 			usage();
20430715Sbostic 		if (argc > 3) {
20530715Sbostic 			bootxx = argv[--argc];
20630715Sbostic 			xxboot = argv[--argc];
20730715Sbostic 		}
20830715Sbostic #else
20930715Sbostic 		if (argc > 3 || argc < 2)
21030715Sbostic 			usage();
21130715Sbostic #endif
21230715Sbostic 		if (argc > 2)
21330715Sbostic 			name = argv[--argc];
21430418Skarels 		makelabel(type, name, &lab);
21531617Skarels 		lp = makebootarea(bootarea, &lab);
21630418Skarels 		*lp = lab;
21730715Sbostic 		if (checklabel(lp) == 0)
218*34641Skarels 			error = writelabel(f, bootarea, lp);
21930418Skarels 		break;
22034032Skarels 	case WRITEABLE: {
22134032Skarels 		int flag = 1;
22234032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
22334032Skarels 			Perror("ioctl DIOCWLABEL");
22434032Skarels 		break;
22530418Skarels 	}
22634032Skarels 	}
227*34641Skarels 	exit(error);
22830418Skarels }
22930418Skarels 
23034032Skarels /*
23134032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
23234032Skarels  * effect, set the names of the primary and secondary boot files
23334032Skarels  * if specified.
23434032Skarels  */
23530418Skarels makelabel(type, name, lp)
23630418Skarels 	char *type, *name;
23730418Skarels 	register struct disklabel *lp;
23830418Skarels {
23930418Skarels 	register struct disklabel *dp;
24034032Skarels 	char *strcpy();
24130418Skarels 
24230418Skarels 	dp = getdiskbyname(type);
24330418Skarels 	if (dp == NULL) {
24430418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
24530418Skarels 		exit(1);
24630418Skarels 	}
24730418Skarels 	*lp = *dp;
24834032Skarels #ifdef BOOT
24934032Skarels 	/*
25034032Skarels 	 * Check if disktab specifies the bootstraps (b0 or b1).
25134032Skarels 	 */
25234032Skarels 	if (!xxboot && lp->d_boot0) {
25334032Skarels 		if (*lp->d_boot0 != '/')
25434032Skarels 			(void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
25534032Skarels 		else
25634032Skarels 			(void)strcpy(boot0, lp->d_boot0);
25734032Skarels 		xxboot = boot0;
25834032Skarels 	}
25934032Skarels 	if (!bootxx && lp->d_boot1) {
26034032Skarels 		if (*lp->d_boot1 != '/')
26134032Skarels 			(void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
26234032Skarels 		else
26334032Skarels 			(void)strcpy(boot1, lp->d_boot1);
26434032Skarels 		bootxx = boot1;
26534032Skarels 	}
26634032Skarels 	/*
26734032Skarels 	 * If bootstraps not specified anywhere, makebootarea()
26834032Skarels 	 * will choose ones based on the name of the disk special
26934032Skarels 	 * file. E.g. /dev/ra0 -> raboot, bootra
27034032Skarels 	 */
27134032Skarels #endif /*BOOT*/
27234032Skarels 	/* d_packname is union d_boot[01], so zero */
27334032Skarels 	bzero(lp->d_packname, sizeof(lp->d_packname));
27430418Skarels 	if (name)
27534032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
27630418Skarels }
27730418Skarels 
27830418Skarels writelabel(f, boot, lp)
27930418Skarels 	int f;
28030418Skarels 	char *boot;
28130418Skarels 	register struct disklabel *lp;
28230418Skarels {
28330715Sbostic 	register int i;
28434032Skarels 	int flag;
28534032Skarels 	off_t lseek();
28630418Skarels 
28730418Skarels 	lp->d_magic = DISKMAGIC;
28830418Skarels 	lp->d_magic2 = DISKMAGIC;
28930418Skarels 	lp->d_checksum = 0;
29030418Skarels 	lp->d_checksum = dkcksum(lp);
29130677Skarels 	if (rflag) {
29234032Skarels 		/*
29334032Skarels 		 * First set the kernel disk label,
29434032Skarels 		 * then write a label to the raw disk.
29534032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
29634032Skarels 		 * keep going; otherwise, the kernel consistency checks
29734032Skarels 		 * may prevent us from changing the current (in-core)
29834032Skarels 		 * label.
29934032Skarels 		 */
30034032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
301*34641Skarels 		    errno != ENODEV && errno != ENOTTY) {
302*34641Skarels 			l_perror("ioctl DIOCSDINFO");
303*34641Skarels 			return (1);
304*34641Skarels 		}
30531617Skarels 		(void)lseek(f, (off_t)0, L_SET);
30634032Skarels 		/*
30734032Skarels 		 * write enable label sector before write (if necessary),
30834032Skarels 		 * disable after writing.
30934032Skarels 		 */
31034032Skarels 		flag = 1;
31134032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
31234032Skarels 			perror("ioctl DIOCWLABEL");
313*34641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
314*34641Skarels 			perror("write");
315*34641Skarels 			return (1);
316*34641Skarels 		}
31734032Skarels 		flag = 0;
31834032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
319*34641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
320*34641Skarels 		l_perror("ioctl DIOCWDINFO");
321*34641Skarels 		return (1);
322*34641Skarels 	}
32334032Skarels #ifdef vax
32430677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
32530677Skarels 		daddr_t alt;
32630677Skarels 
32730677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
32830677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
32930715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
33030677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
33130677Skarels 				int oerrno = errno;
33230677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
33330677Skarels 				errno = oerrno;
33430677Skarels 				perror("write");
33530677Skarels 			}
33630418Skarels 		}
33730418Skarels 	}
33830419Skarels #endif
339*34641Skarels 	return (0);
34030418Skarels }
34130418Skarels 
342*34641Skarels l_perror(s)
343*34641Skarels 	char *s;
344*34641Skarels {
345*34641Skarels 	int saverrno = errno;
346*34641Skarels 
347*34641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
348*34641Skarels 
349*34641Skarels 	switch (saverrno) {
350*34641Skarels 
351*34641Skarels 	case ESRCH:
352*34641Skarels 		fprintf(stderr, "No disk label on disk;\n");
353*34641Skarels 		fprintf(stderr,
354*34641Skarels 		    "use \"disklabel -r\" to install initial label\n");
355*34641Skarels 		break;
356*34641Skarels 
357*34641Skarels 	case EINVAL:
358*34641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
359*34641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
360*34641Skarels 		break;
361*34641Skarels 
362*34641Skarels 	case EBUSY:
363*34641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
364*34641Skarels 		break;
365*34641Skarels 
366*34641Skarels 	case EXDEV:
367*34641Skarels 		fprintf(stderr,
368*34641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
369*34641Skarels 		break;
370*34641Skarels 
371*34641Skarels 	default:
372*34641Skarels 		errno = saverrno;
373*34641Skarels 		perror((char *)NULL);
374*34641Skarels 		break;
375*34641Skarels 	}
376*34641Skarels }
377*34641Skarels 
37830418Skarels /*
37931617Skarels  * Fetch disklabel for disk.
38031617Skarels  * Use ioctl to get label unless -r flag is given.
38130418Skarels  */
38230418Skarels struct disklabel *
38334032Skarels readlabel(f)
38434032Skarels 	int f;
38530418Skarels {
38630418Skarels 	register struct disklabel *lp;
38730418Skarels 
38834032Skarels 	if (rflag) {
38931617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
39031401Skarels 			Perror(specname);
39131617Skarels 		for (lp = (struct disklabel *)bootarea;
39231617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
39330677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
39430677Skarels 			if (lp->d_magic == DISKMAGIC &&
39530677Skarels 			    lp->d_magic2 == DISKMAGIC)
39630677Skarels 				break;
39731617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
39830677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
39930677Skarels 		    dkcksum(lp) != 0) {
40030677Skarels 			fprintf(stderr,
40130418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
40234032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
40334032Skarels 			exit (1);
40430677Skarels 		}
40534032Skarels 	} else {
40634032Skarels 		lp = &lab;
40734032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
40834032Skarels 			Perror("ioctl DIOCGDINFO");
40930418Skarels 	}
41030418Skarels 	return (lp);
41130418Skarels }
41230418Skarels 
41330418Skarels struct disklabel *
41431617Skarels makebootarea(boot, dp)
41530418Skarels 	char *boot;
41630418Skarels 	register struct disklabel *dp;
41730418Skarels {
41830418Skarels 	struct disklabel *lp;
41930418Skarels 	register char *p;
42030418Skarels 	int b;
42130418Skarels #ifdef BOOT
42230715Sbostic 	char	*dkbasename;
42334032Skarels #endif /*BOOT*/
42430715Sbostic 
42534032Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
42634032Skarels 	    LABELOFFSET);
42734032Skarels #ifdef BOOT
42834032Skarels 	if (!rflag)
42934032Skarels 		return (lp);
43034032Skarels 
43134032Skarels 	if (xxboot == NULL || bootxx == NULL) {
43230418Skarels 		dkbasename = np;
43330418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
43430418Skarels 			p = dkname;
43530418Skarels 		else
43630418Skarels 			p++;
43730418Skarels 		while (*p && !isdigit(*p))
43830418Skarels 			*np++ = *p++;
43930418Skarels 		*np++ = '\0';
44030418Skarels 
44134032Skarels 		if (xxboot == NULL) {
44234032Skarels 			(void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
44334032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
44434032Skarels 				dkbasename++;
44534032Skarels 			xxboot = np;
44634032Skarels 			(void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
44734032Skarels 			np += strlen(xxboot) + 1;
44834032Skarels 		}
44934032Skarels 		if (bootxx == NULL) {
45034032Skarels 			(void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
45134032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
45234032Skarels 				dkbasename++;
45334032Skarels 			bootxx = np;
45434032Skarels 			(void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
45534032Skarels 			np += strlen(bootxx) + 1;
45634032Skarels 		}
45730418Skarels 	}
45834032Skarels #ifdef DEBUG
45934032Skarels 	if (debug)
46034032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
46134032Skarels 			xxboot, bootxx);
46234032Skarels #endif
46330418Skarels 
46430418Skarels 	b = open(xxboot, O_RDONLY);
46530418Skarels 	if (b < 0)
46630418Skarels 		Perror(xxboot);
46730715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
46830418Skarels 		Perror(xxboot);
46930418Skarels 	close(b);
47030418Skarels 	b = open(bootxx, O_RDONLY);
47130418Skarels 	if (b < 0)
47230418Skarels 		Perror(bootxx);
47330715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
47430418Skarels 		Perror(bootxx);
47530715Sbostic 	(void)close(b);
47634032Skarels #endif /*BOOT*/
47730418Skarels 
47830418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
47930418Skarels 		if (*p) {
48030418Skarels 			fprintf(stderr,
48130418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
48230418Skarels 			exit(2);
48330418Skarels 		}
48430418Skarels 	return (lp);
48530418Skarels }
48630418Skarels 
48730418Skarels display(f, lp)
48830418Skarels 	FILE *f;
48930418Skarels 	register struct disklabel *lp;
49030418Skarels {
49130715Sbostic 	register int i, j;
49230418Skarels 	register struct partition *pp;
49330418Skarels 
49430418Skarels 	fprintf(f, "# %s:\n", specname);
49530418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
49630418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
49730418Skarels 	else
49830418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
49930418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
50034032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
50131401Skarels 	fprintf(f, "flags:");
50230418Skarels 	if (lp->d_flags & D_REMOVABLE)
50331401Skarels 		fprintf(f, " removeable");
50430418Skarels 	if (lp->d_flags & D_ECC)
50531401Skarels 		fprintf(f, " ecc");
50630418Skarels 	if (lp->d_flags & D_BADSECT)
50731401Skarels 		fprintf(f, " badsect");
50830418Skarels 	fprintf(f, "\n");
50930418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
51030418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
51130418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
51231386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
51330418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
51430715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
51530418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
51630418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
51730418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
51830418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
51930418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
52030418Skarels 	fprintf(f, "drivedata: ");
52130418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
52230418Skarels 		if (lp->d_drivedata[i])
52330418Skarels 			break;
52430418Skarels 	if (i < 0)
52530418Skarels 		i = 0;
52630418Skarels 	for (j = 0; j <= i; j++)
52730418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
52830418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
52930863Skarels 	fprintf(f,
53030863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
53130418Skarels 	pp = lp->d_partitions;
53230418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
53330418Skarels 		if (pp->p_size) {
53430863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
53530863Skarels 			   pp->p_size, pp->p_offset);
53630418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
53730418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
53830418Skarels 			else
53930418Skarels 				fprintf(f, "%8d", pp->p_fstype);
54030863Skarels 			switch (pp->p_fstype) {
54130863Skarels 
54230863Skarels 			case FS_UNUSED:				/* XXX */
54330863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
54430863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
54530863Skarels 				break;
54630863Skarels 
54730863Skarels 			case FS_BSDFFS:
54830863Skarels 				fprintf(f, "    %5d %5d %5d ",
54930863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
55030863Skarels 				    pp->p_cpg);
55130863Skarels 				break;
55230863Skarels 
55330863Skarels 			default:
55430863Skarels 				fprintf(f, "%20.20s", "");
55530863Skarels 				break;
55630863Skarels 			}
55730418Skarels 			fprintf(f, "\t# (Cyl. %4d",
55830418Skarels 			    pp->p_offset / lp->d_secpercyl);
55930418Skarels 			if (pp->p_offset % lp->d_secpercyl)
56030418Skarels 			    putc('*', f);
56130418Skarels 			else
56230418Skarels 			    putc(' ', f);
56330418Skarels 			fprintf(f, "- %d",
56430418Skarels 			    (pp->p_offset +
56530418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
56630418Skarels 			    lp->d_secpercyl - 1);
56730418Skarels 			if (pp->p_size % lp->d_secpercyl)
56830418Skarels 			    putc('*', f);
56930863Skarels 			fprintf(f, ")\n");
57030418Skarels 		}
57130418Skarels 	}
57232121Stef 	fflush(f);
57330418Skarels }
57430418Skarels 
575*34641Skarels edit(lp, f)
57630715Sbostic 	struct disklabel *lp;
577*34641Skarels 	int f;
57830418Skarels {
57930715Sbostic 	register int c;
58030715Sbostic 	struct disklabel label;
58130715Sbostic 	FILE *fd;
58230715Sbostic 	char *mktemp();
58330715Sbostic 
58430715Sbostic 	(void) mktemp(tmpfil);
58530715Sbostic 	fd = fopen(tmpfil, "w");
58630715Sbostic 	if (fd == NULL) {
58730715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
588*34641Skarels 		return (1);
58930715Sbostic 	}
59030715Sbostic 	(void)fchmod(fd, 0600);
59130715Sbostic 	display(fd, lp);
59230715Sbostic 	fclose(fd);
59330715Sbostic 	for (;;) {
59430715Sbostic 		if (!editit())
59530715Sbostic 			break;
59630715Sbostic 		fd = fopen(tmpfil, "r");
59730715Sbostic 		if (fd == NULL) {
59834032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
59934032Skarels 				tmpfil);
60030715Sbostic 			break;
60130715Sbostic 		}
60230863Skarels 		bzero((char *)&label, sizeof(label));
60330715Sbostic 		if (getasciilabel(fd, &label)) {
60430715Sbostic 			*lp = label;
605*34641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
606*34641Skarels 				(void) unlink(tmpfil);
607*34641Skarels 				return (0);
608*34641Skarels 			}
60930715Sbostic 		}
61030715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
61130715Sbostic 		c = getchar();
61230715Sbostic 		if (c != EOF && c != (int)'\n')
61330715Sbostic 			while (getchar() != (int)'\n')
61430715Sbostic 				;
61530715Sbostic 		if  (c == (int)'n')
61630715Sbostic 			break;
61730715Sbostic 	}
61830715Sbostic 	(void) unlink(tmpfil);
619*34641Skarels 	return (1);
62030418Skarels }
62130418Skarels 
62230715Sbostic editit()
62330715Sbostic {
62430715Sbostic 	register int pid, xpid;
62530715Sbostic 	int stat, omask;
62630715Sbostic 	extern char *getenv();
62730418Skarels 
62830715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
62930715Sbostic 	while ((pid = fork()) < 0) {
63030715Sbostic 		extern int errno;
63130715Sbostic 
63230715Sbostic 		if (errno == EPROCLIM) {
63330715Sbostic 			fprintf(stderr, "You have too many processes\n");
63430715Sbostic 			return(0);
63530715Sbostic 		}
63630715Sbostic 		if (errno != EAGAIN) {
63730715Sbostic 			perror("fork");
63830715Sbostic 			return(0);
63930715Sbostic 		}
64030715Sbostic 		sleep(1);
64130715Sbostic 	}
64230715Sbostic 	if (pid == 0) {
64330715Sbostic 		register char *ed;
64430715Sbostic 
64530715Sbostic 		sigsetmask(omask);
64630715Sbostic 		setgid(getgid());
64730715Sbostic 		setuid(getuid());
64830715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
64930715Sbostic 			ed = DEFEDITOR;
65030715Sbostic 		execlp(ed, ed, tmpfil, 0);
65130715Sbostic 		perror(ed);
65230715Sbostic 		exit(1);
65330715Sbostic 	}
65430715Sbostic 	while ((xpid = wait(&stat)) >= 0)
65530715Sbostic 		if (xpid == pid)
65630715Sbostic 			break;
65730715Sbostic 	sigsetmask(omask);
65830715Sbostic 	return(!stat);
65930715Sbostic }
66030715Sbostic 
66130715Sbostic char *
66230715Sbostic skip(cp)
66330715Sbostic 	register char *cp;
66430715Sbostic {
66530715Sbostic 
66630715Sbostic 	while (*cp != '\0' && isspace(*cp))
66730715Sbostic 		cp++;
66830715Sbostic 	if (*cp == '\0' || *cp == '#')
66930715Sbostic 		return ((char *)NULL);
67030715Sbostic 	return (cp);
67130715Sbostic }
67230715Sbostic 
67330715Sbostic char *
67430715Sbostic word(cp)
67530715Sbostic 	register char *cp;
67630715Sbostic {
67730715Sbostic 	register char c;
67830715Sbostic 
67931401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
68031401Skarels 		cp++;
68130715Sbostic 	if ((c = *cp) != '\0') {
68230715Sbostic 		*cp++ = '\0';
68330715Sbostic 		if (c != '#')
68430715Sbostic 			return (skip(cp));
68530715Sbostic 	}
68630715Sbostic 	return ((char *)NULL);
68730715Sbostic }
68830715Sbostic 
68930418Skarels /*
69030418Skarels  * Read an ascii label in from fd f,
69130418Skarels  * in the same format as that put out by display(),
69230418Skarels  * and fill in lp.
69330418Skarels  */
69430418Skarels getasciilabel(f, lp)
69530715Sbostic 	FILE	*f;
69630418Skarels 	register struct disklabel *lp;
69730418Skarels {
69830715Sbostic 	register char **cpp, *cp;
69930863Skarels 	register struct partition *pp;
70030715Sbostic 	char *tp, *s, line[BUFSIZ];
70130715Sbostic 	int v, lineno = 0, errors = 0;
70230715Sbostic 
70330715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
70430715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
70530715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
70630715Sbostic 		lineno++;
70730715Sbostic 		if (cp = index(line,'\n'))
70830715Sbostic 			*cp = '\0';
70930715Sbostic 		cp = skip(line);
71030715Sbostic 		if (cp == NULL)
71130715Sbostic 			continue;
71230715Sbostic 		tp = index(cp, ':');
71330715Sbostic 		if (tp == NULL) {
71430715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
71530715Sbostic 			errors++;
71630715Sbostic 			continue;
71730715Sbostic 		}
71830715Sbostic 		*tp++ = '\0', tp = skip(tp);
71930715Sbostic 		if (streq(cp, "type")) {
72030715Sbostic 			if (tp == NULL)
72130715Sbostic 				tp = "unknown";
72230715Sbostic 			cpp = dktypenames;
72330715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
72430715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
72530715Sbostic 					lp->d_type = cpp - dktypenames;
72630715Sbostic 					goto next;
72730715Sbostic 				}
72830715Sbostic 			v = atoi(tp);
72930715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
73030715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
73130715Sbostic 				    "Warning, unknown disk type", v);
73230715Sbostic 			lp->d_type = v;
73330715Sbostic 			continue;
73430715Sbostic 		}
73530715Sbostic 		if (streq(cp, "flags")) {
73634032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
73734032Skarels 				tp = word(cp);
73830715Sbostic 				if (streq(cp, "removeable"))
73930715Sbostic 					v |= D_REMOVABLE;
74030715Sbostic 				else if (streq(cp, "ecc"))
74130715Sbostic 					v |= D_ECC;
74230715Sbostic 				else if (streq(cp, "badsect"))
74330715Sbostic 					v |= D_BADSECT;
74430715Sbostic 				else {
74530715Sbostic 					fprintf(stderr,
74630715Sbostic 					    "line %d: %s: bad flag\n",
74730715Sbostic 					    lineno, cp);
74830715Sbostic 					errors++;
74930715Sbostic 				}
75030715Sbostic 			}
75130715Sbostic 			lp->d_flags = v;
75230715Sbostic 			continue;
75330715Sbostic 		}
75430715Sbostic 		if (streq(cp, "drivedata")) {
75530715Sbostic 			register int i;
75630715Sbostic 
75731386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
75830715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
75931386Skarels 				tp = word(cp);
76030715Sbostic 			}
76130715Sbostic 			continue;
76230715Sbostic 		}
76330715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
76430863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
76530715Sbostic 				fprintf(stderr,
76630715Sbostic 				    "line %d: bad # of partitions\n", lineno);
76730863Skarels 				lp->d_npartitions = MAXPARTITIONS;
76830863Skarels 				errors++;
76930863Skarels 			} else
77030715Sbostic 				lp->d_npartitions = v;
77130715Sbostic 			continue;
77230715Sbostic 		}
77330715Sbostic 		if (tp == NULL)
77430715Sbostic 			tp = "";
77530715Sbostic 		if (streq(cp, "disk")) {
77630715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
77730715Sbostic 			continue;
77830715Sbostic 		}
77930715Sbostic 		if (streq(cp, "label")) {
78034032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
78130715Sbostic 			continue;
78230715Sbostic 		}
78330715Sbostic 		if (streq(cp, "bytes/sector")) {
78430715Sbostic 			v = atoi(tp);
78530715Sbostic 			if (v <= 0 || (v % 512) != 0) {
78630715Sbostic 				fprintf(stderr,
78730715Sbostic 				    "line %d: %s: bad sector size\n",
78830715Sbostic 				    lineno, tp);
78930715Sbostic 				errors++;
79030715Sbostic 			} else
79130715Sbostic 				lp->d_secsize = v;
79230715Sbostic 			continue;
79330715Sbostic 		}
79430715Sbostic 		if (streq(cp, "sectors/track")) {
79530715Sbostic 			v = atoi(tp);
79630715Sbostic 			if (v <= 0) {
79730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
79830715Sbostic 				    lineno, tp, cp);
79930715Sbostic 				errors++;
80030715Sbostic 			} else
80130715Sbostic 				lp->d_nsectors = v;
80230715Sbostic 			continue;
80330715Sbostic 		}
80431386Skarels 		if (streq(cp, "sectors/cylinder")) {
80531386Skarels 			v = atoi(tp);
80631386Skarels 			if (v <= 0) {
80731386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
80831386Skarels 				    lineno, tp, cp);
80931386Skarels 				errors++;
81031386Skarels 			} else
81131386Skarels 				lp->d_secpercyl = v;
81231386Skarels 			continue;
81331386Skarels 		}
81430715Sbostic 		if (streq(cp, "tracks/cylinder")) {
81530715Sbostic 			v = atoi(tp);
81630715Sbostic 			if (v <= 0) {
81730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
81830715Sbostic 				    lineno, tp, cp);
81930715Sbostic 				errors++;
82030715Sbostic 			} else
82130715Sbostic 				lp->d_ntracks = v;
82230715Sbostic 			continue;
82330715Sbostic 		}
82430715Sbostic 		if (streq(cp, "cylinders")) {
82530715Sbostic 			v = atoi(tp);
82630715Sbostic 			if (v <= 0) {
82730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
82830715Sbostic 				    lineno, tp, cp);
82930715Sbostic 				errors++;
83030715Sbostic 			} else
83130715Sbostic 				lp->d_ncylinders = v;
83230715Sbostic 			continue;
83330715Sbostic 		}
83430715Sbostic 		if (streq(cp, "rpm")) {
83530715Sbostic 			v = atoi(tp);
83630715Sbostic 			if (v <= 0) {
83730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
83830715Sbostic 				    lineno, tp, cp);
83930715Sbostic 				errors++;
84030715Sbostic 			} else
84130715Sbostic 				lp->d_rpm = v;
84230715Sbostic 			continue;
84330715Sbostic 		}
84430715Sbostic 		if (streq(cp, "interleave")) {
84530715Sbostic 			v = atoi(tp);
84630715Sbostic 			if (v <= 0) {
84730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
84830715Sbostic 				    lineno, tp, cp);
84930715Sbostic 				errors++;
85030715Sbostic 			} else
85130715Sbostic 				lp->d_interleave = v;
85230715Sbostic 			continue;
85330715Sbostic 		}
85430715Sbostic 		if (streq(cp, "trackskew")) {
85530715Sbostic 			v = atoi(tp);
85630715Sbostic 			if (v < 0) {
85730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
85830715Sbostic 				    lineno, tp, cp);
85930715Sbostic 				errors++;
86030715Sbostic 			} else
86130715Sbostic 				lp->d_trackskew = v;
86230715Sbostic 			continue;
86330715Sbostic 		}
86430715Sbostic 		if (streq(cp, "cylinderskew")) {
86530715Sbostic 			v = atoi(tp);
86630715Sbostic 			if (v < 0) {
86730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
86830715Sbostic 				    lineno, tp, cp);
86930715Sbostic 				errors++;
87030715Sbostic 			} else
87130715Sbostic 				lp->d_cylskew = v;
87230715Sbostic 			continue;
87330715Sbostic 		}
87430715Sbostic 		if (streq(cp, "headswitch")) {
87530715Sbostic 			v = atoi(tp);
87630715Sbostic 			if (v < 0) {
87730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
87830715Sbostic 				    lineno, tp, cp);
87930715Sbostic 				errors++;
88030715Sbostic 			} else
88130715Sbostic 				lp->d_headswitch = v;
88230715Sbostic 			continue;
88330715Sbostic 		}
88430715Sbostic 		if (streq(cp, "track-to-track seek")) {
88530715Sbostic 			v = atoi(tp);
88630715Sbostic 			if (v < 0) {
88730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
88830715Sbostic 				    lineno, tp, cp);
88930715Sbostic 				errors++;
89030715Sbostic 			} else
89130715Sbostic 				lp->d_trkseek = v;
89230715Sbostic 			continue;
89330715Sbostic 		}
89430715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
89530863Skarels 			unsigned part = *cp - 'a';
89630715Sbostic 
89730863Skarels 			if (part > lp->d_npartitions) {
89830715Sbostic 				fprintf(stderr,
89930715Sbostic 				    "line %d: bad partition name\n", lineno);
90030715Sbostic 				errors++;
90130715Sbostic 				continue;
90230715Sbostic 			}
90330863Skarels 			pp = &lp->d_partitions[part];
90430863Skarels #define NXTNUM(n) { \
90530863Skarels 	cp = tp, tp = word(cp); \
90630863Skarels 	if (tp == NULL) \
90730863Skarels 		tp = cp; \
90830863Skarels 	(n) = atoi(cp); \
90930863Skarels      }
91030863Skarels 
91130863Skarels 			NXTNUM(v);
91230715Sbostic 			if (v < 0) {
91330715Sbostic 				fprintf(stderr,
91430715Sbostic 				    "line %d: %s: bad partition size\n",
91530715Sbostic 				    lineno, cp);
91630715Sbostic 				errors++;
91730715Sbostic 			} else
91830863Skarels 				pp->p_size = v;
91930863Skarels 			NXTNUM(v);
92030715Sbostic 			if (v < 0) {
92130715Sbostic 				fprintf(stderr,
92230715Sbostic 				    "line %d: %s: bad partition offset\n",
92330715Sbostic 				    lineno, cp);
92430715Sbostic 				errors++;
92530715Sbostic 			} else
92630863Skarels 				pp->p_offset = v;
92730715Sbostic 			cp = tp, tp = word(cp);
92830715Sbostic 			cpp = fstypenames;
92930715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
93030715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
93130863Skarels 					pp->p_fstype = cpp - fstypenames;
93230863Skarels 					goto gottype;
93330715Sbostic 				}
93434032Skarels 			if (isdigit(*cp))
93534032Skarels 				v = atoi(cp);
93634032Skarels 			else
93734032Skarels 				v = FSMAXTYPES;
93834032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
93930715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
94030715Sbostic 				    "Warning, unknown filesystem type", cp);
94134032Skarels 				v = FS_UNUSED;
94234032Skarels 			}
94330863Skarels 			pp->p_fstype = v;
94430863Skarels 	gottype:
94530863Skarels 
94630863Skarels 			switch (pp->p_fstype) {
94730863Skarels 
94830863Skarels 			case FS_UNUSED:				/* XXX */
94930863Skarels 				NXTNUM(pp->p_fsize);
95030863Skarels 				if (pp->p_fsize == 0)
95130863Skarels 					break;
95230863Skarels 				NXTNUM(v);
95330863Skarels 				pp->p_frag = v / pp->p_fsize;
95430863Skarels 				break;
95530863Skarels 
95630863Skarels 			case FS_BSDFFS:
95730863Skarels 				NXTNUM(pp->p_fsize);
95830863Skarels 				if (pp->p_fsize == 0)
95930863Skarels 					break;
96030863Skarels 				NXTNUM(v);
96130863Skarels 				pp->p_frag = v / pp->p_fsize;
96230863Skarels 				NXTNUM(pp->p_cpg);
96330863Skarels 				break;
96430863Skarels 
96530863Skarels 			default:
96630863Skarels 				break;
96730863Skarels 			}
96830715Sbostic 			continue;
96930715Sbostic 		}
97030715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
97130715Sbostic 		    lineno, cp);
97230715Sbostic 		errors++;
97330715Sbostic 	next:
97430715Sbostic 		;
97530715Sbostic 	}
97630715Sbostic 	errors += checklabel(lp);
97730715Sbostic 	return (errors == 0);
97830418Skarels }
97930418Skarels 
98030715Sbostic /*
98130715Sbostic  * Check disklabel for errors and fill in
98230715Sbostic  * derived fields according to supplied values.
98330715Sbostic  */
98430715Sbostic checklabel(lp)
98530715Sbostic 	register struct disklabel *lp;
98630418Skarels {
98730715Sbostic 	register struct partition *pp;
98830715Sbostic 	int i, errors = 0;
98930715Sbostic 	char part;
99030418Skarels 
99130715Sbostic 	if (lp->d_secsize == 0) {
99230715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
99330715Sbostic 		return (1);
99430715Sbostic 	}
99530715Sbostic 	if (lp->d_nsectors == 0) {
99630715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
99730715Sbostic 		return (1);
99830715Sbostic 	}
99930715Sbostic 	if (lp->d_ntracks == 0) {
100030715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
100130715Sbostic 		return (1);
100230715Sbostic 	}
100330715Sbostic 	if  (lp->d_ncylinders == 0) {
100430715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
100530715Sbostic 		errors++;
100630715Sbostic 	}
100730715Sbostic 	if (lp->d_rpm == 0)
100830715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
100930715Sbostic 	if (lp->d_secpercyl == 0)
101030715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
101130715Sbostic 	if (lp->d_secperunit == 0)
101230715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
101330715Sbostic 	if (lp->d_bbsize == 0) {
101430715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
101530715Sbostic 		errors++;
101630715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
101730715Sbostic 		Warning("boot block size %% sector-size != 0\n");
101830715Sbostic 	if (lp->d_sbsize == 0) {
101930715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
102030715Sbostic 		errors++;
102130715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
102230715Sbostic 		Warning("super block size %% sector-size != 0\n");
102330715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
102430715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
102530715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
102630715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
102730715Sbostic 		part = 'a' + i;
102830715Sbostic 		pp = &lp->d_partitions[i];
102930715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
103030715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
103130715Sbostic 			    part, pp->p_offset);
103230715Sbostic #ifdef notdef
103330715Sbostic 		if (pp->p_size % lp->d_secpercyl)
103430715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
103530715Sbostic 			    part);
103630715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
103730715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
103830715Sbostic 			    part);
103930715Sbostic #endif
104030715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
104130715Sbostic 			fprintf(stderr,
104230715Sbostic 			    "partition %c: offset past end of unit\n", part);
104330715Sbostic 			errors++;
104430715Sbostic 		}
104530715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
104630715Sbostic 			fprintf(stderr,
104730715Sbostic 			    "partition %c: partition extends past end of unit\n",
104830715Sbostic 			    part);
104930715Sbostic 			errors++;
105030715Sbostic 		}
105130715Sbostic 	}
105230715Sbostic 	for (; i < MAXPARTITIONS; i++) {
105330715Sbostic 		part = 'a' + i;
105430715Sbostic 		pp = &lp->d_partitions[i];
105530715Sbostic 		if (pp->p_size || pp->p_offset)
105630715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
105734032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
105830715Sbostic 	}
105930715Sbostic 	return (errors);
106030715Sbostic }
106130715Sbostic 
106230715Sbostic /*VARARGS1*/
106330715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
106430715Sbostic 	char *fmt;
106530715Sbostic {
106630715Sbostic 
106730715Sbostic 	fprintf(stderr, "Warning, ");
106830715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
106930715Sbostic 	fprintf(stderr, "\n");
107030715Sbostic }
107130715Sbostic 
107230715Sbostic Perror(str)
107330715Sbostic 	char *str;
107430715Sbostic {
107530715Sbostic 	fputs("disklabel: ", stderr); perror(str);
107630418Skarels 	exit(4);
107730418Skarels }
107830715Sbostic 
107930715Sbostic usage()
108030715Sbostic {
108130715Sbostic #ifdef BOOT
108234032Skarels 	fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
108330715Sbostic "usage: disklabel [-r] disk", "(to read label)",
108430715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
108530715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
108634032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
108734032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
108830715Sbostic #else
108934032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
109030715Sbostic "usage: disklabel [-r] disk", "(to read label)",
109130715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
109230715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
109334032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
109434032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
109530715Sbostic #endif
109630715Sbostic 	exit(1);
109730715Sbostic }
1098