xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 34032)
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*34032Skarels static char sccsid[] = "@(#)disklabel.c	5.12 (Berkeley) 04/20/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];
69*34032Skarels char	boot0[MAXPATHLEN];
70*34032Skarels char	boot1[MAXPATHLEN];
7130418Skarels 
72*34032Skarels enum	{ UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
7330418Skarels 
7430677Skarels int	rflag;
7530677Skarels 
76*34032Skarels #ifdef DEBUG
77*34032Skarels int	debug;
78*34032Skarels #endif
79*34032Skarels 
8030418Skarels main(argc, argv)
8130418Skarels 	int argc;
8230418Skarels 	char *argv[];
8330418Skarels {
84*34032Skarels 	extern int optind;
8530418Skarels 	register struct disklabel *lp;
86*34032Skarels 	FILE *t;
87*34032Skarels 	int ch, f;
8830715Sbostic 	char *name = 0, *type;
8930418Skarels 
90*34032Skarels 	while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
91*34032Skarels 		switch (ch) {
92*34032Skarels 			case 'N':
93*34032Skarels 				if (op != UNSPEC)
94*34032Skarels 					usage();
95*34032Skarels 				op = NOWRITE;
96*34032Skarels 				break;
9730715Sbostic 			case 'R':
98*34032Skarels 				if (op != UNSPEC)
99*34032Skarels 					usage();
10030715Sbostic 				op = RESTORE;
10130715Sbostic 				break;
102*34032Skarels 			case 'W':
103*34032Skarels 				if (op != UNSPEC)
104*34032Skarels 					usage();
105*34032Skarels 				op = WRITEABLE;
106*34032Skarels 				break;
10730715Sbostic 			case 'e':
108*34032Skarels 				if (op != UNSPEC)
109*34032Skarels 					usage();
11030715Sbostic 				op = EDIT;
11130715Sbostic 				break;
11230715Sbostic 			case 'r':
11330715Sbostic 				++rflag;
11430715Sbostic 				break;
11530715Sbostic 			case 'w':
116*34032Skarels 				if (op != UNSPEC)
117*34032Skarels 					usage();
11830715Sbostic 				op = WRITE;
11930715Sbostic 				break;
120*34032Skarels #ifdef DEBUG
121*34032Skarels 			case 'd':
122*34032Skarels 				debug++;
123*34032Skarels 				break;
124*34032Skarels #endif
12530715Sbostic 			case '?':
12630715Sbostic 			default:
12730715Sbostic 				usage();
12830715Sbostic 		}
12930715Sbostic 	argc -= optind;
13030715Sbostic 	argv += optind;
131*34032Skarels 	if (op == UNSPEC)
132*34032Skarels 		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();
156*34032Skarels 		lp = readlabel(f);
15730715Sbostic 		if (edit(lp))
15830715Sbostic 			writelabel(f, bootarea, lp);
15930715Sbostic 		break;
160*34032Skarels 	case NOWRITE: {
161*34032Skarels 		int flag = 0;
162*34032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
163*34032Skarels 			Perror("ioctl DIOCWLABEL");
164*34032Skarels 		break;
165*34032Skarels 	}
16630418Skarels 	case READ:
16730715Sbostic 		if (argc != 1)
16830715Sbostic 			usage();
169*34032Skarels 		lp = readlabel(f);
17030418Skarels 		display(stdout, lp);
17130715Sbostic 		(void) checklabel(lp);
17230418Skarels 		break;
17330715Sbostic 	case RESTORE:
17430715Sbostic #ifdef BOOT
175*34032Skarels 		if (rflag) {
176*34032Skarels 			if (argc == 4) {	/* [ priboot secboot ] */
177*34032Skarels 				xxboot = argv[2];
178*34032Skarels 				bootxx = argv[3];
179*34032Skarels 				lab.d_secsize = DEV_BSIZE;	/* XXX */
180*34032Skarels 				lab.d_bbsize = BBSIZE;		/* XXX */
181*34032Skarels 			}
182*34032Skarels 			else if (argc == 3) 	/* [ disktype ] */
183*34032Skarels 				makelabel(argv[2], (char *)NULL, &lab);
184*34032Skarels 			else {
185*34032Skarels 				fprintf(stderr,
186*34032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
187*34032Skarels 				exit(1);
188*34032Skarels 			}
189*34032Skarels 		}
190*34032Skarels 		else
19131617Skarels #endif
19230715Sbostic 		if (argc != 2)
19330715Sbostic 			usage();
19431617Skarels 		lp = makebootarea(bootarea, &lab);
19530715Sbostic 		if (!(t = fopen(argv[1],"r")))
19630715Sbostic 			Perror(argv[1]);
19730715Sbostic 		if (getasciilabel(t, lp))
19830715Sbostic 			writelabel(f, bootarea, lp);
19930418Skarels 		break;
20030418Skarels 	case WRITE:
20130715Sbostic 		type = argv[1];
20230715Sbostic #ifdef BOOT
20330715Sbostic 		if (argc > 5 || argc < 2)
20430715Sbostic 			usage();
20530715Sbostic 		if (argc > 3) {
20630715Sbostic 			bootxx = argv[--argc];
20730715Sbostic 			xxboot = argv[--argc];
20830715Sbostic 		}
20930715Sbostic #else
21030715Sbostic 		if (argc > 3 || argc < 2)
21130715Sbostic 			usage();
21230715Sbostic #endif
21330715Sbostic 		if (argc > 2)
21430715Sbostic 			name = argv[--argc];
21530418Skarels 		makelabel(type, name, &lab);
21631617Skarels 		lp = makebootarea(bootarea, &lab);
21730418Skarels 		*lp = lab;
21830715Sbostic 		if (checklabel(lp) == 0)
21930715Sbostic 			writelabel(f, bootarea, lp);
22030418Skarels 		break;
221*34032Skarels 	case WRITEABLE: {
222*34032Skarels 		int flag = 1;
223*34032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
224*34032Skarels 			Perror("ioctl DIOCWLABEL");
225*34032Skarels 		break;
22630418Skarels 	}
227*34032Skarels 	}
22830418Skarels 	exit(0);
22930418Skarels }
23030418Skarels 
231*34032Skarels /*
232*34032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
233*34032Skarels  * effect, set the names of the primary and secondary boot files
234*34032Skarels  * if specified.
235*34032Skarels  */
23630418Skarels makelabel(type, name, lp)
23730418Skarels 	char *type, *name;
23830418Skarels 	register struct disklabel *lp;
23930418Skarels {
24030418Skarels 	register struct disklabel *dp;
241*34032Skarels 	char *strcpy();
24230418Skarels 
24330418Skarels 	dp = getdiskbyname(type);
24430418Skarels 	if (dp == NULL) {
24530418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
24630418Skarels 		exit(1);
24730418Skarels 	}
24830418Skarels 	*lp = *dp;
249*34032Skarels #ifdef BOOT
250*34032Skarels 	/*
251*34032Skarels 	 * Check if disktab specifies the bootstraps (b0 or b1).
252*34032Skarels 	 */
253*34032Skarels 	if (!xxboot && lp->d_boot0) {
254*34032Skarels 		if (*lp->d_boot0 != '/')
255*34032Skarels 			(void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
256*34032Skarels 		else
257*34032Skarels 			(void)strcpy(boot0, lp->d_boot0);
258*34032Skarels 		xxboot = boot0;
259*34032Skarels 	}
260*34032Skarels 	if (!bootxx && lp->d_boot1) {
261*34032Skarels 		if (*lp->d_boot1 != '/')
262*34032Skarels 			(void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
263*34032Skarels 		else
264*34032Skarels 			(void)strcpy(boot1, lp->d_boot1);
265*34032Skarels 		bootxx = boot1;
266*34032Skarels 	}
267*34032Skarels 	/*
268*34032Skarels 	 * If bootstraps not specified anywhere, makebootarea()
269*34032Skarels 	 * will choose ones based on the name of the disk special
270*34032Skarels 	 * file. E.g. /dev/ra0 -> raboot, bootra
271*34032Skarels 	 */
272*34032Skarels #endif /*BOOT*/
273*34032Skarels 	/* d_packname is union d_boot[01], so zero */
274*34032Skarels 	bzero(lp->d_packname, sizeof(lp->d_packname));
27530418Skarels 	if (name)
276*34032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
27730418Skarels }
27830418Skarels 
27930418Skarels writelabel(f, boot, lp)
28030418Skarels 	int f;
28130418Skarels 	char *boot;
28230418Skarels 	register struct disklabel *lp;
28330418Skarels {
28430715Sbostic 	register int i;
285*34032Skarels 	int flag;
286*34032Skarels 	off_t lseek();
28730418Skarels 
28830418Skarels 	lp->d_magic = DISKMAGIC;
28930418Skarels 	lp->d_magic2 = DISKMAGIC;
29030418Skarels 	lp->d_checksum = 0;
29130418Skarels 	lp->d_checksum = dkcksum(lp);
29230677Skarels 	if (rflag) {
293*34032Skarels 		/*
294*34032Skarels 		 * First set the kernel disk label,
295*34032Skarels 		 * then write a label to the raw disk.
296*34032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
297*34032Skarels 		 * keep going; otherwise, the kernel consistency checks
298*34032Skarels 		 * may prevent us from changing the current (in-core)
299*34032Skarels 		 * label.
300*34032Skarels 		 */
301*34032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
302*34032Skarels 		    errno != ENODEV && errno != ENOTTY)
303*34032Skarels 			Perror("ioctl DIOCSDINFO");
30431617Skarels 		(void)lseek(f, (off_t)0, L_SET);
305*34032Skarels 		/*
306*34032Skarels 		 * write enable label sector before write (if necessary),
307*34032Skarels 		 * disable after writing.
308*34032Skarels 		 */
309*34032Skarels 		flag = 1;
310*34032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
311*34032Skarels 			perror("ioctl DIOCWLABEL");
312*34032Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize)
31330677Skarels 			Perror("write");
314*34032Skarels 		flag = 0;
315*34032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
31630677Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0)
31730677Skarels 		Perror("ioctl DIOCWDINFO");
318*34032Skarels #ifdef vax
31930677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
32030677Skarels 		daddr_t alt;
32130677Skarels 
32230677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
32330677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
32430715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
32530677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
32630677Skarels 				int oerrno = errno;
32730677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
32830677Skarels 				errno = oerrno;
32930677Skarels 				perror("write");
33030677Skarels 			}
33130418Skarels 		}
33230418Skarels 	}
33330419Skarels #endif
33430418Skarels }
33530418Skarels 
33630418Skarels /*
33731617Skarels  * Fetch disklabel for disk.
33831617Skarels  * Use ioctl to get label unless -r flag is given.
33930418Skarels  */
34030418Skarels struct disklabel *
341*34032Skarels readlabel(f)
342*34032Skarels 	int f;
34330418Skarels {
34430418Skarels 	register struct disklabel *lp;
34530418Skarels 
346*34032Skarels 	if (rflag) {
34731617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
34831401Skarels 			Perror(specname);
34931617Skarels 		for (lp = (struct disklabel *)bootarea;
35031617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
35130677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
35230677Skarels 			if (lp->d_magic == DISKMAGIC &&
35330677Skarels 			    lp->d_magic2 == DISKMAGIC)
35430677Skarels 				break;
35531617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
35630677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
35730677Skarels 		    dkcksum(lp) != 0) {
35830677Skarels 			fprintf(stderr,
35930418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
360*34032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
361*34032Skarels 			exit (1);
36230677Skarels 		}
363*34032Skarels 	} else {
364*34032Skarels 		lp = &lab;
365*34032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
366*34032Skarels 			Perror("ioctl DIOCGDINFO");
36730418Skarels 	}
36830418Skarels 	return (lp);
36930418Skarels }
37030418Skarels 
37130418Skarels struct disklabel *
37231617Skarels makebootarea(boot, dp)
37330418Skarels 	char *boot;
37430418Skarels 	register struct disklabel *dp;
37530418Skarels {
37630418Skarels 	struct disklabel *lp;
37730418Skarels 	register char *p;
37830418Skarels 	int b;
37930418Skarels #ifdef BOOT
38030715Sbostic 	char	*dkbasename;
381*34032Skarels #endif /*BOOT*/
38230715Sbostic 
383*34032Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
384*34032Skarels 	    LABELOFFSET);
385*34032Skarels #ifdef BOOT
386*34032Skarels 	if (!rflag)
387*34032Skarels 		return (lp);
388*34032Skarels 
389*34032Skarels 	if (xxboot == NULL || bootxx == NULL) {
39030418Skarels 		dkbasename = np;
39130418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
39230418Skarels 			p = dkname;
39330418Skarels 		else
39430418Skarels 			p++;
39530418Skarels 		while (*p && !isdigit(*p))
39630418Skarels 			*np++ = *p++;
39730418Skarels 		*np++ = '\0';
39830418Skarels 
399*34032Skarels 		if (xxboot == NULL) {
400*34032Skarels 			(void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
401*34032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
402*34032Skarels 				dkbasename++;
403*34032Skarels 			xxboot = np;
404*34032Skarels 			(void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
405*34032Skarels 			np += strlen(xxboot) + 1;
406*34032Skarels 		}
407*34032Skarels 		if (bootxx == NULL) {
408*34032Skarels 			(void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
409*34032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
410*34032Skarels 				dkbasename++;
411*34032Skarels 			bootxx = np;
412*34032Skarels 			(void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
413*34032Skarels 			np += strlen(bootxx) + 1;
414*34032Skarels 		}
41530418Skarels 	}
416*34032Skarels #ifdef DEBUG
417*34032Skarels 	if (debug)
418*34032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
419*34032Skarels 			xxboot, bootxx);
420*34032Skarels #endif
42130418Skarels 
42230418Skarels 	b = open(xxboot, O_RDONLY);
42330418Skarels 	if (b < 0)
42430418Skarels 		Perror(xxboot);
42530715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
42630418Skarels 		Perror(xxboot);
42730418Skarels 	close(b);
42830418Skarels 	b = open(bootxx, O_RDONLY);
42930418Skarels 	if (b < 0)
43030418Skarels 		Perror(bootxx);
43130715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
43230418Skarels 		Perror(bootxx);
43330715Sbostic 	(void)close(b);
434*34032Skarels #endif /*BOOT*/
43530418Skarels 
43630418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
43730418Skarels 		if (*p) {
43830418Skarels 			fprintf(stderr,
43930418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
44030418Skarels 			exit(2);
44130418Skarels 		}
44230418Skarels 	return (lp);
44330418Skarels }
44430418Skarels 
44530418Skarels display(f, lp)
44630418Skarels 	FILE *f;
44730418Skarels 	register struct disklabel *lp;
44830418Skarels {
44930715Sbostic 	register int i, j;
45030418Skarels 	register struct partition *pp;
45130418Skarels 
45230418Skarels 	fprintf(f, "# %s:\n", specname);
45330418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
45430418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
45530418Skarels 	else
45630418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
45730418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
458*34032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
45931401Skarels 	fprintf(f, "flags:");
46030418Skarels 	if (lp->d_flags & D_REMOVABLE)
46131401Skarels 		fprintf(f, " removeable");
46230418Skarels 	if (lp->d_flags & D_ECC)
46331401Skarels 		fprintf(f, " ecc");
46430418Skarels 	if (lp->d_flags & D_BADSECT)
46531401Skarels 		fprintf(f, " badsect");
46630418Skarels 	fprintf(f, "\n");
46730418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
46830418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
46930418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
47031386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
47130418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
47230715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
47330418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
47430418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
47530418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
47630418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
47730418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
47830418Skarels 	fprintf(f, "drivedata: ");
47930418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
48030418Skarels 		if (lp->d_drivedata[i])
48130418Skarels 			break;
48230418Skarels 	if (i < 0)
48330418Skarels 		i = 0;
48430418Skarels 	for (j = 0; j <= i; j++)
48530418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
48630418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
48730863Skarels 	fprintf(f,
48830863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
48930418Skarels 	pp = lp->d_partitions;
49030418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
49130418Skarels 		if (pp->p_size) {
49230863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
49330863Skarels 			   pp->p_size, pp->p_offset);
49430418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
49530418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
49630418Skarels 			else
49730418Skarels 				fprintf(f, "%8d", pp->p_fstype);
49830863Skarels 			switch (pp->p_fstype) {
49930863Skarels 
50030863Skarels 			case FS_UNUSED:				/* XXX */
50130863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
50230863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
50330863Skarels 				break;
50430863Skarels 
50530863Skarels 			case FS_BSDFFS:
50630863Skarels 				fprintf(f, "    %5d %5d %5d ",
50730863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
50830863Skarels 				    pp->p_cpg);
50930863Skarels 				break;
51030863Skarels 
51130863Skarels 			default:
51230863Skarels 				fprintf(f, "%20.20s", "");
51330863Skarels 				break;
51430863Skarels 			}
51530418Skarels 			fprintf(f, "\t# (Cyl. %4d",
51630418Skarels 			    pp->p_offset / lp->d_secpercyl);
51730418Skarels 			if (pp->p_offset % lp->d_secpercyl)
51830418Skarels 			    putc('*', f);
51930418Skarels 			else
52030418Skarels 			    putc(' ', f);
52130418Skarels 			fprintf(f, "- %d",
52230418Skarels 			    (pp->p_offset +
52330418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
52430418Skarels 			    lp->d_secpercyl - 1);
52530418Skarels 			if (pp->p_size % lp->d_secpercyl)
52630418Skarels 			    putc('*', f);
52730863Skarels 			fprintf(f, ")\n");
52830418Skarels 		}
52930418Skarels 	}
53032121Stef 	fflush(f);
53130418Skarels }
53230418Skarels 
53330715Sbostic edit(lp)
53430715Sbostic 	struct disklabel *lp;
53530418Skarels {
53630715Sbostic 	register int c;
53730715Sbostic 	struct disklabel label;
53830715Sbostic 	FILE *fd;
53930715Sbostic 	char *mktemp();
54030715Sbostic 
54130715Sbostic 	(void) mktemp(tmpfil);
54230715Sbostic 	fd = fopen(tmpfil, "w");
54330715Sbostic 	if (fd == NULL) {
54430715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
54530715Sbostic 		return (0);
54630715Sbostic 	}
54730715Sbostic 	(void)fchmod(fd, 0600);
54830715Sbostic 	display(fd, lp);
54930715Sbostic 	fclose(fd);
55030715Sbostic 	for (;;) {
55130715Sbostic 		if (!editit())
55230715Sbostic 			break;
55330715Sbostic 		fd = fopen(tmpfil, "r");
55430715Sbostic 		if (fd == NULL) {
555*34032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
556*34032Skarels 				tmpfil);
55730715Sbostic 			break;
55830715Sbostic 		}
55930863Skarels 		bzero((char *)&label, sizeof(label));
56030715Sbostic 		if (getasciilabel(fd, &label)) {
56130715Sbostic 			*lp = label;
56230715Sbostic 			(void) unlink(tmpfil);
56330715Sbostic 			return (1);
56430715Sbostic 		}
56530715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
56630715Sbostic 		c = getchar();
56730715Sbostic 		if (c != EOF && c != (int)'\n')
56830715Sbostic 			while (getchar() != (int)'\n')
56930715Sbostic 				;
57030715Sbostic 		if  (c == (int)'n')
57130715Sbostic 			break;
57230715Sbostic 	}
57330715Sbostic 	(void) unlink(tmpfil);
57430715Sbostic 	return (0);
57530418Skarels }
57630418Skarels 
57730715Sbostic editit()
57830715Sbostic {
57930715Sbostic 	register int pid, xpid;
58030715Sbostic 	int stat, omask;
58130715Sbostic 	extern char *getenv();
58230418Skarels 
58330715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
58430715Sbostic 	while ((pid = fork()) < 0) {
58530715Sbostic 		extern int errno;
58630715Sbostic 
58730715Sbostic 		if (errno == EPROCLIM) {
58830715Sbostic 			fprintf(stderr, "You have too many processes\n");
58930715Sbostic 			return(0);
59030715Sbostic 		}
59130715Sbostic 		if (errno != EAGAIN) {
59230715Sbostic 			perror("fork");
59330715Sbostic 			return(0);
59430715Sbostic 		}
59530715Sbostic 		sleep(1);
59630715Sbostic 	}
59730715Sbostic 	if (pid == 0) {
59830715Sbostic 		register char *ed;
59930715Sbostic 
60030715Sbostic 		sigsetmask(omask);
60130715Sbostic 		setgid(getgid());
60230715Sbostic 		setuid(getuid());
60330715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
60430715Sbostic 			ed = DEFEDITOR;
60530715Sbostic 		execlp(ed, ed, tmpfil, 0);
60630715Sbostic 		perror(ed);
60730715Sbostic 		exit(1);
60830715Sbostic 	}
60930715Sbostic 	while ((xpid = wait(&stat)) >= 0)
61030715Sbostic 		if (xpid == pid)
61130715Sbostic 			break;
61230715Sbostic 	sigsetmask(omask);
61330715Sbostic 	return(!stat);
61430715Sbostic }
61530715Sbostic 
61630715Sbostic char *
61730715Sbostic skip(cp)
61830715Sbostic 	register char *cp;
61930715Sbostic {
62030715Sbostic 
62130715Sbostic 	while (*cp != '\0' && isspace(*cp))
62230715Sbostic 		cp++;
62330715Sbostic 	if (*cp == '\0' || *cp == '#')
62430715Sbostic 		return ((char *)NULL);
62530715Sbostic 	return (cp);
62630715Sbostic }
62730715Sbostic 
62830715Sbostic char *
62930715Sbostic word(cp)
63030715Sbostic 	register char *cp;
63130715Sbostic {
63230715Sbostic 	register char c;
63330715Sbostic 
63431401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
63531401Skarels 		cp++;
63630715Sbostic 	if ((c = *cp) != '\0') {
63730715Sbostic 		*cp++ = '\0';
63830715Sbostic 		if (c != '#')
63930715Sbostic 			return (skip(cp));
64030715Sbostic 	}
64130715Sbostic 	return ((char *)NULL);
64230715Sbostic }
64330715Sbostic 
64430418Skarels /*
64530418Skarels  * Read an ascii label in from fd f,
64630418Skarels  * in the same format as that put out by display(),
64730418Skarels  * and fill in lp.
64830418Skarels  */
64930418Skarels getasciilabel(f, lp)
65030715Sbostic 	FILE	*f;
65130418Skarels 	register struct disklabel *lp;
65230418Skarels {
65330715Sbostic 	register char **cpp, *cp;
65430863Skarels 	register struct partition *pp;
65530715Sbostic 	char *tp, *s, line[BUFSIZ];
65630715Sbostic 	int v, lineno = 0, errors = 0;
65730715Sbostic 
65830715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
65930715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
66030715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
66130715Sbostic 		lineno++;
66230715Sbostic 		if (cp = index(line,'\n'))
66330715Sbostic 			*cp = '\0';
66430715Sbostic 		cp = skip(line);
66530715Sbostic 		if (cp == NULL)
66630715Sbostic 			continue;
66730715Sbostic 		tp = index(cp, ':');
66830715Sbostic 		if (tp == NULL) {
66930715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
67030715Sbostic 			errors++;
67130715Sbostic 			continue;
67230715Sbostic 		}
67330715Sbostic 		*tp++ = '\0', tp = skip(tp);
67430715Sbostic 		if (streq(cp, "type")) {
67530715Sbostic 			if (tp == NULL)
67630715Sbostic 				tp = "unknown";
67730715Sbostic 			cpp = dktypenames;
67830715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
67930715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
68030715Sbostic 					lp->d_type = cpp - dktypenames;
68130715Sbostic 					goto next;
68230715Sbostic 				}
68330715Sbostic 			v = atoi(tp);
68430715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
68530715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
68630715Sbostic 				    "Warning, unknown disk type", v);
68730715Sbostic 			lp->d_type = v;
68830715Sbostic 			continue;
68930715Sbostic 		}
69030715Sbostic 		if (streq(cp, "flags")) {
691*34032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
692*34032Skarels 				tp = word(cp);
69330715Sbostic 				if (streq(cp, "removeable"))
69430715Sbostic 					v |= D_REMOVABLE;
69530715Sbostic 				else if (streq(cp, "ecc"))
69630715Sbostic 					v |= D_ECC;
69730715Sbostic 				else if (streq(cp, "badsect"))
69830715Sbostic 					v |= D_BADSECT;
69930715Sbostic 				else {
70030715Sbostic 					fprintf(stderr,
70130715Sbostic 					    "line %d: %s: bad flag\n",
70230715Sbostic 					    lineno, cp);
70330715Sbostic 					errors++;
70430715Sbostic 				}
70530715Sbostic 			}
70630715Sbostic 			lp->d_flags = v;
70730715Sbostic 			continue;
70830715Sbostic 		}
70930715Sbostic 		if (streq(cp, "drivedata")) {
71030715Sbostic 			register int i;
71130715Sbostic 
71231386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
71330715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
71431386Skarels 				tp = word(cp);
71530715Sbostic 			}
71630715Sbostic 			continue;
71730715Sbostic 		}
71830715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
71930863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
72030715Sbostic 				fprintf(stderr,
72130715Sbostic 				    "line %d: bad # of partitions\n", lineno);
72230863Skarels 				lp->d_npartitions = MAXPARTITIONS;
72330863Skarels 				errors++;
72430863Skarels 			} else
72530715Sbostic 				lp->d_npartitions = v;
72630715Sbostic 			continue;
72730715Sbostic 		}
72830715Sbostic 		if (tp == NULL)
72930715Sbostic 			tp = "";
73030715Sbostic 		if (streq(cp, "disk")) {
73130715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
73230715Sbostic 			continue;
73330715Sbostic 		}
73430715Sbostic 		if (streq(cp, "label")) {
735*34032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
73630715Sbostic 			continue;
73730715Sbostic 		}
73830715Sbostic 		if (streq(cp, "bytes/sector")) {
73930715Sbostic 			v = atoi(tp);
74030715Sbostic 			if (v <= 0 || (v % 512) != 0) {
74130715Sbostic 				fprintf(stderr,
74230715Sbostic 				    "line %d: %s: bad sector size\n",
74330715Sbostic 				    lineno, tp);
74430715Sbostic 				errors++;
74530715Sbostic 			} else
74630715Sbostic 				lp->d_secsize = v;
74730715Sbostic 			continue;
74830715Sbostic 		}
74930715Sbostic 		if (streq(cp, "sectors/track")) {
75030715Sbostic 			v = atoi(tp);
75130715Sbostic 			if (v <= 0) {
75230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
75330715Sbostic 				    lineno, tp, cp);
75430715Sbostic 				errors++;
75530715Sbostic 			} else
75630715Sbostic 				lp->d_nsectors = v;
75730715Sbostic 			continue;
75830715Sbostic 		}
75931386Skarels 		if (streq(cp, "sectors/cylinder")) {
76031386Skarels 			v = atoi(tp);
76131386Skarels 			if (v <= 0) {
76231386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
76331386Skarels 				    lineno, tp, cp);
76431386Skarels 				errors++;
76531386Skarels 			} else
76631386Skarels 				lp->d_secpercyl = v;
76731386Skarels 			continue;
76831386Skarels 		}
76930715Sbostic 		if (streq(cp, "tracks/cylinder")) {
77030715Sbostic 			v = atoi(tp);
77130715Sbostic 			if (v <= 0) {
77230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
77330715Sbostic 				    lineno, tp, cp);
77430715Sbostic 				errors++;
77530715Sbostic 			} else
77630715Sbostic 				lp->d_ntracks = v;
77730715Sbostic 			continue;
77830715Sbostic 		}
77930715Sbostic 		if (streq(cp, "cylinders")) {
78030715Sbostic 			v = atoi(tp);
78130715Sbostic 			if (v <= 0) {
78230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
78330715Sbostic 				    lineno, tp, cp);
78430715Sbostic 				errors++;
78530715Sbostic 			} else
78630715Sbostic 				lp->d_ncylinders = v;
78730715Sbostic 			continue;
78830715Sbostic 		}
78930715Sbostic 		if (streq(cp, "rpm")) {
79030715Sbostic 			v = atoi(tp);
79130715Sbostic 			if (v <= 0) {
79230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
79330715Sbostic 				    lineno, tp, cp);
79430715Sbostic 				errors++;
79530715Sbostic 			} else
79630715Sbostic 				lp->d_rpm = v;
79730715Sbostic 			continue;
79830715Sbostic 		}
79930715Sbostic 		if (streq(cp, "interleave")) {
80030715Sbostic 			v = atoi(tp);
80130715Sbostic 			if (v <= 0) {
80230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
80330715Sbostic 				    lineno, tp, cp);
80430715Sbostic 				errors++;
80530715Sbostic 			} else
80630715Sbostic 				lp->d_interleave = v;
80730715Sbostic 			continue;
80830715Sbostic 		}
80930715Sbostic 		if (streq(cp, "trackskew")) {
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_trackskew = v;
81730715Sbostic 			continue;
81830715Sbostic 		}
81930715Sbostic 		if (streq(cp, "cylinderskew")) {
82030715Sbostic 			v = atoi(tp);
82130715Sbostic 			if (v < 0) {
82230715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
82330715Sbostic 				    lineno, tp, cp);
82430715Sbostic 				errors++;
82530715Sbostic 			} else
82630715Sbostic 				lp->d_cylskew = v;
82730715Sbostic 			continue;
82830715Sbostic 		}
82930715Sbostic 		if (streq(cp, "headswitch")) {
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_headswitch = v;
83730715Sbostic 			continue;
83830715Sbostic 		}
83930715Sbostic 		if (streq(cp, "track-to-track seek")) {
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_trkseek = v;
84730715Sbostic 			continue;
84830715Sbostic 		}
84930715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
85030863Skarels 			unsigned part = *cp - 'a';
85130715Sbostic 
85230863Skarels 			if (part > lp->d_npartitions) {
85330715Sbostic 				fprintf(stderr,
85430715Sbostic 				    "line %d: bad partition name\n", lineno);
85530715Sbostic 				errors++;
85630715Sbostic 				continue;
85730715Sbostic 			}
85830863Skarels 			pp = &lp->d_partitions[part];
85930863Skarels #define NXTNUM(n) { \
86030863Skarels 	cp = tp, tp = word(cp); \
86130863Skarels 	if (tp == NULL) \
86230863Skarels 		tp = cp; \
86330863Skarels 	(n) = atoi(cp); \
86430863Skarels      }
86530863Skarels 
86630863Skarels 			NXTNUM(v);
86730715Sbostic 			if (v < 0) {
86830715Sbostic 				fprintf(stderr,
86930715Sbostic 				    "line %d: %s: bad partition size\n",
87030715Sbostic 				    lineno, cp);
87130715Sbostic 				errors++;
87230715Sbostic 			} else
87330863Skarels 				pp->p_size = v;
87430863Skarels 			NXTNUM(v);
87530715Sbostic 			if (v < 0) {
87630715Sbostic 				fprintf(stderr,
87730715Sbostic 				    "line %d: %s: bad partition offset\n",
87830715Sbostic 				    lineno, cp);
87930715Sbostic 				errors++;
88030715Sbostic 			} else
88130863Skarels 				pp->p_offset = v;
88230715Sbostic 			cp = tp, tp = word(cp);
88330715Sbostic 			cpp = fstypenames;
88430715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
88530715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
88630863Skarels 					pp->p_fstype = cpp - fstypenames;
88730863Skarels 					goto gottype;
88830715Sbostic 				}
889*34032Skarels 			if (isdigit(*cp))
890*34032Skarels 				v = atoi(cp);
891*34032Skarels 			else
892*34032Skarels 				v = FSMAXTYPES;
893*34032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
89430715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
89530715Sbostic 				    "Warning, unknown filesystem type", cp);
896*34032Skarels 				v = FS_UNUSED;
897*34032Skarels 			}
89830863Skarels 			pp->p_fstype = v;
89930863Skarels 	gottype:
90030863Skarels 
90130863Skarels 			switch (pp->p_fstype) {
90230863Skarels 
90330863Skarels 			case FS_UNUSED:				/* XXX */
90430863Skarels 				NXTNUM(pp->p_fsize);
90530863Skarels 				if (pp->p_fsize == 0)
90630863Skarels 					break;
90730863Skarels 				NXTNUM(v);
90830863Skarels 				pp->p_frag = v / pp->p_fsize;
90930863Skarels 				break;
91030863Skarels 
91130863Skarels 			case FS_BSDFFS:
91230863Skarels 				NXTNUM(pp->p_fsize);
91330863Skarels 				if (pp->p_fsize == 0)
91430863Skarels 					break;
91530863Skarels 				NXTNUM(v);
91630863Skarels 				pp->p_frag = v / pp->p_fsize;
91730863Skarels 				NXTNUM(pp->p_cpg);
91830863Skarels 				break;
91930863Skarels 
92030863Skarels 			default:
92130863Skarels 				break;
92230863Skarels 			}
92330715Sbostic 			continue;
92430715Sbostic 		}
92530715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
92630715Sbostic 		    lineno, cp);
92730715Sbostic 		errors++;
92830715Sbostic 	next:
92930715Sbostic 		;
93030715Sbostic 	}
93130715Sbostic 	errors += checklabel(lp);
93230715Sbostic 	return (errors == 0);
93330418Skarels }
93430418Skarels 
93530715Sbostic /*
93630715Sbostic  * Check disklabel for errors and fill in
93730715Sbostic  * derived fields according to supplied values.
93830715Sbostic  */
93930715Sbostic checklabel(lp)
94030715Sbostic 	register struct disklabel *lp;
94130418Skarels {
94230715Sbostic 	register struct partition *pp;
94330715Sbostic 	int i, errors = 0;
94430715Sbostic 	char part;
94530418Skarels 
94630715Sbostic 	if (lp->d_secsize == 0) {
94730715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
94830715Sbostic 		return (1);
94930715Sbostic 	}
95030715Sbostic 	if (lp->d_nsectors == 0) {
95130715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
95230715Sbostic 		return (1);
95330715Sbostic 	}
95430715Sbostic 	if (lp->d_ntracks == 0) {
95530715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
95630715Sbostic 		return (1);
95730715Sbostic 	}
95830715Sbostic 	if  (lp->d_ncylinders == 0) {
95930715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
96030715Sbostic 		errors++;
96130715Sbostic 	}
96230715Sbostic 	if (lp->d_rpm == 0)
96330715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
96430715Sbostic 	if (lp->d_secpercyl == 0)
96530715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
96630715Sbostic 	if (lp->d_secperunit == 0)
96730715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
96830715Sbostic 	if (lp->d_bbsize == 0) {
96930715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
97030715Sbostic 		errors++;
97130715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
97230715Sbostic 		Warning("boot block size %% sector-size != 0\n");
97330715Sbostic 	if (lp->d_sbsize == 0) {
97430715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
97530715Sbostic 		errors++;
97630715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
97730715Sbostic 		Warning("super block size %% sector-size != 0\n");
97830715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
97930715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
98030715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
98130715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
98230715Sbostic 		part = 'a' + i;
98330715Sbostic 		pp = &lp->d_partitions[i];
98430715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
98530715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
98630715Sbostic 			    part, pp->p_offset);
98730715Sbostic #ifdef notdef
98830715Sbostic 		if (pp->p_size % lp->d_secpercyl)
98930715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
99030715Sbostic 			    part);
99130715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
99230715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
99330715Sbostic 			    part);
99430715Sbostic #endif
99530715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
99630715Sbostic 			fprintf(stderr,
99730715Sbostic 			    "partition %c: offset past end of unit\n", part);
99830715Sbostic 			errors++;
99930715Sbostic 		}
100030715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
100130715Sbostic 			fprintf(stderr,
100230715Sbostic 			    "partition %c: partition extends past end of unit\n",
100330715Sbostic 			    part);
100430715Sbostic 			errors++;
100530715Sbostic 		}
100630715Sbostic 	}
100730715Sbostic 	for (; i < MAXPARTITIONS; i++) {
100830715Sbostic 		part = 'a' + i;
100930715Sbostic 		pp = &lp->d_partitions[i];
101030715Sbostic 		if (pp->p_size || pp->p_offset)
101130715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
1012*34032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
101330715Sbostic 	}
101430715Sbostic 	return (errors);
101530715Sbostic }
101630715Sbostic 
101730715Sbostic /*VARARGS1*/
101830715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
101930715Sbostic 	char *fmt;
102030715Sbostic {
102130715Sbostic 
102230715Sbostic 	fprintf(stderr, "Warning, ");
102330715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
102430715Sbostic 	fprintf(stderr, "\n");
102530715Sbostic }
102630715Sbostic 
102730715Sbostic Perror(str)
102830715Sbostic 	char *str;
102930715Sbostic {
103030715Sbostic 	fputs("disklabel: ", stderr); perror(str);
103130418Skarels 	exit(4);
103230418Skarels }
103330715Sbostic 
103430715Sbostic usage()
103530715Sbostic {
103630715Sbostic #ifdef BOOT
1037*34032Skarels 	fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
103830715Sbostic "usage: disklabel [-r] disk", "(to read label)",
103930715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
104030715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
1041*34032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
1042*34032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
104330715Sbostic #else
1044*34032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
104530715Sbostic "usage: disklabel [-r] disk", "(to read label)",
104630715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
104730715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
1048*34032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
1049*34032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
105030715Sbostic #endif
105130715Sbostic 	exit(1);
105230715Sbostic }
1053