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