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.9 (Berkeley) 06/19/87"; 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 char *sprintf(); 64 65 extern int errno; 66 char namebuf[BBSIZE], *np = namebuf; 67 struct disklabel lab; 68 struct disklabel *readlabel(), *makebootarea(); 69 char bootarea[BBSIZE]; 70 71 enum { READ, WRITE, EDIT, RESTORE } op = READ; 72 73 int rflag; 74 75 main(argc, argv) 76 int argc; 77 char *argv[]; 78 { 79 extern int optind; 80 register struct disklabel *lp; 81 FILE *t; 82 int ch, f; 83 char *name = 0, *type; 84 85 while ((ch = getopt(argc, argv, "Rerw")) != EOF) 86 switch((char)ch) { 87 case 'R': 88 op = RESTORE; 89 break; 90 case 'e': 91 op = EDIT; 92 break; 93 case 'r': 94 ++rflag; 95 break; 96 case 'w': 97 op = WRITE; 98 break; 99 case '?': 100 default: 101 usage(); 102 } 103 argc -= optind; 104 argv += optind; 105 if (argc < 1) 106 usage(); 107 108 dkname = argv[0]; 109 if (dkname[0] != '/') { 110 sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION); 111 specname = np; 112 np += strlen(specname) + 1; 113 } else 114 specname = dkname; 115 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 116 if (f < 0 && errno == ENOENT && dkname[0] != '/') { 117 sprintf(specname, "/dev/r%s", dkname); 118 np = namebuf + strlen(specname) + 1; 119 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 120 } 121 if (f < 0) 122 Perror(specname); 123 124 switch(op) { 125 case EDIT: 126 if (argc != 1) 127 usage(); 128 lp = readlabel(f, rflag); 129 if (edit(lp)) 130 writelabel(f, bootarea, lp); 131 break; 132 case READ: 133 if (argc != 1) 134 usage(); 135 lp = readlabel(f, 0); 136 display(stdout, lp); 137 (void) checklabel(lp); 138 break; 139 case RESTORE: 140 #ifdef BOOT 141 if (argc == 4) { 142 xxboot = argv[2]; 143 bootxx = argv[3]; 144 } else 145 #endif 146 if (argc != 2) 147 usage(); 148 lab.d_secsize = DEV_BSIZE; /* XXX */ 149 lab.d_bbsize = BBSIZE; /* XXX */ 150 lp = makebootarea(bootarea, &lab); 151 if (!(t = fopen(argv[1],"r"))) 152 Perror(argv[1]); 153 #ifdef BOOT 154 rflag = 1; /* force bootstrap to be written */ 155 #endif 156 if (getasciilabel(t, lp)) 157 writelabel(f, bootarea, lp); 158 break; 159 case WRITE: 160 type = argv[1]; 161 #ifdef BOOT 162 if (argc > 5 || argc < 2) 163 usage(); 164 if (argc > 3) { 165 bootxx = argv[--argc]; 166 xxboot = argv[--argc]; 167 } 168 #else 169 if (argc > 3 || argc < 2) 170 usage(); 171 #endif 172 if (argc > 2) 173 name = argv[--argc]; 174 makelabel(type, name, &lab); 175 lp = makebootarea(bootarea, &lab); 176 *lp = lab; 177 #ifdef BOOT 178 rflag = 1; /* force bootstrap to be written */ 179 #endif 180 if (checklabel(lp) == 0) 181 writelabel(f, bootarea, lp); 182 break; 183 } 184 exit(0); 185 } 186 187 makelabel(type, name, lp) 188 char *type, *name; 189 register struct disklabel *lp; 190 { 191 register struct disklabel *dp; 192 193 dp = getdiskbyname(type); 194 if (dp == NULL) { 195 fprintf(stderr, "%s: unknown disk type\n", type); 196 exit(1); 197 } 198 *lp = *dp; 199 if (name) 200 (void)strncpy(lp->d_name, name, sizeof(lp->d_name)); 201 } 202 203 writelabel(f, boot, lp) 204 int f; 205 char *boot; 206 register struct disklabel *lp; 207 { 208 register int i; 209 long lseek(); 210 211 lp->d_magic = DISKMAGIC; 212 lp->d_magic2 = DISKMAGIC; 213 lp->d_checksum = 0; 214 lp->d_checksum = dkcksum(lp); 215 if (rflag) { 216 (void)lseek(f, (off_t)0, L_SET); 217 if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 218 Perror("write"); 219 if (ioctl(f, DIOCSDINFO, lp) < 0) 220 Perror("ioctl DIOCSDINFO"); 221 } else if (ioctl(f, DIOCWDINFO, lp) < 0) 222 Perror("ioctl DIOCWDINFO"); 223 #if vax 224 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 225 daddr_t alt; 226 227 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 228 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 229 (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 230 if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 231 int oerrno = errno; 232 fprintf(stderr, "alternate label %d ", i/2); 233 errno = oerrno; 234 perror("write"); 235 } 236 } 237 } 238 #endif 239 } 240 241 /* 242 * Fetch disklabel for disk. 243 * If needboot is given, need bootstrap too. 244 * Use ioctl to get label unless -r flag is given. 245 */ 246 struct disklabel * 247 readlabel(f, needboot) 248 int f, needboot; 249 { 250 register struct disklabel *lp; 251 252 if (needboot || rflag) { 253 lp = (struct disklabel *)(bootarea + LABELOFFSET); 254 if (read(f, bootarea, BBSIZE) < BBSIZE) 255 Perror(specname); 256 } else 257 lp = &lab; 258 if (rflag == 0) { 259 if (ioctl(f, DIOCGDINFO, lp) < 0) 260 Perror("ioctl DIOCGDINFO"); 261 } else { 262 for (lp = (struct disklabel *)bootarea; 263 lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 264 lp = (struct disklabel *)((char *)lp + 16)) 265 if (lp->d_magic == DISKMAGIC && 266 lp->d_magic2 == DISKMAGIC) 267 break; 268 if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 269 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 270 dkcksum(lp) != 0) { 271 fprintf(stderr, 272 "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 273 exit(1); 274 } 275 } 276 return (lp); 277 } 278 279 struct disklabel * 280 makebootarea(boot, dp) 281 char *boot; 282 register struct disklabel *dp; 283 { 284 struct disklabel *lp; 285 register char *p; 286 int b; 287 #ifdef BOOT 288 char *dkbasename; 289 290 if (xxboot == NULL) { 291 dkbasename = np; 292 if ((p = rindex(dkname, '/')) == NULL) 293 p = dkname; 294 else 295 p++; 296 while (*p && !isdigit(*p)) 297 *np++ = *p++; 298 *np++ = '\0'; 299 300 sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 301 if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 302 dkbasename++; 303 xxboot = np; 304 sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 305 np += strlen(xxboot) + 1; 306 307 bootxx = np; 308 sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 309 np += strlen(bootxx) + 1; 310 } 311 312 b = open(xxboot, O_RDONLY); 313 if (b < 0) 314 Perror(xxboot); 315 if (read(b, boot, (int)dp->d_secsize) < 0) 316 Perror(xxboot); 317 close(b); 318 b = open(bootxx, O_RDONLY); 319 if (b < 0) 320 Perror(bootxx); 321 if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 322 Perror(bootxx); 323 (void)close(b); 324 #endif 325 326 lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 327 LABELOFFSET); 328 for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 329 if (*p) { 330 fprintf(stderr, 331 "Bootstrap doesn't leave room for disk label\n"); 332 exit(2); 333 } 334 return (lp); 335 } 336 337 display(f, lp) 338 FILE *f; 339 register struct disklabel *lp; 340 { 341 register int i, j; 342 register struct partition *pp; 343 344 fprintf(f, "# %s:\n", specname); 345 if ((unsigned) lp->d_type < DKMAXTYPES) 346 fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 347 else 348 fprintf(f, "type: %d\n", lp->d_type); 349 fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 350 fprintf(f, "label: %.*s\n", sizeof(lp->d_name), lp->d_name); 351 fprintf(f, "flags:"); 352 if (lp->d_flags & D_REMOVABLE) 353 fprintf(f, " removeable"); 354 if (lp->d_flags & D_ECC) 355 fprintf(f, " ecc"); 356 if (lp->d_flags & D_BADSECT) 357 fprintf(f, " badsect"); 358 fprintf(f, "\n"); 359 fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 360 fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 361 fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 362 fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 363 fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 364 fprintf(f, "rpm: %d\n", lp->d_rpm); 365 fprintf(f, "interleave: %d\n", lp->d_interleave); 366 fprintf(f, "trackskew: %d\n", lp->d_trackskew); 367 fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 368 fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 369 fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 370 fprintf(f, "drivedata: "); 371 for (i = NDDATA - 1; i >= 0; i--) 372 if (lp->d_drivedata[i]) 373 break; 374 if (i < 0) 375 i = 0; 376 for (j = 0; j <= i; j++) 377 fprintf(f, "%d ", lp->d_drivedata[j]); 378 fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 379 fprintf(f, 380 "# size offset fstype [fsize bsize cpg]\n"); 381 pp = lp->d_partitions; 382 for (i = 0; i < lp->d_npartitions; i++, pp++) { 383 if (pp->p_size) { 384 fprintf(f, " %c: %8d %8d ", 'a' + i, 385 pp->p_size, pp->p_offset); 386 if ((unsigned) pp->p_fstype < FSMAXTYPES) 387 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 388 else 389 fprintf(f, "%8d", pp->p_fstype); 390 switch (pp->p_fstype) { 391 392 case FS_UNUSED: /* XXX */ 393 fprintf(f, " %5d %5d %5.5s ", 394 pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 395 break; 396 397 case FS_BSDFFS: 398 fprintf(f, " %5d %5d %5d ", 399 pp->p_fsize, pp->p_fsize * pp->p_frag, 400 pp->p_cpg); 401 break; 402 403 default: 404 fprintf(f, "%20.20s", ""); 405 break; 406 } 407 fprintf(f, "\t# (Cyl. %4d", 408 pp->p_offset / lp->d_secpercyl); 409 if (pp->p_offset % lp->d_secpercyl) 410 putc('*', f); 411 else 412 putc(' ', f); 413 fprintf(f, "- %d", 414 (pp->p_offset + 415 pp->p_size + lp->d_secpercyl - 1) / 416 lp->d_secpercyl - 1); 417 if (pp->p_size % lp->d_secpercyl) 418 putc('*', f); 419 fprintf(f, ")\n"); 420 } 421 } 422 } 423 424 edit(lp) 425 struct disklabel *lp; 426 { 427 register int c; 428 struct disklabel label; 429 FILE *fd; 430 char *mktemp(); 431 432 (void) mktemp(tmpfil); 433 fd = fopen(tmpfil, "w"); 434 if (fd == NULL) { 435 fprintf(stderr, "%s: Can't create\n", tmpfil); 436 return (0); 437 } 438 (void)fchmod(fd, 0600); 439 display(fd, lp); 440 fclose(fd); 441 for (;;) { 442 if (!editit()) 443 break; 444 fd = fopen(tmpfil, "r"); 445 if (fd == NULL) { 446 fprintf(stderr, "%s: Can't reopen for reading\n"); 447 break; 448 } 449 bzero((char *)&label, sizeof(label)); 450 if (getasciilabel(fd, &label)) { 451 *lp = label; 452 (void) unlink(tmpfil); 453 return (1); 454 } 455 printf("re-edit the label? [y]: "); fflush(stdout); 456 c = getchar(); 457 if (c != EOF && c != (int)'\n') 458 while (getchar() != (int)'\n') 459 ; 460 if (c == (int)'n') 461 break; 462 } 463 (void) unlink(tmpfil); 464 return (0); 465 } 466 467 editit() 468 { 469 register int pid, xpid; 470 int stat, omask; 471 extern char *getenv(); 472 473 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 474 while ((pid = fork()) < 0) { 475 extern int errno; 476 477 if (errno == EPROCLIM) { 478 fprintf(stderr, "You have too many processes\n"); 479 return(0); 480 } 481 if (errno != EAGAIN) { 482 perror("fork"); 483 return(0); 484 } 485 sleep(1); 486 } 487 if (pid == 0) { 488 register char *ed; 489 490 sigsetmask(omask); 491 setgid(getgid()); 492 setuid(getuid()); 493 if ((ed = getenv("EDITOR")) == (char *)0) 494 ed = DEFEDITOR; 495 execlp(ed, ed, tmpfil, 0); 496 perror(ed); 497 exit(1); 498 } 499 while ((xpid = wait(&stat)) >= 0) 500 if (xpid == pid) 501 break; 502 sigsetmask(omask); 503 return(!stat); 504 } 505 506 char * 507 skip(cp) 508 register char *cp; 509 { 510 511 while (*cp != '\0' && isspace(*cp)) 512 cp++; 513 if (*cp == '\0' || *cp == '#') 514 return ((char *)NULL); 515 return (cp); 516 } 517 518 char * 519 word(cp) 520 register char *cp; 521 { 522 register char c; 523 524 while (*cp != '\0' && !isspace(*cp) && *cp != '#') 525 cp++; 526 if ((c = *cp) != '\0') { 527 *cp++ = '\0'; 528 if (c != '#') 529 return (skip(cp)); 530 } 531 return ((char *)NULL); 532 } 533 534 /* 535 * Read an ascii label in from fd f, 536 * in the same format as that put out by display(), 537 * and fill in lp. 538 */ 539 getasciilabel(f, lp) 540 FILE *f; 541 register struct disklabel *lp; 542 { 543 register char **cpp, *cp; 544 register struct partition *pp; 545 char *tp, *s, line[BUFSIZ]; 546 int v, lineno = 0, errors = 0; 547 548 lp->d_bbsize = BBSIZE; /* XXX */ 549 lp->d_sbsize = SBSIZE; /* XXX */ 550 while (fgets(line, sizeof(line) - 1, f)) { 551 lineno++; 552 if (cp = index(line,'\n')) 553 *cp = '\0'; 554 cp = skip(line); 555 if (cp == NULL) 556 continue; 557 tp = index(cp, ':'); 558 if (tp == NULL) { 559 fprintf(stderr, "line %d: syntax error\n", lineno); 560 errors++; 561 continue; 562 } 563 *tp++ = '\0', tp = skip(tp); 564 if (streq(cp, "type")) { 565 if (tp == NULL) 566 tp = "unknown"; 567 cpp = dktypenames; 568 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 569 if ((s = *cpp) && streq(s, tp)) { 570 lp->d_type = cpp - dktypenames; 571 goto next; 572 } 573 v = atoi(tp); 574 if ((unsigned)v >= DKMAXTYPES) 575 fprintf(stderr, "line %d:%s %d\n", lineno, 576 "Warning, unknown disk type", v); 577 lp->d_type = v; 578 continue; 579 } 580 if (streq(cp, "flags")) { 581 for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) { 582 if (streq(cp, "removeable")) 583 v |= D_REMOVABLE; 584 else if (streq(cp, "ecc")) 585 v |= D_ECC; 586 else if (streq(cp, "badsect")) 587 v |= D_BADSECT; 588 else { 589 fprintf(stderr, 590 "line %d: %s: bad flag\n", 591 lineno, cp); 592 errors++; 593 } 594 } 595 lp->d_flags = v; 596 continue; 597 } 598 if (streq(cp, "drivedata")) { 599 register int i; 600 601 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 602 lp->d_drivedata[i++] = atoi(cp); 603 tp = word(cp); 604 } 605 continue; 606 } 607 if (sscanf(cp, "%d partitions", &v) == 1) { 608 if (v == 0 || (unsigned)v > MAXPARTITIONS) { 609 fprintf(stderr, 610 "line %d: bad # of partitions\n", lineno); 611 lp->d_npartitions = MAXPARTITIONS; 612 errors++; 613 } else 614 lp->d_npartitions = v; 615 continue; 616 } 617 if (tp == NULL) 618 tp = ""; 619 if (streq(cp, "disk")) { 620 strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 621 continue; 622 } 623 if (streq(cp, "label")) { 624 strncpy(lp->d_name, tp, sizeof (lp->d_name)); 625 continue; 626 } 627 if (streq(cp, "bytes/sector")) { 628 v = atoi(tp); 629 if (v <= 0 || (v % 512) != 0) { 630 fprintf(stderr, 631 "line %d: %s: bad sector size\n", 632 lineno, tp); 633 errors++; 634 } else 635 lp->d_secsize = v; 636 continue; 637 } 638 if (streq(cp, "sectors/track")) { 639 v = atoi(tp); 640 if (v <= 0) { 641 fprintf(stderr, "line %d: %s: bad %s\n", 642 lineno, tp, cp); 643 errors++; 644 } else 645 lp->d_nsectors = v; 646 continue; 647 } 648 if (streq(cp, "sectors/cylinder")) { 649 v = atoi(tp); 650 if (v <= 0) { 651 fprintf(stderr, "line %d: %s: bad %s\n", 652 lineno, tp, cp); 653 errors++; 654 } else 655 lp->d_secpercyl = v; 656 continue; 657 } 658 if (streq(cp, "tracks/cylinder")) { 659 v = atoi(tp); 660 if (v <= 0) { 661 fprintf(stderr, "line %d: %s: bad %s\n", 662 lineno, tp, cp); 663 errors++; 664 } else 665 lp->d_ntracks = v; 666 continue; 667 } 668 if (streq(cp, "cylinders")) { 669 v = atoi(tp); 670 if (v <= 0) { 671 fprintf(stderr, "line %d: %s: bad %s\n", 672 lineno, tp, cp); 673 errors++; 674 } else 675 lp->d_ncylinders = v; 676 continue; 677 } 678 if (streq(cp, "rpm")) { 679 v = atoi(tp); 680 if (v <= 0) { 681 fprintf(stderr, "line %d: %s: bad %s\n", 682 lineno, tp, cp); 683 errors++; 684 } else 685 lp->d_rpm = v; 686 continue; 687 } 688 if (streq(cp, "interleave")) { 689 v = atoi(tp); 690 if (v <= 0) { 691 fprintf(stderr, "line %d: %s: bad %s\n", 692 lineno, tp, cp); 693 errors++; 694 } else 695 lp->d_interleave = v; 696 continue; 697 } 698 if (streq(cp, "trackskew")) { 699 v = atoi(tp); 700 if (v < 0) { 701 fprintf(stderr, "line %d: %s: bad %s\n", 702 lineno, tp, cp); 703 errors++; 704 } else 705 lp->d_trackskew = v; 706 continue; 707 } 708 if (streq(cp, "cylinderskew")) { 709 v = atoi(tp); 710 if (v < 0) { 711 fprintf(stderr, "line %d: %s: bad %s\n", 712 lineno, tp, cp); 713 errors++; 714 } else 715 lp->d_cylskew = v; 716 continue; 717 } 718 if (streq(cp, "headswitch")) { 719 v = atoi(tp); 720 if (v < 0) { 721 fprintf(stderr, "line %d: %s: bad %s\n", 722 lineno, tp, cp); 723 errors++; 724 } else 725 lp->d_headswitch = v; 726 continue; 727 } 728 if (streq(cp, "track-to-track seek")) { 729 v = atoi(tp); 730 if (v < 0) { 731 fprintf(stderr, "line %d: %s: bad %s\n", 732 lineno, tp, cp); 733 errors++; 734 } else 735 lp->d_trkseek = v; 736 continue; 737 } 738 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 739 unsigned part = *cp - 'a'; 740 741 if (part > lp->d_npartitions) { 742 fprintf(stderr, 743 "line %d: bad partition name\n", lineno); 744 errors++; 745 continue; 746 } 747 pp = &lp->d_partitions[part]; 748 #define NXTNUM(n) { \ 749 cp = tp, tp = word(cp); \ 750 if (tp == NULL) \ 751 tp = cp; \ 752 (n) = atoi(cp); \ 753 } 754 755 NXTNUM(v); 756 if (v < 0) { 757 fprintf(stderr, 758 "line %d: %s: bad partition size\n", 759 lineno, cp); 760 errors++; 761 } else 762 pp->p_size = v; 763 NXTNUM(v); 764 if (v < 0) { 765 fprintf(stderr, 766 "line %d: %s: bad partition offset\n", 767 lineno, cp); 768 errors++; 769 } else 770 pp->p_offset = v; 771 cp = tp, tp = word(cp); 772 cpp = fstypenames; 773 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 774 if ((s = *cpp) && streq(s, cp)) { 775 pp->p_fstype = cpp - fstypenames; 776 goto gottype; 777 } 778 v = atoi(cp); 779 if ((unsigned)v >= FSMAXTYPES) 780 fprintf(stderr, "line %d: %s %s\n", lineno, 781 "Warning, unknown filesystem type", cp); 782 pp->p_fstype = v; 783 gottype: 784 785 switch (pp->p_fstype) { 786 787 case FS_UNUSED: /* XXX */ 788 NXTNUM(pp->p_fsize); 789 if (pp->p_fsize == 0) 790 break; 791 NXTNUM(v); 792 pp->p_frag = v / pp->p_fsize; 793 break; 794 795 case FS_BSDFFS: 796 NXTNUM(pp->p_fsize); 797 if (pp->p_fsize == 0) 798 break; 799 NXTNUM(v); 800 pp->p_frag = v / pp->p_fsize; 801 NXTNUM(pp->p_cpg); 802 break; 803 804 default: 805 break; 806 } 807 continue; 808 } 809 fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 810 lineno, cp); 811 errors++; 812 next: 813 ; 814 } 815 errors += checklabel(lp); 816 return (errors == 0); 817 } 818 819 /* 820 * Check disklabel for errors and fill in 821 * derived fields according to supplied values. 822 */ 823 checklabel(lp) 824 register struct disklabel *lp; 825 { 826 register struct partition *pp; 827 int i, errors = 0; 828 char part; 829 830 if (lp->d_secsize == 0) { 831 fprintf(stderr, "sector size %d\n", lp->d_secsize); 832 return (1); 833 } 834 if (lp->d_nsectors == 0) { 835 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 836 return (1); 837 } 838 if (lp->d_ntracks == 0) { 839 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 840 return (1); 841 } 842 if (lp->d_ncylinders == 0) { 843 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 844 errors++; 845 } 846 if (lp->d_rpm == 0) 847 Warning("revolutions/minute %d\n", lp->d_rpm); 848 if (lp->d_secpercyl == 0) 849 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 850 if (lp->d_secperunit == 0) 851 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 852 if (lp->d_bbsize == 0) { 853 fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 854 errors++; 855 } else if (lp->d_bbsize % lp->d_secsize) 856 Warning("boot block size %% sector-size != 0\n"); 857 if (lp->d_sbsize == 0) { 858 fprintf(stderr, "super block size %d\n", lp->d_sbsize); 859 errors++; 860 } else if (lp->d_sbsize % lp->d_secsize) 861 Warning("super block size %% sector-size != 0\n"); 862 if (lp->d_npartitions > MAXPARTITIONS) 863 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 864 lp->d_npartitions, MAXPARTITIONS); 865 for (i = 0; i < lp->d_npartitions; i++) { 866 part = 'a' + i; 867 pp = &lp->d_partitions[i]; 868 if (pp->p_size == 0 && pp->p_offset != 0) 869 Warning("partition %c: size 0, but offset %d\n", 870 part, pp->p_offset); 871 #ifdef notdef 872 if (pp->p_size % lp->d_secpercyl) 873 Warning("partition %c: size %% cylinder-size != 0\n", 874 part); 875 if (pp->p_offset % lp->d_secpercyl) 876 Warning("partition %c: offset %% cylinder-size != 0\n", 877 part); 878 #endif 879 if (pp->p_offset > lp->d_secperunit) { 880 fprintf(stderr, 881 "partition %c: offset past end of unit\n", part); 882 errors++; 883 } 884 if (pp->p_offset + pp->p_size > lp->d_secperunit) { 885 fprintf(stderr, 886 "partition %c: partition extends past end of unit\n", 887 part); 888 errors++; 889 } 890 } 891 for (; i < MAXPARTITIONS; i++) { 892 part = 'a' + i; 893 pp = &lp->d_partitions[i]; 894 if (pp->p_size || pp->p_offset) 895 Warning("unused partition %c: size %d offset %d\n", 896 pp->p_size, pp->p_offset); 897 } 898 return (errors); 899 } 900 901 /*VARARGS1*/ 902 Warning(fmt, a1, a2, a3, a4, a5) 903 char *fmt; 904 { 905 906 fprintf(stderr, "Warning, "); 907 fprintf(stderr, fmt, a1, a2, a3, a4, a5); 908 fprintf(stderr, "\n"); 909 } 910 911 Perror(str) 912 char *str; 913 { 914 fputs("disklabel: ", stderr); perror(str); 915 exit(4); 916 } 917 918 usage() 919 { 920 #ifdef BOOT 921 fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n", 922 "usage: disklabel [-r] disk", "(to read label)", 923 "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 924 "or disklabel -e [-r] disk", "(to edit label)", 925 "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 926 #else 927 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 928 "usage: disklabel [-r] disk", "(to read label)", 929 "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 930 "or disklabel -e [-r] disk", "(to edit label)", 931 "or disklabel -R [-r] disk protofile", "(to restore label)"); 932 #endif 933 exit(1); 934 } 935