1: /* 2: * Copyright (c) 1987, 1993 3: * The Regents of the University of California. All rights reserved. 4: * 5: * This code is derived from software contributed to Berkeley by 6: * Symmetric Computer Systems. 7: * 8: * Redistribution and use in source and binary forms, with or without 9: * modification, are permitted provided that the following conditions 10: * are met: 11: * 1. Redistributions of source code must retain the above copyright 12: * notice, this list of conditions and the following disclaimer. 13: * 2. Redistributions in binary form must reproduce the above copyright 14: * notice, this list of conditions and the following disclaimer in the 15: * documentation and/or other materials provided with the distribution. 16: * 3. All advertising materials mentioning features or use of this software 17: * must display the following acknowledgement: 18: * This product includes software developed by the University of 19: * California, Berkeley and its contributors. 20: * 4. Neither the name of the University nor the names of its contributors 21: * may be used to endorse or promote products derived from this software 22: * without specific prior written permission. 23: * 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34: * SUCH DAMAGE. 35: */ 36: 37: #if !defined(lint) && defined(DOSCCS) 38: static char copyright[] = 39: "@(#) Copyright (c) 1987, 1993\n\ 40: The Regents of the University of California. All rights reserved.\n"; 41: 42: static char sccsid[] = "@(#)disklabel.c 8.1.3 (2.11BSD) 1999/10/25"; 43: /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 44: #endif 45: 46: #include <sys/param.h> 47: #include <sys/signal.h> 48: #include <sys/errno.h> 49: #include <sys/file.h> 50: #include <sys/ioctl.h> 51: #include <sys/stat.h> 52: #define DKTYPENAMES 53: #include <sys/disklabel.h> 54: #include <sys/fs.h> 55: #include <string.h> 56: #include <stdlib.h> 57: #include <stdio.h> 58: #include <ctype.h> 59: #include "pathnames.h" 60: 61: /* 62: * Disklabel: read and write disklabels. 63: * The label is usually placed on one of the first sectors of the disk. 64: * Many machines also place a bootstrap in the same area, 65: * in which case the label is embedded in the bootstrap. 66: * The bootstrap source must leave space at the proper offset 67: * for the label on such machines. 68: */ 69: 70: /* 71: * 2.11BSD has to do some things differently than other systems. BBSIZE 72: * may be 1024 bytes but the disk boot roms only read the 512 byte sector 0. 73: * The boot and label areas each occupy 1/2 of the 1kb 'filesystem block' 74: * which precedes the superblock. The bootblock is sector 0 and the label block 75: * is sector 1. Each is a disjoint and independent area. Thus the logic in 76: * this program which treated the label area as a subset or offset of the 77: * boot area had to change. 78: * 79: * The 'a' partition is used to access the raw device - as did the 'tahoe'. 80: */ 81: 82: #define RAWPARTITION 'a' 83: 84: #define DEFEDITOR _PATH_VI 85: #define streq(a,b) (strcmp(a,b) == 0) 86: 87: char *dkname; 88: char *specname; 89: char tmpfil[] = _PATH_TMP; 90: 91: char namebuf[256], *np = namebuf; 92: struct disklabel lab; 93: struct disklabel *readlabel(), *makebootarea(); 94: char bootarea[BBSIZE]; /* 512 for bootblock, 512 for label */ 95: 96: int installboot; /* non-zero if we should install a boot program */ 97: char *xxboot; /* primary boot */ 98: char boot0[MAXPATHLEN]; 99: 100: enum { 101: UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT 102: } op = UNSPEC; 103: 104: int rflag; 105: 106: #ifdef DEBUG 107: int debug; 108: #define OPTIONS "BNRWb:derw" 109: #else 110: #define OPTIONS "BNRWb:erw" 111: #endif 112: 113: main(argc, argv) 114: int argc; 115: char *argv[]; 116: { 117: register struct disklabel *lp; 118: FILE *t; 119: int ch, f, flag, error = 0; 120: char *name = 0; 121: 122: while ((ch = getopt(argc, argv, OPTIONS)) != EOF) 123: switch (ch) { 124: case 'B': 125: ++installboot; 126: break; 127: case 'b': 128: xxboot = optarg; 129: break; 130: case 'N': 131: if (op != UNSPEC) 132: usage(); 133: op = NOWRITE; 134: break; 135: case 'R': 136: if (op != UNSPEC) 137: usage(); 138: op = RESTORE; 139: break; 140: case 'W': 141: if (op != UNSPEC) 142: usage(); 143: op = WRITEABLE; 144: break; 145: case 'e': 146: if (op != UNSPEC) 147: usage(); 148: op = EDIT; 149: break; 150: case 'r': 151: ++rflag; 152: break; 153: case 'w': 154: if (op != UNSPEC) 155: usage(); 156: op = WRITE; 157: break; 158: #ifdef DEBUG 159: case 'd': 160: debug++; 161: break; 162: #endif 163: case '?': 164: default: 165: usage(); 166: } 167: argc -= optind; 168: argv += optind; 169: if (installboot) { 170: rflag++; 171: if (op == UNSPEC) 172: op = WRITEBOOT; 173: } else { 174: if (op == UNSPEC) 175: op = READ; 176: xxboot = 0; 177: } 178: 179: if (argc < 1) 180: usage(); 181: 182: dkname = argv[0]; 183: if (dkname[0] != '/') { 184: (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION); 185: specname = np; 186: np += strlen(specname) + 1; 187: } else 188: specname = dkname; 189: f = open(specname, op == READ ? O_RDONLY : O_RDWR); 190: if (f < 0 && errno == ENOENT && dkname[0] != '/') { 191: (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname); 192: np = namebuf + strlen(specname) + 1; 193: f = open(specname, op == READ ? O_RDONLY : O_RDWR); 194: } 195: if (f < 0) 196: Perror(specname); 197: 198: switch(op) { 199: 200: case EDIT: 201: if (argc != 1) 202: usage(); 203: lp = readlabel(f); 204: error = edit(lp, f); 205: break; 206: 207: case NOWRITE: 208: flag = 0; 209: if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 210: Perror("ioctl DIOCWLABEL"); 211: break; 212: 213: case READ: 214: if (argc != 1) 215: usage(); 216: lp = readlabel(f); 217: display(stdout, lp); 218: error = checklabel(lp); 219: break; 220: 221: case RESTORE: 222: if (installboot && argc == 3) { 223: makelabel(argv[2], 0, &lab); 224: argc--; 225: } 226: if (argc != 2) 227: usage(); 228: lp = makebootarea(bootarea, &lab, f); 229: if (!(t = fopen(argv[1], "r"))) 230: Perror(argv[1]); 231: if (getasciilabel(t, lp)) 232: error = writelabel(f, bootarea, lp); 233: break; 234: 235: case WRITE: 236: if (argc == 3) { 237: name = argv[2]; 238: argc--; 239: } 240: if (argc != 2) 241: usage(); 242: makelabel(argv[1], name, &lab); 243: lp = makebootarea(bootarea, &lab, f); 244: *lp = lab; 245: if (checklabel(lp) == 0) 246: error = writelabel(f, bootarea, lp); 247: break; 248: 249: case WRITEABLE: 250: flag = 1; 251: if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 252: Perror("ioctl DIOCWLABEL"); 253: break; 254: 255: case WRITEBOOT: 256: { 257: struct disklabel tlab; 258: 259: lp = readlabel(f); 260: tlab = *lp; 261: if (argc == 2) 262: makelabel(argv[1], 0, &lab); 263: lp = makebootarea(bootarea, &lab, f); 264: *lp = tlab; 265: if (checklabel(lp) == 0) 266: error = writelabel(f, bootarea, lp); 267: break; 268: } 269: } 270: exit(error); 271: } 272: 273: /* 274: * Construct a prototype disklabel from /etc/disktab. As a side 275: * effect, set the names of the primary and secondary boot files 276: * if specified. 277: */ 278: makelabel(type, name, lp) 279: char *type, *name; 280: register struct disklabel *lp; 281: { 282: register struct disklabel *dp; 283: char *strcpy(); 284: 285: dp = getdiskbyname(type); 286: if (dp == NULL) { 287: fprintf(stderr, "%s: unknown disk type\n", type); 288: exit(1); 289: } 290: *lp = *dp; 291: 292: /* 293: * Set bootstrap name. 294: * 1. If set from command line, use it, 295: * 2. otherwise, check if disktab specifies it (b0), 296: * 3. otherwise, makebootarea() will choose one based on the name 297: * of the disk special file. E.g. /dev/ra0 -> rauboot 298: */ 299: if (!xxboot && lp->d_boot0) { 300: if (*lp->d_boot0 != '/') 301: (void)sprintf(boot0, "%s/%s", 302: _PATH_BOOTDIR, lp->d_boot0); 303: else 304: (void)strcpy(boot0, lp->d_boot0); 305: xxboot = boot0; 306: } 307: /* d_packname is union d_boot0, so zero */ 308: bzero(lp->d_packname, sizeof(lp->d_packname)); 309: if (name) 310: (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 311: } 312: 313: writelabel(f, boot, lp) 314: int f; 315: char *boot; 316: register struct disklabel *lp; 317: { 318: register int i; 319: int flag; 320: 321: lp->d_magic = DISKMAGIC; 322: lp->d_magic2 = DISKMAGIC; 323: lp->d_checksum = 0; 324: lp->d_checksum = dkcksum(lp); 325: if (rflag) { 326: /* 327: * First set the kernel disk label, 328: * then write a label to the raw disk. 329: * If the SDINFO ioctl fails because it is unimplemented, 330: * keep going; otherwise, the kernel consistency checks 331: * may prevent us from changing the current (in-core) 332: * label. Normally EFAULT would not be here - but the ioctl 333: * maximum data length changed and old kernels would generate 334: * an error prematurely in the ioctl dispatch. 335: */ 336: if (ioctl(f, DIOCSDINFO, lp) < 0 && 337: errno != EFAULT && errno != ENODEV && errno != ENOTTY) { 338: l_perror("ioctl DIOCSDINFO"); 339: return (1); 340: } 341: (void)lseek(f, (off_t)0, L_SET); 342: /* 343: * write enable label sector before write (if necessary), 344: * disable after writing. 345: */ 346: flag = 1; 347: if (ioctl(f, DIOCWLABEL, &flag) < 0) 348: perror("ioctl DIOCWLABEL"); 349: /* 350: * Write the boot block sector (512 bytes) followed immediately by the 351: * label sector (512 bytes) = BBSIZE (1kb) total. 352: */ 353: if (write(f, boot, BBSIZE) != BBSIZE) { 354: perror("write"); 355: return (1); 356: } 357: flag = 0; 358: (void) ioctl(f, DIOCWLABEL, &flag); 359: } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 360: l_perror("ioctl DIOCWDINFO"); 361: return (1); 362: } 363: return (0); 364: } 365: 366: l_perror(s) 367: char *s; 368: { 369: int saverrno = errno; 370: 371: fprintf(stderr, "disklabel: %s: ", s); 372: 373: switch (saverrno) { 374: 375: case ESRCH: 376: fprintf(stderr, "No disk label on disk;\n"); 377: fprintf(stderr, 378: "use \"disklabel -r\" to install initial label\n"); 379: break; 380: 381: case EINVAL: 382: fprintf(stderr, "Label magic number or checksum is wrong!\n"); 383: fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 384: break; 385: 386: case EBUSY: 387: fprintf(stderr, "Open partition would move or shrink\n"); 388: break; 389: 390: case EXDEV: 391: fprintf(stderr, 392: "Labeled partition or 'a' partition must start at beginning of disk\n"); 393: break; 394: 395: default: 396: errno = saverrno; 397: perror((char *)NULL); 398: break; 399: } 400: } 401: 402: /* 403: * Fetch disklabel for disk. 404: * Use ioctl to get label unless -r flag is given. 405: * 406: * We use the search logic for the label even though the label will be 407: * in the second half of the bootarea. If there ever is a valid label 408: * residing in the boot sector things are going to get weird. 409: */ 410: struct disklabel * 411: readlabel(f) 412: int f; 413: { 414: register struct disklabel *lp; 415: register struct disklabel *xx = (struct disklabel *)(bootarea + BBSIZE - sizeof (struct disklabel)); 416: 417: if (rflag) { 418: if (lseek(f, (daddr_t)0, L_SET) < 0) 419: Perror(specname); 420: if (read(f, bootarea, BBSIZE) < BBSIZE) 421: Perror(specname); 422: for (lp = (struct disklabel *)bootarea; 423: lp <= xx; 424: lp = (struct disklabel *)((char *)lp + 16)) 425: if (lp->d_magic == DISKMAGIC && 426: lp->d_magic2 == DISKMAGIC) 427: break; 428: if (lp > xx || 429: lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 430: dkcksum(lp) != 0) { 431: fprintf(stderr, 432: "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 433: exit (1); 434: } 435: } else { 436: lp = &lab; 437: if (ioctl(f, DIOCGDINFO, lp) < 0) 438: Perror("ioctl DIOCGDINFO"); 439: } 440: return (lp); 441: } 442: 443: /* 444: * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 445: * Returns a pointer to the disklabel portion of the bootarea. 446: */ 447: struct disklabel * 448: makebootarea(boot, dp, f) 449: char *boot; 450: register struct disklabel *dp; 451: int f; 452: { 453: struct disklabel *lp; 454: register char *p; 455: int b; 456: char *dkbasename; 457: struct stat sb; 458: 459: /* XXX */ 460: /* 461: * sectors are 512 bytes, filesystem blocks are DEV_BSIZE (1024) bytes. 462: * We override the sector size so that things like the RL02 work 463: * right. The RL drives use a hardware sector size of 256 bytes 464: * which would wreck havoc in the calculation below. Actually the 465: * disktab file should be "fixed" - all entries should omit 'se' and 466: * use the default of 512. 467: */ 468: dp->d_secsize = 512; 469: dp->d_bbsize = 512; 470: lp = (struct disklabel *) 471: (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 472: bzero((char *)lp, sizeof *lp); 473: 474: /* 475: * If we are not installing a boot program but we are installing a 476: * label on disk then we must read the current bootarea so we don't 477: * clobber the existing boot. 478: */ 479: if (!installboot) { 480: if (rflag) { 481: if (lseek(f, (daddr_t)0, L_SET) < 0) 482: Perror(specname); 483: if (read(f, boot, BBSIZE) < BBSIZE) 484: Perror(specname); 485: bzero((char *)lp, sizeof *lp); 486: } 487: return (lp); 488: } 489: /* 490: * We are installing a boot program. Determine the name(s) and 491: * read them into the appropriate places in the boot area. 492: */ 493: if (!xxboot) { 494: dkbasename = np; 495: if ((p = rindex(dkname, '/')) == NULL) 496: p = dkname; 497: else 498: p++; 499: while (*p && !isdigit(*p)) 500: *np++ = *p++; 501: *np++ = '\0'; 502: 503: (void)sprintf(np, "%s/%suboot", 504: _PATH_BOOTDIR, dkbasename); 505: if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 506: dkbasename++; 507: xxboot = np; 508: (void)sprintf(xxboot, "%s/%suboot", 509: _PATH_BOOTDIR, dkbasename); 510: np += strlen(xxboot) + 1; 511: } 512: #ifdef DEBUG 513: if (debug) 514: fprintf(stderr, "bootstrap: xxboot = %s\n", xxboot); 515: #endif 516: 517: /* 518: * Rule: 519: * 1. One-piece bootstrap up to 512 bytes is all that is supported. 520: */ 521: b = open(xxboot, O_RDONLY); 522: if (b < 0) 523: Perror(xxboot); 524: if (read(b, boot, 512) < 0) 525: Perror(xxboot); 526: (void)fstat(b, &sb); 527: if (sb.st_size > 512) 528: Warning("boot > 512 bytes - filesystem likely not bootable"); 529: (void)close(b); 530: return (lp); 531: } 532: 533: display(f, lp) 534: FILE *f; 535: register struct disklabel *lp; 536: { 537: register int i, j; 538: register struct partition *pp; 539: 540: fprintf(f, "# %s:\n", specname); 541: if ((unsigned) lp->d_type < DKMAXTYPES) 542: fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 543: else 544: fprintf(f, "type: %d\n", lp->d_type); 545: fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 546: fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname); 547: fprintf(f, "flags:"); 548: if (lp->d_flags & D_REMOVABLE) 549: fprintf(f, " removeable"); 550: if (lp->d_flags & D_ECC) 551: fprintf(f, " ecc"); 552: if (lp->d_flags & D_BADSECT) 553: fprintf(f, " badsect"); 554: fprintf(f, "\n"); 555: fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 556: fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 557: fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 558: fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 559: fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 560: fprintf(f, "rpm: %d\n", lp->d_rpm); 561: fprintf(f, "interleave: %d\n", lp->d_interleave); 562: fprintf(f, "trackskew: %d\n", lp->d_trackskew); 563: fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 564: fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 565: fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 566: fprintf(f, "drivedata: "); 567: for (i = NDDATA - 1; i >= 0; i--) 568: if (lp->d_drivedata[i]) 569: break; 570: if (i < 0) 571: i = 0; 572: for (j = 0; j <= i; j++) 573: fprintf(f, "%ld ", lp->d_drivedata[j]); 574: fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 575: fprintf(f, 576: "# size offset fstype [fsize bsize]\n"); 577: pp = lp->d_partitions; 578: for (i = 0; i < lp->d_npartitions; i++, pp++) { 579: if (pp->p_size) { 580: fprintf(f, " %c: %8ld %8ld ", 'a' + i, 581: pp->p_size, pp->p_offset); 582: if ((unsigned) pp->p_fstype < FSMAXTYPES) 583: fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 584: else 585: fprintf(f, "%8d", pp->p_fstype); 586: switch (pp->p_fstype) { 587: 588: case FS_V71K: 589: case FS_UNUSED: /* XXX */ 590: fprintf(f, " %5d %5d ", 591: pp->p_fsize, pp->p_fsize * pp->p_frag); 592: break; 593: 594: default: 595: fprintf(f, "%20.20s", ""); 596: break; 597: } 598: fprintf(f, "\t# (Cyl. %4ld", 599: pp->p_offset / lp->d_secpercyl); 600: if (pp->p_offset % lp->d_secpercyl) 601: putc('*', f); 602: else 603: putc(' ', f); 604: fprintf(f, "- %ld", 605: (pp->p_offset + 606: pp->p_size + lp->d_secpercyl - 1) / 607: lp->d_secpercyl - 1); 608: if (pp->p_size % lp->d_secpercyl) 609: putc('*', f); 610: fprintf(f, ")\n"); 611: } 612: } 613: fflush(f); 614: } 615: 616: edit(lp, f) 617: struct disklabel *lp; 618: int f; 619: { 620: register int c; 621: struct disklabel label; 622: FILE *fd; 623: char *mktemp(); 624: 625: (void) mktemp(tmpfil); 626: fd = fopen(tmpfil, "w"); 627: if (fd == NULL) { 628: fprintf(stderr, "%s: Can't create\n", tmpfil); 629: return (1); 630: } 631: (void)fchmod(fileno(fd), 0600); 632: display(fd, lp); 633: fclose(fd); 634: for (;;) { 635: if (!editit()) 636: break; 637: fd = fopen(tmpfil, "r"); 638: if (fd == NULL) { 639: fprintf(stderr, "%s: Can't reopen for reading\n", 640: tmpfil); 641: break; 642: } 643: bzero((char *)&label, sizeof(label)); 644: if (getasciilabel(fd, &label)) { 645: *lp = label; 646: if (writelabel(f, bootarea, lp) == 0) { 647: (void) unlink(tmpfil); 648: return (0); 649: } 650: } 651: printf("re-edit the label? [y]: "); fflush(stdout); 652: c = getchar(); 653: if (c != EOF && c != (int)'\n') 654: while (getchar() != (int)'\n') 655: ; 656: if (c == (int)'n') 657: break; 658: } 659: (void) unlink(tmpfil); 660: return (1); 661: } 662: 663: editit() 664: { 665: register int pid, xpid; 666: int stat; 667: sigset_t set, oset; 668: 669: sigemptyset(&set); 670: sigaddset(&set, SIGINT); 671: sigaddset(&set, SIGHUP); 672: sigaddset(&set, SIGQUIT); 673: (void)sigprocmask(SIG_BLOCK, &set, &oset); 674: while ((pid = fork()) < 0) { 675: 676: if (errno == EPROCLIM) { 677: fprintf(stderr, "You have too many processes\n"); 678: return(0); 679: } 680: if (errno != EAGAIN) { 681: perror("fork"); 682: return(0); 683: } 684: sleep(1); 685: } 686: if (pid == 0) { 687: register char *ed; 688: 689: (void)sigprocmask(SIG_SETMASK, &oset, NULL); 690: setgid(getgid()); 691: setuid(getuid()); 692: if ((ed = getenv("EDITOR")) == (char *)0) 693: ed = DEFEDITOR; 694: execlp(ed, ed, tmpfil, 0); 695: perror(ed); 696: exit(1); 697: } 698: while ((xpid = wait(&stat)) >= 0) 699: if (xpid == pid) 700: break; 701: (void)sigprocmask(SIG_SETMASK, &oset, NULL); 702: return(!stat); 703: } 704: 705: char * 706: skip(cp) 707: register char *cp; 708: { 709: 710: while (*cp != '\0' && isspace(*cp)) 711: cp++; 712: if (*cp == '\0' || *cp == '#') 713: return ((char *)NULL); 714: return (cp); 715: } 716: 717: char * 718: word(cp) 719: register char *cp; 720: { 721: register char c; 722: 723: while (*cp != '\0' && !isspace(*cp) && *cp != '#') 724: cp++; 725: if ((c = *cp) != '\0') { 726: *cp++ = '\0'; 727: if (c != '#') 728: return (skip(cp)); 729: } 730: return ((char *)NULL); 731: } 732: 733: /* 734: * Read an ascii label in from fd f, 735: * in the same format as that put out by display(), 736: * and fill in lp. 737: */ 738: getasciilabel(f, lp) 739: FILE *f; 740: register struct disklabel *lp; 741: { 742: register char **cpp, *cp; 743: register struct partition *pp; 744: char *tp, *s, line[BUFSIZ]; 745: int lineno = 0, errors = 0; 746: long v; 747: 748: lp->d_bbsize = 512; /* XXX */ 749: lp->d_sbsize = SBSIZE; 750: while (fgets(line, sizeof(line) - 1, f)) { 751: lineno++; 752: if (cp = index(line,'\n')) 753: *cp = '\0'; 754: cp = skip(line); 755: if (cp == NULL) 756: continue; 757: tp = index(cp, ':'); 758: if (tp == NULL) { 759: fprintf(stderr, "line %d: syntax error\n", lineno); 760: errors++; 761: continue; 762: } 763: *tp++ = '\0', tp = skip(tp); 764: if (streq(cp, "type")) { 765: if (tp == NULL) 766: tp = "unknown"; 767: cpp = dktypenames; 768: for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 769: if ((s = *cpp) && streq(s, tp)) { 770: lp->d_type = cpp - dktypenames; 771: goto next; 772: } 773: v = atoi(tp); 774: if ((unsigned)v >= DKMAXTYPES) 775: fprintf(stderr, "line %d:%s %d\n", lineno, 776: "Warning, unknown disk type", v); 777: lp->d_type = v; 778: continue; 779: } 780: if (streq(cp, "flags")) { 781: for (v = 0; (cp = tp) && *cp != '\0';) { 782: tp = word(cp); 783: if (streq(cp, "removeable")) 784: v |= D_REMOVABLE; 785: else if (streq(cp, "ecc")) 786: v |= D_ECC; 787: else if (streq(cp, "badsect")) 788: v |= D_BADSECT; 789: else { 790: fprintf(stderr, 791: "line %d: %s: bad flag\n", 792: lineno, cp); 793: errors++; 794: } 795: } 796: lp->d_flags = v; 797: continue; 798: } 799: if (streq(cp, "drivedata")) { 800: register int i; 801: 802: for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 803: lp->d_drivedata[i++] = atol(cp); 804: tp = word(cp); 805: } 806: continue; 807: } 808: if (sscanf(cp, "%ld partitions", &v) == 1) { 809: if (v == 0 || (unsigned)v > MAXPARTITIONS) { 810: fprintf(stderr, 811: "line %d: bad # of partitions\n", lineno); 812: lp->d_npartitions = MAXPARTITIONS; 813: errors++; 814: } else 815: lp->d_npartitions = v; 816: continue; 817: } 818: if (tp == NULL) 819: tp = ""; 820: if (streq(cp, "disk")) { 821: strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 822: continue; 823: } 824: if (streq(cp, "label")) { 825: strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 826: continue; 827: } 828: /* 829: * ARGH! Have to fix the 'se#256' entries in disktab after all or this 830: * check will cause errors. 831: */ 832: if (streq(cp, "bytes/sector")) { 833: v = atoi(tp); 834: if (v <= 0 || (v % 512) != 0) { 835: fprintf(stderr, 836: "line %d: %s: bad sector size\n", 837: lineno, tp); 838: errors++; 839: } else 840: lp->d_secsize = v; 841: continue; 842: } 843: if (streq(cp, "sectors/track")) { 844: v = atoi(tp); 845: if (v <= 0) { 846: fprintf(stderr, "line %d: %s: bad %s\n", 847: lineno, tp, cp); 848: errors++; 849: } else 850: lp->d_nsectors = v; 851: continue; 852: } 853: if (streq(cp, "sectors/cylinder")) { 854: v = atoi(tp); 855: if (v <= 0) { 856: fprintf(stderr, "line %d: %s: bad %s\n", 857: lineno, tp, cp); 858: errors++; 859: } else 860: lp->d_secpercyl = v; 861: continue; 862: } 863: if (streq(cp, "tracks/cylinder")) { 864: v = atoi(tp); 865: if (v <= 0) { 866: fprintf(stderr, "line %d: %s: bad %s\n", 867: lineno, tp, cp); 868: errors++; 869: } else 870: lp->d_ntracks = v; 871: continue; 872: } 873: if (streq(cp, "cylinders")) { 874: v = atoi(tp); 875: if (v <= 0) { 876: fprintf(stderr, "line %d: %s: bad %s\n", 877: lineno, tp, cp); 878: errors++; 879: } else 880: lp->d_ncylinders = v; 881: continue; 882: } 883: if (streq(cp, "rpm")) { 884: v = atoi(tp); 885: if (v <= 0) { 886: fprintf(stderr, "line %d: %s: bad %s\n", 887: lineno, tp, cp); 888: errors++; 889: } else 890: lp->d_rpm = v; 891: continue; 892: } 893: if (streq(cp, "interleave")) { 894: v = atoi(tp); 895: if (v <= 0) { 896: fprintf(stderr, "line %d: %s: bad %s\n", 897: lineno, tp, cp); 898: errors++; 899: } else 900: lp->d_interleave = v; 901: continue; 902: } 903: if (streq(cp, "trackskew")) { 904: v = atoi(tp); 905: if (v < 0) { 906: fprintf(stderr, "line %d: %s: bad %s\n", 907: lineno, tp, cp); 908: errors++; 909: } else 910: lp->d_trackskew = v; 911: continue; 912: } 913: if (streq(cp, "cylinderskew")) { 914: v = atoi(tp); 915: if (v < 0) { 916: fprintf(stderr, "line %d: %s: bad %s\n", 917: lineno, tp, cp); 918: errors++; 919: } else 920: lp->d_cylskew = v; 921: continue; 922: } 923: if (streq(cp, "headswitch")) { 924: v = atoi(tp); 925: if (v < 0) { 926: fprintf(stderr, "line %d: %s: bad %s\n", 927: lineno, tp, cp); 928: errors++; 929: } else 930: lp->d_headswitch = v; 931: continue; 932: } 933: if (streq(cp, "track-to-track seek")) { 934: v = atoi(tp); 935: if (v < 0) { 936: fprintf(stderr, "line %d: %s: bad %s\n", 937: lineno, tp, cp); 938: errors++; 939: } else 940: lp->d_trkseek = v; 941: continue; 942: } 943: if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 944: unsigned part = *cp - 'a'; 945: 946: if (part > lp->d_npartitions) { 947: fprintf(stderr, 948: "line %d: bad partition name '%c' %d %d\n", 949: lineno, *cp, part, lp->d_npartitions); 950: errors++; 951: continue; 952: } 953: pp = &lp->d_partitions[part]; 954: #define NXTNUM(n) { \ 955: cp = tp, tp = word(cp); \ 956: if (tp == NULL) \ 957: tp = cp; \ 958: (n) = atol(cp); \ 959: } 960: 961: NXTNUM(v); 962: if (v < 0) { 963: fprintf(stderr, 964: "line %d: %s: bad partition size\n", 965: lineno, cp); 966: errors++; 967: } else 968: pp->p_size = v; 969: NXTNUM(v); 970: if (v < 0) { 971: fprintf(stderr, 972: "line %d: %s: bad partition offset\n", 973: lineno, cp); 974: errors++; 975: } else 976: pp->p_offset = v; 977: cp = tp, tp = word(cp); 978: cpp = fstypenames; 979: for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 980: if ((s = *cpp) && streq(s, cp)) { 981: pp->p_fstype = cpp - fstypenames; 982: goto gottype; 983: } 984: if (isdigit(*cp)) 985: v = atoi(cp); 986: else 987: v = FSMAXTYPES; 988: if ((unsigned)v >= FSMAXTYPES) { 989: fprintf(stderr, "line %d: %s %s\n", lineno, 990: "Warning, unknown filesystem type", cp); 991: v = FS_UNUSED; 992: } 993: pp->p_fstype = v; 994: gottype: 995: 996: switch (pp->p_fstype) { 997: 998: case FS_UNUSED: /* XXX */ 999: case FS_V71K: 1000: NXTNUM(pp->p_fsize); 1001: if (pp->p_fsize == 0) 1002: break; 1003: NXTNUM(v); 1004: pp->p_frag = v / pp->p_fsize; 1005: break; 1006: 1007: default: 1008: break; 1009: } 1010: continue; 1011: } 1012: fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 1013: lineno, cp); 1014: errors++; 1015: next: 1016: ; 1017: } 1018: errors += checklabel(lp); 1019: return (errors == 0); 1020: } 1021: 1022: /* 1023: * Check disklabel for errors and fill in 1024: * derived fields according to supplied values. 1025: */ 1026: checklabel(lp) 1027: register struct disklabel *lp; 1028: { 1029: register struct partition *pp; 1030: int i, errors = 0; 1031: char part; 1032: 1033: if (lp->d_secsize == 0) { 1034: fprintf(stderr, "sector size %d\n", lp->d_secsize); 1035: return (1); 1036: } 1037: if (lp->d_nsectors == 0) { 1038: fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 1039: return (1); 1040: } 1041: if (lp->d_ntracks == 0) { 1042: fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 1043: return (1); 1044: } 1045: if (lp->d_ncylinders == 0) { 1046: fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 1047: errors++; 1048: } 1049: if (lp->d_rpm == 0) 1050: Warning("revolutions/minute %d", lp->d_rpm); 1051: if (lp->d_secpercyl == 0) 1052: lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1053: if (lp->d_secperunit == 0) 1054: lp->d_secperunit = (long) lp->d_secpercyl * lp->d_ncylinders; 1055: if (lp->d_bbsize == 0) { 1056: fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 1057: errors++; 1058: } else if (lp->d_bbsize % lp->d_secsize) 1059: Warning("boot block size %% sector-size != 0"); 1060: if (lp->d_sbsize == 0) { 1061: fprintf(stderr, "super block size %d\n", lp->d_sbsize); 1062: errors++; 1063: } else if (lp->d_sbsize % lp->d_secsize) 1064: Warning("super block size %% sector-size != 0"); 1065: if (lp->d_npartitions > MAXPARTITIONS) 1066: Warning("number of partitions (%d) > MAXPARTITIONS (%d)", 1067: lp->d_npartitions, MAXPARTITIONS); 1068: for (i = 0; i < lp->d_npartitions; i++) { 1069: part = 'a' + i; 1070: pp = &lp->d_partitions[i]; 1071: if (pp->p_size == 0 && pp->p_offset != 0) 1072: Warning("partition %c: size 0, but offset %ld", 1073: part, pp->p_offset); 1074: #ifdef notdef 1075: if (pp->p_size % lp->d_secpercyl) 1076: Warning("partition %c: size %% cylinder-size != 0", 1077: part); 1078: if (pp->p_offset % lp->d_secpercyl) 1079: Warning("partition %c: offset %% cylinder-size != 0", 1080: part); 1081: #endif 1082: if (pp->p_offset > lp->d_secperunit) { 1083: fprintf(stderr, 1084: "partition %c: offset past end of unit %ld %ld\n", 1085: part, pp->p_offset, lp->d_secperunit); 1086: errors++; 1087: } 1088: if (pp->p_offset + pp->p_size > lp->d_secperunit) { 1089: fprintf(stderr, 1090: "partition %c: extends past end of unit %ld %ld %ld\n", 1091: part, pp->p_offset, pp->p_size, lp->d_secperunit); 1092: errors++; 1093: } 1094: } 1095: for (; i < MAXPARTITIONS; i++) { 1096: part = 'a' + i; 1097: pp = &lp->d_partitions[i]; 1098: if (pp->p_size || pp->p_offset) 1099: Warning("unused partition %c: size %ld offset %ld", 1100: 'a' + i, pp->p_size, pp->p_offset); 1101: } 1102: return (errors); 1103: } 1104: 1105: /*VARARGS1*/ 1106: Warning(fmt, a1, a2, a3, a4, a5) 1107: char *fmt; 1108: { 1109: 1110: fprintf(stderr, "Warning, "); 1111: fprintf(stderr, fmt, a1, a2, a3, a4, a5); 1112: fprintf(stderr, "\n"); 1113: } 1114: 1115: Perror(str) 1116: char *str; 1117: { 1118: fputs("disklabel: ", stderr); perror(str); 1119: exit(4); 1120: } 1121: 1122: usage() 1123: { 1124: fprintf(stderr, 1125: "%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n", 1126: "usage: disklabel [-r] disk", 1127: "(to read label)", 1128: "or disklabel -w [-r] disk type [ packid ]", 1129: "(to write label with existing boot program)", 1130: "or disklabel -e [-r] disk", 1131: "(to edit label)", 1132: "or disklabel -R [-r] disk protofile", 1133: "(to restore label with existing boot program)", 1134: "or disklabel -B [ -b bootprog ] disk [ type ]", 1135: "(to install boot program with existing on-disk label)", 1136: "or disklabel -w -B [ -b bootprog ] disk type [ packid ]", 1137: "(to write label and install boot program)", 1138: "or disklabel -R -B [ -b bootprog ] disk protofile [ type ]", 1139: "(to restore label and install boot program)", 1140: "or disklabel [-NW] disk", 1141: "(to write disable/enable label)"); 1142: exit(1); 1143: }