130715Sbostic /* 235983Sbostic * Copyright (c) 1987 The Regents of the University of California. 335983Sbostic * All rights reserved. 435983Sbostic * 535983Sbostic * This code is derived from software contributed to Berkeley by 635983Sbostic * Symmetric Computer Systems. 735983Sbostic * 842698Sbostic * %sccs.include.redist.c% 930715Sbostic */ 1030715Sbostic 1130418Skarels #ifndef lint 1235983Sbostic char copyright[] = 1335983Sbostic "@(#) Copyright (c) 1987 The Regents of the University of California.\n\ 1435983Sbostic All rights reserved.\n"; 1535983Sbostic #endif /* not lint */ 1635983Sbostic 1735983Sbostic #ifndef lint 18*58602Smckusick static char sccsid[] = "@(#)disklabel.c 5.24 (Berkeley) 03/09/93"; 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> 27*58602Smckusick #include <sys/stat.h> 2830418Skarels #define DKTYPENAMES 2930418Skarels #include <sys/disklabel.h> 3051615Sbostic #include <ufs/ffs/fs.h> 3157996Sralph #include <unistd.h> 3251615Sbostic #include <string.h> 3337261Sbostic #include <stdio.h> 3437261Sbostic #include <ctype.h> 3537261Sbostic #include "pathnames.h" 3630418Skarels 3730418Skarels /* 3830418Skarels * Disklabel: read and write disklabels. 3930418Skarels * The label is usually placed on one of the first sectors of the disk. 40*58602Smckusick * Many machines also place a bootstrap in the same area, 4130418Skarels * in which case the label is embedded in the bootstrap. 4230418Skarels * The bootstrap source must leave space at the proper offset 4330418Skarels * for the label on such machines. 4430418Skarels */ 4530418Skarels 46*58602Smckusick #ifdef tahoe 47*58602Smckusick #define RAWPARTITION 'a' 48*58602Smckusick #else 4930677Skarels #define RAWPARTITION 'c' 5030677Skarels #endif 5130677Skarels 5230677Skarels #ifndef BBSIZE 5330418Skarels #define BBSIZE 8192 /* size of boot area, with label */ 5430677Skarels #endif 5530418Skarels 56*58602Smckusick #ifdef tahoe 57*58602Smckusick #define NUMBOOT 0 5830677Skarels #else 59*58602Smckusick #if defined(hp300) || defined(hp800) 60*58602Smckusick #define NUMBOOT 1 61*58602Smckusick #else 62*58602Smckusick #define NUMBOOT 2 6330418Skarels #endif 6430677Skarels #endif 6530418Skarels 6638505Sbostic #define DEFEDITOR _PATH_VI 6730715Sbostic #define streq(a,b) (strcmp(a,b) == 0) 6830715Sbostic 6931617Skarels char *dkname; 7030418Skarels char *specname; 7137945Sbostic char tmpfil[] = _PATH_TMP; 7230418Skarels 7330418Skarels extern int errno; 7430418Skarels char namebuf[BBSIZE], *np = namebuf; 7531617Skarels struct disklabel lab; 7631617Skarels struct disklabel *readlabel(), *makebootarea(); 7730418Skarels char bootarea[BBSIZE]; 78*58602Smckusick 79*58602Smckusick #if NUMBOOT > 0 80*58602Smckusick int installboot; /* non-zero if we should install a boot program */ 81*58602Smckusick char *bootbuf; /* pointer to buffer with remainder of boot prog */ 82*58602Smckusick int bootsize; /* size of remaining boot program */ 83*58602Smckusick char *xxboot; /* primary boot */ 84*58602Smckusick char *bootxx; /* secondary boot */ 8534032Skarels char boot0[MAXPATHLEN]; 8634032Skarels char boot1[MAXPATHLEN]; 87*58602Smckusick #endif 8830418Skarels 89*58602Smckusick enum { 90*58602Smckusick UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT 91*58602Smckusick } op = UNSPEC; 9230418Skarels 9330677Skarels int rflag; 9430677Skarels 9534032Skarels #ifdef DEBUG 9634032Skarels int debug; 97*58602Smckusick #define OPTIONS "BNRWb:ders:w" 9857996Sralph #else 99*58602Smckusick #define OPTIONS "BNRWb:ers:w" 10034032Skarels #endif 10134032Skarels 102*58602Smckusick 10330418Skarels main(argc, argv) 10430418Skarels int argc; 10530418Skarels char *argv[]; 10630418Skarels { 107*58602Smckusick extern char *optarg; 10834032Skarels extern int optind; 10930418Skarels register struct disklabel *lp; 11034032Skarels FILE *t; 111*58602Smckusick int ch, f, flag, error = 0; 112*58602Smckusick char *name = 0; 11330418Skarels 114*58602Smckusick while ((ch = getopt(argc, argv, OPTIONS)) != EOF) 11534032Skarels switch (ch) { 116*58602Smckusick #if NUMBOOT > 0 117*58602Smckusick case 'B': 118*58602Smckusick ++installboot; 119*58602Smckusick break; 120*58602Smckusick case 'b': 121*58602Smckusick xxboot = optarg; 122*58602Smckusick break; 123*58602Smckusick #if NUMBOOT > 1 124*58602Smckusick case 's': 125*58602Smckusick bootxx = optarg; 126*58602Smckusick break; 127*58602Smckusick #endif 128*58602Smckusick #endif 12934032Skarels case 'N': 13034032Skarels if (op != UNSPEC) 13134032Skarels usage(); 13234032Skarels op = NOWRITE; 13334032Skarels break; 13430715Sbostic case 'R': 13534032Skarels if (op != UNSPEC) 13634032Skarels usage(); 13730715Sbostic op = RESTORE; 13830715Sbostic break; 13934032Skarels case 'W': 14034032Skarels if (op != UNSPEC) 14134032Skarels usage(); 14234032Skarels op = WRITEABLE; 14334032Skarels break; 14430715Sbostic case 'e': 14534032Skarels if (op != UNSPEC) 14634032Skarels usage(); 14730715Sbostic op = EDIT; 14830715Sbostic break; 14930715Sbostic case 'r': 15030715Sbostic ++rflag; 15130715Sbostic break; 15230715Sbostic case 'w': 15334032Skarels if (op != UNSPEC) 15434032Skarels usage(); 15530715Sbostic op = WRITE; 15630715Sbostic break; 15734032Skarels #ifdef DEBUG 15834032Skarels case 'd': 15934032Skarels debug++; 16034032Skarels break; 16134032Skarels #endif 16230715Sbostic case '?': 16330715Sbostic default: 16430715Sbostic usage(); 16530715Sbostic } 16630715Sbostic argc -= optind; 16730715Sbostic argv += optind; 168*58602Smckusick #if NUMBOOT > 0 169*58602Smckusick if (installboot) { 170*58602Smckusick rflag++; 171*58602Smckusick if (op == UNSPEC) 172*58602Smckusick op = WRITEBOOT; 173*58602Smckusick } else { 174*58602Smckusick if (op == UNSPEC) 175*58602Smckusick op = READ; 176*58602Smckusick xxboot = bootxx = 0; 177*58602Smckusick } 178*58602Smckusick #else 17934032Skarels if (op == UNSPEC) 18034032Skarels op = READ; 181*58602Smckusick #endif 18230715Sbostic if (argc < 1) 18330715Sbostic usage(); 18430715Sbostic 18530715Sbostic dkname = argv[0]; 18630418Skarels if (dkname[0] != '/') { 18737945Sbostic (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION); 18830418Skarels specname = np; 18930418Skarels np += strlen(specname) + 1; 19030418Skarels } else 19130418Skarels specname = dkname; 19230418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 19330418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 19437945Sbostic (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname); 19530418Skarels np = namebuf + strlen(specname) + 1; 19630418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 19730418Skarels } 19830418Skarels if (f < 0) 19930418Skarels Perror(specname); 20030418Skarels 20130715Sbostic switch(op) { 202*58602Smckusick 20330715Sbostic case EDIT: 20430715Sbostic if (argc != 1) 20530715Sbostic usage(); 20634032Skarels lp = readlabel(f); 20734641Skarels error = edit(lp, f); 20830715Sbostic break; 209*58602Smckusick 210*58602Smckusick case NOWRITE: 211*58602Smckusick flag = 0; 21234032Skarels if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 21334032Skarels Perror("ioctl DIOCWLABEL"); 21434032Skarels break; 215*58602Smckusick 21630418Skarels case READ: 21730715Sbostic if (argc != 1) 21830715Sbostic usage(); 21934032Skarels lp = readlabel(f); 22030418Skarels display(stdout, lp); 22134641Skarels error = checklabel(lp); 22230418Skarels break; 223*58602Smckusick 22430715Sbostic case RESTORE: 225*58602Smckusick #if NUMBOOT > 0 226*58602Smckusick if (installboot && argc == 3) { 227*58602Smckusick makelabel(argv[2], 0, &lab); 228*58602Smckusick argc--; 22934032Skarels } 23031617Skarels #endif 23130715Sbostic if (argc != 2) 23230715Sbostic usage(); 233*58602Smckusick lp = makebootarea(bootarea, &lab, f); 234*58602Smckusick if (!(t = fopen(argv[1], "r"))) 23530715Sbostic Perror(argv[1]); 23630715Sbostic if (getasciilabel(t, lp)) 23734641Skarels error = writelabel(f, bootarea, lp); 23830418Skarels break; 239*58602Smckusick 24030418Skarels case WRITE: 241*58602Smckusick if (argc == 3) { 242*58602Smckusick name = argv[2]; 243*58602Smckusick argc--; 24430715Sbostic } 245*58602Smckusick if (argc != 2) 24630715Sbostic usage(); 247*58602Smckusick makelabel(argv[1], name, &lab); 248*58602Smckusick lp = makebootarea(bootarea, &lab, f); 24930418Skarels *lp = lab; 25030715Sbostic if (checklabel(lp) == 0) 25134641Skarels error = writelabel(f, bootarea, lp); 25230418Skarels break; 253*58602Smckusick 254*58602Smckusick case WRITEABLE: 255*58602Smckusick flag = 1; 25634032Skarels if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 25734032Skarels Perror("ioctl DIOCWLABEL"); 25834032Skarels break; 259*58602Smckusick 260*58602Smckusick #if NUMBOOT > 0 261*58602Smckusick case WRITEBOOT: 262*58602Smckusick { 263*58602Smckusick struct disklabel tlab; 264*58602Smckusick 265*58602Smckusick lp = readlabel(f); 266*58602Smckusick tlab = *lp; 267*58602Smckusick if (argc == 2) 268*58602Smckusick makelabel(argv[1], 0, &lab); 269*58602Smckusick lp = makebootarea(bootarea, &lab, f); 270*58602Smckusick *lp = tlab; 271*58602Smckusick if (checklabel(lp) == 0) 272*58602Smckusick error = writelabel(f, bootarea, lp); 273*58602Smckusick break; 27430418Skarels } 275*58602Smckusick #endif 27634032Skarels } 27734641Skarels exit(error); 27830418Skarels } 27930418Skarels 28034032Skarels /* 28134032Skarels * Construct a prototype disklabel from /etc/disktab. As a side 28234032Skarels * effect, set the names of the primary and secondary boot files 28334032Skarels * if specified. 28434032Skarels */ 28530418Skarels makelabel(type, name, lp) 28630418Skarels char *type, *name; 28730418Skarels register struct disklabel *lp; 28830418Skarels { 28930418Skarels register struct disklabel *dp; 29034032Skarels char *strcpy(); 29130418Skarels 29230418Skarels dp = getdiskbyname(type); 29330418Skarels if (dp == NULL) { 29430418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 29530418Skarels exit(1); 29630418Skarels } 29730418Skarels *lp = *dp; 298*58602Smckusick #if NUMBOOT > 0 29934032Skarels /* 300*58602Smckusick * Set bootstrap name(s). 301*58602Smckusick * 1. If set from command line, use those, 302*58602Smckusick * 2. otherwise, check if disktab specifies them (b0 or b1), 303*58602Smckusick * 3. otherwise, makebootarea() will choose ones based on the name 304*58602Smckusick * of the disk special file. E.g. /dev/ra0 -> raboot, bootra 30534032Skarels */ 30634032Skarels if (!xxboot && lp->d_boot0) { 30734032Skarels if (*lp->d_boot0 != '/') 308*58602Smckusick (void)sprintf(boot0, "%s/%s", 309*58602Smckusick _PATH_BOOTDIR, lp->d_boot0); 31034032Skarels else 31134032Skarels (void)strcpy(boot0, lp->d_boot0); 31234032Skarels xxboot = boot0; 31334032Skarels } 314*58602Smckusick #if NUMBOOT > 1 31534032Skarels if (!bootxx && lp->d_boot1) { 31634032Skarels if (*lp->d_boot1 != '/') 317*58602Smckusick (void)sprintf(boot1, "%s/%s", 318*58602Smckusick _PATH_BOOTDIR, lp->d_boot1); 31934032Skarels else 32034032Skarels (void)strcpy(boot1, lp->d_boot1); 32134032Skarels bootxx = boot1; 32234032Skarels } 323*58602Smckusick #endif 324*58602Smckusick #endif 32534032Skarels /* d_packname is union d_boot[01], so zero */ 32634032Skarels bzero(lp->d_packname, sizeof(lp->d_packname)); 32730418Skarels if (name) 32834032Skarels (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 32930418Skarels } 33030418Skarels 33130418Skarels writelabel(f, boot, lp) 33230418Skarels int f; 33330418Skarels char *boot; 33430418Skarels register struct disklabel *lp; 33530418Skarels { 33630715Sbostic register int i; 33734032Skarels int flag; 33830418Skarels 339*58602Smckusick setbootflag(lp); 34030418Skarels lp->d_magic = DISKMAGIC; 34130418Skarels lp->d_magic2 = DISKMAGIC; 34230418Skarels lp->d_checksum = 0; 34330418Skarels lp->d_checksum = dkcksum(lp); 34430677Skarels if (rflag) { 34534032Skarels /* 34634032Skarels * First set the kernel disk label, 34734032Skarels * then write a label to the raw disk. 34834032Skarels * If the SDINFO ioctl fails because it is unimplemented, 34934032Skarels * keep going; otherwise, the kernel consistency checks 35034032Skarels * may prevent us from changing the current (in-core) 35134032Skarels * label. 35234032Skarels */ 35334032Skarels if (ioctl(f, DIOCSDINFO, lp) < 0 && 35434641Skarels errno != ENODEV && errno != ENOTTY) { 35534641Skarels l_perror("ioctl DIOCSDINFO"); 35634641Skarels return (1); 35734641Skarels } 35857996Sralph (void)lseek(f, (off_t)0, SEEK_SET); 35934032Skarels /* 36034032Skarels * write enable label sector before write (if necessary), 36134032Skarels * disable after writing. 36234032Skarels */ 36334032Skarels flag = 1; 36434032Skarels if (ioctl(f, DIOCWLABEL, &flag) < 0) 36534032Skarels perror("ioctl DIOCWLABEL"); 36634641Skarels if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 36734641Skarels perror("write"); 36834641Skarels return (1); 36934641Skarels } 370*58602Smckusick #if NUMBOOT > 0 371*58602Smckusick /* 372*58602Smckusick * Output the remainder of the disklabel 373*58602Smckusick */ 374*58602Smckusick if (bootbuf && write(f, bootbuf, bootsize) != bootsize) { 375*58602Smckusick perror("write"); 376*58602Smckusick return(1); 377*58602Smckusick } 378*58602Smckusick #endif 37934032Skarels flag = 0; 38034032Skarels (void) ioctl(f, DIOCWLABEL, &flag); 38134641Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 38234641Skarels l_perror("ioctl DIOCWDINFO"); 38334641Skarels return (1); 38434641Skarels } 38534032Skarels #ifdef vax 38630677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 38730677Skarels daddr_t alt; 38830677Skarels 38930677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 39030677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 39157996Sralph (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), 392*58602Smckusick SEEK_SET); 39330677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 39430677Skarels int oerrno = errno; 39530677Skarels fprintf(stderr, "alternate label %d ", i/2); 39630677Skarels errno = oerrno; 39730677Skarels perror("write"); 39830677Skarels } 39930418Skarels } 40030418Skarels } 40130419Skarels #endif 40234641Skarels return (0); 40330418Skarels } 40430418Skarels 40534641Skarels l_perror(s) 40634641Skarels char *s; 40734641Skarels { 40834641Skarels int saverrno = errno; 40934641Skarels 41034641Skarels fprintf(stderr, "disklabel: %s: ", s); 41134641Skarels 41234641Skarels switch (saverrno) { 41334641Skarels 41434641Skarels case ESRCH: 41534641Skarels fprintf(stderr, "No disk label on disk;\n"); 41634641Skarels fprintf(stderr, 41734641Skarels "use \"disklabel -r\" to install initial label\n"); 41834641Skarels break; 41934641Skarels 42034641Skarels case EINVAL: 42134641Skarels fprintf(stderr, "Label magic number or checksum is wrong!\n"); 42234641Skarels fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 42334641Skarels break; 42434641Skarels 42534641Skarels case EBUSY: 42634641Skarels fprintf(stderr, "Open partition would move or shrink\n"); 42734641Skarels break; 42834641Skarels 42934641Skarels case EXDEV: 43034641Skarels fprintf(stderr, 43134641Skarels "Labeled partition or 'a' partition must start at beginning of disk\n"); 43234641Skarels break; 43334641Skarels 43434641Skarels default: 43534641Skarels errno = saverrno; 43634641Skarels perror((char *)NULL); 43734641Skarels break; 43834641Skarels } 43934641Skarels } 44034641Skarels 44130418Skarels /* 44231617Skarels * Fetch disklabel for disk. 44331617Skarels * Use ioctl to get label unless -r flag is given. 44430418Skarels */ 44530418Skarels struct disklabel * 44634032Skarels readlabel(f) 44734032Skarels int f; 44830418Skarels { 44930418Skarels register struct disklabel *lp; 45030418Skarels 45134032Skarels if (rflag) { 45231617Skarels if (read(f, bootarea, BBSIZE) < BBSIZE) 45331401Skarels Perror(specname); 45431617Skarels for (lp = (struct disklabel *)bootarea; 45531617Skarels lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 45630677Skarels lp = (struct disklabel *)((char *)lp + 16)) 45730677Skarels if (lp->d_magic == DISKMAGIC && 45830677Skarels lp->d_magic2 == DISKMAGIC) 45930677Skarels break; 46031617Skarels if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 46130677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 46230677Skarels dkcksum(lp) != 0) { 46330677Skarels fprintf(stderr, 46430418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 46534032Skarels /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */ 46634032Skarels exit (1); 46730677Skarels } 46834032Skarels } else { 46934032Skarels lp = &lab; 47034032Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 47134032Skarels Perror("ioctl DIOCGDINFO"); 47230418Skarels } 47330418Skarels return (lp); 47430418Skarels } 47530418Skarels 476*58602Smckusick /* 477*58602Smckusick * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 478*58602Smckusick * Returns a pointer to the disklabel portion of the bootarea. 479*58602Smckusick */ 48030418Skarels struct disklabel * 481*58602Smckusick makebootarea(boot, dp, f) 48230418Skarels char *boot; 48330418Skarels register struct disklabel *dp; 484*58602Smckusick int f; 48530418Skarels { 48630418Skarels struct disklabel *lp; 48730418Skarels register char *p; 48830418Skarels int b; 489*58602Smckusick #if NUMBOOT > 0 490*58602Smckusick char *dkbasename; 491*58602Smckusick struct stat sb; 492*58602Smckusick #endif 49330715Sbostic 494*58602Smckusick /* XXX */ 495*58602Smckusick if (dp->d_secsize == 0) { 496*58602Smckusick dp->d_secsize = DEV_BSIZE; 497*58602Smckusick dp->d_bbsize = BBSIZE; 498*58602Smckusick } 499*58602Smckusick lp = (struct disklabel *) 500*58602Smckusick (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 501*58602Smckusick bzero((char *)lp, sizeof *lp); 502*58602Smckusick #if NUMBOOT > 0 503*58602Smckusick /* 504*58602Smckusick * If we are not installing a boot program but we are installing a 505*58602Smckusick * label on disk then we must read the current bootarea so we don't 506*58602Smckusick * clobber the existing boot. 507*58602Smckusick */ 508*58602Smckusick if (!installboot) { 509*58602Smckusick if (rflag) { 510*58602Smckusick if (read(f, boot, BBSIZE) < BBSIZE) 511*58602Smckusick Perror(specname); 512*58602Smckusick bzero((char *)lp, sizeof *lp); 513*58602Smckusick } 51434032Skarels return (lp); 515*58602Smckusick } 516*58602Smckusick /* 517*58602Smckusick * We are installing a boot program. Determine the name(s) and 518*58602Smckusick * read them into the appropriate places in the boot area. 519*58602Smckusick */ 520*58602Smckusick if (!xxboot || !bootxx) { 52130418Skarels dkbasename = np; 52230418Skarels if ((p = rindex(dkname, '/')) == NULL) 52330418Skarels p = dkname; 52430418Skarels else 52530418Skarels p++; 52630418Skarels while (*p && !isdigit(*p)) 52730418Skarels *np++ = *p++; 52830418Skarels *np++ = '\0'; 52930418Skarels 530*58602Smckusick if (!xxboot) { 531*58602Smckusick (void)sprintf(np, "%s/%sboot", 532*58602Smckusick _PATH_BOOTDIR, dkbasename); 53334032Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 53434032Skarels dkbasename++; 53534032Skarels xxboot = np; 536*58602Smckusick (void)sprintf(xxboot, "%s/%sboot", 537*58602Smckusick _PATH_BOOTDIR, dkbasename); 53834032Skarels np += strlen(xxboot) + 1; 53934032Skarels } 540*58602Smckusick #if NUMBOOT > 1 541*58602Smckusick if (!bootxx) { 542*58602Smckusick (void)sprintf(np, "%s/boot%s", 543*58602Smckusick _PATH_BOOTDIR, dkbasename); 54434032Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 54534032Skarels dkbasename++; 54634032Skarels bootxx = np; 547*58602Smckusick (void)sprintf(bootxx, "%s/boot%s", 548*58602Smckusick _PATH_BOOTDIR, dkbasename); 54934032Skarels np += strlen(bootxx) + 1; 55034032Skarels } 551*58602Smckusick #endif 55230418Skarels } 55334032Skarels #ifdef DEBUG 55434032Skarels if (debug) 55534032Skarels fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n", 556*58602Smckusick xxboot, bootxx ? bootxx : "NONE"); 55734032Skarels #endif 55830418Skarels 559*58602Smckusick /* 560*58602Smckusick * Strange rules: 561*58602Smckusick * 1. One-piece bootstrap (hp300/hp800) 562*58602Smckusick * up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest 563*58602Smckusick * is remembered and written later following the bootarea. 564*58602Smckusick * 2. Two-piece bootstraps (vax/i386?/mips?) 565*58602Smckusick * up to d_secsize bytes of ``xxboot'' go in first d_secsize 566*58602Smckusick * bytes of bootarea, remaining d_bbsize-d_secsize filled 567*58602Smckusick * from ``bootxx''. 568*58602Smckusick */ 56930418Skarels b = open(xxboot, O_RDONLY); 57030418Skarels if (b < 0) 57130418Skarels Perror(xxboot); 572*58602Smckusick #if NUMBOOT > 1 57330715Sbostic if (read(b, boot, (int)dp->d_secsize) < 0) 57430418Skarels Perror(xxboot); 575*58602Smckusick (void)close(b); 57630418Skarels b = open(bootxx, O_RDONLY); 57730418Skarels if (b < 0) 57830418Skarels Perror(bootxx); 57930715Sbostic if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 58030418Skarels Perror(bootxx); 581*58602Smckusick #else 582*58602Smckusick if (read(b, boot, (int)dp->d_bbsize) < 0) 583*58602Smckusick Perror(xxboot); 584*58602Smckusick (void)fstat(b, &sb); 585*58602Smckusick bootsize = (int)sb.st_size - dp->d_bbsize; 586*58602Smckusick if (bootsize > 0) { 587*58602Smckusick /* XXX assume d_secsize is a power of two */ 588*58602Smckusick bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1); 589*58602Smckusick bootbuf = (char *)malloc((size_t)bootsize); 590*58602Smckusick if (bootbuf == 0) 591*58602Smckusick Perror(xxboot); 592*58602Smckusick if (read(b, bootbuf, bootsize) < 0) { 593*58602Smckusick free(bootbuf); 594*58602Smckusick Perror(xxboot); 595*58602Smckusick } 596*58602Smckusick } 597*58602Smckusick #endif 59830715Sbostic (void)close(b); 599*58602Smckusick #endif 600*58602Smckusick /* 601*58602Smckusick * Make sure no part of the bootstrap is written in the area 602*58602Smckusick * reserved for the label. 603*58602Smckusick */ 60430418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 60530418Skarels if (*p) { 60630418Skarels fprintf(stderr, 60730418Skarels "Bootstrap doesn't leave room for disk label\n"); 60830418Skarels exit(2); 60930418Skarels } 61030418Skarels return (lp); 61130418Skarels } 61230418Skarels 61330418Skarels display(f, lp) 61430418Skarels FILE *f; 61530418Skarels register struct disklabel *lp; 61630418Skarels { 61730715Sbostic register int i, j; 61830418Skarels register struct partition *pp; 61930418Skarels 62030418Skarels fprintf(f, "# %s:\n", specname); 62130418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 62230418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 62330418Skarels else 62430418Skarels fprintf(f, "type: %d\n", lp->d_type); 62530418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 62634032Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname); 62731401Skarels fprintf(f, "flags:"); 62830418Skarels if (lp->d_flags & D_REMOVABLE) 62931401Skarels fprintf(f, " removeable"); 63030418Skarels if (lp->d_flags & D_ECC) 63131401Skarels fprintf(f, " ecc"); 63230418Skarels if (lp->d_flags & D_BADSECT) 63331401Skarels fprintf(f, " badsect"); 63430418Skarels fprintf(f, "\n"); 63530418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 63630418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 63730418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 63831386Skarels fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 63930418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 64030715Sbostic fprintf(f, "rpm: %d\n", lp->d_rpm); 64130418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 64230418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 64330418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 64430418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 64530418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 64630418Skarels fprintf(f, "drivedata: "); 64730418Skarels for (i = NDDATA - 1; i >= 0; i--) 64830418Skarels if (lp->d_drivedata[i]) 64930418Skarels break; 65030418Skarels if (i < 0) 65130418Skarels i = 0; 65230418Skarels for (j = 0; j <= i; j++) 65330418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 65430418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 65530863Skarels fprintf(f, 65630863Skarels "# size offset fstype [fsize bsize cpg]\n"); 65730418Skarels pp = lp->d_partitions; 65830418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 65930418Skarels if (pp->p_size) { 66030863Skarels fprintf(f, " %c: %8d %8d ", 'a' + i, 66130863Skarels pp->p_size, pp->p_offset); 66230418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 66330418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 66430418Skarels else 66530418Skarels fprintf(f, "%8d", pp->p_fstype); 66630863Skarels switch (pp->p_fstype) { 66730863Skarels 66830863Skarels case FS_UNUSED: /* XXX */ 66930863Skarels fprintf(f, " %5d %5d %5.5s ", 67030863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 67130863Skarels break; 67230863Skarels 67330863Skarels case FS_BSDFFS: 67430863Skarels fprintf(f, " %5d %5d %5d ", 67530863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, 67630863Skarels pp->p_cpg); 67730863Skarels break; 67830863Skarels 67930863Skarels default: 68030863Skarels fprintf(f, "%20.20s", ""); 68130863Skarels break; 68230863Skarels } 68330418Skarels fprintf(f, "\t# (Cyl. %4d", 68430418Skarels pp->p_offset / lp->d_secpercyl); 68530418Skarels if (pp->p_offset % lp->d_secpercyl) 68630418Skarels putc('*', f); 68730418Skarels else 68830418Skarels putc(' ', f); 68930418Skarels fprintf(f, "- %d", 69030418Skarels (pp->p_offset + 69130418Skarels pp->p_size + lp->d_secpercyl - 1) / 69230418Skarels lp->d_secpercyl - 1); 69330418Skarels if (pp->p_size % lp->d_secpercyl) 69430418Skarels putc('*', f); 69530863Skarels fprintf(f, ")\n"); 69630418Skarels } 69730418Skarels } 69832121Stef fflush(f); 69930418Skarels } 70030418Skarels 70134641Skarels edit(lp, f) 70230715Sbostic struct disklabel *lp; 70334641Skarels int f; 70430418Skarels { 70530715Sbostic register int c; 70630715Sbostic struct disklabel label; 70730715Sbostic FILE *fd; 70830715Sbostic char *mktemp(); 70930715Sbostic 71030715Sbostic (void) mktemp(tmpfil); 71130715Sbostic fd = fopen(tmpfil, "w"); 71230715Sbostic if (fd == NULL) { 71330715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 71434641Skarels return (1); 71530715Sbostic } 716*58602Smckusick (void)fchmod(fileno(fd), 0600); 71730715Sbostic display(fd, lp); 71830715Sbostic fclose(fd); 71930715Sbostic for (;;) { 72030715Sbostic if (!editit()) 72130715Sbostic break; 72230715Sbostic fd = fopen(tmpfil, "r"); 72330715Sbostic if (fd == NULL) { 72434032Skarels fprintf(stderr, "%s: Can't reopen for reading\n", 72534032Skarels tmpfil); 72630715Sbostic break; 72730715Sbostic } 72830863Skarels bzero((char *)&label, sizeof(label)); 72930715Sbostic if (getasciilabel(fd, &label)) { 73030715Sbostic *lp = label; 73134641Skarels if (writelabel(f, bootarea, lp) == 0) { 73234641Skarels (void) unlink(tmpfil); 73334641Skarels return (0); 73434641Skarels } 73530715Sbostic } 73630715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 73730715Sbostic c = getchar(); 73830715Sbostic if (c != EOF && c != (int)'\n') 73930715Sbostic while (getchar() != (int)'\n') 74030715Sbostic ; 74130715Sbostic if (c == (int)'n') 74230715Sbostic break; 74330715Sbostic } 74430715Sbostic (void) unlink(tmpfil); 74534641Skarels return (1); 74630418Skarels } 74730418Skarels 74830715Sbostic editit() 74930715Sbostic { 75030715Sbostic register int pid, xpid; 75130715Sbostic int stat, omask; 75230715Sbostic extern char *getenv(); 75330418Skarels 75430715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 75530715Sbostic while ((pid = fork()) < 0) { 75630715Sbostic extern int errno; 75730715Sbostic 75830715Sbostic if (errno == EPROCLIM) { 75930715Sbostic fprintf(stderr, "You have too many processes\n"); 76030715Sbostic return(0); 76130715Sbostic } 76230715Sbostic if (errno != EAGAIN) { 76330715Sbostic perror("fork"); 76430715Sbostic return(0); 76530715Sbostic } 76630715Sbostic sleep(1); 76730715Sbostic } 76830715Sbostic if (pid == 0) { 76930715Sbostic register char *ed; 77030715Sbostic 77130715Sbostic sigsetmask(omask); 77230715Sbostic setgid(getgid()); 77330715Sbostic setuid(getuid()); 77430715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 77530715Sbostic ed = DEFEDITOR; 77630715Sbostic execlp(ed, ed, tmpfil, 0); 77730715Sbostic perror(ed); 77830715Sbostic exit(1); 77930715Sbostic } 78030715Sbostic while ((xpid = wait(&stat)) >= 0) 78130715Sbostic if (xpid == pid) 78230715Sbostic break; 78330715Sbostic sigsetmask(omask); 78430715Sbostic return(!stat); 78530715Sbostic } 78630715Sbostic 78730715Sbostic char * 78830715Sbostic skip(cp) 78930715Sbostic register char *cp; 79030715Sbostic { 79130715Sbostic 79230715Sbostic while (*cp != '\0' && isspace(*cp)) 79330715Sbostic cp++; 79430715Sbostic if (*cp == '\0' || *cp == '#') 79530715Sbostic return ((char *)NULL); 79630715Sbostic return (cp); 79730715Sbostic } 79830715Sbostic 79930715Sbostic char * 80030715Sbostic word(cp) 80130715Sbostic register char *cp; 80230715Sbostic { 80330715Sbostic register char c; 80430715Sbostic 80531401Skarels while (*cp != '\0' && !isspace(*cp) && *cp != '#') 80631401Skarels cp++; 80730715Sbostic if ((c = *cp) != '\0') { 80830715Sbostic *cp++ = '\0'; 80930715Sbostic if (c != '#') 81030715Sbostic return (skip(cp)); 81130715Sbostic } 81230715Sbostic return ((char *)NULL); 81330715Sbostic } 81430715Sbostic 81530418Skarels /* 81630418Skarels * Read an ascii label in from fd f, 81730418Skarels * in the same format as that put out by display(), 81830418Skarels * and fill in lp. 81930418Skarels */ 82030418Skarels getasciilabel(f, lp) 82130715Sbostic FILE *f; 82230418Skarels register struct disklabel *lp; 82330418Skarels { 82430715Sbostic register char **cpp, *cp; 82530863Skarels register struct partition *pp; 82630715Sbostic char *tp, *s, line[BUFSIZ]; 82730715Sbostic int v, lineno = 0, errors = 0; 82830715Sbostic 82930715Sbostic lp->d_bbsize = BBSIZE; /* XXX */ 83030715Sbostic lp->d_sbsize = SBSIZE; /* XXX */ 83130715Sbostic while (fgets(line, sizeof(line) - 1, f)) { 83230715Sbostic lineno++; 83330715Sbostic if (cp = index(line,'\n')) 83430715Sbostic *cp = '\0'; 83530715Sbostic cp = skip(line); 83630715Sbostic if (cp == NULL) 83730715Sbostic continue; 83830715Sbostic tp = index(cp, ':'); 83930715Sbostic if (tp == NULL) { 84030715Sbostic fprintf(stderr, "line %d: syntax error\n", lineno); 84130715Sbostic errors++; 84230715Sbostic continue; 84330715Sbostic } 84430715Sbostic *tp++ = '\0', tp = skip(tp); 84530715Sbostic if (streq(cp, "type")) { 84630715Sbostic if (tp == NULL) 84730715Sbostic tp = "unknown"; 84830715Sbostic cpp = dktypenames; 84930715Sbostic for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 85030715Sbostic if ((s = *cpp) && streq(s, tp)) { 85130715Sbostic lp->d_type = cpp - dktypenames; 85230715Sbostic goto next; 85330715Sbostic } 85430715Sbostic v = atoi(tp); 85530715Sbostic if ((unsigned)v >= DKMAXTYPES) 85630715Sbostic fprintf(stderr, "line %d:%s %d\n", lineno, 85730715Sbostic "Warning, unknown disk type", v); 85830715Sbostic lp->d_type = v; 85930715Sbostic continue; 86030715Sbostic } 86130715Sbostic if (streq(cp, "flags")) { 86234032Skarels for (v = 0; (cp = tp) && *cp != '\0';) { 86334032Skarels tp = word(cp); 86430715Sbostic if (streq(cp, "removeable")) 86530715Sbostic v |= D_REMOVABLE; 86630715Sbostic else if (streq(cp, "ecc")) 86730715Sbostic v |= D_ECC; 86830715Sbostic else if (streq(cp, "badsect")) 86930715Sbostic v |= D_BADSECT; 87030715Sbostic else { 87130715Sbostic fprintf(stderr, 87230715Sbostic "line %d: %s: bad flag\n", 87330715Sbostic lineno, cp); 87430715Sbostic errors++; 87530715Sbostic } 87630715Sbostic } 87730715Sbostic lp->d_flags = v; 87830715Sbostic continue; 87930715Sbostic } 88030715Sbostic if (streq(cp, "drivedata")) { 88130715Sbostic register int i; 88230715Sbostic 88331386Skarels for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 88430715Sbostic lp->d_drivedata[i++] = atoi(cp); 88531386Skarels tp = word(cp); 88630715Sbostic } 88730715Sbostic continue; 88830715Sbostic } 88930715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 89030863Skarels if (v == 0 || (unsigned)v > MAXPARTITIONS) { 89130715Sbostic fprintf(stderr, 89230715Sbostic "line %d: bad # of partitions\n", lineno); 89330863Skarels lp->d_npartitions = MAXPARTITIONS; 89430863Skarels errors++; 89530863Skarels } else 89630715Sbostic lp->d_npartitions = v; 89730715Sbostic continue; 89830715Sbostic } 89930715Sbostic if (tp == NULL) 90030715Sbostic tp = ""; 90130715Sbostic if (streq(cp, "disk")) { 90230715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 90330715Sbostic continue; 90430715Sbostic } 90530715Sbostic if (streq(cp, "label")) { 90634032Skarels strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 90730715Sbostic continue; 90830715Sbostic } 90930715Sbostic if (streq(cp, "bytes/sector")) { 91030715Sbostic v = atoi(tp); 91130715Sbostic if (v <= 0 || (v % 512) != 0) { 91230715Sbostic fprintf(stderr, 91330715Sbostic "line %d: %s: bad sector size\n", 91430715Sbostic lineno, tp); 91530715Sbostic errors++; 91630715Sbostic } else 91730715Sbostic lp->d_secsize = v; 91830715Sbostic continue; 91930715Sbostic } 92030715Sbostic if (streq(cp, "sectors/track")) { 92130715Sbostic v = atoi(tp); 92230715Sbostic if (v <= 0) { 92330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 92430715Sbostic lineno, tp, cp); 92530715Sbostic errors++; 92630715Sbostic } else 92730715Sbostic lp->d_nsectors = v; 92830715Sbostic continue; 92930715Sbostic } 93031386Skarels if (streq(cp, "sectors/cylinder")) { 93131386Skarels v = atoi(tp); 93231386Skarels if (v <= 0) { 93331386Skarels fprintf(stderr, "line %d: %s: bad %s\n", 93431386Skarels lineno, tp, cp); 93531386Skarels errors++; 93631386Skarels } else 93731386Skarels lp->d_secpercyl = v; 93831386Skarels continue; 93931386Skarels } 94030715Sbostic if (streq(cp, "tracks/cylinder")) { 94130715Sbostic v = atoi(tp); 94230715Sbostic if (v <= 0) { 94330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 94430715Sbostic lineno, tp, cp); 94530715Sbostic errors++; 94630715Sbostic } else 94730715Sbostic lp->d_ntracks = v; 94830715Sbostic continue; 94930715Sbostic } 95030715Sbostic if (streq(cp, "cylinders")) { 95130715Sbostic v = atoi(tp); 95230715Sbostic if (v <= 0) { 95330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 95430715Sbostic lineno, tp, cp); 95530715Sbostic errors++; 95630715Sbostic } else 95730715Sbostic lp->d_ncylinders = v; 95830715Sbostic continue; 95930715Sbostic } 96030715Sbostic if (streq(cp, "rpm")) { 96130715Sbostic v = atoi(tp); 96230715Sbostic if (v <= 0) { 96330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 96430715Sbostic lineno, tp, cp); 96530715Sbostic errors++; 96630715Sbostic } else 96730715Sbostic lp->d_rpm = v; 96830715Sbostic continue; 96930715Sbostic } 97030715Sbostic if (streq(cp, "interleave")) { 97130715Sbostic v = atoi(tp); 97230715Sbostic if (v <= 0) { 97330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 97430715Sbostic lineno, tp, cp); 97530715Sbostic errors++; 97630715Sbostic } else 97730715Sbostic lp->d_interleave = v; 97830715Sbostic continue; 97930715Sbostic } 98030715Sbostic if (streq(cp, "trackskew")) { 98130715Sbostic v = atoi(tp); 98230715Sbostic if (v < 0) { 98330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 98430715Sbostic lineno, tp, cp); 98530715Sbostic errors++; 98630715Sbostic } else 98730715Sbostic lp->d_trackskew = v; 98830715Sbostic continue; 98930715Sbostic } 99030715Sbostic if (streq(cp, "cylinderskew")) { 99130715Sbostic v = atoi(tp); 99230715Sbostic if (v < 0) { 99330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 99430715Sbostic lineno, tp, cp); 99530715Sbostic errors++; 99630715Sbostic } else 99730715Sbostic lp->d_cylskew = v; 99830715Sbostic continue; 99930715Sbostic } 100030715Sbostic if (streq(cp, "headswitch")) { 100130715Sbostic v = atoi(tp); 100230715Sbostic if (v < 0) { 100330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 100430715Sbostic lineno, tp, cp); 100530715Sbostic errors++; 100630715Sbostic } else 100730715Sbostic lp->d_headswitch = v; 100830715Sbostic continue; 100930715Sbostic } 101030715Sbostic if (streq(cp, "track-to-track seek")) { 101130715Sbostic v = atoi(tp); 101230715Sbostic if (v < 0) { 101330715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 101430715Sbostic lineno, tp, cp); 101530715Sbostic errors++; 101630715Sbostic } else 101730715Sbostic lp->d_trkseek = v; 101830715Sbostic continue; 101930715Sbostic } 102030715Sbostic if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 102130863Skarels unsigned part = *cp - 'a'; 102230715Sbostic 102330863Skarels if (part > lp->d_npartitions) { 102430715Sbostic fprintf(stderr, 102530715Sbostic "line %d: bad partition name\n", lineno); 102630715Sbostic errors++; 102730715Sbostic continue; 102830715Sbostic } 102930863Skarels pp = &lp->d_partitions[part]; 103030863Skarels #define NXTNUM(n) { \ 103130863Skarels cp = tp, tp = word(cp); \ 103230863Skarels if (tp == NULL) \ 103330863Skarels tp = cp; \ 103430863Skarels (n) = atoi(cp); \ 103530863Skarels } 103630863Skarels 103730863Skarels NXTNUM(v); 103830715Sbostic if (v < 0) { 103930715Sbostic fprintf(stderr, 104030715Sbostic "line %d: %s: bad partition size\n", 104130715Sbostic lineno, cp); 104230715Sbostic errors++; 104330715Sbostic } else 104430863Skarels pp->p_size = v; 104530863Skarels NXTNUM(v); 104630715Sbostic if (v < 0) { 104730715Sbostic fprintf(stderr, 104830715Sbostic "line %d: %s: bad partition offset\n", 104930715Sbostic lineno, cp); 105030715Sbostic errors++; 105130715Sbostic } else 105230863Skarels pp->p_offset = v; 105330715Sbostic cp = tp, tp = word(cp); 105430715Sbostic cpp = fstypenames; 105530715Sbostic for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 105630715Sbostic if ((s = *cpp) && streq(s, cp)) { 105730863Skarels pp->p_fstype = cpp - fstypenames; 105830863Skarels goto gottype; 105930715Sbostic } 106034032Skarels if (isdigit(*cp)) 106134032Skarels v = atoi(cp); 106234032Skarels else 106334032Skarels v = FSMAXTYPES; 106434032Skarels if ((unsigned)v >= FSMAXTYPES) { 106530715Sbostic fprintf(stderr, "line %d: %s %s\n", lineno, 106630715Sbostic "Warning, unknown filesystem type", cp); 106734032Skarels v = FS_UNUSED; 106834032Skarels } 106930863Skarels pp->p_fstype = v; 107030863Skarels gottype: 107130863Skarels 107230863Skarels switch (pp->p_fstype) { 107330863Skarels 107430863Skarels case FS_UNUSED: /* XXX */ 107530863Skarels NXTNUM(pp->p_fsize); 107630863Skarels if (pp->p_fsize == 0) 107730863Skarels break; 107830863Skarels NXTNUM(v); 107930863Skarels pp->p_frag = v / pp->p_fsize; 108030863Skarels break; 108130863Skarels 108230863Skarels case FS_BSDFFS: 108330863Skarels NXTNUM(pp->p_fsize); 108430863Skarels if (pp->p_fsize == 0) 108530863Skarels break; 108630863Skarels NXTNUM(v); 108730863Skarels pp->p_frag = v / pp->p_fsize; 108830863Skarels NXTNUM(pp->p_cpg); 108930863Skarels break; 109030863Skarels 109130863Skarels default: 109230863Skarels break; 109330863Skarels } 109430715Sbostic continue; 109530715Sbostic } 109630715Sbostic fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 109730715Sbostic lineno, cp); 109830715Sbostic errors++; 109930715Sbostic next: 110030715Sbostic ; 110130715Sbostic } 110230715Sbostic errors += checklabel(lp); 110330715Sbostic return (errors == 0); 110430418Skarels } 110530418Skarels 110630715Sbostic /* 110730715Sbostic * Check disklabel for errors and fill in 110830715Sbostic * derived fields according to supplied values. 110930715Sbostic */ 111030715Sbostic checklabel(lp) 111130715Sbostic register struct disklabel *lp; 111230418Skarels { 111330715Sbostic register struct partition *pp; 111430715Sbostic int i, errors = 0; 111530715Sbostic char part; 111630418Skarels 111730715Sbostic if (lp->d_secsize == 0) { 111830715Sbostic fprintf(stderr, "sector size %d\n", lp->d_secsize); 111930715Sbostic return (1); 112030715Sbostic } 112130715Sbostic if (lp->d_nsectors == 0) { 112230715Sbostic fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 112330715Sbostic return (1); 112430715Sbostic } 112530715Sbostic if (lp->d_ntracks == 0) { 112630715Sbostic fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 112730715Sbostic return (1); 112830715Sbostic } 112930715Sbostic if (lp->d_ncylinders == 0) { 113030715Sbostic fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 113130715Sbostic errors++; 113230715Sbostic } 113330715Sbostic if (lp->d_rpm == 0) 1134*58602Smckusick Warning("revolutions/minute %d", lp->d_rpm); 113530715Sbostic if (lp->d_secpercyl == 0) 113630715Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 113730715Sbostic if (lp->d_secperunit == 0) 113830715Sbostic lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 113930715Sbostic if (lp->d_bbsize == 0) { 114030715Sbostic fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 114130715Sbostic errors++; 114230715Sbostic } else if (lp->d_bbsize % lp->d_secsize) 1143*58602Smckusick Warning("boot block size %% sector-size != 0"); 114430715Sbostic if (lp->d_sbsize == 0) { 114530715Sbostic fprintf(stderr, "super block size %d\n", lp->d_sbsize); 114630715Sbostic errors++; 114730715Sbostic } else if (lp->d_sbsize % lp->d_secsize) 1148*58602Smckusick Warning("super block size %% sector-size != 0"); 114930715Sbostic if (lp->d_npartitions > MAXPARTITIONS) 1150*58602Smckusick Warning("number of partitions (%d) > MAXPARTITIONS (%d)", 115130715Sbostic lp->d_npartitions, MAXPARTITIONS); 115230715Sbostic for (i = 0; i < lp->d_npartitions; i++) { 115330715Sbostic part = 'a' + i; 115430715Sbostic pp = &lp->d_partitions[i]; 115530715Sbostic if (pp->p_size == 0 && pp->p_offset != 0) 1156*58602Smckusick Warning("partition %c: size 0, but offset %d", 115730715Sbostic part, pp->p_offset); 115830715Sbostic #ifdef notdef 115930715Sbostic if (pp->p_size % lp->d_secpercyl) 1160*58602Smckusick Warning("partition %c: size %% cylinder-size != 0", 116130715Sbostic part); 116230715Sbostic if (pp->p_offset % lp->d_secpercyl) 1163*58602Smckusick Warning("partition %c: offset %% cylinder-size != 0", 116430715Sbostic part); 116530715Sbostic #endif 116630715Sbostic if (pp->p_offset > lp->d_secperunit) { 116730715Sbostic fprintf(stderr, 116830715Sbostic "partition %c: offset past end of unit\n", part); 116930715Sbostic errors++; 117030715Sbostic } 117130715Sbostic if (pp->p_offset + pp->p_size > lp->d_secperunit) { 117230715Sbostic fprintf(stderr, 117330715Sbostic "partition %c: partition extends past end of unit\n", 117430715Sbostic part); 117530715Sbostic errors++; 117630715Sbostic } 117730715Sbostic } 117830715Sbostic for (; i < MAXPARTITIONS; i++) { 117930715Sbostic part = 'a' + i; 118030715Sbostic pp = &lp->d_partitions[i]; 118130715Sbostic if (pp->p_size || pp->p_offset) 1182*58602Smckusick Warning("unused partition %c: size %d offset %d", 118334032Skarels 'a' + i, pp->p_size, pp->p_offset); 118430715Sbostic } 118530715Sbostic return (errors); 118630715Sbostic } 118730715Sbostic 1188*58602Smckusick /* 1189*58602Smckusick * If we are installing a boot program that doesn't fit in d_bbsize 1190*58602Smckusick * we need to mark those partitions that the boot overflows into. 1191*58602Smckusick * This allows newfs to prevent creation of a filesystem where it might 1192*58602Smckusick * clobber bootstrap code. 1193*58602Smckusick */ 1194*58602Smckusick setbootflag(lp) 1195*58602Smckusick register struct disklabel *lp; 1196*58602Smckusick { 1197*58602Smckusick register struct partition *pp; 1198*58602Smckusick int i, errors = 0; 1199*58602Smckusick char part; 1200*58602Smckusick u_long boffset; 1201*58602Smckusick 1202*58602Smckusick if (bootbuf == 0) 1203*58602Smckusick return; 1204*58602Smckusick boffset = bootsize / lp->d_secsize; 1205*58602Smckusick for (i = 0; i < lp->d_npartitions; i++) { 1206*58602Smckusick part = 'a' + i; 1207*58602Smckusick pp = &lp->d_partitions[i]; 1208*58602Smckusick if (pp->p_size == 0) 1209*58602Smckusick continue; 1210*58602Smckusick if (boffset > pp->p_offset && pp->p_fstype != FS_BOOT) { 1211*58602Smckusick if (pp->p_fstype != FS_UNUSED) { 1212*58602Smckusick fprintf(stderr, 1213*58602Smckusick "boot overlaps used partition %c\n", 1214*58602Smckusick part); 1215*58602Smckusick errors++; 1216*58602Smckusick } else { 1217*58602Smckusick pp->p_fstype = FS_BOOT; 1218*58602Smckusick Warning("boot overlaps partition %c, %s", 1219*58602Smckusick part, "marked as FS_BOOT"); 1220*58602Smckusick } 1221*58602Smckusick } else if (pp->p_fstype == FS_BOOT) 1222*58602Smckusick pp->p_fstype = FS_UNUSED; 1223*58602Smckusick } 1224*58602Smckusick if (errors) { 1225*58602Smckusick fprintf(stderr, "Cannot install boot program\n"); 1226*58602Smckusick exit(4); 1227*58602Smckusick } 1228*58602Smckusick } 1229*58602Smckusick 123030715Sbostic /*VARARGS1*/ 123130715Sbostic Warning(fmt, a1, a2, a3, a4, a5) 123230715Sbostic char *fmt; 123330715Sbostic { 123430715Sbostic 123530715Sbostic fprintf(stderr, "Warning, "); 123630715Sbostic fprintf(stderr, fmt, a1, a2, a3, a4, a5); 123730715Sbostic fprintf(stderr, "\n"); 123830715Sbostic } 123930715Sbostic 124030715Sbostic Perror(str) 124130715Sbostic char *str; 124230715Sbostic { 124330715Sbostic fputs("disklabel: ", stderr); perror(str); 124430418Skarels exit(4); 124530418Skarels } 124630715Sbostic 124730715Sbostic usage() 124830715Sbostic { 1249*58602Smckusick #if NUMBOOT > 0 1250*58602Smckusick fprintf(stderr, 1251*58602Smckusick "%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", 1252*58602Smckusick "usage: disklabel [-r] disk", 1253*58602Smckusick "(to read label)", 1254*58602Smckusick "or disklabel -w [-r] disk type [ packid ]", 1255*58602Smckusick "(to write label with existing boot program)", 1256*58602Smckusick "or disklabel -e [-r] disk", 1257*58602Smckusick "(to edit label)", 1258*58602Smckusick "or disklabel -R [-r] disk protofile", 1259*58602Smckusick "(to restore label with existing boot program)", 1260*58602Smckusick #if NUMBOOT > 1 1261*58602Smckusick "or disklabel -B [ -b boot1 [ -s boot2 ] ] disk [ type ]", 1262*58602Smckusick "(to install boot program with existing label)", 1263*58602Smckusick "or disklabel -w -B [ -b boot1 [ -s boot2 ] ] disk type [ packid ]", 1264*58602Smckusick "(to write label and boot program)", 1265*58602Smckusick "or disklabel -R -B [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]", 1266*58602Smckusick "(to restore label and boot program)", 126730715Sbostic #else 1268*58602Smckusick "or disklabel -B [ -b bootprog ] disk [ type ]", 1269*58602Smckusick "(to install boot program with existing on-disk label)", 1270*58602Smckusick "or disklabel -w -B [ -b bootprog ] disk type [ packid ]", 1271*58602Smckusick "(to write label and install boot program)", 1272*58602Smckusick "or disklabel -R -B [ -b bootprog ] disk protofile [ type ]", 1273*58602Smckusick "(to restore label and install boot program)", 1274*58602Smckusick #endif 1275*58602Smckusick "or disklabel [-NW] disk", 1276*58602Smckusick "(to write disable/enable label)"); 1277*58602Smckusick #else 127834032Skarels fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 127930715Sbostic "usage: disklabel [-r] disk", "(to read label)", 128030715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 128130715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 128234032Skarels "or disklabel -R [-r] disk protofile", "(to restore label)", 128334032Skarels "or disklabel [-NW] disk", "(to write disable/enable label)"); 128430715Sbostic #endif 128530715Sbostic exit(1); 128630715Sbostic } 1287