xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 35983)
130715Sbostic /*
2*35983Sbostic  * Copyright (c) 1987 The Regents of the University of California.
3*35983Sbostic  * All rights reserved.
4*35983Sbostic  *
5*35983Sbostic  * This code is derived from software contributed to Berkeley by
6*35983Sbostic  * Symmetric Computer Systems.
7*35983Sbostic  *
8*35983Sbostic  * Redistribution and use in source and binary forms are permitted
9*35983Sbostic  * provided that the above copyright notice and this paragraph are
10*35983Sbostic  * duplicated in all such forms and that any documentation,
11*35983Sbostic  * advertising materials, and other materials related to such
12*35983Sbostic  * distribution and use acknowledge that the software was developed
13*35983Sbostic  * by the University of California, Berkeley.  The name of the
14*35983Sbostic  * University may not be used to endorse or promote products derived
15*35983Sbostic  * from this software without specific prior written permission.
16*35983Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*35983Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*35983Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1930715Sbostic  */
2030715Sbostic 
2130418Skarels #ifndef lint
22*35983Sbostic char copyright[] =
23*35983Sbostic "@(#) Copyright (c) 1987 The Regents of the University of California.\n\
24*35983Sbostic  All rights reserved.\n";
25*35983Sbostic #endif /* not lint */
26*35983Sbostic 
27*35983Sbostic #ifndef lint
28*35983Sbostic static char sccsid[] = "@(#)disklabel.c	5.14 (Berkeley) 10/21/88";
2930418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
30*35983Sbostic #endif /* not lint */
3130418Skarels 
3230418Skarels #include <stdio.h>
3330418Skarels #include <ctype.h>
3430418Skarels #include <sys/param.h>
3530715Sbostic #include <sys/signal.h>
3630418Skarels #include <sys/errno.h>
3730418Skarels #include <sys/file.h>
3830715Sbostic #include <sys/ioctl.h>
3930677Skarels #include <sys/fs.h>
4030715Sbostic #include <strings.h>
4130418Skarels #define DKTYPENAMES
4230418Skarels #include <sys/disklabel.h>
4330418Skarels 
4430418Skarels /*
4530418Skarels  * Disklabel: read and write disklabels.
4630418Skarels  * The label is usually placed on one of the first sectors of the disk.
4730418Skarels  * Many machines (VAX 11/750) also place a bootstrap in the same area,
4830418Skarels  * in which case the label is embedded in the bootstrap.
4930418Skarels  * The bootstrap source must leave space at the proper offset
5030418Skarels  * for the label on such machines.
5130418Skarels  */
5230418Skarels 
5330677Skarels #ifdef vax
5430677Skarels #define RAWPARTITION	'c'
5530677Skarels #else
5630677Skarels #define RAWPARTITION	'a'
5730677Skarels #endif
5830677Skarels 
5930677Skarels #ifndef BBSIZE
6030418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
6130677Skarels #endif
6230418Skarels 
6330418Skarels #ifdef vax
6430418Skarels #define	BOOT				/* also have bootstrap in "boot area" */
6530418Skarels #define	BOOTDIR	"/usr/mdec"		/* source of boot binaries */
6630677Skarels #else
6730677Skarels #ifdef lint
6830677Skarels #define	BOOT
6930418Skarels #endif
7030677Skarels #endif
7130418Skarels 
7230715Sbostic #define	DEFEDITOR	"/usr/ucb/vi"
7330715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
7430715Sbostic 
7530715Sbostic #ifdef BOOT
7630418Skarels char	*xxboot;
7730418Skarels char	*bootxx;
7830715Sbostic #endif
7931617Skarels 
8031617Skarels char	*dkname;
8130418Skarels char	*specname;
8230715Sbostic char	tmpfil[] = "/tmp/EdDk.aXXXXXX";
8330418Skarels 
8430418Skarels extern	int errno;
8530418Skarels char	namebuf[BBSIZE], *np = namebuf;
8631617Skarels struct	disklabel lab;
8731617Skarels struct	disklabel *readlabel(), *makebootarea();
8830418Skarels char	bootarea[BBSIZE];
8934032Skarels char	boot0[MAXPATHLEN];
9034032Skarels char	boot1[MAXPATHLEN];
9130418Skarels 
9234032Skarels enum	{ UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC;
9330418Skarels 
9430677Skarels int	rflag;
9530677Skarels 
9634032Skarels #ifdef DEBUG
9734032Skarels int	debug;
9834032Skarels #endif
9934032Skarels 
10030418Skarels main(argc, argv)
10130418Skarels 	int argc;
10230418Skarels 	char *argv[];
10330418Skarels {
10434032Skarels 	extern int optind;
10530418Skarels 	register struct disklabel *lp;
10634032Skarels 	FILE *t;
10734641Skarels 	int ch, f, error = 0;
10830715Sbostic 	char *name = 0, *type;
10930418Skarels 
11034032Skarels 	while ((ch = getopt(argc, argv, "NRWerw")) != EOF)
11134032Skarels 		switch (ch) {
11234032Skarels 			case 'N':
11334032Skarels 				if (op != UNSPEC)
11434032Skarels 					usage();
11534032Skarels 				op = NOWRITE;
11634032Skarels 				break;
11730715Sbostic 			case 'R':
11834032Skarels 				if (op != UNSPEC)
11934032Skarels 					usage();
12030715Sbostic 				op = RESTORE;
12130715Sbostic 				break;
12234032Skarels 			case 'W':
12334032Skarels 				if (op != UNSPEC)
12434032Skarels 					usage();
12534032Skarels 				op = WRITEABLE;
12634032Skarels 				break;
12730715Sbostic 			case 'e':
12834032Skarels 				if (op != UNSPEC)
12934032Skarels 					usage();
13030715Sbostic 				op = EDIT;
13130715Sbostic 				break;
13230715Sbostic 			case 'r':
13330715Sbostic 				++rflag;
13430715Sbostic 				break;
13530715Sbostic 			case 'w':
13634032Skarels 				if (op != UNSPEC)
13734032Skarels 					usage();
13830715Sbostic 				op = WRITE;
13930715Sbostic 				break;
14034032Skarels #ifdef DEBUG
14134032Skarels 			case 'd':
14234032Skarels 				debug++;
14334032Skarels 				break;
14434032Skarels #endif
14530715Sbostic 			case '?':
14630715Sbostic 			default:
14730715Sbostic 				usage();
14830715Sbostic 		}
14930715Sbostic 	argc -= optind;
15030715Sbostic 	argv += optind;
15134032Skarels 	if (op == UNSPEC)
15234032Skarels 		op = READ;
15330715Sbostic 	if (argc < 1)
15430715Sbostic 		usage();
15530715Sbostic 
15630715Sbostic 	dkname = argv[0];
15730418Skarels 	if (dkname[0] != '/') {
15832439Sbostic 		(void)sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION);
15930418Skarels 		specname = np;
16030418Skarels 		np += strlen(specname) + 1;
16130418Skarels 	} else
16230418Skarels 		specname = dkname;
16330418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
16430418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
16532439Sbostic 		(void)sprintf(specname, "/dev/r%s", dkname);
16630418Skarels 		np = namebuf + strlen(specname) + 1;
16730418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
16830418Skarels 	}
16930418Skarels 	if (f < 0)
17030418Skarels 		Perror(specname);
17130418Skarels 
17230715Sbostic 	switch(op) {
17330715Sbostic 	case EDIT:
17430715Sbostic 		if (argc != 1)
17530715Sbostic 			usage();
17634032Skarels 		lp = readlabel(f);
17734641Skarels 		error = edit(lp, f);
17830715Sbostic 		break;
17934032Skarels 	case NOWRITE: {
18034032Skarels 		int flag = 0;
18134032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
18234032Skarels 			Perror("ioctl DIOCWLABEL");
18334032Skarels 		break;
18434032Skarels 	}
18530418Skarels 	case READ:
18630715Sbostic 		if (argc != 1)
18730715Sbostic 			usage();
18834032Skarels 		lp = readlabel(f);
18930418Skarels 		display(stdout, lp);
19034641Skarels 		error = checklabel(lp);
19130418Skarels 		break;
19230715Sbostic 	case RESTORE:
19330715Sbostic #ifdef BOOT
19434032Skarels 		if (rflag) {
19534032Skarels 			if (argc == 4) {	/* [ priboot secboot ] */
19634032Skarels 				xxboot = argv[2];
19734032Skarels 				bootxx = argv[3];
19834032Skarels 				lab.d_secsize = DEV_BSIZE;	/* XXX */
19934032Skarels 				lab.d_bbsize = BBSIZE;		/* XXX */
20034032Skarels 			}
20134032Skarels 			else if (argc == 3) 	/* [ disktype ] */
20234032Skarels 				makelabel(argv[2], (char *)NULL, &lab);
20334032Skarels 			else {
20434032Skarels 				fprintf(stderr,
20534032Skarels "Must specify either disktype or bootfiles with -r flag of RESTORE option\n");
20634032Skarels 				exit(1);
20734032Skarels 			}
20834032Skarels 		}
20934032Skarels 		else
21031617Skarels #endif
21130715Sbostic 		if (argc != 2)
21230715Sbostic 			usage();
21331617Skarels 		lp = makebootarea(bootarea, &lab);
21430715Sbostic 		if (!(t = fopen(argv[1],"r")))
21530715Sbostic 			Perror(argv[1]);
21630715Sbostic 		if (getasciilabel(t, lp))
21734641Skarels 			error = writelabel(f, bootarea, lp);
21830418Skarels 		break;
21930418Skarels 	case WRITE:
22030715Sbostic 		type = argv[1];
22130715Sbostic #ifdef BOOT
22230715Sbostic 		if (argc > 5 || argc < 2)
22330715Sbostic 			usage();
22430715Sbostic 		if (argc > 3) {
22530715Sbostic 			bootxx = argv[--argc];
22630715Sbostic 			xxboot = argv[--argc];
22730715Sbostic 		}
22830715Sbostic #else
22930715Sbostic 		if (argc > 3 || argc < 2)
23030715Sbostic 			usage();
23130715Sbostic #endif
23230715Sbostic 		if (argc > 2)
23330715Sbostic 			name = argv[--argc];
23430418Skarels 		makelabel(type, name, &lab);
23531617Skarels 		lp = makebootarea(bootarea, &lab);
23630418Skarels 		*lp = lab;
23730715Sbostic 		if (checklabel(lp) == 0)
23834641Skarels 			error = writelabel(f, bootarea, lp);
23930418Skarels 		break;
24034032Skarels 	case WRITEABLE: {
24134032Skarels 		int flag = 1;
24234032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
24334032Skarels 			Perror("ioctl DIOCWLABEL");
24434032Skarels 		break;
24530418Skarels 	}
24634032Skarels 	}
24734641Skarels 	exit(error);
24830418Skarels }
24930418Skarels 
25034032Skarels /*
25134032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
25234032Skarels  * effect, set the names of the primary and secondary boot files
25334032Skarels  * if specified.
25434032Skarels  */
25530418Skarels makelabel(type, name, lp)
25630418Skarels 	char *type, *name;
25730418Skarels 	register struct disklabel *lp;
25830418Skarels {
25930418Skarels 	register struct disklabel *dp;
26034032Skarels 	char *strcpy();
26130418Skarels 
26230418Skarels 	dp = getdiskbyname(type);
26330418Skarels 	if (dp == NULL) {
26430418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
26530418Skarels 		exit(1);
26630418Skarels 	}
26730418Skarels 	*lp = *dp;
26834032Skarels #ifdef BOOT
26934032Skarels 	/*
27034032Skarels 	 * Check if disktab specifies the bootstraps (b0 or b1).
27134032Skarels 	 */
27234032Skarels 	if (!xxboot && lp->d_boot0) {
27334032Skarels 		if (*lp->d_boot0 != '/')
27434032Skarels 			(void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0);
27534032Skarels 		else
27634032Skarels 			(void)strcpy(boot0, lp->d_boot0);
27734032Skarels 		xxboot = boot0;
27834032Skarels 	}
27934032Skarels 	if (!bootxx && lp->d_boot1) {
28034032Skarels 		if (*lp->d_boot1 != '/')
28134032Skarels 			(void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1);
28234032Skarels 		else
28334032Skarels 			(void)strcpy(boot1, lp->d_boot1);
28434032Skarels 		bootxx = boot1;
28534032Skarels 	}
28634032Skarels 	/*
28734032Skarels 	 * If bootstraps not specified anywhere, makebootarea()
28834032Skarels 	 * will choose ones based on the name of the disk special
28934032Skarels 	 * file. E.g. /dev/ra0 -> raboot, bootra
29034032Skarels 	 */
29134032Skarels #endif /*BOOT*/
29234032Skarels 	/* d_packname is union d_boot[01], so zero */
29334032Skarels 	bzero(lp->d_packname, sizeof(lp->d_packname));
29430418Skarels 	if (name)
29534032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
29630418Skarels }
29730418Skarels 
29830418Skarels writelabel(f, boot, lp)
29930418Skarels 	int f;
30030418Skarels 	char *boot;
30130418Skarels 	register struct disklabel *lp;
30230418Skarels {
30330715Sbostic 	register int i;
30434032Skarels 	int flag;
30534032Skarels 	off_t lseek();
30630418Skarels 
30730418Skarels 	lp->d_magic = DISKMAGIC;
30830418Skarels 	lp->d_magic2 = DISKMAGIC;
30930418Skarels 	lp->d_checksum = 0;
31030418Skarels 	lp->d_checksum = dkcksum(lp);
31130677Skarels 	if (rflag) {
31234032Skarels 		/*
31334032Skarels 		 * First set the kernel disk label,
31434032Skarels 		 * then write a label to the raw disk.
31534032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
31634032Skarels 		 * keep going; otherwise, the kernel consistency checks
31734032Skarels 		 * may prevent us from changing the current (in-core)
31834032Skarels 		 * label.
31934032Skarels 		 */
32034032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
32134641Skarels 		    errno != ENODEV && errno != ENOTTY) {
32234641Skarels 			l_perror("ioctl DIOCSDINFO");
32334641Skarels 			return (1);
32434641Skarels 		}
32531617Skarels 		(void)lseek(f, (off_t)0, L_SET);
32634032Skarels 		/*
32734032Skarels 		 * write enable label sector before write (if necessary),
32834032Skarels 		 * disable after writing.
32934032Skarels 		 */
33034032Skarels 		flag = 1;
33134032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
33234032Skarels 			perror("ioctl DIOCWLABEL");
33334641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
33434641Skarels 			perror("write");
33534641Skarels 			return (1);
33634641Skarels 		}
33734032Skarels 		flag = 0;
33834032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
33934641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
34034641Skarels 		l_perror("ioctl DIOCWDINFO");
34134641Skarels 		return (1);
34234641Skarels 	}
34334032Skarels #ifdef vax
34430677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
34530677Skarels 		daddr_t alt;
34630677Skarels 
34730677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
34830677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
34930715Sbostic 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET);
35030677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
35130677Skarels 				int oerrno = errno;
35230677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
35330677Skarels 				errno = oerrno;
35430677Skarels 				perror("write");
35530677Skarels 			}
35630418Skarels 		}
35730418Skarels 	}
35830419Skarels #endif
35934641Skarels 	return (0);
36030418Skarels }
36130418Skarels 
36234641Skarels l_perror(s)
36334641Skarels 	char *s;
36434641Skarels {
36534641Skarels 	int saverrno = errno;
36634641Skarels 
36734641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
36834641Skarels 
36934641Skarels 	switch (saverrno) {
37034641Skarels 
37134641Skarels 	case ESRCH:
37234641Skarels 		fprintf(stderr, "No disk label on disk;\n");
37334641Skarels 		fprintf(stderr,
37434641Skarels 		    "use \"disklabel -r\" to install initial label\n");
37534641Skarels 		break;
37634641Skarels 
37734641Skarels 	case EINVAL:
37834641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
37934641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
38034641Skarels 		break;
38134641Skarels 
38234641Skarels 	case EBUSY:
38334641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
38434641Skarels 		break;
38534641Skarels 
38634641Skarels 	case EXDEV:
38734641Skarels 		fprintf(stderr,
38834641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
38934641Skarels 		break;
39034641Skarels 
39134641Skarels 	default:
39234641Skarels 		errno = saverrno;
39334641Skarels 		perror((char *)NULL);
39434641Skarels 		break;
39534641Skarels 	}
39634641Skarels }
39734641Skarels 
39830418Skarels /*
39931617Skarels  * Fetch disklabel for disk.
40031617Skarels  * Use ioctl to get label unless -r flag is given.
40130418Skarels  */
40230418Skarels struct disklabel *
40334032Skarels readlabel(f)
40434032Skarels 	int f;
40530418Skarels {
40630418Skarels 	register struct disklabel *lp;
40730418Skarels 
40834032Skarels 	if (rflag) {
40931617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
41031401Skarels 			Perror(specname);
41131617Skarels 		for (lp = (struct disklabel *)bootarea;
41231617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
41330677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
41430677Skarels 			if (lp->d_magic == DISKMAGIC &&
41530677Skarels 			    lp->d_magic2 == DISKMAGIC)
41630677Skarels 				break;
41731617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
41830677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
41930677Skarels 		    dkcksum(lp) != 0) {
42030677Skarels 			fprintf(stderr,
42130418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
42234032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
42334032Skarels 			exit (1);
42430677Skarels 		}
42534032Skarels 	} else {
42634032Skarels 		lp = &lab;
42734032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
42834032Skarels 			Perror("ioctl DIOCGDINFO");
42930418Skarels 	}
43030418Skarels 	return (lp);
43130418Skarels }
43230418Skarels 
43330418Skarels struct disklabel *
43431617Skarels makebootarea(boot, dp)
43530418Skarels 	char *boot;
43630418Skarels 	register struct disklabel *dp;
43730418Skarels {
43830418Skarels 	struct disklabel *lp;
43930418Skarels 	register char *p;
44030418Skarels 	int b;
44130418Skarels #ifdef BOOT
44230715Sbostic 	char	*dkbasename;
44334032Skarels #endif /*BOOT*/
44430715Sbostic 
44534032Skarels 	lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) +
44634032Skarels 	    LABELOFFSET);
44734032Skarels #ifdef BOOT
44834032Skarels 	if (!rflag)
44934032Skarels 		return (lp);
45034032Skarels 
45134032Skarels 	if (xxboot == NULL || bootxx == NULL) {
45230418Skarels 		dkbasename = np;
45330418Skarels 		if ((p = rindex(dkname, '/')) == NULL)
45430418Skarels 			p = dkname;
45530418Skarels 		else
45630418Skarels 			p++;
45730418Skarels 		while (*p && !isdigit(*p))
45830418Skarels 			*np++ = *p++;
45930418Skarels 		*np++ = '\0';
46030418Skarels 
46134032Skarels 		if (xxboot == NULL) {
46234032Skarels 			(void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename);
46334032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
46434032Skarels 				dkbasename++;
46534032Skarels 			xxboot = np;
46634032Skarels 			(void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename);
46734032Skarels 			np += strlen(xxboot) + 1;
46834032Skarels 		}
46934032Skarels 		if (bootxx == NULL) {
47034032Skarels 			(void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename);
47134032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
47234032Skarels 				dkbasename++;
47334032Skarels 			bootxx = np;
47434032Skarels 			(void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename);
47534032Skarels 			np += strlen(bootxx) + 1;
47634032Skarels 		}
47730418Skarels 	}
47834032Skarels #ifdef DEBUG
47934032Skarels 	if (debug)
48034032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
48134032Skarels 			xxboot, bootxx);
48234032Skarels #endif
48330418Skarels 
48430418Skarels 	b = open(xxboot, O_RDONLY);
48530418Skarels 	if (b < 0)
48630418Skarels 		Perror(xxboot);
48730715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
48830418Skarels 		Perror(xxboot);
48930418Skarels 	close(b);
49030418Skarels 	b = open(bootxx, O_RDONLY);
49130418Skarels 	if (b < 0)
49230418Skarels 		Perror(bootxx);
49330715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
49430418Skarels 		Perror(bootxx);
49530715Sbostic 	(void)close(b);
49634032Skarels #endif /*BOOT*/
49730418Skarels 
49830418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
49930418Skarels 		if (*p) {
50030418Skarels 			fprintf(stderr,
50130418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
50230418Skarels 			exit(2);
50330418Skarels 		}
50430418Skarels 	return (lp);
50530418Skarels }
50630418Skarels 
50730418Skarels display(f, lp)
50830418Skarels 	FILE *f;
50930418Skarels 	register struct disklabel *lp;
51030418Skarels {
51130715Sbostic 	register int i, j;
51230418Skarels 	register struct partition *pp;
51330418Skarels 
51430418Skarels 	fprintf(f, "# %s:\n", specname);
51530418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
51630418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
51730418Skarels 	else
51830418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
51930418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
52034032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
52131401Skarels 	fprintf(f, "flags:");
52230418Skarels 	if (lp->d_flags & D_REMOVABLE)
52331401Skarels 		fprintf(f, " removeable");
52430418Skarels 	if (lp->d_flags & D_ECC)
52531401Skarels 		fprintf(f, " ecc");
52630418Skarels 	if (lp->d_flags & D_BADSECT)
52731401Skarels 		fprintf(f, " badsect");
52830418Skarels 	fprintf(f, "\n");
52930418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
53030418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
53130418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
53231386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
53330418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
53430715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
53530418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
53630418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
53730418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
53830418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
53930418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
54030418Skarels 	fprintf(f, "drivedata: ");
54130418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
54230418Skarels 		if (lp->d_drivedata[i])
54330418Skarels 			break;
54430418Skarels 	if (i < 0)
54530418Skarels 		i = 0;
54630418Skarels 	for (j = 0; j <= i; j++)
54730418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
54830418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
54930863Skarels 	fprintf(f,
55030863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
55130418Skarels 	pp = lp->d_partitions;
55230418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
55330418Skarels 		if (pp->p_size) {
55430863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
55530863Skarels 			   pp->p_size, pp->p_offset);
55630418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
55730418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
55830418Skarels 			else
55930418Skarels 				fprintf(f, "%8d", pp->p_fstype);
56030863Skarels 			switch (pp->p_fstype) {
56130863Skarels 
56230863Skarels 			case FS_UNUSED:				/* XXX */
56330863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
56430863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
56530863Skarels 				break;
56630863Skarels 
56730863Skarels 			case FS_BSDFFS:
56830863Skarels 				fprintf(f, "    %5d %5d %5d ",
56930863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
57030863Skarels 				    pp->p_cpg);
57130863Skarels 				break;
57230863Skarels 
57330863Skarels 			default:
57430863Skarels 				fprintf(f, "%20.20s", "");
57530863Skarels 				break;
57630863Skarels 			}
57730418Skarels 			fprintf(f, "\t# (Cyl. %4d",
57830418Skarels 			    pp->p_offset / lp->d_secpercyl);
57930418Skarels 			if (pp->p_offset % lp->d_secpercyl)
58030418Skarels 			    putc('*', f);
58130418Skarels 			else
58230418Skarels 			    putc(' ', f);
58330418Skarels 			fprintf(f, "- %d",
58430418Skarels 			    (pp->p_offset +
58530418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
58630418Skarels 			    lp->d_secpercyl - 1);
58730418Skarels 			if (pp->p_size % lp->d_secpercyl)
58830418Skarels 			    putc('*', f);
58930863Skarels 			fprintf(f, ")\n");
59030418Skarels 		}
59130418Skarels 	}
59232121Stef 	fflush(f);
59330418Skarels }
59430418Skarels 
59534641Skarels edit(lp, f)
59630715Sbostic 	struct disklabel *lp;
59734641Skarels 	int f;
59830418Skarels {
59930715Sbostic 	register int c;
60030715Sbostic 	struct disklabel label;
60130715Sbostic 	FILE *fd;
60230715Sbostic 	char *mktemp();
60330715Sbostic 
60430715Sbostic 	(void) mktemp(tmpfil);
60530715Sbostic 	fd = fopen(tmpfil, "w");
60630715Sbostic 	if (fd == NULL) {
60730715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
60834641Skarels 		return (1);
60930715Sbostic 	}
61030715Sbostic 	(void)fchmod(fd, 0600);
61130715Sbostic 	display(fd, lp);
61230715Sbostic 	fclose(fd);
61330715Sbostic 	for (;;) {
61430715Sbostic 		if (!editit())
61530715Sbostic 			break;
61630715Sbostic 		fd = fopen(tmpfil, "r");
61730715Sbostic 		if (fd == NULL) {
61834032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
61934032Skarels 				tmpfil);
62030715Sbostic 			break;
62130715Sbostic 		}
62230863Skarels 		bzero((char *)&label, sizeof(label));
62330715Sbostic 		if (getasciilabel(fd, &label)) {
62430715Sbostic 			*lp = label;
62534641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
62634641Skarels 				(void) unlink(tmpfil);
62734641Skarels 				return (0);
62834641Skarels 			}
62930715Sbostic 		}
63030715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
63130715Sbostic 		c = getchar();
63230715Sbostic 		if (c != EOF && c != (int)'\n')
63330715Sbostic 			while (getchar() != (int)'\n')
63430715Sbostic 				;
63530715Sbostic 		if  (c == (int)'n')
63630715Sbostic 			break;
63730715Sbostic 	}
63830715Sbostic 	(void) unlink(tmpfil);
63934641Skarels 	return (1);
64030418Skarels }
64130418Skarels 
64230715Sbostic editit()
64330715Sbostic {
64430715Sbostic 	register int pid, xpid;
64530715Sbostic 	int stat, omask;
64630715Sbostic 	extern char *getenv();
64730418Skarels 
64830715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
64930715Sbostic 	while ((pid = fork()) < 0) {
65030715Sbostic 		extern int errno;
65130715Sbostic 
65230715Sbostic 		if (errno == EPROCLIM) {
65330715Sbostic 			fprintf(stderr, "You have too many processes\n");
65430715Sbostic 			return(0);
65530715Sbostic 		}
65630715Sbostic 		if (errno != EAGAIN) {
65730715Sbostic 			perror("fork");
65830715Sbostic 			return(0);
65930715Sbostic 		}
66030715Sbostic 		sleep(1);
66130715Sbostic 	}
66230715Sbostic 	if (pid == 0) {
66330715Sbostic 		register char *ed;
66430715Sbostic 
66530715Sbostic 		sigsetmask(omask);
66630715Sbostic 		setgid(getgid());
66730715Sbostic 		setuid(getuid());
66830715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
66930715Sbostic 			ed = DEFEDITOR;
67030715Sbostic 		execlp(ed, ed, tmpfil, 0);
67130715Sbostic 		perror(ed);
67230715Sbostic 		exit(1);
67330715Sbostic 	}
67430715Sbostic 	while ((xpid = wait(&stat)) >= 0)
67530715Sbostic 		if (xpid == pid)
67630715Sbostic 			break;
67730715Sbostic 	sigsetmask(omask);
67830715Sbostic 	return(!stat);
67930715Sbostic }
68030715Sbostic 
68130715Sbostic char *
68230715Sbostic skip(cp)
68330715Sbostic 	register char *cp;
68430715Sbostic {
68530715Sbostic 
68630715Sbostic 	while (*cp != '\0' && isspace(*cp))
68730715Sbostic 		cp++;
68830715Sbostic 	if (*cp == '\0' || *cp == '#')
68930715Sbostic 		return ((char *)NULL);
69030715Sbostic 	return (cp);
69130715Sbostic }
69230715Sbostic 
69330715Sbostic char *
69430715Sbostic word(cp)
69530715Sbostic 	register char *cp;
69630715Sbostic {
69730715Sbostic 	register char c;
69830715Sbostic 
69931401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
70031401Skarels 		cp++;
70130715Sbostic 	if ((c = *cp) != '\0') {
70230715Sbostic 		*cp++ = '\0';
70330715Sbostic 		if (c != '#')
70430715Sbostic 			return (skip(cp));
70530715Sbostic 	}
70630715Sbostic 	return ((char *)NULL);
70730715Sbostic }
70830715Sbostic 
70930418Skarels /*
71030418Skarels  * Read an ascii label in from fd f,
71130418Skarels  * in the same format as that put out by display(),
71230418Skarels  * and fill in lp.
71330418Skarels  */
71430418Skarels getasciilabel(f, lp)
71530715Sbostic 	FILE	*f;
71630418Skarels 	register struct disklabel *lp;
71730418Skarels {
71830715Sbostic 	register char **cpp, *cp;
71930863Skarels 	register struct partition *pp;
72030715Sbostic 	char *tp, *s, line[BUFSIZ];
72130715Sbostic 	int v, lineno = 0, errors = 0;
72230715Sbostic 
72330715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
72430715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
72530715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
72630715Sbostic 		lineno++;
72730715Sbostic 		if (cp = index(line,'\n'))
72830715Sbostic 			*cp = '\0';
72930715Sbostic 		cp = skip(line);
73030715Sbostic 		if (cp == NULL)
73130715Sbostic 			continue;
73230715Sbostic 		tp = index(cp, ':');
73330715Sbostic 		if (tp == NULL) {
73430715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
73530715Sbostic 			errors++;
73630715Sbostic 			continue;
73730715Sbostic 		}
73830715Sbostic 		*tp++ = '\0', tp = skip(tp);
73930715Sbostic 		if (streq(cp, "type")) {
74030715Sbostic 			if (tp == NULL)
74130715Sbostic 				tp = "unknown";
74230715Sbostic 			cpp = dktypenames;
74330715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
74430715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
74530715Sbostic 					lp->d_type = cpp - dktypenames;
74630715Sbostic 					goto next;
74730715Sbostic 				}
74830715Sbostic 			v = atoi(tp);
74930715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
75030715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
75130715Sbostic 				    "Warning, unknown disk type", v);
75230715Sbostic 			lp->d_type = v;
75330715Sbostic 			continue;
75430715Sbostic 		}
75530715Sbostic 		if (streq(cp, "flags")) {
75634032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
75734032Skarels 				tp = word(cp);
75830715Sbostic 				if (streq(cp, "removeable"))
75930715Sbostic 					v |= D_REMOVABLE;
76030715Sbostic 				else if (streq(cp, "ecc"))
76130715Sbostic 					v |= D_ECC;
76230715Sbostic 				else if (streq(cp, "badsect"))
76330715Sbostic 					v |= D_BADSECT;
76430715Sbostic 				else {
76530715Sbostic 					fprintf(stderr,
76630715Sbostic 					    "line %d: %s: bad flag\n",
76730715Sbostic 					    lineno, cp);
76830715Sbostic 					errors++;
76930715Sbostic 				}
77030715Sbostic 			}
77130715Sbostic 			lp->d_flags = v;
77230715Sbostic 			continue;
77330715Sbostic 		}
77430715Sbostic 		if (streq(cp, "drivedata")) {
77530715Sbostic 			register int i;
77630715Sbostic 
77731386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
77830715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
77931386Skarels 				tp = word(cp);
78030715Sbostic 			}
78130715Sbostic 			continue;
78230715Sbostic 		}
78330715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
78430863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
78530715Sbostic 				fprintf(stderr,
78630715Sbostic 				    "line %d: bad # of partitions\n", lineno);
78730863Skarels 				lp->d_npartitions = MAXPARTITIONS;
78830863Skarels 				errors++;
78930863Skarels 			} else
79030715Sbostic 				lp->d_npartitions = v;
79130715Sbostic 			continue;
79230715Sbostic 		}
79330715Sbostic 		if (tp == NULL)
79430715Sbostic 			tp = "";
79530715Sbostic 		if (streq(cp, "disk")) {
79630715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
79730715Sbostic 			continue;
79830715Sbostic 		}
79930715Sbostic 		if (streq(cp, "label")) {
80034032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
80130715Sbostic 			continue;
80230715Sbostic 		}
80330715Sbostic 		if (streq(cp, "bytes/sector")) {
80430715Sbostic 			v = atoi(tp);
80530715Sbostic 			if (v <= 0 || (v % 512) != 0) {
80630715Sbostic 				fprintf(stderr,
80730715Sbostic 				    "line %d: %s: bad sector size\n",
80830715Sbostic 				    lineno, tp);
80930715Sbostic 				errors++;
81030715Sbostic 			} else
81130715Sbostic 				lp->d_secsize = v;
81230715Sbostic 			continue;
81330715Sbostic 		}
81430715Sbostic 		if (streq(cp, "sectors/track")) {
81530715Sbostic 			v = atoi(tp);
81630715Sbostic 			if (v <= 0) {
81730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
81830715Sbostic 				    lineno, tp, cp);
81930715Sbostic 				errors++;
82030715Sbostic 			} else
82130715Sbostic 				lp->d_nsectors = v;
82230715Sbostic 			continue;
82330715Sbostic 		}
82431386Skarels 		if (streq(cp, "sectors/cylinder")) {
82531386Skarels 			v = atoi(tp);
82631386Skarels 			if (v <= 0) {
82731386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
82831386Skarels 				    lineno, tp, cp);
82931386Skarels 				errors++;
83031386Skarels 			} else
83131386Skarels 				lp->d_secpercyl = v;
83231386Skarels 			continue;
83331386Skarels 		}
83430715Sbostic 		if (streq(cp, "tracks/cylinder")) {
83530715Sbostic 			v = atoi(tp);
83630715Sbostic 			if (v <= 0) {
83730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
83830715Sbostic 				    lineno, tp, cp);
83930715Sbostic 				errors++;
84030715Sbostic 			} else
84130715Sbostic 				lp->d_ntracks = v;
84230715Sbostic 			continue;
84330715Sbostic 		}
84430715Sbostic 		if (streq(cp, "cylinders")) {
84530715Sbostic 			v = atoi(tp);
84630715Sbostic 			if (v <= 0) {
84730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
84830715Sbostic 				    lineno, tp, cp);
84930715Sbostic 				errors++;
85030715Sbostic 			} else
85130715Sbostic 				lp->d_ncylinders = v;
85230715Sbostic 			continue;
85330715Sbostic 		}
85430715Sbostic 		if (streq(cp, "rpm")) {
85530715Sbostic 			v = atoi(tp);
85630715Sbostic 			if (v <= 0) {
85730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
85830715Sbostic 				    lineno, tp, cp);
85930715Sbostic 				errors++;
86030715Sbostic 			} else
86130715Sbostic 				lp->d_rpm = v;
86230715Sbostic 			continue;
86330715Sbostic 		}
86430715Sbostic 		if (streq(cp, "interleave")) {
86530715Sbostic 			v = atoi(tp);
86630715Sbostic 			if (v <= 0) {
86730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
86830715Sbostic 				    lineno, tp, cp);
86930715Sbostic 				errors++;
87030715Sbostic 			} else
87130715Sbostic 				lp->d_interleave = v;
87230715Sbostic 			continue;
87330715Sbostic 		}
87430715Sbostic 		if (streq(cp, "trackskew")) {
87530715Sbostic 			v = atoi(tp);
87630715Sbostic 			if (v < 0) {
87730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
87830715Sbostic 				    lineno, tp, cp);
87930715Sbostic 				errors++;
88030715Sbostic 			} else
88130715Sbostic 				lp->d_trackskew = v;
88230715Sbostic 			continue;
88330715Sbostic 		}
88430715Sbostic 		if (streq(cp, "cylinderskew")) {
88530715Sbostic 			v = atoi(tp);
88630715Sbostic 			if (v < 0) {
88730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
88830715Sbostic 				    lineno, tp, cp);
88930715Sbostic 				errors++;
89030715Sbostic 			} else
89130715Sbostic 				lp->d_cylskew = v;
89230715Sbostic 			continue;
89330715Sbostic 		}
89430715Sbostic 		if (streq(cp, "headswitch")) {
89530715Sbostic 			v = atoi(tp);
89630715Sbostic 			if (v < 0) {
89730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
89830715Sbostic 				    lineno, tp, cp);
89930715Sbostic 				errors++;
90030715Sbostic 			} else
90130715Sbostic 				lp->d_headswitch = v;
90230715Sbostic 			continue;
90330715Sbostic 		}
90430715Sbostic 		if (streq(cp, "track-to-track seek")) {
90530715Sbostic 			v = atoi(tp);
90630715Sbostic 			if (v < 0) {
90730715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
90830715Sbostic 				    lineno, tp, cp);
90930715Sbostic 				errors++;
91030715Sbostic 			} else
91130715Sbostic 				lp->d_trkseek = v;
91230715Sbostic 			continue;
91330715Sbostic 		}
91430715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
91530863Skarels 			unsigned part = *cp - 'a';
91630715Sbostic 
91730863Skarels 			if (part > lp->d_npartitions) {
91830715Sbostic 				fprintf(stderr,
91930715Sbostic 				    "line %d: bad partition name\n", lineno);
92030715Sbostic 				errors++;
92130715Sbostic 				continue;
92230715Sbostic 			}
92330863Skarels 			pp = &lp->d_partitions[part];
92430863Skarels #define NXTNUM(n) { \
92530863Skarels 	cp = tp, tp = word(cp); \
92630863Skarels 	if (tp == NULL) \
92730863Skarels 		tp = cp; \
92830863Skarels 	(n) = atoi(cp); \
92930863Skarels      }
93030863Skarels 
93130863Skarels 			NXTNUM(v);
93230715Sbostic 			if (v < 0) {
93330715Sbostic 				fprintf(stderr,
93430715Sbostic 				    "line %d: %s: bad partition size\n",
93530715Sbostic 				    lineno, cp);
93630715Sbostic 				errors++;
93730715Sbostic 			} else
93830863Skarels 				pp->p_size = v;
93930863Skarels 			NXTNUM(v);
94030715Sbostic 			if (v < 0) {
94130715Sbostic 				fprintf(stderr,
94230715Sbostic 				    "line %d: %s: bad partition offset\n",
94330715Sbostic 				    lineno, cp);
94430715Sbostic 				errors++;
94530715Sbostic 			} else
94630863Skarels 				pp->p_offset = v;
94730715Sbostic 			cp = tp, tp = word(cp);
94830715Sbostic 			cpp = fstypenames;
94930715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
95030715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
95130863Skarels 					pp->p_fstype = cpp - fstypenames;
95230863Skarels 					goto gottype;
95330715Sbostic 				}
95434032Skarels 			if (isdigit(*cp))
95534032Skarels 				v = atoi(cp);
95634032Skarels 			else
95734032Skarels 				v = FSMAXTYPES;
95834032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
95930715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
96030715Sbostic 				    "Warning, unknown filesystem type", cp);
96134032Skarels 				v = FS_UNUSED;
96234032Skarels 			}
96330863Skarels 			pp->p_fstype = v;
96430863Skarels 	gottype:
96530863Skarels 
96630863Skarels 			switch (pp->p_fstype) {
96730863Skarels 
96830863Skarels 			case FS_UNUSED:				/* XXX */
96930863Skarels 				NXTNUM(pp->p_fsize);
97030863Skarels 				if (pp->p_fsize == 0)
97130863Skarels 					break;
97230863Skarels 				NXTNUM(v);
97330863Skarels 				pp->p_frag = v / pp->p_fsize;
97430863Skarels 				break;
97530863Skarels 
97630863Skarels 			case FS_BSDFFS:
97730863Skarels 				NXTNUM(pp->p_fsize);
97830863Skarels 				if (pp->p_fsize == 0)
97930863Skarels 					break;
98030863Skarels 				NXTNUM(v);
98130863Skarels 				pp->p_frag = v / pp->p_fsize;
98230863Skarels 				NXTNUM(pp->p_cpg);
98330863Skarels 				break;
98430863Skarels 
98530863Skarels 			default:
98630863Skarels 				break;
98730863Skarels 			}
98830715Sbostic 			continue;
98930715Sbostic 		}
99030715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
99130715Sbostic 		    lineno, cp);
99230715Sbostic 		errors++;
99330715Sbostic 	next:
99430715Sbostic 		;
99530715Sbostic 	}
99630715Sbostic 	errors += checklabel(lp);
99730715Sbostic 	return (errors == 0);
99830418Skarels }
99930418Skarels 
100030715Sbostic /*
100130715Sbostic  * Check disklabel for errors and fill in
100230715Sbostic  * derived fields according to supplied values.
100330715Sbostic  */
100430715Sbostic checklabel(lp)
100530715Sbostic 	register struct disklabel *lp;
100630418Skarels {
100730715Sbostic 	register struct partition *pp;
100830715Sbostic 	int i, errors = 0;
100930715Sbostic 	char part;
101030418Skarels 
101130715Sbostic 	if (lp->d_secsize == 0) {
101230715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
101330715Sbostic 		return (1);
101430715Sbostic 	}
101530715Sbostic 	if (lp->d_nsectors == 0) {
101630715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
101730715Sbostic 		return (1);
101830715Sbostic 	}
101930715Sbostic 	if (lp->d_ntracks == 0) {
102030715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
102130715Sbostic 		return (1);
102230715Sbostic 	}
102330715Sbostic 	if  (lp->d_ncylinders == 0) {
102430715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
102530715Sbostic 		errors++;
102630715Sbostic 	}
102730715Sbostic 	if (lp->d_rpm == 0)
102830715Sbostic 		Warning("revolutions/minute %d\n", lp->d_rpm);
102930715Sbostic 	if (lp->d_secpercyl == 0)
103030715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
103130715Sbostic 	if (lp->d_secperunit == 0)
103230715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
103330715Sbostic 	if (lp->d_bbsize == 0) {
103430715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
103530715Sbostic 		errors++;
103630715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
103730715Sbostic 		Warning("boot block size %% sector-size != 0\n");
103830715Sbostic 	if (lp->d_sbsize == 0) {
103930715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
104030715Sbostic 		errors++;
104130715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
104230715Sbostic 		Warning("super block size %% sector-size != 0\n");
104330715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
104430715Sbostic 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n",
104530715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
104630715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
104730715Sbostic 		part = 'a' + i;
104830715Sbostic 		pp = &lp->d_partitions[i];
104930715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
105030715Sbostic 			Warning("partition %c: size 0, but offset %d\n",
105130715Sbostic 			    part, pp->p_offset);
105230715Sbostic #ifdef notdef
105330715Sbostic 		if (pp->p_size % lp->d_secpercyl)
105430715Sbostic 			Warning("partition %c: size %% cylinder-size != 0\n",
105530715Sbostic 			    part);
105630715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
105730715Sbostic 			Warning("partition %c: offset %% cylinder-size != 0\n",
105830715Sbostic 			    part);
105930715Sbostic #endif
106030715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
106130715Sbostic 			fprintf(stderr,
106230715Sbostic 			    "partition %c: offset past end of unit\n", part);
106330715Sbostic 			errors++;
106430715Sbostic 		}
106530715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
106630715Sbostic 			fprintf(stderr,
106730715Sbostic 			    "partition %c: partition extends past end of unit\n",
106830715Sbostic 			    part);
106930715Sbostic 			errors++;
107030715Sbostic 		}
107130715Sbostic 	}
107230715Sbostic 	for (; i < MAXPARTITIONS; i++) {
107330715Sbostic 		part = 'a' + i;
107430715Sbostic 		pp = &lp->d_partitions[i];
107530715Sbostic 		if (pp->p_size || pp->p_offset)
107630715Sbostic 			Warning("unused partition %c: size %d offset %d\n",
107734032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
107830715Sbostic 	}
107930715Sbostic 	return (errors);
108030715Sbostic }
108130715Sbostic 
108230715Sbostic /*VARARGS1*/
108330715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
108430715Sbostic 	char *fmt;
108530715Sbostic {
108630715Sbostic 
108730715Sbostic 	fprintf(stderr, "Warning, ");
108830715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
108930715Sbostic 	fprintf(stderr, "\n");
109030715Sbostic }
109130715Sbostic 
109230715Sbostic Perror(str)
109330715Sbostic 	char *str;
109430715Sbostic {
109530715Sbostic 	fputs("disklabel: ", stderr); perror(str);
109630418Skarels 	exit(4);
109730418Skarels }
109830715Sbostic 
109930715Sbostic usage()
110030715Sbostic {
110130715Sbostic #ifdef BOOT
110234032Skarels 	fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n",
110330715Sbostic "usage: disklabel [-r] disk", "(to read label)",
110430715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)",
110530715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
110634032Skarels "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)",
110734032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
110830715Sbostic #else
110934032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
111030715Sbostic "usage: disklabel [-r] disk", "(to read label)",
111130715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
111230715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
111334032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
111434032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
111530715Sbostic #endif
111630715Sbostic 	exit(1);
111730715Sbostic }
1118