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*31401Skarels static char sccsid[] = "@(#)disklabel.c 5.8 (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]); 154*31401Skarels #ifdef BOOT 155*31401Skarels rflag = 1; /* force bootstrap to be written */ 156*31401Skarels #endif 15730715Sbostic if (getasciilabel(t, lp)) 15830715Sbostic writelabel(f, bootarea, lp); 15930418Skarels break; 16030418Skarels case WRITE: 16130715Sbostic type = argv[1]; 16230715Sbostic #ifdef BOOT 16330715Sbostic if (argc > 5 || argc < 2) 16430715Sbostic usage(); 16530715Sbostic if (argc > 3) { 16630715Sbostic bootxx = argv[--argc]; 16730715Sbostic xxboot = argv[--argc]; 16830715Sbostic } 16930715Sbostic #else 17030715Sbostic if (argc > 3 || argc < 2) 17130715Sbostic usage(); 17230715Sbostic #endif 17330715Sbostic if (argc > 2) 17430715Sbostic name = argv[--argc]; 17530418Skarels makelabel(type, name, &lab); 17630418Skarels lp = getbootarea(bootarea, &lab); 17730418Skarels *lp = lab; 178*31401Skarels #ifdef BOOT 179*31401Skarels rflag = 1; /* force bootstrap to be written */ 180*31401Skarels #endif 18130715Sbostic if (checklabel(lp) == 0) 18230715Sbostic writelabel(f, bootarea, lp); 18330418Skarels break; 18430418Skarels } 18530418Skarels exit(0); 18630418Skarels } 18730418Skarels 18830418Skarels makelabel(type, name, lp) 18930418Skarels char *type, *name; 19030418Skarels register struct disklabel *lp; 19130418Skarels { 19230418Skarels register struct disklabel *dp; 19330418Skarels 19430418Skarels dp = getdiskbyname(type); 19530418Skarels if (dp == NULL) { 19630418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 19730418Skarels exit(1); 19830418Skarels } 19930418Skarels *lp = *dp; 20030418Skarels if (name) 20130715Sbostic (void)strncpy(lp->d_name, name, sizeof(lp->d_name)); 20230418Skarels } 20330418Skarels 20430418Skarels writelabel(f, boot, lp) 20530418Skarels int f; 20630418Skarels char *boot; 20730418Skarels register struct disklabel *lp; 20830418Skarels { 20930715Sbostic register int i; 21030715Sbostic long lseek(); 21130418Skarels 21230418Skarels lp->d_magic = DISKMAGIC; 21330418Skarels lp->d_magic2 = DISKMAGIC; 21430418Skarels lp->d_checksum = 0; 21530418Skarels lp->d_checksum = dkcksum(lp); 21630715Sbostic (void)lseek(f, (off_t)0, L_SET); 21730677Skarels if (rflag) { 21830677Skarels if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 21930677Skarels Perror("write"); 22030677Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 22130677Skarels Perror("ioctl DIOCSDINFO"); 22230677Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) 22330677Skarels Perror("ioctl DIOCWDINFO"); 22430419Skarels #if vax 22530677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 22630677Skarels daddr_t alt; 22730677Skarels 22830677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 22930677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 23030715Sbostic (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 23130677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 23230677Skarels int oerrno = errno; 23330677Skarels fprintf(stderr, "alternate label %d ", i/2); 23430677Skarels errno = oerrno; 23530677Skarels perror("write"); 23630677Skarels } 23730418Skarels } 23830418Skarels } 23930419Skarels #endif 24030418Skarels } 24130418Skarels 24230418Skarels /* 24330418Skarels * Read disklabel from disk. 24430418Skarels * If boot is given, need bootstrap too. 24530677Skarels * If boot not needed, use ioctl to get label 24630677Skarels * unless -r flag is given. 24730418Skarels */ 24830418Skarels struct disklabel * 24930418Skarels readlabel(f, boot) 25030418Skarels int f; 25130418Skarels char *boot; 25230418Skarels { 25330418Skarels register struct disklabel *lp; 25430677Skarels register char *buf; 25530418Skarels 25630677Skarels if (boot) 25730677Skarels buf = boot; 25830677Skarels else 25930677Skarels buf = bootarea; 26030677Skarels lp = (struct disklabel *)(buf + LABELOFFSET); 261*31401Skarels if (boot || rflag) 262*31401Skarels if (read(f, buf, BBSIZE) < BBSIZE) 263*31401Skarels Perror(specname); 264*31401Skarels if (rflag == 0) { 26530677Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 26630677Skarels Perror("ioctl DIOCGDINFO"); 26730677Skarels } else { 26830677Skarels for (lp = (struct disklabel *)buf; 26930677Skarels lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp)); 27030677Skarels lp = (struct disklabel *)((char *)lp + 16)) 27130677Skarels if (lp->d_magic == DISKMAGIC && 27230677Skarels lp->d_magic2 == DISKMAGIC) 27330677Skarels break; 27430677Skarels if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) || 27530677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 27630677Skarels dkcksum(lp) != 0) { 27730677Skarels fprintf(stderr, 27830418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 27930677Skarels exit(1); 28030677Skarels } 28130418Skarels } 28230418Skarels return (lp); 28330418Skarels } 28430418Skarels 28530418Skarels struct disklabel * 28630418Skarels getbootarea(boot, dp) 28730418Skarels char *boot; 28830418Skarels register struct disklabel *dp; 28930418Skarels { 29030418Skarels struct disklabel *lp; 29130418Skarels register char *p; 29230418Skarels int b; 29330418Skarels 29430418Skarels #ifdef BOOT 29530715Sbostic char *dkbasename; 29630715Sbostic 29730418Skarels if (xxboot == NULL) { 29830418Skarels dkbasename = np; 29930418Skarels if ((p = rindex(dkname, '/')) == NULL) 30030418Skarels p = dkname; 30130418Skarels else 30230418Skarels p++; 30330418Skarels while (*p && !isdigit(*p)) 30430418Skarels *np++ = *p++; 30530418Skarels *np++ = '\0'; 30630418Skarels 30730418Skarels sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 30830418Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 30930418Skarels dkbasename++; 31030418Skarels xxboot = np; 31130418Skarels sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 31230418Skarels np += strlen(xxboot) + 1; 31330418Skarels 31430418Skarels bootxx = np; 31530418Skarels sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 31630418Skarels np += strlen(bootxx) + 1; 31730418Skarels } 31830418Skarels 31930418Skarels b = open(xxboot, O_RDONLY); 32030418Skarels if (b < 0) 32130418Skarels Perror(xxboot); 32230715Sbostic if (read(b, boot, (int)dp->d_secsize) < 0) 32330418Skarels Perror(xxboot); 32430418Skarels close(b); 32530418Skarels b = open(bootxx, O_RDONLY); 32630418Skarels if (b < 0) 32730418Skarels Perror(bootxx); 32830715Sbostic if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 32930418Skarels Perror(bootxx); 33030715Sbostic (void)close(b); 33130418Skarels #endif 33230418Skarels 33330418Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 33430418Skarels LABELOFFSET); 33530418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 33630418Skarels if (*p) { 33730418Skarels fprintf(stderr, 33830418Skarels "Bootstrap doesn't leave room for disk label\n"); 33930418Skarels exit(2); 34030418Skarels } 34130418Skarels return (lp); 34230418Skarels } 34330418Skarels 34430418Skarels display(f, lp) 34530418Skarels FILE *f; 34630418Skarels register struct disklabel *lp; 34730418Skarels { 34830715Sbostic register int i, j; 34930418Skarels register struct partition *pp; 35030418Skarels 35130418Skarels fprintf(f, "# %s:\n", specname); 35230418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 35330418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 35430418Skarels else 35530418Skarels fprintf(f, "type: %d\n", lp->d_type); 35630418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 35730418Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 358*31401Skarels fprintf(f, "flags:"); 35930418Skarels if (lp->d_flags & D_REMOVABLE) 360*31401Skarels fprintf(f, " removeable"); 36130418Skarels if (lp->d_flags & D_ECC) 362*31401Skarels fprintf(f, " ecc"); 36330418Skarels if (lp->d_flags & D_BADSECT) 364*31401Skarels fprintf(f, " badsect"); 36530418Skarels fprintf(f, "\n"); 36630418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 36730418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 36830418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 36931386Skarels fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 37030418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 37130715Sbostic fprintf(f, "rpm: %d\n", lp->d_rpm); 37230418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 37330418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 37430418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 37530418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 37630418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 37730418Skarels fprintf(f, "drivedata: "); 37830418Skarels for (i = NDDATA - 1; i >= 0; i--) 37930418Skarels if (lp->d_drivedata[i]) 38030418Skarels break; 38130418Skarels if (i < 0) 38230418Skarels i = 0; 38330418Skarels for (j = 0; j <= i; j++) 38430418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 38530418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 38630863Skarels fprintf(f, 38730863Skarels "# size offset fstype [fsize bsize cpg]\n"); 38830418Skarels pp = lp->d_partitions; 38930418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 39030418Skarels if (pp->p_size) { 39130863Skarels fprintf(f, " %c: %8d %8d ", 'a' + i, 39230863Skarels pp->p_size, pp->p_offset); 39330418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 39430418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 39530418Skarels else 39630418Skarels fprintf(f, "%8d", pp->p_fstype); 39730863Skarels switch (pp->p_fstype) { 39830863Skarels 39930863Skarels case FS_UNUSED: /* XXX */ 40030863Skarels fprintf(f, " %5d %5d %5.5s ", 40130863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 40230863Skarels break; 40330863Skarels 40430863Skarels case FS_BSDFFS: 40530863Skarels fprintf(f, " %5d %5d %5d ", 40630863Skarels pp->p_fsize, pp->p_fsize * pp->p_frag, 40730863Skarels pp->p_cpg); 40830863Skarels break; 40930863Skarels 41030863Skarels default: 41130863Skarels fprintf(f, "%20.20s", ""); 41230863Skarels break; 41330863Skarels } 41430418Skarels fprintf(f, "\t# (Cyl. %4d", 41530418Skarels pp->p_offset / lp->d_secpercyl); 41630418Skarels if (pp->p_offset % lp->d_secpercyl) 41730418Skarels putc('*', f); 41830418Skarels else 41930418Skarels putc(' ', f); 42030418Skarels fprintf(f, "- %d", 42130418Skarels (pp->p_offset + 42230418Skarels pp->p_size + lp->d_secpercyl - 1) / 42330418Skarels lp->d_secpercyl - 1); 42430418Skarels if (pp->p_size % lp->d_secpercyl) 42530418Skarels putc('*', f); 42630863Skarels fprintf(f, ")\n"); 42730418Skarels } 42830418Skarels } 42930418Skarels } 43030418Skarels 43130715Sbostic edit(lp) 43230715Sbostic struct disklabel *lp; 43330418Skarels { 43430715Sbostic register int c; 43530715Sbostic struct disklabel label; 43630715Sbostic FILE *fd; 43730715Sbostic char *mktemp(); 43830715Sbostic 43930715Sbostic (void) mktemp(tmpfil); 44030715Sbostic fd = fopen(tmpfil, "w"); 44130715Sbostic if (fd == NULL) { 44230715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 44330715Sbostic return (0); 44430715Sbostic } 44530715Sbostic (void)fchmod(fd, 0600); 44630715Sbostic display(fd, lp); 44730715Sbostic fclose(fd); 44830715Sbostic for (;;) { 44930715Sbostic if (!editit()) 45030715Sbostic break; 45130715Sbostic fd = fopen(tmpfil, "r"); 45230715Sbostic if (fd == NULL) { 45330715Sbostic fprintf(stderr, "%s: Can't reopen for reading\n"); 45430715Sbostic break; 45530715Sbostic } 45630863Skarels bzero((char *)&label, sizeof(label)); 45730715Sbostic if (getasciilabel(fd, &label)) { 45830715Sbostic *lp = label; 45930715Sbostic (void) unlink(tmpfil); 46030715Sbostic return (1); 46130715Sbostic } 46230715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 46330715Sbostic c = getchar(); 46430715Sbostic if (c != EOF && c != (int)'\n') 46530715Sbostic while (getchar() != (int)'\n') 46630715Sbostic ; 46730715Sbostic if (c == (int)'n') 46830715Sbostic break; 46930715Sbostic } 47030715Sbostic (void) unlink(tmpfil); 47130715Sbostic return (0); 47230418Skarels } 47330418Skarels 47430715Sbostic editit() 47530715Sbostic { 47630715Sbostic register int pid, xpid; 47730715Sbostic int stat, omask; 47830715Sbostic extern char *getenv(); 47930418Skarels 48030715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 48130715Sbostic while ((pid = fork()) < 0) { 48230715Sbostic extern int errno; 48330715Sbostic 48430715Sbostic if (errno == EPROCLIM) { 48530715Sbostic fprintf(stderr, "You have too many processes\n"); 48630715Sbostic return(0); 48730715Sbostic } 48830715Sbostic if (errno != EAGAIN) { 48930715Sbostic perror("fork"); 49030715Sbostic return(0); 49130715Sbostic } 49230715Sbostic sleep(1); 49330715Sbostic } 49430715Sbostic if (pid == 0) { 49530715Sbostic register char *ed; 49630715Sbostic 49730715Sbostic sigsetmask(omask); 49830715Sbostic setgid(getgid()); 49930715Sbostic setuid(getuid()); 50030715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 50130715Sbostic ed = DEFEDITOR; 50230715Sbostic execlp(ed, ed, tmpfil, 0); 50330715Sbostic perror(ed); 50430715Sbostic exit(1); 50530715Sbostic } 50630715Sbostic while ((xpid = wait(&stat)) >= 0) 50730715Sbostic if (xpid == pid) 50830715Sbostic break; 50930715Sbostic sigsetmask(omask); 51030715Sbostic return(!stat); 51130715Sbostic } 51230715Sbostic 51330715Sbostic char * 51430715Sbostic skip(cp) 51530715Sbostic register char *cp; 51630715Sbostic { 51730715Sbostic 51830715Sbostic while (*cp != '\0' && isspace(*cp)) 51930715Sbostic cp++; 52030715Sbostic if (*cp == '\0' || *cp == '#') 52130715Sbostic return ((char *)NULL); 52230715Sbostic return (cp); 52330715Sbostic } 52430715Sbostic 52530715Sbostic char * 52630715Sbostic word(cp) 52730715Sbostic register char *cp; 52830715Sbostic { 52930715Sbostic register char c; 53030715Sbostic 531*31401Skarels while (*cp != '\0' && !isspace(*cp) && *cp != '#') 532*31401Skarels cp++; 53330715Sbostic if ((c = *cp) != '\0') { 53430715Sbostic *cp++ = '\0'; 53530715Sbostic if (c != '#') 53630715Sbostic return (skip(cp)); 53730715Sbostic } 53830715Sbostic return ((char *)NULL); 53930715Sbostic } 54030715Sbostic 54130418Skarels /* 54230418Skarels * Read an ascii label in from fd f, 54330418Skarels * in the same format as that put out by display(), 54430418Skarels * and fill in lp. 54530418Skarels */ 54630418Skarels getasciilabel(f, lp) 54730715Sbostic FILE *f; 54830418Skarels register struct disklabel *lp; 54930418Skarels { 55030715Sbostic register char **cpp, *cp; 55130863Skarels register struct partition *pp; 55230715Sbostic char *tp, *s, line[BUFSIZ]; 55330715Sbostic int v, lineno = 0, errors = 0; 55430715Sbostic 55530715Sbostic lp->d_bbsize = BBSIZE; /* XXX */ 55630715Sbostic lp->d_sbsize = SBSIZE; /* XXX */ 55730715Sbostic while (fgets(line, sizeof(line) - 1, f)) { 55830715Sbostic lineno++; 55930715Sbostic if (cp = index(line,'\n')) 56030715Sbostic *cp = '\0'; 56130715Sbostic cp = skip(line); 56230715Sbostic if (cp == NULL) 56330715Sbostic continue; 56430715Sbostic tp = index(cp, ':'); 56530715Sbostic if (tp == NULL) { 56630715Sbostic fprintf(stderr, "line %d: syntax error\n", lineno); 56730715Sbostic errors++; 56830715Sbostic continue; 56930715Sbostic } 57030715Sbostic *tp++ = '\0', tp = skip(tp); 57130715Sbostic if (streq(cp, "type")) { 57230715Sbostic if (tp == NULL) 57330715Sbostic tp = "unknown"; 57430715Sbostic cpp = dktypenames; 57530715Sbostic for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 57630715Sbostic if ((s = *cpp) && streq(s, tp)) { 57730715Sbostic lp->d_type = cpp - dktypenames; 57830715Sbostic goto next; 57930715Sbostic } 58030715Sbostic v = atoi(tp); 58130715Sbostic if ((unsigned)v >= DKMAXTYPES) 58230715Sbostic fprintf(stderr, "line %d:%s %d\n", lineno, 58330715Sbostic "Warning, unknown disk type", v); 58430715Sbostic lp->d_type = v; 58530715Sbostic continue; 58630715Sbostic } 58730715Sbostic if (streq(cp, "flags")) { 58831386Skarels for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) { 58930715Sbostic if (streq(cp, "removeable")) 59030715Sbostic v |= D_REMOVABLE; 59130715Sbostic else if (streq(cp, "ecc")) 59230715Sbostic v |= D_ECC; 59330715Sbostic else if (streq(cp, "badsect")) 59430715Sbostic v |= D_BADSECT; 59530715Sbostic else { 59630715Sbostic fprintf(stderr, 59730715Sbostic "line %d: %s: bad flag\n", 59830715Sbostic lineno, cp); 59930715Sbostic errors++; 60030715Sbostic } 60130715Sbostic } 60230715Sbostic lp->d_flags = v; 60330715Sbostic continue; 60430715Sbostic } 60530715Sbostic if (streq(cp, "drivedata")) { 60630715Sbostic register int i; 60730715Sbostic 60831386Skarels for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 60930715Sbostic lp->d_drivedata[i++] = atoi(cp); 61031386Skarels tp = word(cp); 61130715Sbostic } 61230715Sbostic continue; 61330715Sbostic } 61430715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 61530863Skarels if (v == 0 || (unsigned)v > MAXPARTITIONS) { 61630715Sbostic fprintf(stderr, 61730715Sbostic "line %d: bad # of partitions\n", lineno); 61830863Skarels lp->d_npartitions = MAXPARTITIONS; 61930863Skarels errors++; 62030863Skarels } else 62130715Sbostic lp->d_npartitions = v; 62230715Sbostic continue; 62330715Sbostic } 62430715Sbostic if (tp == NULL) 62530715Sbostic tp = ""; 62630715Sbostic if (streq(cp, "disk")) { 62730715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 62830715Sbostic continue; 62930715Sbostic } 63030715Sbostic if (streq(cp, "label")) { 63130715Sbostic strncpy(lp->d_name, tp, sizeof (lp->d_name)); 63230715Sbostic continue; 63330715Sbostic } 63430715Sbostic if (streq(cp, "bytes/sector")) { 63530715Sbostic v = atoi(tp); 63630715Sbostic if (v <= 0 || (v % 512) != 0) { 63730715Sbostic fprintf(stderr, 63830715Sbostic "line %d: %s: bad sector size\n", 63930715Sbostic lineno, tp); 64030715Sbostic errors++; 64130715Sbostic } else 64230715Sbostic lp->d_secsize = v; 64330715Sbostic continue; 64430715Sbostic } 64530715Sbostic if (streq(cp, "sectors/track")) { 64630715Sbostic v = atoi(tp); 64730715Sbostic if (v <= 0) { 64830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 64930715Sbostic lineno, tp, cp); 65030715Sbostic errors++; 65130715Sbostic } else 65230715Sbostic lp->d_nsectors = v; 65330715Sbostic continue; 65430715Sbostic } 65531386Skarels if (streq(cp, "sectors/cylinder")) { 65631386Skarels v = atoi(tp); 65731386Skarels if (v <= 0) { 65831386Skarels fprintf(stderr, "line %d: %s: bad %s\n", 65931386Skarels lineno, tp, cp); 66031386Skarels errors++; 66131386Skarels } else 66231386Skarels lp->d_secpercyl = v; 66331386Skarels continue; 66431386Skarels } 66530715Sbostic if (streq(cp, "tracks/cylinder")) { 66630715Sbostic v = atoi(tp); 66730715Sbostic if (v <= 0) { 66830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 66930715Sbostic lineno, tp, cp); 67030715Sbostic errors++; 67130715Sbostic } else 67230715Sbostic lp->d_ntracks = v; 67330715Sbostic continue; 67430715Sbostic } 67530715Sbostic if (streq(cp, "cylinders")) { 67630715Sbostic v = atoi(tp); 67730715Sbostic if (v <= 0) { 67830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 67930715Sbostic lineno, tp, cp); 68030715Sbostic errors++; 68130715Sbostic } else 68230715Sbostic lp->d_ncylinders = v; 68330715Sbostic continue; 68430715Sbostic } 68530715Sbostic if (streq(cp, "rpm")) { 68630715Sbostic v = atoi(tp); 68730715Sbostic if (v <= 0) { 68830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 68930715Sbostic lineno, tp, cp); 69030715Sbostic errors++; 69130715Sbostic } else 69230715Sbostic lp->d_rpm = v; 69330715Sbostic continue; 69430715Sbostic } 69530715Sbostic if (streq(cp, "interleave")) { 69630715Sbostic v = atoi(tp); 69730715Sbostic if (v <= 0) { 69830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 69930715Sbostic lineno, tp, cp); 70030715Sbostic errors++; 70130715Sbostic } else 70230715Sbostic lp->d_interleave = v; 70330715Sbostic continue; 70430715Sbostic } 70530715Sbostic if (streq(cp, "trackskew")) { 70630715Sbostic v = atoi(tp); 70730715Sbostic if (v < 0) { 70830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 70930715Sbostic lineno, tp, cp); 71030715Sbostic errors++; 71130715Sbostic } else 71230715Sbostic lp->d_trackskew = v; 71330715Sbostic continue; 71430715Sbostic } 71530715Sbostic if (streq(cp, "cylinderskew")) { 71630715Sbostic v = atoi(tp); 71730715Sbostic if (v < 0) { 71830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 71930715Sbostic lineno, tp, cp); 72030715Sbostic errors++; 72130715Sbostic } else 72230715Sbostic lp->d_cylskew = v; 72330715Sbostic continue; 72430715Sbostic } 72530715Sbostic if (streq(cp, "headswitch")) { 72630715Sbostic v = atoi(tp); 72730715Sbostic if (v < 0) { 72830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 72930715Sbostic lineno, tp, cp); 73030715Sbostic errors++; 73130715Sbostic } else 73230715Sbostic lp->d_headswitch = v; 73330715Sbostic continue; 73430715Sbostic } 73530715Sbostic if (streq(cp, "track-to-track seek")) { 73630715Sbostic v = atoi(tp); 73730715Sbostic if (v < 0) { 73830715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 73930715Sbostic lineno, tp, cp); 74030715Sbostic errors++; 74130715Sbostic } else 74230715Sbostic lp->d_trkseek = v; 74330715Sbostic continue; 74430715Sbostic } 74530715Sbostic if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 74630863Skarels unsigned part = *cp - 'a'; 74730715Sbostic 74830863Skarels if (part > lp->d_npartitions) { 74930715Sbostic fprintf(stderr, 75030715Sbostic "line %d: bad partition name\n", lineno); 75130715Sbostic errors++; 75230715Sbostic continue; 75330715Sbostic } 75430863Skarels pp = &lp->d_partitions[part]; 75530863Skarels #define NXTNUM(n) { \ 75630863Skarels cp = tp, tp = word(cp); \ 75730863Skarels if (tp == NULL) \ 75830863Skarels tp = cp; \ 75930863Skarels (n) = atoi(cp); \ 76030863Skarels } 76130863Skarels 76230863Skarels NXTNUM(v); 76330715Sbostic if (v < 0) { 76430715Sbostic fprintf(stderr, 76530715Sbostic "line %d: %s: bad partition size\n", 76630715Sbostic lineno, cp); 76730715Sbostic errors++; 76830715Sbostic } else 76930863Skarels pp->p_size = v; 77030863Skarels NXTNUM(v); 77130715Sbostic if (v < 0) { 77230715Sbostic fprintf(stderr, 77330715Sbostic "line %d: %s: bad partition offset\n", 77430715Sbostic lineno, cp); 77530715Sbostic errors++; 77630715Sbostic } else 77730863Skarels pp->p_offset = v; 77830715Sbostic cp = tp, tp = word(cp); 77930715Sbostic cpp = fstypenames; 78030715Sbostic for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 78130715Sbostic if ((s = *cpp) && streq(s, cp)) { 78230863Skarels pp->p_fstype = cpp - fstypenames; 78330863Skarels goto gottype; 78430715Sbostic } 78530715Sbostic v = atoi(cp); 78630715Sbostic if ((unsigned)v >= FSMAXTYPES) 78730715Sbostic fprintf(stderr, "line %d: %s %s\n", lineno, 78830715Sbostic "Warning, unknown filesystem type", cp); 78930863Skarels pp->p_fstype = v; 79030863Skarels gottype: 79130863Skarels 79230863Skarels switch (pp->p_fstype) { 79330863Skarels 79430863Skarels case FS_UNUSED: /* XXX */ 79530863Skarels NXTNUM(pp->p_fsize); 79630863Skarels if (pp->p_fsize == 0) 79730863Skarels break; 79830863Skarels NXTNUM(v); 79930863Skarels pp->p_frag = v / pp->p_fsize; 80030863Skarels break; 80130863Skarels 80230863Skarels case FS_BSDFFS: 80330863Skarels NXTNUM(pp->p_fsize); 80430863Skarels if (pp->p_fsize == 0) 80530863Skarels break; 80630863Skarels NXTNUM(v); 80730863Skarels pp->p_frag = v / pp->p_fsize; 80830863Skarels NXTNUM(pp->p_cpg); 80930863Skarels break; 81030863Skarels 81130863Skarels default: 81230863Skarels break; 81330863Skarels } 81430715Sbostic continue; 81530715Sbostic } 81630715Sbostic fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 81730715Sbostic lineno, cp); 81830715Sbostic errors++; 81930715Sbostic next: 82030715Sbostic ; 82130715Sbostic } 82230715Sbostic errors += checklabel(lp); 82330715Sbostic return (errors == 0); 82430418Skarels } 82530418Skarels 82630715Sbostic /* 82730715Sbostic * Check disklabel for errors and fill in 82830715Sbostic * derived fields according to supplied values. 82930715Sbostic */ 83030715Sbostic checklabel(lp) 83130715Sbostic register struct disklabel *lp; 83230418Skarels { 83330715Sbostic register struct partition *pp; 83430715Sbostic int i, errors = 0; 83530715Sbostic char part; 83630418Skarels 83730715Sbostic if (lp->d_secsize == 0) { 83830715Sbostic fprintf(stderr, "sector size %d\n", lp->d_secsize); 83930715Sbostic return (1); 84030715Sbostic } 84130715Sbostic if (lp->d_nsectors == 0) { 84230715Sbostic fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 84330715Sbostic return (1); 84430715Sbostic } 84530715Sbostic if (lp->d_ntracks == 0) { 84630715Sbostic fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 84730715Sbostic return (1); 84830715Sbostic } 84930715Sbostic if (lp->d_ncylinders == 0) { 85030715Sbostic fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 85130715Sbostic errors++; 85230715Sbostic } 85330715Sbostic if (lp->d_rpm == 0) 85430715Sbostic Warning("revolutions/minute %d\n", lp->d_rpm); 85530715Sbostic if (lp->d_secpercyl == 0) 85630715Sbostic lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 85730715Sbostic if (lp->d_secperunit == 0) 85830715Sbostic lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 85930715Sbostic if (lp->d_bbsize == 0) { 86030715Sbostic fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 86130715Sbostic errors++; 86230715Sbostic } else if (lp->d_bbsize % lp->d_secsize) 86330715Sbostic Warning("boot block size %% sector-size != 0\n"); 86430715Sbostic if (lp->d_sbsize == 0) { 86530715Sbostic fprintf(stderr, "super block size %d\n", lp->d_sbsize); 86630715Sbostic errors++; 86730715Sbostic } else if (lp->d_sbsize % lp->d_secsize) 86830715Sbostic Warning("super block size %% sector-size != 0\n"); 86930715Sbostic if (lp->d_npartitions > MAXPARTITIONS) 87030715Sbostic Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 87130715Sbostic lp->d_npartitions, MAXPARTITIONS); 87230715Sbostic for (i = 0; i < lp->d_npartitions; i++) { 87330715Sbostic part = 'a' + i; 87430715Sbostic pp = &lp->d_partitions[i]; 87530715Sbostic if (pp->p_size == 0 && pp->p_offset != 0) 87630715Sbostic Warning("partition %c: size 0, but offset %d\n", 87730715Sbostic part, pp->p_offset); 87830715Sbostic #ifdef notdef 87930715Sbostic if (pp->p_size % lp->d_secpercyl) 88030715Sbostic Warning("partition %c: size %% cylinder-size != 0\n", 88130715Sbostic part); 88230715Sbostic if (pp->p_offset % lp->d_secpercyl) 88330715Sbostic Warning("partition %c: offset %% cylinder-size != 0\n", 88430715Sbostic part); 88530715Sbostic #endif 88630715Sbostic if (pp->p_offset > lp->d_secperunit) { 88730715Sbostic fprintf(stderr, 88830715Sbostic "partition %c: offset past end of unit\n", part); 88930715Sbostic errors++; 89030715Sbostic } 89130715Sbostic if (pp->p_offset + pp->p_size > lp->d_secperunit) { 89230715Sbostic fprintf(stderr, 89330715Sbostic "partition %c: partition extends past end of unit\n", 89430715Sbostic part); 89530715Sbostic errors++; 89630715Sbostic } 89730715Sbostic } 89830715Sbostic for (; i < MAXPARTITIONS; i++) { 89930715Sbostic part = 'a' + i; 90030715Sbostic pp = &lp->d_partitions[i]; 90130715Sbostic if (pp->p_size || pp->p_offset) 90230715Sbostic Warning("unused partition %c: size %d offset %d\n", 90330715Sbostic pp->p_size, pp->p_offset); 90430715Sbostic } 90530715Sbostic return (errors); 90630715Sbostic } 90730715Sbostic 90830715Sbostic /*VARARGS1*/ 90930715Sbostic Warning(fmt, a1, a2, a3, a4, a5) 91030715Sbostic char *fmt; 91130715Sbostic { 91230715Sbostic 91330715Sbostic fprintf(stderr, "Warning, "); 91430715Sbostic fprintf(stderr, fmt, a1, a2, a3, a4, a5); 91530715Sbostic fprintf(stderr, "\n"); 91630715Sbostic } 91730715Sbostic 91830715Sbostic Perror(str) 91930715Sbostic char *str; 92030715Sbostic { 92130715Sbostic fputs("disklabel: ", stderr); perror(str); 92230418Skarels exit(4); 92330418Skarels } 92430715Sbostic 92530715Sbostic usage() 92630715Sbostic { 92730715Sbostic #ifdef BOOT 92830715Sbostic fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n", 92930715Sbostic "usage: disklabel [-r] disk", "(to read label)", 93030715Sbostic "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 93130715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 93230715Sbostic "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 93330715Sbostic #else 93430715Sbostic fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 93530715Sbostic "usage: disklabel [-r] disk", "(to read label)", 93630715Sbostic "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 93730715Sbostic "or disklabel -e [-r] disk", "(to edit label)", 93830715Sbostic "or disklabel -R [-r] disk protofile", "(to restore label)"); 93930715Sbostic #endif 94030715Sbostic exit(1); 94130715Sbostic } 942