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