xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 42042)
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  *
835983Sbostic  * Redistribution and use in source and binary forms are permitted
935983Sbostic  * provided that the above copyright notice and this paragraph are
1035983Sbostic  * duplicated in all such forms and that any documentation,
1135983Sbostic  * advertising materials, and other materials related to such
1235983Sbostic  * distribution and use acknowledge that the software was developed
1335983Sbostic  * by the University of California, Berkeley.  The name of the
1435983Sbostic  * University may not be used to endorse or promote products derived
1535983Sbostic  * from this software without specific prior written permission.
1635983Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1735983Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1835983Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1930715Sbostic  */
2030715Sbostic 
2130418Skarels #ifndef lint
2235983Sbostic char copyright[] =
2335983Sbostic "@(#) Copyright (c) 1987 The Regents of the University of California.\n\
2435983Sbostic  All rights reserved.\n";
2535983Sbostic #endif /* not lint */
2635983Sbostic 
2735983Sbostic #ifndef lint
28*42042Sbostic static char sccsid[] = "@(#)disklabel.c	5.18 (Berkeley) 05/15/90";
2930418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
3035983Sbostic #endif /* not lint */
3130418Skarels 
3230418Skarels #include <sys/param.h>
3330715Sbostic #include <sys/signal.h>
3430418Skarels #include <sys/errno.h>
3530418Skarels #include <sys/file.h>
3630715Sbostic #include <sys/ioctl.h>
3738505Sbostic #include <ufs/fs.h>
38*42042Sbostic #include <string.h>
3930418Skarels #define DKTYPENAMES
4030418Skarels #include <sys/disklabel.h>
4137261Sbostic #include <stdio.h>
4237261Sbostic #include <ctype.h>
4337261Sbostic #include "pathnames.h"
4430418Skarels 
4530418Skarels /*
4630418Skarels  * Disklabel: read and write disklabels.
4730418Skarels  * The label is usually placed on one of the first sectors of the disk.
4830418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
4930418Skarels  * in which case the label is embedded in the bootstrap.
5030418Skarels  * The bootstrap source must leave space at the proper offset
5130418Skarels  * for the label on such machines.
5230418Skarels  */
5330418Skarels 
5430677Skarels #ifdef vax
5530677Skarels #define RAWPARTITION	'c'
5630677Skarels #else
5730677Skarels #define RAWPARTITION	'a'
5830677Skarels #endif
5930677Skarels 
6030677Skarels #ifndef BBSIZE
6130418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
6230677Skarels #endif
6330418Skarels 
6430418Skarels #ifdef vax
6530418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
6637261Sbostic #define	BOOTDIR	_PATH_BOOTDIR		/* source of boot binaries */
6730677Skarels #else
6830677Skarels #ifdef lint
6930677Skarels #define	BOOT
7030418Skarels #endif
7130677Skarels #endif
7230418Skarels 
7338505Sbostic #define	DEFEDITOR	_PATH_VI
7430715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
7530715Sbostic 
7630715Sbostic #ifdef BOOT
7730418Skarels char	*xxboot;
7830418Skarels char	*bootxx;
7930715Sbostic #endif
8031617Skarels 
8131617Skarels char	*dkname;
8230418Skarels char	*specname;
8337945Sbostic char	tmpfil[] = _PATH_TMP;
8430418Skarels 
8530418Skarels extern	int errno;
8630418Skarels char	namebuf[BBSIZE], *np = namebuf;
8731617Skarels struct	disklabel lab;
8831617Skarels struct	disklabel *readlabel(), *makebootarea();
8930418Skarels char	bootarea[BBSIZE];
9034032Skarels char	boot0[MAXPATHLEN];
9134032Skarels char	boot1[MAXPATHLEN];
9230418Skarels 
9334032Skarels enum	{ UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
9430418Skarels 
9530677Skarels int	rflag;
9630677Skarels 
9734032Skarels #ifdef DEBUG
9834032Skarels int	debug;
9934032Skarels #endif
10034032Skarels 
10130418Skarels main(argc, argv)
10230418Skarels 	int argc;
10330418Skarels 	char *argv[];
10430418Skarels {
10534032Skarels 	extern int optind;
10630418Skarels 	register struct disklabel *lp;
10734032Skarels 	FILE *t;
10834641Skarels 	int ch, f, error = 0;
10930715Sbostic 	char *name = 0, *type;
11030418Skarels 
11134032Skarels 	while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
11234032Skarels 		switch (ch) {
11334032Skarels 			case 'N':
11434032Skarels 				if (op != UNSPEC)
11534032Skarels 					usage();
11634032Skarels 				op = NOWRITE;
11734032Skarels 				break;
11830715Sbostic 			case 'R':
11934032Skarels 				if (op != UNSPEC)
12034032Skarels 					usage();
12130715Sbostic 				op = RESTORE;
12230715Sbostic 				break;
12334032Skarels 			case 'W':
12434032Skarels 				if (op != UNSPEC)
12534032Skarels 					usage();
12634032Skarels 				op = WRITEABLE;
12734032Skarels 				break;
12830715Sbostic 			case 'e':
12934032Skarels 				if (op != UNSPEC)
13034032Skarels 					usage();
13130715Sbostic 				op = EDIT;
13230715Sbostic 				break;
13330715Sbostic 			case 'r':
13430715Sbostic 				++rflag;
13530715Sbostic 				break;
13630715Sbostic 			case 'w':
13734032Skarels 				if (op != UNSPEC)
13834032Skarels 					usage();
13930715Sbostic 				op = WRITE;
14030715Sbostic 				break;
14134032Skarels #ifdef DEBUG
14234032Skarels 			case 'd':
14334032Skarels 				debug++;
14434032Skarels 				break;
14534032Skarels #endif
14630715Sbostic 			case '?':
14730715Sbostic 			default:
14830715Sbostic 				usage();
14930715Sbostic 		}
15030715Sbostic 	argc -= optind;
15130715Sbostic 	argv += optind;
15234032Skarels 	if (op == UNSPEC)
15334032Skarels 		op = READ;
15430715Sbostic 	if (argc < 1)
15530715Sbostic 		usage();
15630715Sbostic 
15730715Sbostic 	dkname = argv[0];
15830418Skarels 	if (dkname[0] != '/') {
15937945Sbostic 		(void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION);
16030418Skarels 		specname = np;
16130418Skarels 		np += strlen(specname) + 1;
16230418Skarels 	} else
16330418Skarels 		specname = dkname;
16430418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
16530418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
16637945Sbostic 		(void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname);
16730418Skarels 		np = namebuf + strlen(specname) + 1;
16830418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
16930418Skarels 	}
17030418Skarels 	if (f < 0)
17130418Skarels 		Perror(specname);
17230418Skarels 
17330715Sbostic 	switch(op) {
17430715Sbostic 	case EDIT:
17530715Sbostic 		if (argc != 1)
17630715Sbostic 			usage();
17734032Skarels 		lp = readlabel(f);
17834641Skarels 		error = edit(lp, f);
17930715Sbostic 		break;
18034032Skarels 	case NOWRITE: {
18134032Skarels 		int flag = 0;
18234032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
18334032Skarels 			Perror("ioctl DIOCWLABEL");
18434032Skarels 		break;
18534032Skarels 	}
18630418Skarels 	case READ:
18730715Sbostic 		if (argc != 1)
18830715Sbostic 			usage();
18934032Skarels 		lp = readlabel(f);
19030418Skarels 		display(stdout, lp);
19134641Skarels 		error = checklabel(lp);
19230418Skarels 		break;
19330715Sbostic 	case RESTORE:
19430715Sbostic #ifdef BOOT
19534032Skarels 		if (rflag) {
19634032Skarels 			if (argc == 4) {	/* [ priboot secboot ] */
19734032Skarels 				xxboot = argv[2];
19834032Skarels 				bootxx = argv[3];
19934032Skarels 				lab.d_secsize = DEV_BSIZE;	/* XXX */
20034032Skarels 				lab.d_bbsize = BBSIZE;		/* XXX */
20134032Skarels 			}
20234032Skarels 			else if (argc == 3) 	/* [ disktype ] */
20334032Skarels 				makelabel(argv[2], (char *)NULL, &lab);
20434032Skarels 			else {
20534032Skarels 				fprintf(stderr,
20634032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
20734032Skarels 				exit(1);
20834032Skarels 			}
20934032Skarels 		}
21034032Skarels 		else
21131617Skarels #endif
21230715Sbostic 		if (argc != 2)
21330715Sbostic 			usage();
21431617Skarels 		lp = makebootarea(bootarea, &lab);
21530715Sbostic 		if (!(t = fopen(argv[1],"r")))
21630715Sbostic 			Perror(argv[1]);
21730715Sbostic 		if (getasciilabel(t, lp))
21834641Skarels 			error = writelabel(f, bootarea, lp);
21930418Skarels 		break;
22030418Skarels 	case WRITE:
22130715Sbostic 		type = argv[1];
22230715Sbostic #ifdef BOOT
22330715Sbostic 		if (argc > 5 || argc < 2)
22430715Sbostic 			usage();
22530715Sbostic 		if (argc > 3) {
22630715Sbostic 			bootxx = argv[--argc];
22730715Sbostic 			xxboot = argv[--argc];
22830715Sbostic 		}
22930715Sbostic #else
23030715Sbostic 		if (argc > 3 || argc < 2)
23130715Sbostic 			usage();
23230715Sbostic #endif
23330715Sbostic 		if (argc > 2)
23430715Sbostic 			name = argv[--argc];
23530418Skarels 		makelabel(type, name, &lab);
23631617Skarels 		lp = makebootarea(bootarea, &lab);
23730418Skarels 		*lp = lab;
23830715Sbostic 		if (checklabel(lp) == 0)
23934641Skarels 			error = writelabel(f, bootarea, lp);
24030418Skarels 		break;
24134032Skarels 	case WRITEABLE: {
24234032Skarels 		int flag = 1;
24334032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
24434032Skarels 			Perror("ioctl DIOCWLABEL");
24534032Skarels 		break;
24630418Skarels 	}
24734032Skarels 	}
24834641Skarels 	exit(error);
24930418Skarels }
25030418Skarels 
25134032Skarels /*
25234032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
25334032Skarels  * effect, set the names of the primary and secondary boot files
25434032Skarels  * if specified.
25534032Skarels  */
25630418Skarels makelabel(type, name, lp)
25730418Skarels 	char *type, *name;
25830418Skarels 	register struct disklabel *lp;
25930418Skarels {
26030418Skarels 	register struct disklabel *dp;
26134032Skarels 	char *strcpy();
26230418Skarels 
26330418Skarels 	dp = getdiskbyname(type);
26430418Skarels 	if (dp == NULL) {
26530418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
26630418Skarels 		exit(1);
26730418Skarels 	}
26830418Skarels 	*lp = *dp;
26934032Skarels #ifdef BOOT
27034032Skarels 	/*
27134032Skarels 	 * Check if disktab specifies the bootstraps (b0 or b1).
27234032Skarels 	 */
27334032Skarels 	if (!xxboot && lp->d_boot0) {
27434032Skarels 		if (*lp->d_boot0 != '/')
27534032Skarels 			(void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
27634032Skarels 		else
27734032Skarels 			(void)strcpy(boot0, lp->d_boot0);
27834032Skarels 		xxboot = boot0;
27934032Skarels 	}
28034032Skarels 	if (!bootxx && lp->d_boot1) {
28134032Skarels 		if (*lp->d_boot1 != '/')
28234032Skarels 			(void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
28334032Skarels 		else
28434032Skarels 			(void)strcpy(boot1, lp->d_boot1);
28534032Skarels 		bootxx = boot1;
28634032Skarels 	}
28734032Skarels 	/*
28834032Skarels 	 * If bootstraps not specified anywhere, makebootarea()
28934032Skarels 	 * will choose ones based on the name of the disk special
29034032Skarels 	 * file. E.g. /dev/ra0 -> raboot, bootra
29134032Skarels 	 */
29234032Skarels #endif /*BOOT*/
29334032Skarels 	/* d_packname is union d_boot[01], so zero */
29434032Skarels 	bzero(lp->d_packname, sizeof(lp->d_packname));
29530418Skarels 	if (name)
29634032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
29730418Skarels }
29830418Skarels 
29930418Skarels writelabel(f, boot, lp)
30030418Skarels 	int f;
30130418Skarels 	char *boot;
30230418Skarels 	register struct disklabel *lp;
30330418Skarels {
30430715Sbostic 	register int i;
30534032Skarels 	int flag;
30634032Skarels 	off_t lseek();
30730418Skarels 
30830418Skarels 	lp->d_magic = DISKMAGIC;
30930418Skarels 	lp->d_magic2 = DISKMAGIC;
31030418Skarels 	lp->d_checksum = 0;
31130418Skarels 	lp->d_checksum = dkcksum(lp);
31230677Skarels 	if (rflag) {
31334032Skarels 		/*
31434032Skarels 		 * First set the kernel disk label,
31534032Skarels 		 * then write a label to the raw disk.
31634032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
31734032Skarels 		 * keep going; otherwise, the kernel consistency checks
31834032Skarels 		 * may prevent us from changing the current (in-core)
31934032Skarels 		 * label.
32034032Skarels 		 */
32134032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
32234641Skarels 		    errno != ENODEV && errno != ENOTTY) {
32334641Skarels 			l_perror("ioctl DIOCSDINFO");
32434641Skarels 			return (1);
32534641Skarels 		}
32631617Skarels 		(void)lseek(f, (off_t)0, L_SET);
32734032Skarels 		/*
32834032Skarels 		 * write enable label sector before write (if necessary),
32934032Skarels 		 * disable after writing.
33034032Skarels 		 */
33134032Skarels 		flag = 1;
33234032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
33334032Skarels 			perror("ioctl DIOCWLABEL");
33434641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
33534641Skarels 			perror("write");
33634641Skarels 			return (1);
33734641Skarels 		}
33834032Skarels 		flag = 0;
33934032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
34034641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
34134641Skarels 		l_perror("ioctl DIOCWDINFO");
34234641Skarels 		return (1);
34334641Skarels 	}
34434032Skarels #ifdef vax
34530677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
34630677Skarels 		daddr_t alt;
34730677Skarels 
34830677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
34930677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
35030715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
35130677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
35230677Skarels 				int oerrno = errno;
35330677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
35430677Skarels 				errno = oerrno;
35530677Skarels 				perror("write");
35630677Skarels 			}
35730418Skarels 		}
35830418Skarels 	}
35930419Skarels #endif
36034641Skarels 	return (0);
36130418Skarels }
36230418Skarels 
36334641Skarels l_perror(s)
36434641Skarels 	char *s;
36534641Skarels {
36634641Skarels 	int saverrno = errno;
36734641Skarels 
36834641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
36934641Skarels 
37034641Skarels 	switch (saverrno) {
37134641Skarels 
37234641Skarels 	case ESRCH:
37334641Skarels 		fprintf(stderr, "No disk label on disk;\n");
37434641Skarels 		fprintf(stderr,
37534641Skarels 		    "use \"disklabel -r\" to install initial label\n");
37634641Skarels 		break;
37734641Skarels 
37834641Skarels 	case EINVAL:
37934641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
38034641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
38134641Skarels 		break;
38234641Skarels 
38334641Skarels 	case EBUSY:
38434641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
38534641Skarels 		break;
38634641Skarels 
38734641Skarels 	case EXDEV:
38834641Skarels 		fprintf(stderr,
38934641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
39034641Skarels 		break;
39134641Skarels 
39234641Skarels 	default:
39334641Skarels 		errno = saverrno;
39434641Skarels 		perror((char *)NULL);
39534641Skarels 		break;
39634641Skarels 	}
39734641Skarels }
39834641Skarels 
39930418Skarels /*
40031617Skarels  * Fetch disklabel for disk.
40131617Skarels  * Use ioctl to get label unless -r flag is given.
40230418Skarels  */
40330418Skarels struct disklabel *
40434032Skarels readlabel(f)
40534032Skarels 	int f;
40630418Skarels {
40730418Skarels 	register struct disklabel *lp;
40830418Skarels 
40934032Skarels 	if (rflag) {
41031617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
41131401Skarels 			Perror(specname);
41231617Skarels 		for (lp = (struct disklabel *)bootarea;
41331617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
41430677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
41530677Skarels 			if (lp->d_magic == DISKMAGIC &&
41630677Skarels 			    lp->d_magic2 == DISKMAGIC)
41730677Skarels 				break;
41831617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
41930677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
42030677Skarels 		    dkcksum(lp) != 0) {
42130677Skarels 			fprintf(stderr,
42230418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
42334032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
42434032Skarels 			exit (1);
42530677Skarels 		}
42634032Skarels 	} else {
42734032Skarels 		lp = &lab;
42834032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
42934032Skarels 			Perror("ioctl DIOCGDINFO");
43030418Skarels 	}
43130418Skarels 	return (lp);
43230418Skarels }
43330418Skarels 
43430418Skarels struct disklabel *
43531617Skarels makebootarea(boot, dp)
43630418Skarels 	char *boot;
43730418Skarels 	register struct disklabel *dp;
43830418Skarels {
43930418Skarels 	struct disklabel *lp;
44030418Skarels 	register char *p;
44130418Skarels 	int b;
44230418Skarels #ifdef BOOT
44330715Sbostic 	char	*dkbasename;
44434032Skarels #endif /*BOOT*/
44530715Sbostic 
44634032Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
44734032Skarels 	    LABELOFFSET);
44834032Skarels #ifdef BOOT
44934032Skarels 	if (!rflag)
45034032Skarels 		return (lp);
45134032Skarels 
45234032Skarels 	if (xxboot == NULL || bootxx == NULL) {
45330418Skarels 		dkbasename = np;
45430418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
45530418Skarels 			p = dkname;
45630418Skarels 		else
45730418Skarels 			p++;
45830418Skarels 		while (*p && !isdigit(*p))
45930418Skarels 			*np++ = *p++;
46030418Skarels 		*np++ = '\0';
46130418Skarels 
46234032Skarels 		if (xxboot == NULL) {
46334032Skarels 			(void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
46434032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
46534032Skarels 				dkbasename++;
46634032Skarels 			xxboot = np;
46734032Skarels 			(void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
46834032Skarels 			np += strlen(xxboot) + 1;
46934032Skarels 		}
47034032Skarels 		if (bootxx == NULL) {
47134032Skarels 			(void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
47234032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
47334032Skarels 				dkbasename++;
47434032Skarels 			bootxx = np;
47534032Skarels 			(void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
47634032Skarels 			np += strlen(bootxx) + 1;
47734032Skarels 		}
47830418Skarels 	}
47934032Skarels #ifdef DEBUG
48034032Skarels 	if (debug)
48134032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
48234032Skarels 			xxboot, bootxx);
48334032Skarels #endif
48430418Skarels 
48530418Skarels 	b = open(xxboot, O_RDONLY);
48630418Skarels 	if (b < 0)
48730418Skarels 		Perror(xxboot);
48830715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
48930418Skarels 		Perror(xxboot);
49030418Skarels 	close(b);
49130418Skarels 	b = open(bootxx, O_RDONLY);
49230418Skarels 	if (b < 0)
49330418Skarels 		Perror(bootxx);
49430715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
49530418Skarels 		Perror(bootxx);
49630715Sbostic 	(void)close(b);
49734032Skarels #endif /*BOOT*/
49830418Skarels 
49930418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
50030418Skarels 		if (*p) {
50130418Skarels 			fprintf(stderr,
50230418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
50330418Skarels 			exit(2);
50430418Skarels 		}
50530418Skarels 	return (lp);
50630418Skarels }
50730418Skarels 
50830418Skarels display(f, lp)
50930418Skarels 	FILE *f;
51030418Skarels 	register struct disklabel *lp;
51130418Skarels {
51230715Sbostic 	register int i, j;
51330418Skarels 	register struct partition *pp;
51430418Skarels 
51530418Skarels 	fprintf(f, "# %s:\n", specname);
51630418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
51730418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
51830418Skarels 	else
51930418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
52030418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
52134032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
52231401Skarels 	fprintf(f, "flags:");
52330418Skarels 	if (lp->d_flags & D_REMOVABLE)
52431401Skarels 		fprintf(f, " removeable");
52530418Skarels 	if (lp->d_flags & D_ECC)
52631401Skarels 		fprintf(f, " ecc");
52730418Skarels 	if (lp->d_flags & D_BADSECT)
52831401Skarels 		fprintf(f, " badsect");
52930418Skarels 	fprintf(f, "\n");
53030418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
53130418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
53230418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
53331386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
53430418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
53530715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
53630418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
53730418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
53830418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
53930418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
54030418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
54130418Skarels 	fprintf(f, "drivedata: ");
54230418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
54330418Skarels 		if (lp->d_drivedata[i])
54430418Skarels 			break;
54530418Skarels 	if (i < 0)
54630418Skarels 		i = 0;
54730418Skarels 	for (j = 0; j <= i; j++)
54830418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
54930418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
55030863Skarels 	fprintf(f,
55130863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
55230418Skarels 	pp = lp->d_partitions;
55330418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
55430418Skarels 		if (pp->p_size) {
55530863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
55630863Skarels 			   pp->p_size, pp->p_offset);
55730418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
55830418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
55930418Skarels 			else
56030418Skarels 				fprintf(f, "%8d", pp->p_fstype);
56130863Skarels 			switch (pp->p_fstype) {
56230863Skarels 
56330863Skarels 			case FS_UNUSED:				/* XXX */
56430863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
56530863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
56630863Skarels 				break;
56730863Skarels 
56830863Skarels 			case FS_BSDFFS:
56930863Skarels 				fprintf(f, "    %5d %5d %5d ",
57030863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
57130863Skarels 				    pp->p_cpg);
57230863Skarels 				break;
57330863Skarels 
57430863Skarels 			default:
57530863Skarels 				fprintf(f, "%20.20s", "");
57630863Skarels 				break;
57730863Skarels 			}
57830418Skarels 			fprintf(f, "\t# (Cyl. %4d",
57930418Skarels 			    pp->p_offset / lp->d_secpercyl);
58030418Skarels 			if (pp->p_offset % lp->d_secpercyl)
58130418Skarels 			    putc('*', f);
58230418Skarels 			else
58330418Skarels 			    putc(' ', f);
58430418Skarels 			fprintf(f, "- %d",
58530418Skarels 			    (pp->p_offset +
58630418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
58730418Skarels 			    lp->d_secpercyl - 1);
58830418Skarels 			if (pp->p_size % lp->d_secpercyl)
58930418Skarels 			    putc('*', f);
59030863Skarels 			fprintf(f, ")\n");
59130418Skarels 		}
59230418Skarels 	}
59332121Stef 	fflush(f);
59430418Skarels }
59530418Skarels 
59634641Skarels edit(lp, f)
59730715Sbostic 	struct disklabel *lp;
59834641Skarels 	int f;
59930418Skarels {
60030715Sbostic 	register int c;
60130715Sbostic 	struct disklabel label;
60230715Sbostic 	FILE *fd;
60330715Sbostic 	char *mktemp();
60430715Sbostic 
60530715Sbostic 	(void) mktemp(tmpfil);
60630715Sbostic 	fd = fopen(tmpfil, "w");
60730715Sbostic 	if (fd == NULL) {
60830715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
60934641Skarels 		return (1);
61030715Sbostic 	}
61130715Sbostic 	(void)fchmod(fd, 0600);
61230715Sbostic 	display(fd, lp);
61330715Sbostic 	fclose(fd);
61430715Sbostic 	for (;;) {
61530715Sbostic 		if (!editit())
61630715Sbostic 			break;
61730715Sbostic 		fd = fopen(tmpfil, "r");
61830715Sbostic 		if (fd == NULL) {
61934032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
62034032Skarels 				tmpfil);
62130715Sbostic 			break;
62230715Sbostic 		}
62330863Skarels 		bzero((char *)&label, sizeof(label));
62430715Sbostic 		if (getasciilabel(fd, &label)) {
62530715Sbostic 			*lp = label;
62634641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
62734641Skarels 				(void) unlink(tmpfil);
62834641Skarels 				return (0);
62934641Skarels 			}
63030715Sbostic 		}
63130715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
63230715Sbostic 		c = getchar();
63330715Sbostic 		if (c != EOF && c != (int)'\n')
63430715Sbostic 			while (getchar() != (int)'\n')
63530715Sbostic 				;
63630715Sbostic 		if  (c == (int)'n')
63730715Sbostic 			break;
63830715Sbostic 	}
63930715Sbostic 	(void) unlink(tmpfil);
64034641Skarels 	return (1);
64130418Skarels }
64230418Skarels 
64330715Sbostic editit()
64430715Sbostic {
64530715Sbostic 	register int pid, xpid;
64630715Sbostic 	int stat, omask;
64730715Sbostic 	extern char *getenv();
64830418Skarels 
64930715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
65030715Sbostic 	while ((pid = fork()) < 0) {
65130715Sbostic 		extern int errno;
65230715Sbostic 
65330715Sbostic 		if (errno == EPROCLIM) {
65430715Sbostic 			fprintf(stderr, "You have too many processes\n");
65530715Sbostic 			return(0);
65630715Sbostic 		}
65730715Sbostic 		if (errno != EAGAIN) {
65830715Sbostic 			perror("fork");
65930715Sbostic 			return(0);
66030715Sbostic 		}
66130715Sbostic 		sleep(1);
66230715Sbostic 	}
66330715Sbostic 	if (pid == 0) {
66430715Sbostic 		register char *ed;
66530715Sbostic 
66630715Sbostic 		sigsetmask(omask);
66730715Sbostic 		setgid(getgid());
66830715Sbostic 		setuid(getuid());
66930715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
67030715Sbostic 			ed = DEFEDITOR;
67130715Sbostic 		execlp(ed, ed, tmpfil, 0);
67230715Sbostic 		perror(ed);
67330715Sbostic 		exit(1);
67430715Sbostic 	}
67530715Sbostic 	while ((xpid = wait(&stat)) >= 0)
67630715Sbostic 		if (xpid == pid)
67730715Sbostic 			break;
67830715Sbostic 	sigsetmask(omask);
67930715Sbostic 	return(!stat);
68030715Sbostic }
68130715Sbostic 
68230715Sbostic char *
68330715Sbostic skip(cp)
68430715Sbostic 	register char *cp;
68530715Sbostic {
68630715Sbostic 
68730715Sbostic 	while (*cp != '\0' && isspace(*cp))
68830715Sbostic 		cp++;
68930715Sbostic 	if (*cp == '\0' || *cp == '#')
69030715Sbostic 		return ((char *)NULL);
69130715Sbostic 	return (cp);
69230715Sbostic }
69330715Sbostic 
69430715Sbostic char *
69530715Sbostic word(cp)
69630715Sbostic 	register char *cp;
69730715Sbostic {
69830715Sbostic 	register char c;
69930715Sbostic 
70031401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
70131401Skarels 		cp++;
70230715Sbostic 	if ((c = *cp) != '\0') {
70330715Sbostic 		*cp++ = '\0';
70430715Sbostic 		if (c != '#')
70530715Sbostic 			return (skip(cp));
70630715Sbostic 	}
70730715Sbostic 	return ((char *)NULL);
70830715Sbostic }
70930715Sbostic 
71030418Skarels /*
71130418Skarels  * Read an ascii label in from fd f,
71230418Skarels  * in the same format as that put out by display(),
71330418Skarels  * and fill in lp.
71430418Skarels  */
71530418Skarels getasciilabel(f, lp)
71630715Sbostic 	FILE	*f;
71730418Skarels 	register struct disklabel *lp;
71830418Skarels {
71930715Sbostic 	register char **cpp, *cp;
72030863Skarels 	register struct partition *pp;
72130715Sbostic 	char *tp, *s, line[BUFSIZ];
72230715Sbostic 	int v, lineno = 0, errors = 0;
72330715Sbostic 
72430715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
72530715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
72630715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
72730715Sbostic 		lineno++;
72830715Sbostic 		if (cp = index(line,'\n'))
72930715Sbostic 			*cp = '\0';
73030715Sbostic 		cp = skip(line);
73130715Sbostic 		if (cp == NULL)
73230715Sbostic 			continue;
73330715Sbostic 		tp = index(cp, ':');
73430715Sbostic 		if (tp == NULL) {
73530715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
73630715Sbostic 			errors++;
73730715Sbostic 			continue;
73830715Sbostic 		}
73930715Sbostic 		*tp++ = '\0', tp = skip(tp);
74030715Sbostic 		if (streq(cp, "type")) {
74130715Sbostic 			if (tp == NULL)
74230715Sbostic 				tp = "unknown";
74330715Sbostic 			cpp = dktypenames;
74430715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
74530715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
74630715Sbostic 					lp->d_type = cpp - dktypenames;
74730715Sbostic 					goto next;
74830715Sbostic 				}
74930715Sbostic 			v = atoi(tp);
75030715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
75130715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
75230715Sbostic 				    "Warning, unknown disk type", v);
75330715Sbostic 			lp->d_type = v;
75430715Sbostic 			continue;
75530715Sbostic 		}
75630715Sbostic 		if (streq(cp, "flags")) {
75734032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
75834032Skarels 				tp = word(cp);
75930715Sbostic 				if (streq(cp, "removeable"))
76030715Sbostic 					v |= D_REMOVABLE;
76130715Sbostic 				else if (streq(cp, "ecc"))
76230715Sbostic 					v |= D_ECC;
76330715Sbostic 				else if (streq(cp, "badsect"))
76430715Sbostic 					v |= D_BADSECT;
76530715Sbostic 				else {
76630715Sbostic 					fprintf(stderr,
76730715Sbostic 					    "line %d: %s: bad flag\n",
76830715Sbostic 					    lineno, cp);
76930715Sbostic 					errors++;
77030715Sbostic 				}
77130715Sbostic 			}
77230715Sbostic 			lp->d_flags = v;
77330715Sbostic 			continue;
77430715Sbostic 		}
77530715Sbostic 		if (streq(cp, "drivedata")) {
77630715Sbostic 			register int i;
77730715Sbostic 
77831386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
77930715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
78031386Skarels 				tp = word(cp);
78130715Sbostic 			}
78230715Sbostic 			continue;
78330715Sbostic 		}
78430715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
78530863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
78630715Sbostic 				fprintf(stderr,
78730715Sbostic 				    "line %d: bad # of partitions\n", lineno);
78830863Skarels 				lp->d_npartitions = MAXPARTITIONS;
78930863Skarels 				errors++;
79030863Skarels 			} else
79130715Sbostic 				lp->d_npartitions = v;
79230715Sbostic 			continue;
79330715Sbostic 		}
79430715Sbostic 		if (tp == NULL)
79530715Sbostic 			tp = "";
79630715Sbostic 		if (streq(cp, "disk")) {
79730715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
79830715Sbostic 			continue;
79930715Sbostic 		}
80030715Sbostic 		if (streq(cp, "label")) {
80134032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
80230715Sbostic 			continue;
80330715Sbostic 		}
80430715Sbostic 		if (streq(cp, "bytes/sector")) {
80530715Sbostic 			v = atoi(tp);
80630715Sbostic 			if (v <= 0 || (v % 512) != 0) {
80730715Sbostic 				fprintf(stderr,
80830715Sbostic 				    "line %d: %s: bad sector size\n",
80930715Sbostic 				    lineno, tp);
81030715Sbostic 				errors++;
81130715Sbostic 			} else
81230715Sbostic 				lp->d_secsize = v;
81330715Sbostic 			continue;
81430715Sbostic 		}
81530715Sbostic 		if (streq(cp, "sectors/track")) {
81630715Sbostic 			v = atoi(tp);
81730715Sbostic 			if (v <= 0) {
81830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
81930715Sbostic 				    lineno, tp, cp);
82030715Sbostic 				errors++;
82130715Sbostic 			} else
82230715Sbostic 				lp->d_nsectors = v;
82330715Sbostic 			continue;
82430715Sbostic 		}
82531386Skarels 		if (streq(cp, "sectors/cylinder")) {
82631386Skarels 			v = atoi(tp);
82731386Skarels 			if (v <= 0) {
82831386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
82931386Skarels 				    lineno, tp, cp);
83031386Skarels 				errors++;
83131386Skarels 			} else
83231386Skarels 				lp->d_secpercyl = v;
83331386Skarels 			continue;
83431386Skarels 		}
83530715Sbostic 		if (streq(cp, "tracks/cylinder")) {
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_ntracks = v;
84330715Sbostic 			continue;
84430715Sbostic 		}
84530715Sbostic 		if (streq(cp, "cylinders")) {
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_ncylinders = v;
85330715Sbostic 			continue;
85430715Sbostic 		}
85530715Sbostic 		if (streq(cp, "rpm")) {
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_rpm = v;
86330715Sbostic 			continue;
86430715Sbostic 		}
86530715Sbostic 		if (streq(cp, "interleave")) {
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_interleave = v;
87330715Sbostic 			continue;
87430715Sbostic 		}
87530715Sbostic 		if (streq(cp, "trackskew")) {
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_trackskew = v;
88330715Sbostic 			continue;
88430715Sbostic 		}
88530715Sbostic 		if (streq(cp, "cylinderskew")) {
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_cylskew = v;
89330715Sbostic 			continue;
89430715Sbostic 		}
89530715Sbostic 		if (streq(cp, "headswitch")) {
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_headswitch = v;
90330715Sbostic 			continue;
90430715Sbostic 		}
90530715Sbostic 		if (streq(cp, "track-to-track seek")) {
90630715Sbostic 			v = atoi(tp);
90730715Sbostic 			if (v < 0) {
90830715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
90930715Sbostic 				    lineno, tp, cp);
91030715Sbostic 				errors++;
91130715Sbostic 			} else
91230715Sbostic 				lp->d_trkseek = v;
91330715Sbostic 			continue;
91430715Sbostic 		}
91530715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
91630863Skarels 			unsigned part = *cp - 'a';
91730715Sbostic 
91830863Skarels 			if (part > lp->d_npartitions) {
91930715Sbostic 				fprintf(stderr,
92030715Sbostic 				    "line %d: bad partition name\n", lineno);
92130715Sbostic 				errors++;
92230715Sbostic 				continue;
92330715Sbostic 			}
92430863Skarels 			pp = &lp->d_partitions[part];
92530863Skarels #define NXTNUM(n) { \
92630863Skarels 	cp = tp, tp = word(cp); \
92730863Skarels 	if (tp == NULL) \
92830863Skarels 		tp = cp; \
92930863Skarels 	(n) = atoi(cp); \
93030863Skarels      }
93130863Skarels 
93230863Skarels 			NXTNUM(v);
93330715Sbostic 			if (v < 0) {
93430715Sbostic 				fprintf(stderr,
93530715Sbostic 				    "line %d: %s: bad partition size\n",
93630715Sbostic 				    lineno, cp);
93730715Sbostic 				errors++;
93830715Sbostic 			} else
93930863Skarels 				pp->p_size = v;
94030863Skarels 			NXTNUM(v);
94130715Sbostic 			if (v < 0) {
94230715Sbostic 				fprintf(stderr,
94330715Sbostic 				    "line %d: %s: bad partition offset\n",
94430715Sbostic 				    lineno, cp);
94530715Sbostic 				errors++;
94630715Sbostic 			} else
94730863Skarels 				pp->p_offset = v;
94830715Sbostic 			cp = tp, tp = word(cp);
94930715Sbostic 			cpp = fstypenames;
95030715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
95130715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
95230863Skarels 					pp->p_fstype = cpp - fstypenames;
95330863Skarels 					goto gottype;
95430715Sbostic 				}
95534032Skarels 			if (isdigit(*cp))
95634032Skarels 				v = atoi(cp);
95734032Skarels 			else
95834032Skarels 				v = FSMAXTYPES;
95934032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
96030715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
96130715Sbostic 				    "Warning, unknown filesystem type", cp);
96234032Skarels 				v = FS_UNUSED;
96334032Skarels 			}
96430863Skarels 			pp->p_fstype = v;
96530863Skarels 	gottype:
96630863Skarels 
96730863Skarels 			switch (pp->p_fstype) {
96830863Skarels 
96930863Skarels 			case FS_UNUSED:				/* XXX */
97030863Skarels 				NXTNUM(pp->p_fsize);
97130863Skarels 				if (pp->p_fsize == 0)
97230863Skarels 					break;
97330863Skarels 				NXTNUM(v);
97430863Skarels 				pp->p_frag = v / pp->p_fsize;
97530863Skarels 				break;
97630863Skarels 
97730863Skarels 			case FS_BSDFFS:
97830863Skarels 				NXTNUM(pp->p_fsize);
97930863Skarels 				if (pp->p_fsize == 0)
98030863Skarels 					break;
98130863Skarels 				NXTNUM(v);
98230863Skarels 				pp->p_frag = v / pp->p_fsize;
98330863Skarels 				NXTNUM(pp->p_cpg);
98430863Skarels 				break;
98530863Skarels 
98630863Skarels 			default:
98730863Skarels 				break;
98830863Skarels 			}
98930715Sbostic 			continue;
99030715Sbostic 		}
99130715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
99230715Sbostic 		    lineno, cp);
99330715Sbostic 		errors++;
99430715Sbostic 	next:
99530715Sbostic 		;
99630715Sbostic 	}
99730715Sbostic 	errors += checklabel(lp);
99830715Sbostic 	return (errors == 0);
99930418Skarels }
100030418Skarels 
100130715Sbostic /*
100230715Sbostic  * Check disklabel for errors and fill in
100330715Sbostic  * derived fields according to supplied values.
100430715Sbostic  */
100530715Sbostic checklabel(lp)
100630715Sbostic 	register struct disklabel *lp;
100730418Skarels {
100830715Sbostic 	register struct partition *pp;
100930715Sbostic 	int i, errors = 0;
101030715Sbostic 	char part;
101130418Skarels 
101230715Sbostic 	if (lp->d_secsize == 0) {
101330715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
101430715Sbostic 		return (1);
101530715Sbostic 	}
101630715Sbostic 	if (lp->d_nsectors == 0) {
101730715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
101830715Sbostic 		return (1);
101930715Sbostic 	}
102030715Sbostic 	if (lp->d_ntracks == 0) {
102130715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
102230715Sbostic 		return (1);
102330715Sbostic 	}
102430715Sbostic 	if  (lp->d_ncylinders == 0) {
102530715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
102630715Sbostic 		errors++;
102730715Sbostic 	}
102830715Sbostic 	if (lp->d_rpm == 0)
102930715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
103030715Sbostic 	if (lp->d_secpercyl == 0)
103130715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
103230715Sbostic 	if (lp->d_secperunit == 0)
103330715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
103430715Sbostic 	if (lp->d_bbsize == 0) {
103530715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
103630715Sbostic 		errors++;
103730715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
103830715Sbostic 		Warning("boot block size %% sector-size != 0\n");
103930715Sbostic 	if (lp->d_sbsize == 0) {
104030715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
104130715Sbostic 		errors++;
104230715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
104330715Sbostic 		Warning("super block size %% sector-size != 0\n");
104430715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
104530715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
104630715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
104730715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
104830715Sbostic 		part = 'a' + i;
104930715Sbostic 		pp = &lp->d_partitions[i];
105030715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
105130715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
105230715Sbostic 			    part, pp->p_offset);
105330715Sbostic #ifdef notdef
105430715Sbostic 		if (pp->p_size % lp->d_secpercyl)
105530715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
105630715Sbostic 			    part);
105730715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
105830715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
105930715Sbostic 			    part);
106030715Sbostic #endif
106130715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
106230715Sbostic 			fprintf(stderr,
106330715Sbostic 			    "partition %c: offset past end of unit\n", part);
106430715Sbostic 			errors++;
106530715Sbostic 		}
106630715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
106730715Sbostic 			fprintf(stderr,
106830715Sbostic 			    "partition %c: partition extends past end of unit\n",
106930715Sbostic 			    part);
107030715Sbostic 			errors++;
107130715Sbostic 		}
107230715Sbostic 	}
107330715Sbostic 	for (; i < MAXPARTITIONS; i++) {
107430715Sbostic 		part = 'a' + i;
107530715Sbostic 		pp = &lp->d_partitions[i];
107630715Sbostic 		if (pp->p_size || pp->p_offset)
107730715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
107834032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
107930715Sbostic 	}
108030715Sbostic 	return (errors);
108130715Sbostic }
108230715Sbostic 
108330715Sbostic /*VARARGS1*/
108430715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
108530715Sbostic 	char *fmt;
108630715Sbostic {
108730715Sbostic 
108830715Sbostic 	fprintf(stderr, "Warning, ");
108930715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
109030715Sbostic 	fprintf(stderr, "\n");
109130715Sbostic }
109230715Sbostic 
109330715Sbostic Perror(str)
109430715Sbostic 	char *str;
109530715Sbostic {
109630715Sbostic 	fputs("disklabel: ", stderr); perror(str);
109730418Skarels 	exit(4);
109830418Skarels }
109930715Sbostic 
110030715Sbostic usage()
110130715Sbostic {
110230715Sbostic #ifdef BOOT
110334032Skarels 	fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
110430715Sbostic "usage: disklabel [-r] disk", "(to read label)",
110530715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
110630715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
110734032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
110834032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
110930715Sbostic #else
111034032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
111130715Sbostic "usage: disklabel [-r] disk", "(to read label)",
111230715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
111330715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
111434032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
111534032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
111630715Sbostic #endif
111730715Sbostic 	exit(1);
111830715Sbostic }
1119