1*30418Skarels #ifndef lint 2*30418Skarels static char sccsid[] = "@(#)disklabel.c 5.1 (Berkeley) 01/19/87"; 3*30418Skarels /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 4*30418Skarels #endif 5*30418Skarels 6*30418Skarels #include <stdio.h> 7*30418Skarels #include <ctype.h> 8*30418Skarels #include <sys/param.h> 9*30418Skarels #include <sys/errno.h> 10*30418Skarels #include <sys/file.h> 11*30418Skarels #include <sys/ioctl.h> 12*30418Skarels #define DKTYPENAMES 13*30418Skarels #include <sys/disklabel.h> 14*30418Skarels 15*30418Skarels /* 16*30418Skarels * Disklabel: read and write disklabels. 17*30418Skarels * The label is usually placed on one of the first sectors of the disk. 18*30418Skarels * Many machines (VAX 11/750) also place a bootstrap in the same area, 19*30418Skarels * in which case the label is embedded in the bootstrap. 20*30418Skarels * The bootstrap source must leave space at the proper offset 21*30418Skarels * for the label on such machines. 22*30418Skarels */ 23*30418Skarels 24*30418Skarels #define BBSIZE 8192 /* size of boot area, with label */ 25*30418Skarels 26*30418Skarels #ifdef vax 27*30418Skarels #define BOOT /* also have bootstrap in "boot area" */ 28*30418Skarels #define BOOTDIR "/usr/mdec" /* source of boot binaries */ 29*30418Skarels #endif 30*30418Skarels 31*30418Skarels char *dkname; 32*30418Skarels char *dkbasename; 33*30418Skarels char *xxboot; 34*30418Skarels char *bootxx; 35*30418Skarels char *specname; 36*30418Skarels char *sprintf(); 37*30418Skarels char *rindex(); 38*30418Skarels 39*30418Skarels extern int errno; 40*30418Skarels char namebuf[BBSIZE], *np = namebuf; 41*30418Skarels char bootarea[BBSIZE]; 42*30418Skarels struct disklabel lab; 43*30418Skarels struct disklabel *readlabel(), *getbootarea(); 44*30418Skarels 45*30418Skarels int op; /* one of: */ 46*30418Skarels #define READ 1 47*30418Skarels #define WRITE 2 48*30418Skarels #define EDIT 3 49*30418Skarels #define RESTORE 4 50*30418Skarels 51*30418Skarels main(argc, argv) 52*30418Skarels int argc; 53*30418Skarels char *argv[]; 54*30418Skarels { 55*30418Skarels register struct disklabel *lp; 56*30418Skarels int f, t; 57*30418Skarels char *name = 0, *asciifile, *type; 58*30418Skarels 59*30418Skarels while (argc > 1 && argv[1][0] == '-') { 60*30418Skarels if (strcmp(argv[1], "-e") == 0) { 61*30418Skarels if (argc != 3) 62*30418Skarels goto usage; 63*30418Skarels op = EDIT; 64*30418Skarels } else if (strcmp(argv[1], "-w") == 0) { 65*30418Skarels if (argc != 4) 66*30418Skarels goto usage; 67*30418Skarels op = RESTORE; 68*30418Skarels } else 69*30418Skarels goto usage; 70*30418Skarels argv++; 71*30418Skarels argc--; 72*30418Skarels } 73*30418Skarels if (argc < 2 || argc > 6) { 74*30418Skarels usage: 75*30418Skarels fprintf(stderr, "%s%s%s%s", 76*30418Skarels #ifdef BOOT 77*30418Skarels "usage: disklabel disk (to read label)\n", 78*30418Skarels "or disklabel disk type [ packid ] [ xxboot bootxx ] (to write label)\n", 79*30418Skarels "or disklabel -e disk (to edit label)\n", 80*30418Skarels "or disklabel -w disk protofile [ xxboot bootxx ] (to restore label)\n" 81*30418Skarels #else 82*30418Skarels "usage: disklabel disk (to read label)\n", 83*30418Skarels "or disklabel disk type [ packid ] (to write label)\n", 84*30418Skarels "or disklabel -e disk (to edit label)\n", 85*30418Skarels "or disklabel -w disk protofile (to restore label)\n" 86*30418Skarels #endif 87*30418Skarels ); 88*30418Skarels exit(1); 89*30418Skarels } 90*30418Skarels if (op == 0) 91*30418Skarels if (argc == 2) 92*30418Skarels op = READ; 93*30418Skarels else 94*30418Skarels op = WRITE; 95*30418Skarels dkname = argv[1]; 96*30418Skarels if (dkname[0] != '/') { 97*30418Skarels sprintf(np, "/dev/r%sc", dkname); 98*30418Skarels specname = np; 99*30418Skarels np += strlen(specname) + 1; 100*30418Skarels } else 101*30418Skarels specname = dkname; 102*30418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 103*30418Skarels if (f < 0 && errno == ENOENT && dkname[0] != '/') { 104*30418Skarels sprintf(specname, "/dev/r%s", dkname); 105*30418Skarels np = namebuf + strlen(specname) + 1; 106*30418Skarels f = open(specname, op == READ ? O_RDONLY : O_RDWR); 107*30418Skarels } 108*30418Skarels if (f < 0) 109*30418Skarels Perror(specname); 110*30418Skarels 111*30418Skarels if (op == WRITE) { 112*30418Skarels type = argv[2]; 113*30418Skarels if (argc == 4 || argc == 6) { 114*30418Skarels name = argv[3]; 115*30418Skarels argv++; 116*30418Skarels argc--; 117*30418Skarels } 118*30418Skarels } 119*30418Skarels if (op == RESTORE) { 120*30418Skarels asciifile = argv[2]; 121*30418Skarels argv++; 122*30418Skarels argc--; 123*30418Skarels } 124*30418Skarels #ifdef BOOT 125*30418Skarels if (argc == 5) { 126*30418Skarels xxboot = argv[3]; 127*30418Skarels bootxx = argv[4]; 128*30418Skarels } 129*30418Skarels #endif 130*30418Skarels 131*30418Skarels 132*30418Skarels switch (op) { 133*30418Skarels 134*30418Skarels case READ: 135*30418Skarels lp = readlabel(f, 0); 136*30418Skarels display(stdout, lp); 137*30418Skarels break; 138*30418Skarels 139*30418Skarels case EDIT: 140*30418Skarels lp = readlabel(f, bootarea); 141*30418Skarels edit(f, lp); 142*30418Skarels writelabel(f, bootarea, lp); 143*30418Skarels break; 144*30418Skarels 145*30418Skarels case WRITE: 146*30418Skarels makelabel(type, name, &lab); 147*30418Skarels lp = getbootarea(bootarea, &lab); 148*30418Skarels *lp = lab; 149*30418Skarels writelabel(f, bootarea, lp); 150*30418Skarels break; 151*30418Skarels 152*30418Skarels case RESTORE: 153*30418Skarels lab.d_secsize = DEV_BSIZE; /* XXX */ 154*30418Skarels lab.d_bbsize = BBSIZE; /* XXX */ 155*30418Skarels lp = getbootarea(bootarea, &lab); 156*30418Skarels t = open(asciifile, O_RDONLY); 157*30418Skarels if (t < 0) 158*30418Skarels Perror(asciifile); 159*30418Skarels getasciilabel(t, lp); 160*30418Skarels writelabel(f, bootarea, lp); 161*30418Skarels break; 162*30418Skarels } 163*30418Skarels exit(0); 164*30418Skarels } 165*30418Skarels 166*30418Skarels makelabel(type, name, lp) 167*30418Skarels char *type, *name; 168*30418Skarels register struct disklabel *lp; 169*30418Skarels { 170*30418Skarels register struct disklabel *dp; 171*30418Skarels register char *p; 172*30418Skarels 173*30418Skarels dp = getdiskbyname(type); 174*30418Skarels if (dp == NULL) { 175*30418Skarels fprintf(stderr, "%s: unknown disk type\n", type); 176*30418Skarels exit(1); 177*30418Skarels } 178*30418Skarels *lp = *dp; 179*30418Skarels if (name) 180*30418Skarels strncpy(lp->d_name, name, sizeof(lp->d_name)); 181*30418Skarels } 182*30418Skarels 183*30418Skarels writelabel(f, boot, lp) 184*30418Skarels int f; 185*30418Skarels char *boot; 186*30418Skarels register struct disklabel *lp; 187*30418Skarels { 188*30418Skarels register i; 189*30418Skarels daddr_t alt; 190*30418Skarels 191*30418Skarels lp->d_magic = DISKMAGIC; 192*30418Skarels lp->d_magic2 = DISKMAGIC; 193*30418Skarels #if ENDIAN != BIG 194*30418Skarels swablabel(lp); 195*30418Skarels #endif 196*30418Skarels lp->d_checksum = 0; 197*30418Skarels lp->d_checksum = dkcksum(lp); 198*30418Skarels lseek(f, (off_t)0, L_SET); 199*30418Skarels if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 200*30418Skarels Perror("write"); 201*30418Skarels #ifdef notyet 202*30418Skarels alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 203*30418Skarels for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 204*30418Skarels lseek(f, (off_t)(alt + i) * lp->d_secsize, L_SET); 205*30418Skarels if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 206*30418Skarels int oerrno = errno; 207*30418Skarels fprintf(stderr, "alternate label %d ", i/2); 208*30418Skarels errno = oerrno; 209*30418Skarels perror("write"); 210*30418Skarels } 211*30418Skarels } 212*30418Skarels if (ioctl(f, DIOCSDINFO, lp) < 0) 213*30418Skarels Perror("ioctl DIOCSDINFO"); 214*30418Skarels #endif 215*30418Skarels } 216*30418Skarels 217*30418Skarels /* 218*30418Skarels * Read disklabel from disk. 219*30418Skarels * If boot is given, need bootstrap too. 220*30418Skarels * If boot not needed, could use ioctl to get label. 221*30418Skarels */ 222*30418Skarels struct disklabel * 223*30418Skarels readlabel(f, boot) 224*30418Skarels int f; 225*30418Skarels char *boot; 226*30418Skarels { 227*30418Skarels register struct disklabel *lp; 228*30418Skarels u_long magic = htonl(DISKMAGIC); 229*30418Skarels 230*30418Skarels if (boot == NULL) 231*30418Skarels boot = bootarea; 232*30418Skarels if (read(f, boot, BBSIZE) < BBSIZE) 233*30418Skarels Perror(specname); 234*30418Skarels for (lp = (struct disklabel *)(boot + LABELOFFSET); 235*30418Skarels lp <= (struct disklabel *)(boot + BBSIZE - 236*30418Skarels sizeof(struct disklabel)); 237*30418Skarels lp = (struct disklabel *)((char *)lp + 128)) 238*30418Skarels if (lp->d_magic == magic && lp->d_magic2 == magic) 239*30418Skarels break; 240*30418Skarels if (lp > (struct disklabel *)(boot + BBSIZE - 241*30418Skarels sizeof(struct disklabel)) || 242*30418Skarels lp->d_magic != magic || lp->d_magic2 != magic || 243*30418Skarels dkcksum(lp) != 0) { 244*30418Skarels fprintf(stderr, 245*30418Skarels "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 246*30418Skarels exit(1); 247*30418Skarels } 248*30418Skarels #if ENDIAN != BIG 249*30418Skarels swablabel(lp); 250*30418Skarels #endif 251*30418Skarels return (lp); 252*30418Skarels } 253*30418Skarels 254*30418Skarels struct disklabel * 255*30418Skarels getbootarea(boot, dp) 256*30418Skarels char *boot; 257*30418Skarels register struct disklabel *dp; 258*30418Skarels { 259*30418Skarels struct disklabel *lp; 260*30418Skarels register char *p; 261*30418Skarels int b; 262*30418Skarels 263*30418Skarels #ifdef BOOT 264*30418Skarels if (xxboot == NULL) { 265*30418Skarels dkbasename = np; 266*30418Skarels if ((p = rindex(dkname, '/')) == NULL) 267*30418Skarels p = dkname; 268*30418Skarels else 269*30418Skarels p++; 270*30418Skarels while (*p && !isdigit(*p)) 271*30418Skarels *np++ = *p++; 272*30418Skarels *np++ = '\0'; 273*30418Skarels 274*30418Skarels sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 275*30418Skarels if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 276*30418Skarels dkbasename++; 277*30418Skarels xxboot = np; 278*30418Skarels sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 279*30418Skarels np += strlen(xxboot) + 1; 280*30418Skarels 281*30418Skarels bootxx = np; 282*30418Skarels sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 283*30418Skarels np += strlen(bootxx) + 1; 284*30418Skarels } 285*30418Skarels 286*30418Skarels b = open(xxboot, O_RDONLY); 287*30418Skarels if (b < 0) 288*30418Skarels Perror(xxboot); 289*30418Skarels if (read(b, boot, dp->d_secsize) < 0) 290*30418Skarels Perror(xxboot); 291*30418Skarels close(b); 292*30418Skarels b = open(bootxx, O_RDONLY); 293*30418Skarels if (b < 0) 294*30418Skarels Perror(bootxx); 295*30418Skarels if (read(b, &boot[dp->d_secsize], dp->d_bbsize-dp->d_secsize) < 0) 296*30418Skarels Perror(bootxx); 297*30418Skarels close(b); 298*30418Skarels #endif 299*30418Skarels 300*30418Skarels lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 301*30418Skarels LABELOFFSET); 302*30418Skarels for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 303*30418Skarels if (*p) { 304*30418Skarels fprintf(stderr, 305*30418Skarels "Bootstrap doesn't leave room for disk label\n"); 306*30418Skarels exit(2); 307*30418Skarels } 308*30418Skarels return (lp); 309*30418Skarels } 310*30418Skarels 311*30418Skarels display(f, lp) 312*30418Skarels FILE *f; 313*30418Skarels register struct disklabel *lp; 314*30418Skarels { 315*30418Skarels register i, j; 316*30418Skarels register struct partition *pp; 317*30418Skarels 318*30418Skarels fprintf(f, "# %s:\n", specname); 319*30418Skarels if ((unsigned) lp->d_type < DKMAXTYPES) 320*30418Skarels fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 321*30418Skarels else 322*30418Skarels fprintf(f, "type: %d\n", lp->d_type); 323*30418Skarels fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 324*30418Skarels fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 325*30418Skarels fprintf(f, "flags: "); 326*30418Skarels if (lp->d_flags & D_REMOVABLE) 327*30418Skarels fprintf(f, "removeable "); 328*30418Skarels if (lp->d_flags & D_ECC) 329*30418Skarels fprintf(f, "ecc "); 330*30418Skarels if (lp->d_flags & D_BADSECT) 331*30418Skarels fprintf(f, "badsect "); 332*30418Skarels fprintf(f, "\n"); 333*30418Skarels fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 334*30418Skarels fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 335*30418Skarels fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 336*30418Skarels fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 337*30418Skarels fprintf(f, "interleave: %d\n", lp->d_interleave); 338*30418Skarels fprintf(f, "trackskew: %d\n", lp->d_trackskew); 339*30418Skarels fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 340*30418Skarels fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 341*30418Skarels fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 342*30418Skarels fprintf(f, "drivedata: "); 343*30418Skarels for (i = NDDATA - 1; i >= 0; i--) 344*30418Skarels if (lp->d_drivedata[i]) 345*30418Skarels break; 346*30418Skarels if (i < 0) 347*30418Skarels i = 0; 348*30418Skarels for (j = 0; j <= i; j++) 349*30418Skarels fprintf(f, "%d ", lp->d_drivedata[j]); 350*30418Skarels fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 351*30418Skarels fprintf(f, "#\t size offset fstype\n"); 352*30418Skarels pp = lp->d_partitions; 353*30418Skarels for (i = 0; i < lp->d_npartitions; i++, pp++) { 354*30418Skarels fprintf(f, "\t%c: %8d %8d ", 'a' + i, 355*30418Skarels pp->p_size, pp->p_offset); 356*30418Skarels if (pp->p_size) { 357*30418Skarels if ((unsigned) pp->p_fstype < FSMAXTYPES) 358*30418Skarels fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 359*30418Skarels else 360*30418Skarels fprintf(f, "%8d", pp->p_fstype); 361*30418Skarels fprintf(f, "\t# (Cyl. %4d", 362*30418Skarels pp->p_offset / lp->d_secpercyl); 363*30418Skarels if (pp->p_offset % lp->d_secpercyl) 364*30418Skarels putc('*', f); 365*30418Skarels else 366*30418Skarels putc(' ', f); 367*30418Skarels fprintf(f, "- %d", 368*30418Skarels (pp->p_offset + 369*30418Skarels pp->p_size + lp->d_secpercyl - 1) / 370*30418Skarels lp->d_secpercyl - 1); 371*30418Skarels if (pp->p_size % lp->d_secpercyl) 372*30418Skarels putc('*', f); 373*30418Skarels putc(')', f); 374*30418Skarels } 375*30418Skarels fprintf(f, "\n"); 376*30418Skarels } 377*30418Skarels } 378*30418Skarels 379*30418Skarels edit(f) 380*30418Skarels int f; 381*30418Skarels { 382*30418Skarels fprintf(stderr, "sorry, not yet\n"); 383*30418Skarels exit(1); 384*30418Skarels } 385*30418Skarels 386*30418Skarels 387*30418Skarels /* 388*30418Skarels * Read an ascii label in from fd f, 389*30418Skarels * in the same format as that put out by display(), 390*30418Skarels * and fill in lp. 391*30418Skarels */ 392*30418Skarels getasciilabel(f, lp) 393*30418Skarels int f; 394*30418Skarels register struct disklabel *lp; 395*30418Skarels { 396*30418Skarels fprintf(stderr, "sorry, not yet\n"); 397*30418Skarels exit(1); 398*30418Skarels } 399*30418Skarels 400*30418Skarels Perror(op) 401*30418Skarels char *op; 402*30418Skarels { 403*30418Skarels 404*30418Skarels fprintf(stderr, "disklabel: "); perror(op); 405*30418Skarels exit(4); 406*30418Skarels } 407