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) 06/04/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], (char *)NULL, &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 } 1098