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.7 (Berkeley) 06/04/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 char *dkname; 56 #ifdef BOOT 57 char *xxboot; 58 char *bootxx; 59 #endif 60 char *specname; 61 char tmpfil[] = "/tmp/EdDk.aXXXXXX"; 62 char *sprintf(); 63 64 extern int errno; 65 char namebuf[BBSIZE], *np = namebuf; 66 char bootarea[BBSIZE]; 67 struct disklabel lab; 68 struct disklabel *readlabel(), *getbootarea(); 69 70 enum { READ, WRITE, EDIT, RESTORE } op = READ; 71 72 int rflag; 73 74 main(argc, argv) 75 int argc; 76 char *argv[]; 77 { 78 extern int optind; 79 register struct disklabel *lp; 80 FILE *t; 81 int ch, f; 82 char *name = 0, *type; 83 84 while ((ch = getopt(argc, argv, "Rerw")) != EOF) 85 switch((char)ch) { 86 case 'R': 87 op = RESTORE; 88 break; 89 case 'e': 90 op = EDIT; 91 break; 92 case 'r': 93 ++rflag; 94 break; 95 case 'w': 96 op = WRITE; 97 break; 98 case '?': 99 default: 100 usage(); 101 } 102 argc -= optind; 103 argv += optind; 104 if (argc < 1) 105 usage(); 106 107 dkname = argv[0]; 108 if (dkname[0] != '/') { 109 sprintf(np, "/dev/r%s%c", dkname, RAWPARTITION); 110 specname = np; 111 np += strlen(specname) + 1; 112 } else 113 specname = dkname; 114 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 115 if (f < 0 && errno == ENOENT && dkname[0] != '/') { 116 sprintf(specname, "/dev/r%s", dkname); 117 np = namebuf + strlen(specname) + 1; 118 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 119 } 120 if (f < 0) 121 Perror(specname); 122 123 switch(op) { 124 case EDIT: 125 if (argc != 1) 126 usage(); 127 lp = readlabel(f, bootarea); 128 if (edit(lp)) 129 writelabel(f, bootarea, lp); 130 break; 131 case READ: 132 if (argc != 1) 133 usage(); 134 lp = readlabel(f, (char *)0); 135 display(stdout, lp); 136 (void) checklabel(lp); 137 break; 138 case RESTORE: 139 #ifdef BOOT 140 if (argc == 4) { 141 xxboot = argv[2]; 142 bootxx = argv[3]; 143 } 144 else 145 #else 146 if (argc != 2) 147 usage(); 148 #endif 149 lab.d_secsize = DEV_BSIZE; /* XXX */ 150 lab.d_bbsize = BBSIZE; /* XXX */ 151 lp = getbootarea(bootarea, &lab); 152 if (!(t = fopen(argv[1],"r"))) 153 Perror(argv[1]); 154 if (getasciilabel(t, lp)) 155 writelabel(f, bootarea, lp); 156 break; 157 case WRITE: 158 type = argv[1]; 159 #ifdef BOOT 160 if (argc > 5 || argc < 2) 161 usage(); 162 if (argc > 3) { 163 bootxx = argv[--argc]; 164 xxboot = argv[--argc]; 165 } 166 #else 167 if (argc > 3 || argc < 2) 168 usage(); 169 #endif 170 if (argc > 2) 171 name = argv[--argc]; 172 makelabel(type, name, &lab); 173 lp = getbootarea(bootarea, &lab); 174 *lp = lab; 175 if (checklabel(lp) == 0) 176 writelabel(f, bootarea, lp); 177 break; 178 } 179 exit(0); 180 } 181 182 makelabel(type, name, lp) 183 char *type, *name; 184 register struct disklabel *lp; 185 { 186 register struct disklabel *dp; 187 188 dp = getdiskbyname(type); 189 if (dp == NULL) { 190 fprintf(stderr, "%s: unknown disk type\n", type); 191 exit(1); 192 } 193 *lp = *dp; 194 if (name) 195 (void)strncpy(lp->d_name, name, sizeof(lp->d_name)); 196 } 197 198 writelabel(f, boot, lp) 199 int f; 200 char *boot; 201 register struct disklabel *lp; 202 { 203 register int i; 204 long lseek(); 205 206 lp->d_magic = DISKMAGIC; 207 lp->d_magic2 = DISKMAGIC; 208 lp->d_checksum = 0; 209 lp->d_checksum = dkcksum(lp); 210 (void)lseek(f, (off_t)0, L_SET); 211 if (rflag) { 212 if (write(f, boot, lp->d_bbsize) < lp->d_bbsize) 213 Perror("write"); 214 if (ioctl(f, DIOCSDINFO, lp) < 0) 215 Perror("ioctl DIOCSDINFO"); 216 } else if (ioctl(f, DIOCWDINFO, lp) < 0) 217 Perror("ioctl DIOCWDINFO"); 218 #if vax 219 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 220 daddr_t alt; 221 222 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 223 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 224 (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 225 if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 226 int oerrno = errno; 227 fprintf(stderr, "alternate label %d ", i/2); 228 errno = oerrno; 229 perror("write"); 230 } 231 } 232 } 233 #endif 234 } 235 236 /* 237 * Read disklabel from disk. 238 * If boot is given, need bootstrap too. 239 * If boot not needed, use ioctl to get label 240 * unless -r flag is given. 241 */ 242 struct disklabel * 243 readlabel(f, boot) 244 int f; 245 char *boot; 246 { 247 register struct disklabel *lp; 248 register char *buf; 249 250 if (boot) 251 buf = boot; 252 else 253 buf = bootarea; 254 lp = (struct disklabel *)(buf + LABELOFFSET); 255 if (rflag == 0 && boot == 0) { 256 if (ioctl(f, DIOCGDINFO, lp) < 0) 257 Perror("ioctl DIOCGDINFO"); 258 } else { 259 if (read(f, buf, BBSIZE) < BBSIZE) 260 Perror(specname); 261 for (lp = (struct disklabel *)buf; 262 lp <= (struct disklabel *)(buf + BBSIZE - sizeof(*lp)); 263 lp = (struct disklabel *)((char *)lp + 16)) 264 if (lp->d_magic == DISKMAGIC && 265 lp->d_magic2 == DISKMAGIC) 266 break; 267 if (lp > (struct disklabel *)(buf + BBSIZE - sizeof(*lp)) || 268 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 269 dkcksum(lp) != 0) { 270 fprintf(stderr, 271 "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 272 exit(1); 273 } 274 } 275 return (lp); 276 } 277 278 struct disklabel * 279 getbootarea(boot, dp) 280 char *boot; 281 register struct disklabel *dp; 282 { 283 struct disklabel *lp; 284 register char *p; 285 int b; 286 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)) 525 if (*cp++ == '#') 526 break; 527 if ((c = *cp) != '\0') { 528 *cp++ = '\0'; 529 if (c != '#') 530 return (skip(cp)); 531 } 532 return ((char *)NULL); 533 } 534 535 /* 536 * Read an ascii label in from fd f, 537 * in the same format as that put out by display(), 538 * and fill in lp. 539 */ 540 getasciilabel(f, lp) 541 FILE *f; 542 register struct disklabel *lp; 543 { 544 register char **cpp, *cp; 545 register struct partition *pp; 546 char *tp, *s, line[BUFSIZ]; 547 int v, lineno = 0, errors = 0; 548 549 lp->d_bbsize = BBSIZE; /* XXX */ 550 lp->d_sbsize = SBSIZE; /* XXX */ 551 while (fgets(line, sizeof(line) - 1, f)) { 552 lineno++; 553 if (cp = index(line,'\n')) 554 *cp = '\0'; 555 cp = skip(line); 556 if (cp == NULL) 557 continue; 558 tp = index(cp, ':'); 559 if (tp == NULL) { 560 fprintf(stderr, "line %d: syntax error\n", lineno); 561 errors++; 562 continue; 563 } 564 *tp++ = '\0', tp = skip(tp); 565 if (streq(cp, "type")) { 566 if (tp == NULL) 567 tp = "unknown"; 568 cpp = dktypenames; 569 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 570 if ((s = *cpp) && streq(s, tp)) { 571 lp->d_type = cpp - dktypenames; 572 goto next; 573 } 574 v = atoi(tp); 575 if ((unsigned)v >= DKMAXTYPES) 576 fprintf(stderr, "line %d:%s %d\n", lineno, 577 "Warning, unknown disk type", v); 578 lp->d_type = v; 579 continue; 580 } 581 if (streq(cp, "flags")) { 582 for (v = 0; (cp = tp) && *cp != '\0'; tp = word(cp)) { 583 if (streq(cp, "removeable")) 584 v |= D_REMOVABLE; 585 else if (streq(cp, "ecc")) 586 v |= D_ECC; 587 else if (streq(cp, "badsect")) 588 v |= D_BADSECT; 589 else { 590 fprintf(stderr, 591 "line %d: %s: bad flag\n", 592 lineno, cp); 593 errors++; 594 } 595 } 596 lp->d_flags = v; 597 continue; 598 } 599 if (streq(cp, "drivedata")) { 600 register int i; 601 602 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 603 lp->d_drivedata[i++] = atoi(cp); 604 tp = word(cp); 605 } 606 continue; 607 } 608 if (sscanf(cp, "%d partitions", &v) == 1) { 609 if (v == 0 || (unsigned)v > MAXPARTITIONS) { 610 fprintf(stderr, 611 "line %d: bad # of partitions\n", lineno); 612 lp->d_npartitions = MAXPARTITIONS; 613 errors++; 614 } else 615 lp->d_npartitions = v; 616 continue; 617 } 618 if (tp == NULL) 619 tp = ""; 620 if (streq(cp, "disk")) { 621 strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 622 continue; 623 } 624 if (streq(cp, "label")) { 625 strncpy(lp->d_name, tp, sizeof (lp->d_name)); 626 continue; 627 } 628 if (streq(cp, "bytes/sector")) { 629 v = atoi(tp); 630 if (v <= 0 || (v % 512) != 0) { 631 fprintf(stderr, 632 "line %d: %s: bad sector size\n", 633 lineno, tp); 634 errors++; 635 } else 636 lp->d_secsize = v; 637 continue; 638 } 639 if (streq(cp, "sectors/track")) { 640 v = atoi(tp); 641 if (v <= 0) { 642 fprintf(stderr, "line %d: %s: bad %s\n", 643 lineno, tp, cp); 644 errors++; 645 } else 646 lp->d_nsectors = v; 647 continue; 648 } 649 if (streq(cp, "sectors/cylinder")) { 650 v = atoi(tp); 651 if (v <= 0) { 652 fprintf(stderr, "line %d: %s: bad %s\n", 653 lineno, tp, cp); 654 errors++; 655 } else 656 lp->d_secpercyl = v; 657 continue; 658 } 659 if (streq(cp, "tracks/cylinder")) { 660 v = atoi(tp); 661 if (v <= 0) { 662 fprintf(stderr, "line %d: %s: bad %s\n", 663 lineno, tp, cp); 664 errors++; 665 } else 666 lp->d_ntracks = v; 667 continue; 668 } 669 if (streq(cp, "cylinders")) { 670 v = atoi(tp); 671 if (v <= 0) { 672 fprintf(stderr, "line %d: %s: bad %s\n", 673 lineno, tp, cp); 674 errors++; 675 } else 676 lp->d_ncylinders = v; 677 continue; 678 } 679 if (streq(cp, "rpm")) { 680 v = atoi(tp); 681 if (v <= 0) { 682 fprintf(stderr, "line %d: %s: bad %s\n", 683 lineno, tp, cp); 684 errors++; 685 } else 686 lp->d_rpm = v; 687 continue; 688 } 689 if (streq(cp, "interleave")) { 690 v = atoi(tp); 691 if (v <= 0) { 692 fprintf(stderr, "line %d: %s: bad %s\n", 693 lineno, tp, cp); 694 errors++; 695 } else 696 lp->d_interleave = v; 697 continue; 698 } 699 if (streq(cp, "trackskew")) { 700 v = atoi(tp); 701 if (v < 0) { 702 fprintf(stderr, "line %d: %s: bad %s\n", 703 lineno, tp, cp); 704 errors++; 705 } else 706 lp->d_trackskew = v; 707 continue; 708 } 709 if (streq(cp, "cylinderskew")) { 710 v = atoi(tp); 711 if (v < 0) { 712 fprintf(stderr, "line %d: %s: bad %s\n", 713 lineno, tp, cp); 714 errors++; 715 } else 716 lp->d_cylskew = v; 717 continue; 718 } 719 if (streq(cp, "headswitch")) { 720 v = atoi(tp); 721 if (v < 0) { 722 fprintf(stderr, "line %d: %s: bad %s\n", 723 lineno, tp, cp); 724 errors++; 725 } else 726 lp->d_headswitch = v; 727 continue; 728 } 729 if (streq(cp, "track-to-track seek")) { 730 v = atoi(tp); 731 if (v < 0) { 732 fprintf(stderr, "line %d: %s: bad %s\n", 733 lineno, tp, cp); 734 errors++; 735 } else 736 lp->d_trkseek = v; 737 continue; 738 } 739 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 740 unsigned part = *cp - 'a'; 741 742 if (part > lp->d_npartitions) { 743 fprintf(stderr, 744 "line %d: bad partition name\n", lineno); 745 errors++; 746 continue; 747 } 748 pp = &lp->d_partitions[part]; 749 #define NXTNUM(n) { \ 750 cp = tp, tp = word(cp); \ 751 if (tp == NULL) \ 752 tp = cp; \ 753 (n) = atoi(cp); \ 754 } 755 756 NXTNUM(v); 757 if (v < 0) { 758 fprintf(stderr, 759 "line %d: %s: bad partition size\n", 760 lineno, cp); 761 errors++; 762 } else 763 pp->p_size = v; 764 NXTNUM(v); 765 if (v < 0) { 766 fprintf(stderr, 767 "line %d: %s: bad partition offset\n", 768 lineno, cp); 769 errors++; 770 } else 771 pp->p_offset = v; 772 cp = tp, tp = word(cp); 773 cpp = fstypenames; 774 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 775 if ((s = *cpp) && streq(s, cp)) { 776 pp->p_fstype = cpp - fstypenames; 777 goto gottype; 778 } 779 v = atoi(cp); 780 if ((unsigned)v >= FSMAXTYPES) 781 fprintf(stderr, "line %d: %s %s\n", lineno, 782 "Warning, unknown filesystem type", cp); 783 pp->p_fstype = v; 784 gottype: 785 786 switch (pp->p_fstype) { 787 788 case FS_UNUSED: /* XXX */ 789 NXTNUM(pp->p_fsize); 790 if (pp->p_fsize == 0) 791 break; 792 NXTNUM(v); 793 pp->p_frag = v / pp->p_fsize; 794 break; 795 796 case FS_BSDFFS: 797 NXTNUM(pp->p_fsize); 798 if (pp->p_fsize == 0) 799 break; 800 NXTNUM(v); 801 pp->p_frag = v / pp->p_fsize; 802 NXTNUM(pp->p_cpg); 803 break; 804 805 default: 806 break; 807 } 808 continue; 809 } 810 fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 811 lineno, cp); 812 errors++; 813 next: 814 ; 815 } 816 errors += checklabel(lp); 817 return (errors == 0); 818 } 819 820 /* 821 * Check disklabel for errors and fill in 822 * derived fields according to supplied values. 823 */ 824 checklabel(lp) 825 register struct disklabel *lp; 826 { 827 register struct partition *pp; 828 int i, errors = 0; 829 char part; 830 831 if (lp->d_secsize == 0) { 832 fprintf(stderr, "sector size %d\n", lp->d_secsize); 833 return (1); 834 } 835 if (lp->d_nsectors == 0) { 836 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 837 return (1); 838 } 839 if (lp->d_ntracks == 0) { 840 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 841 return (1); 842 } 843 if (lp->d_ncylinders == 0) { 844 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 845 errors++; 846 } 847 if (lp->d_rpm == 0) 848 Warning("revolutions/minute %d\n", lp->d_rpm); 849 if (lp->d_secpercyl == 0) 850 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 851 if (lp->d_secperunit == 0) 852 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 853 if (lp->d_bbsize == 0) { 854 fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 855 errors++; 856 } else if (lp->d_bbsize % lp->d_secsize) 857 Warning("boot block size %% sector-size != 0\n"); 858 if (lp->d_sbsize == 0) { 859 fprintf(stderr, "super block size %d\n", lp->d_sbsize); 860 errors++; 861 } else if (lp->d_sbsize % lp->d_secsize) 862 Warning("super block size %% sector-size != 0\n"); 863 if (lp->d_npartitions > MAXPARTITIONS) 864 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 865 lp->d_npartitions, MAXPARTITIONS); 866 for (i = 0; i < lp->d_npartitions; i++) { 867 part = 'a' + i; 868 pp = &lp->d_partitions[i]; 869 if (pp->p_size == 0 && pp->p_offset != 0) 870 Warning("partition %c: size 0, but offset %d\n", 871 part, pp->p_offset); 872 #ifdef notdef 873 if (pp->p_size % lp->d_secpercyl) 874 Warning("partition %c: size %% cylinder-size != 0\n", 875 part); 876 if (pp->p_offset % lp->d_secpercyl) 877 Warning("partition %c: offset %% cylinder-size != 0\n", 878 part); 879 #endif 880 if (pp->p_offset > lp->d_secperunit) { 881 fprintf(stderr, 882 "partition %c: offset past end of unit\n", part); 883 errors++; 884 } 885 if (pp->p_offset + pp->p_size > lp->d_secperunit) { 886 fprintf(stderr, 887 "partition %c: partition extends past end of unit\n", 888 part); 889 errors++; 890 } 891 } 892 for (; i < MAXPARTITIONS; i++) { 893 part = 'a' + i; 894 pp = &lp->d_partitions[i]; 895 if (pp->p_size || pp->p_offset) 896 Warning("unused partition %c: size %d offset %d\n", 897 pp->p_size, pp->p_offset); 898 } 899 return (errors); 900 } 901 902 /*VARARGS1*/ 903 Warning(fmt, a1, a2, a3, a4, a5) 904 char *fmt; 905 { 906 907 fprintf(stderr, "Warning, "); 908 fprintf(stderr, fmt, a1, a2, a3, a4, a5); 909 fprintf(stderr, "\n"); 910 } 911 912 Perror(str) 913 char *str; 914 { 915 fputs("disklabel: ", stderr); perror(str); 916 exit(4); 917 } 918 919 usage() 920 { 921 #ifdef BOOT 922 fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n", 923 "usage: disklabel [-r] disk", "(to read label)", 924 "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 925 "or disklabel -e [-r] disk", "(to edit label)", 926 "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 927 #else 928 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 929 "usage: disklabel [-r] disk", "(to read label)", 930 "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 931 "or disklabel -e [-r] disk", "(to edit label)", 932 "or disklabel -R [-r] disk protofile", "(to restore label)"); 933 #endif 934 exit(1); 935 } 936