xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 68990)
130715Sbostic /*
261480Sbostic  * Copyright (c) 1987, 1993
361480Sbostic  *	The Regents of the University of California.  All rights reserved.
435983Sbostic  *
535983Sbostic  * This code is derived from software contributed to Berkeley by
635983Sbostic  * Symmetric Computer Systems.
735983Sbostic  *
842698Sbostic  * %sccs.include.redist.c%
930715Sbostic  */
1030715Sbostic 
1130418Skarels #ifndef lint
1261480Sbostic static char copyright[] =
1361480Sbostic "@(#) Copyright (c) 1987, 1993\n\
1461480Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1535983Sbostic #endif /* not lint */
1635983Sbostic 
1735983Sbostic #ifndef lint
18*68990Sbostic static char sccsid[] = "@(#)disklabel.c	8.3 (Berkeley) 04/28/95";
1930418Skarels /* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
2035983Sbostic #endif /* not lint */
2130418Skarels 
2230418Skarels #include <sys/param.h>
2330715Sbostic #include <sys/signal.h>
2430418Skarels #include <sys/errno.h>
2530418Skarels #include <sys/file.h>
2630715Sbostic #include <sys/ioctl.h>
2758602Smckusick #include <sys/stat.h>
2830418Skarels #define DKTYPENAMES
2930418Skarels #include <sys/disklabel.h>
3051615Sbostic #include <ufs/ffs/fs.h>
3157996Sralph #include <unistd.h>
3251615Sbostic #include <string.h>
3337261Sbostic #include <stdio.h>
3437261Sbostic #include <ctype.h>
3537261Sbostic #include "pathnames.h"
3630418Skarels 
3730418Skarels /*
3830418Skarels  * Disklabel: read and write disklabels.
3930418Skarels  * The label is usually placed on one of the first sectors of the disk.
4058602Smckusick  * Many machines also place a bootstrap in the same area,
4130418Skarels  * in which case the label is embedded in the bootstrap.
4230418Skarels  * The bootstrap source must leave space at the proper offset
4330418Skarels  * for the label on such machines.
4430418Skarels  */
4530418Skarels 
4658602Smckusick #ifdef tahoe
4758602Smckusick #define RAWPARTITION	'a'
4858602Smckusick #else
4930677Skarels #define RAWPARTITION	'c'
5030677Skarels #endif
5130677Skarels 
5230677Skarels #ifndef BBSIZE
5330418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
5430677Skarels #endif
5530418Skarels 
5658602Smckusick #ifdef tahoe
5758602Smckusick #define	NUMBOOT	0
5830677Skarels #else
5958602Smckusick #if defined(hp300) || defined(hp800)
6058602Smckusick #define	NUMBOOT	1
6158602Smckusick #else
6258602Smckusick #define	NUMBOOT	2
6330418Skarels #endif
6430677Skarels #endif
6530418Skarels 
6638505Sbostic #define	DEFEDITOR	_PATH_VI
6730715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
6830715Sbostic 
6931617Skarels char	*dkname;
7030418Skarels char	*specname;
7137945Sbostic char	tmpfil[] = _PATH_TMP;
7230418Skarels 
7330418Skarels extern	int errno;
7430418Skarels char	namebuf[BBSIZE], *np = namebuf;
7531617Skarels struct	disklabel lab;
7631617Skarels struct	disklabel *readlabel(), *makebootarea();
7730418Skarels char	bootarea[BBSIZE];
7858602Smckusick 
7958602Smckusick #if NUMBOOT > 0
8058602Smckusick int	installboot;	/* non-zero if we should install a boot program */
8158602Smckusick char	*bootbuf;	/* pointer to buffer with remainder of boot prog */
8258602Smckusick int	bootsize;	/* size of remaining boot program */
8358602Smckusick char	*xxboot;	/* primary boot */
8458602Smckusick char	*bootxx;	/* secondary boot */
8534032Skarels char	boot0[MAXPATHLEN];
8634032Skarels char	boot1[MAXPATHLEN];
8758602Smckusick #endif
8830418Skarels 
8958602Smckusick enum	{
9058602Smckusick 	UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT
9158602Smckusick } op = UNSPEC;
9230418Skarels 
9330677Skarels int	rflag;
9430677Skarels 
9534032Skarels #ifdef DEBUG
9634032Skarels int	debug;
9758602Smckusick #define OPTIONS	"BNRWb:ders:w"
9857996Sralph #else
9958602Smckusick #define OPTIONS	"BNRWb:ers:w"
10034032Skarels #endif
10134032Skarels 
10258602Smckusick 
10330418Skarels main(argc, argv)
10430418Skarels 	int argc;
10530418Skarels 	char *argv[];
10630418Skarels {
10758602Smckusick 	extern char *optarg;
10834032Skarels 	extern int optind;
10930418Skarels 	register struct disklabel *lp;
11034032Skarels 	FILE *t;
11158602Smckusick 	int ch, f, flag, error = 0;
11258602Smckusick 	char *name = 0;
11330418Skarels 
11458602Smckusick 	while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
11534032Skarels 		switch (ch) {
11658602Smckusick #if NUMBOOT > 0
11758602Smckusick 			case 'B':
11858602Smckusick 				++installboot;
11958602Smckusick 				break;
12058602Smckusick 			case 'b':
12158602Smckusick 				xxboot = optarg;
12258602Smckusick 				break;
12358602Smckusick #if NUMBOOT > 1
12458602Smckusick 			case 's':
12558602Smckusick 				bootxx = optarg;
12658602Smckusick 				break;
12758602Smckusick #endif
12858602Smckusick #endif
12934032Skarels 			case 'N':
13034032Skarels 				if (op != UNSPEC)
13134032Skarels 					usage();
13234032Skarels 				op = NOWRITE;
13334032Skarels 				break;
13430715Sbostic 			case 'R':
13534032Skarels 				if (op != UNSPEC)
13634032Skarels 					usage();
13730715Sbostic 				op = RESTORE;
13830715Sbostic 				break;
13934032Skarels 			case 'W':
14034032Skarels 				if (op != UNSPEC)
14134032Skarels 					usage();
14234032Skarels 				op = WRITEABLE;
14334032Skarels 				break;
14430715Sbostic 			case 'e':
14534032Skarels 				if (op != UNSPEC)
14634032Skarels 					usage();
14730715Sbostic 				op = EDIT;
14830715Sbostic 				break;
14930715Sbostic 			case 'r':
15030715Sbostic 				++rflag;
15130715Sbostic 				break;
15230715Sbostic 			case 'w':
15334032Skarels 				if (op != UNSPEC)
15434032Skarels 					usage();
15530715Sbostic 				op = WRITE;
15630715Sbostic 				break;
15734032Skarels #ifdef DEBUG
15834032Skarels 			case 'd':
15934032Skarels 				debug++;
16034032Skarels 				break;
16134032Skarels #endif
16230715Sbostic 			case '?':
16330715Sbostic 			default:
16430715Sbostic 				usage();
16530715Sbostic 		}
16630715Sbostic 	argc -= optind;
16730715Sbostic 	argv += optind;
16858602Smckusick #if NUMBOOT > 0
16958602Smckusick 	if (installboot) {
17058602Smckusick 		rflag++;
17158602Smckusick 		if (op == UNSPEC)
17258602Smckusick 			op = WRITEBOOT;
17358602Smckusick 	} else {
17458602Smckusick 		if (op == UNSPEC)
17558602Smckusick 			op = READ;
17658602Smckusick 		xxboot = bootxx = 0;
17758602Smckusick 	}
17858602Smckusick #else
17934032Skarels 	if (op == UNSPEC)
18034032Skarels 		op = READ;
18158602Smckusick #endif
18230715Sbostic 	if (argc < 1)
18330715Sbostic 		usage();
18430715Sbostic 
18530715Sbostic 	dkname = argv[0];
18630418Skarels 	if (dkname[0] != '/') {
18765574Sbostic 		(void)sprintf(np, "%sr%s%c", _PATH_DEV, dkname, RAWPARTITION);
18830418Skarels 		specname = np;
18930418Skarels 		np += strlen(specname) + 1;
19030418Skarels 	} else
19130418Skarels 		specname = dkname;
19230418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
19330418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
19465574Sbostic 		(void)sprintf(specname, "%sr%s", _PATH_DEV, dkname);
19530418Skarels 		np = namebuf + strlen(specname) + 1;
19630418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
19730418Skarels 	}
19830418Skarels 	if (f < 0)
19930418Skarels 		Perror(specname);
20030418Skarels 
20130715Sbostic 	switch(op) {
20258602Smckusick 
20330715Sbostic 	case EDIT:
20430715Sbostic 		if (argc != 1)
20530715Sbostic 			usage();
20634032Skarels 		lp = readlabel(f);
20734641Skarels 		error = edit(lp, f);
20830715Sbostic 		break;
20958602Smckusick 
21058602Smckusick 	case NOWRITE:
21158602Smckusick 		flag = 0;
21234032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
21334032Skarels 			Perror("ioctl DIOCWLABEL");
21434032Skarels 		break;
21558602Smckusick 
21630418Skarels 	case READ:
21730715Sbostic 		if (argc != 1)
21830715Sbostic 			usage();
21934032Skarels 		lp = readlabel(f);
22030418Skarels 		display(stdout, lp);
22134641Skarels 		error = checklabel(lp);
22230418Skarels 		break;
22358602Smckusick 
22430715Sbostic 	case RESTORE:
22558602Smckusick #if NUMBOOT > 0
22658602Smckusick 		if (installboot && argc == 3) {
22758602Smckusick 			makelabel(argv[2], 0, &lab);
22858602Smckusick 			argc--;
22934032Skarels 		}
23031617Skarels #endif
23130715Sbostic 		if (argc != 2)
23230715Sbostic 			usage();
23358602Smckusick 		lp = makebootarea(bootarea, &lab, f);
23458602Smckusick 		if (!(t = fopen(argv[1], "r")))
23530715Sbostic 			Perror(argv[1]);
23630715Sbostic 		if (getasciilabel(t, lp))
23734641Skarels 			error = writelabel(f, bootarea, lp);
23830418Skarels 		break;
23958602Smckusick 
24030418Skarels 	case WRITE:
24158602Smckusick 		if (argc == 3) {
24258602Smckusick 			name = argv[2];
24358602Smckusick 			argc--;
24430715Sbostic 		}
24558602Smckusick 		if (argc != 2)
24630715Sbostic 			usage();
24758602Smckusick 		makelabel(argv[1], name, &lab);
24858602Smckusick 		lp = makebootarea(bootarea, &lab, f);
24930418Skarels 		*lp = lab;
25030715Sbostic 		if (checklabel(lp) == 0)
25134641Skarels 			error = writelabel(f, bootarea, lp);
25230418Skarels 		break;
25358602Smckusick 
25458602Smckusick 	case WRITEABLE:
25558602Smckusick 		flag = 1;
25634032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
25734032Skarels 			Perror("ioctl DIOCWLABEL");
25834032Skarels 		break;
25958602Smckusick 
26058602Smckusick #if NUMBOOT > 0
26158602Smckusick 	case WRITEBOOT:
26258602Smckusick 	{
26358602Smckusick 		struct disklabel tlab;
26458602Smckusick 
26558602Smckusick 		lp = readlabel(f);
26658602Smckusick 		tlab = *lp;
26758602Smckusick 		if (argc == 2)
26858602Smckusick 			makelabel(argv[1], 0, &lab);
26958602Smckusick 		lp = makebootarea(bootarea, &lab, f);
27058602Smckusick 		*lp = tlab;
27158602Smckusick 		if (checklabel(lp) == 0)
27258602Smckusick 			error = writelabel(f, bootarea, lp);
27358602Smckusick 		break;
27430418Skarels 	}
27558602Smckusick #endif
27634032Skarels 	}
27734641Skarels 	exit(error);
27830418Skarels }
27930418Skarels 
28034032Skarels /*
28134032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
28234032Skarels  * effect, set the names of the primary and secondary boot files
28334032Skarels  * if specified.
28434032Skarels  */
28530418Skarels makelabel(type, name, lp)
28630418Skarels 	char *type, *name;
28730418Skarels 	register struct disklabel *lp;
28830418Skarels {
28930418Skarels 	register struct disklabel *dp;
29034032Skarels 	char *strcpy();
29130418Skarels 
29230418Skarels 	dp = getdiskbyname(type);
29330418Skarels 	if (dp == NULL) {
29430418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
29530418Skarels 		exit(1);
29630418Skarels 	}
29730418Skarels 	*lp = *dp;
29858602Smckusick #if NUMBOOT > 0
29934032Skarels 	/*
30058602Smckusick 	 * Set bootstrap name(s).
30158602Smckusick 	 * 1. If set from command line, use those,
30258602Smckusick 	 * 2. otherwise, check if disktab specifies them (b0 or b1),
30358602Smckusick 	 * 3. otherwise, makebootarea() will choose ones based on the name
30458602Smckusick 	 *    of the disk special file. E.g. /dev/ra0 -> raboot, bootra
30534032Skarels 	 */
30634032Skarels 	if (!xxboot && lp->d_boot0) {
30734032Skarels 		if (*lp->d_boot0 != '/')
30858602Smckusick 			(void)sprintf(boot0, "%s/%s",
30958602Smckusick 				      _PATH_BOOTDIR, lp->d_boot0);
31034032Skarels 		else
31134032Skarels 			(void)strcpy(boot0, lp->d_boot0);
31234032Skarels 		xxboot = boot0;
31334032Skarels 	}
31458602Smckusick #if NUMBOOT > 1
31534032Skarels 	if (!bootxx && lp->d_boot1) {
31634032Skarels 		if (*lp->d_boot1 != '/')
31758602Smckusick 			(void)sprintf(boot1, "%s/%s",
31858602Smckusick 				      _PATH_BOOTDIR, lp->d_boot1);
31934032Skarels 		else
32034032Skarels 			(void)strcpy(boot1, lp->d_boot1);
32134032Skarels 		bootxx = boot1;
32234032Skarels 	}
32358602Smckusick #endif
32458602Smckusick #endif
32534032Skarels 	/* d_packname is union d_boot[01], so zero */
326*68990Sbostic 	memset(lp->d_packname, 0, sizeof(lp->d_packname));
32730418Skarels 	if (name)
32834032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
32930418Skarels }
33030418Skarels 
33130418Skarels writelabel(f, boot, lp)
33230418Skarels 	int f;
33330418Skarels 	char *boot;
33430418Skarels 	register struct disklabel *lp;
33530418Skarels {
33630715Sbostic 	register int i;
33734032Skarels 	int flag;
33830418Skarels 
33958602Smckusick 	setbootflag(lp);
34030418Skarels 	lp->d_magic = DISKMAGIC;
34130418Skarels 	lp->d_magic2 = DISKMAGIC;
34230418Skarels 	lp->d_checksum = 0;
34330418Skarels 	lp->d_checksum = dkcksum(lp);
34430677Skarels 	if (rflag) {
34534032Skarels 		/*
34634032Skarels 		 * First set the kernel disk label,
34734032Skarels 		 * then write a label to the raw disk.
34834032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
34934032Skarels 		 * keep going; otherwise, the kernel consistency checks
35034032Skarels 		 * may prevent us from changing the current (in-core)
35134032Skarels 		 * label.
35234032Skarels 		 */
35334032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
35434641Skarels 		    errno != ENODEV && errno != ENOTTY) {
35534641Skarels 			l_perror("ioctl DIOCSDINFO");
35634641Skarels 			return (1);
35734641Skarels 		}
35857996Sralph 		(void)lseek(f, (off_t)0, SEEK_SET);
35934032Skarels 		/*
36034032Skarels 		 * write enable label sector before write (if necessary),
36134032Skarels 		 * disable after writing.
36234032Skarels 		 */
36334032Skarels 		flag = 1;
36434032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
36534032Skarels 			perror("ioctl DIOCWLABEL");
36634641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
36734641Skarels 			perror("write");
36834641Skarels 			return (1);
36934641Skarels 		}
37058602Smckusick #if NUMBOOT > 0
37158602Smckusick 		/*
37258602Smckusick 		 * Output the remainder of the disklabel
37358602Smckusick 		 */
37458602Smckusick 		if (bootbuf && write(f, bootbuf, bootsize) != bootsize) {
37558602Smckusick 			perror("write");
37658602Smckusick 			return(1);
37758602Smckusick 		}
37858602Smckusick #endif
37934032Skarels 		flag = 0;
38034032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
38134641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
38234641Skarels 		l_perror("ioctl DIOCWDINFO");
38334641Skarels 		return (1);
38434641Skarels 	}
38534032Skarels #ifdef vax
38630677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
38730677Skarels 		daddr_t alt;
38830677Skarels 
38930677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
39030677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
39157996Sralph 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize),
39258602Smckusick 			    SEEK_SET);
39330677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
39430677Skarels 				int oerrno = errno;
39530677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
39630677Skarels 				errno = oerrno;
39730677Skarels 				perror("write");
39830677Skarels 			}
39930418Skarels 		}
40030418Skarels 	}
40130419Skarels #endif
40234641Skarels 	return (0);
40330418Skarels }
40430418Skarels 
40534641Skarels l_perror(s)
40634641Skarels 	char *s;
40734641Skarels {
40834641Skarels 	int saverrno = errno;
40934641Skarels 
41034641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
41134641Skarels 
41234641Skarels 	switch (saverrno) {
41334641Skarels 
41434641Skarels 	case ESRCH:
41534641Skarels 		fprintf(stderr, "No disk label on disk;\n");
41634641Skarels 		fprintf(stderr,
41734641Skarels 		    "use \"disklabel -r\" to install initial label\n");
41834641Skarels 		break;
41934641Skarels 
42034641Skarels 	case EINVAL:
42134641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
42234641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
42334641Skarels 		break;
42434641Skarels 
42534641Skarels 	case EBUSY:
42634641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
42734641Skarels 		break;
42834641Skarels 
42934641Skarels 	case EXDEV:
43034641Skarels 		fprintf(stderr,
43134641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
43234641Skarels 		break;
43334641Skarels 
43434641Skarels 	default:
43534641Skarels 		errno = saverrno;
43634641Skarels 		perror((char *)NULL);
43734641Skarels 		break;
43834641Skarels 	}
43934641Skarels }
44034641Skarels 
44130418Skarels /*
44231617Skarels  * Fetch disklabel for disk.
44331617Skarels  * Use ioctl to get label unless -r flag is given.
44430418Skarels  */
44530418Skarels struct disklabel *
44634032Skarels readlabel(f)
44734032Skarels 	int f;
44830418Skarels {
44930418Skarels 	register struct disklabel *lp;
45030418Skarels 
45134032Skarels 	if (rflag) {
45231617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
45331401Skarels 			Perror(specname);
45431617Skarels 		for (lp = (struct disklabel *)bootarea;
45531617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
45630677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
45730677Skarels 			if (lp->d_magic == DISKMAGIC &&
45830677Skarels 			    lp->d_magic2 == DISKMAGIC)
45930677Skarels 				break;
46031617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
46130677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
46230677Skarels 		    dkcksum(lp) != 0) {
46330677Skarels 			fprintf(stderr,
46430418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
46534032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
46634032Skarels 			exit (1);
46730677Skarels 		}
46834032Skarels 	} else {
46934032Skarels 		lp = &lab;
47034032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
47134032Skarels 			Perror("ioctl DIOCGDINFO");
47230418Skarels 	}
47330418Skarels 	return (lp);
47430418Skarels }
47530418Skarels 
47658602Smckusick /*
47758602Smckusick  * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot''
47858602Smckusick  * Returns a pointer to the disklabel portion of the bootarea.
47958602Smckusick  */
48030418Skarels struct disklabel *
48158602Smckusick makebootarea(boot, dp, f)
48230418Skarels 	char *boot;
48330418Skarels 	register struct disklabel *dp;
48458602Smckusick 	int f;
48530418Skarels {
48630418Skarels 	struct disklabel *lp;
48730418Skarels 	register char *p;
48830418Skarels 	int b;
48958602Smckusick #if NUMBOOT > 0
49058602Smckusick 	char *dkbasename;
49158602Smckusick 	struct stat sb;
49258602Smckusick #endif
49330715Sbostic 
49458602Smckusick 	/* XXX */
49558602Smckusick 	if (dp->d_secsize == 0) {
49658602Smckusick 		dp->d_secsize = DEV_BSIZE;
49758602Smckusick 		dp->d_bbsize = BBSIZE;
49858602Smckusick 	}
49958602Smckusick 	lp = (struct disklabel *)
50058602Smckusick 		(boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET);
501*68990Sbostic 	memset(lp, 0, sizeof *lp);
50258602Smckusick #if NUMBOOT > 0
50358602Smckusick 	/*
50458602Smckusick 	 * If we are not installing a boot program but we are installing a
50558602Smckusick 	 * label on disk then we must read the current bootarea so we don't
50658602Smckusick 	 * clobber the existing boot.
50758602Smckusick 	 */
50858602Smckusick 	if (!installboot) {
50958602Smckusick 		if (rflag) {
51058602Smckusick 			if (read(f, boot, BBSIZE) < BBSIZE)
51158602Smckusick 				Perror(specname);
512*68990Sbostic 			memset(lp, 0, sizeof *lp);
51358602Smckusick 		}
51434032Skarels 		return (lp);
51558602Smckusick 	}
51658602Smckusick 	/*
51758602Smckusick 	 * We are installing a boot program.  Determine the name(s) and
51858602Smckusick 	 * read them into the appropriate places in the boot area.
51958602Smckusick 	 */
52058602Smckusick 	if (!xxboot || !bootxx) {
52130418Skarels 		dkbasename = np;
522*68990Sbostic 		if ((p = strrchr(dkname, '/')) == NULL)
52330418Skarels 			p = dkname;
52430418Skarels 		else
52530418Skarels 			p++;
52630418Skarels 		while (*p && !isdigit(*p))
52730418Skarels 			*np++ = *p++;
52830418Skarels 		*np++ = '\0';
52930418Skarels 
53058602Smckusick 		if (!xxboot) {
53158602Smckusick 			(void)sprintf(np, "%s/%sboot",
53258602Smckusick 				      _PATH_BOOTDIR, dkbasename);
53334032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
53434032Skarels 				dkbasename++;
53534032Skarels 			xxboot = np;
53658602Smckusick 			(void)sprintf(xxboot, "%s/%sboot",
53758602Smckusick 				      _PATH_BOOTDIR, dkbasename);
53834032Skarels 			np += strlen(xxboot) + 1;
53934032Skarels 		}
54058602Smckusick #if NUMBOOT > 1
54158602Smckusick 		if (!bootxx) {
54258602Smckusick 			(void)sprintf(np, "%s/boot%s",
54358602Smckusick 				      _PATH_BOOTDIR, dkbasename);
54434032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
54534032Skarels 				dkbasename++;
54634032Skarels 			bootxx = np;
54758602Smckusick 			(void)sprintf(bootxx, "%s/boot%s",
54858602Smckusick 				      _PATH_BOOTDIR, dkbasename);
54934032Skarels 			np += strlen(bootxx) + 1;
55034032Skarels 		}
55158602Smckusick #endif
55230418Skarels 	}
55334032Skarels #ifdef DEBUG
55434032Skarels 	if (debug)
55534032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
55658602Smckusick 			xxboot, bootxx ? bootxx : "NONE");
55734032Skarels #endif
55830418Skarels 
55958602Smckusick 	/*
56058602Smckusick 	 * Strange rules:
56158602Smckusick 	 * 1. One-piece bootstrap (hp300/hp800)
56258602Smckusick 	 *	up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest
56358602Smckusick 	 *	is remembered and written later following the bootarea.
56458602Smckusick 	 * 2. Two-piece bootstraps (vax/i386?/mips?)
56558602Smckusick 	 *	up to d_secsize bytes of ``xxboot'' go in first d_secsize
56658602Smckusick 	 *	bytes of bootarea, remaining d_bbsize-d_secsize filled
56758602Smckusick 	 *	from ``bootxx''.
56858602Smckusick 	 */
56930418Skarels 	b = open(xxboot, O_RDONLY);
57030418Skarels 	if (b < 0)
57130418Skarels 		Perror(xxboot);
57258602Smckusick #if NUMBOOT > 1
57330715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
57430418Skarels 		Perror(xxboot);
57558602Smckusick 	(void)close(b);
57630418Skarels 	b = open(bootxx, O_RDONLY);
57730418Skarels 	if (b < 0)
57830418Skarels 		Perror(bootxx);
57930715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
58030418Skarels 		Perror(bootxx);
58158602Smckusick #else
58258602Smckusick 	if (read(b, boot, (int)dp->d_bbsize) < 0)
58358602Smckusick 		Perror(xxboot);
58458602Smckusick 	(void)fstat(b, &sb);
58558602Smckusick 	bootsize = (int)sb.st_size - dp->d_bbsize;
58658602Smckusick 	if (bootsize > 0) {
58758602Smckusick 		/* XXX assume d_secsize is a power of two */
58858602Smckusick 		bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1);
58958602Smckusick 		bootbuf = (char *)malloc((size_t)bootsize);
59058602Smckusick 		if (bootbuf == 0)
59158602Smckusick 			Perror(xxboot);
59258602Smckusick 		if (read(b, bootbuf, bootsize) < 0) {
59358602Smckusick 			free(bootbuf);
59458602Smckusick 			Perror(xxboot);
59558602Smckusick 		}
59658602Smckusick 	}
59758602Smckusick #endif
59830715Sbostic 	(void)close(b);
59958602Smckusick #endif
60058602Smckusick 	/*
60158602Smckusick 	 * Make sure no part of the bootstrap is written in the area
60258602Smckusick 	 * reserved for the label.
60358602Smckusick 	 */
60430418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
60530418Skarels 		if (*p) {
60630418Skarels 			fprintf(stderr,
60730418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
60830418Skarels 			exit(2);
60930418Skarels 		}
61030418Skarels 	return (lp);
61130418Skarels }
61230418Skarels 
61330418Skarels display(f, lp)
61430418Skarels 	FILE *f;
61530418Skarels 	register struct disklabel *lp;
61630418Skarels {
61730715Sbostic 	register int i, j;
61830418Skarels 	register struct partition *pp;
61930418Skarels 
62030418Skarels 	fprintf(f, "# %s:\n", specname);
62130418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
62230418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
62330418Skarels 	else
62430418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
62530418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
62634032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
62731401Skarels 	fprintf(f, "flags:");
62830418Skarels 	if (lp->d_flags & D_REMOVABLE)
62931401Skarels 		fprintf(f, " removeable");
63030418Skarels 	if (lp->d_flags & D_ECC)
63131401Skarels 		fprintf(f, " ecc");
63230418Skarels 	if (lp->d_flags & D_BADSECT)
63331401Skarels 		fprintf(f, " badsect");
63430418Skarels 	fprintf(f, "\n");
63530418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
63630418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
63730418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
63831386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
63930418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
64030715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
64130418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
64230418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
64330418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
64430418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
64530418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
64630418Skarels 	fprintf(f, "drivedata: ");
64730418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
64830418Skarels 		if (lp->d_drivedata[i])
64930418Skarels 			break;
65030418Skarels 	if (i < 0)
65130418Skarels 		i = 0;
65230418Skarels 	for (j = 0; j <= i; j++)
65330418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
65430418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
65530863Skarels 	fprintf(f,
65630863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
65730418Skarels 	pp = lp->d_partitions;
65830418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
65930418Skarels 		if (pp->p_size) {
66030863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
66130863Skarels 			   pp->p_size, pp->p_offset);
66230418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
66330418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
66430418Skarels 			else
66530418Skarels 				fprintf(f, "%8d", pp->p_fstype);
66630863Skarels 			switch (pp->p_fstype) {
66730863Skarels 
66830863Skarels 			case FS_UNUSED:				/* XXX */
66930863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
67030863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
67130863Skarels 				break;
67230863Skarels 
67330863Skarels 			case FS_BSDFFS:
67430863Skarels 				fprintf(f, "    %5d %5d %5d ",
67530863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
67630863Skarels 				    pp->p_cpg);
67730863Skarels 				break;
67830863Skarels 
67930863Skarels 			default:
68030863Skarels 				fprintf(f, "%20.20s", "");
68130863Skarels 				break;
68230863Skarels 			}
68330418Skarels 			fprintf(f, "\t# (Cyl. %4d",
68430418Skarels 			    pp->p_offset / lp->d_secpercyl);
68530418Skarels 			if (pp->p_offset % lp->d_secpercyl)
68630418Skarels 			    putc('*', f);
68730418Skarels 			else
68830418Skarels 			    putc(' ', f);
68930418Skarels 			fprintf(f, "- %d",
69030418Skarels 			    (pp->p_offset +
69130418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
69230418Skarels 			    lp->d_secpercyl - 1);
69330418Skarels 			if (pp->p_size % lp->d_secpercyl)
69430418Skarels 			    putc('*', f);
69530863Skarels 			fprintf(f, ")\n");
69630418Skarels 		}
69730418Skarels 	}
69832121Stef 	fflush(f);
69930418Skarels }
70030418Skarels 
70134641Skarels edit(lp, f)
70230715Sbostic 	struct disklabel *lp;
70334641Skarels 	int f;
70430418Skarels {
70530715Sbostic 	register int c;
70630715Sbostic 	struct disklabel label;
70730715Sbostic 	FILE *fd;
70830715Sbostic 	char *mktemp();
70930715Sbostic 
71030715Sbostic 	(void) mktemp(tmpfil);
71130715Sbostic 	fd = fopen(tmpfil, "w");
71230715Sbostic 	if (fd == NULL) {
71330715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
71434641Skarels 		return (1);
71530715Sbostic 	}
71658602Smckusick 	(void)fchmod(fileno(fd), 0600);
71730715Sbostic 	display(fd, lp);
71830715Sbostic 	fclose(fd);
71930715Sbostic 	for (;;) {
72030715Sbostic 		if (!editit())
72130715Sbostic 			break;
72230715Sbostic 		fd = fopen(tmpfil, "r");
72330715Sbostic 		if (fd == NULL) {
72434032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
72534032Skarels 				tmpfil);
72630715Sbostic 			break;
72730715Sbostic 		}
728*68990Sbostic 		memset(&label, 0, sizeof(label));
72930715Sbostic 		if (getasciilabel(fd, &label)) {
73030715Sbostic 			*lp = label;
73134641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
73234641Skarels 				(void) unlink(tmpfil);
73334641Skarels 				return (0);
73434641Skarels 			}
73530715Sbostic 		}
73630715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
73730715Sbostic 		c = getchar();
73830715Sbostic 		if (c != EOF && c != (int)'\n')
73930715Sbostic 			while (getchar() != (int)'\n')
74030715Sbostic 				;
74130715Sbostic 		if  (c == (int)'n')
74230715Sbostic 			break;
74330715Sbostic 	}
74430715Sbostic 	(void) unlink(tmpfil);
74534641Skarels 	return (1);
74630418Skarels }
74730418Skarels 
74830715Sbostic editit()
74930715Sbostic {
75030715Sbostic 	register int pid, xpid;
75130715Sbostic 	int stat, omask;
75230715Sbostic 	extern char *getenv();
75330418Skarels 
75430715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
75530715Sbostic 	while ((pid = fork()) < 0) {
75630715Sbostic 		extern int errno;
75730715Sbostic 
75830715Sbostic 		if (errno == EPROCLIM) {
75930715Sbostic 			fprintf(stderr, "You have too many processes\n");
76030715Sbostic 			return(0);
76130715Sbostic 		}
76230715Sbostic 		if (errno != EAGAIN) {
76330715Sbostic 			perror("fork");
76430715Sbostic 			return(0);
76530715Sbostic 		}
76630715Sbostic 		sleep(1);
76730715Sbostic 	}
76830715Sbostic 	if (pid == 0) {
76930715Sbostic 		register char *ed;
77030715Sbostic 
77130715Sbostic 		sigsetmask(omask);
77230715Sbostic 		setgid(getgid());
77330715Sbostic 		setuid(getuid());
77430715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
77530715Sbostic 			ed = DEFEDITOR;
77630715Sbostic 		execlp(ed, ed, tmpfil, 0);
77730715Sbostic 		perror(ed);
77830715Sbostic 		exit(1);
77930715Sbostic 	}
78030715Sbostic 	while ((xpid = wait(&stat)) >= 0)
78130715Sbostic 		if (xpid == pid)
78230715Sbostic 			break;
78330715Sbostic 	sigsetmask(omask);
78430715Sbostic 	return(!stat);
78530715Sbostic }
78630715Sbostic 
78730715Sbostic char *
78830715Sbostic skip(cp)
78930715Sbostic 	register char *cp;
79030715Sbostic {
79130715Sbostic 
79230715Sbostic 	while (*cp != '\0' && isspace(*cp))
79330715Sbostic 		cp++;
79430715Sbostic 	if (*cp == '\0' || *cp == '#')
79530715Sbostic 		return ((char *)NULL);
79630715Sbostic 	return (cp);
79730715Sbostic }
79830715Sbostic 
79930715Sbostic char *
80030715Sbostic word(cp)
80130715Sbostic 	register char *cp;
80230715Sbostic {
80330715Sbostic 	register char c;
80430715Sbostic 
80531401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
80631401Skarels 		cp++;
80730715Sbostic 	if ((c = *cp) != '\0') {
80830715Sbostic 		*cp++ = '\0';
80930715Sbostic 		if (c != '#')
81030715Sbostic 			return (skip(cp));
81130715Sbostic 	}
81230715Sbostic 	return ((char *)NULL);
81330715Sbostic }
81430715Sbostic 
81530418Skarels /*
81630418Skarels  * Read an ascii label in from fd f,
81730418Skarels  * in the same format as that put out by display(),
81830418Skarels  * and fill in lp.
81930418Skarels  */
82030418Skarels getasciilabel(f, lp)
82130715Sbostic 	FILE	*f;
82230418Skarels 	register struct disklabel *lp;
82330418Skarels {
82430715Sbostic 	register char **cpp, *cp;
82530863Skarels 	register struct partition *pp;
82630715Sbostic 	char *tp, *s, line[BUFSIZ];
82730715Sbostic 	int v, lineno = 0, errors = 0;
82830715Sbostic 
82930715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
83030715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
83130715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
83230715Sbostic 		lineno++;
833*68990Sbostic 		if (cp = strchr(line,'\n'))
83430715Sbostic 			*cp = '\0';
83530715Sbostic 		cp = skip(line);
83630715Sbostic 		if (cp == NULL)
83730715Sbostic 			continue;
838*68990Sbostic 		tp = strchr(cp, ':');
83930715Sbostic 		if (tp == NULL) {
84030715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
84130715Sbostic 			errors++;
84230715Sbostic 			continue;
84330715Sbostic 		}
84430715Sbostic 		*tp++ = '\0', tp = skip(tp);
84530715Sbostic 		if (streq(cp, "type")) {
84630715Sbostic 			if (tp == NULL)
84730715Sbostic 				tp = "unknown";
84830715Sbostic 			cpp = dktypenames;
84930715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
85030715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
85130715Sbostic 					lp->d_type = cpp - dktypenames;
85230715Sbostic 					goto next;
85330715Sbostic 				}
85430715Sbostic 			v = atoi(tp);
85530715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
85630715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
85730715Sbostic 				    "Warning, unknown disk type", v);
85830715Sbostic 			lp->d_type = v;
85930715Sbostic 			continue;
86030715Sbostic 		}
86130715Sbostic 		if (streq(cp, "flags")) {
86234032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
86334032Skarels 				tp = word(cp);
86430715Sbostic 				if (streq(cp, "removeable"))
86530715Sbostic 					v |= D_REMOVABLE;
86630715Sbostic 				else if (streq(cp, "ecc"))
86730715Sbostic 					v |= D_ECC;
86830715Sbostic 				else if (streq(cp, "badsect"))
86930715Sbostic 					v |= D_BADSECT;
87030715Sbostic 				else {
87130715Sbostic 					fprintf(stderr,
87230715Sbostic 					    "line %d: %s: bad flag\n",
87330715Sbostic 					    lineno, cp);
87430715Sbostic 					errors++;
87530715Sbostic 				}
87630715Sbostic 			}
87730715Sbostic 			lp->d_flags = v;
87830715Sbostic 			continue;
87930715Sbostic 		}
88030715Sbostic 		if (streq(cp, "drivedata")) {
88130715Sbostic 			register int i;
88230715Sbostic 
88331386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
88430715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
88531386Skarels 				tp = word(cp);
88630715Sbostic 			}
88730715Sbostic 			continue;
88830715Sbostic 		}
88930715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
89030863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
89130715Sbostic 				fprintf(stderr,
89230715Sbostic 				    "line %d: bad # of partitions\n", lineno);
89330863Skarels 				lp->d_npartitions = MAXPARTITIONS;
89430863Skarels 				errors++;
89530863Skarels 			} else
89630715Sbostic 				lp->d_npartitions = v;
89730715Sbostic 			continue;
89830715Sbostic 		}
89930715Sbostic 		if (tp == NULL)
90030715Sbostic 			tp = "";
90130715Sbostic 		if (streq(cp, "disk")) {
90230715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
90330715Sbostic 			continue;
90430715Sbostic 		}
90530715Sbostic 		if (streq(cp, "label")) {
90634032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
90730715Sbostic 			continue;
90830715Sbostic 		}
90930715Sbostic 		if (streq(cp, "bytes/sector")) {
91030715Sbostic 			v = atoi(tp);
91130715Sbostic 			if (v <= 0 || (v % 512) != 0) {
91230715Sbostic 				fprintf(stderr,
91330715Sbostic 				    "line %d: %s: bad sector size\n",
91430715Sbostic 				    lineno, tp);
91530715Sbostic 				errors++;
91630715Sbostic 			} else
91730715Sbostic 				lp->d_secsize = v;
91830715Sbostic 			continue;
91930715Sbostic 		}
92030715Sbostic 		if (streq(cp, "sectors/track")) {
92130715Sbostic 			v = atoi(tp);
92230715Sbostic 			if (v <= 0) {
92330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
92430715Sbostic 				    lineno, tp, cp);
92530715Sbostic 				errors++;
92630715Sbostic 			} else
92730715Sbostic 				lp->d_nsectors = v;
92830715Sbostic 			continue;
92930715Sbostic 		}
93031386Skarels 		if (streq(cp, "sectors/cylinder")) {
93131386Skarels 			v = atoi(tp);
93231386Skarels 			if (v <= 0) {
93331386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
93431386Skarels 				    lineno, tp, cp);
93531386Skarels 				errors++;
93631386Skarels 			} else
93731386Skarels 				lp->d_secpercyl = v;
93831386Skarels 			continue;
93931386Skarels 		}
94030715Sbostic 		if (streq(cp, "tracks/cylinder")) {
94130715Sbostic 			v = atoi(tp);
94230715Sbostic 			if (v <= 0) {
94330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
94430715Sbostic 				    lineno, tp, cp);
94530715Sbostic 				errors++;
94630715Sbostic 			} else
94730715Sbostic 				lp->d_ntracks = v;
94830715Sbostic 			continue;
94930715Sbostic 		}
95030715Sbostic 		if (streq(cp, "cylinders")) {
95130715Sbostic 			v = atoi(tp);
95230715Sbostic 			if (v <= 0) {
95330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
95430715Sbostic 				    lineno, tp, cp);
95530715Sbostic 				errors++;
95630715Sbostic 			} else
95730715Sbostic 				lp->d_ncylinders = v;
95830715Sbostic 			continue;
95930715Sbostic 		}
96030715Sbostic 		if (streq(cp, "rpm")) {
96130715Sbostic 			v = atoi(tp);
96230715Sbostic 			if (v <= 0) {
96330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
96430715Sbostic 				    lineno, tp, cp);
96530715Sbostic 				errors++;
96630715Sbostic 			} else
96730715Sbostic 				lp->d_rpm = v;
96830715Sbostic 			continue;
96930715Sbostic 		}
97030715Sbostic 		if (streq(cp, "interleave")) {
97130715Sbostic 			v = atoi(tp);
97230715Sbostic 			if (v <= 0) {
97330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
97430715Sbostic 				    lineno, tp, cp);
97530715Sbostic 				errors++;
97630715Sbostic 			} else
97730715Sbostic 				lp->d_interleave = v;
97830715Sbostic 			continue;
97930715Sbostic 		}
98030715Sbostic 		if (streq(cp, "trackskew")) {
98130715Sbostic 			v = atoi(tp);
98230715Sbostic 			if (v < 0) {
98330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
98430715Sbostic 				    lineno, tp, cp);
98530715Sbostic 				errors++;
98630715Sbostic 			} else
98730715Sbostic 				lp->d_trackskew = v;
98830715Sbostic 			continue;
98930715Sbostic 		}
99030715Sbostic 		if (streq(cp, "cylinderskew")) {
99130715Sbostic 			v = atoi(tp);
99230715Sbostic 			if (v < 0) {
99330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
99430715Sbostic 				    lineno, tp, cp);
99530715Sbostic 				errors++;
99630715Sbostic 			} else
99730715Sbostic 				lp->d_cylskew = v;
99830715Sbostic 			continue;
99930715Sbostic 		}
100030715Sbostic 		if (streq(cp, "headswitch")) {
100130715Sbostic 			v = atoi(tp);
100230715Sbostic 			if (v < 0) {
100330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
100430715Sbostic 				    lineno, tp, cp);
100530715Sbostic 				errors++;
100630715Sbostic 			} else
100730715Sbostic 				lp->d_headswitch = v;
100830715Sbostic 			continue;
100930715Sbostic 		}
101030715Sbostic 		if (streq(cp, "track-to-track seek")) {
101130715Sbostic 			v = atoi(tp);
101230715Sbostic 			if (v < 0) {
101330715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
101430715Sbostic 				    lineno, tp, cp);
101530715Sbostic 				errors++;
101630715Sbostic 			} else
101730715Sbostic 				lp->d_trkseek = v;
101830715Sbostic 			continue;
101930715Sbostic 		}
102030715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
102130863Skarels 			unsigned part = *cp - 'a';
102230715Sbostic 
102330863Skarels 			if (part > lp->d_npartitions) {
102430715Sbostic 				fprintf(stderr,
102530715Sbostic 				    "line %d: bad partition name\n", lineno);
102630715Sbostic 				errors++;
102730715Sbostic 				continue;
102830715Sbostic 			}
102930863Skarels 			pp = &lp->d_partitions[part];
103030863Skarels #define NXTNUM(n) { \
103130863Skarels 	cp = tp, tp = word(cp); \
103230863Skarels 	if (tp == NULL) \
103330863Skarels 		tp = cp; \
103430863Skarels 	(n) = atoi(cp); \
103530863Skarels      }
103630863Skarels 
103730863Skarels 			NXTNUM(v);
103830715Sbostic 			if (v < 0) {
103930715Sbostic 				fprintf(stderr,
104030715Sbostic 				    "line %d: %s: bad partition size\n",
104130715Sbostic 				    lineno, cp);
104230715Sbostic 				errors++;
104330715Sbostic 			} else
104430863Skarels 				pp->p_size = v;
104530863Skarels 			NXTNUM(v);
104630715Sbostic 			if (v < 0) {
104730715Sbostic 				fprintf(stderr,
104830715Sbostic 				    "line %d: %s: bad partition offset\n",
104930715Sbostic 				    lineno, cp);
105030715Sbostic 				errors++;
105130715Sbostic 			} else
105230863Skarels 				pp->p_offset = v;
105330715Sbostic 			cp = tp, tp = word(cp);
105430715Sbostic 			cpp = fstypenames;
105530715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
105630715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
105730863Skarels 					pp->p_fstype = cpp - fstypenames;
105830863Skarels 					goto gottype;
105930715Sbostic 				}
106034032Skarels 			if (isdigit(*cp))
106134032Skarels 				v = atoi(cp);
106234032Skarels 			else
106334032Skarels 				v = FSMAXTYPES;
106434032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
106530715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
106630715Sbostic 				    "Warning, unknown filesystem type", cp);
106734032Skarels 				v = FS_UNUSED;
106834032Skarels 			}
106930863Skarels 			pp->p_fstype = v;
107030863Skarels 	gottype:
107130863Skarels 
107230863Skarels 			switch (pp->p_fstype) {
107330863Skarels 
107430863Skarels 			case FS_UNUSED:				/* XXX */
107530863Skarels 				NXTNUM(pp->p_fsize);
107630863Skarels 				if (pp->p_fsize == 0)
107730863Skarels 					break;
107830863Skarels 				NXTNUM(v);
107930863Skarels 				pp->p_frag = v / pp->p_fsize;
108030863Skarels 				break;
108130863Skarels 
108230863Skarels 			case FS_BSDFFS:
108330863Skarels 				NXTNUM(pp->p_fsize);
108430863Skarels 				if (pp->p_fsize == 0)
108530863Skarels 					break;
108630863Skarels 				NXTNUM(v);
108730863Skarels 				pp->p_frag = v / pp->p_fsize;
108830863Skarels 				NXTNUM(pp->p_cpg);
108930863Skarels 				break;
109030863Skarels 
109130863Skarels 			default:
109230863Skarels 				break;
109330863Skarels 			}
109430715Sbostic 			continue;
109530715Sbostic 		}
109630715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
109730715Sbostic 		    lineno, cp);
109830715Sbostic 		errors++;
109930715Sbostic 	next:
110030715Sbostic 		;
110130715Sbostic 	}
110230715Sbostic 	errors += checklabel(lp);
110330715Sbostic 	return (errors == 0);
110430418Skarels }
110530418Skarels 
110630715Sbostic /*
110730715Sbostic  * Check disklabel for errors and fill in
110830715Sbostic  * derived fields according to supplied values.
110930715Sbostic  */
111030715Sbostic checklabel(lp)
111130715Sbostic 	register struct disklabel *lp;
111230418Skarels {
111330715Sbostic 	register struct partition *pp;
111430715Sbostic 	int i, errors = 0;
111530715Sbostic 	char part;
111630418Skarels 
111730715Sbostic 	if (lp->d_secsize == 0) {
111830715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
111930715Sbostic 		return (1);
112030715Sbostic 	}
112130715Sbostic 	if (lp->d_nsectors == 0) {
112230715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
112330715Sbostic 		return (1);
112430715Sbostic 	}
112530715Sbostic 	if (lp->d_ntracks == 0) {
112630715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
112730715Sbostic 		return (1);
112830715Sbostic 	}
112930715Sbostic 	if  (lp->d_ncylinders == 0) {
113030715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
113130715Sbostic 		errors++;
113230715Sbostic 	}
113330715Sbostic 	if (lp->d_rpm == 0)
113458602Smckusick 		Warning("revolutions/minute %d", lp->d_rpm);
113530715Sbostic 	if (lp->d_secpercyl == 0)
113630715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
113730715Sbostic 	if (lp->d_secperunit == 0)
113830715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
113930715Sbostic 	if (lp->d_bbsize == 0) {
114030715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
114130715Sbostic 		errors++;
114230715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
114358602Smckusick 		Warning("boot block size %% sector-size != 0");
114430715Sbostic 	if (lp->d_sbsize == 0) {
114530715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
114630715Sbostic 		errors++;
114730715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
114858602Smckusick 		Warning("super block size %% sector-size != 0");
114930715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
115058602Smckusick 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)",
115130715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
115230715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
115330715Sbostic 		part = 'a' + i;
115430715Sbostic 		pp = &lp->d_partitions[i];
115530715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
115658602Smckusick 			Warning("partition %c: size 0, but offset %d",
115730715Sbostic 			    part, pp->p_offset);
115830715Sbostic #ifdef notdef
115930715Sbostic 		if (pp->p_size % lp->d_secpercyl)
116058602Smckusick 			Warning("partition %c: size %% cylinder-size != 0",
116130715Sbostic 			    part);
116230715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
116358602Smckusick 			Warning("partition %c: offset %% cylinder-size != 0",
116430715Sbostic 			    part);
116530715Sbostic #endif
116630715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
116730715Sbostic 			fprintf(stderr,
116830715Sbostic 			    "partition %c: offset past end of unit\n", part);
116930715Sbostic 			errors++;
117030715Sbostic 		}
117130715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
117230715Sbostic 			fprintf(stderr,
117330715Sbostic 			    "partition %c: partition extends past end of unit\n",
117430715Sbostic 			    part);
117530715Sbostic 			errors++;
117630715Sbostic 		}
117730715Sbostic 	}
117830715Sbostic 	for (; i < MAXPARTITIONS; i++) {
117930715Sbostic 		part = 'a' + i;
118030715Sbostic 		pp = &lp->d_partitions[i];
118130715Sbostic 		if (pp->p_size || pp->p_offset)
118258602Smckusick 			Warning("unused partition %c: size %d offset %d",
118334032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
118430715Sbostic 	}
118530715Sbostic 	return (errors);
118630715Sbostic }
118730715Sbostic 
118858602Smckusick /*
118958602Smckusick  * If we are installing a boot program that doesn't fit in d_bbsize
119058602Smckusick  * we need to mark those partitions that the boot overflows into.
119158602Smckusick  * This allows newfs to prevent creation of a filesystem where it might
119258602Smckusick  * clobber bootstrap code.
119358602Smckusick  */
119458602Smckusick setbootflag(lp)
119558602Smckusick 	register struct disklabel *lp;
119658602Smckusick {
119758602Smckusick 	register struct partition *pp;
119858602Smckusick 	int i, errors = 0;
119958602Smckusick 	char part;
120058602Smckusick 	u_long boffset;
120158602Smckusick 
120258602Smckusick 	if (bootbuf == 0)
120358602Smckusick 		return;
120458602Smckusick 	boffset = bootsize / lp->d_secsize;
120558602Smckusick 	for (i = 0; i < lp->d_npartitions; i++) {
120658602Smckusick 		part = 'a' + i;
120758602Smckusick 		pp = &lp->d_partitions[i];
120858602Smckusick 		if (pp->p_size == 0)
120958602Smckusick 			continue;
121059087Shibler 		if (boffset <= pp->p_offset) {
121159087Shibler 			if (pp->p_fstype == FS_BOOT)
121259087Shibler 				pp->p_fstype = FS_UNUSED;
121359087Shibler 		} else if (pp->p_fstype != FS_BOOT) {
121458602Smckusick 			if (pp->p_fstype != FS_UNUSED) {
121558602Smckusick 				fprintf(stderr,
121659087Shibler 					"boot overlaps used partition %c\n",
121758602Smckusick 					part);
121858602Smckusick 				errors++;
121958602Smckusick 			} else {
122058602Smckusick 				pp->p_fstype = FS_BOOT;
122158602Smckusick 				Warning("boot overlaps partition %c, %s",
122258602Smckusick 					part, "marked as FS_BOOT");
122358602Smckusick 			}
122459087Shibler 		}
122558602Smckusick 	}
122658602Smckusick 	if (errors) {
122758602Smckusick 		fprintf(stderr, "Cannot install boot program\n");
122858602Smckusick 		exit(4);
122958602Smckusick 	}
123058602Smckusick }
123158602Smckusick 
123230715Sbostic /*VARARGS1*/
123330715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
123430715Sbostic 	char *fmt;
123530715Sbostic {
123630715Sbostic 
123730715Sbostic 	fprintf(stderr, "Warning, ");
123830715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
123930715Sbostic 	fprintf(stderr, "\n");
124030715Sbostic }
124130715Sbostic 
124230715Sbostic Perror(str)
124330715Sbostic 	char *str;
124430715Sbostic {
124530715Sbostic 	fputs("disklabel: ", stderr); perror(str);
124630418Skarels 	exit(4);
124730418Skarels }
124830715Sbostic 
124930715Sbostic usage()
125030715Sbostic {
125158602Smckusick #if NUMBOOT > 0
125258602Smckusick 	fprintf(stderr,
125358602Smckusick "%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n",
125458602Smckusick "usage: disklabel [-r] disk",
125558602Smckusick 		"(to read label)",
125658602Smckusick "or disklabel -w [-r] disk type [ packid ]",
125758602Smckusick 		"(to write label with existing boot program)",
125858602Smckusick "or disklabel -e [-r] disk",
125958602Smckusick 		"(to edit label)",
126058602Smckusick "or disklabel -R [-r] disk protofile",
126158602Smckusick 		"(to restore label with existing boot program)",
126258602Smckusick #if NUMBOOT > 1
126358602Smckusick "or disklabel -B [ -b boot1 [ -s boot2 ] ] disk [ type ]",
126458602Smckusick 		"(to install boot program with existing label)",
126558602Smckusick "or disklabel -w -B [ -b boot1 [ -s boot2 ] ] disk type [ packid ]",
126658602Smckusick 		"(to write label and boot program)",
126758602Smckusick "or disklabel -R -B [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]",
126858602Smckusick 		"(to restore label and boot program)",
126930715Sbostic #else
127058602Smckusick "or disklabel -B [ -b bootprog ] disk [ type ]",
127158602Smckusick 		"(to install boot program with existing on-disk label)",
127258602Smckusick "or disklabel -w -B [ -b bootprog ] disk type [ packid ]",
127358602Smckusick 		"(to write label and install boot program)",
127458602Smckusick "or disklabel -R -B [ -b bootprog ] disk protofile [ type ]",
127558602Smckusick 		"(to restore label and install boot program)",
127658602Smckusick #endif
127758602Smckusick "or disklabel [-NW] disk",
127858602Smckusick 		"(to write disable/enable label)");
127958602Smckusick #else
128034032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
128130715Sbostic "usage: disklabel [-r] disk", "(to read label)",
128230715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
128330715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
128434032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
128534032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
128630715Sbostic #endif
128730715Sbostic 	exit(1);
128830715Sbostic }
1289