xref: /csrg-svn/sbin/disklabel/disklabel.c (revision 69258)
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*69258Smckusick static char sccsid[] = "@(#)disklabel.c	8.4 (Berkeley) 05/04/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>
30*69258Smckusick #include <ufs/ufs/dinode.h>
3151615Sbostic #include <ufs/ffs/fs.h>
3257996Sralph #include <unistd.h>
3351615Sbostic #include <string.h>
3437261Sbostic #include <stdio.h>
3537261Sbostic #include <ctype.h>
3637261Sbostic #include "pathnames.h"
3730418Skarels 
3830418Skarels /*
3930418Skarels  * Disklabel: read and write disklabels.
4030418Skarels  * The label is usually placed on one of the first sectors of the disk.
4158602Smckusick  * Many machines also place a bootstrap in the same area,
4230418Skarels  * in which case the label is embedded in the bootstrap.
4330418Skarels  * The bootstrap source must leave space at the proper offset
4430418Skarels  * for the label on such machines.
4530418Skarels  */
4630418Skarels 
4758602Smckusick #ifdef tahoe
4858602Smckusick #define RAWPARTITION	'a'
4958602Smckusick #else
5030677Skarels #define RAWPARTITION	'c'
5130677Skarels #endif
5230677Skarels 
5330677Skarels #ifndef BBSIZE
5430418Skarels #define	BBSIZE	8192			/* size of boot area, with label */
5530677Skarels #endif
5630418Skarels 
5758602Smckusick #ifdef tahoe
5858602Smckusick #define	NUMBOOT	0
5930677Skarels #else
6058602Smckusick #if defined(hp300) || defined(hp800)
6158602Smckusick #define	NUMBOOT	1
6258602Smckusick #else
6358602Smckusick #define	NUMBOOT	2
6430418Skarels #endif
6530677Skarels #endif
6630418Skarels 
6738505Sbostic #define	DEFEDITOR	_PATH_VI
6830715Sbostic #define	streq(a,b)	(strcmp(a,b) == 0)
6930715Sbostic 
7031617Skarels char	*dkname;
7130418Skarels char	*specname;
7237945Sbostic char	tmpfil[] = _PATH_TMP;
7330418Skarels 
7430418Skarels extern	int errno;
7530418Skarels char	namebuf[BBSIZE], *np = namebuf;
7631617Skarels struct	disklabel lab;
7731617Skarels struct	disklabel *readlabel(), *makebootarea();
7830418Skarels char	bootarea[BBSIZE];
7958602Smckusick 
8058602Smckusick #if NUMBOOT > 0
8158602Smckusick int	installboot;	/* non-zero if we should install a boot program */
8258602Smckusick char	*bootbuf;	/* pointer to buffer with remainder of boot prog */
8358602Smckusick int	bootsize;	/* size of remaining boot program */
8458602Smckusick char	*xxboot;	/* primary boot */
8558602Smckusick char	*bootxx;	/* secondary boot */
8634032Skarels char	boot0[MAXPATHLEN];
8734032Skarels char	boot1[MAXPATHLEN];
8858602Smckusick #endif
8930418Skarels 
9058602Smckusick enum	{
9158602Smckusick 	UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT
9258602Smckusick } op = UNSPEC;
9330418Skarels 
9430677Skarels int	rflag;
9530677Skarels 
9634032Skarels #ifdef DEBUG
9734032Skarels int	debug;
9858602Smckusick #define OPTIONS	"BNRWb:ders:w"
9957996Sralph #else
10058602Smckusick #define OPTIONS	"BNRWb:ers:w"
10134032Skarels #endif
10234032Skarels 
10358602Smckusick 
main(argc,argv)10430418Skarels main(argc, argv)
10530418Skarels 	int argc;
10630418Skarels 	char *argv[];
10730418Skarels {
10858602Smckusick 	extern char *optarg;
10934032Skarels 	extern int optind;
11030418Skarels 	register struct disklabel *lp;
11134032Skarels 	FILE *t;
11258602Smckusick 	int ch, f, flag, error = 0;
11358602Smckusick 	char *name = 0;
11430418Skarels 
11558602Smckusick 	while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
11634032Skarels 		switch (ch) {
11758602Smckusick #if NUMBOOT > 0
11858602Smckusick 			case 'B':
11958602Smckusick 				++installboot;
12058602Smckusick 				break;
12158602Smckusick 			case 'b':
12258602Smckusick 				xxboot = optarg;
12358602Smckusick 				break;
12458602Smckusick #if NUMBOOT > 1
12558602Smckusick 			case 's':
12658602Smckusick 				bootxx = optarg;
12758602Smckusick 				break;
12858602Smckusick #endif
12958602Smckusick #endif
13034032Skarels 			case 'N':
13134032Skarels 				if (op != UNSPEC)
13234032Skarels 					usage();
13334032Skarels 				op = NOWRITE;
13434032Skarels 				break;
13530715Sbostic 			case 'R':
13634032Skarels 				if (op != UNSPEC)
13734032Skarels 					usage();
13830715Sbostic 				op = RESTORE;
13930715Sbostic 				break;
14034032Skarels 			case 'W':
14134032Skarels 				if (op != UNSPEC)
14234032Skarels 					usage();
14334032Skarels 				op = WRITEABLE;
14434032Skarels 				break;
14530715Sbostic 			case 'e':
14634032Skarels 				if (op != UNSPEC)
14734032Skarels 					usage();
14830715Sbostic 				op = EDIT;
14930715Sbostic 				break;
15030715Sbostic 			case 'r':
15130715Sbostic 				++rflag;
15230715Sbostic 				break;
15330715Sbostic 			case 'w':
15434032Skarels 				if (op != UNSPEC)
15534032Skarels 					usage();
15630715Sbostic 				op = WRITE;
15730715Sbostic 				break;
15834032Skarels #ifdef DEBUG
15934032Skarels 			case 'd':
16034032Skarels 				debug++;
16134032Skarels 				break;
16234032Skarels #endif
16330715Sbostic 			case '?':
16430715Sbostic 			default:
16530715Sbostic 				usage();
16630715Sbostic 		}
16730715Sbostic 	argc -= optind;
16830715Sbostic 	argv += optind;
16958602Smckusick #if NUMBOOT > 0
17058602Smckusick 	if (installboot) {
17158602Smckusick 		rflag++;
17258602Smckusick 		if (op == UNSPEC)
17358602Smckusick 			op = WRITEBOOT;
17458602Smckusick 	} else {
17558602Smckusick 		if (op == UNSPEC)
17658602Smckusick 			op = READ;
17758602Smckusick 		xxboot = bootxx = 0;
17858602Smckusick 	}
17958602Smckusick #else
18034032Skarels 	if (op == UNSPEC)
18134032Skarels 		op = READ;
18258602Smckusick #endif
18330715Sbostic 	if (argc < 1)
18430715Sbostic 		usage();
18530715Sbostic 
18630715Sbostic 	dkname = argv[0];
18730418Skarels 	if (dkname[0] != '/') {
18865574Sbostic 		(void)sprintf(np, "%sr%s%c", _PATH_DEV, dkname, RAWPARTITION);
18930418Skarels 		specname = np;
19030418Skarels 		np += strlen(specname) + 1;
19130418Skarels 	} else
19230418Skarels 		specname = dkname;
19330418Skarels 	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
19430418Skarels 	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
19565574Sbostic 		(void)sprintf(specname, "%sr%s", _PATH_DEV, dkname);
19630418Skarels 		np = namebuf + strlen(specname) + 1;
19730418Skarels 		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
19830418Skarels 	}
19930418Skarels 	if (f < 0)
20030418Skarels 		Perror(specname);
20130418Skarels 
20230715Sbostic 	switch(op) {
20358602Smckusick 
20430715Sbostic 	case EDIT:
20530715Sbostic 		if (argc != 1)
20630715Sbostic 			usage();
20734032Skarels 		lp = readlabel(f);
20834641Skarels 		error = edit(lp, f);
20930715Sbostic 		break;
21058602Smckusick 
21158602Smckusick 	case NOWRITE:
21258602Smckusick 		flag = 0;
21334032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
21434032Skarels 			Perror("ioctl DIOCWLABEL");
21534032Skarels 		break;
21658602Smckusick 
21730418Skarels 	case READ:
21830715Sbostic 		if (argc != 1)
21930715Sbostic 			usage();
22034032Skarels 		lp = readlabel(f);
22130418Skarels 		display(stdout, lp);
22234641Skarels 		error = checklabel(lp);
22330418Skarels 		break;
22458602Smckusick 
22530715Sbostic 	case RESTORE:
22658602Smckusick #if NUMBOOT > 0
22758602Smckusick 		if (installboot && argc == 3) {
22858602Smckusick 			makelabel(argv[2], 0, &lab);
22958602Smckusick 			argc--;
23034032Skarels 		}
23131617Skarels #endif
23230715Sbostic 		if (argc != 2)
23330715Sbostic 			usage();
23458602Smckusick 		lp = makebootarea(bootarea, &lab, f);
23558602Smckusick 		if (!(t = fopen(argv[1], "r")))
23630715Sbostic 			Perror(argv[1]);
23730715Sbostic 		if (getasciilabel(t, lp))
23834641Skarels 			error = writelabel(f, bootarea, lp);
23930418Skarels 		break;
24058602Smckusick 
24130418Skarels 	case WRITE:
24258602Smckusick 		if (argc == 3) {
24358602Smckusick 			name = argv[2];
24458602Smckusick 			argc--;
24530715Sbostic 		}
24658602Smckusick 		if (argc != 2)
24730715Sbostic 			usage();
24858602Smckusick 		makelabel(argv[1], name, &lab);
24958602Smckusick 		lp = makebootarea(bootarea, &lab, f);
25030418Skarels 		*lp = lab;
25130715Sbostic 		if (checklabel(lp) == 0)
25234641Skarels 			error = writelabel(f, bootarea, lp);
25330418Skarels 		break;
25458602Smckusick 
25558602Smckusick 	case WRITEABLE:
25658602Smckusick 		flag = 1;
25734032Skarels 		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
25834032Skarels 			Perror("ioctl DIOCWLABEL");
25934032Skarels 		break;
26058602Smckusick 
26158602Smckusick #if NUMBOOT > 0
26258602Smckusick 	case WRITEBOOT:
26358602Smckusick 	{
26458602Smckusick 		struct disklabel tlab;
26558602Smckusick 
26658602Smckusick 		lp = readlabel(f);
26758602Smckusick 		tlab = *lp;
26858602Smckusick 		if (argc == 2)
26958602Smckusick 			makelabel(argv[1], 0, &lab);
27058602Smckusick 		lp = makebootarea(bootarea, &lab, f);
27158602Smckusick 		*lp = tlab;
27258602Smckusick 		if (checklabel(lp) == 0)
27358602Smckusick 			error = writelabel(f, bootarea, lp);
27458602Smckusick 		break;
27530418Skarels 	}
27658602Smckusick #endif
27734032Skarels 	}
27834641Skarels 	exit(error);
27930418Skarels }
28030418Skarels 
28134032Skarels /*
28234032Skarels  * Construct a prototype disklabel from /etc/disktab.  As a side
28334032Skarels  * effect, set the names of the primary and secondary boot files
28434032Skarels  * if specified.
28534032Skarels  */
makelabel(type,name,lp)28630418Skarels makelabel(type, name, lp)
28730418Skarels 	char *type, *name;
28830418Skarels 	register struct disklabel *lp;
28930418Skarels {
29030418Skarels 	register struct disklabel *dp;
29134032Skarels 	char *strcpy();
29230418Skarels 
29330418Skarels 	dp = getdiskbyname(type);
29430418Skarels 	if (dp == NULL) {
29530418Skarels 		fprintf(stderr, "%s: unknown disk type\n", type);
29630418Skarels 		exit(1);
29730418Skarels 	}
29830418Skarels 	*lp = *dp;
29958602Smckusick #if NUMBOOT > 0
30034032Skarels 	/*
30158602Smckusick 	 * Set bootstrap name(s).
30258602Smckusick 	 * 1. If set from command line, use those,
30358602Smckusick 	 * 2. otherwise, check if disktab specifies them (b0 or b1),
30458602Smckusick 	 * 3. otherwise, makebootarea() will choose ones based on the name
30558602Smckusick 	 *    of the disk special file. E.g. /dev/ra0 -> raboot, bootra
30634032Skarels 	 */
30734032Skarels 	if (!xxboot && lp->d_boot0) {
30834032Skarels 		if (*lp->d_boot0 != '/')
30958602Smckusick 			(void)sprintf(boot0, "%s/%s",
31058602Smckusick 				      _PATH_BOOTDIR, lp->d_boot0);
31134032Skarels 		else
31234032Skarels 			(void)strcpy(boot0, lp->d_boot0);
31334032Skarels 		xxboot = boot0;
31434032Skarels 	}
31558602Smckusick #if NUMBOOT > 1
31634032Skarels 	if (!bootxx && lp->d_boot1) {
31734032Skarels 		if (*lp->d_boot1 != '/')
31858602Smckusick 			(void)sprintf(boot1, "%s/%s",
31958602Smckusick 				      _PATH_BOOTDIR, lp->d_boot1);
32034032Skarels 		else
32134032Skarels 			(void)strcpy(boot1, lp->d_boot1);
32234032Skarels 		bootxx = boot1;
32334032Skarels 	}
32458602Smckusick #endif
32558602Smckusick #endif
32634032Skarels 	/* d_packname is union d_boot[01], so zero */
32768990Sbostic 	memset(lp->d_packname, 0, sizeof(lp->d_packname));
32830418Skarels 	if (name)
32934032Skarels 		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
33030418Skarels }
33130418Skarels 
writelabel(f,boot,lp)33230418Skarels writelabel(f, boot, lp)
33330418Skarels 	int f;
33430418Skarels 	char *boot;
33530418Skarels 	register struct disklabel *lp;
33630418Skarels {
33730715Sbostic 	register int i;
33834032Skarels 	int flag;
33930418Skarels 
34058602Smckusick 	setbootflag(lp);
34130418Skarels 	lp->d_magic = DISKMAGIC;
34230418Skarels 	lp->d_magic2 = DISKMAGIC;
34330418Skarels 	lp->d_checksum = 0;
34430418Skarels 	lp->d_checksum = dkcksum(lp);
34530677Skarels 	if (rflag) {
34634032Skarels 		/*
34734032Skarels 		 * First set the kernel disk label,
34834032Skarels 		 * then write a label to the raw disk.
34934032Skarels 		 * If the SDINFO ioctl fails because it is unimplemented,
35034032Skarels 		 * keep going; otherwise, the kernel consistency checks
35134032Skarels 		 * may prevent us from changing the current (in-core)
35234032Skarels 		 * label.
35334032Skarels 		 */
35434032Skarels 		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
35534641Skarels 		    errno != ENODEV && errno != ENOTTY) {
35634641Skarels 			l_perror("ioctl DIOCSDINFO");
35734641Skarels 			return (1);
35834641Skarels 		}
35957996Sralph 		(void)lseek(f, (off_t)0, SEEK_SET);
36034032Skarels 		/*
36134032Skarels 		 * write enable label sector before write (if necessary),
36234032Skarels 		 * disable after writing.
36334032Skarels 		 */
36434032Skarels 		flag = 1;
36534032Skarels 		if (ioctl(f, DIOCWLABEL, &flag) < 0)
36634032Skarels 			perror("ioctl DIOCWLABEL");
36734641Skarels 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
36834641Skarels 			perror("write");
36934641Skarels 			return (1);
37034641Skarels 		}
37158602Smckusick #if NUMBOOT > 0
37258602Smckusick 		/*
37358602Smckusick 		 * Output the remainder of the disklabel
37458602Smckusick 		 */
37558602Smckusick 		if (bootbuf && write(f, bootbuf, bootsize) != bootsize) {
37658602Smckusick 			perror("write");
37758602Smckusick 			return(1);
37858602Smckusick 		}
37958602Smckusick #endif
38034032Skarels 		flag = 0;
38134032Skarels 		(void) ioctl(f, DIOCWLABEL, &flag);
38234641Skarels 	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
38334641Skarels 		l_perror("ioctl DIOCWDINFO");
38434641Skarels 		return (1);
38534641Skarels 	}
38634032Skarels #ifdef vax
38730677Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
38830677Skarels 		daddr_t alt;
38930677Skarels 
39030677Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
39130677Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
39257996Sralph 			(void)lseek(f, (off_t)((alt + i) * lp->d_secsize),
39358602Smckusick 			    SEEK_SET);
39430677Skarels 			if (write(f, boot, lp->d_secsize) < lp->d_secsize) {
39530677Skarels 				int oerrno = errno;
39630677Skarels 				fprintf(stderr, "alternate label %d ", i/2);
39730677Skarels 				errno = oerrno;
39830677Skarels 				perror("write");
39930677Skarels 			}
40030418Skarels 		}
40130418Skarels 	}
40230419Skarels #endif
40334641Skarels 	return (0);
40430418Skarels }
40530418Skarels 
l_perror(s)40634641Skarels l_perror(s)
40734641Skarels 	char *s;
40834641Skarels {
40934641Skarels 	int saverrno = errno;
41034641Skarels 
41134641Skarels 	fprintf(stderr, "disklabel: %s: ", s);
41234641Skarels 
41334641Skarels 	switch (saverrno) {
41434641Skarels 
41534641Skarels 	case ESRCH:
41634641Skarels 		fprintf(stderr, "No disk label on disk;\n");
41734641Skarels 		fprintf(stderr,
41834641Skarels 		    "use \"disklabel -r\" to install initial label\n");
41934641Skarels 		break;
42034641Skarels 
42134641Skarels 	case EINVAL:
42234641Skarels 		fprintf(stderr, "Label magic number or checksum is wrong!\n");
42334641Skarels 		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
42434641Skarels 		break;
42534641Skarels 
42634641Skarels 	case EBUSY:
42734641Skarels 		fprintf(stderr, "Open partition would move or shrink\n");
42834641Skarels 		break;
42934641Skarels 
43034641Skarels 	case EXDEV:
43134641Skarels 		fprintf(stderr,
43234641Skarels 	"Labeled partition or 'a' partition must start at beginning of disk\n");
43334641Skarels 		break;
43434641Skarels 
43534641Skarels 	default:
43634641Skarels 		errno = saverrno;
43734641Skarels 		perror((char *)NULL);
43834641Skarels 		break;
43934641Skarels 	}
44034641Skarels }
44134641Skarels 
44230418Skarels /*
44331617Skarels  * Fetch disklabel for disk.
44431617Skarels  * Use ioctl to get label unless -r flag is given.
44530418Skarels  */
44630418Skarels struct disklabel *
readlabel(f)44734032Skarels readlabel(f)
44834032Skarels 	int f;
44930418Skarels {
45030418Skarels 	register struct disklabel *lp;
45130418Skarels 
45234032Skarels 	if (rflag) {
45331617Skarels 		if (read(f, bootarea, BBSIZE) < BBSIZE)
45431401Skarels 			Perror(specname);
45531617Skarels 		for (lp = (struct disklabel *)bootarea;
45631617Skarels 		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
45730677Skarels 		    lp = (struct disklabel *)((char *)lp + 16))
45830677Skarels 			if (lp->d_magic == DISKMAGIC &&
45930677Skarels 			    lp->d_magic2 == DISKMAGIC)
46030677Skarels 				break;
46131617Skarels 		if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) ||
46230677Skarels 		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
46330677Skarels 		    dkcksum(lp) != 0) {
46430677Skarels 			fprintf(stderr,
46530418Skarels 	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
46634032Skarels 			/* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
46734032Skarels 			exit (1);
46830677Skarels 		}
46934032Skarels 	} else {
47034032Skarels 		lp = &lab;
47134032Skarels 		if (ioctl(f, DIOCGDINFO, lp) < 0)
47234032Skarels 			Perror("ioctl DIOCGDINFO");
47330418Skarels 	}
47430418Skarels 	return (lp);
47530418Skarels }
47630418Skarels 
47758602Smckusick /*
47858602Smckusick  * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot''
47958602Smckusick  * Returns a pointer to the disklabel portion of the bootarea.
48058602Smckusick  */
48130418Skarels struct disklabel *
makebootarea(boot,dp,f)48258602Smckusick makebootarea(boot, dp, f)
48330418Skarels 	char *boot;
48430418Skarels 	register struct disklabel *dp;
48558602Smckusick 	int f;
48630418Skarels {
48730418Skarels 	struct disklabel *lp;
48830418Skarels 	register char *p;
48930418Skarels 	int b;
49058602Smckusick #if NUMBOOT > 0
49158602Smckusick 	char *dkbasename;
49258602Smckusick 	struct stat sb;
49358602Smckusick #endif
49430715Sbostic 
49558602Smckusick 	/* XXX */
49658602Smckusick 	if (dp->d_secsize == 0) {
49758602Smckusick 		dp->d_secsize = DEV_BSIZE;
49858602Smckusick 		dp->d_bbsize = BBSIZE;
49958602Smckusick 	}
50058602Smckusick 	lp = (struct disklabel *)
50158602Smckusick 		(boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET);
50268990Sbostic 	memset(lp, 0, sizeof *lp);
50358602Smckusick #if NUMBOOT > 0
50458602Smckusick 	/*
50558602Smckusick 	 * If we are not installing a boot program but we are installing a
50658602Smckusick 	 * label on disk then we must read the current bootarea so we don't
50758602Smckusick 	 * clobber the existing boot.
50858602Smckusick 	 */
50958602Smckusick 	if (!installboot) {
51058602Smckusick 		if (rflag) {
51158602Smckusick 			if (read(f, boot, BBSIZE) < BBSIZE)
51258602Smckusick 				Perror(specname);
51368990Sbostic 			memset(lp, 0, sizeof *lp);
51458602Smckusick 		}
51534032Skarels 		return (lp);
51658602Smckusick 	}
51758602Smckusick 	/*
51858602Smckusick 	 * We are installing a boot program.  Determine the name(s) and
51958602Smckusick 	 * read them into the appropriate places in the boot area.
52058602Smckusick 	 */
52158602Smckusick 	if (!xxboot || !bootxx) {
52230418Skarels 		dkbasename = np;
52368990Sbostic 		if ((p = strrchr(dkname, '/')) == NULL)
52430418Skarels 			p = dkname;
52530418Skarels 		else
52630418Skarels 			p++;
52730418Skarels 		while (*p && !isdigit(*p))
52830418Skarels 			*np++ = *p++;
52930418Skarels 		*np++ = '\0';
53030418Skarels 
53158602Smckusick 		if (!xxboot) {
53258602Smckusick 			(void)sprintf(np, "%s/%sboot",
53358602Smckusick 				      _PATH_BOOTDIR, dkbasename);
53434032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
53534032Skarels 				dkbasename++;
53634032Skarels 			xxboot = np;
53758602Smckusick 			(void)sprintf(xxboot, "%s/%sboot",
53858602Smckusick 				      _PATH_BOOTDIR, dkbasename);
53934032Skarels 			np += strlen(xxboot) + 1;
54034032Skarels 		}
54158602Smckusick #if NUMBOOT > 1
54258602Smckusick 		if (!bootxx) {
54358602Smckusick 			(void)sprintf(np, "%s/boot%s",
54458602Smckusick 				      _PATH_BOOTDIR, dkbasename);
54534032Skarels 			if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
54634032Skarels 				dkbasename++;
54734032Skarels 			bootxx = np;
54858602Smckusick 			(void)sprintf(bootxx, "%s/boot%s",
54958602Smckusick 				      _PATH_BOOTDIR, dkbasename);
55034032Skarels 			np += strlen(bootxx) + 1;
55134032Skarels 		}
55258602Smckusick #endif
55330418Skarels 	}
55434032Skarels #ifdef DEBUG
55534032Skarels 	if (debug)
55634032Skarels 		fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n",
55758602Smckusick 			xxboot, bootxx ? bootxx : "NONE");
55834032Skarels #endif
55930418Skarels 
56058602Smckusick 	/*
56158602Smckusick 	 * Strange rules:
56258602Smckusick 	 * 1. One-piece bootstrap (hp300/hp800)
56358602Smckusick 	 *	up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest
56458602Smckusick 	 *	is remembered and written later following the bootarea.
56558602Smckusick 	 * 2. Two-piece bootstraps (vax/i386?/mips?)
56658602Smckusick 	 *	up to d_secsize bytes of ``xxboot'' go in first d_secsize
56758602Smckusick 	 *	bytes of bootarea, remaining d_bbsize-d_secsize filled
56858602Smckusick 	 *	from ``bootxx''.
56958602Smckusick 	 */
57030418Skarels 	b = open(xxboot, O_RDONLY);
57130418Skarels 	if (b < 0)
57230418Skarels 		Perror(xxboot);
57358602Smckusick #if NUMBOOT > 1
57430715Sbostic 	if (read(b, boot, (int)dp->d_secsize) < 0)
57530418Skarels 		Perror(xxboot);
57658602Smckusick 	(void)close(b);
57730418Skarels 	b = open(bootxx, O_RDONLY);
57830418Skarels 	if (b < 0)
57930418Skarels 		Perror(bootxx);
58030715Sbostic 	if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
58130418Skarels 		Perror(bootxx);
58258602Smckusick #else
58358602Smckusick 	if (read(b, boot, (int)dp->d_bbsize) < 0)
58458602Smckusick 		Perror(xxboot);
58558602Smckusick 	(void)fstat(b, &sb);
58658602Smckusick 	bootsize = (int)sb.st_size - dp->d_bbsize;
58758602Smckusick 	if (bootsize > 0) {
58858602Smckusick 		/* XXX assume d_secsize is a power of two */
58958602Smckusick 		bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1);
59058602Smckusick 		bootbuf = (char *)malloc((size_t)bootsize);
59158602Smckusick 		if (bootbuf == 0)
59258602Smckusick 			Perror(xxboot);
59358602Smckusick 		if (read(b, bootbuf, bootsize) < 0) {
59458602Smckusick 			free(bootbuf);
59558602Smckusick 			Perror(xxboot);
59658602Smckusick 		}
59758602Smckusick 	}
59858602Smckusick #endif
59930715Sbostic 	(void)close(b);
60058602Smckusick #endif
60158602Smckusick 	/*
60258602Smckusick 	 * Make sure no part of the bootstrap is written in the area
60358602Smckusick 	 * reserved for the label.
60458602Smckusick 	 */
60530418Skarels 	for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
60630418Skarels 		if (*p) {
60730418Skarels 			fprintf(stderr,
60830418Skarels 			    "Bootstrap doesn't leave room for disk label\n");
60930418Skarels 			exit(2);
61030418Skarels 		}
61130418Skarels 	return (lp);
61230418Skarels }
61330418Skarels 
display(f,lp)61430418Skarels display(f, lp)
61530418Skarels 	FILE *f;
61630418Skarels 	register struct disklabel *lp;
61730418Skarels {
61830715Sbostic 	register int i, j;
61930418Skarels 	register struct partition *pp;
62030418Skarels 
62130418Skarels 	fprintf(f, "# %s:\n", specname);
62230418Skarels 	if ((unsigned) lp->d_type < DKMAXTYPES)
62330418Skarels 		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
62430418Skarels 	else
62530418Skarels 		fprintf(f, "type: %d\n", lp->d_type);
62630418Skarels 	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
62734032Skarels 	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
62831401Skarels 	fprintf(f, "flags:");
62930418Skarels 	if (lp->d_flags & D_REMOVABLE)
63031401Skarels 		fprintf(f, " removeable");
63130418Skarels 	if (lp->d_flags & D_ECC)
63231401Skarels 		fprintf(f, " ecc");
63330418Skarels 	if (lp->d_flags & D_BADSECT)
63431401Skarels 		fprintf(f, " badsect");
63530418Skarels 	fprintf(f, "\n");
63630418Skarels 	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
63730418Skarels 	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
63830418Skarels 	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
63931386Skarels 	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
64030418Skarels 	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
64130715Sbostic 	fprintf(f, "rpm: %d\n", lp->d_rpm);
64230418Skarels 	fprintf(f, "interleave: %d\n", lp->d_interleave);
64330418Skarels 	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
64430418Skarels 	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
64530418Skarels 	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
64630418Skarels 	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
64730418Skarels 	fprintf(f, "drivedata: ");
64830418Skarels 	for (i = NDDATA - 1; i >= 0; i--)
64930418Skarels 		if (lp->d_drivedata[i])
65030418Skarels 			break;
65130418Skarels 	if (i < 0)
65230418Skarels 		i = 0;
65330418Skarels 	for (j = 0; j <= i; j++)
65430418Skarels 		fprintf(f, "%d ", lp->d_drivedata[j]);
65530418Skarels 	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
65630863Skarels 	fprintf(f,
65730863Skarels 	    "#        size   offset    fstype   [fsize bsize   cpg]\n");
65830418Skarels 	pp = lp->d_partitions;
65930418Skarels 	for (i = 0; i < lp->d_npartitions; i++, pp++) {
66030418Skarels 		if (pp->p_size) {
66130863Skarels 			fprintf(f, "  %c: %8d %8d  ", 'a' + i,
66230863Skarels 			   pp->p_size, pp->p_offset);
66330418Skarels 			if ((unsigned) pp->p_fstype < FSMAXTYPES)
66430418Skarels 				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
66530418Skarels 			else
66630418Skarels 				fprintf(f, "%8d", pp->p_fstype);
66730863Skarels 			switch (pp->p_fstype) {
66830863Skarels 
66930863Skarels 			case FS_UNUSED:				/* XXX */
67030863Skarels 				fprintf(f, "    %5d %5d %5.5s ",
67130863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag, "");
67230863Skarels 				break;
67330863Skarels 
67430863Skarels 			case FS_BSDFFS:
67530863Skarels 				fprintf(f, "    %5d %5d %5d ",
67630863Skarels 				    pp->p_fsize, pp->p_fsize * pp->p_frag,
67730863Skarels 				    pp->p_cpg);
67830863Skarels 				break;
67930863Skarels 
68030863Skarels 			default:
68130863Skarels 				fprintf(f, "%20.20s", "");
68230863Skarels 				break;
68330863Skarels 			}
68430418Skarels 			fprintf(f, "\t# (Cyl. %4d",
68530418Skarels 			    pp->p_offset / lp->d_secpercyl);
68630418Skarels 			if (pp->p_offset % lp->d_secpercyl)
68730418Skarels 			    putc('*', f);
68830418Skarels 			else
68930418Skarels 			    putc(' ', f);
69030418Skarels 			fprintf(f, "- %d",
69130418Skarels 			    (pp->p_offset +
69230418Skarels 			    pp->p_size + lp->d_secpercyl - 1) /
69330418Skarels 			    lp->d_secpercyl - 1);
69430418Skarels 			if (pp->p_size % lp->d_secpercyl)
69530418Skarels 			    putc('*', f);
69630863Skarels 			fprintf(f, ")\n");
69730418Skarels 		}
69830418Skarels 	}
69932121Stef 	fflush(f);
70030418Skarels }
70130418Skarels 
70234641Skarels edit(lp, f)
70330715Sbostic 	struct disklabel *lp;
70434641Skarels 	int f;
70530418Skarels {
70630715Sbostic 	register int c;
70730715Sbostic 	struct disklabel label;
70830715Sbostic 	FILE *fd;
70930715Sbostic 	char *mktemp();
71030715Sbostic 
71130715Sbostic 	(void) mktemp(tmpfil);
71230715Sbostic 	fd = fopen(tmpfil, "w");
71330715Sbostic 	if (fd == NULL) {
71430715Sbostic 		fprintf(stderr, "%s: Can't create\n", tmpfil);
71534641Skarels 		return (1);
71630715Sbostic 	}
71758602Smckusick 	(void)fchmod(fileno(fd), 0600);
71830715Sbostic 	display(fd, lp);
71930715Sbostic 	fclose(fd);
72030715Sbostic 	for (;;) {
72130715Sbostic 		if (!editit())
72230715Sbostic 			break;
72330715Sbostic 		fd = fopen(tmpfil, "r");
72430715Sbostic 		if (fd == NULL) {
72534032Skarels 			fprintf(stderr, "%s: Can't reopen for reading\n",
72634032Skarels 				tmpfil);
72730715Sbostic 			break;
72830715Sbostic 		}
72968990Sbostic 		memset(&label, 0, sizeof(label));
73030715Sbostic 		if (getasciilabel(fd, &label)) {
73130715Sbostic 			*lp = label;
73234641Skarels 			if (writelabel(f, bootarea, lp) == 0) {
73334641Skarels 				(void) unlink(tmpfil);
73434641Skarels 				return (0);
73534641Skarels 			}
73630715Sbostic 		}
73730715Sbostic 		printf("re-edit the label? [y]: "); fflush(stdout);
73830715Sbostic 		c = getchar();
73930715Sbostic 		if (c != EOF && c != (int)'\n')
74030715Sbostic 			while (getchar() != (int)'\n')
74130715Sbostic 				;
74230715Sbostic 		if  (c == (int)'n')
74330715Sbostic 			break;
74430715Sbostic 	}
74530715Sbostic 	(void) unlink(tmpfil);
74634641Skarels 	return (1);
74730418Skarels }
74830418Skarels 
editit()74930715Sbostic editit()
75030715Sbostic {
75130715Sbostic 	register int pid, xpid;
75230715Sbostic 	int stat, omask;
75330715Sbostic 	extern char *getenv();
75430418Skarels 
75530715Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
75630715Sbostic 	while ((pid = fork()) < 0) {
75730715Sbostic 		extern int errno;
75830715Sbostic 
75930715Sbostic 		if (errno == EPROCLIM) {
76030715Sbostic 			fprintf(stderr, "You have too many processes\n");
76130715Sbostic 			return(0);
76230715Sbostic 		}
76330715Sbostic 		if (errno != EAGAIN) {
76430715Sbostic 			perror("fork");
76530715Sbostic 			return(0);
76630715Sbostic 		}
76730715Sbostic 		sleep(1);
76830715Sbostic 	}
76930715Sbostic 	if (pid == 0) {
77030715Sbostic 		register char *ed;
77130715Sbostic 
77230715Sbostic 		sigsetmask(omask);
77330715Sbostic 		setgid(getgid());
77430715Sbostic 		setuid(getuid());
77530715Sbostic 		if ((ed = getenv("EDITOR")) == (char *)0)
77630715Sbostic 			ed = DEFEDITOR;
77730715Sbostic 		execlp(ed, ed, tmpfil, 0);
77830715Sbostic 		perror(ed);
77930715Sbostic 		exit(1);
78030715Sbostic 	}
78130715Sbostic 	while ((xpid = wait(&stat)) >= 0)
78230715Sbostic 		if (xpid == pid)
78330715Sbostic 			break;
78430715Sbostic 	sigsetmask(omask);
78530715Sbostic 	return(!stat);
78630715Sbostic }
78730715Sbostic 
78830715Sbostic char *
skip(cp)78930715Sbostic skip(cp)
79030715Sbostic 	register char *cp;
79130715Sbostic {
79230715Sbostic 
79330715Sbostic 	while (*cp != '\0' && isspace(*cp))
79430715Sbostic 		cp++;
79530715Sbostic 	if (*cp == '\0' || *cp == '#')
79630715Sbostic 		return ((char *)NULL);
79730715Sbostic 	return (cp);
79830715Sbostic }
79930715Sbostic 
80030715Sbostic char *
word(cp)80130715Sbostic word(cp)
80230715Sbostic 	register char *cp;
80330715Sbostic {
80430715Sbostic 	register char c;
80530715Sbostic 
80631401Skarels 	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
80731401Skarels 		cp++;
80830715Sbostic 	if ((c = *cp) != '\0') {
80930715Sbostic 		*cp++ = '\0';
81030715Sbostic 		if (c != '#')
81130715Sbostic 			return (skip(cp));
81230715Sbostic 	}
81330715Sbostic 	return ((char *)NULL);
81430715Sbostic }
81530715Sbostic 
81630418Skarels /*
81730418Skarels  * Read an ascii label in from fd f,
81830418Skarels  * in the same format as that put out by display(),
81930418Skarels  * and fill in lp.
82030418Skarels  */
getasciilabel(f,lp)82130418Skarels getasciilabel(f, lp)
82230715Sbostic 	FILE	*f;
82330418Skarels 	register struct disklabel *lp;
82430418Skarels {
82530715Sbostic 	register char **cpp, *cp;
82630863Skarels 	register struct partition *pp;
82730715Sbostic 	char *tp, *s, line[BUFSIZ];
82830715Sbostic 	int v, lineno = 0, errors = 0;
82930715Sbostic 
83030715Sbostic 	lp->d_bbsize = BBSIZE;				/* XXX */
83130715Sbostic 	lp->d_sbsize = SBSIZE;				/* XXX */
83230715Sbostic 	while (fgets(line, sizeof(line) - 1, f)) {
83330715Sbostic 		lineno++;
83468990Sbostic 		if (cp = strchr(line,'\n'))
83530715Sbostic 			*cp = '\0';
83630715Sbostic 		cp = skip(line);
83730715Sbostic 		if (cp == NULL)
83830715Sbostic 			continue;
83968990Sbostic 		tp = strchr(cp, ':');
84030715Sbostic 		if (tp == NULL) {
84130715Sbostic 			fprintf(stderr, "line %d: syntax error\n", lineno);
84230715Sbostic 			errors++;
84330715Sbostic 			continue;
84430715Sbostic 		}
84530715Sbostic 		*tp++ = '\0', tp = skip(tp);
84630715Sbostic 		if (streq(cp, "type")) {
84730715Sbostic 			if (tp == NULL)
84830715Sbostic 				tp = "unknown";
84930715Sbostic 			cpp = dktypenames;
85030715Sbostic 			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
85130715Sbostic 				if ((s = *cpp) && streq(s, tp)) {
85230715Sbostic 					lp->d_type = cpp - dktypenames;
85330715Sbostic 					goto next;
85430715Sbostic 				}
85530715Sbostic 			v = atoi(tp);
85630715Sbostic 			if ((unsigned)v >= DKMAXTYPES)
85730715Sbostic 				fprintf(stderr, "line %d:%s %d\n", lineno,
85830715Sbostic 				    "Warning, unknown disk type", v);
85930715Sbostic 			lp->d_type = v;
86030715Sbostic 			continue;
86130715Sbostic 		}
86230715Sbostic 		if (streq(cp, "flags")) {
86334032Skarels 			for (v = 0; (cp = tp) && *cp != '\0';) {
86434032Skarels 				tp = word(cp);
86530715Sbostic 				if (streq(cp, "removeable"))
86630715Sbostic 					v |= D_REMOVABLE;
86730715Sbostic 				else if (streq(cp, "ecc"))
86830715Sbostic 					v |= D_ECC;
86930715Sbostic 				else if (streq(cp, "badsect"))
87030715Sbostic 					v |= D_BADSECT;
87130715Sbostic 				else {
87230715Sbostic 					fprintf(stderr,
87330715Sbostic 					    "line %d: %s: bad flag\n",
87430715Sbostic 					    lineno, cp);
87530715Sbostic 					errors++;
87630715Sbostic 				}
87730715Sbostic 			}
87830715Sbostic 			lp->d_flags = v;
87930715Sbostic 			continue;
88030715Sbostic 		}
88130715Sbostic 		if (streq(cp, "drivedata")) {
88230715Sbostic 			register int i;
88330715Sbostic 
88431386Skarels 			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
88530715Sbostic 				lp->d_drivedata[i++] = atoi(cp);
88631386Skarels 				tp = word(cp);
88730715Sbostic 			}
88830715Sbostic 			continue;
88930715Sbostic 		}
89030715Sbostic 		if (sscanf(cp, "%d partitions", &v) == 1) {
89130863Skarels 			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
89230715Sbostic 				fprintf(stderr,
89330715Sbostic 				    "line %d: bad # of partitions\n", lineno);
89430863Skarels 				lp->d_npartitions = MAXPARTITIONS;
89530863Skarels 				errors++;
89630863Skarels 			} else
89730715Sbostic 				lp->d_npartitions = v;
89830715Sbostic 			continue;
89930715Sbostic 		}
90030715Sbostic 		if (tp == NULL)
90130715Sbostic 			tp = "";
90230715Sbostic 		if (streq(cp, "disk")) {
90330715Sbostic 			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
90430715Sbostic 			continue;
90530715Sbostic 		}
90630715Sbostic 		if (streq(cp, "label")) {
90734032Skarels 			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
90830715Sbostic 			continue;
90930715Sbostic 		}
91030715Sbostic 		if (streq(cp, "bytes/sector")) {
91130715Sbostic 			v = atoi(tp);
91230715Sbostic 			if (v <= 0 || (v % 512) != 0) {
91330715Sbostic 				fprintf(stderr,
91430715Sbostic 				    "line %d: %s: bad sector size\n",
91530715Sbostic 				    lineno, tp);
91630715Sbostic 				errors++;
91730715Sbostic 			} else
91830715Sbostic 				lp->d_secsize = v;
91930715Sbostic 			continue;
92030715Sbostic 		}
92130715Sbostic 		if (streq(cp, "sectors/track")) {
92230715Sbostic 			v = atoi(tp);
92330715Sbostic 			if (v <= 0) {
92430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
92530715Sbostic 				    lineno, tp, cp);
92630715Sbostic 				errors++;
92730715Sbostic 			} else
92830715Sbostic 				lp->d_nsectors = v;
92930715Sbostic 			continue;
93030715Sbostic 		}
93131386Skarels 		if (streq(cp, "sectors/cylinder")) {
93231386Skarels 			v = atoi(tp);
93331386Skarels 			if (v <= 0) {
93431386Skarels 				fprintf(stderr, "line %d: %s: bad %s\n",
93531386Skarels 				    lineno, tp, cp);
93631386Skarels 				errors++;
93731386Skarels 			} else
93831386Skarels 				lp->d_secpercyl = v;
93931386Skarels 			continue;
94031386Skarels 		}
94130715Sbostic 		if (streq(cp, "tracks/cylinder")) {
94230715Sbostic 			v = atoi(tp);
94330715Sbostic 			if (v <= 0) {
94430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
94530715Sbostic 				    lineno, tp, cp);
94630715Sbostic 				errors++;
94730715Sbostic 			} else
94830715Sbostic 				lp->d_ntracks = v;
94930715Sbostic 			continue;
95030715Sbostic 		}
95130715Sbostic 		if (streq(cp, "cylinders")) {
95230715Sbostic 			v = atoi(tp);
95330715Sbostic 			if (v <= 0) {
95430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
95530715Sbostic 				    lineno, tp, cp);
95630715Sbostic 				errors++;
95730715Sbostic 			} else
95830715Sbostic 				lp->d_ncylinders = v;
95930715Sbostic 			continue;
96030715Sbostic 		}
96130715Sbostic 		if (streq(cp, "rpm")) {
96230715Sbostic 			v = atoi(tp);
96330715Sbostic 			if (v <= 0) {
96430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
96530715Sbostic 				    lineno, tp, cp);
96630715Sbostic 				errors++;
96730715Sbostic 			} else
96830715Sbostic 				lp->d_rpm = v;
96930715Sbostic 			continue;
97030715Sbostic 		}
97130715Sbostic 		if (streq(cp, "interleave")) {
97230715Sbostic 			v = atoi(tp);
97330715Sbostic 			if (v <= 0) {
97430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
97530715Sbostic 				    lineno, tp, cp);
97630715Sbostic 				errors++;
97730715Sbostic 			} else
97830715Sbostic 				lp->d_interleave = v;
97930715Sbostic 			continue;
98030715Sbostic 		}
98130715Sbostic 		if (streq(cp, "trackskew")) {
98230715Sbostic 			v = atoi(tp);
98330715Sbostic 			if (v < 0) {
98430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
98530715Sbostic 				    lineno, tp, cp);
98630715Sbostic 				errors++;
98730715Sbostic 			} else
98830715Sbostic 				lp->d_trackskew = v;
98930715Sbostic 			continue;
99030715Sbostic 		}
99130715Sbostic 		if (streq(cp, "cylinderskew")) {
99230715Sbostic 			v = atoi(tp);
99330715Sbostic 			if (v < 0) {
99430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
99530715Sbostic 				    lineno, tp, cp);
99630715Sbostic 				errors++;
99730715Sbostic 			} else
99830715Sbostic 				lp->d_cylskew = v;
99930715Sbostic 			continue;
100030715Sbostic 		}
100130715Sbostic 		if (streq(cp, "headswitch")) {
100230715Sbostic 			v = atoi(tp);
100330715Sbostic 			if (v < 0) {
100430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
100530715Sbostic 				    lineno, tp, cp);
100630715Sbostic 				errors++;
100730715Sbostic 			} else
100830715Sbostic 				lp->d_headswitch = v;
100930715Sbostic 			continue;
101030715Sbostic 		}
101130715Sbostic 		if (streq(cp, "track-to-track seek")) {
101230715Sbostic 			v = atoi(tp);
101330715Sbostic 			if (v < 0) {
101430715Sbostic 				fprintf(stderr, "line %d: %s: bad %s\n",
101530715Sbostic 				    lineno, tp, cp);
101630715Sbostic 				errors++;
101730715Sbostic 			} else
101830715Sbostic 				lp->d_trkseek = v;
101930715Sbostic 			continue;
102030715Sbostic 		}
102130715Sbostic 		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
102230863Skarels 			unsigned part = *cp - 'a';
102330715Sbostic 
102430863Skarels 			if (part > lp->d_npartitions) {
102530715Sbostic 				fprintf(stderr,
102630715Sbostic 				    "line %d: bad partition name\n", lineno);
102730715Sbostic 				errors++;
102830715Sbostic 				continue;
102930715Sbostic 			}
103030863Skarels 			pp = &lp->d_partitions[part];
103130863Skarels #define NXTNUM(n) { \
103230863Skarels 	cp = tp, tp = word(cp); \
103330863Skarels 	if (tp == NULL) \
103430863Skarels 		tp = cp; \
103530863Skarels 	(n) = atoi(cp); \
103630863Skarels      }
103730863Skarels 
103830863Skarels 			NXTNUM(v);
103930715Sbostic 			if (v < 0) {
104030715Sbostic 				fprintf(stderr,
104130715Sbostic 				    "line %d: %s: bad partition size\n",
104230715Sbostic 				    lineno, cp);
104330715Sbostic 				errors++;
104430715Sbostic 			} else
104530863Skarels 				pp->p_size = v;
104630863Skarels 			NXTNUM(v);
104730715Sbostic 			if (v < 0) {
104830715Sbostic 				fprintf(stderr,
104930715Sbostic 				    "line %d: %s: bad partition offset\n",
105030715Sbostic 				    lineno, cp);
105130715Sbostic 				errors++;
105230715Sbostic 			} else
105330863Skarels 				pp->p_offset = v;
105430715Sbostic 			cp = tp, tp = word(cp);
105530715Sbostic 			cpp = fstypenames;
105630715Sbostic 			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
105730715Sbostic 				if ((s = *cpp) && streq(s, cp)) {
105830863Skarels 					pp->p_fstype = cpp - fstypenames;
105930863Skarels 					goto gottype;
106030715Sbostic 				}
106134032Skarels 			if (isdigit(*cp))
106234032Skarels 				v = atoi(cp);
106334032Skarels 			else
106434032Skarels 				v = FSMAXTYPES;
106534032Skarels 			if ((unsigned)v >= FSMAXTYPES) {
106630715Sbostic 				fprintf(stderr, "line %d: %s %s\n", lineno,
106730715Sbostic 				    "Warning, unknown filesystem type", cp);
106834032Skarels 				v = FS_UNUSED;
106934032Skarels 			}
107030863Skarels 			pp->p_fstype = v;
107130863Skarels 	gottype:
107230863Skarels 
107330863Skarels 			switch (pp->p_fstype) {
107430863Skarels 
107530863Skarels 			case FS_UNUSED:				/* XXX */
107630863Skarels 				NXTNUM(pp->p_fsize);
107730863Skarels 				if (pp->p_fsize == 0)
107830863Skarels 					break;
107930863Skarels 				NXTNUM(v);
108030863Skarels 				pp->p_frag = v / pp->p_fsize;
108130863Skarels 				break;
108230863Skarels 
108330863Skarels 			case FS_BSDFFS:
108430863Skarels 				NXTNUM(pp->p_fsize);
108530863Skarels 				if (pp->p_fsize == 0)
108630863Skarels 					break;
108730863Skarels 				NXTNUM(v);
108830863Skarels 				pp->p_frag = v / pp->p_fsize;
108930863Skarels 				NXTNUM(pp->p_cpg);
109030863Skarels 				break;
109130863Skarels 
109230863Skarels 			default:
109330863Skarels 				break;
109430863Skarels 			}
109530715Sbostic 			continue;
109630715Sbostic 		}
109730715Sbostic 		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
109830715Sbostic 		    lineno, cp);
109930715Sbostic 		errors++;
110030715Sbostic 	next:
110130715Sbostic 		;
110230715Sbostic 	}
110330715Sbostic 	errors += checklabel(lp);
110430715Sbostic 	return (errors == 0);
110530418Skarels }
110630418Skarels 
110730715Sbostic /*
110830715Sbostic  * Check disklabel for errors and fill in
110930715Sbostic  * derived fields according to supplied values.
111030715Sbostic  */
checklabel(lp)111130715Sbostic checklabel(lp)
111230715Sbostic 	register struct disklabel *lp;
111330418Skarels {
111430715Sbostic 	register struct partition *pp;
111530715Sbostic 	int i, errors = 0;
111630715Sbostic 	char part;
111730418Skarels 
111830715Sbostic 	if (lp->d_secsize == 0) {
111930715Sbostic 		fprintf(stderr, "sector size %d\n", lp->d_secsize);
112030715Sbostic 		return (1);
112130715Sbostic 	}
112230715Sbostic 	if (lp->d_nsectors == 0) {
112330715Sbostic 		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
112430715Sbostic 		return (1);
112530715Sbostic 	}
112630715Sbostic 	if (lp->d_ntracks == 0) {
112730715Sbostic 		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
112830715Sbostic 		return (1);
112930715Sbostic 	}
113030715Sbostic 	if  (lp->d_ncylinders == 0) {
113130715Sbostic 		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
113230715Sbostic 		errors++;
113330715Sbostic 	}
113430715Sbostic 	if (lp->d_rpm == 0)
113558602Smckusick 		Warning("revolutions/minute %d", lp->d_rpm);
113630715Sbostic 	if (lp->d_secpercyl == 0)
113730715Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
113830715Sbostic 	if (lp->d_secperunit == 0)
113930715Sbostic 		lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
114030715Sbostic 	if (lp->d_bbsize == 0) {
114130715Sbostic 		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
114230715Sbostic 		errors++;
114330715Sbostic 	} else if (lp->d_bbsize % lp->d_secsize)
114458602Smckusick 		Warning("boot block size %% sector-size != 0");
114530715Sbostic 	if (lp->d_sbsize == 0) {
114630715Sbostic 		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
114730715Sbostic 		errors++;
114830715Sbostic 	} else if (lp->d_sbsize % lp->d_secsize)
114958602Smckusick 		Warning("super block size %% sector-size != 0");
115030715Sbostic 	if (lp->d_npartitions > MAXPARTITIONS)
115158602Smckusick 		Warning("number of partitions (%d) > MAXPARTITIONS (%d)",
115230715Sbostic 		    lp->d_npartitions, MAXPARTITIONS);
115330715Sbostic 	for (i = 0; i < lp->d_npartitions; i++) {
115430715Sbostic 		part = 'a' + i;
115530715Sbostic 		pp = &lp->d_partitions[i];
115630715Sbostic 		if (pp->p_size == 0 && pp->p_offset != 0)
115758602Smckusick 			Warning("partition %c: size 0, but offset %d",
115830715Sbostic 			    part, pp->p_offset);
115930715Sbostic #ifdef notdef
116030715Sbostic 		if (pp->p_size % lp->d_secpercyl)
116158602Smckusick 			Warning("partition %c: size %% cylinder-size != 0",
116230715Sbostic 			    part);
116330715Sbostic 		if (pp->p_offset % lp->d_secpercyl)
116458602Smckusick 			Warning("partition %c: offset %% cylinder-size != 0",
116530715Sbostic 			    part);
116630715Sbostic #endif
116730715Sbostic 		if (pp->p_offset > lp->d_secperunit) {
116830715Sbostic 			fprintf(stderr,
116930715Sbostic 			    "partition %c: offset past end of unit\n", part);
117030715Sbostic 			errors++;
117130715Sbostic 		}
117230715Sbostic 		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
117330715Sbostic 			fprintf(stderr,
117430715Sbostic 			    "partition %c: partition extends past end of unit\n",
117530715Sbostic 			    part);
117630715Sbostic 			errors++;
117730715Sbostic 		}
117830715Sbostic 	}
117930715Sbostic 	for (; i < MAXPARTITIONS; i++) {
118030715Sbostic 		part = 'a' + i;
118130715Sbostic 		pp = &lp->d_partitions[i];
118230715Sbostic 		if (pp->p_size || pp->p_offset)
118358602Smckusick 			Warning("unused partition %c: size %d offset %d",
118434032Skarels 			    'a' + i, pp->p_size, pp->p_offset);
118530715Sbostic 	}
118630715Sbostic 	return (errors);
118730715Sbostic }
118830715Sbostic 
118958602Smckusick /*
119058602Smckusick  * If we are installing a boot program that doesn't fit in d_bbsize
119158602Smckusick  * we need to mark those partitions that the boot overflows into.
119258602Smckusick  * This allows newfs to prevent creation of a filesystem where it might
119358602Smckusick  * clobber bootstrap code.
119458602Smckusick  */
setbootflag(lp)119558602Smckusick setbootflag(lp)
119658602Smckusick 	register struct disklabel *lp;
119758602Smckusick {
119858602Smckusick 	register struct partition *pp;
119958602Smckusick 	int i, errors = 0;
120058602Smckusick 	char part;
120158602Smckusick 	u_long boffset;
120258602Smckusick 
120358602Smckusick 	if (bootbuf == 0)
120458602Smckusick 		return;
120558602Smckusick 	boffset = bootsize / lp->d_secsize;
120658602Smckusick 	for (i = 0; i < lp->d_npartitions; i++) {
120758602Smckusick 		part = 'a' + i;
120858602Smckusick 		pp = &lp->d_partitions[i];
120958602Smckusick 		if (pp->p_size == 0)
121058602Smckusick 			continue;
121159087Shibler 		if (boffset <= pp->p_offset) {
121259087Shibler 			if (pp->p_fstype == FS_BOOT)
121359087Shibler 				pp->p_fstype = FS_UNUSED;
121459087Shibler 		} else if (pp->p_fstype != FS_BOOT) {
121558602Smckusick 			if (pp->p_fstype != FS_UNUSED) {
121658602Smckusick 				fprintf(stderr,
121759087Shibler 					"boot overlaps used partition %c\n",
121858602Smckusick 					part);
121958602Smckusick 				errors++;
122058602Smckusick 			} else {
122158602Smckusick 				pp->p_fstype = FS_BOOT;
122258602Smckusick 				Warning("boot overlaps partition %c, %s",
122358602Smckusick 					part, "marked as FS_BOOT");
122458602Smckusick 			}
122559087Shibler 		}
122658602Smckusick 	}
122758602Smckusick 	if (errors) {
122858602Smckusick 		fprintf(stderr, "Cannot install boot program\n");
122958602Smckusick 		exit(4);
123058602Smckusick 	}
123158602Smckusick }
123258602Smckusick 
123330715Sbostic /*VARARGS1*/
Warning(fmt,a1,a2,a3,a4,a5)123430715Sbostic Warning(fmt, a1, a2, a3, a4, a5)
123530715Sbostic 	char *fmt;
123630715Sbostic {
123730715Sbostic 
123830715Sbostic 	fprintf(stderr, "Warning, ");
123930715Sbostic 	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
124030715Sbostic 	fprintf(stderr, "\n");
124130715Sbostic }
124230715Sbostic 
Perror(str)124330715Sbostic Perror(str)
124430715Sbostic 	char *str;
124530715Sbostic {
124630715Sbostic 	fputs("disklabel: ", stderr); perror(str);
124730418Skarels 	exit(4);
124830418Skarels }
124930715Sbostic 
usage()125030715Sbostic usage()
125130715Sbostic {
125258602Smckusick #if NUMBOOT > 0
125358602Smckusick 	fprintf(stderr,
125458602Smckusick "%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",
125558602Smckusick "usage: disklabel [-r] disk",
125658602Smckusick 		"(to read label)",
125758602Smckusick "or disklabel -w [-r] disk type [ packid ]",
125858602Smckusick 		"(to write label with existing boot program)",
125958602Smckusick "or disklabel -e [-r] disk",
126058602Smckusick 		"(to edit label)",
126158602Smckusick "or disklabel -R [-r] disk protofile",
126258602Smckusick 		"(to restore label with existing boot program)",
126358602Smckusick #if NUMBOOT > 1
126458602Smckusick "or disklabel -B [ -b boot1 [ -s boot2 ] ] disk [ type ]",
126558602Smckusick 		"(to install boot program with existing label)",
126658602Smckusick "or disklabel -w -B [ -b boot1 [ -s boot2 ] ] disk type [ packid ]",
126758602Smckusick 		"(to write label and boot program)",
126858602Smckusick "or disklabel -R -B [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]",
126958602Smckusick 		"(to restore label and boot program)",
127030715Sbostic #else
127158602Smckusick "or disklabel -B [ -b bootprog ] disk [ type ]",
127258602Smckusick 		"(to install boot program with existing on-disk label)",
127358602Smckusick "or disklabel -w -B [ -b bootprog ] disk type [ packid ]",
127458602Smckusick 		"(to write label and install boot program)",
127558602Smckusick "or disklabel -R -B [ -b bootprog ] disk protofile [ type ]",
127658602Smckusick 		"(to restore label and install boot program)",
127758602Smckusick #endif
127858602Smckusick "or disklabel [-NW] disk",
127958602Smckusick 		"(to write disable/enable label)");
128058602Smckusick #else
128134032Skarels 	fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
128230715Sbostic "usage: disklabel [-r] disk", "(to read label)",
128330715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)",
128430715Sbostic "or disklabel -e [-r] disk", "(to edit label)",
128534032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)",
128634032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)");
128730715Sbostic #endif
128830715Sbostic 	exit(1);
128930715Sbostic }
1290