130418Skarels #ifndef lint 2*30419Skarels static char sccsid[] = "@(#)disklabel.c 5.2 (Berkeley) 01/19/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> 1130418Skarels #include <sys/ioctl.h> 1230418Skarels #define DKTYPENAMES 1330418Skarels #include <sys/disklabel.h> 1430418Skarels 1530418Skarels /* 1630418Skarels * Disklabel: read and write disklabels. 1730418Skarels * The label is usually placed on one of the first sectors of the disk. 1830418Skarels * Many machines (VAX 11/750) also place a bootstrap in the same area, 1930418Skarels * in which case the label is embedded in the bootstrap. 2030418Skarels * The bootstrap source must leave space at the proper offset 2130418Skarels * for the label on such machines. 2230418Skarels */ 2330418Skarels 2430418Skarels #define BBSIZE 8192 /* size of boot area, with label */ 2530418Skarels 2630418Skarels #ifdef vax 2730418Skarels #define BOOT /* also have bootstrap in "boot area" */ 2830418Skarels #define BOOTDIR "/usr/mdec" /* source of boot binaries */ 2930418Skarels #endif 3030418Skarels 3130418Skarels char *dkname; 3230418Skarels char *dkbasename; 3330418Skarels char *xxboot; 3430418Skarels char *bootxx; 3530418Skarels char *specname; 3630418Skarels char *sprintf(); 3730418Skarels char *rindex(); 3830418Skarels 3930418Skarels extern int errno; 4030418Skarels char namebuf[BBSIZE], *np = namebuf; 4130418Skarels char bootarea[BBSIZE]; 4230418Skarels struct disklabel lab; 4330418Skarels struct disklabel *readlabel(), *getbootarea(); 4430418Skarels 4530418Skarels int op; /* one of: */ 4630418Skarels #define READ 1 4730418Skarels #define WRITE 2 4830418Skarels #define EDIT 3 4930418Skarels #define RESTORE 4 5030418Skarels 5130418Skarels main(argc, argv) 5230418Skarels int argc; 5330418Skarels char *argv[]; 5430418Skarels { 5530418Skarels register struct disklabel *lp; 5630418Skarels int f, t; 5730418Skarels char *name = 0, *asciifile, *type; 5830418Skarels 5930418Skarels while (argc > 1 && argv[1][0] == '-') { 6030418Skarels if (strcmp(argv[1], "-e") == 0) { 6130418Skarels if (argc != 3) 6230418Skarels goto usage; 6330418Skarels op = EDIT; 6430418Skarels } else if (strcmp(argv[1], "-w") == 0) { 6530418Skarels if (argc != 4) 6630418Skarels goto usage; 6730418Skarels op = RESTORE; 6830418Skarels } else 6930418Skarels goto usage; 7030418Skarels argv++; 7130418Skarels argc--; 7230418Skarels } 7330418Skarels if (argc < 2 || argc > 6) { 7430418Skarels usage: 7530418Skarels fprintf(stderr, "%s%s%s%s", 7630418Skarels #ifdef BOOT 7730418Skarels "usage: disklabel disk (to read label)\n", 7830418Skarels "or disklabel disk type [ packid ] [ xxboot bootxx ] (to write label)\n", 7930418Skarels "or disklabel -e disk (to edit label)\n", 8030418Skarels "or disklabel -w disk protofile [ xxboot bootxx ] (to restore label)\n" 8130418Skarels #else 8230418Skarels "usage: disklabel disk (to read label)\n", 8330418Skarels "or disklabel disk type [ packid ] (to write label)\n", 8430418Skarels "or disklabel -e disk (to edit label)\n", 8530418Skarels "or disklabel -w disk protofile (to restore label)\n" 8630418Skarels #endif 8730418Skarels ); 8830418Skarels exit(1); 8930418Skarels } 9030418Skarels if (op == 0) 9130418Skarels if (argc == 2) 9230418Skarels op = READ; 9330418Skarels else 9430418Skarels op = WRITE; 9530418Skarels dkname = argv[1]; 9630418Skarels if (dkname[0] != '/') { 9730418Skarels sprintf(np, "/dev/r%sc", dkname); 9830418Skarels specname = np; 9930418Skarels np += strlen(specname) + 1; 10030418Skarels } else 10130418Skarels specname = dkname; 10230418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 10330418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 10430418Skarels sprintf(specname, "/dev/r%s", dkname); 10530418Skarels np = namebuf + strlen(specname) + 1; 10630418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 10730418Skarels } 10830418Skarels if (f < 0) 10930418Skarels Perror(specname); 11030418Skarels 11130418Skarels if (op == WRITE) { 11230418Skarels type = argv[2]; 11330418Skarels if (argc == 4 || argc == 6) { 11430418Skarels name = argv[3]; 11530418Skarels argv++; 11630418Skarels argc--; 11730418Skarels } 11830418Skarels } 11930418Skarels if (op == RESTORE) { 12030418Skarels asciifile = argv[2]; 12130418Skarels argv++; 12230418Skarels argc--; 12330418Skarels } 12430418Skarels #ifdef BOOT 12530418Skarels if (argc == 5) { 12630418Skarels xxboot = argv[3]; 12730418Skarels bootxx = argv[4]; 12830418Skarels } 12930418Skarels #endif 13030418Skarels 13130418Skarels 13230418Skarels switch (op) { 13330418Skarels 13430418Skarels case READ: 13530418Skarels lp = readlabel(f, 0); 13630418Skarels display(stdout, lp); 13730418Skarels break; 13830418Skarels 13930418Skarels case EDIT: 14030418Skarels lp = readlabel(f, bootarea); 14130418Skarels edit(f, lp); 14230418Skarels writelabel(f, bootarea, lp); 14330418Skarels break; 14430418Skarels 14530418Skarels case WRITE: 14630418Skarels makelabel(type, name, &lab); 14730418Skarels lp = getbootarea(bootarea, &lab); 14830418Skarels *lp = lab; 14930418Skarels writelabel(f, bootarea, lp); 15030418Skarels break; 15130418Skarels 15230418Skarels case RESTORE: 15330418Skarels lab.d_secsize = DEV_BSIZE; /* XXX */ 15430418Skarels lab.d_bbsize = BBSIZE; /* XXX */ 15530418Skarels lp = getbootarea(bootarea, &lab); 15630418Skarels t = open(asciifile, O_RDONLY); 15730418Skarels if (t < 0) 15830418Skarels Perror(asciifile); 15930418Skarels getasciilabel(t, lp); 16030418Skarels writelabel(f, bootarea, lp); 16130418Skarels break; 16230418Skarels } 16330418Skarels exit(0); 16430418Skarels } 16530418Skarels 16630418Skarels makelabel(type, name, lp) 16730418Skarels char *type, *name; 16830418Skarels register struct disklabel *lp; 16930418Skarels { 17030418Skarels register struct disklabel *dp; 17130418Skarels register char *p; 17230418Skarels 17330418Skarels dp = getdiskbyname(type); 17430418Skarels if (dp == NULL) { 17530418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 17630418Skarels exit(1); 17730418Skarels } 17830418Skarels *lp = *dp; 17930418Skarels if (name) 18030418Skarels strncpy(lp->d_name, name, sizeof(lp->d_name)); 18130418Skarels } 18230418Skarels 18330418Skarels writelabel(f, boot, lp) 18430418Skarels int f; 18530418Skarels char *boot; 18630418Skarels register struct disklabel *lp; 18730418Skarels { 18830418Skarels register i; 189*30419Skarels daddr_t bbsize; 190*30419Skarels #if vax 19130418Skarels daddr_t alt; 192*30419Skarels int nsectors, secsize; 193*30419Skarels #endif 19430418Skarels 19530418Skarels lp->d_magic = DISKMAGIC; 19630418Skarels lp->d_magic2 = DISKMAGIC; 197*30419Skarels bbsize = lp->d_bbsize; 198*30419Skarels #if vax 199*30419Skarels /* copy before swabbing */ 200*30419Skarels if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) 201*30419Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 202*30419Skarels else 203*30419Skarels alt = 0; 204*30419Skarels nsectors = lp->d_nsectors; 205*30419Skarels secsize = lp->d_secsize; 206*30419Skarels #endif 20730418Skarels swablabel(lp); 20830418Skarels lp->d_checksum = 0; 20930418Skarels lp->d_checksum = dkcksum(lp); 21030418Skarels lseek(f, (off_t)0, L_SET); 211*30419Skarels if (write(f, boot, bbsize) < bbsize) 21230418Skarels Perror("write"); 213*30419Skarels #if vax 214*30419Skarels if (alt) 215*30419Skarels for (i = 1; i < 11 && i < nsectors; i += 2) { 216*30419Skarels lseek(f, (off_t)(alt + i) * secsize, L_SET); 217*30419Skarels if (write(f, boot, secsize) < secsize) { 21830418Skarels int oerrno = errno; 21930418Skarels fprintf(stderr, "alternate label %d ", i/2); 22030418Skarels errno = oerrno; 22130418Skarels perror("write"); 22230418Skarels } 22330418Skarels } 224*30419Skarels #endif 225*30419Skarels #ifdef notyet 22630418Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 22730418Skarels Perror("ioctl DIOCSDINFO"); 22830418Skarels #endif 22930418Skarels } 23030418Skarels 23130418Skarels /* 23230418Skarels * Read disklabel from disk. 23330418Skarels * If boot is given, need bootstrap too. 23430418Skarels * If boot not needed, could use ioctl to get label. 23530418Skarels */ 23630418Skarels struct disklabel * 23730418Skarels readlabel(f, boot) 23830418Skarels int f; 23930418Skarels char *boot; 24030418Skarels { 24130418Skarels register struct disklabel *lp; 24230418Skarels u_long magic = htonl(DISKMAGIC); 24330418Skarels 24430418Skarels if (boot == NULL) 24530418Skarels boot = bootarea; 24630418Skarels if (read(f, boot, BBSIZE) < BBSIZE) 24730418Skarels Perror(specname); 24830418Skarels for (lp = (struct disklabel *)(boot + LABELOFFSET); 24930418Skarels lp <= (struct disklabel *)(boot + BBSIZE - 25030418Skarels sizeof(struct disklabel)); 25130418Skarels lp = (struct disklabel *)((char *)lp + 128)) 25230418Skarels if (lp->d_magic == magic && lp->d_magic2 == magic) 25330418Skarels break; 25430418Skarels if (lp > (struct disklabel *)(boot + BBSIZE - 25530418Skarels sizeof(struct disklabel)) || 25630418Skarels lp->d_magic != magic || lp->d_magic2 != magic || 25730418Skarels dkcksum(lp) != 0) { 25830418Skarels fprintf(stderr, 25930418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 26030418Skarels exit(1); 26130418Skarels } 26230418Skarels swablabel(lp); 26330418Skarels return (lp); 26430418Skarels } 26530418Skarels 26630418Skarels struct disklabel * 26730418Skarels getbootarea(boot, dp) 26830418Skarels char *boot; 26930418Skarels register struct disklabel *dp; 27030418Skarels { 27130418Skarels struct disklabel *lp; 27230418Skarels register char *p; 27330418Skarels int b; 27430418Skarels 27530418Skarels #ifdef BOOT 27630418Skarels if (xxboot == NULL) { 27730418Skarels dkbasename = np; 27830418Skarels if ((p = rindex(dkname, '/')) == NULL) 27930418Skarels p = dkname; 28030418Skarels else 28130418Skarels p++; 28230418Skarels while (*p && !isdigit(*p)) 28330418Skarels *np++ = *p++; 28430418Skarels *np++ = '\0'; 28530418Skarels 28630418Skarels sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 28730418Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 28830418Skarels dkbasename++; 28930418Skarels xxboot = np; 29030418Skarels sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 29130418Skarels np += strlen(xxboot) + 1; 29230418Skarels 29330418Skarels bootxx = np; 29430418Skarels sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 29530418Skarels np += strlen(bootxx) + 1; 29630418Skarels } 29730418Skarels 29830418Skarels b = open(xxboot, O_RDONLY); 29930418Skarels if (b < 0) 30030418Skarels Perror(xxboot); 30130418Skarels if (read(b, boot, dp->d_secsize) < 0) 30230418Skarels Perror(xxboot); 30330418Skarels close(b); 30430418Skarels b = open(bootxx, O_RDONLY); 30530418Skarels if (b < 0) 30630418Skarels Perror(bootxx); 30730418Skarels if (read(b, &boot[dp->d_secsize], dp->d_bbsize-dp->d_secsize) < 0) 30830418Skarels Perror(bootxx); 30930418Skarels close(b); 31030418Skarels #endif 31130418Skarels 31230418Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 31330418Skarels LABELOFFSET); 31430418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 31530418Skarels if (*p) { 31630418Skarels fprintf(stderr, 31730418Skarels "Bootstrap doesn't leave room for disk label\n"); 31830418Skarels exit(2); 31930418Skarels } 32030418Skarels return (lp); 32130418Skarels } 32230418Skarels 32330418Skarels display(f, lp) 32430418Skarels FILE *f; 32530418Skarels register struct disklabel *lp; 32630418Skarels { 32730418Skarels register i, j; 32830418Skarels register struct partition *pp; 32930418Skarels 33030418Skarels fprintf(f, "# %s:\n", specname); 33130418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 33230418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 33330418Skarels else 33430418Skarels fprintf(f, "type: %d\n", lp->d_type); 33530418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 33630418Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 33730418Skarels fprintf(f, "flags: "); 33830418Skarels if (lp->d_flags & D_REMOVABLE) 33930418Skarels fprintf(f, "removeable "); 34030418Skarels if (lp->d_flags & D_ECC) 34130418Skarels fprintf(f, "ecc "); 34230418Skarels if (lp->d_flags & D_BADSECT) 34330418Skarels fprintf(f, "badsect "); 34430418Skarels fprintf(f, "\n"); 34530418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 34630418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 34730418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 34830418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 34930418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 35030418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 35130418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 35230418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 35330418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 35430418Skarels fprintf(f, "drivedata: "); 35530418Skarels for (i = NDDATA - 1; i >= 0; i--) 35630418Skarels if (lp->d_drivedata[i]) 35730418Skarels break; 35830418Skarels if (i < 0) 35930418Skarels i = 0; 36030418Skarels for (j = 0; j <= i; j++) 36130418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 36230418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 36330418Skarels fprintf(f, "#\t size offset fstype\n"); 36430418Skarels pp = lp->d_partitions; 36530418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 36630418Skarels fprintf(f, "\t%c: %8d %8d ", 'a' + i, 36730418Skarels pp->p_size, pp->p_offset); 36830418Skarels if (pp->p_size) { 36930418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 37030418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 37130418Skarels else 37230418Skarels fprintf(f, "%8d", pp->p_fstype); 37330418Skarels fprintf(f, "\t# (Cyl. %4d", 37430418Skarels pp->p_offset / lp->d_secpercyl); 37530418Skarels if (pp->p_offset % lp->d_secpercyl) 37630418Skarels putc('*', f); 37730418Skarels else 37830418Skarels putc(' ', f); 37930418Skarels fprintf(f, "- %d", 38030418Skarels (pp->p_offset + 38130418Skarels pp->p_size + lp->d_secpercyl - 1) / 38230418Skarels lp->d_secpercyl - 1); 38330418Skarels if (pp->p_size % lp->d_secpercyl) 38430418Skarels putc('*', f); 38530418Skarels putc(')', f); 38630418Skarels } 38730418Skarels fprintf(f, "\n"); 38830418Skarels } 38930418Skarels } 39030418Skarels 39130418Skarels edit(f) 39230418Skarels int f; 39330418Skarels { 39430418Skarels fprintf(stderr, "sorry, not yet\n"); 39530418Skarels exit(1); 39630418Skarels } 39730418Skarels 39830418Skarels 39930418Skarels /* 40030418Skarels * Read an ascii label in from fd f, 40130418Skarels * in the same format as that put out by display(), 40230418Skarels * and fill in lp. 40330418Skarels */ 40430418Skarels getasciilabel(f, lp) 40530418Skarels int f; 40630418Skarels register struct disklabel *lp; 40730418Skarels { 40830418Skarels fprintf(stderr, "sorry, not yet\n"); 40930418Skarels exit(1); 41030418Skarels } 41130418Skarels 41230418Skarels Perror(op) 41330418Skarels char *op; 41430418Skarels { 41530418Skarels 41630418Skarels fprintf(stderr, "disklabel: "); perror(op); 41730418Skarels exit(4); 41830418Skarels } 419