130715Sbostic /* 230715Sbostic * Copyright (c) 1987 Regents of the University of California. 330715Sbostic * All rights reserved. The Berkeley software License Agreement 430715Sbostic * specifies the terms and conditions for redistribution. 530715Sbostic */ 630715Sbostic 730418Skarels #ifndef lint 8*30863Skarels static char sccsid[] = "@(#)disklabel.c 5.6 (Berkeley) 04/07/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> 1530715Sbostic #include <sys/signal.h> 1630418Skarels #include <sys/errno.h> 1730418Skarels #include <sys/file.h> 1830715Sbostic #include <sys/ioctl.h> 1930677Skarels #include <sys/fs.h> 2030715Sbostic #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 5230715Sbostic #define DEFEDITOR "/usr/ucb/vi" 5330715Sbostic #define streq(a,b) (strcmp(a,b) == 0) 5430715Sbostic 5530418Skarels char *dkname; 5630715Sbostic #ifdef BOOT 5730418Skarels char *xxboot; 5830418Skarels char *bootxx; 5930715Sbostic #endif 6030418Skarels char *specname; 6130715Sbostic 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 7030715Sbostic enum { READ, WRITE, EDIT, RESTORE } op = READ; 7130418Skarels 7230677Skarels int rflag; 7330677Skarels 7430418Skarels main(argc, argv) 7530418Skarels int argc; 7630418Skarels char *argv[]; 7730418Skarels { 7830715Sbostic extern int optind; 7930418Skarels register struct disklabel *lp; 8030715Sbostic FILE *t; 8130715Sbostic int ch, f; 8230715Sbostic char *name = 0, *type; 8330418Skarels 8430715Sbostic while ((ch = getopt(argc, argv, "Rerw")) != EOF) 8530715Sbostic switch((char)ch) { 8630715Sbostic case 'R': 8730715Sbostic op = RESTORE; 8830715Sbostic break; 8930715Sbostic case 'e': 9030715Sbostic op = EDIT; 9130715Sbostic break; 9230715Sbostic case 'r': 9330715Sbostic ++rflag; 9430715Sbostic break; 9530715Sbostic case 'w': 9630715Sbostic op = WRITE; 9730715Sbostic break; 9830715Sbostic case '?': 9930715Sbostic default: 10030715Sbostic usage(); 10130715Sbostic } 10230715Sbostic argc -= optind; 10330715Sbostic argv += optind; 10430715Sbostic if (argc < 1) 10530715Sbostic usage(); 10630715Sbostic 10730715Sbostic 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 12330715Sbostic switch(op) { 12430715Sbostic case EDIT: 12530715Sbostic if (argc != 1) 12630715Sbostic usage(); 12730715Sbostic lp = readlabel(f, bootarea); 12830715Sbostic if (edit(lp)) 12930715Sbostic writelabel(f, bootarea, lp); 13030715Sbostic break; 13130418Skarels case READ: 13230715Sbostic if (argc != 1) 13330715Sbostic usage(); 13430715Sbostic lp = readlabel(f, (char *)0); 13530418Skarels display(stdout, lp); 13630715Sbostic (void) checklabel(lp); 13730418Skarels break; 13830715Sbostic case RESTORE: 13930715Sbostic #ifdef BOOT 14030715Sbostic if (argc == 4) { 14130715Sbostic xxboot = argv[2]; 14230715Sbostic bootxx = argv[3]; 14330715Sbostic } 14430715Sbostic else 14530715Sbostic #else 14630715Sbostic if (argc != 2) 14730715Sbostic usage(); 14830715Sbostic #endif 14930715Sbostic lab.d_secsize = DEV_BSIZE; /* XXX */ 15030715Sbostic lab.d_bbsize = BBSIZE; /* XXX */ 15130715Sbostic lp = getbootarea(bootarea, &lab); 15230715Sbostic if (!(t = fopen(argv[1],"r"))) 15330715Sbostic Perror(argv[1]); 15430715Sbostic if (getasciilabel(t, lp)) 15530715Sbostic writelabel(f, bootarea, lp); 15630418Skarels break; 15730418Skarels case WRITE: 15830715Sbostic type = argv[1]; 15930715Sbostic #ifdef BOOT 16030715Sbostic if (argc > 5 || argc < 2) 16130715Sbostic usage(); 16230715Sbostic if (argc > 3) { 16330715Sbostic bootxx = argv[--argc]; 16430715Sbostic xxboot = argv[--argc]; 16530715Sbostic } 16630715Sbostic #else 16730715Sbostic if (argc > 3 || argc < 2) 16830715Sbostic usage(); 16930715Sbostic #endif 17030715Sbostic if (argc > 2) 17130715Sbostic name = argv[--argc]; 17230418Skarels makelabel(type, name, &lab); 17330418Skarels lp = getbootarea(bootarea, &lab); 17430418Skarels *lp = lab; 17530715Sbostic if (checklabel(lp) == 0) 17630715Sbostic writelabel(f, bootarea, lp); 17730418Skarels break; 17830418Skarels } 17930418Skarels exit(0); 18030418Skarels } 18130418Skarels 18230418Skarels makelabel(type, name, lp) 18330418Skarels char *type, *name; 18430418Skarels register struct disklabel *lp; 18530418Skarels { 18630418Skarels register struct disklabel *dp; 18730418Skarels 18830418Skarels dp = getdiskbyname(type); 18930418Skarels if (dp == NULL) { 19030418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 19130418Skarels exit(1); 19230418Skarels } 19330418Skarels *lp = *dp; 19430418Skarels if (name) 19530715Sbostic (void)strncpy(lp->d_name, name, sizeof(lp->d_name)); 19630418Skarels } 19730418Skarels 19830418Skarels writelabel(f, boot, lp) 19930418Skarels int f; 20030418Skarels char *boot; 20130418Skarels register struct disklabel *lp; 20230418Skarels { 20330715Sbostic register int i; 20430715Sbostic long lseek(); 20530418Skarels 20630418Skarels lp->d_magic = DISKMAGIC; 20730418Skarels lp->d_magic2 = DISKMAGIC; 20830418Skarels lp->d_checksum = 0; 20930418Skarels lp->d_checksum = dkcksum(lp); 21030715Sbostic (void)lseek(f, (off_t)0, L_SET); 21130677Skarels if (rflag) { 21230677Skarels if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 21330677Skarels Perror("write"); 21430677Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 21530677Skarels Perror("ioctl DIOCSDINFO"); 21630677Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) 21730677Skarels Perror("ioctl DIOCWDINFO"); 21830419Skarels #if vax 21930677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 22030677Skarels daddr_t alt; 22130677Skarels 22230677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 22330677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 22430715Sbostic (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 22530677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 22630677Skarels int oerrno = errno; 22730677Skarels fprintf(stderr, "alternate label %d ", i/2); 22830677Skarels errno = oerrno; 22930677Skarels perror("write"); 23030677Skarels } 23130418Skarels } 23230418Skarels } 23330419Skarels #endif 23430418Skarels } 23530418Skarels 23630418Skarels /* 23730418Skarels * Read disklabel from disk. 23830418Skarels * If boot is given, need bootstrap too. 23930677Skarels * If boot not needed, use ioctl to get label 24030677Skarels * unless -r flag is given. 24130418Skarels */ 24230418Skarels struct disklabel * 24330418Skarels readlabel(f, boot) 24430418Skarels int f; 24530418Skarels char *boot; 24630418Skarels { 24730418Skarels register struct disklabel *lp; 24830677Skarels register char *buf; 24930418Skarels 25030677Skarels if (boot) 25130677Skarels buf = boot; 25230677Skarels else 25330677Skarels buf = bootarea; 25430677Skarels lp = (struct disklabel *)(buf + LABELOFFSET); 25530677Skarels if (rflag == 0 && boot == 0) { 25630677Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 25730677Skarels Perror("ioctl DIOCGDINFO"); 25830677Skarels } else { 25930677Skarels if (read(f, buf, BBSIZE) < BBSIZE) 26030677Skarels Perror(specname); 26130677Skarels for (lp = (struct disklabel *)buf; 26230677Skarels lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp)); 26330677Skarels lp = (struct disklabel *)((char *)lp + 16)) 26430677Skarels if (lp->d_magic == DISKMAGIC && 26530677Skarels lp->d_magic2 == DISKMAGIC) 26630677Skarels break; 26730677Skarels if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) || 26830677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 26930677Skarels dkcksum(lp) != 0) { 27030677Skarels fprintf(stderr, 27130418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 27230677Skarels exit(1); 27330677Skarels } 27430418Skarels } 27530418Skarels return (lp); 27630418Skarels } 27730418Skarels 27830418Skarels struct disklabel * 27930418Skarels getbootarea(boot, dp) 28030418Skarels char *boot; 28130418Skarels register struct disklabel *dp; 28230418Skarels { 28330418Skarels struct disklabel *lp; 28430418Skarels register char *p; 28530418Skarels int b; 28630418Skarels 28730418Skarels #ifdef BOOT 28830715Sbostic char *dkbasename; 28930715Sbostic 29030418Skarels if (xxboot == NULL) { 29130418Skarels dkbasename = np; 29230418Skarels if ((p = rindex(dkname, '/')) == NULL) 29330418Skarels p = dkname; 29430418Skarels else 29530418Skarels p++; 29630418Skarels while (*p && !isdigit(*p)) 29730418Skarels *np++ = *p++; 29830418Skarels *np++ = '\0'; 29930418Skarels 30030418Skarels sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 30130418Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 30230418Skarels dkbasename++; 30330418Skarels xxboot = np; 30430418Skarels sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 30530418Skarels np += strlen(xxboot) + 1; 30630418Skarels 30730418Skarels bootxx = np; 30830418Skarels sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 30930418Skarels np += strlen(bootxx) + 1; 31030418Skarels } 31130418Skarels 31230418Skarels b = open(xxboot, O_RDONLY); 31330418Skarels if (b < 0) 31430418Skarels Perror(xxboot); 31530715Sbostic if (read(b, boot, (int)dp->d_secsize) < 0) 31630418Skarels Perror(xxboot); 31730418Skarels close(b); 31830418Skarels b = open(bootxx, O_RDONLY); 31930418Skarels if (b < 0) 32030418Skarels Perror(bootxx); 32130715Sbostic if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 32230418Skarels Perror(bootxx); 32330715Sbostic (void)close(b); 32430418Skarels #endif 32530418Skarels 32630418Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 32730418Skarels LABELOFFSET); 32830418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 32930418Skarels if (*p) { 33030418Skarels fprintf(stderr, 33130418Skarels "Bootstrap doesn't leave room for disk label\n"); 33230418Skarels exit(2); 33330418Skarels } 33430418Skarels return (lp); 33530418Skarels } 33630418Skarels 33730418Skarels display(f, lp) 33830418Skarels FILE *f; 33930418Skarels register struct disklabel *lp; 34030418Skarels { 34130715Sbostic register int i, j; 34230418Skarels register struct partition *pp; 34330418Skarels 34430418Skarels fprintf(f, "# %s:\n", specname); 34530418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 34630418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 34730418Skarels else 34830418Skarels fprintf(f, "type: %d\n", lp->d_type); 34930418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 35030418Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 35130418Skarels fprintf(f, "flags: "); 35230418Skarels if (lp->d_flags & D_REMOVABLE) 35330418Skarels fprintf(f, "removeable "); 35430418Skarels if (lp->d_flags & D_ECC) 35530418Skarels fprintf(f, "ecc "); 35630418Skarels if (lp->d_flags & D_BADSECT) 35730418Skarels fprintf(f, "badsect "); 35830418Skarels fprintf(f, "\n"); 35930418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 36030418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 36130418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 36230418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 36330715Sbostic fprintf(f, "rpm: %d\n", lp->d_rpm); 36430418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 36530418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 36630418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 36730418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 36830418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 36930418Skarels fprintf(f, "drivedata: "); 37030418Skarels for (i = NDDATA - 1; i >= 0; i--) 37130418Skarels if (lp->d_drivedata[i]) 37230418Skarels break; 37330418Skarels if (i < 0) 37430418Skarels i = 0; 37530418Skarels for (j = 0; j <= i; j++) 37630418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 37730418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 378*30863Skarels fprintf(f, 379*30863Skarels "# size offset fstype [fsize bsize cpg]\n"); 38030418Skarels pp = lp->d_partitions; 38130418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 38230418Skarels if (pp->p_size) { 383*30863Skarels fprintf(f, " %c: %8d %8d ", 'a' + i, 384*30863Skarels pp->p_size, pp->p_offset); 38530418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 38630418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 38730418Skarels else 38830418Skarels fprintf(f, "%8d", pp->p_fstype); 389*30863Skarels switch (pp->p_fstype) { 390*30863Skarels 391*30863Skarels case FS_UNUSED: /* XXX */ 392*30863Skarels fprintf(f, " %5d %5d %5.5s ", 393*30863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 394*30863Skarels break; 395*30863Skarels 396*30863Skarels case FS_BSDFFS: 397*30863Skarels fprintf(f, " %5d %5d %5d ", 398*30863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, 399*30863Skarels pp->p_cpg); 400*30863Skarels break; 401*30863Skarels 402*30863Skarels default: 403*30863Skarels fprintf(f, "%20.20s", ""); 404*30863Skarels break; 405*30863Skarels } 40630418Skarels fprintf(f, "\t# (Cyl. %4d", 40730418Skarels pp->p_offset / lp->d_secpercyl); 40830418Skarels if (pp->p_offset % lp->d_secpercyl) 40930418Skarels putc('*', f); 41030418Skarels else 41130418Skarels putc(' ', f); 41230418Skarels fprintf(f, "- %d", 41330418Skarels (pp->p_offset + 41430418Skarels pp->p_size + lp->d_secpercyl - 1) / 41530418Skarels lp->d_secpercyl - 1); 41630418Skarels if (pp->p_size % lp->d_secpercyl) 41730418Skarels putc('*', f); 418*30863Skarels fprintf(f, ")\n"); 41930418Skarels } 42030418Skarels } 42130418Skarels } 42230418Skarels 42330715Sbostic edit(lp) 42430715Sbostic struct disklabel *lp; 42530418Skarels { 42630715Sbostic register int c; 42730715Sbostic struct disklabel label; 42830715Sbostic FILE *fd; 42930715Sbostic char *mktemp(); 43030715Sbostic 43130715Sbostic (void) mktemp(tmpfil); 43230715Sbostic fd = fopen(tmpfil, "w"); 43330715Sbostic if (fd == NULL) { 43430715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 43530715Sbostic return (0); 43630715Sbostic } 43730715Sbostic (void)fchmod(fd, 0600); 43830715Sbostic display(fd, lp); 43930715Sbostic fclose(fd); 44030715Sbostic for (;;) { 44130715Sbostic if (!editit()) 44230715Sbostic break; 44330715Sbostic fd = fopen(tmpfil, "r"); 44430715Sbostic if (fd == NULL) { 44530715Sbostic fprintf(stderr, "%s: Can't reopen for reading\n"); 44630715Sbostic break; 44730715Sbostic } 448*30863Skarels bzero((char *)&label, sizeof(label)); 44930715Sbostic if (getasciilabel(fd, &label)) { 45030715Sbostic *lp = label; 45130715Sbostic (void) unlink(tmpfil); 45230715Sbostic return (1); 45330715Sbostic } 45430715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 45530715Sbostic c = getchar(); 45630715Sbostic if (c != EOF && c != (int)'\n') 45730715Sbostic while (getchar() != (int)'\n') 45830715Sbostic ; 45930715Sbostic if (c == (int)'n') 46030715Sbostic break; 46130715Sbostic } 46230715Sbostic (void) unlink(tmpfil); 46330715Sbostic return (0); 46430418Skarels } 46530418Skarels 46630715Sbostic editit() 46730715Sbostic { 46830715Sbostic register int pid, xpid; 46930715Sbostic int stat, omask; 47030715Sbostic extern char *getenv(); 47130418Skarels 47230715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 47330715Sbostic while ((pid = fork()) < 0) { 47430715Sbostic extern int errno; 47530715Sbostic 47630715Sbostic if (errno == EPROCLIM) { 47730715Sbostic fprintf(stderr, "You have too many processes\n"); 47830715Sbostic return(0); 47930715Sbostic } 48030715Sbostic if (errno != EAGAIN) { 48130715Sbostic perror("fork"); 48230715Sbostic return(0); 48330715Sbostic } 48430715Sbostic sleep(1); 48530715Sbostic } 48630715Sbostic if (pid == 0) { 48730715Sbostic register char *ed; 48830715Sbostic 48930715Sbostic sigsetmask(omask); 49030715Sbostic setgid(getgid()); 49130715Sbostic setuid(getuid()); 49230715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 49330715Sbostic ed = DEFEDITOR; 49430715Sbostic execlp(ed, ed, tmpfil, 0); 49530715Sbostic perror(ed); 49630715Sbostic exit(1); 49730715Sbostic } 49830715Sbostic while ((xpid = wait(&stat)) >= 0) 49930715Sbostic if (xpid == pid) 50030715Sbostic break; 50130715Sbostic sigsetmask(omask); 50230715Sbostic return(!stat); 50330715Sbostic } 50430715Sbostic 50530715Sbostic char * 50630715Sbostic skip(cp) 50730715Sbostic register char *cp; 50830715Sbostic { 50930715Sbostic 51030715Sbostic while (*cp != '\0' && isspace(*cp)) 51130715Sbostic cp++; 51230715Sbostic if (*cp == '\0' || *cp == '#') 51330715Sbostic return ((char *)NULL); 51430715Sbostic return (cp); 51530715Sbostic } 51630715Sbostic 51730715Sbostic char * 51830715Sbostic word(cp) 51930715Sbostic register char *cp; 52030715Sbostic { 52130715Sbostic register char c; 52230715Sbostic 52330715Sbostic while (*cp != '\0' && !isspace(*cp)) 52430715Sbostic if (*cp++ == '#') 52530715Sbostic break; 52630715Sbostic if ((c = *cp) != '\0') { 52730715Sbostic *cp++ = '\0'; 52830715Sbostic if (c != '#') 52930715Sbostic return (skip(cp)); 53030715Sbostic } 53130715Sbostic return ((char *)NULL); 53230715Sbostic } 53330715Sbostic 53430418Skarels /* 53530418Skarels * Read an ascii label in from fd f, 53630418Skarels * in the same format as that put out by display(), 53730418Skarels * and fill in lp. 53830418Skarels */ 53930418Skarels getasciilabel(f, lp) 54030715Sbostic FILE *f; 54130418Skarels register struct disklabel *lp; 54230418Skarels { 54330715Sbostic register char **cpp, *cp; 544*30863Skarels register struct partition *pp; 54530715Sbostic char *tp, *s, line[BUFSIZ]; 54630715Sbostic int v, lineno = 0, errors = 0; 54730715Sbostic 54830715Sbostic lp->d_bbsize = BBSIZE; /* XXX */ 54930715Sbostic lp->d_sbsize = SBSIZE; /* XXX */ 55030715Sbostic while (fgets(line, sizeof(line) - 1, f)) { 55130715Sbostic lineno++; 55230715Sbostic if (cp = index(line,'\n')) 55330715Sbostic *cp = '\0'; 55430715Sbostic cp = skip(line); 55530715Sbostic if (cp == NULL) 55630715Sbostic continue; 55730715Sbostic tp = index(cp, ':'); 55830715Sbostic if (tp == NULL) { 55930715Sbostic fprintf(stderr, "line %d: syntax error\n", lineno); 56030715Sbostic errors++; 56130715Sbostic continue; 56230715Sbostic } 56330715Sbostic *tp++ = '\0', tp = skip(tp); 56430715Sbostic if (streq(cp, "type")) { 56530715Sbostic if (tp == NULL) 56630715Sbostic tp = "unknown"; 56730715Sbostic cpp = dktypenames; 56830715Sbostic for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 56930715Sbostic if ((s = *cpp) && streq(s, tp)) { 57030715Sbostic lp->d_type = cpp - dktypenames; 57130715Sbostic goto next; 57230715Sbostic } 57330715Sbostic v = atoi(tp); 57430715Sbostic if ((unsigned)v >= DKMAXTYPES) 57530715Sbostic fprintf(stderr, "line %d:%s %d\n", lineno, 57630715Sbostic "Warning, unknown disk type", v); 57730715Sbostic lp->d_type = v; 57830715Sbostic continue; 57930715Sbostic } 58030715Sbostic if (streq(cp, "flags")) { 58130715Sbostic v = 0; 58230715Sbostic while ((cp = tp) && *cp != '\0') { 58330715Sbostic if (tp = skip(cp)) { 58430715Sbostic *tp++ = '\0'; 58530715Sbostic while (*tp && isspace(*tp)) 58630715Sbostic tp++; 58730715Sbostic } 58830715Sbostic if (streq(cp, "removeable")) 58930715Sbostic v |= D_REMOVABLE; 59030715Sbostic else if (streq(cp, "ecc")) 59130715Sbostic v |= D_ECC; 59230715Sbostic else if (streq(cp, "badsect")) 59330715Sbostic v |= D_BADSECT; 59430715Sbostic else { 59530715Sbostic fprintf(stderr, 59630715Sbostic "line %d: %s: bad flag\n", 59730715Sbostic lineno, cp); 59830715Sbostic errors++; 59930715Sbostic } 60030715Sbostic } 60130715Sbostic lp->d_flags = v; 60230715Sbostic continue; 60330715Sbostic } 60430715Sbostic if (streq(cp, "drivedata")) { 60530715Sbostic register int i; 60630715Sbostic 60730715Sbostic for (i = 0;(cp = tp) && *cp != '\0' && i < NDDATA;) { 60830715Sbostic if (tp = skip(cp)) { 60930715Sbostic *tp++ = '\0'; 61030715Sbostic while (*tp != '\0' && isspace(*tp)) 61130715Sbostic tp++; 61230715Sbostic } 61330715Sbostic lp->d_drivedata[i++] = atoi(cp); 61430715Sbostic } 61530715Sbostic continue; 61630715Sbostic } 61730715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 618*30863Skarels if (v == 0 || (unsigned)v > MAXPARTITIONS) { 61930715Sbostic fprintf(stderr, 62030715Sbostic "line %d: bad # of partitions\n", lineno); 621*30863Skarels lp->d_npartitions = MAXPARTITIONS; 622*30863Skarels errors++; 623*30863Skarels } else 62430715Sbostic lp->d_npartitions = v; 62530715Sbostic continue; 62630715Sbostic } 62730715Sbostic if (tp == NULL) 62830715Sbostic tp = ""; 62930715Sbostic if (streq(cp, "disk")) { 63030715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 63130715Sbostic continue; 63230715Sbostic } 63330715Sbostic if (streq(cp, "label")) { 63430715Sbostic strncpy(lp->d_name, tp, sizeof (lp->d_name)); 63530715Sbostic continue; 63630715Sbostic } 63730715Sbostic if (streq(cp, "bytes/sector")) { 63830715Sbostic v = atoi(tp); 63930715Sbostic if (v <= 0 || (v % 512) != 0) { 64030715Sbostic fprintf(stderr, 64130715Sbostic "line %d: %s: bad sector size\n", 64230715Sbostic lineno, tp); 64330715Sbostic errors++; 64430715Sbostic } else 64530715Sbostic lp->d_secsize = v; 64630715Sbostic continue; 64730715Sbostic } 64830715Sbostic if (streq(cp, "sectors/track")) { 64930715Sbostic v = atoi(tp); 65030715Sbostic if (v <= 0) { 65130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 65230715Sbostic lineno, tp, cp); 65330715Sbostic errors++; 65430715Sbostic } else 65530715Sbostic lp->d_nsectors = v; 65630715Sbostic continue; 65730715Sbostic } 65830715Sbostic if (streq(cp, "tracks/cylinder")) { 65930715Sbostic v = atoi(tp); 66030715Sbostic if (v <= 0) { 66130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 66230715Sbostic lineno, tp, cp); 66330715Sbostic errors++; 66430715Sbostic } else 66530715Sbostic lp->d_ntracks = v; 66630715Sbostic continue; 66730715Sbostic } 66830715Sbostic if (streq(cp, "cylinders")) { 66930715Sbostic v = atoi(tp); 67030715Sbostic if (v <= 0) { 67130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 67230715Sbostic lineno, tp, cp); 67330715Sbostic errors++; 67430715Sbostic } else 67530715Sbostic lp->d_ncylinders = v; 67630715Sbostic continue; 67730715Sbostic } 67830715Sbostic if (streq(cp, "rpm")) { 67930715Sbostic v = atoi(tp); 68030715Sbostic if (v <= 0) { 68130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 68230715Sbostic lineno, tp, cp); 68330715Sbostic errors++; 68430715Sbostic } else 68530715Sbostic lp->d_rpm = v; 68630715Sbostic continue; 68730715Sbostic } 68830715Sbostic if (streq(cp, "interleave")) { 68930715Sbostic v = atoi(tp); 69030715Sbostic if (v <= 0) { 69130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 69230715Sbostic lineno, tp, cp); 69330715Sbostic errors++; 69430715Sbostic } else 69530715Sbostic lp->d_interleave = v; 69630715Sbostic continue; 69730715Sbostic } 69830715Sbostic if (streq(cp, "trackskew")) { 69930715Sbostic v = atoi(tp); 70030715Sbostic if (v < 0) { 70130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 70230715Sbostic lineno, tp, cp); 70330715Sbostic errors++; 70430715Sbostic } else 70530715Sbostic lp->d_trackskew = v; 70630715Sbostic continue; 70730715Sbostic } 70830715Sbostic if (streq(cp, "cylinderskew")) { 70930715Sbostic v = atoi(tp); 71030715Sbostic if (v < 0) { 71130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 71230715Sbostic lineno, tp, cp); 71330715Sbostic errors++; 71430715Sbostic } else 71530715Sbostic lp->d_cylskew = v; 71630715Sbostic continue; 71730715Sbostic } 71830715Sbostic if (streq(cp, "headswitch")) { 71930715Sbostic v = atoi(tp); 72030715Sbostic if (v < 0) { 72130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 72230715Sbostic lineno, tp, cp); 72330715Sbostic errors++; 72430715Sbostic } else 72530715Sbostic lp->d_headswitch = v; 72630715Sbostic continue; 72730715Sbostic } 72830715Sbostic if (streq(cp, "track-to-track seek")) { 72930715Sbostic v = atoi(tp); 73030715Sbostic if (v < 0) { 73130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 73230715Sbostic lineno, tp, cp); 73330715Sbostic errors++; 73430715Sbostic } else 73530715Sbostic lp->d_trkseek = v; 73630715Sbostic continue; 73730715Sbostic } 73830715Sbostic if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 739*30863Skarels unsigned part = *cp - 'a'; 74030715Sbostic 741*30863Skarels if (part > lp->d_npartitions) { 74230715Sbostic fprintf(stderr, 74330715Sbostic "line %d: bad partition name\n", lineno); 74430715Sbostic errors++; 74530715Sbostic continue; 74630715Sbostic } 747*30863Skarels pp = &lp->d_partitions[part]; 748*30863Skarels #define NXTNUM(n) { \ 749*30863Skarels cp = tp, tp = word(cp); \ 750*30863Skarels if (tp == NULL) \ 751*30863Skarels tp = cp; \ 752*30863Skarels (n) = atoi(cp); \ 753*30863Skarels } 754*30863Skarels 755*30863Skarels NXTNUM(v); 75630715Sbostic if (v < 0) { 75730715Sbostic fprintf(stderr, 75830715Sbostic "line %d: %s: bad partition size\n", 75930715Sbostic lineno, cp); 76030715Sbostic errors++; 76130715Sbostic } else 762*30863Skarels pp->p_size = v; 763*30863Skarels NXTNUM(v); 76430715Sbostic if (v < 0) { 76530715Sbostic fprintf(stderr, 76630715Sbostic "line %d: %s: bad partition offset\n", 76730715Sbostic lineno, cp); 76830715Sbostic errors++; 76930715Sbostic } else 770*30863Skarels pp->p_offset = v; 77130715Sbostic cp = tp, tp = word(cp); 77230715Sbostic cpp = fstypenames; 77330715Sbostic for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 77430715Sbostic if ((s = *cpp) && streq(s, cp)) { 775*30863Skarels pp->p_fstype = cpp - fstypenames; 776*30863Skarels goto gottype; 77730715Sbostic } 77830715Sbostic v = atoi(cp); 77930715Sbostic if ((unsigned)v >= FSMAXTYPES) 78030715Sbostic fprintf(stderr, "line %d: %s %s\n", lineno, 78130715Sbostic "Warning, unknown filesystem type", cp); 782*30863Skarels pp->p_fstype = v; 783*30863Skarels gottype: 784*30863Skarels 785*30863Skarels switch (pp->p_fstype) { 786*30863Skarels 787*30863Skarels case FS_UNUSED: /* XXX */ 788*30863Skarels NXTNUM(pp->p_fsize); 789*30863Skarels if (pp->p_fsize == 0) 790*30863Skarels break; 791*30863Skarels NXTNUM(v); 792*30863Skarels pp->p_frag = v / pp->p_fsize; 793*30863Skarels break; 794*30863Skarels 795*30863Skarels case FS_BSDFFS: 796*30863Skarels NXTNUM(pp->p_fsize); 797*30863Skarels if (pp->p_fsize == 0) 798*30863Skarels break; 799*30863Skarels NXTNUM(v); 800*30863Skarels pp->p_frag = v / pp->p_fsize; 801*30863Skarels NXTNUM(pp->p_cpg); 802*30863Skarels break; 803*30863Skarels 804*30863Skarels default: 805*30863Skarels break; 806*30863Skarels } 80730715Sbostic continue; 80830715Sbostic } 80930715Sbostic fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 81030715Sbostic lineno, cp); 81130715Sbostic errors++; 81230715Sbostic next: 81330715Sbostic ; 81430715Sbostic } 81530715Sbostic errors += checklabel(lp); 81630715Sbostic return (errors == 0); 81730418Skarels } 81830418Skarels 81930715Sbostic /* 82030715Sbostic * Check disklabel for errors and fill in 82130715Sbostic * derived fields according to supplied values. 82230715Sbostic */ 82330715Sbostic checklabel(lp) 82430715Sbostic register struct disklabel *lp; 82530418Skarels { 82630715Sbostic register struct partition *pp; 82730715Sbostic int i, errors = 0; 82830715Sbostic char part; 82930418Skarels 83030715Sbostic if (lp->d_secsize == 0) { 83130715Sbostic fprintf(stderr, "sector size %d\n", lp->d_secsize); 83230715Sbostic return (1); 83330715Sbostic } 83430715Sbostic if (lp->d_nsectors == 0) { 83530715Sbostic fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 83630715Sbostic return (1); 83730715Sbostic } 83830715Sbostic if (lp->d_ntracks == 0) { 83930715Sbostic fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 84030715Sbostic return (1); 84130715Sbostic } 84230715Sbostic if (lp->d_ncylinders == 0) { 84330715Sbostic fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 84430715Sbostic errors++; 84530715Sbostic } 84630715Sbostic if (lp->d_rpm == 0) 84730715Sbostic Warning("revolutions/minute %d\n", lp->d_rpm); 84830715Sbostic if (lp->d_secpercyl == 0) 84930715Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 85030715Sbostic if (lp->d_secperunit == 0) 85130715Sbostic lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 85230715Sbostic if (lp->d_bbsize == 0) { 85330715Sbostic fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 85430715Sbostic errors++; 85530715Sbostic } else if (lp->d_bbsize % lp->d_secsize) 85630715Sbostic Warning("boot block size %% sector-size != 0\n"); 85730715Sbostic if (lp->d_sbsize == 0) { 85830715Sbostic fprintf(stderr, "super block size %d\n", lp->d_sbsize); 85930715Sbostic errors++; 86030715Sbostic } else if (lp->d_sbsize % lp->d_secsize) 86130715Sbostic Warning("super block size %% sector-size != 0\n"); 86230715Sbostic if (lp->d_npartitions > MAXPARTITIONS) 86330715Sbostic Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 86430715Sbostic lp->d_npartitions, MAXPARTITIONS); 86530715Sbostic for (i = 0; i < lp->d_npartitions; i++) { 86630715Sbostic part = 'a' + i; 86730715Sbostic pp = &lp->d_partitions[i]; 86830715Sbostic if (pp->p_size == 0 && pp->p_offset != 0) 86930715Sbostic Warning("partition %c: size 0, but offset %d\n", 87030715Sbostic part, pp->p_offset); 87130715Sbostic #ifdef notdef 87230715Sbostic if (pp->p_size % lp->d_secpercyl) 87330715Sbostic Warning("partition %c: size %% cylinder-size != 0\n", 87430715Sbostic part); 87530715Sbostic if (pp->p_offset % lp->d_secpercyl) 87630715Sbostic Warning("partition %c: offset %% cylinder-size != 0\n", 87730715Sbostic part); 87830715Sbostic #endif 87930715Sbostic if (pp->p_offset > lp->d_secperunit) { 88030715Sbostic fprintf(stderr, 88130715Sbostic "partition %c: offset past end of unit\n", part); 88230715Sbostic errors++; 88330715Sbostic } 88430715Sbostic if (pp->p_offset + pp->p_size > lp->d_secperunit) { 88530715Sbostic fprintf(stderr, 88630715Sbostic "partition %c: partition extends past end of unit\n", 88730715Sbostic part); 88830715Sbostic errors++; 88930715Sbostic } 89030715Sbostic } 89130715Sbostic for (; i < MAXPARTITIONS; i++) { 89230715Sbostic part = 'a' + i; 89330715Sbostic pp = &lp->d_partitions[i]; 89430715Sbostic if (pp->p_size || pp->p_offset) 89530715Sbostic Warning("unused partition %c: size %d offset %d\n", 89630715Sbostic pp->p_size, pp->p_offset); 89730715Sbostic } 89830715Sbostic return (errors); 89930715Sbostic } 90030715Sbostic 90130715Sbostic /*VARARGS1*/ 90230715Sbostic Warning(fmt, a1, a2, a3, a4, a5) 90330715Sbostic char *fmt; 90430715Sbostic { 90530715Sbostic 90630715Sbostic fprintf(stderr, "Warning, "); 90730715Sbostic fprintf(stderr, fmt, a1, a2, a3, a4, a5); 90830715Sbostic fprintf(stderr, "\n"); 90930715Sbostic } 91030715Sbostic 91130715Sbostic Perror(str) 91230715Sbostic char *str; 91330715Sbostic { 91430715Sbostic fputs("disklabel: ", stderr); perror(str); 91530418Skarels exit(4); 91630418Skarels } 91730715Sbostic 91830715Sbostic usage() 91930715Sbostic { 92030715Sbostic #ifdef BOOT 92130715Sbostic fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n", 92230715Sbostic "usage: disklabel [-r] disk", "(to read label)", 92330715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 92430715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 92530715Sbostic "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 92630715Sbostic #else 92730715Sbostic fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 92830715Sbostic "usage: disklabel [-r] disk", "(to read label)", 92930715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 93030715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 93130715Sbostic "or disklabel -R [-r] disk protofile", "(to restore label)"); 93230715Sbostic #endif 93330715Sbostic exit(1); 93430715Sbostic } 935