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