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