xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 57996)
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*57996Sralph static char sccsid[] = "@(#)disklabel.c	5.23 (Berkeley) 02/15/93";
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>
2730418Skarels #define DKTYPENAMES
2830418Skarels #include <sys/disklabel.h>
2951615Sbostic #include <ufs/ffs/fs.h>
30*57996Sralph #include <unistd.h>
3151615Sbostic #include <string.h>
3237261Sbostic #include <stdio.h>
3337261Sbostic #include <ctype.h>
3437261Sbostic #include "pathnames.h"
3530418Skarels 
3630418Skarels /*
3730418Skarels  * Disklabel: read and write disklabels.
3830418Skarels  * The label is usually placed on one of the first sectors of the disk.
3930418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
4030418Skarels  * in which case the label is embedded in the bootstrap.
4130418Skarels  * The bootstrap source must leave space at the proper offset
4230418Skarels  * for the label on such machines.
4330418Skarels  */
4430418Skarels 
4553196Sralph #if defined(vax) || defined(i386) || defined(mips)
4630677Skarels #define RAWPARTITION	'c'
4730677Skarels #else
4830677Skarels #define RAWPARTITION	'a'
4930677Skarels #endif
5030677Skarels 
5130677Skarels #ifndef BBSIZE
5230418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
5330677Skarels #endif
5430418Skarels 
5553196Sralph #if defined(vax) || defined(i386) || defined(mips)
5630418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
5737261Sbostic #define	BOOTDIR	_PATH_BOOTDIR		/* source of boot binaries */
5830677Skarels #else
5930677Skarels #ifdef lint
6030677Skarels #define	BOOT
6130418Skarels #endif
6230677Skarels #endif
6330418Skarels 
6438505Sbostic #define	DEFEDITOR	_PATH_VI
6530715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
6630715Sbostic 
6730715Sbostic #ifdef BOOT
6830418Skarels char	*xxboot;
6930418Skarels char	*bootxx;
7030715Sbostic #endif
7131617Skarels 
7231617Skarels char	*dkname;
7330418Skarels char	*specname;
7437945Sbostic char	tmpfil[] = _PATH_TMP;
7530418Skarels 
7630418Skarels extern	int errno;
7730418Skarels char	namebuf[BBSIZE], *np = namebuf;
7831617Skarels struct	disklabel lab;
7931617Skarels struct	disklabel *readlabel(), *makebootarea();
8030418Skarels char	bootarea[BBSIZE];
8134032Skarels char	boot0[MAXPATHLEN];
8234032Skarels char	boot1[MAXPATHLEN];
8330418Skarels 
8434032Skarels enum	{ UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
8530418Skarels 
8630677Skarels int	rflag;
8730677Skarels 
8834032Skarels #ifdef DEBUG
8934032Skarels int	debug;
90*57996Sralph #define GETOPT_FLAGS "NRWerwd"
91*57996Sralph #else
92*57996Sralph #define GETOPT_FLAGS "NRWerw"
9334032Skarels #endif
9434032Skarels 
9530418Skarels main(argc, argv)
9630418Skarels 	int argc;
9730418Skarels 	char *argv[];
9830418Skarels {
9934032Skarels 	extern int optind;
10030418Skarels 	register struct disklabel *lp;
10134032Skarels 	FILE *t;
10234641Skarels 	int ch, f, error = 0;
10330715Sbostic 	char *name = 0, *type;
10430418Skarels 
105*57996Sralph 	while ((ch = getopt(argc, argv, GETOPT_FLAGS)) != EOF)
10634032Skarels 		switch (ch) {
10734032Skarels 			case 'N':
10834032Skarels 				if (op != UNSPEC)
10934032Skarels 					usage();
11034032Skarels 				op = NOWRITE;
11134032Skarels 				break;
11230715Sbostic 			case 'R':
11334032Skarels 				if (op != UNSPEC)
11434032Skarels 					usage();
11530715Sbostic 				op = RESTORE;
11630715Sbostic 				break;
11734032Skarels 			case 'W':
11834032Skarels 				if (op != UNSPEC)
11934032Skarels 					usage();
12034032Skarels 				op = WRITEABLE;
12134032Skarels 				break;
12230715Sbostic 			case 'e':
12334032Skarels 				if (op != UNSPEC)
12434032Skarels 					usage();
12530715Sbostic 				op = EDIT;
12630715Sbostic 				break;
12730715Sbostic 			case 'r':
12830715Sbostic 				++rflag;
12930715Sbostic 				break;
13030715Sbostic 			case 'w':
13134032Skarels 				if (op != UNSPEC)
13234032Skarels 					usage();
13330715Sbostic 				op = WRITE;
13430715Sbostic 				break;
13534032Skarels #ifdef DEBUG
13634032Skarels 			case 'd':
13734032Skarels 				debug++;
13834032Skarels 				break;
13934032Skarels #endif
14030715Sbostic 			case '?':
14130715Sbostic 			default:
14230715Sbostic 				usage();
14330715Sbostic 		}
14430715Sbostic 	argc -= optind;
14530715Sbostic 	argv += optind;
14634032Skarels 	if (op == UNSPEC)
14734032Skarels 		op = READ;
14830715Sbostic 	if (argc < 1)
14930715Sbostic 		usage();
15030715Sbostic 
15130715Sbostic 	dkname = argv[0];
15230418Skarels 	if (dkname[0] != '/') {
15337945Sbostic 		(void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION);
15430418Skarels 		specname = np;
15530418Skarels 		np += strlen(specname) + 1;
15630418Skarels 	} else
15730418Skarels 		specname = dkname;
15830418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
15930418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
16037945Sbostic 		(void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname);
16130418Skarels 		np = namebuf + strlen(specname) + 1;
16230418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
16330418Skarels 	}
16430418Skarels 	if (f < 0)
16530418Skarels 		Perror(specname);
16630418Skarels 
16730715Sbostic 	switch(op) {
16830715Sbostic 	case EDIT:
16930715Sbostic 		if (argc != 1)
17030715Sbostic 			usage();
17134032Skarels 		lp = readlabel(f);
17234641Skarels 		error = edit(lp, f);
17330715Sbostic 		break;
17434032Skarels 	case NOWRITE: {
17534032Skarels 		int flag = 0;
17634032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
17734032Skarels 			Perror("ioctl DIOCWLABEL");
17834032Skarels 		break;
17934032Skarels 	}
18030418Skarels 	case READ:
18130715Sbostic 		if (argc != 1)
18230715Sbostic 			usage();
18334032Skarels 		lp = readlabel(f);
18430418Skarels 		display(stdout, lp);
18534641Skarels 		error = checklabel(lp);
18630418Skarels 		break;
18730715Sbostic 	case RESTORE:
18830715Sbostic #ifdef BOOT
18934032Skarels 		if (rflag) {
19034032Skarels 			if (argc == 4) {	/* [ priboot secboot ] */
19134032Skarels 				xxboot = argv[2];
19234032Skarels 				bootxx = argv[3];
19334032Skarels 				lab.d_secsize = DEV_BSIZE;	/* XXX */
19434032Skarels 				lab.d_bbsize = BBSIZE;		/* XXX */
19534032Skarels 			}
19634032Skarels 			else if (argc == 3) 	/* [ disktype ] */
19734032Skarels 				makelabel(argv[2], (char *)NULL, &lab);
19834032Skarels 			else {
19934032Skarels 				fprintf(stderr,
20034032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
20134032Skarels 				exit(1);
20234032Skarels 			}
20334032Skarels 		}
20434032Skarels 		else
20531617Skarels #endif
20630715Sbostic 		if (argc != 2)
20730715Sbostic 			usage();
20831617Skarels 		lp = makebootarea(bootarea, &lab);
20930715Sbostic 		if (!(t = fopen(argv[1],"r")))
21030715Sbostic 			Perror(argv[1]);
21130715Sbostic 		if (getasciilabel(t, lp))
21234641Skarels 			error = writelabel(f, bootarea, lp);
21330418Skarels 		break;
21430418Skarels 	case WRITE:
21530715Sbostic 		type = argv[1];
21630715Sbostic #ifdef BOOT
21730715Sbostic 		if (argc > 5 || argc < 2)
21830715Sbostic 			usage();
21930715Sbostic 		if (argc > 3) {
22030715Sbostic 			bootxx = argv[--argc];
22130715Sbostic 			xxboot = argv[--argc];
22230715Sbostic 		}
22330715Sbostic #else
22430715Sbostic 		if (argc > 3 || argc < 2)
22530715Sbostic 			usage();
22630715Sbostic #endif
22730715Sbostic 		if (argc > 2)
228*57996Sralph 			name = argv[2];
22930418Skarels 		makelabel(type, name, &lab);
23031617Skarels 		lp = makebootarea(bootarea, &lab);
23130418Skarels 		*lp = lab;
23230715Sbostic 		if (checklabel(lp) == 0)
23334641Skarels 			error = writelabel(f, bootarea, lp);
23430418Skarels 		break;
23534032Skarels 	case WRITEABLE: {
23634032Skarels 		int flag = 1;
23734032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
23834032Skarels 			Perror("ioctl DIOCWLABEL");
23934032Skarels 		break;
24030418Skarels 	}
24134032Skarels 	}
24234641Skarels 	exit(error);
24330418Skarels }
24430418Skarels 
24534032Skarels /*
24634032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
24734032Skarels  * effect, set the names of the primary and secondary boot files
24834032Skarels  * if specified.
24934032Skarels  */
25030418Skarels makelabel(type, name, lp)
25130418Skarels 	char *type, *name;
25230418Skarels 	register struct disklabel *lp;
25330418Skarels {
25430418Skarels 	register struct disklabel *dp;
25534032Skarels 	char *strcpy();
25630418Skarels 
25730418Skarels 	dp = getdiskbyname(type);
25830418Skarels 	if (dp == NULL) {
25930418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
26030418Skarels 		exit(1);
26130418Skarels 	}
26230418Skarels 	*lp = *dp;
26334032Skarels #ifdef BOOT
26434032Skarels 	/*
26534032Skarels 	 * Check if disktab specifies the bootstraps (b0 or b1).
26634032Skarels 	 */
26734032Skarels 	if (!xxboot && lp->d_boot0) {
26834032Skarels 		if (*lp->d_boot0 != '/')
26934032Skarels 			(void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
27034032Skarels 		else
27134032Skarels 			(void)strcpy(boot0, lp->d_boot0);
27234032Skarels 		xxboot = boot0;
27334032Skarels 	}
27434032Skarels 	if (!bootxx && lp->d_boot1) {
27534032Skarels 		if (*lp->d_boot1 != '/')
27634032Skarels 			(void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
27734032Skarels 		else
27834032Skarels 			(void)strcpy(boot1, lp->d_boot1);
27934032Skarels 		bootxx = boot1;
28034032Skarels 	}
28134032Skarels 	/*
28234032Skarels 	 * If bootstraps not specified anywhere, makebootarea()
28334032Skarels 	 * will choose ones based on the name of the disk special
28434032Skarels 	 * file. E.g. /dev/ra0 -> raboot, bootra
28534032Skarels 	 */
28634032Skarels #endif /*BOOT*/
28734032Skarels 	/* d_packname is union d_boot[01], so zero */
28834032Skarels 	bzero(lp->d_packname, sizeof(lp->d_packname));
28930418Skarels 	if (name)
29034032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
29130418Skarels }
29230418Skarels 
29330418Skarels writelabel(f, boot, lp)
29430418Skarels 	int f;
29530418Skarels 	char *boot;
29630418Skarels 	register struct disklabel *lp;
29730418Skarels {
29830715Sbostic 	register int i;
29934032Skarels 	int flag;
30030418Skarels 
30130418Skarels 	lp->d_magic = DISKMAGIC;
30230418Skarels 	lp->d_magic2 = DISKMAGIC;
30330418Skarels 	lp->d_checksum = 0;
30430418Skarels 	lp->d_checksum = dkcksum(lp);
30530677Skarels 	if (rflag) {
30634032Skarels 		/*
30734032Skarels 		 * First set the kernel disk label,
30834032Skarels 		 * then write a label to the raw disk.
30934032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
31034032Skarels 		 * keep going; otherwise, the kernel consistency checks
31134032Skarels 		 * may prevent us from changing the current (in-core)
31234032Skarels 		 * label.
31334032Skarels 		 */
31434032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
31534641Skarels 		    errno != ENODEV && errno != ENOTTY) {
31634641Skarels 			l_perror("ioctl DIOCSDINFO");
31734641Skarels 			return (1);
31834641Skarels 		}
319*57996Sralph 		(void)lseek(f, (off_t)0, SEEK_SET);
32034032Skarels 		/*
32134032Skarels 		 * write enable label sector before write (if necessary),
32234032Skarels 		 * disable after writing.
32334032Skarels 		 */
32434032Skarels 		flag = 1;
32534032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
32634032Skarels 			perror("ioctl DIOCWLABEL");
32734641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
32834641Skarels 			perror("write");
32934641Skarels 			return (1);
33034641Skarels 		}
33134032Skarels 		flag = 0;
33234032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
33334641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
33434641Skarels 		l_perror("ioctl DIOCWDINFO");
33534641Skarels 		return (1);
33634641Skarels 	}
33734032Skarels #ifdef vax
33830677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
33930677Skarels 		daddr_t alt;
34030677Skarels 
34130677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
34230677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
343*57996Sralph 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize),
344*57996Sralph 				SEEK_SET);
34530677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
34630677Skarels 				int oerrno = errno;
34730677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
34830677Skarels 				errno = oerrno;
34930677Skarels 				perror("write");
35030677Skarels 			}
35130418Skarels 		}
35230418Skarels 	}
35330419Skarels #endif
35434641Skarels 	return (0);
35530418Skarels }
35630418Skarels 
35734641Skarels l_perror(s)
35834641Skarels 	char *s;
35934641Skarels {
36034641Skarels 	int saverrno = errno;
36134641Skarels 
36234641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
36334641Skarels 
36434641Skarels 	switch (saverrno) {
36534641Skarels 
36634641Skarels 	case ESRCH:
36734641Skarels 		fprintf(stderr, "No disk label on disk;\n");
36834641Skarels 		fprintf(stderr,
36934641Skarels 		    "use \"disklabel -r\" to install initial label\n");
37034641Skarels 		break;
37134641Skarels 
37234641Skarels 	case EINVAL:
37334641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
37434641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
37534641Skarels 		break;
37634641Skarels 
37734641Skarels 	case EBUSY:
37834641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
37934641Skarels 		break;
38034641Skarels 
38134641Skarels 	case EXDEV:
38234641Skarels 		fprintf(stderr,
38334641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
38434641Skarels 		break;
38534641Skarels 
38634641Skarels 	default:
38734641Skarels 		errno = saverrno;
38834641Skarels 		perror((char *)NULL);
38934641Skarels 		break;
39034641Skarels 	}
39134641Skarels }
39234641Skarels 
39330418Skarels /*
39431617Skarels  * Fetch disklabel for disk.
39531617Skarels  * Use ioctl to get label unless -r flag is given.
39630418Skarels  */
39730418Skarels struct disklabel *
39834032Skarels readlabel(f)
39934032Skarels 	int f;
40030418Skarels {
40130418Skarels 	register struct disklabel *lp;
40230418Skarels 
40334032Skarels 	if (rflag) {
40431617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
40531401Skarels 			Perror(specname);
40631617Skarels 		for (lp = (struct disklabel *)bootarea;
40731617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
40830677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
40930677Skarels 			if (lp->d_magic == DISKMAGIC &&
41030677Skarels 			    lp->d_magic2 == DISKMAGIC)
41130677Skarels 				break;
41231617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
41330677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
41430677Skarels 		    dkcksum(lp) != 0) {
41530677Skarels 			fprintf(stderr,
41630418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
41734032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
41834032Skarels 			exit (1);
41930677Skarels 		}
42034032Skarels 	} else {
42134032Skarels 		lp = &lab;
42234032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
42334032Skarels 			Perror("ioctl DIOCGDINFO");
42430418Skarels 	}
42530418Skarels 	return (lp);
42630418Skarels }
42730418Skarels 
42830418Skarels struct disklabel *
42931617Skarels makebootarea(boot, dp)
43030418Skarels 	char *boot;
43130418Skarels 	register struct disklabel *dp;
43230418Skarels {
43330418Skarels 	struct disklabel *lp;
43430418Skarels 	register char *p;
43530418Skarels 	int b;
43630418Skarels #ifdef BOOT
43730715Sbostic 	char	*dkbasename;
43834032Skarels #endif /*BOOT*/
43930715Sbostic 
44034032Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
44134032Skarels 	    LABELOFFSET);
44234032Skarels #ifdef BOOT
44334032Skarels 	if (!rflag)
44434032Skarels 		return (lp);
44534032Skarels 
44634032Skarels 	if (xxboot == NULL || bootxx == NULL) {
44730418Skarels 		dkbasename = np;
44830418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
44930418Skarels 			p = dkname;
45030418Skarels 		else
45130418Skarels 			p++;
45230418Skarels 		while (*p && !isdigit(*p))
45330418Skarels 			*np++ = *p++;
45430418Skarels 		*np++ = '\0';
45530418Skarels 
45634032Skarels 		if (xxboot == NULL) {
45734032Skarels 			(void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
45834032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
45934032Skarels 				dkbasename++;
46034032Skarels 			xxboot = np;
46134032Skarels 			(void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
46234032Skarels 			np += strlen(xxboot) + 1;
46334032Skarels 		}
46434032Skarels 		if (bootxx == NULL) {
46534032Skarels 			(void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
46634032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
46734032Skarels 				dkbasename++;
46834032Skarels 			bootxx = np;
46934032Skarels 			(void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
47034032Skarels 			np += strlen(bootxx) + 1;
47134032Skarels 		}
47230418Skarels 	}
47334032Skarels #ifdef DEBUG
47434032Skarels 	if (debug)
47534032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
47634032Skarels 			xxboot, bootxx);
47734032Skarels #endif
47830418Skarels 
47930418Skarels 	b = open(xxboot, O_RDONLY);
48030418Skarels 	if (b < 0)
48130418Skarels 		Perror(xxboot);
48230715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
48330418Skarels 		Perror(xxboot);
48430418Skarels 	close(b);
48530418Skarels 	b = open(bootxx, O_RDONLY);
48630418Skarels 	if (b < 0)
48730418Skarels 		Perror(bootxx);
48830715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
48930418Skarels 		Perror(bootxx);
49030715Sbostic 	(void)close(b);
49134032Skarels #endif /*BOOT*/
49230418Skarels 
49330418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
49430418Skarels 		if (*p) {
49530418Skarels 			fprintf(stderr,
49630418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
49730418Skarels 			exit(2);
49830418Skarels 		}
49930418Skarels 	return (lp);
50030418Skarels }
50130418Skarels 
50230418Skarels display(f, lp)
50330418Skarels 	FILE *f;
50430418Skarels 	register struct disklabel *lp;
50530418Skarels {
50630715Sbostic 	register int i, j;
50730418Skarels 	register struct partition *pp;
50830418Skarels 
50930418Skarels 	fprintf(f, "# %s:\n", specname);
51030418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
51130418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
51230418Skarels 	else
51330418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
51430418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
51534032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
51631401Skarels 	fprintf(f, "flags:");
51730418Skarels 	if (lp->d_flags & D_REMOVABLE)
51831401Skarels 		fprintf(f, " removeable");
51930418Skarels 	if (lp->d_flags & D_ECC)
52031401Skarels 		fprintf(f, " ecc");
52130418Skarels 	if (lp->d_flags & D_BADSECT)
52231401Skarels 		fprintf(f, " badsect");
52330418Skarels 	fprintf(f, "\n");
52430418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
52530418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
52630418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
52731386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
52830418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
52930715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
53030418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
53130418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
53230418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
53330418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
53430418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
53530418Skarels 	fprintf(f, "drivedata: ");
53630418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
53730418Skarels 		if (lp->d_drivedata[i])
53830418Skarels 			break;
53930418Skarels 	if (i < 0)
54030418Skarels 		i = 0;
54130418Skarels 	for (j = 0; j <= i; j++)
54230418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
54330418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
54430863Skarels 	fprintf(f,
54530863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
54630418Skarels 	pp = lp->d_partitions;
54730418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
54830418Skarels 		if (pp->p_size) {
54930863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
55030863Skarels 			   pp->p_size, pp->p_offset);
55130418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
55230418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
55330418Skarels 			else
55430418Skarels 				fprintf(f, "%8d", pp->p_fstype);
55530863Skarels 			switch (pp->p_fstype) {
55630863Skarels 
55730863Skarels 			case FS_UNUSED:				/* XXX */
55830863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
55930863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
56030863Skarels 				break;
56130863Skarels 
56230863Skarels 			case FS_BSDFFS:
56330863Skarels 				fprintf(f, "    %5d %5d %5d ",
56430863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
56530863Skarels 				    pp->p_cpg);
56630863Skarels 				break;
56730863Skarels 
56830863Skarels 			default:
56930863Skarels 				fprintf(f, "%20.20s", "");
57030863Skarels 				break;
57130863Skarels 			}
57230418Skarels 			fprintf(f, "\t# (Cyl. %4d",
57330418Skarels 			    pp->p_offset / lp->d_secpercyl);
57430418Skarels 			if (pp->p_offset % lp->d_secpercyl)
57530418Skarels 			    putc('*', f);
57630418Skarels 			else
57730418Skarels 			    putc(' ', f);
57830418Skarels 			fprintf(f, "- %d",
57930418Skarels 			    (pp->p_offset +
58030418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
58130418Skarels 			    lp->d_secpercyl - 1);
58230418Skarels 			if (pp->p_size % lp->d_secpercyl)
58330418Skarels 			    putc('*', f);
58430863Skarels 			fprintf(f, ")\n");
58530418Skarels 		}
58630418Skarels 	}
58732121Stef 	fflush(f);
58830418Skarels }
58930418Skarels 
59034641Skarels edit(lp, f)
59130715Sbostic 	struct disklabel *lp;
59234641Skarels 	int f;
59330418Skarels {
59430715Sbostic 	register int c;
59530715Sbostic 	struct disklabel label;
59630715Sbostic 	FILE *fd;
59730715Sbostic 	char *mktemp();
59830715Sbostic 
59930715Sbostic 	(void) mktemp(tmpfil);
60030715Sbostic 	fd = fopen(tmpfil, "w");
60130715Sbostic 	if (fd == NULL) {
60230715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
60334641Skarels 		return (1);
60430715Sbostic 	}
60530715Sbostic 	(void)fchmod(fd, 0600);
60630715Sbostic 	display(fd, lp);
60730715Sbostic 	fclose(fd);
60830715Sbostic 	for (;;) {
60930715Sbostic 		if (!editit())
61030715Sbostic 			break;
61130715Sbostic 		fd = fopen(tmpfil, "r");
61230715Sbostic 		if (fd == NULL) {
61334032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
61434032Skarels 				tmpfil);
61530715Sbostic 			break;
61630715Sbostic 		}
61730863Skarels 		bzero((char *)&label, sizeof(label));
61830715Sbostic 		if (getasciilabel(fd, &label)) {
61930715Sbostic 			*lp = label;
62034641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
62134641Skarels 				(void) unlink(tmpfil);
62234641Skarels 				return (0);
62334641Skarels 			}
62430715Sbostic 		}
62530715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
62630715Sbostic 		c = getchar();
62730715Sbostic 		if (c != EOF && c != (int)'\n')
62830715Sbostic 			while (getchar() != (int)'\n')
62930715Sbostic 				;
63030715Sbostic 		if  (c == (int)'n')
63130715Sbostic 			break;
63230715Sbostic 	}
63330715Sbostic 	(void) unlink(tmpfil);
63434641Skarels 	return (1);
63530418Skarels }
63630418Skarels 
63730715Sbostic editit()
63830715Sbostic {
63930715Sbostic 	register int pid, xpid;
64030715Sbostic 	int stat, omask;
64130715Sbostic 	extern char *getenv();
64230418Skarels 
64330715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
64430715Sbostic 	while ((pid = fork()) < 0) {
64530715Sbostic 		extern int errno;
64630715Sbostic 
64730715Sbostic 		if (errno == EPROCLIM) {
64830715Sbostic 			fprintf(stderr, "You have too many processes\n");
64930715Sbostic 			return(0);
65030715Sbostic 		}
65130715Sbostic 		if (errno != EAGAIN) {
65230715Sbostic 			perror("fork");
65330715Sbostic 			return(0);
65430715Sbostic 		}
65530715Sbostic 		sleep(1);
65630715Sbostic 	}
65730715Sbostic 	if (pid == 0) {
65830715Sbostic 		register char *ed;
65930715Sbostic 
66030715Sbostic 		sigsetmask(omask);
66130715Sbostic 		setgid(getgid());
66230715Sbostic 		setuid(getuid());
66330715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
66430715Sbostic 			ed = DEFEDITOR;
66530715Sbostic 		execlp(ed, ed, tmpfil, 0);
66630715Sbostic 		perror(ed);
66730715Sbostic 		exit(1);
66830715Sbostic 	}
66930715Sbostic 	while ((xpid = wait(&stat)) >= 0)
67030715Sbostic 		if (xpid == pid)
67130715Sbostic 			break;
67230715Sbostic 	sigsetmask(omask);
67330715Sbostic 	return(!stat);
67430715Sbostic }
67530715Sbostic 
67630715Sbostic char *
67730715Sbostic skip(cp)
67830715Sbostic 	register char *cp;
67930715Sbostic {
68030715Sbostic 
68130715Sbostic 	while (*cp != '\0' && isspace(*cp))
68230715Sbostic 		cp++;
68330715Sbostic 	if (*cp == '\0' || *cp == '#')
68430715Sbostic 		return ((char *)NULL);
68530715Sbostic 	return (cp);
68630715Sbostic }
68730715Sbostic 
68830715Sbostic char *
68930715Sbostic word(cp)
69030715Sbostic 	register char *cp;
69130715Sbostic {
69230715Sbostic 	register char c;
69330715Sbostic 
69431401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
69531401Skarels 		cp++;
69630715Sbostic 	if ((c = *cp) != '\0') {
69730715Sbostic 		*cp++ = '\0';
69830715Sbostic 		if (c != '#')
69930715Sbostic 			return (skip(cp));
70030715Sbostic 	}
70130715Sbostic 	return ((char *)NULL);
70230715Sbostic }
70330715Sbostic 
70430418Skarels /*
70530418Skarels  * Read an ascii label in from fd f,
70630418Skarels  * in the same format as that put out by display(),
70730418Skarels  * and fill in lp.
70830418Skarels  */
70930418Skarels getasciilabel(f, lp)
71030715Sbostic 	FILE	*f;
71130418Skarels 	register struct disklabel *lp;
71230418Skarels {
71330715Sbostic 	register char **cpp, *cp;
71430863Skarels 	register struct partition *pp;
71530715Sbostic 	char *tp, *s, line[BUFSIZ];
71630715Sbostic 	int v, lineno = 0, errors = 0;
71730715Sbostic 
71830715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
71930715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
72030715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
72130715Sbostic 		lineno++;
72230715Sbostic 		if (cp = index(line,'\n'))
72330715Sbostic 			*cp = '\0';
72430715Sbostic 		cp = skip(line);
72530715Sbostic 		if (cp == NULL)
72630715Sbostic 			continue;
72730715Sbostic 		tp = index(cp, ':');
72830715Sbostic 		if (tp == NULL) {
72930715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
73030715Sbostic 			errors++;
73130715Sbostic 			continue;
73230715Sbostic 		}
73330715Sbostic 		*tp++ = '\0', tp = skip(tp);
73430715Sbostic 		if (streq(cp, "type")) {
73530715Sbostic 			if (tp == NULL)
73630715Sbostic 				tp = "unknown";
73730715Sbostic 			cpp = dktypenames;
73830715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
73930715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
74030715Sbostic 					lp->d_type = cpp - dktypenames;
74130715Sbostic 					goto next;
74230715Sbostic 				}
74330715Sbostic 			v = atoi(tp);
74430715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
74530715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
74630715Sbostic 				    "Warning, unknown disk type", v);
74730715Sbostic 			lp->d_type = v;
74830715Sbostic 			continue;
74930715Sbostic 		}
75030715Sbostic 		if (streq(cp, "flags")) {
75134032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
75234032Skarels 				tp = word(cp);
75330715Sbostic 				if (streq(cp, "removeable"))
75430715Sbostic 					v |= D_REMOVABLE;
75530715Sbostic 				else if (streq(cp, "ecc"))
75630715Sbostic 					v |= D_ECC;
75730715Sbostic 				else if (streq(cp, "badsect"))
75830715Sbostic 					v |= D_BADSECT;
75930715Sbostic 				else {
76030715Sbostic 					fprintf(stderr,
76130715Sbostic 					    "line %d: %s: bad flag\n",
76230715Sbostic 					    lineno, cp);
76330715Sbostic 					errors++;
76430715Sbostic 				}
76530715Sbostic 			}
76630715Sbostic 			lp->d_flags = v;
76730715Sbostic 			continue;
76830715Sbostic 		}
76930715Sbostic 		if (streq(cp, "drivedata")) {
77030715Sbostic 			register int i;
77130715Sbostic 
77231386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
77330715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
77431386Skarels 				tp = word(cp);
77530715Sbostic 			}
77630715Sbostic 			continue;
77730715Sbostic 		}
77830715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
77930863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
78030715Sbostic 				fprintf(stderr,
78130715Sbostic 				    "line %d: bad # of partitions\n", lineno);
78230863Skarels 				lp->d_npartitions = MAXPARTITIONS;
78330863Skarels 				errors++;
78430863Skarels 			} else
78530715Sbostic 				lp->d_npartitions = v;
78630715Sbostic 			continue;
78730715Sbostic 		}
78830715Sbostic 		if (tp == NULL)
78930715Sbostic 			tp = "";
79030715Sbostic 		if (streq(cp, "disk")) {
79130715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
79230715Sbostic 			continue;
79330715Sbostic 		}
79430715Sbostic 		if (streq(cp, "label")) {
79534032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
79630715Sbostic 			continue;
79730715Sbostic 		}
79830715Sbostic 		if (streq(cp, "bytes/sector")) {
79930715Sbostic 			v = atoi(tp);
80030715Sbostic 			if (v <= 0 || (v % 512) != 0) {
80130715Sbostic 				fprintf(stderr,
80230715Sbostic 				    "line %d: %s: bad sector size\n",
80330715Sbostic 				    lineno, tp);
80430715Sbostic 				errors++;
80530715Sbostic 			} else
80630715Sbostic 				lp->d_secsize = v;
80730715Sbostic 			continue;
80830715Sbostic 		}
80930715Sbostic 		if (streq(cp, "sectors/track")) {
81030715Sbostic 			v = atoi(tp);
81130715Sbostic 			if (v <= 0) {
81230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
81330715Sbostic 				    lineno, tp, cp);
81430715Sbostic 				errors++;
81530715Sbostic 			} else
81630715Sbostic 				lp->d_nsectors = v;
81730715Sbostic 			continue;
81830715Sbostic 		}
81931386Skarels 		if (streq(cp, "sectors/cylinder")) {
82031386Skarels 			v = atoi(tp);
82131386Skarels 			if (v <= 0) {
82231386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
82331386Skarels 				    lineno, tp, cp);
82431386Skarels 				errors++;
82531386Skarels 			} else
82631386Skarels 				lp->d_secpercyl = v;
82731386Skarels 			continue;
82831386Skarels 		}
82930715Sbostic 		if (streq(cp, "tracks/cylinder")) {
83030715Sbostic 			v = atoi(tp);
83130715Sbostic 			if (v <= 0) {
83230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
83330715Sbostic 				    lineno, tp, cp);
83430715Sbostic 				errors++;
83530715Sbostic 			} else
83630715Sbostic 				lp->d_ntracks = v;
83730715Sbostic 			continue;
83830715Sbostic 		}
83930715Sbostic 		if (streq(cp, "cylinders")) {
84030715Sbostic 			v = atoi(tp);
84130715Sbostic 			if (v <= 0) {
84230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
84330715Sbostic 				    lineno, tp, cp);
84430715Sbostic 				errors++;
84530715Sbostic 			} else
84630715Sbostic 				lp->d_ncylinders = v;
84730715Sbostic 			continue;
84830715Sbostic 		}
84930715Sbostic 		if (streq(cp, "rpm")) {
85030715Sbostic 			v = atoi(tp);
85130715Sbostic 			if (v <= 0) {
85230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
85330715Sbostic 				    lineno, tp, cp);
85430715Sbostic 				errors++;
85530715Sbostic 			} else
85630715Sbostic 				lp->d_rpm = v;
85730715Sbostic 			continue;
85830715Sbostic 		}
85930715Sbostic 		if (streq(cp, "interleave")) {
86030715Sbostic 			v = atoi(tp);
86130715Sbostic 			if (v <= 0) {
86230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
86330715Sbostic 				    lineno, tp, cp);
86430715Sbostic 				errors++;
86530715Sbostic 			} else
86630715Sbostic 				lp->d_interleave = v;
86730715Sbostic 			continue;
86830715Sbostic 		}
86930715Sbostic 		if (streq(cp, "trackskew")) {
87030715Sbostic 			v = atoi(tp);
87130715Sbostic 			if (v < 0) {
87230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
87330715Sbostic 				    lineno, tp, cp);
87430715Sbostic 				errors++;
87530715Sbostic 			} else
87630715Sbostic 				lp->d_trackskew = v;
87730715Sbostic 			continue;
87830715Sbostic 		}
87930715Sbostic 		if (streq(cp, "cylinderskew")) {
88030715Sbostic 			v = atoi(tp);
88130715Sbostic 			if (v < 0) {
88230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
88330715Sbostic 				    lineno, tp, cp);
88430715Sbostic 				errors++;
88530715Sbostic 			} else
88630715Sbostic 				lp->d_cylskew = v;
88730715Sbostic 			continue;
88830715Sbostic 		}
88930715Sbostic 		if (streq(cp, "headswitch")) {
89030715Sbostic 			v = atoi(tp);
89130715Sbostic 			if (v < 0) {
89230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
89330715Sbostic 				    lineno, tp, cp);
89430715Sbostic 				errors++;
89530715Sbostic 			} else
89630715Sbostic 				lp->d_headswitch = v;
89730715Sbostic 			continue;
89830715Sbostic 		}
89930715Sbostic 		if (streq(cp, "track-to-track seek")) {
90030715Sbostic 			v = atoi(tp);
90130715Sbostic 			if (v < 0) {
90230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
90330715Sbostic 				    lineno, tp, cp);
90430715Sbostic 				errors++;
90530715Sbostic 			} else
90630715Sbostic 				lp->d_trkseek = v;
90730715Sbostic 			continue;
90830715Sbostic 		}
90930715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
91030863Skarels 			unsigned part = *cp - 'a';
91130715Sbostic 
91230863Skarels 			if (part > lp->d_npartitions) {
91330715Sbostic 				fprintf(stderr,
91430715Sbostic 				    "line %d: bad partition name\n", lineno);
91530715Sbostic 				errors++;
91630715Sbostic 				continue;
91730715Sbostic 			}
91830863Skarels 			pp = &lp->d_partitions[part];
91930863Skarels #define NXTNUM(n) { \
92030863Skarels 	cp = tp, tp = word(cp); \
92130863Skarels 	if (tp == NULL) \
92230863Skarels 		tp = cp; \
92330863Skarels 	(n) = atoi(cp); \
92430863Skarels      }
92530863Skarels 
92630863Skarels 			NXTNUM(v);
92730715Sbostic 			if (v < 0) {
92830715Sbostic 				fprintf(stderr,
92930715Sbostic 				    "line %d: %s: bad partition size\n",
93030715Sbostic 				    lineno, cp);
93130715Sbostic 				errors++;
93230715Sbostic 			} else
93330863Skarels 				pp->p_size = v;
93430863Skarels 			NXTNUM(v);
93530715Sbostic 			if (v < 0) {
93630715Sbostic 				fprintf(stderr,
93730715Sbostic 				    "line %d: %s: bad partition offset\n",
93830715Sbostic 				    lineno, cp);
93930715Sbostic 				errors++;
94030715Sbostic 			} else
94130863Skarels 				pp->p_offset = v;
94230715Sbostic 			cp = tp, tp = word(cp);
94330715Sbostic 			cpp = fstypenames;
94430715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
94530715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
94630863Skarels 					pp->p_fstype = cpp - fstypenames;
94730863Skarels 					goto gottype;
94830715Sbostic 				}
94934032Skarels 			if (isdigit(*cp))
95034032Skarels 				v = atoi(cp);
95134032Skarels 			else
95234032Skarels 				v = FSMAXTYPES;
95334032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
95430715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
95530715Sbostic 				    "Warning, unknown filesystem type", cp);
95634032Skarels 				v = FS_UNUSED;
95734032Skarels 			}
95830863Skarels 			pp->p_fstype = v;
95930863Skarels 	gottype:
96030863Skarels 
96130863Skarels 			switch (pp->p_fstype) {
96230863Skarels 
96330863Skarels 			case FS_UNUSED:				/* XXX */
96430863Skarels 				NXTNUM(pp->p_fsize);
96530863Skarels 				if (pp->p_fsize == 0)
96630863Skarels 					break;
96730863Skarels 				NXTNUM(v);
96830863Skarels 				pp->p_frag = v / pp->p_fsize;
96930863Skarels 				break;
97030863Skarels 
97130863Skarels 			case FS_BSDFFS:
97230863Skarels 				NXTNUM(pp->p_fsize);
97330863Skarels 				if (pp->p_fsize == 0)
97430863Skarels 					break;
97530863Skarels 				NXTNUM(v);
97630863Skarels 				pp->p_frag = v / pp->p_fsize;
97730863Skarels 				NXTNUM(pp->p_cpg);
97830863Skarels 				break;
97930863Skarels 
98030863Skarels 			default:
98130863Skarels 				break;
98230863Skarels 			}
98330715Sbostic 			continue;
98430715Sbostic 		}
98530715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
98630715Sbostic 		    lineno, cp);
98730715Sbostic 		errors++;
98830715Sbostic 	next:
98930715Sbostic 		;
99030715Sbostic 	}
99130715Sbostic 	errors += checklabel(lp);
99230715Sbostic 	return (errors == 0);
99330418Skarels }
99430418Skarels 
99530715Sbostic /*
99630715Sbostic  * Check disklabel for errors and fill in
99730715Sbostic  * derived fields according to supplied values.
99830715Sbostic  */
99930715Sbostic checklabel(lp)
100030715Sbostic 	register struct disklabel *lp;
100130418Skarels {
100230715Sbostic 	register struct partition *pp;
100330715Sbostic 	int i, errors = 0;
100430715Sbostic 	char part;
100530418Skarels 
100630715Sbostic 	if (lp->d_secsize == 0) {
100730715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
100830715Sbostic 		return (1);
100930715Sbostic 	}
101030715Sbostic 	if (lp->d_nsectors == 0) {
101130715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
101230715Sbostic 		return (1);
101330715Sbostic 	}
101430715Sbostic 	if (lp->d_ntracks == 0) {
101530715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
101630715Sbostic 		return (1);
101730715Sbostic 	}
101830715Sbostic 	if  (lp->d_ncylinders == 0) {
101930715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
102030715Sbostic 		errors++;
102130715Sbostic 	}
102230715Sbostic 	if (lp->d_rpm == 0)
102330715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
102430715Sbostic 	if (lp->d_secpercyl == 0)
102530715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
102630715Sbostic 	if (lp->d_secperunit == 0)
102730715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
102830715Sbostic 	if (lp->d_bbsize == 0) {
102930715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
103030715Sbostic 		errors++;
103130715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
103230715Sbostic 		Warning("boot block size %% sector-size != 0\n");
103330715Sbostic 	if (lp->d_sbsize == 0) {
103430715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
103530715Sbostic 		errors++;
103630715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
103730715Sbostic 		Warning("super block size %% sector-size != 0\n");
103830715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
103930715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
104030715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
104130715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
104230715Sbostic 		part = 'a' + i;
104330715Sbostic 		pp = &lp->d_partitions[i];
104430715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
104530715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
104630715Sbostic 			    part, pp->p_offset);
104730715Sbostic #ifdef notdef
104830715Sbostic 		if (pp->p_size % lp->d_secpercyl)
104930715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
105030715Sbostic 			    part);
105130715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
105230715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
105330715Sbostic 			    part);
105430715Sbostic #endif
105530715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
105630715Sbostic 			fprintf(stderr,
105730715Sbostic 			    "partition %c: offset past end of unit\n", part);
105830715Sbostic 			errors++;
105930715Sbostic 		}
106030715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
106130715Sbostic 			fprintf(stderr,
106230715Sbostic 			    "partition %c: partition extends past end of unit\n",
106330715Sbostic 			    part);
106430715Sbostic 			errors++;
106530715Sbostic 		}
106630715Sbostic 	}
106730715Sbostic 	for (; i < MAXPARTITIONS; i++) {
106830715Sbostic 		part = 'a' + i;
106930715Sbostic 		pp = &lp->d_partitions[i];
107030715Sbostic 		if (pp->p_size || pp->p_offset)
107130715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
107234032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
107330715Sbostic 	}
107430715Sbostic 	return (errors);
107530715Sbostic }
107630715Sbostic 
107730715Sbostic /*VARARGS1*/
107830715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
107930715Sbostic 	char *fmt;
108030715Sbostic {
108130715Sbostic 
108230715Sbostic 	fprintf(stderr, "Warning, ");
108330715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
108430715Sbostic 	fprintf(stderr, "\n");
108530715Sbostic }
108630715Sbostic 
108730715Sbostic Perror(str)
108830715Sbostic 	char *str;
108930715Sbostic {
109030715Sbostic 	fputs("disklabel: ", stderr); perror(str);
109130418Skarels 	exit(4);
109230418Skarels }
109330715Sbostic 
109430715Sbostic usage()
109530715Sbostic {
109630715Sbostic #ifdef BOOT
109734032Skarels 	fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
109830715Sbostic "usage: disklabel [-r] disk", "(to read label)",
109930715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
110030715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
110134032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
110234032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
110330715Sbostic #else
110434032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
110530715Sbostic "usage: disklabel [-r] disk", "(to read label)",
110630715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
110730715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
110834032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
110934032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
111030715Sbostic #endif
111130715Sbostic 	exit(1);
111230715Sbostic }
1113