130418Skarels #ifndef lint 2*30677Skarels static char sccsid[] = "@(#)disklabel.c 5.3 (Berkeley) 03/27/87"; 330418Skarels /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 430418Skarels #endif 530418Skarels 630418Skarels #include <stdio.h> 730418Skarels #include <ctype.h> 830418Skarels #include <sys/param.h> 930418Skarels #include <sys/errno.h> 1030418Skarels #include <sys/file.h> 11*30677Skarels #include <sys/fs.h> 1230418Skarels #include <sys/ioctl.h> 1330418Skarels #define DKTYPENAMES 1430418Skarels #include <sys/disklabel.h> 1530418Skarels 1630418Skarels /* 1730418Skarels * Disklabel: read and write disklabels. 1830418Skarels * The label is usually placed on one of the first sectors of the disk. 1930418Skarels * Many machines (VAX 11/750) also place a bootstrap in the same area, 2030418Skarels * in which case the label is embedded in the bootstrap. 2130418Skarels * The bootstrap source must leave space at the proper offset 2230418Skarels * for the label on such machines. 2330418Skarels */ 2430418Skarels 25*30677Skarels #ifdef vax 26*30677Skarels #define RAWPARTITION 'c' 27*30677Skarels #else 28*30677Skarels #define RAWPARTITION 'a' 29*30677Skarels #endif 30*30677Skarels 31*30677Skarels #ifndef BBSIZE 3230418Skarels #define BBSIZE 8192 /* size of boot area, with label */ 33*30677Skarels #endif 3430418Skarels 3530418Skarels #ifdef vax 3630418Skarels #define BOOT /* also have bootstrap in "boot area" */ 3730418Skarels #define BOOTDIR "/usr/mdec" /* source of boot binaries */ 38*30677Skarels #else 39*30677Skarels #ifdef lint 40*30677Skarels #define BOOT 4130418Skarels #endif 42*30677Skarels #endif 4330418Skarels 4430418Skarels char *dkname; 4530418Skarels char *dkbasename; 4630418Skarels char *xxboot; 4730418Skarels char *bootxx; 4830418Skarels char *specname; 4930418Skarels char *sprintf(); 5030418Skarels char *rindex(); 5130418Skarels 5230418Skarels extern int errno; 5330418Skarels char namebuf[BBSIZE], *np = namebuf; 5430418Skarels char bootarea[BBSIZE]; 5530418Skarels struct disklabel lab; 5630418Skarels struct disklabel *readlabel(), *getbootarea(); 5730418Skarels 5830418Skarels int op; /* one of: */ 5930418Skarels #define READ 1 6030418Skarels #define WRITE 2 6130418Skarels #define EDIT 3 6230418Skarels #define RESTORE 4 6330418Skarels 64*30677Skarels int rflag; 65*30677Skarels 6630418Skarels main(argc, argv) 6730418Skarels int argc; 6830418Skarels char *argv[]; 6930418Skarels { 7030418Skarels register struct disklabel *lp; 7130418Skarels int f, t; 7230418Skarels char *name = 0, *asciifile, *type; 7330418Skarels 7430418Skarels while (argc > 1 && argv[1][0] == '-') { 7530418Skarels if (strcmp(argv[1], "-e") == 0) { 7630418Skarels if (argc != 3) 7730418Skarels goto usage; 7830418Skarels op = EDIT; 7930418Skarels } else if (strcmp(argv[1], "-w") == 0) { 8030418Skarels if (argc != 4) 8130418Skarels goto usage; 8230418Skarels op = RESTORE; 83*30677Skarels } else if (strcmp(argv[1], "-r") == 0) 84*30677Skarels rflag++; 85*30677Skarels else 8630418Skarels goto usage; 8730418Skarels argv++; 8830418Skarels argc--; 8930418Skarels } 9030418Skarels if (argc < 2 || argc > 6) { 9130418Skarels usage: 9230418Skarels fprintf(stderr, "%s%s%s%s", 9330418Skarels #ifdef BOOT 9430418Skarels "usage: disklabel disk (to read label)\n", 9530418Skarels "or disklabel disk type [ packid ] [ xxboot bootxx ] (to write label)\n", 9630418Skarels "or disklabel -e disk (to edit label)\n", 9730418Skarels "or disklabel -w disk protofile [ xxboot bootxx ] (to restore label)\n" 9830418Skarels #else 9930418Skarels "usage: disklabel disk (to read label)\n", 10030418Skarels "or disklabel disk type [ packid ] (to write label)\n", 10130418Skarels "or disklabel -e disk (to edit label)\n", 10230418Skarels "or disklabel -w disk protofile (to restore label)\n" 10330418Skarels #endif 10430418Skarels ); 10530418Skarels exit(1); 10630418Skarels } 10730418Skarels if (op == 0) 10830418Skarels if (argc == 2) 10930418Skarels op = READ; 11030418Skarels else 11130418Skarels op = WRITE; 11230418Skarels dkname = argv[1]; 11330418Skarels if (dkname[0] != '/') { 114*30677Skarels sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION); 11530418Skarels specname = np; 11630418Skarels np += strlen(specname) + 1; 11730418Skarels } else 11830418Skarels specname = dkname; 11930418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 12030418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 12130418Skarels sprintf(specname, "/dev/r%s", dkname); 12230418Skarels np = namebuf + strlen(specname) + 1; 12330418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 12430418Skarels } 12530418Skarels if (f < 0) 12630418Skarels Perror(specname); 12730418Skarels 12830418Skarels if (op == WRITE) { 12930418Skarels type = argv[2]; 13030418Skarels if (argc == 4 || argc == 6) { 13130418Skarels name = argv[3]; 13230418Skarels argv++; 13330418Skarels argc--; 13430418Skarels } 13530418Skarels } 13630418Skarels if (op == RESTORE) { 13730418Skarels asciifile = argv[2]; 13830418Skarels argv++; 13930418Skarels argc--; 14030418Skarels } 14130418Skarels #ifdef BOOT 14230418Skarels if (argc == 5) { 14330418Skarels xxboot = argv[3]; 14430418Skarels bootxx = argv[4]; 14530418Skarels } 14630418Skarels #endif 14730418Skarels 14830418Skarels 14930418Skarels switch (op) { 15030418Skarels 15130418Skarels case READ: 15230418Skarels lp = readlabel(f, 0); 15330418Skarels display(stdout, lp); 15430418Skarels break; 15530418Skarels 15630418Skarels case EDIT: 15730418Skarels lp = readlabel(f, bootarea); 15830418Skarels edit(f, lp); 15930418Skarels writelabel(f, bootarea, lp); 16030418Skarels break; 16130418Skarels 16230418Skarels case WRITE: 16330418Skarels makelabel(type, name, &lab); 16430418Skarels lp = getbootarea(bootarea, &lab); 16530418Skarels *lp = lab; 16630418Skarels writelabel(f, bootarea, lp); 16730418Skarels break; 16830418Skarels 16930418Skarels case RESTORE: 17030418Skarels lab.d_secsize = DEV_BSIZE; /* XXX */ 17130418Skarels lab.d_bbsize = BBSIZE; /* XXX */ 17230418Skarels lp = getbootarea(bootarea, &lab); 17330418Skarels t = open(asciifile, O_RDONLY); 17430418Skarels if (t < 0) 17530418Skarels Perror(asciifile); 17630418Skarels getasciilabel(t, lp); 17730418Skarels writelabel(f, bootarea, lp); 17830418Skarels break; 17930418Skarels } 18030418Skarels exit(0); 18130418Skarels } 18230418Skarels 18330418Skarels makelabel(type, name, lp) 18430418Skarels char *type, *name; 18530418Skarels register struct disklabel *lp; 18630418Skarels { 18730418Skarels register struct disklabel *dp; 18830418Skarels register char *p; 18930418Skarels 19030418Skarels dp = getdiskbyname(type); 19130418Skarels if (dp == NULL) { 19230418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 19330418Skarels exit(1); 19430418Skarels } 19530418Skarels *lp = *dp; 19630418Skarels if (name) 19730418Skarels strncpy(lp->d_name, name, sizeof(lp->d_name)); 19830418Skarels } 19930418Skarels 20030418Skarels writelabel(f, boot, lp) 20130418Skarels int f; 20230418Skarels char *boot; 20330418Skarels register struct disklabel *lp; 20430418Skarels { 20530418Skarels register i; 20630418Skarels 20730418Skarels lp->d_magic = DISKMAGIC; 20830418Skarels lp->d_magic2 = DISKMAGIC; 20930418Skarels lp->d_checksum = 0; 21030418Skarels lp->d_checksum = dkcksum(lp); 21130418Skarels lseek(f, (off_t)0, L_SET); 212*30677Skarels if (rflag) { 213*30677Skarels if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 214*30677Skarels Perror("write"); 215*30677Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 216*30677Skarels Perror("ioctl DIOCSDINFO"); 217*30677Skarels } else if (ioctl(f, DIOCWDINFO, lp) < 0) 218*30677Skarels Perror("ioctl DIOCWDINFO"); 21930419Skarels #if vax 220*30677Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 221*30677Skarels daddr_t alt; 222*30677Skarels 223*30677Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 224*30677Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 225*30677Skarels lseek(f, (off_t)(alt + i) * lp->d_secsize, L_SET); 226*30677Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 227*30677Skarels int oerrno = errno; 228*30677Skarels fprintf(stderr, "alternate label %d ", i/2); 229*30677Skarels errno = oerrno; 230*30677Skarels perror("write"); 231*30677Skarels } 23230418Skarels } 23330418Skarels } 23430419Skarels #endif 23530418Skarels } 23630418Skarels 23730418Skarels /* 23830418Skarels * Read disklabel from disk. 23930418Skarels * If boot is given, need bootstrap too. 240*30677Skarels * If boot not needed, use ioctl to get label 241*30677Skarels * unless -r flag is given. 24230418Skarels */ 24330418Skarels struct disklabel * 24430418Skarels readlabel(f, boot) 24530418Skarels int f; 24630418Skarels char *boot; 24730418Skarels { 24830418Skarels register struct disklabel *lp; 249*30677Skarels register char *buf; 25030418Skarels 251*30677Skarels if (boot) 252*30677Skarels buf = boot; 253*30677Skarels else 254*30677Skarels buf = bootarea; 255*30677Skarels lp = (struct disklabel *)(buf + LABELOFFSET); 256*30677Skarels if (rflag == 0 && boot == 0) { 257*30677Skarels if (ioctl(f, DIOCGDINFO, lp) < 0) 258*30677Skarels Perror("ioctl DIOCGDINFO"); 259*30677Skarels } else { 260*30677Skarels if (read(f, buf, BBSIZE) < BBSIZE) 261*30677Skarels Perror(specname); 262*30677Skarels for (lp = (struct disklabel *)buf; 263*30677Skarels lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp)); 264*30677Skarels lp = (struct disklabel *)((char *)lp + 16)) 265*30677Skarels if (lp->d_magic == DISKMAGIC && 266*30677Skarels lp->d_magic2 == DISKMAGIC) 267*30677Skarels break; 268*30677Skarels if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) || 269*30677Skarels lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 270*30677Skarels dkcksum(lp) != 0) { 271*30677Skarels fprintf(stderr, 27230418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 273*30677Skarels exit(1); 274*30677Skarels } 27530418Skarels } 27630418Skarels return (lp); 27730418Skarels } 27830418Skarels 27930418Skarels struct disklabel * 28030418Skarels getbootarea(boot, dp) 28130418Skarels char *boot; 28230418Skarels register struct disklabel *dp; 28330418Skarels { 28430418Skarels struct disklabel *lp; 28530418Skarels register char *p; 28630418Skarels int b; 28730418Skarels 28830418Skarels #ifdef BOOT 28930418Skarels if (xxboot == NULL) { 29030418Skarels dkbasename = np; 29130418Skarels if ((p = rindex(dkname, '/')) == NULL) 29230418Skarels p = dkname; 29330418Skarels else 29430418Skarels p++; 29530418Skarels while (*p && !isdigit(*p)) 29630418Skarels *np++ = *p++; 29730418Skarels *np++ = '\0'; 29830418Skarels 29930418Skarels sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 30030418Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 30130418Skarels dkbasename++; 30230418Skarels xxboot = np; 30330418Skarels sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 30430418Skarels np += strlen(xxboot) + 1; 30530418Skarels 30630418Skarels bootxx = np; 30730418Skarels sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 30830418Skarels np += strlen(bootxx) + 1; 30930418Skarels } 31030418Skarels 31130418Skarels b = open(xxboot, O_RDONLY); 31230418Skarels if (b < 0) 31330418Skarels Perror(xxboot); 31430418Skarels if (read(b, boot, dp->d_secsize) < 0) 31530418Skarels Perror(xxboot); 31630418Skarels close(b); 31730418Skarels b = open(bootxx, O_RDONLY); 31830418Skarels if (b < 0) 31930418Skarels Perror(bootxx); 32030418Skarels if (read(b, &boot[dp->d_secsize], dp->d_bbsize-dp->d_secsize) < 0) 32130418Skarels Perror(bootxx); 32230418Skarels close(b); 32330418Skarels #endif 32430418Skarels 32530418Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 32630418Skarels LABELOFFSET); 32730418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 32830418Skarels if (*p) { 32930418Skarels fprintf(stderr, 33030418Skarels "Bootstrap doesn't leave room for disk label\n"); 33130418Skarels exit(2); 33230418Skarels } 33330418Skarels return (lp); 33430418Skarels } 33530418Skarels 33630418Skarels display(f, lp) 33730418Skarels FILE *f; 33830418Skarels register struct disklabel *lp; 33930418Skarels { 34030418Skarels register i, j; 34130418Skarels register struct partition *pp; 34230418Skarels 34330418Skarels fprintf(f, "# %s:\n", specname); 34430418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 34530418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 34630418Skarels else 34730418Skarels fprintf(f, "type: %d\n", lp->d_type); 34830418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 34930418Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 35030418Skarels fprintf(f, "flags: "); 35130418Skarels if (lp->d_flags & D_REMOVABLE) 35230418Skarels fprintf(f, "removeable "); 35330418Skarels if (lp->d_flags & D_ECC) 35430418Skarels fprintf(f, "ecc "); 35530418Skarels if (lp->d_flags & D_BADSECT) 35630418Skarels fprintf(f, "badsect "); 35730418Skarels fprintf(f, "\n"); 35830418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 35930418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 36030418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 36130418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 36230418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 36330418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 36430418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 36530418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 36630418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 36730418Skarels fprintf(f, "drivedata: "); 36830418Skarels for (i = NDDATA - 1; i >= 0; i--) 36930418Skarels if (lp->d_drivedata[i]) 37030418Skarels break; 37130418Skarels if (i < 0) 37230418Skarels i = 0; 37330418Skarels for (j = 0; j <= i; j++) 37430418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 37530418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 37630418Skarels fprintf(f, "#\t size offset fstype\n"); 37730418Skarels pp = lp->d_partitions; 37830418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 37930418Skarels fprintf(f, "\t%c: %8d %8d ", 'a' + i, 38030418Skarels pp->p_size, pp->p_offset); 38130418Skarels if (pp->p_size) { 38230418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 38330418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 38430418Skarels else 38530418Skarels fprintf(f, "%8d", pp->p_fstype); 38630418Skarels fprintf(f, "\t# (Cyl. %4d", 38730418Skarels pp->p_offset / lp->d_secpercyl); 38830418Skarels if (pp->p_offset % lp->d_secpercyl) 38930418Skarels putc('*', f); 39030418Skarels else 39130418Skarels putc(' ', f); 39230418Skarels fprintf(f, "- %d", 39330418Skarels (pp->p_offset + 39430418Skarels pp->p_size + lp->d_secpercyl - 1) / 39530418Skarels lp->d_secpercyl - 1); 39630418Skarels if (pp->p_size % lp->d_secpercyl) 39730418Skarels putc('*', f); 39830418Skarels putc(')', f); 39930418Skarels } 40030418Skarels fprintf(f, "\n"); 40130418Skarels } 40230418Skarels } 40330418Skarels 40430418Skarels edit(f) 40530418Skarels int f; 40630418Skarels { 40730418Skarels fprintf(stderr, "sorry, not yet\n"); 40830418Skarels exit(1); 40930418Skarels } 41030418Skarels 41130418Skarels 41230418Skarels /* 41330418Skarels * Read an ascii label in from fd f, 41430418Skarels * in the same format as that put out by display(), 41530418Skarels * and fill in lp. 41630418Skarels */ 41730418Skarels getasciilabel(f, lp) 41830418Skarels int f; 41930418Skarels register struct disklabel *lp; 42030418Skarels { 42130418Skarels fprintf(stderr, "sorry, not yet\n"); 42230418Skarels exit(1); 42330418Skarels } 42430418Skarels 42530418Skarels Perror(op) 42630418Skarels char *op; 42730418Skarels { 42830418Skarels 42930418Skarels fprintf(stderr, "disklabel: "); perror(op); 43030418Skarels exit(4); 43130418Skarels } 432