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*32121Stef static char sccsid[] = "@(#)disklabel.c 5.10 (Berkeley) 09/10/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 5931617Skarels 6031617Skarels 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; 6731617Skarels struct disklabel lab; 6831617Skarels 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(); 12831617Skarels lp = readlabel(f, rflag); 12930715Sbostic if (edit(lp)) 13030715Sbostic writelabel(f, bootarea, lp); 13130715Sbostic break; 13230418Skarels case READ: 13330715Sbostic if (argc != 1) 13430715Sbostic usage(); 13531617Skarels 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]; 14431617Skarels } else 14531617Skarels #endif 14630715Sbostic if (argc != 2) 14730715Sbostic usage(); 14830715Sbostic lab.d_secsize = DEV_BSIZE; /* XXX */ 14930715Sbostic lab.d_bbsize = BBSIZE; /* XXX */ 15031617Skarels 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); 17531617Skarels 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) { 21631617Skarels (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 /* 24231617Skarels * Fetch disklabel for disk. 24331617Skarels * If needboot is given, need bootstrap too. 24431617Skarels * Use ioctl to get label unless -r flag is given. 24530418Skarels */ 24630418Skarels struct disklabel * 24731617Skarels readlabel(f, needboot) 24831617Skarels int f, needboot; 24930418Skarels { 25030418Skarels register struct disklabel *lp; 25130418Skarels 25231617Skarels if (needboot || rflag) { 25331617Skarels lp = (struct disklabel *)(bootarea + LABELOFFSET); 25431617Skarels if (read(f, bootarea, BBSIZE) < BBSIZE) 25531401Skarels Perror(specname); 25631617Skarels } else 25731617Skarels lp = &lab; 25831401Skarels if (rflag == 0) { 25930677Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 26030677Skarels Perror("ioctl DIOCGDINFO"); 26130677Skarels } else { 26231617Skarels for (lp = (struct disklabel *)bootarea; 26331617Skarels 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; 26831617Skarels 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 * 28031617Skarels 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 } 422*32121Stef fflush(f); 42330418Skarels } 42430418Skarels 42530715Sbostic edit(lp) 42630715Sbostic struct disklabel *lp; 42730418Skarels { 42830715Sbostic register int c; 42930715Sbostic struct disklabel label; 43030715Sbostic FILE *fd; 43130715Sbostic char *mktemp(); 43230715Sbostic 43330715Sbostic (void) mktemp(tmpfil); 43430715Sbostic fd = fopen(tmpfil, "w"); 43530715Sbostic if (fd == NULL) { 43630715Sbostic fprintf(stderr, "%s: Can't create\n", tmpfil); 43730715Sbostic return (0); 43830715Sbostic } 43930715Sbostic (void)fchmod(fd, 0600); 44030715Sbostic display(fd, lp); 44130715Sbostic fclose(fd); 44230715Sbostic for (;;) { 44330715Sbostic if (!editit()) 44430715Sbostic break; 44530715Sbostic fd = fopen(tmpfil, "r"); 44630715Sbostic if (fd == NULL) { 44730715Sbostic fprintf(stderr, "%s: Can't reopen for reading\n"); 44830715Sbostic break; 44930715Sbostic } 45030863Skarels bzero((char *)&label, sizeof(label)); 45130715Sbostic if (getasciilabel(fd, &label)) { 45230715Sbostic *lp = label; 45330715Sbostic (void) unlink(tmpfil); 45430715Sbostic return (1); 45530715Sbostic } 45630715Sbostic printf("re-edit the label? [y]: "); fflush(stdout); 45730715Sbostic c = getchar(); 45830715Sbostic if (c != EOF && c != (int)'\n') 45930715Sbostic while (getchar() != (int)'\n') 46030715Sbostic ; 46130715Sbostic if (c == (int)'n') 46230715Sbostic break; 46330715Sbostic } 46430715Sbostic (void) unlink(tmpfil); 46530715Sbostic return (0); 46630418Skarels } 46730418Skarels 46830715Sbostic editit() 46930715Sbostic { 47030715Sbostic register int pid, xpid; 47130715Sbostic int stat, omask; 47230715Sbostic extern char *getenv(); 47330418Skarels 47430715Sbostic omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 47530715Sbostic while ((pid = fork()) < 0) { 47630715Sbostic extern int errno; 47730715Sbostic 47830715Sbostic if (errno == EPROCLIM) { 47930715Sbostic fprintf(stderr, "You have too many processes\n"); 48030715Sbostic return(0); 48130715Sbostic } 48230715Sbostic if (errno != EAGAIN) { 48330715Sbostic perror("fork"); 48430715Sbostic return(0); 48530715Sbostic } 48630715Sbostic sleep(1); 48730715Sbostic } 48830715Sbostic if (pid == 0) { 48930715Sbostic register char *ed; 49030715Sbostic 49130715Sbostic sigsetmask(omask); 49230715Sbostic setgid(getgid()); 49330715Sbostic setuid(getuid()); 49430715Sbostic if ((ed = getenv("EDITOR")) == (char *)0) 49530715Sbostic ed = DEFEDITOR; 49630715Sbostic execlp(ed, ed, tmpfil, 0); 49730715Sbostic perror(ed); 49830715Sbostic exit(1); 49930715Sbostic } 50030715Sbostic while ((xpid = wait(&stat)) >= 0) 50130715Sbostic if (xpid == pid) 50230715Sbostic break; 50330715Sbostic sigsetmask(omask); 50430715Sbostic return(!stat); 50530715Sbostic } 50630715Sbostic 50730715Sbostic char * 50830715Sbostic skip(cp) 50930715Sbostic register char *cp; 51030715Sbostic { 51130715Sbostic 51230715Sbostic while (*cp != '\0' && isspace(*cp)) 51330715Sbostic cp++; 51430715Sbostic if (*cp == '\0' || *cp == '#') 51530715Sbostic return ((char *)NULL); 51630715Sbostic return (cp); 51730715Sbostic } 51830715Sbostic 51930715Sbostic char * 52030715Sbostic word(cp) 52130715Sbostic register char *cp; 52230715Sbostic { 52330715Sbostic register char c; 52430715Sbostic 52531401Skarels while (*cp != '\0' && !isspace(*cp) && *cp != '#') 52631401Skarels cp++; 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")) { 58231386Skarels 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 60231386Skarels for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 60330715Sbostic lp->d_drivedata[i++] = atoi(cp); 60431386Skarels 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 } 64931386Skarels if (streq(cp, "sectors/cylinder")) { 65031386Skarels v = atoi(tp); 65131386Skarels if (v <= 0) { 65231386Skarels fprintf(stderr, "line %d: %s: bad %s\n", 65331386Skarels lineno, tp, cp); 65431386Skarels errors++; 65531386Skarels } else 65631386Skarels lp->d_secpercyl = v; 65731386Skarels continue; 65831386Skarels } 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 92231617Skarels fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%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