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.6 (Berkeley) 04/07/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, "cylinders: %d\n", lp->d_ncylinders); 363 fprintf(f, "rpm: %d\n", lp->d_rpm); 364 fprintf(f, "interleave: %d\n", lp->d_interleave); 365 fprintf(f, "trackskew: %d\n", lp->d_trackskew); 366 fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 367 fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 368 fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 369 fprintf(f, "drivedata: "); 370 for (i = NDDATA - 1; i >= 0; i--) 371 if (lp->d_drivedata[i]) 372 break; 373 if (i < 0) 374 i = 0; 375 for (j = 0; j <= i; j++) 376 fprintf(f, "%d ", lp->d_drivedata[j]); 377 fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 378 fprintf(f, 379 "# size offset fstype [fsize bsize cpg]\n"); 380 pp = lp->d_partitions; 381 for (i = 0; i < lp->d_npartitions; i++, pp++) { 382 if (pp->p_size) { 383 fprintf(f, " %c: %8d %8d ", 'a' + i, 384 pp->p_size, pp->p_offset); 385 if ((unsigned) pp->p_fstype < FSMAXTYPES) 386 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 387 else 388 fprintf(f, "%8d", pp->p_fstype); 389 switch (pp->p_fstype) { 390 391 case FS_UNUSED: /* XXX */ 392 fprintf(f, " %5d %5d %5.5s ", 393 pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 394 break; 395 396 case FS_BSDFFS: 397 fprintf(f, " %5d %5d %5d ", 398 pp->p_fsize, pp->p_fsize * pp->p_frag, 399 pp->p_cpg); 400 break; 401 402 default: 403 fprintf(f, "%20.20s", ""); 404 break; 405 } 406 fprintf(f, "\t# (Cyl. %4d", 407 pp->p_offset / lp->d_secpercyl); 408 if (pp->p_offset % lp->d_secpercyl) 409 putc('*', f); 410 else 411 putc(' ', f); 412 fprintf(f, "- %d", 413 (pp->p_offset + 414 pp->p_size + lp->d_secpercyl - 1) / 415 lp->d_secpercyl - 1); 416 if (pp->p_size % lp->d_secpercyl) 417 putc('*', f); 418 fprintf(f, ")\n"); 419 } 420 } 421 } 422 423 edit(lp) 424 struct disklabel *lp; 425 { 426 register int c; 427 struct disklabel label; 428 FILE *fd; 429 char *mktemp(); 430 431 (void) mktemp(tmpfil); 432 fd = fopen(tmpfil, "w"); 433 if (fd == NULL) { 434 fprintf(stderr, "%s: Can't create\n", tmpfil); 435 return (0); 436 } 437 (void)fchmod(fd, 0600); 438 display(fd, lp); 439 fclose(fd); 440 for (;;) { 441 if (!editit()) 442 break; 443 fd = fopen(tmpfil, "r"); 444 if (fd == NULL) { 445 fprintf(stderr, "%s: Can't reopen for reading\n"); 446 break; 447 } 448 bzero((char *)&label, sizeof(label)); 449 if (getasciilabel(fd, &label)) { 450 *lp = label; 451 (void) unlink(tmpfil); 452 return (1); 453 } 454 printf("re-edit the label? [y]: "); fflush(stdout); 455 c = getchar(); 456 if (c != EOF && c != (int)'\n') 457 while (getchar() != (int)'\n') 458 ; 459 if (c == (int)'n') 460 break; 461 } 462 (void) unlink(tmpfil); 463 return (0); 464 } 465 466 editit() 467 { 468 register int pid, xpid; 469 int stat, omask; 470 extern char *getenv(); 471 472 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 473 while ((pid = fork()) < 0) { 474 extern int errno; 475 476 if (errno == EPROCLIM) { 477 fprintf(stderr, "You have too many processes\n"); 478 return(0); 479 } 480 if (errno != EAGAIN) { 481 perror("fork"); 482 return(0); 483 } 484 sleep(1); 485 } 486 if (pid == 0) { 487 register char *ed; 488 489 sigsetmask(omask); 490 setgid(getgid()); 491 setuid(getuid()); 492 if ((ed = getenv("EDITOR")) == (char *)0) 493 ed = DEFEDITOR; 494 execlp(ed, ed, tmpfil, 0); 495 perror(ed); 496 exit(1); 497 } 498 while ((xpid = wait(&stat)) >= 0) 499 if (xpid == pid) 500 break; 501 sigsetmask(omask); 502 return(!stat); 503 } 504 505 char * 506 skip(cp) 507 register char *cp; 508 { 509 510 while (*cp != '\0' && isspace(*cp)) 511 cp++; 512 if (*cp == '\0' || *cp == '#') 513 return ((char *)NULL); 514 return (cp); 515 } 516 517 char * 518 word(cp) 519 register char *cp; 520 { 521 register char c; 522 523 while (*cp != '\0' && !isspace(*cp)) 524 if (*cp++ == '#') 525 break; 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 v = 0; 582 while ((cp = tp) && *cp != '\0') { 583 if (tp = skip(cp)) { 584 *tp++ = '\0'; 585 while (*tp && isspace(*tp)) 586 tp++; 587 } 588 if (streq(cp, "removeable")) 589 v |= D_REMOVABLE; 590 else if (streq(cp, "ecc")) 591 v |= D_ECC; 592 else if (streq(cp, "badsect")) 593 v |= D_BADSECT; 594 else { 595 fprintf(stderr, 596 "line %d: %s: bad flag\n", 597 lineno, cp); 598 errors++; 599 } 600 } 601 lp->d_flags = v; 602 continue; 603 } 604 if (streq(cp, "drivedata")) { 605 register int i; 606 607 for (i = 0;(cp = tp) && *cp != '\0' && i < NDDATA;) { 608 if (tp = skip(cp)) { 609 *tp++ = '\0'; 610 while (*tp != '\0' && isspace(*tp)) 611 tp++; 612 } 613 lp->d_drivedata[i++] = atoi(cp); 614 } 615 continue; 616 } 617 if (sscanf(cp, "%d partitions", &v) == 1) { 618 if (v == 0 || (unsigned)v > MAXPARTITIONS) { 619 fprintf(stderr, 620 "line %d: bad # of partitions\n", lineno); 621 lp->d_npartitions = MAXPARTITIONS; 622 errors++; 623 } else 624 lp->d_npartitions = v; 625 continue; 626 } 627 if (tp == NULL) 628 tp = ""; 629 if (streq(cp, "disk")) { 630 strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 631 continue; 632 } 633 if (streq(cp, "label")) { 634 strncpy(lp->d_name, tp, sizeof (lp->d_name)); 635 continue; 636 } 637 if (streq(cp, "bytes/sector")) { 638 v = atoi(tp); 639 if (v <= 0 || (v % 512) != 0) { 640 fprintf(stderr, 641 "line %d: %s: bad sector size\n", 642 lineno, tp); 643 errors++; 644 } else 645 lp->d_secsize = v; 646 continue; 647 } 648 if (streq(cp, "sectors/track")) { 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_nsectors = 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, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%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