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.10 (Berkeley) 09/10/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 fflush(f); 423 } 424 425 edit(lp) 426 struct disklabel *lp; 427 { 428 register int c; 429 struct disklabel label; 430 FILE *fd; 431 char *mktemp(); 432 433 (void) mktemp(tmpfil); 434 fd = fopen(tmpfil, "w"); 435 if (fd == NULL) { 436 fprintf(stderr, "%s: Can't create\n", tmpfil); 437 return (0); 438 } 439 (void)fchmod(fd, 0600); 440 display(fd, lp); 441 fclose(fd); 442 for (;;) { 443 if (!editit()) 444 break; 445 fd = fopen(tmpfil, "r"); 446 if (fd == NULL) { 447 fprintf(stderr, "%s: Can't reopen for reading\n"); 448 break; 449 } 450 bzero((char *)&label, sizeof(label)); 451 if (getasciilabel(fd, &label)) { 452 *lp = label; 453 (void) unlink(tmpfil); 454 return (1); 455 } 456 printf("re-edit the label? [y]: "); fflush(stdout); 457 c = getchar(); 458 if (c != EOF && c != (int)'\n') 459 while (getchar() != (int)'\n') 460 ; 461 if (c == (int)'n') 462 break; 463 } 464 (void) unlink(tmpfil); 465 return (0); 466 } 467 468 editit() 469 { 470 register int pid, xpid; 471 int stat, omask; 472 extern char *getenv(); 473 474 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 475 while ((pid = fork()) < 0) { 476 extern int errno; 477 478 if (errno == EPROCLIM) { 479 fprintf(stderr, "You have too many processes\n"); 480 return(0); 481 } 482 if (errno != EAGAIN) { 483 perror("fork"); 484 return(0); 485 } 486 sleep(1); 487 } 488 if (pid == 0) { 489 register char *ed; 490 491 sigsetmask(omask); 492 setgid(getgid()); 493 setuid(getuid()); 494 if ((ed = getenv("EDITOR")) == (char *)0) 495 ed = DEFEDITOR; 496 execlp(ed, ed, tmpfil, 0); 497 perror(ed); 498 exit(1); 499 } 500 while ((xpid = wait(&stat)) >= 0) 501 if (xpid == pid) 502 break; 503 sigsetmask(omask); 504 return(!stat); 505 } 506 507 char * 508 skip(cp) 509 register char *cp; 510 { 511 512 while (*cp != '\0' && isspace(*cp)) 513 cp++; 514 if (*cp == '\0' || *cp == '#') 515 return ((char *)NULL); 516 return (cp); 517 } 518 519 char * 520 word(cp) 521 register char *cp; 522 { 523 register char c; 524 525 while (*cp != '\0' && !isspace(*cp) && *cp != '#') 526 cp++; 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, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%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