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