1*30715Sbostic /* 2*30715Sbostic * Copyright (c) 1987 Regents of the University of California. 3*30715Sbostic * All rights reserved. The Berkeley software License Agreement 4*30715Sbostic * specifies the terms and conditions for redistribution. 5*30715Sbostic */ 6*30715Sbostic 730418Skarels #ifndef lint 8*30715Sbostic static char sccsid[] = "@(#)disklabel.c 5.4 (Berkeley) 04/01/87"; 930418Skarels /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 1030418Skarels #endif 1130418Skarels 1230418Skarels #include <stdio.h> 1330418Skarels #include <ctype.h> 1430418Skarels #include <sys/param.h> 15*30715Sbostic #include <sys/signal.h> 1630418Skarels #include <sys/errno.h> 1730418Skarels #include <sys/file.h> 18*30715Sbostic #include <sys/ioctl.h> 1930677Skarels #include <sys/fs.h> 20*30715Sbostic #include <strings.h> 2130418Skarels #define DKTYPENAMES 2230418Skarels #include <sys/disklabel.h> 2330418Skarels 2430418Skarels /* 2530418Skarels * Disklabel: read and write disklabels. 2630418Skarels * The label is usually placed on one of the first sectors of the disk. 2730418Skarels * Many machines (VAX 11/750) also place a bootstrap in the same area, 2830418Skarels * in which case the label is embedded in the bootstrap. 2930418Skarels * The bootstrap source must leave space at the proper offset 3030418Skarels * for the label on such machines. 3130418Skarels */ 3230418Skarels 3330677Skarels #ifdef vax 3430677Skarels #define RAWPARTITION 'c' 3530677Skarels #else 3630677Skarels #define RAWPARTITION 'a' 3730677Skarels #endif 3830677Skarels 3930677Skarels #ifndef BBSIZE 4030418Skarels #define BBSIZE 8192 /* size of boot area, with label */ 4130677Skarels #endif 4230418Skarels 4330418Skarels #ifdef vax 4430418Skarels #define BOOT /* also have bootstrap in "boot area" */ 4530418Skarels #define BOOTDIR "/usr/mdec" /* source of boot binaries */ 4630677Skarels #else 4730677Skarels #ifdef lint 4830677Skarels #define BOOT 4930418Skarels #endif 5030677Skarels #endif 5130418Skarels 52*30715Sbostic #define DEFEDITOR "/usr/ucb/vi" 53*30715Sbostic #define streq(a,b) (strcmp(a,b) == 0) 54*30715Sbostic 5530418Skarels char *dkname; 56*30715Sbostic #ifdef BOOT 5730418Skarels char *xxboot; 5830418Skarels char *bootxx; 59*30715Sbostic #endif 6030418Skarels char *specname; 61*30715Sbostic char tmpfil[] = "/tmp/EdDk.aXXXXXX"; 6230418Skarels char *sprintf(); 6330418Skarels 6430418Skarels extern int errno; 6530418Skarels char namebuf[BBSIZE], *np = namebuf; 6630418Skarels char bootarea[BBSIZE]; 6730418Skarels struct disklabel lab; 6830418Skarels struct disklabel *readlabel(), *getbootarea(); 6930418Skarels 70*30715Sbostic enum { READ, WRITE, EDIT, RESTORE } op = READ; 7130418Skarels 7230677Skarels int rflag; 7330677Skarels 7430418Skarels main(argc, argv) 7530418Skarels int argc; 7630418Skarels char *argv[]; 7730418Skarels { 78*30715Sbostic extern int optind; 7930418Skarels register struct disklabel *lp; 80*30715Sbostic FILE *t; 81*30715Sbostic int ch, f; 82*30715Sbostic char *name = 0, *type; 8330418Skarels 84*30715Sbostic while ((ch = getopt(argc, argv, "Rerw")) != EOF) 85*30715Sbostic switch((char)ch) { 86*30715Sbostic case 'R': 87*30715Sbostic op = RESTORE; 88*30715Sbostic break; 89*30715Sbostic case 'e': 90*30715Sbostic op = EDIT; 91*30715Sbostic break; 92*30715Sbostic case 'r': 93*30715Sbostic ++rflag; 94*30715Sbostic break; 95*30715Sbostic case 'w': 96*30715Sbostic op = WRITE; 97*30715Sbostic break; 98*30715Sbostic case '?': 99*30715Sbostic default: 100*30715Sbostic usage(); 101*30715Sbostic } 102*30715Sbostic argc -= optind; 103*30715Sbostic argv += optind; 104*30715Sbostic if (argc < 1) 105*30715Sbostic usage(); 106*30715Sbostic 107*30715Sbostic dkname = argv[0]; 10830418Skarels if (dkname[0] != '/') { 10930677Skarels sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION); 11030418Skarels specname = np; 11130418Skarels np += strlen(specname) + 1; 11230418Skarels } else 11330418Skarels specname = dkname; 11430418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 11530418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 11630418Skarels sprintf(specname, "/dev/r%s", dkname); 11730418Skarels np = namebuf + strlen(specname) + 1; 11830418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 11930418Skarels } 12030418Skarels if (f < 0) 12130418Skarels Perror(specname); 12230418Skarels 123*30715Sbostic switch(op) { 124*30715Sbostic case EDIT: 125*30715Sbostic if (argc != 1) 126*30715Sbostic usage(); 127*30715Sbostic lp = readlabel(f, bootarea); 128*30715Sbostic if (edit(lp)) 129*30715Sbostic writelabel(f, bootarea, lp); 130*30715Sbostic break; 13130418Skarels case READ: 132*30715Sbostic if (argc != 1) 133*30715Sbostic usage(); 134*30715Sbostic lp = readlabel(f, (char *)0); 13530418Skarels display(stdout, lp); 136*30715Sbostic (void) checklabel(lp); 13730418Skarels break; 138*30715Sbostic case RESTORE: 139*30715Sbostic #ifdef BOOT 140*30715Sbostic if (argc == 4) { 141*30715Sbostic xxboot = argv[2]; 142*30715Sbostic bootxx = argv[3]; 143*30715Sbostic } 144*30715Sbostic else 145*30715Sbostic #else 146*30715Sbostic if (argc != 2) 147*30715Sbostic usage(); 148*30715Sbostic #endif 149*30715Sbostic lab.d_secsize = DEV_BSIZE; /* XXX */ 150*30715Sbostic lab.d_bbsize = BBSIZE; /* XXX */ 151*30715Sbostic lp = getbootarea(bootarea, &lab); 152*30715Sbostic if (!(t = fopen(argv[1],"r"))) 153*30715Sbostic Perror(argv[1]); 154*30715Sbostic if (getasciilabel(t, lp)) 155*30715Sbostic writelabel(f, bootarea, lp); 15630418Skarels break; 15730418Skarels case WRITE: 158*30715Sbostic type = argv[1]; 159*30715Sbostic #ifdef BOOT 160*30715Sbostic if (argc > 5 || argc < 2) 161*30715Sbostic usage(); 162*30715Sbostic if (argc > 3) { 163*30715Sbostic bootxx = argv[--argc]; 164*30715Sbostic xxboot = argv[--argc]; 165*30715Sbostic } 166*30715Sbostic #else 167*30715Sbostic #ifdef FIX_FOR_LATER 168*30715Sbostic if (argc > 3 || argc < 2) 169*30715Sbostic #endif 170*30715Sbostic usage(); 171*30715Sbostic #endif 172*30715Sbostic if (argc > 2) 173*30715Sbostic name = argv[--argc]; 17430418Skarels makelabel(type, name, &lab); 17530418Skarels lp = getbootarea(bootarea, &lab); 17630418Skarels *lp = lab; 177*30715Sbostic if (checklabel(lp) == 0) 178*30715Sbostic writelabel(f, bootarea, lp); 17930418Skarels break; 18030418Skarels } 18130418Skarels exit(0); 18230418Skarels } 18330418Skarels 18430418Skarels makelabel(type, name, lp) 18530418Skarels char *type, *name; 18630418Skarels register struct disklabel *lp; 18730418Skarels { 18830418Skarels register struct disklabel *dp; 18930418Skarels 19030418Skarels dp = getdiskbyname(type); 19130418Skarels if (dp == NULL) { 19230418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 19330418Skarels exit(1); 19430418Skarels } 19530418Skarels *lp = *dp; 19630418Skarels if (name) 197*30715Sbostic (void)strncpy(lp->d_name, name, sizeof(lp->d_name)); 19830418Skarels } 19930418Skarels 20030418Skarels writelabel(f, boot, lp) 20130418Skarels int f; 20230418Skarels char *boot; 20330418Skarels register struct disklabel *lp; 20430418Skarels { 205*30715Sbostic register int i; 206*30715Sbostic long lseek(); 20730418Skarels 20830418Skarels lp->d_magic = DISKMAGIC; 20930418Skarels lp->d_magic2 = DISKMAGIC; 21030418Skarels lp->d_checksum = 0; 21130418Skarels lp->d_checksum = dkcksum(lp); 212*30715Sbostic (void)lseek(f, (off_t)0, L_SET); 21330677Skarels if (rflag) { 21430677Skarels if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 21530677Skarels Perror("write"); 21630677Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 21730677Skarels Perror("ioctl DIOCSDINFO"); 21830677Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) 21930677Skarels Perror("ioctl DIOCWDINFO"); 22030419Skarels #if vax 22130677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 22230677Skarels daddr_t alt; 22330677Skarels 22430677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 22530677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 226*30715Sbostic (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 22730677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 22830677Skarels int oerrno = errno; 22930677Skarels fprintf(stderr, "alternate label %d ", i/2); 23030677Skarels errno = oerrno; 23130677Skarels perror("write"); 23230677Skarels } 23330418Skarels } 23430418Skarels } 23530419Skarels #endif 23630418Skarels } 23730418Skarels 23830418Skarels /* 23930418Skarels * Read disklabel from disk. 24030418Skarels * If boot is given, need bootstrap too. 24130677Skarels * If boot not needed, use ioctl to get label 24230677Skarels * unless -r flag is given. 24330418Skarels */ 24430418Skarels struct disklabel * 24530418Skarels readlabel(f, boot) 24630418Skarels int f; 24730418Skarels char *boot; 24830418Skarels { 24930418Skarels register struct disklabel *lp; 25030677Skarels register char *buf; 25130418Skarels 25230677Skarels if (boot) 25330677Skarels buf = boot; 25430677Skarels else 25530677Skarels buf = bootarea; 25630677Skarels lp = (struct disklabel *)(buf + LABELOFFSET); 25730677Skarels if (rflag == 0 && boot == 0) { 25830677Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 25930677Skarels Perror("ioctl DIOCGDINFO"); 26030677Skarels } else { 26130677Skarels if (read(f, buf, BBSIZE) < BBSIZE) 26230677Skarels Perror(specname); 26330677Skarels for (lp = (struct disklabel *)buf; 26430677Skarels lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp)); 26530677Skarels lp = (struct disklabel *)((char *)lp + 16)) 26630677Skarels if (lp->d_magic == DISKMAGIC && 26730677Skarels lp->d_magic2 == DISKMAGIC) 26830677Skarels break; 26930677Skarels if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) || 27030677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 27130677Skarels dkcksum(lp) != 0) { 27230677Skarels fprintf(stderr, 27330418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 27430677Skarels exit(1); 27530677Skarels } 27630418Skarels } 27730418Skarels return (lp); 27830418Skarels } 27930418Skarels 28030418Skarels struct disklabel * 28130418Skarels getbootarea(boot, dp) 28230418Skarels char *boot; 28330418Skarels register struct disklabel *dp; 28430418Skarels { 28530418Skarels struct disklabel *lp; 28630418Skarels register char *p; 28730418Skarels int b; 28830418Skarels 28930418Skarels #ifdef BOOT 290*30715Sbostic char *dkbasename; 291*30715Sbostic 29230418Skarels if (xxboot == NULL) { 29330418Skarels dkbasename = np; 29430418Skarels if ((p = rindex(dkname, '/')) == NULL) 29530418Skarels p = dkname; 29630418Skarels else 29730418Skarels p++; 29830418Skarels while (*p && !isdigit(*p)) 29930418Skarels *np++ = *p++; 30030418Skarels *np++ = '\0'; 30130418Skarels 30230418Skarels sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 30330418Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 30430418Skarels dkbasename++; 30530418Skarels xxboot = np; 30630418Skarels sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 30730418Skarels np += strlen(xxboot) + 1; 30830418Skarels 30930418Skarels bootxx = np; 31030418Skarels sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 31130418Skarels np += strlen(bootxx) + 1; 31230418Skarels } 31330418Skarels 31430418Skarels b = open(xxboot, O_RDONLY); 31530418Skarels if (b < 0) 31630418Skarels Perror(xxboot); 317*30715Sbostic if (read(b, boot, (int)dp->d_secsize) < 0) 31830418Skarels Perror(xxboot); 31930418Skarels close(b); 32030418Skarels b = open(bootxx, O_RDONLY); 32130418Skarels if (b < 0) 32230418Skarels Perror(bootxx); 323*30715Sbostic if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 32430418Skarels Perror(bootxx); 325*30715Sbostic (void)close(b); 32630418Skarels #endif 32730418Skarels 32830418Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 32930418Skarels LABELOFFSET); 33030418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 33130418Skarels if (*p) { 33230418Skarels fprintf(stderr, 33330418Skarels "Bootstrap doesn't leave room for disk label\n"); 33430418Skarels exit(2); 33530418Skarels } 33630418Skarels return (lp); 33730418Skarels } 33830418Skarels 33930418Skarels display(f, lp) 34030418Skarels FILE *f; 34130418Skarels register struct disklabel *lp; 34230418Skarels { 343*30715Sbostic register int i, j; 34430418Skarels register struct partition *pp; 34530418Skarels 34630418Skarels fprintf(f, "# %s:\n", specname); 34730418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 34830418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 34930418Skarels else 35030418Skarels fprintf(f, "type: %d\n", lp->d_type); 35130418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 35230418Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 35330418Skarels fprintf(f, "flags: "); 35430418Skarels if (lp->d_flags & D_REMOVABLE) 35530418Skarels fprintf(f, "removeable "); 35630418Skarels if (lp->d_flags & D_ECC) 35730418Skarels fprintf(f, "ecc "); 35830418Skarels if (lp->d_flags & D_BADSECT) 35930418Skarels fprintf(f, "badsect "); 36030418Skarels fprintf(f, "\n"); 36130418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 36230418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 36330418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 36430418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 365*30715Sbostic fprintf(f, "rpm: %d\n", lp->d_rpm); 36630418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 36730418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 36830418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 36930418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 37030418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 37130418Skarels fprintf(f, "drivedata: "); 37230418Skarels for (i = NDDATA - 1; i >= 0; i--) 37330418Skarels if (lp->d_drivedata[i]) 37430418Skarels break; 37530418Skarels if (i < 0) 37630418Skarels i = 0; 37730418Skarels for (j = 0; j <= i; j++) 37830418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 37930418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 38030418Skarels fprintf(f, "#\t size offset fstype\n"); 38130418Skarels pp = lp->d_partitions; 38230418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 38330418Skarels fprintf(f, "\t%c: %8d %8d ", 'a' + i, 38430418Skarels pp->p_size, pp->p_offset); 38530418Skarels if (pp->p_size) { 38630418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 38730418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 38830418Skarels else 38930418Skarels fprintf(f, "%8d", pp->p_fstype); 39030418Skarels fprintf(f, "\t# (Cyl. %4d", 39130418Skarels pp->p_offset / lp->d_secpercyl); 39230418Skarels if (pp->p_offset % lp->d_secpercyl) 39330418Skarels putc('*', f); 39430418Skarels else 39530418Skarels putc(' ', f); 39630418Skarels fprintf(f, "- %d", 39730418Skarels (pp->p_offset + 39830418Skarels pp->p_size + lp->d_secpercyl - 1) / 39930418Skarels lp->d_secpercyl - 1); 40030418Skarels if (pp->p_size % lp->d_secpercyl) 40130418Skarels putc('*', f); 40230418Skarels putc(')', f); 40330418Skarels } 40430418Skarels fprintf(f, "\n"); 40530418Skarels } 40630418Skarels } 40730418Skarels 408*30715Sbostic edit(lp) 409*30715Sbostic struct disklabel *lp; 41030418Skarels { 411*30715Sbostic register int c; 412*30715Sbostic struct disklabel label; 413*30715Sbostic FILE *fd; 414*30715Sbostic char *mktemp(); 415*30715Sbostic 416*30715Sbostic (void) mktemp(tmpfil); 417*30715Sbostic fd = fopen(tmpfil, "w"); 418*30715Sbostic if (fd == NULL) { 419*30715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 420*30715Sbostic return (0); 421*30715Sbostic } 422*30715Sbostic (void)fchmod(fd, 0600); 423*30715Sbostic display(fd, lp); 424*30715Sbostic fclose(fd); 425*30715Sbostic for (;;) { 426*30715Sbostic if (!editit()) 427*30715Sbostic break; 428*30715Sbostic fd = fopen(tmpfil, "r"); 429*30715Sbostic if (fd == NULL) { 430*30715Sbostic fprintf(stderr, "%s: Can't reopen for reading\n"); 431*30715Sbostic break; 432*30715Sbostic } 433*30715Sbostic label = *lp; 434*30715Sbostic if (getasciilabel(fd, &label)) { 435*30715Sbostic *lp = label; 436*30715Sbostic (void) unlink(tmpfil); 437*30715Sbostic return (1); 438*30715Sbostic } 439*30715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 440*30715Sbostic c = getchar(); 441*30715Sbostic if (c != EOF && c != (int)'\n') 442*30715Sbostic while (getchar() != (int)'\n') 443*30715Sbostic ; 444*30715Sbostic if (c == (int)'n') 445*30715Sbostic break; 446*30715Sbostic } 447*30715Sbostic (void) unlink(tmpfil); 448*30715Sbostic return (0); 44930418Skarels } 45030418Skarels 451*30715Sbostic editit() 452*30715Sbostic { 453*30715Sbostic register int pid, xpid; 454*30715Sbostic int stat, omask; 455*30715Sbostic extern char *getenv(); 45630418Skarels 457*30715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 458*30715Sbostic while ((pid = fork()) < 0) { 459*30715Sbostic extern int errno; 460*30715Sbostic 461*30715Sbostic if (errno == EPROCLIM) { 462*30715Sbostic fprintf(stderr, "You have too many processes\n"); 463*30715Sbostic return(0); 464*30715Sbostic } 465*30715Sbostic if (errno != EAGAIN) { 466*30715Sbostic perror("fork"); 467*30715Sbostic return(0); 468*30715Sbostic } 469*30715Sbostic sleep(1); 470*30715Sbostic } 471*30715Sbostic if (pid == 0) { 472*30715Sbostic register char *ed; 473*30715Sbostic 474*30715Sbostic sigsetmask(omask); 475*30715Sbostic setgid(getgid()); 476*30715Sbostic setuid(getuid()); 477*30715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 478*30715Sbostic ed = DEFEDITOR; 479*30715Sbostic execlp(ed, ed, tmpfil, 0); 480*30715Sbostic perror(ed); 481*30715Sbostic exit(1); 482*30715Sbostic } 483*30715Sbostic while ((xpid = wait(&stat)) >= 0) 484*30715Sbostic if (xpid == pid) 485*30715Sbostic break; 486*30715Sbostic sigsetmask(omask); 487*30715Sbostic return(!stat); 488*30715Sbostic } 489*30715Sbostic 490*30715Sbostic char * 491*30715Sbostic skip(cp) 492*30715Sbostic register char *cp; 493*30715Sbostic { 494*30715Sbostic 495*30715Sbostic while (*cp != '\0' && isspace(*cp)) 496*30715Sbostic cp++; 497*30715Sbostic if (*cp == '\0' || *cp == '#') 498*30715Sbostic return ((char *)NULL); 499*30715Sbostic return (cp); 500*30715Sbostic } 501*30715Sbostic 502*30715Sbostic char * 503*30715Sbostic word(cp) 504*30715Sbostic register char *cp; 505*30715Sbostic { 506*30715Sbostic register char c; 507*30715Sbostic 508*30715Sbostic while (*cp != '\0' && !isspace(*cp)) 509*30715Sbostic if (*cp++ == '#') 510*30715Sbostic break; 511*30715Sbostic if ((c = *cp) != '\0') { 512*30715Sbostic *cp++ = '\0'; 513*30715Sbostic if (c != '#') 514*30715Sbostic return (skip(cp)); 515*30715Sbostic } 516*30715Sbostic return ((char *)NULL); 517*30715Sbostic } 518*30715Sbostic 51930418Skarels /* 52030418Skarels * Read an ascii label in from fd f, 52130418Skarels * in the same format as that put out by display(), 52230418Skarels * and fill in lp. 52330418Skarels */ 52430418Skarels getasciilabel(f, lp) 525*30715Sbostic FILE *f; 52630418Skarels register struct disklabel *lp; 52730418Skarels { 528*30715Sbostic register char **cpp, *cp; 529*30715Sbostic char *tp, *s, line[BUFSIZ]; 530*30715Sbostic int v, lineno = 0, errors = 0; 531*30715Sbostic 532*30715Sbostic lp->d_bbsize = BBSIZE; /* XXX */ 533*30715Sbostic lp->d_sbsize = SBSIZE; /* XXX */ 534*30715Sbostic while (fgets(line, sizeof(line) - 1, f)) { 535*30715Sbostic lineno++; 536*30715Sbostic if (cp = index(line,'\n')) 537*30715Sbostic *cp = '\0'; 538*30715Sbostic cp = skip(line); 539*30715Sbostic if (cp == NULL) 540*30715Sbostic continue; 541*30715Sbostic tp = index(cp, ':'); 542*30715Sbostic if (tp == NULL) { 543*30715Sbostic fprintf(stderr, "line %d: syntax error\n", lineno); 544*30715Sbostic errors++; 545*30715Sbostic continue; 546*30715Sbostic } 547*30715Sbostic *tp++ = '\0', tp = skip(tp); 548*30715Sbostic if (streq(cp, "type")) { 549*30715Sbostic if (tp == NULL) 550*30715Sbostic tp = "unknown"; 551*30715Sbostic cpp = dktypenames; 552*30715Sbostic for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 553*30715Sbostic if ((s = *cpp) && streq(s, tp)) { 554*30715Sbostic lp->d_type = cpp - dktypenames; 555*30715Sbostic goto next; 556*30715Sbostic } 557*30715Sbostic v = atoi(tp); 558*30715Sbostic if ((unsigned)v >= DKMAXTYPES) 559*30715Sbostic fprintf(stderr, "line %d:%s %d\n", lineno, 560*30715Sbostic "Warning, unknown disk type", v); 561*30715Sbostic lp->d_type = v; 562*30715Sbostic continue; 563*30715Sbostic } 564*30715Sbostic if (streq(cp, "flags")) { 565*30715Sbostic v = 0; 566*30715Sbostic while ((cp = tp) && *cp != '\0') { 567*30715Sbostic if (tp = skip(cp)) { 568*30715Sbostic *tp++ = '\0'; 569*30715Sbostic while (*tp && isspace(*tp)) 570*30715Sbostic tp++; 571*30715Sbostic } 572*30715Sbostic if (streq(cp, "removeable")) 573*30715Sbostic v |= D_REMOVABLE; 574*30715Sbostic else if (streq(cp, "ecc")) 575*30715Sbostic v |= D_ECC; 576*30715Sbostic else if (streq(cp, "badsect")) 577*30715Sbostic v |= D_BADSECT; 578*30715Sbostic else { 579*30715Sbostic fprintf(stderr, 580*30715Sbostic "line %d: %s: bad flag\n", 581*30715Sbostic lineno, cp); 582*30715Sbostic errors++; 583*30715Sbostic } 584*30715Sbostic } 585*30715Sbostic lp->d_flags = v; 586*30715Sbostic continue; 587*30715Sbostic } 588*30715Sbostic if (streq(cp, "drivedata")) { 589*30715Sbostic register int i; 590*30715Sbostic 591*30715Sbostic for (i = 0;(cp = tp) && *cp != '\0' && i < NDDATA;) { 592*30715Sbostic if (tp = skip(cp)) { 593*30715Sbostic *tp++ = '\0'; 594*30715Sbostic while (*tp != '\0' && isspace(*tp)) 595*30715Sbostic tp++; 596*30715Sbostic } 597*30715Sbostic lp->d_drivedata[i++] = atoi(cp); 598*30715Sbostic } 599*30715Sbostic continue; 600*30715Sbostic } 601*30715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 602*30715Sbostic if (v == 0 || (unsigned)v > MAXPARTITIONS) 603*30715Sbostic fprintf(stderr, 604*30715Sbostic "line %d: bad # of partitions\n", lineno); 605*30715Sbostic else 606*30715Sbostic lp->d_npartitions = v; 607*30715Sbostic continue; 608*30715Sbostic } 609*30715Sbostic if (tp == NULL) 610*30715Sbostic tp = ""; 611*30715Sbostic if (streq(cp, "disk")) { 612*30715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 613*30715Sbostic continue; 614*30715Sbostic } 615*30715Sbostic if (streq(cp, "label")) { 616*30715Sbostic strncpy(lp->d_name, tp, sizeof (lp->d_name)); 617*30715Sbostic continue; 618*30715Sbostic } 619*30715Sbostic if (streq(cp, "bytes/sector")) { 620*30715Sbostic v = atoi(tp); 621*30715Sbostic if (v <= 0 || (v % 512) != 0) { 622*30715Sbostic fprintf(stderr, 623*30715Sbostic "line %d: %s: bad sector size\n", 624*30715Sbostic lineno, tp); 625*30715Sbostic errors++; 626*30715Sbostic } else 627*30715Sbostic lp->d_secsize = v; 628*30715Sbostic continue; 629*30715Sbostic } 630*30715Sbostic if (streq(cp, "sectors/track")) { 631*30715Sbostic v = atoi(tp); 632*30715Sbostic if (v <= 0) { 633*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 634*30715Sbostic lineno, tp, cp); 635*30715Sbostic errors++; 636*30715Sbostic } else 637*30715Sbostic lp->d_nsectors = v; 638*30715Sbostic continue; 639*30715Sbostic } 640*30715Sbostic if (streq(cp, "tracks/cylinder")) { 641*30715Sbostic v = atoi(tp); 642*30715Sbostic if (v <= 0) { 643*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 644*30715Sbostic lineno, tp, cp); 645*30715Sbostic errors++; 646*30715Sbostic } else 647*30715Sbostic lp->d_ntracks = v; 648*30715Sbostic continue; 649*30715Sbostic } 650*30715Sbostic if (streq(cp, "cylinders")) { 651*30715Sbostic v = atoi(tp); 652*30715Sbostic if (v <= 0) { 653*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 654*30715Sbostic lineno, tp, cp); 655*30715Sbostic errors++; 656*30715Sbostic } else 657*30715Sbostic lp->d_ncylinders = v; 658*30715Sbostic continue; 659*30715Sbostic } 660*30715Sbostic if (streq(cp, "rpm")) { 661*30715Sbostic v = atoi(tp); 662*30715Sbostic if (v <= 0) { 663*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 664*30715Sbostic lineno, tp, cp); 665*30715Sbostic errors++; 666*30715Sbostic } else 667*30715Sbostic lp->d_rpm = v; 668*30715Sbostic continue; 669*30715Sbostic } 670*30715Sbostic if (streq(cp, "interleave")) { 671*30715Sbostic v = atoi(tp); 672*30715Sbostic if (v <= 0) { 673*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 674*30715Sbostic lineno, tp, cp); 675*30715Sbostic errors++; 676*30715Sbostic } else 677*30715Sbostic lp->d_interleave = v; 678*30715Sbostic continue; 679*30715Sbostic } 680*30715Sbostic if (streq(cp, "trackskew")) { 681*30715Sbostic v = atoi(tp); 682*30715Sbostic if (v < 0) { 683*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 684*30715Sbostic lineno, tp, cp); 685*30715Sbostic errors++; 686*30715Sbostic } else 687*30715Sbostic lp->d_trackskew = v; 688*30715Sbostic continue; 689*30715Sbostic } 690*30715Sbostic if (streq(cp, "cylinderskew")) { 691*30715Sbostic v = atoi(tp); 692*30715Sbostic if (v < 0) { 693*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 694*30715Sbostic lineno, tp, cp); 695*30715Sbostic errors++; 696*30715Sbostic } else 697*30715Sbostic lp->d_cylskew = v; 698*30715Sbostic continue; 699*30715Sbostic } 700*30715Sbostic if (streq(cp, "headswitch")) { 701*30715Sbostic v = atoi(tp); 702*30715Sbostic if (v < 0) { 703*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 704*30715Sbostic lineno, tp, cp); 705*30715Sbostic errors++; 706*30715Sbostic } else 707*30715Sbostic lp->d_headswitch = v; 708*30715Sbostic continue; 709*30715Sbostic } 710*30715Sbostic if (streq(cp, "track-to-track seek")) { 711*30715Sbostic v = atoi(tp); 712*30715Sbostic if (v < 0) { 713*30715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 714*30715Sbostic lineno, tp, cp); 715*30715Sbostic errors++; 716*30715Sbostic } else 717*30715Sbostic lp->d_trkseek = v; 718*30715Sbostic continue; 719*30715Sbostic } 720*30715Sbostic if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 721*30715Sbostic int part = *cp - 'a'; 722*30715Sbostic 723*30715Sbostic if ((unsigned)part > MAXPARTITIONS) { 724*30715Sbostic fprintf(stderr, 725*30715Sbostic "line %d: bad partition name\n", lineno); 726*30715Sbostic errors++; 727*30715Sbostic continue; 728*30715Sbostic } 729*30715Sbostic cp = tp, tp = word(cp); 730*30715Sbostic if (tp == NULL) 731*30715Sbostic tp = cp; 732*30715Sbostic v = atoi(cp); 733*30715Sbostic if (v < 0) { 734*30715Sbostic fprintf(stderr, 735*30715Sbostic "line %d: %s: bad partition size\n", 736*30715Sbostic lineno, cp); 737*30715Sbostic errors++; 738*30715Sbostic } else 739*30715Sbostic lp->d_partitions[part].p_size = v; 740*30715Sbostic cp = tp, tp = word(cp); 741*30715Sbostic if (tp == NULL) 742*30715Sbostic tp = cp; 743*30715Sbostic v = atoi(cp); 744*30715Sbostic if (v < 0) { 745*30715Sbostic fprintf(stderr, 746*30715Sbostic "line %d: %s: bad partition offset\n", 747*30715Sbostic lineno, cp); 748*30715Sbostic errors++; 749*30715Sbostic } else 750*30715Sbostic lp->d_partitions[part].p_offset = v; 751*30715Sbostic cp = tp, tp = word(cp); 752*30715Sbostic cpp = fstypenames; 753*30715Sbostic for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 754*30715Sbostic if ((s = *cpp) && streq(s, cp)) { 755*30715Sbostic lp->d_partitions[part].p_fstype = 756*30715Sbostic cpp - fstypenames; 757*30715Sbostic goto next; 758*30715Sbostic } 759*30715Sbostic v = atoi(cp); 760*30715Sbostic if ((unsigned)v >= FSMAXTYPES) 761*30715Sbostic fprintf(stderr, "line %d: %s %s\n", lineno, 762*30715Sbostic "Warning, unknown filesystem type", cp); 763*30715Sbostic lp->d_partitions[part].p_fstype = v; 764*30715Sbostic continue; 765*30715Sbostic } 766*30715Sbostic fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 767*30715Sbostic lineno, cp); 768*30715Sbostic errors++; 769*30715Sbostic next: 770*30715Sbostic ; 771*30715Sbostic } 772*30715Sbostic errors += checklabel(lp); 773*30715Sbostic return (errors == 0); 77430418Skarels } 77530418Skarels 776*30715Sbostic /* 777*30715Sbostic * Check disklabel for errors and fill in 778*30715Sbostic * derived fields according to supplied values. 779*30715Sbostic */ 780*30715Sbostic checklabel(lp) 781*30715Sbostic register struct disklabel *lp; 78230418Skarels { 783*30715Sbostic register struct partition *pp; 784*30715Sbostic int i, errors = 0; 785*30715Sbostic char part; 78630418Skarels 787*30715Sbostic if (lp->d_secsize == 0) { 788*30715Sbostic fprintf(stderr, "sector size %d\n", lp->d_secsize); 789*30715Sbostic return (1); 790*30715Sbostic } 791*30715Sbostic if (lp->d_nsectors == 0) { 792*30715Sbostic fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 793*30715Sbostic return (1); 794*30715Sbostic } 795*30715Sbostic if (lp->d_ntracks == 0) { 796*30715Sbostic fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 797*30715Sbostic return (1); 798*30715Sbostic } 799*30715Sbostic if (lp->d_ncylinders == 0) { 800*30715Sbostic fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 801*30715Sbostic errors++; 802*30715Sbostic } 803*30715Sbostic if (lp->d_rpm == 0) 804*30715Sbostic Warning("revolutions/minute %d\n", lp->d_rpm); 805*30715Sbostic if (lp->d_secpercyl == 0) 806*30715Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 807*30715Sbostic if (lp->d_secperunit == 0) 808*30715Sbostic lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 809*30715Sbostic if (lp->d_bbsize == 0) { 810*30715Sbostic fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 811*30715Sbostic errors++; 812*30715Sbostic } else if (lp->d_bbsize % lp->d_secsize) 813*30715Sbostic Warning("boot block size %% sector-size != 0\n"); 814*30715Sbostic if (lp->d_sbsize == 0) { 815*30715Sbostic fprintf(stderr, "super block size %d\n", lp->d_sbsize); 816*30715Sbostic errors++; 817*30715Sbostic } else if (lp->d_sbsize % lp->d_secsize) 818*30715Sbostic Warning("super block size %% sector-size != 0\n"); 819*30715Sbostic if (lp->d_npartitions > MAXPARTITIONS) 820*30715Sbostic Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 821*30715Sbostic lp->d_npartitions, MAXPARTITIONS); 822*30715Sbostic for (i = 0; i < lp->d_npartitions; i++) { 823*30715Sbostic part = 'a' + i; 824*30715Sbostic pp = &lp->d_partitions[i]; 825*30715Sbostic if (pp->p_size == 0 && pp->p_offset != 0) 826*30715Sbostic Warning("partition %c: size 0, but offset %d\n", 827*30715Sbostic part, pp->p_offset); 828*30715Sbostic #ifdef notdef 829*30715Sbostic if (pp->p_size % lp->d_secpercyl) 830*30715Sbostic Warning("partition %c: size %% cylinder-size != 0\n", 831*30715Sbostic part); 832*30715Sbostic if (pp->p_offset % lp->d_secpercyl) 833*30715Sbostic Warning("partition %c: offset %% cylinder-size != 0\n", 834*30715Sbostic part); 835*30715Sbostic #endif 836*30715Sbostic if (pp->p_offset > lp->d_secperunit) { 837*30715Sbostic fprintf(stderr, 838*30715Sbostic "partition %c: offset past end of unit\n", part); 839*30715Sbostic errors++; 840*30715Sbostic } 841*30715Sbostic if (pp->p_offset + pp->p_size > lp->d_secperunit) { 842*30715Sbostic fprintf(stderr, 843*30715Sbostic "partition %c: partition extends past end of unit\n", 844*30715Sbostic part); 845*30715Sbostic errors++; 846*30715Sbostic } 847*30715Sbostic } 848*30715Sbostic for (; i < MAXPARTITIONS; i++) { 849*30715Sbostic part = 'a' + i; 850*30715Sbostic pp = &lp->d_partitions[i]; 851*30715Sbostic if (pp->p_size || pp->p_offset) 852*30715Sbostic Warning("unused partition %c: size %d offset %d\n", 853*30715Sbostic pp->p_size, pp->p_offset); 854*30715Sbostic } 855*30715Sbostic return (errors); 856*30715Sbostic } 857*30715Sbostic 858*30715Sbostic /*VARARGS1*/ 859*30715Sbostic Warning(fmt, a1, a2, a3, a4, a5) 860*30715Sbostic char *fmt; 861*30715Sbostic { 862*30715Sbostic 863*30715Sbostic fprintf(stderr, "Warning, "); 864*30715Sbostic fprintf(stderr, fmt, a1, a2, a3, a4, a5); 865*30715Sbostic fprintf(stderr, "\n"); 866*30715Sbostic } 867*30715Sbostic 868*30715Sbostic Perror(str) 869*30715Sbostic char *str; 870*30715Sbostic { 871*30715Sbostic fputs("disklabel: ", stderr); perror(str); 87230418Skarels exit(4); 87330418Skarels } 874*30715Sbostic 875*30715Sbostic usage() 876*30715Sbostic { 877*30715Sbostic #ifdef BOOT 878*30715Sbostic fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n", 879*30715Sbostic "usage: disklabel [-r] disk", "(to read label)", 880*30715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 881*30715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 882*30715Sbostic "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 883*30715Sbostic #else 884*30715Sbostic fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 885*30715Sbostic "usage: disklabel [-r] disk", "(to read label)", 886*30715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 887*30715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 888*30715Sbostic "or disklabel -R [-r] disk protofile", "(to restore label)"); 889*30715Sbostic #endif 890*30715Sbostic exit(1); 891*30715Sbostic } 892