xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 46345)
130715Sbostic /*
235983Sbostic  * Copyright (c) 1987 The Regents of the University of California.
335983Sbostic  * All rights reserved.
435983Sbostic  *
535983Sbostic  * This code is derived from software contributed to Berkeley by
635983Sbostic  * Symmetric Computer Systems.
735983Sbostic  *
842698Sbostic  * %sccs.include.redist.c%
930715Sbostic  */
1030715Sbostic 
1130418Skarels #ifndef lint
1235983Sbostic char copyright[] =
1335983Sbostic "@(#) Copyright (c) 1987 The Regents of the University of California.\n\
1435983Sbostic  All rights reserved.\n";
1535983Sbostic #endif /* not lint */
1635983Sbostic 
1735983Sbostic #ifndef lint
18*46345Swilliam static char sccsid[] = "@(#)disklabel.c	5.20 (Berkeley) 02/09/91";
1930418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
2035983Sbostic #endif /* not lint */
2130418Skarels 
2230418Skarels #include <sys/param.h>
2330715Sbostic #include <sys/signal.h>
2430418Skarels #include <sys/errno.h>
2530418Skarels #include <sys/file.h>
2630715Sbostic #include <sys/ioctl.h>
2738505Sbostic #include <ufs/fs.h>
2842042Sbostic #include <string.h>
2930418Skarels #define DKTYPENAMES
3030418Skarels #include <sys/disklabel.h>
3137261Sbostic #include <stdio.h>
3237261Sbostic #include <ctype.h>
3337261Sbostic #include "pathnames.h"
3430418Skarels 
3530418Skarels /*
3630418Skarels  * Disklabel: read and write disklabels.
3730418Skarels  * The label is usually placed on one of the first sectors of the disk.
3830418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
3930418Skarels  * in which case the label is embedded in the bootstrap.
4030418Skarels  * The bootstrap source must leave space at the proper offset
4130418Skarels  * for the label on such machines.
4230418Skarels  */
4330418Skarels 
44*46345Swilliam #if defined(vax) || defined(i386)
4530677Skarels #define RAWPARTITION	'c'
4630677Skarels #else
4730677Skarels #define RAWPARTITION	'a'
4830677Skarels #endif
4930677Skarels 
5030677Skarels #ifndef BBSIZE
5130418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
5230677Skarels #endif
5330418Skarels 
54*46345Swilliam #if defined(vax) || defined(i386)
5530418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
5637261Sbostic #define	BOOTDIR	_PATH_BOOTDIR		/* source of boot binaries */
5730677Skarels #else
5830677Skarels #ifdef lint
5930677Skarels #define	BOOT
6030418Skarels #endif
6130677Skarels #endif
6230418Skarels 
6338505Sbostic #define	DEFEDITOR	_PATH_VI
6430715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
6530715Sbostic 
6630715Sbostic #ifdef BOOT
6730418Skarels char	*xxboot;
6830418Skarels char	*bootxx;
6930715Sbostic #endif
7031617Skarels 
7131617Skarels char	*dkname;
7230418Skarels char	*specname;
7337945Sbostic char	tmpfil[] = _PATH_TMP;
7430418Skarels 
7530418Skarels extern	int errno;
7630418Skarels char	namebuf[BBSIZE], *np = namebuf;
7731617Skarels struct	disklabel lab;
7831617Skarels struct	disklabel *readlabel(), *makebootarea();
7930418Skarels char	bootarea[BBSIZE];
8034032Skarels char	boot0[MAXPATHLEN];
8134032Skarels char	boot1[MAXPATHLEN];
8230418Skarels 
8334032Skarels enum	{ UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
8430418Skarels 
8530677Skarels int	rflag;
8630677Skarels 
8734032Skarels #ifdef DEBUG
8834032Skarels int	debug;
8934032Skarels #endif
9034032Skarels 
9130418Skarels main(argc, argv)
9230418Skarels 	int argc;
9330418Skarels 	char *argv[];
9430418Skarels {
9534032Skarels 	extern int optind;
9630418Skarels 	register struct disklabel *lp;
9734032Skarels 	FILE *t;
9834641Skarels 	int ch, f, error = 0;
9930715Sbostic 	char *name = 0, *type;
10030418Skarels 
10134032Skarels 	while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
10234032Skarels 		switch (ch) {
10334032Skarels 			case 'N':
10434032Skarels 				if (op != UNSPEC)
10534032Skarels 					usage();
10634032Skarels 				op = NOWRITE;
10734032Skarels 				break;
10830715Sbostic 			case 'R':
10934032Skarels 				if (op != UNSPEC)
11034032Skarels 					usage();
11130715Sbostic 				op = RESTORE;
11230715Sbostic 				break;
11334032Skarels 			case 'W':
11434032Skarels 				if (op != UNSPEC)
11534032Skarels 					usage();
11634032Skarels 				op = WRITEABLE;
11734032Skarels 				break;
11830715Sbostic 			case 'e':
11934032Skarels 				if (op != UNSPEC)
12034032Skarels 					usage();
12130715Sbostic 				op = EDIT;
12230715Sbostic 				break;
12330715Sbostic 			case 'r':
12430715Sbostic 				++rflag;
12530715Sbostic 				break;
12630715Sbostic 			case 'w':
12734032Skarels 				if (op != UNSPEC)
12834032Skarels 					usage();
12930715Sbostic 				op = WRITE;
13030715Sbostic 				break;
13134032Skarels #ifdef DEBUG
13234032Skarels 			case 'd':
13334032Skarels 				debug++;
13434032Skarels 				break;
13534032Skarels #endif
13630715Sbostic 			case '?':
13730715Sbostic 			default:
13830715Sbostic 				usage();
13930715Sbostic 		}
14030715Sbostic 	argc -= optind;
14130715Sbostic 	argv += optind;
14234032Skarels 	if (op == UNSPEC)
14334032Skarels 		op = READ;
14430715Sbostic 	if (argc < 1)
14530715Sbostic 		usage();
14630715Sbostic 
14730715Sbostic 	dkname = argv[0];
14830418Skarels 	if (dkname[0] != '/') {
14937945Sbostic 		(void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION);
15030418Skarels 		specname = np;
15130418Skarels 		np += strlen(specname) + 1;
15230418Skarels 	} else
15330418Skarels 		specname = dkname;
15430418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
15530418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
15637945Sbostic 		(void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname);
15730418Skarels 		np = namebuf + strlen(specname) + 1;
15830418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
15930418Skarels 	}
16030418Skarels 	if (f < 0)
16130418Skarels 		Perror(specname);
16230418Skarels 
16330715Sbostic 	switch(op) {
16430715Sbostic 	case EDIT:
16530715Sbostic 		if (argc != 1)
16630715Sbostic 			usage();
16734032Skarels 		lp = readlabel(f);
16834641Skarels 		error = edit(lp, f);
16930715Sbostic 		break;
17034032Skarels 	case NOWRITE: {
17134032Skarels 		int flag = 0;
17234032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
17334032Skarels 			Perror("ioctl DIOCWLABEL");
17434032Skarels 		break;
17534032Skarels 	}
17630418Skarels 	case READ:
17730715Sbostic 		if (argc != 1)
17830715Sbostic 			usage();
17934032Skarels 		lp = readlabel(f);
18030418Skarels 		display(stdout, lp);
18134641Skarels 		error = checklabel(lp);
18230418Skarels 		break;
18330715Sbostic 	case RESTORE:
18430715Sbostic #ifdef BOOT
18534032Skarels 		if (rflag) {
18634032Skarels 			if (argc == 4) {	/* [ priboot secboot ] */
18734032Skarels 				xxboot = argv[2];
18834032Skarels 				bootxx = argv[3];
18934032Skarels 				lab.d_secsize = DEV_BSIZE;	/* XXX */
19034032Skarels 				lab.d_bbsize = BBSIZE;		/* XXX */
19134032Skarels 			}
19234032Skarels 			else if (argc == 3) 	/* [ disktype ] */
19334032Skarels 				makelabel(argv[2], (char *)NULL, &lab);
19434032Skarels 			else {
19534032Skarels 				fprintf(stderr,
19634032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
19734032Skarels 				exit(1);
19834032Skarels 			}
19934032Skarels 		}
20034032Skarels 		else
20131617Skarels #endif
20230715Sbostic 		if (argc != 2)
20330715Sbostic 			usage();
20431617Skarels 		lp = makebootarea(bootarea, &lab);
20530715Sbostic 		if (!(t = fopen(argv[1],"r")))
20630715Sbostic 			Perror(argv[1]);
20730715Sbostic 		if (getasciilabel(t, lp))
20834641Skarels 			error = writelabel(f, bootarea, lp);
20930418Skarels 		break;
21030418Skarels 	case WRITE:
21130715Sbostic 		type = argv[1];
21230715Sbostic #ifdef BOOT
21330715Sbostic 		if (argc > 5 || argc < 2)
21430715Sbostic 			usage();
21530715Sbostic 		if (argc > 3) {
21630715Sbostic 			bootxx = argv[--argc];
21730715Sbostic 			xxboot = argv[--argc];
21830715Sbostic 		}
21930715Sbostic #else
22030715Sbostic 		if (argc > 3 || argc < 2)
22130715Sbostic 			usage();
22230715Sbostic #endif
22330715Sbostic 		if (argc > 2)
22430715Sbostic 			name = argv[--argc];
22530418Skarels 		makelabel(type, name, &lab);
22631617Skarels 		lp = makebootarea(bootarea, &lab);
22730418Skarels 		*lp = lab;
22830715Sbostic 		if (checklabel(lp) == 0)
22934641Skarels 			error = writelabel(f, bootarea, lp);
23030418Skarels 		break;
23134032Skarels 	case WRITEABLE: {
23234032Skarels 		int flag = 1;
23334032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
23434032Skarels 			Perror("ioctl DIOCWLABEL");
23534032Skarels 		break;
23630418Skarels 	}
23734032Skarels 	}
23834641Skarels 	exit(error);
23930418Skarels }
24030418Skarels 
24134032Skarels /*
24234032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
24334032Skarels  * effect, set the names of the primary and secondary boot files
24434032Skarels  * if specified.
24534032Skarels  */
24630418Skarels makelabel(type, name, lp)
24730418Skarels 	char *type, *name;
24830418Skarels 	register struct disklabel *lp;
24930418Skarels {
25030418Skarels 	register struct disklabel *dp;
25134032Skarels 	char *strcpy();
25230418Skarels 
25330418Skarels 	dp = getdiskbyname(type);
25430418Skarels 	if (dp == NULL) {
25530418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
25630418Skarels 		exit(1);
25730418Skarels 	}
25830418Skarels 	*lp = *dp;
25934032Skarels #ifdef BOOT
26034032Skarels 	/*
26134032Skarels 	 * Check if disktab specifies the bootstraps (b0 or b1).
26234032Skarels 	 */
26334032Skarels 	if (!xxboot && lp->d_boot0) {
26434032Skarels 		if (*lp->d_boot0 != '/')
26534032Skarels 			(void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
26634032Skarels 		else
26734032Skarels 			(void)strcpy(boot0, lp->d_boot0);
26834032Skarels 		xxboot = boot0;
26934032Skarels 	}
27034032Skarels 	if (!bootxx && lp->d_boot1) {
27134032Skarels 		if (*lp->d_boot1 != '/')
27234032Skarels 			(void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
27334032Skarels 		else
27434032Skarels 			(void)strcpy(boot1, lp->d_boot1);
27534032Skarels 		bootxx = boot1;
27634032Skarels 	}
27734032Skarels 	/*
27834032Skarels 	 * If bootstraps not specified anywhere, makebootarea()
27934032Skarels 	 * will choose ones based on the name of the disk special
28034032Skarels 	 * file. E.g. /dev/ra0 -> raboot, bootra
28134032Skarels 	 */
28234032Skarels #endif /*BOOT*/
28334032Skarels 	/* d_packname is union d_boot[01], so zero */
28434032Skarels 	bzero(lp->d_packname, sizeof(lp->d_packname));
28530418Skarels 	if (name)
28634032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
28730418Skarels }
28830418Skarels 
28930418Skarels writelabel(f, boot, lp)
29030418Skarels 	int f;
29130418Skarels 	char *boot;
29230418Skarels 	register struct disklabel *lp;
29330418Skarels {
29430715Sbostic 	register int i;
29534032Skarels 	int flag;
29634032Skarels 	off_t lseek();
29730418Skarels 
29830418Skarels 	lp->d_magic = DISKMAGIC;
29930418Skarels 	lp->d_magic2 = DISKMAGIC;
30030418Skarels 	lp->d_checksum = 0;
30130418Skarels 	lp->d_checksum = dkcksum(lp);
30230677Skarels 	if (rflag) {
30334032Skarels 		/*
30434032Skarels 		 * First set the kernel disk label,
30534032Skarels 		 * then write a label to the raw disk.
30634032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
30734032Skarels 		 * keep going; otherwise, the kernel consistency checks
30834032Skarels 		 * may prevent us from changing the current (in-core)
30934032Skarels 		 * label.
31034032Skarels 		 */
31134032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
31234641Skarels 		    errno != ENODEV && errno != ENOTTY) {
31334641Skarels 			l_perror("ioctl DIOCSDINFO");
31434641Skarels 			return (1);
31534641Skarels 		}
31631617Skarels 		(void)lseek(f, (off_t)0, L_SET);
31734032Skarels 		/*
31834032Skarels 		 * write enable label sector before write (if necessary),
31934032Skarels 		 * disable after writing.
32034032Skarels 		 */
32134032Skarels 		flag = 1;
32234032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
32334032Skarels 			perror("ioctl DIOCWLABEL");
32434641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
32534641Skarels 			perror("write");
32634641Skarels 			return (1);
32734641Skarels 		}
32834032Skarels 		flag = 0;
32934032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
33034641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
33134641Skarels 		l_perror("ioctl DIOCWDINFO");
33234641Skarels 		return (1);
33334641Skarels 	}
33434032Skarels #ifdef vax
33530677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
33630677Skarels 		daddr_t alt;
33730677Skarels 
33830677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
33930677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
34030715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
34130677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
34230677Skarels 				int oerrno = errno;
34330677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
34430677Skarels 				errno = oerrno;
34530677Skarels 				perror("write");
34630677Skarels 			}
34730418Skarels 		}
34830418Skarels 	}
34930419Skarels #endif
35034641Skarels 	return (0);
35130418Skarels }
35230418Skarels 
35334641Skarels l_perror(s)
35434641Skarels 	char *s;
35534641Skarels {
35634641Skarels 	int saverrno = errno;
35734641Skarels 
35834641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
35934641Skarels 
36034641Skarels 	switch (saverrno) {
36134641Skarels 
36234641Skarels 	case ESRCH:
36334641Skarels 		fprintf(stderr, "No disk label on disk;\n");
36434641Skarels 		fprintf(stderr,
36534641Skarels 		    "use \"disklabel -r\" to install initial label\n");
36634641Skarels 		break;
36734641Skarels 
36834641Skarels 	case EINVAL:
36934641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
37034641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
37134641Skarels 		break;
37234641Skarels 
37334641Skarels 	case EBUSY:
37434641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
37534641Skarels 		break;
37634641Skarels 
37734641Skarels 	case EXDEV:
37834641Skarels 		fprintf(stderr,
37934641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
38034641Skarels 		break;
38134641Skarels 
38234641Skarels 	default:
38334641Skarels 		errno = saverrno;
38434641Skarels 		perror((char *)NULL);
38534641Skarels 		break;
38634641Skarels 	}
38734641Skarels }
38834641Skarels 
38930418Skarels /*
39031617Skarels  * Fetch disklabel for disk.
39131617Skarels  * Use ioctl to get label unless -r flag is given.
39230418Skarels  */
39330418Skarels struct disklabel *
39434032Skarels readlabel(f)
39534032Skarels 	int f;
39630418Skarels {
39730418Skarels 	register struct disklabel *lp;
39830418Skarels 
39934032Skarels 	if (rflag) {
40031617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
40131401Skarels 			Perror(specname);
40231617Skarels 		for (lp = (struct disklabel *)bootarea;
40331617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
40430677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
40530677Skarels 			if (lp->d_magic == DISKMAGIC &&
40630677Skarels 			    lp->d_magic2 == DISKMAGIC)
40730677Skarels 				break;
40831617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
40930677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
41030677Skarels 		    dkcksum(lp) != 0) {
41130677Skarels 			fprintf(stderr,
41230418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
41334032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
41434032Skarels 			exit (1);
41530677Skarels 		}
41634032Skarels 	} else {
41734032Skarels 		lp = &lab;
41834032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
41934032Skarels 			Perror("ioctl DIOCGDINFO");
42030418Skarels 	}
42130418Skarels 	return (lp);
42230418Skarels }
42330418Skarels 
42430418Skarels struct disklabel *
42531617Skarels makebootarea(boot, dp)
42630418Skarels 	char *boot;
42730418Skarels 	register struct disklabel *dp;
42830418Skarels {
42930418Skarels 	struct disklabel *lp;
43030418Skarels 	register char *p;
43130418Skarels 	int b;
43230418Skarels #ifdef BOOT
43330715Sbostic 	char	*dkbasename;
43434032Skarels #endif /*BOOT*/
43530715Sbostic 
43634032Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
43734032Skarels 	    LABELOFFSET);
43834032Skarels #ifdef BOOT
43934032Skarels 	if (!rflag)
44034032Skarels 		return (lp);
44134032Skarels 
44234032Skarels 	if (xxboot == NULL || bootxx == NULL) {
44330418Skarels 		dkbasename = np;
44430418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
44530418Skarels 			p = dkname;
44630418Skarels 		else
44730418Skarels 			p++;
44830418Skarels 		while (*p && !isdigit(*p))
44930418Skarels 			*np++ = *p++;
45030418Skarels 		*np++ = '\0';
45130418Skarels 
45234032Skarels 		if (xxboot == NULL) {
45334032Skarels 			(void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
45434032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
45534032Skarels 				dkbasename++;
45634032Skarels 			xxboot = np;
45734032Skarels 			(void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
45834032Skarels 			np += strlen(xxboot) + 1;
45934032Skarels 		}
46034032Skarels 		if (bootxx == NULL) {
46134032Skarels 			(void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
46234032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
46334032Skarels 				dkbasename++;
46434032Skarels 			bootxx = np;
46534032Skarels 			(void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
46634032Skarels 			np += strlen(bootxx) + 1;
46734032Skarels 		}
46830418Skarels 	}
46934032Skarels #ifdef DEBUG
47034032Skarels 	if (debug)
47134032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
47234032Skarels 			xxboot, bootxx);
47334032Skarels #endif
47430418Skarels 
47530418Skarels 	b = open(xxboot, O_RDONLY);
47630418Skarels 	if (b < 0)
47730418Skarels 		Perror(xxboot);
47830715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
47930418Skarels 		Perror(xxboot);
48030418Skarels 	close(b);
48130418Skarels 	b = open(bootxx, O_RDONLY);
48230418Skarels 	if (b < 0)
48330418Skarels 		Perror(bootxx);
48430715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
48530418Skarels 		Perror(bootxx);
48630715Sbostic 	(void)close(b);
48734032Skarels #endif /*BOOT*/
48830418Skarels 
48930418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
49030418Skarels 		if (*p) {
49130418Skarels 			fprintf(stderr,
49230418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
49330418Skarels 			exit(2);
49430418Skarels 		}
49530418Skarels 	return (lp);
49630418Skarels }
49730418Skarels 
49830418Skarels display(f, lp)
49930418Skarels 	FILE *f;
50030418Skarels 	register struct disklabel *lp;
50130418Skarels {
50230715Sbostic 	register int i, j;
50330418Skarels 	register struct partition *pp;
50430418Skarels 
50530418Skarels 	fprintf(f, "# %s:\n", specname);
50630418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
50730418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
50830418Skarels 	else
50930418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
51030418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
51134032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
51231401Skarels 	fprintf(f, "flags:");
51330418Skarels 	if (lp->d_flags & D_REMOVABLE)
51431401Skarels 		fprintf(f, " removeable");
51530418Skarels 	if (lp->d_flags & D_ECC)
51631401Skarels 		fprintf(f, " ecc");
51730418Skarels 	if (lp->d_flags & D_BADSECT)
51831401Skarels 		fprintf(f, " badsect");
51930418Skarels 	fprintf(f, "\n");
52030418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
52130418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
52230418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
52331386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
52430418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
52530715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
52630418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
52730418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
52830418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
52930418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
53030418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
53130418Skarels 	fprintf(f, "drivedata: ");
53230418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
53330418Skarels 		if (lp->d_drivedata[i])
53430418Skarels 			break;
53530418Skarels 	if (i < 0)
53630418Skarels 		i = 0;
53730418Skarels 	for (j = 0; j <= i; j++)
53830418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
53930418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
54030863Skarels 	fprintf(f,
54130863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
54230418Skarels 	pp = lp->d_partitions;
54330418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
54430418Skarels 		if (pp->p_size) {
54530863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
54630863Skarels 			   pp->p_size, pp->p_offset);
54730418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
54830418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
54930418Skarels 			else
55030418Skarels 				fprintf(f, "%8d", pp->p_fstype);
55130863Skarels 			switch (pp->p_fstype) {
55230863Skarels 
55330863Skarels 			case FS_UNUSED:				/* XXX */
55430863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
55530863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
55630863Skarels 				break;
55730863Skarels 
55830863Skarels 			case FS_BSDFFS:
55930863Skarels 				fprintf(f, "    %5d %5d %5d ",
56030863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
56130863Skarels 				    pp->p_cpg);
56230863Skarels 				break;
56330863Skarels 
56430863Skarels 			default:
56530863Skarels 				fprintf(f, "%20.20s", "");
56630863Skarels 				break;
56730863Skarels 			}
56830418Skarels 			fprintf(f, "\t# (Cyl. %4d",
56930418Skarels 			    pp->p_offset / lp->d_secpercyl);
57030418Skarels 			if (pp->p_offset % lp->d_secpercyl)
57130418Skarels 			    putc('*', f);
57230418Skarels 			else
57330418Skarels 			    putc(' ', f);
57430418Skarels 			fprintf(f, "- %d",
57530418Skarels 			    (pp->p_offset +
57630418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
57730418Skarels 			    lp->d_secpercyl - 1);
57830418Skarels 			if (pp->p_size % lp->d_secpercyl)
57930418Skarels 			    putc('*', f);
58030863Skarels 			fprintf(f, ")\n");
58130418Skarels 		}
58230418Skarels 	}
58332121Stef 	fflush(f);
58430418Skarels }
58530418Skarels 
58634641Skarels edit(lp, f)
58730715Sbostic 	struct disklabel *lp;
58834641Skarels 	int f;
58930418Skarels {
59030715Sbostic 	register int c;
59130715Sbostic 	struct disklabel label;
59230715Sbostic 	FILE *fd;
59330715Sbostic 	char *mktemp();
59430715Sbostic 
59530715Sbostic 	(void) mktemp(tmpfil);
59630715Sbostic 	fd = fopen(tmpfil, "w");
59730715Sbostic 	if (fd == NULL) {
59830715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
59934641Skarels 		return (1);
60030715Sbostic 	}
60130715Sbostic 	(void)fchmod(fd, 0600);
60230715Sbostic 	display(fd, lp);
60330715Sbostic 	fclose(fd);
60430715Sbostic 	for (;;) {
60530715Sbostic 		if (!editit())
60630715Sbostic 			break;
60730715Sbostic 		fd = fopen(tmpfil, "r");
60830715Sbostic 		if (fd == NULL) {
60934032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
61034032Skarels 				tmpfil);
61130715Sbostic 			break;
61230715Sbostic 		}
61330863Skarels 		bzero((char *)&label, sizeof(label));
61430715Sbostic 		if (getasciilabel(fd, &label)) {
61530715Sbostic 			*lp = label;
61634641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
61734641Skarels 				(void) unlink(tmpfil);
61834641Skarels 				return (0);
61934641Skarels 			}
62030715Sbostic 		}
62130715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
62230715Sbostic 		c = getchar();
62330715Sbostic 		if (c != EOF && c != (int)'\n')
62430715Sbostic 			while (getchar() != (int)'\n')
62530715Sbostic 				;
62630715Sbostic 		if  (c == (int)'n')
62730715Sbostic 			break;
62830715Sbostic 	}
62930715Sbostic 	(void) unlink(tmpfil);
63034641Skarels 	return (1);
63130418Skarels }
63230418Skarels 
63330715Sbostic editit()
63430715Sbostic {
63530715Sbostic 	register int pid, xpid;
63630715Sbostic 	int stat, omask;
63730715Sbostic 	extern char *getenv();
63830418Skarels 
63930715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
64030715Sbostic 	while ((pid = fork()) < 0) {
64130715Sbostic 		extern int errno;
64230715Sbostic 
64330715Sbostic 		if (errno == EPROCLIM) {
64430715Sbostic 			fprintf(stderr, "You have too many processes\n");
64530715Sbostic 			return(0);
64630715Sbostic 		}
64730715Sbostic 		if (errno != EAGAIN) {
64830715Sbostic 			perror("fork");
64930715Sbostic 			return(0);
65030715Sbostic 		}
65130715Sbostic 		sleep(1);
65230715Sbostic 	}
65330715Sbostic 	if (pid == 0) {
65430715Sbostic 		register char *ed;
65530715Sbostic 
65630715Sbostic 		sigsetmask(omask);
65730715Sbostic 		setgid(getgid());
65830715Sbostic 		setuid(getuid());
65930715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
66030715Sbostic 			ed = DEFEDITOR;
66130715Sbostic 		execlp(ed, ed, tmpfil, 0);
66230715Sbostic 		perror(ed);
66330715Sbostic 		exit(1);
66430715Sbostic 	}
66530715Sbostic 	while ((xpid = wait(&stat)) >= 0)
66630715Sbostic 		if (xpid == pid)
66730715Sbostic 			break;
66830715Sbostic 	sigsetmask(omask);
66930715Sbostic 	return(!stat);
67030715Sbostic }
67130715Sbostic 
67230715Sbostic char *
67330715Sbostic skip(cp)
67430715Sbostic 	register char *cp;
67530715Sbostic {
67630715Sbostic 
67730715Sbostic 	while (*cp != '\0' && isspace(*cp))
67830715Sbostic 		cp++;
67930715Sbostic 	if (*cp == '\0' || *cp == '#')
68030715Sbostic 		return ((char *)NULL);
68130715Sbostic 	return (cp);
68230715Sbostic }
68330715Sbostic 
68430715Sbostic char *
68530715Sbostic word(cp)
68630715Sbostic 	register char *cp;
68730715Sbostic {
68830715Sbostic 	register char c;
68930715Sbostic 
69031401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
69131401Skarels 		cp++;
69230715Sbostic 	if ((c = *cp) != '\0') {
69330715Sbostic 		*cp++ = '\0';
69430715Sbostic 		if (c != '#')
69530715Sbostic 			return (skip(cp));
69630715Sbostic 	}
69730715Sbostic 	return ((char *)NULL);
69830715Sbostic }
69930715Sbostic 
70030418Skarels /*
70130418Skarels  * Read an ascii label in from fd f,
70230418Skarels  * in the same format as that put out by display(),
70330418Skarels  * and fill in lp.
70430418Skarels  */
70530418Skarels getasciilabel(f, lp)
70630715Sbostic 	FILE	*f;
70730418Skarels 	register struct disklabel *lp;
70830418Skarels {
70930715Sbostic 	register char **cpp, *cp;
71030863Skarels 	register struct partition *pp;
71130715Sbostic 	char *tp, *s, line[BUFSIZ];
71230715Sbostic 	int v, lineno = 0, errors = 0;
71330715Sbostic 
71430715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
71530715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
71630715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
71730715Sbostic 		lineno++;
71830715Sbostic 		if (cp = index(line,'\n'))
71930715Sbostic 			*cp = '\0';
72030715Sbostic 		cp = skip(line);
72130715Sbostic 		if (cp == NULL)
72230715Sbostic 			continue;
72330715Sbostic 		tp = index(cp, ':');
72430715Sbostic 		if (tp == NULL) {
72530715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
72630715Sbostic 			errors++;
72730715Sbostic 			continue;
72830715Sbostic 		}
72930715Sbostic 		*tp++ = '\0', tp = skip(tp);
73030715Sbostic 		if (streq(cp, "type")) {
73130715Sbostic 			if (tp == NULL)
73230715Sbostic 				tp = "unknown";
73330715Sbostic 			cpp = dktypenames;
73430715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
73530715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
73630715Sbostic 					lp->d_type = cpp - dktypenames;
73730715Sbostic 					goto next;
73830715Sbostic 				}
73930715Sbostic 			v = atoi(tp);
74030715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
74130715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
74230715Sbostic 				    "Warning, unknown disk type", v);
74330715Sbostic 			lp->d_type = v;
74430715Sbostic 			continue;
74530715Sbostic 		}
74630715Sbostic 		if (streq(cp, "flags")) {
74734032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
74834032Skarels 				tp = word(cp);
74930715Sbostic 				if (streq(cp, "removeable"))
75030715Sbostic 					v |= D_REMOVABLE;
75130715Sbostic 				else if (streq(cp, "ecc"))
75230715Sbostic 					v |= D_ECC;
75330715Sbostic 				else if (streq(cp, "badsect"))
75430715Sbostic 					v |= D_BADSECT;
75530715Sbostic 				else {
75630715Sbostic 					fprintf(stderr,
75730715Sbostic 					    "line %d: %s: bad flag\n",
75830715Sbostic 					    lineno, cp);
75930715Sbostic 					errors++;
76030715Sbostic 				}
76130715Sbostic 			}
76230715Sbostic 			lp->d_flags = v;
76330715Sbostic 			continue;
76430715Sbostic 		}
76530715Sbostic 		if (streq(cp, "drivedata")) {
76630715Sbostic 			register int i;
76730715Sbostic 
76831386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
76930715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
77031386Skarels 				tp = word(cp);
77130715Sbostic 			}
77230715Sbostic 			continue;
77330715Sbostic 		}
77430715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
77530863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
77630715Sbostic 				fprintf(stderr,
77730715Sbostic 				    "line %d: bad # of partitions\n", lineno);
77830863Skarels 				lp->d_npartitions = MAXPARTITIONS;
77930863Skarels 				errors++;
78030863Skarels 			} else
78130715Sbostic 				lp->d_npartitions = v;
78230715Sbostic 			continue;
78330715Sbostic 		}
78430715Sbostic 		if (tp == NULL)
78530715Sbostic 			tp = "";
78630715Sbostic 		if (streq(cp, "disk")) {
78730715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
78830715Sbostic 			continue;
78930715Sbostic 		}
79030715Sbostic 		if (streq(cp, "label")) {
79134032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
79230715Sbostic 			continue;
79330715Sbostic 		}
79430715Sbostic 		if (streq(cp, "bytes/sector")) {
79530715Sbostic 			v = atoi(tp);
79630715Sbostic 			if (v <= 0 || (v % 512) != 0) {
79730715Sbostic 				fprintf(stderr,
79830715Sbostic 				    "line %d: %s: bad sector size\n",
79930715Sbostic 				    lineno, tp);
80030715Sbostic 				errors++;
80130715Sbostic 			} else
80230715Sbostic 				lp->d_secsize = v;
80330715Sbostic 			continue;
80430715Sbostic 		}
80530715Sbostic 		if (streq(cp, "sectors/track")) {
80630715Sbostic 			v = atoi(tp);
80730715Sbostic 			if (v <= 0) {
80830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
80930715Sbostic 				    lineno, tp, cp);
81030715Sbostic 				errors++;
81130715Sbostic 			} else
81230715Sbostic 				lp->d_nsectors = v;
81330715Sbostic 			continue;
81430715Sbostic 		}
81531386Skarels 		if (streq(cp, "sectors/cylinder")) {
81631386Skarels 			v = atoi(tp);
81731386Skarels 			if (v <= 0) {
81831386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
81931386Skarels 				    lineno, tp, cp);
82031386Skarels 				errors++;
82131386Skarels 			} else
82231386Skarels 				lp->d_secpercyl = v;
82331386Skarels 			continue;
82431386Skarels 		}
82530715Sbostic 		if (streq(cp, "tracks/cylinder")) {
82630715Sbostic 			v = atoi(tp);
82730715Sbostic 			if (v <= 0) {
82830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
82930715Sbostic 				    lineno, tp, cp);
83030715Sbostic 				errors++;
83130715Sbostic 			} else
83230715Sbostic 				lp->d_ntracks = v;
83330715Sbostic 			continue;
83430715Sbostic 		}
83530715Sbostic 		if (streq(cp, "cylinders")) {
83630715Sbostic 			v = atoi(tp);
83730715Sbostic 			if (v <= 0) {
83830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
83930715Sbostic 				    lineno, tp, cp);
84030715Sbostic 				errors++;
84130715Sbostic 			} else
84230715Sbostic 				lp->d_ncylinders = v;
84330715Sbostic 			continue;
84430715Sbostic 		}
84530715Sbostic 		if (streq(cp, "rpm")) {
84630715Sbostic 			v = atoi(tp);
84730715Sbostic 			if (v <= 0) {
84830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
84930715Sbostic 				    lineno, tp, cp);
85030715Sbostic 				errors++;
85130715Sbostic 			} else
85230715Sbostic 				lp->d_rpm = v;
85330715Sbostic 			continue;
85430715Sbostic 		}
85530715Sbostic 		if (streq(cp, "interleave")) {
85630715Sbostic 			v = atoi(tp);
85730715Sbostic 			if (v <= 0) {
85830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
85930715Sbostic 				    lineno, tp, cp);
86030715Sbostic 				errors++;
86130715Sbostic 			} else
86230715Sbostic 				lp->d_interleave = v;
86330715Sbostic 			continue;
86430715Sbostic 		}
86530715Sbostic 		if (streq(cp, "trackskew")) {
86630715Sbostic 			v = atoi(tp);
86730715Sbostic 			if (v < 0) {
86830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
86930715Sbostic 				    lineno, tp, cp);
87030715Sbostic 				errors++;
87130715Sbostic 			} else
87230715Sbostic 				lp->d_trackskew = v;
87330715Sbostic 			continue;
87430715Sbostic 		}
87530715Sbostic 		if (streq(cp, "cylinderskew")) {
87630715Sbostic 			v = atoi(tp);
87730715Sbostic 			if (v < 0) {
87830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
87930715Sbostic 				    lineno, tp, cp);
88030715Sbostic 				errors++;
88130715Sbostic 			} else
88230715Sbostic 				lp->d_cylskew = v;
88330715Sbostic 			continue;
88430715Sbostic 		}
88530715Sbostic 		if (streq(cp, "headswitch")) {
88630715Sbostic 			v = atoi(tp);
88730715Sbostic 			if (v < 0) {
88830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
88930715Sbostic 				    lineno, tp, cp);
89030715Sbostic 				errors++;
89130715Sbostic 			} else
89230715Sbostic 				lp->d_headswitch = v;
89330715Sbostic 			continue;
89430715Sbostic 		}
89530715Sbostic 		if (streq(cp, "track-to-track seek")) {
89630715Sbostic 			v = atoi(tp);
89730715Sbostic 			if (v < 0) {
89830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
89930715Sbostic 				    lineno, tp, cp);
90030715Sbostic 				errors++;
90130715Sbostic 			} else
90230715Sbostic 				lp->d_trkseek = v;
90330715Sbostic 			continue;
90430715Sbostic 		}
90530715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
90630863Skarels 			unsigned part = *cp - 'a';
90730715Sbostic 
90830863Skarels 			if (part > lp->d_npartitions) {
90930715Sbostic 				fprintf(stderr,
91030715Sbostic 				    "line %d: bad partition name\n", lineno);
91130715Sbostic 				errors++;
91230715Sbostic 				continue;
91330715Sbostic 			}
91430863Skarels 			pp = &lp->d_partitions[part];
91530863Skarels #define NXTNUM(n) { \
91630863Skarels 	cp = tp, tp = word(cp); \
91730863Skarels 	if (tp == NULL) \
91830863Skarels 		tp = cp; \
91930863Skarels 	(n) = atoi(cp); \
92030863Skarels      }
92130863Skarels 
92230863Skarels 			NXTNUM(v);
92330715Sbostic 			if (v < 0) {
92430715Sbostic 				fprintf(stderr,
92530715Sbostic 				    "line %d: %s: bad partition size\n",
92630715Sbostic 				    lineno, cp);
92730715Sbostic 				errors++;
92830715Sbostic 			} else
92930863Skarels 				pp->p_size = v;
93030863Skarels 			NXTNUM(v);
93130715Sbostic 			if (v < 0) {
93230715Sbostic 				fprintf(stderr,
93330715Sbostic 				    "line %d: %s: bad partition offset\n",
93430715Sbostic 				    lineno, cp);
93530715Sbostic 				errors++;
93630715Sbostic 			} else
93730863Skarels 				pp->p_offset = v;
93830715Sbostic 			cp = tp, tp = word(cp);
93930715Sbostic 			cpp = fstypenames;
94030715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
94130715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
94230863Skarels 					pp->p_fstype = cpp - fstypenames;
94330863Skarels 					goto gottype;
94430715Sbostic 				}
94534032Skarels 			if (isdigit(*cp))
94634032Skarels 				v = atoi(cp);
94734032Skarels 			else
94834032Skarels 				v = FSMAXTYPES;
94934032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
95030715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
95130715Sbostic 				    "Warning, unknown filesystem type", cp);
95234032Skarels 				v = FS_UNUSED;
95334032Skarels 			}
95430863Skarels 			pp->p_fstype = v;
95530863Skarels 	gottype:
95630863Skarels 
95730863Skarels 			switch (pp->p_fstype) {
95830863Skarels 
95930863Skarels 			case FS_UNUSED:				/* XXX */
96030863Skarels 				NXTNUM(pp->p_fsize);
96130863Skarels 				if (pp->p_fsize == 0)
96230863Skarels 					break;
96330863Skarels 				NXTNUM(v);
96430863Skarels 				pp->p_frag = v / pp->p_fsize;
96530863Skarels 				break;
96630863Skarels 
96730863Skarels 			case FS_BSDFFS:
96830863Skarels 				NXTNUM(pp->p_fsize);
96930863Skarels 				if (pp->p_fsize == 0)
97030863Skarels 					break;
97130863Skarels 				NXTNUM(v);
97230863Skarels 				pp->p_frag = v / pp->p_fsize;
97330863Skarels 				NXTNUM(pp->p_cpg);
97430863Skarels 				break;
97530863Skarels 
97630863Skarels 			default:
97730863Skarels 				break;
97830863Skarels 			}
97930715Sbostic 			continue;
98030715Sbostic 		}
98130715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
98230715Sbostic 		    lineno, cp);
98330715Sbostic 		errors++;
98430715Sbostic 	next:
98530715Sbostic 		;
98630715Sbostic 	}
98730715Sbostic 	errors += checklabel(lp);
98830715Sbostic 	return (errors == 0);
98930418Skarels }
99030418Skarels 
99130715Sbostic /*
99230715Sbostic  * Check disklabel for errors and fill in
99330715Sbostic  * derived fields according to supplied values.
99430715Sbostic  */
99530715Sbostic checklabel(lp)
99630715Sbostic 	register struct disklabel *lp;
99730418Skarels {
99830715Sbostic 	register struct partition *pp;
99930715Sbostic 	int i, errors = 0;
100030715Sbostic 	char part;
100130418Skarels 
100230715Sbostic 	if (lp->d_secsize == 0) {
100330715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
100430715Sbostic 		return (1);
100530715Sbostic 	}
100630715Sbostic 	if (lp->d_nsectors == 0) {
100730715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
100830715Sbostic 		return (1);
100930715Sbostic 	}
101030715Sbostic 	if (lp->d_ntracks == 0) {
101130715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
101230715Sbostic 		return (1);
101330715Sbostic 	}
101430715Sbostic 	if  (lp->d_ncylinders == 0) {
101530715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
101630715Sbostic 		errors++;
101730715Sbostic 	}
101830715Sbostic 	if (lp->d_rpm == 0)
101930715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
102030715Sbostic 	if (lp->d_secpercyl == 0)
102130715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
102230715Sbostic 	if (lp->d_secperunit == 0)
102330715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
102430715Sbostic 	if (lp->d_bbsize == 0) {
102530715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
102630715Sbostic 		errors++;
102730715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
102830715Sbostic 		Warning("boot block size %% sector-size != 0\n");
102930715Sbostic 	if (lp->d_sbsize == 0) {
103030715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
103130715Sbostic 		errors++;
103230715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
103330715Sbostic 		Warning("super block size %% sector-size != 0\n");
103430715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
103530715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
103630715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
103730715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
103830715Sbostic 		part = 'a' + i;
103930715Sbostic 		pp = &lp->d_partitions[i];
104030715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
104130715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
104230715Sbostic 			    part, pp->p_offset);
104330715Sbostic #ifdef notdef
104430715Sbostic 		if (pp->p_size % lp->d_secpercyl)
104530715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
104630715Sbostic 			    part);
104730715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
104830715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
104930715Sbostic 			    part);
105030715Sbostic #endif
105130715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
105230715Sbostic 			fprintf(stderr,
105330715Sbostic 			    "partition %c: offset past end of unit\n", part);
105430715Sbostic 			errors++;
105530715Sbostic 		}
105630715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
105730715Sbostic 			fprintf(stderr,
105830715Sbostic 			    "partition %c: partition extends past end of unit\n",
105930715Sbostic 			    part);
106030715Sbostic 			errors++;
106130715Sbostic 		}
106230715Sbostic 	}
106330715Sbostic 	for (; i < MAXPARTITIONS; i++) {
106430715Sbostic 		part = 'a' + i;
106530715Sbostic 		pp = &lp->d_partitions[i];
106630715Sbostic 		if (pp->p_size || pp->p_offset)
106730715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
106834032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
106930715Sbostic 	}
107030715Sbostic 	return (errors);
107130715Sbostic }
107230715Sbostic 
107330715Sbostic /*VARARGS1*/
107430715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
107530715Sbostic 	char *fmt;
107630715Sbostic {
107730715Sbostic 
107830715Sbostic 	fprintf(stderr, "Warning, ");
107930715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
108030715Sbostic 	fprintf(stderr, "\n");
108130715Sbostic }
108230715Sbostic 
108330715Sbostic Perror(str)
108430715Sbostic 	char *str;
108530715Sbostic {
108630715Sbostic 	fputs("disklabel: ", stderr); perror(str);
108730418Skarels 	exit(4);
108830418Skarels }
108930715Sbostic 
109030715Sbostic usage()
109130715Sbostic {
109230715Sbostic #ifdef BOOT
109334032Skarels 	fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
109430715Sbostic "usage: disklabel [-r] disk", "(to read label)",
109530715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
109630715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
109734032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
109834032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
109930715Sbostic #else
110034032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
110130715Sbostic "usage: disklabel [-r] disk", "(to read label)",
110230715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
110330715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
110434032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
110534032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
110630715Sbostic #endif
110730715Sbostic 	exit(1);
110830715Sbostic }
1109