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*31386Skarels static char sccsid[] = "@(#)disklabel.c 5.7 (Berkeley) 06/04/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); 362*31386Skarels fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 36330418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 36430715Sbostic fprintf(f, "rpm: %d\n", lp->d_rpm); 36530418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 36630418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 36730418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 36830418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 36930418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 37030418Skarels fprintf(f, "drivedata: "); 37130418Skarels for (i = NDDATA - 1; i >= 0; i--) 37230418Skarels if (lp->d_drivedata[i]) 37330418Skarels break; 37430418Skarels if (i < 0) 37530418Skarels i = 0; 37630418Skarels for (j = 0; j <= i; j++) 37730418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 37830418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 37930863Skarels fprintf(f, 38030863Skarels "# size offset fstype [fsize bsize cpg]\n"); 38130418Skarels pp = lp->d_partitions; 38230418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 38330418Skarels if (pp->p_size) { 38430863Skarels fprintf(f, " %c: %8d %8d ", 'a' + i, 38530863Skarels pp->p_size, pp->p_offset); 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); 39030863Skarels switch (pp->p_fstype) { 39130863Skarels 39230863Skarels case FS_UNUSED: /* XXX */ 39330863Skarels fprintf(f, " %5d %5d %5.5s ", 39430863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 39530863Skarels break; 39630863Skarels 39730863Skarels case FS_BSDFFS: 39830863Skarels fprintf(f, " %5d %5d %5d ", 39930863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, 40030863Skarels pp->p_cpg); 40130863Skarels break; 40230863Skarels 40330863Skarels default: 40430863Skarels fprintf(f, "%20.20s", ""); 40530863Skarels break; 40630863Skarels } 40730418Skarels fprintf(f, "\t# (Cyl. %4d", 40830418Skarels pp->p_offset / lp->d_secpercyl); 40930418Skarels if (pp->p_offset % lp->d_secpercyl) 41030418Skarels putc('*', f); 41130418Skarels else 41230418Skarels putc(' ', f); 41330418Skarels fprintf(f, "- %d", 41430418Skarels (pp->p_offset + 41530418Skarels pp->p_size + lp->d_secpercyl - 1) / 41630418Skarels lp->d_secpercyl - 1); 41730418Skarels if (pp->p_size % lp->d_secpercyl) 41830418Skarels putc('*', f); 41930863Skarels fprintf(f, ")\n"); 42030418Skarels } 42130418Skarels } 42230418Skarels } 42330418Skarels 42430715Sbostic edit(lp) 42530715Sbostic struct disklabel *lp; 42630418Skarels { 42730715Sbostic register int c; 42830715Sbostic struct disklabel label; 42930715Sbostic FILE *fd; 43030715Sbostic char *mktemp(); 43130715Sbostic 43230715Sbostic (void) mktemp(tmpfil); 43330715Sbostic fd = fopen(tmpfil, "w"); 43430715Sbostic if (fd == NULL) { 43530715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 43630715Sbostic return (0); 43730715Sbostic } 43830715Sbostic (void)fchmod(fd, 0600); 43930715Sbostic display(fd, lp); 44030715Sbostic fclose(fd); 44130715Sbostic for (;;) { 44230715Sbostic if (!editit()) 44330715Sbostic break; 44430715Sbostic fd = fopen(tmpfil, "r"); 44530715Sbostic if (fd == NULL) { 44630715Sbostic fprintf(stderr, "%s: Can't reopen for reading\n"); 44730715Sbostic break; 44830715Sbostic } 44930863Skarels bzero((char *)&label, sizeof(label)); 45030715Sbostic if (getasciilabel(fd, &label)) { 45130715Sbostic *lp = label; 45230715Sbostic (void) unlink(tmpfil); 45330715Sbostic return (1); 45430715Sbostic } 45530715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 45630715Sbostic c = getchar(); 45730715Sbostic if (c != EOF && c != (int)'\n') 45830715Sbostic while (getchar() != (int)'\n') 45930715Sbostic ; 46030715Sbostic if (c == (int)'n') 46130715Sbostic break; 46230715Sbostic } 46330715Sbostic (void) unlink(tmpfil); 46430715Sbostic return (0); 46530418Skarels } 46630418Skarels 46730715Sbostic editit() 46830715Sbostic { 46930715Sbostic register int pid, xpid; 47030715Sbostic int stat, omask; 47130715Sbostic extern char *getenv(); 47230418Skarels 47330715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 47430715Sbostic while ((pid = fork()) < 0) { 47530715Sbostic extern int errno; 47630715Sbostic 47730715Sbostic if (errno == EPROCLIM) { 47830715Sbostic fprintf(stderr, "You have too many processes\n"); 47930715Sbostic return(0); 48030715Sbostic } 48130715Sbostic if (errno != EAGAIN) { 48230715Sbostic perror("fork"); 48330715Sbostic return(0); 48430715Sbostic } 48530715Sbostic sleep(1); 48630715Sbostic } 48730715Sbostic if (pid == 0) { 48830715Sbostic register char *ed; 48930715Sbostic 49030715Sbostic sigsetmask(omask); 49130715Sbostic setgid(getgid()); 49230715Sbostic setuid(getuid()); 49330715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 49430715Sbostic ed = DEFEDITOR; 49530715Sbostic execlp(ed, ed, tmpfil, 0); 49630715Sbostic perror(ed); 49730715Sbostic exit(1); 49830715Sbostic } 49930715Sbostic while ((xpid = wait(&stat)) >= 0) 50030715Sbostic if (xpid == pid) 50130715Sbostic break; 50230715Sbostic sigsetmask(omask); 50330715Sbostic return(!stat); 50430715Sbostic } 50530715Sbostic 50630715Sbostic char * 50730715Sbostic skip(cp) 50830715Sbostic register char *cp; 50930715Sbostic { 51030715Sbostic 51130715Sbostic while (*cp != '\0' && isspace(*cp)) 51230715Sbostic cp++; 51330715Sbostic if (*cp == '\0' || *cp == '#') 51430715Sbostic return ((char *)NULL); 51530715Sbostic return (cp); 51630715Sbostic } 51730715Sbostic 51830715Sbostic char * 51930715Sbostic word(cp) 52030715Sbostic register char *cp; 52130715Sbostic { 52230715Sbostic register char c; 52330715Sbostic 52430715Sbostic while (*cp != '\0' && !isspace(*cp)) 52530715Sbostic if (*cp++ == '#') 52630715Sbostic break; 52730715Sbostic if ((c = *cp) != '\0') { 52830715Sbostic *cp++ = '\0'; 52930715Sbostic if (c != '#') 53030715Sbostic return (skip(cp)); 53130715Sbostic } 53230715Sbostic return ((char *)NULL); 53330715Sbostic } 53430715Sbostic 53530418Skarels /* 53630418Skarels * Read an ascii label in from fd f, 53730418Skarels * in the same format as that put out by display(), 53830418Skarels * and fill in lp. 53930418Skarels */ 54030418Skarels getasciilabel(f, lp) 54130715Sbostic FILE *f; 54230418Skarels register struct disklabel *lp; 54330418Skarels { 54430715Sbostic register char **cpp, *cp; 54530863Skarels register struct partition *pp; 54630715Sbostic char *tp, *s, line[BUFSIZ]; 54730715Sbostic int v, lineno = 0, errors = 0; 54830715Sbostic 54930715Sbostic lp->d_bbsize = BBSIZE; /* XXX */ 55030715Sbostic lp->d_sbsize = SBSIZE; /* XXX */ 55130715Sbostic while (fgets(line, sizeof(line) - 1, f)) { 55230715Sbostic lineno++; 55330715Sbostic if (cp = index(line,'\n')) 55430715Sbostic *cp = '\0'; 55530715Sbostic cp = skip(line); 55630715Sbostic if (cp == NULL) 55730715Sbostic continue; 55830715Sbostic tp = index(cp, ':'); 55930715Sbostic if (tp == NULL) { 56030715Sbostic fprintf(stderr, "line %d: syntax error\n", lineno); 56130715Sbostic errors++; 56230715Sbostic continue; 56330715Sbostic } 56430715Sbostic *tp++ = '\0', tp = skip(tp); 56530715Sbostic if (streq(cp, "type")) { 56630715Sbostic if (tp == NULL) 56730715Sbostic tp = "unknown"; 56830715Sbostic cpp = dktypenames; 56930715Sbostic for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 57030715Sbostic if ((s = *cpp) && streq(s, tp)) { 57130715Sbostic lp->d_type = cpp - dktypenames; 57230715Sbostic goto next; 57330715Sbostic } 57430715Sbostic v = atoi(tp); 57530715Sbostic if ((unsigned)v >= DKMAXTYPES) 57630715Sbostic fprintf(stderr, "line %d:%s %d\n", lineno, 57730715Sbostic "Warning, unknown disk type", v); 57830715Sbostic lp->d_type = v; 57930715Sbostic continue; 58030715Sbostic } 58130715Sbostic if (streq(cp, "flags")) { 582*31386Skarels for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) { 58330715Sbostic if (streq(cp, "removeable")) 58430715Sbostic v |= D_REMOVABLE; 58530715Sbostic else if (streq(cp, "ecc")) 58630715Sbostic v |= D_ECC; 58730715Sbostic else if (streq(cp, "badsect")) 58830715Sbostic v |= D_BADSECT; 58930715Sbostic else { 59030715Sbostic fprintf(stderr, 59130715Sbostic "line %d: %s: bad flag\n", 59230715Sbostic lineno, cp); 59330715Sbostic errors++; 59430715Sbostic } 59530715Sbostic } 59630715Sbostic lp->d_flags = v; 59730715Sbostic continue; 59830715Sbostic } 59930715Sbostic if (streq(cp, "drivedata")) { 60030715Sbostic register int i; 60130715Sbostic 602*31386Skarels for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 60330715Sbostic lp->d_drivedata[i++] = atoi(cp); 604*31386Skarels tp = word(cp); 60530715Sbostic } 60630715Sbostic continue; 60730715Sbostic } 60830715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 60930863Skarels if (v == 0 || (unsigned)v > MAXPARTITIONS) { 61030715Sbostic fprintf(stderr, 61130715Sbostic "line %d: bad # of partitions\n", lineno); 61230863Skarels lp->d_npartitions = MAXPARTITIONS; 61330863Skarels errors++; 61430863Skarels } else 61530715Sbostic lp->d_npartitions = v; 61630715Sbostic continue; 61730715Sbostic } 61830715Sbostic if (tp == NULL) 61930715Sbostic tp = ""; 62030715Sbostic if (streq(cp, "disk")) { 62130715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 62230715Sbostic continue; 62330715Sbostic } 62430715Sbostic if (streq(cp, "label")) { 62530715Sbostic strncpy(lp->d_name, tp, sizeof (lp->d_name)); 62630715Sbostic continue; 62730715Sbostic } 62830715Sbostic if (streq(cp, "bytes/sector")) { 62930715Sbostic v = atoi(tp); 63030715Sbostic if (v <= 0 || (v % 512) != 0) { 63130715Sbostic fprintf(stderr, 63230715Sbostic "line %d: %s: bad sector size\n", 63330715Sbostic lineno, tp); 63430715Sbostic errors++; 63530715Sbostic } else 63630715Sbostic lp->d_secsize = v; 63730715Sbostic continue; 63830715Sbostic } 63930715Sbostic if (streq(cp, "sectors/track")) { 64030715Sbostic v = atoi(tp); 64130715Sbostic if (v <= 0) { 64230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 64330715Sbostic lineno, tp, cp); 64430715Sbostic errors++; 64530715Sbostic } else 64630715Sbostic lp->d_nsectors = v; 64730715Sbostic continue; 64830715Sbostic } 649*31386Skarels if (streq(cp, "sectors/cylinder")) { 650*31386Skarels v = atoi(tp); 651*31386Skarels if (v <= 0) { 652*31386Skarels fprintf(stderr, "line %d: %s: bad %s\n", 653*31386Skarels lineno, tp, cp); 654*31386Skarels errors++; 655*31386Skarels } else 656*31386Skarels lp->d_secpercyl = v; 657*31386Skarels continue; 658*31386Skarels } 65930715Sbostic if (streq(cp, "tracks/cylinder")) { 66030715Sbostic v = atoi(tp); 66130715Sbostic if (v <= 0) { 66230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 66330715Sbostic lineno, tp, cp); 66430715Sbostic errors++; 66530715Sbostic } else 66630715Sbostic lp->d_ntracks = v; 66730715Sbostic continue; 66830715Sbostic } 66930715Sbostic if (streq(cp, "cylinders")) { 67030715Sbostic v = atoi(tp); 67130715Sbostic if (v <= 0) { 67230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 67330715Sbostic lineno, tp, cp); 67430715Sbostic errors++; 67530715Sbostic } else 67630715Sbostic lp->d_ncylinders = v; 67730715Sbostic continue; 67830715Sbostic } 67930715Sbostic if (streq(cp, "rpm")) { 68030715Sbostic v = atoi(tp); 68130715Sbostic if (v <= 0) { 68230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 68330715Sbostic lineno, tp, cp); 68430715Sbostic errors++; 68530715Sbostic } else 68630715Sbostic lp->d_rpm = v; 68730715Sbostic continue; 68830715Sbostic } 68930715Sbostic if (streq(cp, "interleave")) { 69030715Sbostic v = atoi(tp); 69130715Sbostic if (v <= 0) { 69230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 69330715Sbostic lineno, tp, cp); 69430715Sbostic errors++; 69530715Sbostic } else 69630715Sbostic lp->d_interleave = v; 69730715Sbostic continue; 69830715Sbostic } 69930715Sbostic if (streq(cp, "trackskew")) { 70030715Sbostic v = atoi(tp); 70130715Sbostic if (v < 0) { 70230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 70330715Sbostic lineno, tp, cp); 70430715Sbostic errors++; 70530715Sbostic } else 70630715Sbostic lp->d_trackskew = v; 70730715Sbostic continue; 70830715Sbostic } 70930715Sbostic if (streq(cp, "cylinderskew")) { 71030715Sbostic v = atoi(tp); 71130715Sbostic if (v < 0) { 71230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 71330715Sbostic lineno, tp, cp); 71430715Sbostic errors++; 71530715Sbostic } else 71630715Sbostic lp->d_cylskew = v; 71730715Sbostic continue; 71830715Sbostic } 71930715Sbostic if (streq(cp, "headswitch")) { 72030715Sbostic v = atoi(tp); 72130715Sbostic if (v < 0) { 72230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 72330715Sbostic lineno, tp, cp); 72430715Sbostic errors++; 72530715Sbostic } else 72630715Sbostic lp->d_headswitch = v; 72730715Sbostic continue; 72830715Sbostic } 72930715Sbostic if (streq(cp, "track-to-track seek")) { 73030715Sbostic v = atoi(tp); 73130715Sbostic if (v < 0) { 73230715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 73330715Sbostic lineno, tp, cp); 73430715Sbostic errors++; 73530715Sbostic } else 73630715Sbostic lp->d_trkseek = v; 73730715Sbostic continue; 73830715Sbostic } 73930715Sbostic if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 74030863Skarels unsigned part = *cp - 'a'; 74130715Sbostic 74230863Skarels if (part > lp->d_npartitions) { 74330715Sbostic fprintf(stderr, 74430715Sbostic "line %d: bad partition name\n", lineno); 74530715Sbostic errors++; 74630715Sbostic continue; 74730715Sbostic } 74830863Skarels pp = &lp->d_partitions[part]; 74930863Skarels #define NXTNUM(n) { \ 75030863Skarels cp = tp, tp = word(cp); \ 75130863Skarels if (tp == NULL) \ 75230863Skarels tp = cp; \ 75330863Skarels (n) = atoi(cp); \ 75430863Skarels } 75530863Skarels 75630863Skarels NXTNUM(v); 75730715Sbostic if (v < 0) { 75830715Sbostic fprintf(stderr, 75930715Sbostic "line %d: %s: bad partition size\n", 76030715Sbostic lineno, cp); 76130715Sbostic errors++; 76230715Sbostic } else 76330863Skarels pp->p_size = v; 76430863Skarels NXTNUM(v); 76530715Sbostic if (v < 0) { 76630715Sbostic fprintf(stderr, 76730715Sbostic "line %d: %s: bad partition offset\n", 76830715Sbostic lineno, cp); 76930715Sbostic errors++; 77030715Sbostic } else 77130863Skarels pp->p_offset = v; 77230715Sbostic cp = tp, tp = word(cp); 77330715Sbostic cpp = fstypenames; 77430715Sbostic for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 77530715Sbostic if ((s = *cpp) && streq(s, cp)) { 77630863Skarels pp->p_fstype = cpp - fstypenames; 77730863Skarels goto gottype; 77830715Sbostic } 77930715Sbostic v = atoi(cp); 78030715Sbostic if ((unsigned)v >= FSMAXTYPES) 78130715Sbostic fprintf(stderr, "line %d: %s %s\n", lineno, 78230715Sbostic "Warning, unknown filesystem type", cp); 78330863Skarels pp->p_fstype = v; 78430863Skarels gottype: 78530863Skarels 78630863Skarels switch (pp->p_fstype) { 78730863Skarels 78830863Skarels case FS_UNUSED: /* XXX */ 78930863Skarels NXTNUM(pp->p_fsize); 79030863Skarels if (pp->p_fsize == 0) 79130863Skarels break; 79230863Skarels NXTNUM(v); 79330863Skarels pp->p_frag = v / pp->p_fsize; 79430863Skarels break; 79530863Skarels 79630863Skarels case FS_BSDFFS: 79730863Skarels NXTNUM(pp->p_fsize); 79830863Skarels if (pp->p_fsize == 0) 79930863Skarels break; 80030863Skarels NXTNUM(v); 80130863Skarels pp->p_frag = v / pp->p_fsize; 80230863Skarels NXTNUM(pp->p_cpg); 80330863Skarels break; 80430863Skarels 80530863Skarels default: 80630863Skarels break; 80730863Skarels } 80830715Sbostic continue; 80930715Sbostic } 81030715Sbostic fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 81130715Sbostic lineno, cp); 81230715Sbostic errors++; 81330715Sbostic next: 81430715Sbostic ; 81530715Sbostic } 81630715Sbostic errors += checklabel(lp); 81730715Sbostic return (errors == 0); 81830418Skarels } 81930418Skarels 82030715Sbostic /* 82130715Sbostic * Check disklabel for errors and fill in 82230715Sbostic * derived fields according to supplied values. 82330715Sbostic */ 82430715Sbostic checklabel(lp) 82530715Sbostic register struct disklabel *lp; 82630418Skarels { 82730715Sbostic register struct partition *pp; 82830715Sbostic int i, errors = 0; 82930715Sbostic char part; 83030418Skarels 83130715Sbostic if (lp->d_secsize == 0) { 83230715Sbostic fprintf(stderr, "sector size %d\n", lp->d_secsize); 83330715Sbostic return (1); 83430715Sbostic } 83530715Sbostic if (lp->d_nsectors == 0) { 83630715Sbostic fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 83730715Sbostic return (1); 83830715Sbostic } 83930715Sbostic if (lp->d_ntracks == 0) { 84030715Sbostic fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 84130715Sbostic return (1); 84230715Sbostic } 84330715Sbostic if (lp->d_ncylinders == 0) { 84430715Sbostic fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 84530715Sbostic errors++; 84630715Sbostic } 84730715Sbostic if (lp->d_rpm == 0) 84830715Sbostic Warning("revolutions/minute %d\n", lp->d_rpm); 84930715Sbostic if (lp->d_secpercyl == 0) 85030715Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 85130715Sbostic if (lp->d_secperunit == 0) 85230715Sbostic lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 85330715Sbostic if (lp->d_bbsize == 0) { 85430715Sbostic fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 85530715Sbostic errors++; 85630715Sbostic } else if (lp->d_bbsize % lp->d_secsize) 85730715Sbostic Warning("boot block size %% sector-size != 0\n"); 85830715Sbostic if (lp->d_sbsize == 0) { 85930715Sbostic fprintf(stderr, "super block size %d\n", lp->d_sbsize); 86030715Sbostic errors++; 86130715Sbostic } else if (lp->d_sbsize % lp->d_secsize) 86230715Sbostic Warning("super block size %% sector-size != 0\n"); 86330715Sbostic if (lp->d_npartitions > MAXPARTITIONS) 86430715Sbostic Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 86530715Sbostic lp->d_npartitions, MAXPARTITIONS); 86630715Sbostic for (i = 0; i < lp->d_npartitions; i++) { 86730715Sbostic part = 'a' + i; 86830715Sbostic pp = &lp->d_partitions[i]; 86930715Sbostic if (pp->p_size == 0 && pp->p_offset != 0) 87030715Sbostic Warning("partition %c: size 0, but offset %d\n", 87130715Sbostic part, pp->p_offset); 87230715Sbostic #ifdef notdef 87330715Sbostic if (pp->p_size % lp->d_secpercyl) 87430715Sbostic Warning("partition %c: size %% cylinder-size != 0\n", 87530715Sbostic part); 87630715Sbostic if (pp->p_offset % lp->d_secpercyl) 87730715Sbostic Warning("partition %c: offset %% cylinder-size != 0\n", 87830715Sbostic part); 87930715Sbostic #endif 88030715Sbostic if (pp->p_offset > lp->d_secperunit) { 88130715Sbostic fprintf(stderr, 88230715Sbostic "partition %c: offset past end of unit\n", part); 88330715Sbostic errors++; 88430715Sbostic } 88530715Sbostic if (pp->p_offset + pp->p_size > lp->d_secperunit) { 88630715Sbostic fprintf(stderr, 88730715Sbostic "partition %c: partition extends past end of unit\n", 88830715Sbostic part); 88930715Sbostic errors++; 89030715Sbostic } 89130715Sbostic } 89230715Sbostic for (; i < MAXPARTITIONS; i++) { 89330715Sbostic part = 'a' + i; 89430715Sbostic pp = &lp->d_partitions[i]; 89530715Sbostic if (pp->p_size || pp->p_offset) 89630715Sbostic Warning("unused partition %c: size %d offset %d\n", 89730715Sbostic pp->p_size, pp->p_offset); 89830715Sbostic } 89930715Sbostic return (errors); 90030715Sbostic } 90130715Sbostic 90230715Sbostic /*VARARGS1*/ 90330715Sbostic Warning(fmt, a1, a2, a3, a4, a5) 90430715Sbostic char *fmt; 90530715Sbostic { 90630715Sbostic 90730715Sbostic fprintf(stderr, "Warning, "); 90830715Sbostic fprintf(stderr, fmt, a1, a2, a3, a4, a5); 90930715Sbostic fprintf(stderr, "\n"); 91030715Sbostic } 91130715Sbostic 91230715Sbostic Perror(str) 91330715Sbostic char *str; 91430715Sbostic { 91530715Sbostic fputs("disklabel: ", stderr); perror(str); 91630418Skarels exit(4); 91730418Skarels } 91830715Sbostic 91930715Sbostic usage() 92030715Sbostic { 92130715Sbostic #ifdef BOOT 92230715Sbostic fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n", 92330715Sbostic "usage: disklabel [-r] disk", "(to read label)", 92430715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 92530715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 92630715Sbostic "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 92730715Sbostic #else 92830715Sbostic fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 92930715Sbostic "usage: disklabel [-r] disk", "(to read label)", 93030715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 93130715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 93230715Sbostic "or disklabel -R [-r] disk protofile", "(to restore label)"); 93330715Sbostic #endif 93430715Sbostic exit(1); 93530715Sbostic } 936