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*31617Skarels static char sccsid[] = "@(#)disklabel.c 5.9 (Berkeley) 06/19/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 5530715Sbostic #ifdef BOOT 5630418Skarels char *xxboot; 5730418Skarels char *bootxx; 5830715Sbostic #endif 59*31617Skarels 60*31617Skarels char *dkname; 6130418Skarels char *specname; 6230715Sbostic char tmpfil[] = "/tmp/EdDk.aXXXXXX"; 6330418Skarels char *sprintf(); 6430418Skarels 6530418Skarels extern int errno; 6630418Skarels char namebuf[BBSIZE], *np = namebuf; 67*31617Skarels struct disklabel lab; 68*31617Skarels struct disklabel *readlabel(), *makebootarea(); 6930418Skarels char bootarea[BBSIZE]; 7030418Skarels 7130715Sbostic enum { READ, WRITE, EDIT, RESTORE } op = READ; 7230418Skarels 7330677Skarels int rflag; 7430677Skarels 7530418Skarels main(argc, argv) 7630418Skarels int argc; 7730418Skarels char *argv[]; 7830418Skarels { 7930715Sbostic extern int optind; 8030418Skarels register struct disklabel *lp; 8130715Sbostic FILE *t; 8230715Sbostic int ch, f; 8330715Sbostic char *name = 0, *type; 8430418Skarels 8530715Sbostic while ((ch = getopt(argc, argv, "Rerw")) != EOF) 8630715Sbostic switch((char)ch) { 8730715Sbostic case 'R': 8830715Sbostic op = RESTORE; 8930715Sbostic break; 9030715Sbostic case 'e': 9130715Sbostic op = EDIT; 9230715Sbostic break; 9330715Sbostic case 'r': 9430715Sbostic ++rflag; 9530715Sbostic break; 9630715Sbostic case 'w': 9730715Sbostic op = WRITE; 9830715Sbostic break; 9930715Sbostic case '?': 10030715Sbostic default: 10130715Sbostic usage(); 10230715Sbostic } 10330715Sbostic argc -= optind; 10430715Sbostic argv += optind; 10530715Sbostic if (argc < 1) 10630715Sbostic usage(); 10730715Sbostic 10830715Sbostic dkname = argv[0]; 10930418Skarels if (dkname[0] != '/') { 11030677Skarels sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION); 11130418Skarels specname = np; 11230418Skarels np += strlen(specname) + 1; 11330418Skarels } else 11430418Skarels specname = dkname; 11530418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 11630418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 11730418Skarels sprintf(specname, "/dev/r%s", dkname); 11830418Skarels np = namebuf + strlen(specname) + 1; 11930418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 12030418Skarels } 12130418Skarels if (f < 0) 12230418Skarels Perror(specname); 12330418Skarels 12430715Sbostic switch(op) { 12530715Sbostic case EDIT: 12630715Sbostic if (argc != 1) 12730715Sbostic usage(); 128*31617Skarels lp = readlabel(f, rflag); 12930715Sbostic if (edit(lp)) 13030715Sbostic writelabel(f, bootarea, lp); 13130715Sbostic break; 13230418Skarels case READ: 13330715Sbostic if (argc != 1) 13430715Sbostic usage(); 135*31617Skarels lp = readlabel(f, 0); 13630418Skarels display(stdout, lp); 13730715Sbostic (void) checklabel(lp); 13830418Skarels break; 13930715Sbostic case RESTORE: 14030715Sbostic #ifdef BOOT 14130715Sbostic if (argc == 4) { 14230715Sbostic xxboot = argv[2]; 14330715Sbostic bootxx = argv[3]; 144*31617Skarels } else 145*31617Skarels #endif 14630715Sbostic if (argc != 2) 14730715Sbostic usage(); 14830715Sbostic lab.d_secsize = DEV_BSIZE; /* XXX */ 14930715Sbostic lab.d_bbsize = BBSIZE; /* XXX */ 150*31617Skarels lp = makebootarea(bootarea, &lab); 15130715Sbostic if (!(t = fopen(argv[1],"r"))) 15230715Sbostic Perror(argv[1]); 15331401Skarels #ifdef BOOT 15431401Skarels rflag = 1; /* force bootstrap to be written */ 15531401Skarels #endif 15630715Sbostic if (getasciilabel(t, lp)) 15730715Sbostic writelabel(f, bootarea, lp); 15830418Skarels break; 15930418Skarels case WRITE: 16030715Sbostic type = argv[1]; 16130715Sbostic #ifdef BOOT 16230715Sbostic if (argc > 5 || argc < 2) 16330715Sbostic usage(); 16430715Sbostic if (argc > 3) { 16530715Sbostic bootxx = argv[--argc]; 16630715Sbostic xxboot = argv[--argc]; 16730715Sbostic } 16830715Sbostic #else 16930715Sbostic if (argc > 3 || argc < 2) 17030715Sbostic usage(); 17130715Sbostic #endif 17230715Sbostic if (argc > 2) 17330715Sbostic name = argv[--argc]; 17430418Skarels makelabel(type, name, &lab); 175*31617Skarels lp = makebootarea(bootarea, &lab); 17630418Skarels *lp = lab; 17731401Skarels #ifdef BOOT 17831401Skarels rflag = 1; /* force bootstrap to be written */ 17931401Skarels #endif 18030715Sbostic if (checklabel(lp) == 0) 18130715Sbostic writelabel(f, bootarea, lp); 18230418Skarels break; 18330418Skarels } 18430418Skarels exit(0); 18530418Skarels } 18630418Skarels 18730418Skarels makelabel(type, name, lp) 18830418Skarels char *type, *name; 18930418Skarels register struct disklabel *lp; 19030418Skarels { 19130418Skarels register struct disklabel *dp; 19230418Skarels 19330418Skarels dp = getdiskbyname(type); 19430418Skarels if (dp == NULL) { 19530418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 19630418Skarels exit(1); 19730418Skarels } 19830418Skarels *lp = *dp; 19930418Skarels if (name) 20030715Sbostic (void)strncpy(lp->d_name, name, sizeof(lp->d_name)); 20130418Skarels } 20230418Skarels 20330418Skarels writelabel(f, boot, lp) 20430418Skarels int f; 20530418Skarels char *boot; 20630418Skarels register struct disklabel *lp; 20730418Skarels { 20830715Sbostic register int i; 20930715Sbostic long lseek(); 21030418Skarels 21130418Skarels lp->d_magic = DISKMAGIC; 21230418Skarels lp->d_magic2 = DISKMAGIC; 21330418Skarels lp->d_checksum = 0; 21430418Skarels lp->d_checksum = dkcksum(lp); 21530677Skarels if (rflag) { 216*31617Skarels (void)lseek(f, (off_t)0, L_SET); 21730677Skarels if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 21830677Skarels Perror("write"); 21930677Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 22030677Skarels Perror("ioctl DIOCSDINFO"); 22130677Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) 22230677Skarels Perror("ioctl DIOCWDINFO"); 22330419Skarels #if vax 22430677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 22530677Skarels daddr_t alt; 22630677Skarels 22730677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 22830677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 22930715Sbostic (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 23030677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 23130677Skarels int oerrno = errno; 23230677Skarels fprintf(stderr, "alternate label %d ", i/2); 23330677Skarels errno = oerrno; 23430677Skarels perror("write"); 23530677Skarels } 23630418Skarels } 23730418Skarels } 23830419Skarels #endif 23930418Skarels } 24030418Skarels 24130418Skarels /* 242*31617Skarels * Fetch disklabel for disk. 243*31617Skarels * If needboot is given, need bootstrap too. 244*31617Skarels * Use ioctl to get label unless -r flag is given. 24530418Skarels */ 24630418Skarels struct disklabel * 247*31617Skarels readlabel(f, needboot) 248*31617Skarels int f, needboot; 24930418Skarels { 25030418Skarels register struct disklabel *lp; 25130418Skarels 252*31617Skarels if (needboot || rflag) { 253*31617Skarels lp = (struct disklabel *)(bootarea + LABELOFFSET); 254*31617Skarels if (read(f, bootarea, BBSIZE) < BBSIZE) 25531401Skarels Perror(specname); 256*31617Skarels } else 257*31617Skarels lp = &lab; 25831401Skarels if (rflag == 0) { 25930677Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 26030677Skarels Perror("ioctl DIOCGDINFO"); 26130677Skarels } else { 262*31617Skarels for (lp = (struct disklabel *)bootarea; 263*31617Skarels lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 26430677Skarels lp = (struct disklabel *)((char *)lp + 16)) 26530677Skarels if (lp->d_magic == DISKMAGIC && 26630677Skarels lp->d_magic2 == DISKMAGIC) 26730677Skarels break; 268*31617Skarels if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 26930677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 27030677Skarels dkcksum(lp) != 0) { 27130677Skarels fprintf(stderr, 27230418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 27330677Skarels exit(1); 27430677Skarels } 27530418Skarels } 27630418Skarels return (lp); 27730418Skarels } 27830418Skarels 27930418Skarels struct disklabel * 280*31617Skarels makebootarea(boot, dp) 28130418Skarels char *boot; 28230418Skarels register struct disklabel *dp; 28330418Skarels { 28430418Skarels struct disklabel *lp; 28530418Skarels register char *p; 28630418Skarels int b; 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); 35131401Skarels fprintf(f, "flags:"); 35230418Skarels if (lp->d_flags & D_REMOVABLE) 35331401Skarels fprintf(f, " removeable"); 35430418Skarels if (lp->d_flags & D_ECC) 35531401Skarels fprintf(f, " ecc"); 35630418Skarels if (lp->d_flags & D_BADSECT) 35731401Skarels 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); 36231386Skarels 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 52431401Skarels while (*cp != '\0' && !isspace(*cp) && *cp != '#') 52531401Skarels cp++; 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; 54430863Skarels 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")) { 58131386Skarels for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) { 58230715Sbostic if (streq(cp, "removeable")) 58330715Sbostic v |= D_REMOVABLE; 58430715Sbostic else if (streq(cp, "ecc")) 58530715Sbostic v |= D_ECC; 58630715Sbostic else if (streq(cp, "badsect")) 58730715Sbostic v |= D_BADSECT; 58830715Sbostic else { 58930715Sbostic fprintf(stderr, 59030715Sbostic "line %d: %s: bad flag\n", 59130715Sbostic lineno, cp); 59230715Sbostic errors++; 59330715Sbostic } 59430715Sbostic } 59530715Sbostic lp->d_flags = v; 59630715Sbostic continue; 59730715Sbostic } 59830715Sbostic if (streq(cp, "drivedata")) { 59930715Sbostic register int i; 60030715Sbostic 60131386Skarels for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 60230715Sbostic lp->d_drivedata[i++] = atoi(cp); 60331386Skarels tp = word(cp); 60430715Sbostic } 60530715Sbostic continue; 60630715Sbostic } 60730715Sbostic if (sscanf(cp, "%d partitions", &v) == 1) { 60830863Skarels if (v == 0 || (unsigned)v > MAXPARTITIONS) { 60930715Sbostic fprintf(stderr, 61030715Sbostic "line %d: bad # of partitions\n", lineno); 61130863Skarels lp->d_npartitions = MAXPARTITIONS; 61230863Skarels errors++; 61330863Skarels } else 61430715Sbostic lp->d_npartitions = v; 61530715Sbostic continue; 61630715Sbostic } 61730715Sbostic if (tp == NULL) 61830715Sbostic tp = ""; 61930715Sbostic if (streq(cp, "disk")) { 62030715Sbostic strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 62130715Sbostic continue; 62230715Sbostic } 62330715Sbostic if (streq(cp, "label")) { 62430715Sbostic strncpy(lp->d_name, tp, sizeof (lp->d_name)); 62530715Sbostic continue; 62630715Sbostic } 62730715Sbostic if (streq(cp, "bytes/sector")) { 62830715Sbostic v = atoi(tp); 62930715Sbostic if (v <= 0 || (v % 512) != 0) { 63030715Sbostic fprintf(stderr, 63130715Sbostic "line %d: %s: bad sector size\n", 63230715Sbostic lineno, tp); 63330715Sbostic errors++; 63430715Sbostic } else 63530715Sbostic lp->d_secsize = v; 63630715Sbostic continue; 63730715Sbostic } 63830715Sbostic if (streq(cp, "sectors/track")) { 63930715Sbostic v = atoi(tp); 64030715Sbostic if (v <= 0) { 64130715Sbostic fprintf(stderr, "line %d: %s: bad %s\n", 64230715Sbostic lineno, tp, cp); 64330715Sbostic errors++; 64430715Sbostic } else 64530715Sbostic lp->d_nsectors = v; 64630715Sbostic continue; 64730715Sbostic } 64831386Skarels if (streq(cp, "sectors/cylinder")) { 64931386Skarels v = atoi(tp); 65031386Skarels if (v <= 0) { 65131386Skarels fprintf(stderr, "line %d: %s: bad %s\n", 65231386Skarels lineno, tp, cp); 65331386Skarels errors++; 65431386Skarels } else 65531386Skarels lp->d_secpercyl = v; 65631386Skarels continue; 65731386Skarels } 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') { 73930863Skarels unsigned part = *cp - 'a'; 74030715Sbostic 74130863Skarels if (part > lp->d_npartitions) { 74230715Sbostic fprintf(stderr, 74330715Sbostic "line %d: bad partition name\n", lineno); 74430715Sbostic errors++; 74530715Sbostic continue; 74630715Sbostic } 74730863Skarels pp = &lp->d_partitions[part]; 74830863Skarels #define NXTNUM(n) { \ 74930863Skarels cp = tp, tp = word(cp); \ 75030863Skarels if (tp == NULL) \ 75130863Skarels tp = cp; \ 75230863Skarels (n) = atoi(cp); \ 75330863Skarels } 75430863Skarels 75530863Skarels NXTNUM(v); 75630715Sbostic if (v < 0) { 75730715Sbostic fprintf(stderr, 75830715Sbostic "line %d: %s: bad partition size\n", 75930715Sbostic lineno, cp); 76030715Sbostic errors++; 76130715Sbostic } else 76230863Skarels pp->p_size = v; 76330863Skarels NXTNUM(v); 76430715Sbostic if (v < 0) { 76530715Sbostic fprintf(stderr, 76630715Sbostic "line %d: %s: bad partition offset\n", 76730715Sbostic lineno, cp); 76830715Sbostic errors++; 76930715Sbostic } else 77030863Skarels 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)) { 77530863Skarels pp->p_fstype = cpp - fstypenames; 77630863Skarels 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); 78230863Skarels pp->p_fstype = v; 78330863Skarels gottype: 78430863Skarels 78530863Skarels switch (pp->p_fstype) { 78630863Skarels 78730863Skarels case FS_UNUSED: /* XXX */ 78830863Skarels NXTNUM(pp->p_fsize); 78930863Skarels if (pp->p_fsize == 0) 79030863Skarels break; 79130863Skarels NXTNUM(v); 79230863Skarels pp->p_frag = v / pp->p_fsize; 79330863Skarels break; 79430863Skarels 79530863Skarels case FS_BSDFFS: 79630863Skarels NXTNUM(pp->p_fsize); 79730863Skarels if (pp->p_fsize == 0) 79830863Skarels break; 79930863Skarels NXTNUM(v); 80030863Skarels pp->p_frag = v / pp->p_fsize; 80130863Skarels NXTNUM(pp->p_cpg); 80230863Skarels break; 80330863Skarels 80430863Skarels default: 80530863Skarels break; 80630863Skarels } 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 921*31617Skarels fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%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