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.5 (Berkeley) 04/01/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, "#\t size offset fstype\n"); 379 pp = lp->d_partitions; 380 for (i = 0; i < lp->d_npartitions; i++, pp++) { 381 fprintf(f, "\t%c: %8d %8d ", 'a' + i, 382 pp->p_size, pp->p_offset); 383 if (pp->p_size) { 384 if ((unsigned) pp->p_fstype < FSMAXTYPES) 385 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 386 else 387 fprintf(f, "%8d", pp->p_fstype); 388 fprintf(f, "\t# (Cyl. %4d", 389 pp->p_offset / lp->d_secpercyl); 390 if (pp->p_offset % lp->d_secpercyl) 391 putc('*', f); 392 else 393 putc(' ', f); 394 fprintf(f, "- %d", 395 (pp->p_offset + 396 pp->p_size + lp->d_secpercyl - 1) / 397 lp->d_secpercyl - 1); 398 if (pp->p_size % lp->d_secpercyl) 399 putc('*', f); 400 putc(')', f); 401 } 402 fprintf(f, "\n"); 403 } 404 } 405 406 edit(lp) 407 struct disklabel *lp; 408 { 409 register int c; 410 struct disklabel label; 411 FILE *fd; 412 char *mktemp(); 413 414 (void) mktemp(tmpfil); 415 fd = fopen(tmpfil, "w"); 416 if (fd == NULL) { 417 fprintf(stderr, "%s: Can't create\n", tmpfil); 418 return (0); 419 } 420 (void)fchmod(fd, 0600); 421 display(fd, lp); 422 fclose(fd); 423 for (;;) { 424 if (!editit()) 425 break; 426 fd = fopen(tmpfil, "r"); 427 if (fd == NULL) { 428 fprintf(stderr, "%s: Can't reopen for reading\n"); 429 break; 430 } 431 label = *lp; 432 if (getasciilabel(fd, &label)) { 433 *lp = label; 434 (void) unlink(tmpfil); 435 return (1); 436 } 437 printf("re-edit the label? [y]: "); fflush(stdout); 438 c = getchar(); 439 if (c != EOF && c != (int)'\n') 440 while (getchar() != (int)'\n') 441 ; 442 if (c == (int)'n') 443 break; 444 } 445 (void) unlink(tmpfil); 446 return (0); 447 } 448 449 editit() 450 { 451 register int pid, xpid; 452 int stat, omask; 453 extern char *getenv(); 454 455 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 456 while ((pid = fork()) < 0) { 457 extern int errno; 458 459 if (errno == EPROCLIM) { 460 fprintf(stderr, "You have too many processes\n"); 461 return(0); 462 } 463 if (errno != EAGAIN) { 464 perror("fork"); 465 return(0); 466 } 467 sleep(1); 468 } 469 if (pid == 0) { 470 register char *ed; 471 472 sigsetmask(omask); 473 setgid(getgid()); 474 setuid(getuid()); 475 if ((ed = getenv("EDITOR")) == (char *)0) 476 ed = DEFEDITOR; 477 execlp(ed, ed, tmpfil, 0); 478 perror(ed); 479 exit(1); 480 } 481 while ((xpid = wait(&stat)) >= 0) 482 if (xpid == pid) 483 break; 484 sigsetmask(omask); 485 return(!stat); 486 } 487 488 char * 489 skip(cp) 490 register char *cp; 491 { 492 493 while (*cp != '\0' && isspace(*cp)) 494 cp++; 495 if (*cp == '\0' || *cp == '#') 496 return ((char *)NULL); 497 return (cp); 498 } 499 500 char * 501 word(cp) 502 register char *cp; 503 { 504 register char c; 505 506 while (*cp != '\0' && !isspace(*cp)) 507 if (*cp++ == '#') 508 break; 509 if ((c = *cp) != '\0') { 510 *cp++ = '\0'; 511 if (c != '#') 512 return (skip(cp)); 513 } 514 return ((char *)NULL); 515 } 516 517 /* 518 * Read an ascii label in from fd f, 519 * in the same format as that put out by display(), 520 * and fill in lp. 521 */ 522 getasciilabel(f, lp) 523 FILE *f; 524 register struct disklabel *lp; 525 { 526 register char **cpp, *cp; 527 char *tp, *s, line[BUFSIZ]; 528 int v, lineno = 0, errors = 0; 529 530 lp->d_bbsize = BBSIZE; /* XXX */ 531 lp->d_sbsize = SBSIZE; /* XXX */ 532 while (fgets(line, sizeof(line) - 1, f)) { 533 lineno++; 534 if (cp = index(line,'\n')) 535 *cp = '\0'; 536 cp = skip(line); 537 if (cp == NULL) 538 continue; 539 tp = index(cp, ':'); 540 if (tp == NULL) { 541 fprintf(stderr, "line %d: syntax error\n", lineno); 542 errors++; 543 continue; 544 } 545 *tp++ = '\0', tp = skip(tp); 546 if (streq(cp, "type")) { 547 if (tp == NULL) 548 tp = "unknown"; 549 cpp = dktypenames; 550 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 551 if ((s = *cpp) && streq(s, tp)) { 552 lp->d_type = cpp - dktypenames; 553 goto next; 554 } 555 v = atoi(tp); 556 if ((unsigned)v >= DKMAXTYPES) 557 fprintf(stderr, "line %d:%s %d\n", lineno, 558 "Warning, unknown disk type", v); 559 lp->d_type = v; 560 continue; 561 } 562 if (streq(cp, "flags")) { 563 v = 0; 564 while ((cp = tp) && *cp != '\0') { 565 if (tp = skip(cp)) { 566 *tp++ = '\0'; 567 while (*tp && isspace(*tp)) 568 tp++; 569 } 570 if (streq(cp, "removeable")) 571 v |= D_REMOVABLE; 572 else if (streq(cp, "ecc")) 573 v |= D_ECC; 574 else if (streq(cp, "badsect")) 575 v |= D_BADSECT; 576 else { 577 fprintf(stderr, 578 "line %d: %s: bad flag\n", 579 lineno, cp); 580 errors++; 581 } 582 } 583 lp->d_flags = v; 584 continue; 585 } 586 if (streq(cp, "drivedata")) { 587 register int i; 588 589 for (i = 0;(cp = tp) && *cp != '\0' && i < NDDATA;) { 590 if (tp = skip(cp)) { 591 *tp++ = '\0'; 592 while (*tp != '\0' && isspace(*tp)) 593 tp++; 594 } 595 lp->d_drivedata[i++] = atoi(cp); 596 } 597 continue; 598 } 599 if (sscanf(cp, "%d partitions", &v) == 1) { 600 if (v == 0 || (unsigned)v > MAXPARTITIONS) 601 fprintf(stderr, 602 "line %d: bad # of partitions\n", lineno); 603 else 604 lp->d_npartitions = v; 605 continue; 606 } 607 if (tp == NULL) 608 tp = ""; 609 if (streq(cp, "disk")) { 610 strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 611 continue; 612 } 613 if (streq(cp, "label")) { 614 strncpy(lp->d_name, tp, sizeof (lp->d_name)); 615 continue; 616 } 617 if (streq(cp, "bytes/sector")) { 618 v = atoi(tp); 619 if (v <= 0 || (v % 512) != 0) { 620 fprintf(stderr, 621 "line %d: %s: bad sector size\n", 622 lineno, tp); 623 errors++; 624 } else 625 lp->d_secsize = v; 626 continue; 627 } 628 if (streq(cp, "sectors/track")) { 629 v = atoi(tp); 630 if (v <= 0) { 631 fprintf(stderr, "line %d: %s: bad %s\n", 632 lineno, tp, cp); 633 errors++; 634 } else 635 lp->d_nsectors = v; 636 continue; 637 } 638 if (streq(cp, "tracks/cylinder")) { 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_ntracks = v; 646 continue; 647 } 648 if (streq(cp, "cylinders")) { 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_ncylinders = v; 656 continue; 657 } 658 if (streq(cp, "rpm")) { 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_rpm = v; 666 continue; 667 } 668 if (streq(cp, "interleave")) { 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_interleave = v; 676 continue; 677 } 678 if (streq(cp, "trackskew")) { 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_trackskew = v; 686 continue; 687 } 688 if (streq(cp, "cylinderskew")) { 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_cylskew = v; 696 continue; 697 } 698 if (streq(cp, "headswitch")) { 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_headswitch = v; 706 continue; 707 } 708 if (streq(cp, "track-to-track seek")) { 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_trkseek = v; 716 continue; 717 } 718 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 719 int part = *cp - 'a'; 720 721 if ((unsigned)part > MAXPARTITIONS) { 722 fprintf(stderr, 723 "line %d: bad partition name\n", lineno); 724 errors++; 725 continue; 726 } 727 cp = tp, tp = word(cp); 728 if (tp == NULL) 729 tp = cp; 730 v = atoi(cp); 731 if (v < 0) { 732 fprintf(stderr, 733 "line %d: %s: bad partition size\n", 734 lineno, cp); 735 errors++; 736 } else 737 lp->d_partitions[part].p_size = v; 738 cp = tp, tp = word(cp); 739 if (tp == NULL) 740 tp = cp; 741 v = atoi(cp); 742 if (v < 0) { 743 fprintf(stderr, 744 "line %d: %s: bad partition offset\n", 745 lineno, cp); 746 errors++; 747 } else 748 lp->d_partitions[part].p_offset = v; 749 cp = tp, tp = word(cp); 750 cpp = fstypenames; 751 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 752 if ((s = *cpp) && streq(s, cp)) { 753 lp->d_partitions[part].p_fstype = 754 cpp - fstypenames; 755 goto next; 756 } 757 v = atoi(cp); 758 if ((unsigned)v >= FSMAXTYPES) 759 fprintf(stderr, "line %d: %s %s\n", lineno, 760 "Warning, unknown filesystem type", cp); 761 lp->d_partitions[part].p_fstype = v; 762 continue; 763 } 764 fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 765 lineno, cp); 766 errors++; 767 next: 768 ; 769 } 770 errors += checklabel(lp); 771 return (errors == 0); 772 } 773 774 /* 775 * Check disklabel for errors and fill in 776 * derived fields according to supplied values. 777 */ 778 checklabel(lp) 779 register struct disklabel *lp; 780 { 781 register struct partition *pp; 782 int i, errors = 0; 783 char part; 784 785 if (lp->d_secsize == 0) { 786 fprintf(stderr, "sector size %d\n", lp->d_secsize); 787 return (1); 788 } 789 if (lp->d_nsectors == 0) { 790 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 791 return (1); 792 } 793 if (lp->d_ntracks == 0) { 794 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 795 return (1); 796 } 797 if (lp->d_ncylinders == 0) { 798 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 799 errors++; 800 } 801 if (lp->d_rpm == 0) 802 Warning("revolutions/minute %d\n", lp->d_rpm); 803 if (lp->d_secpercyl == 0) 804 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 805 if (lp->d_secperunit == 0) 806 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 807 if (lp->d_bbsize == 0) { 808 fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 809 errors++; 810 } else if (lp->d_bbsize % lp->d_secsize) 811 Warning("boot block size %% sector-size != 0\n"); 812 if (lp->d_sbsize == 0) { 813 fprintf(stderr, "super block size %d\n", lp->d_sbsize); 814 errors++; 815 } else if (lp->d_sbsize % lp->d_secsize) 816 Warning("super block size %% sector-size != 0\n"); 817 if (lp->d_npartitions > MAXPARTITIONS) 818 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 819 lp->d_npartitions, MAXPARTITIONS); 820 for (i = 0; i < lp->d_npartitions; i++) { 821 part = 'a' + i; 822 pp = &lp->d_partitions[i]; 823 if (pp->p_size == 0 && pp->p_offset != 0) 824 Warning("partition %c: size 0, but offset %d\n", 825 part, pp->p_offset); 826 #ifdef notdef 827 if (pp->p_size % lp->d_secpercyl) 828 Warning("partition %c: size %% cylinder-size != 0\n", 829 part); 830 if (pp->p_offset % lp->d_secpercyl) 831 Warning("partition %c: offset %% cylinder-size != 0\n", 832 part); 833 #endif 834 if (pp->p_offset > lp->d_secperunit) { 835 fprintf(stderr, 836 "partition %c: offset past end of unit\n", part); 837 errors++; 838 } 839 if (pp->p_offset + pp->p_size > lp->d_secperunit) { 840 fprintf(stderr, 841 "partition %c: partition extends past end of unit\n", 842 part); 843 errors++; 844 } 845 } 846 for (; i < MAXPARTITIONS; i++) { 847 part = 'a' + i; 848 pp = &lp->d_partitions[i]; 849 if (pp->p_size || pp->p_offset) 850 Warning("unused partition %c: size %d offset %d\n", 851 pp->p_size, pp->p_offset); 852 } 853 return (errors); 854 } 855 856 /*VARARGS1*/ 857 Warning(fmt, a1, a2, a3, a4, a5) 858 char *fmt; 859 { 860 861 fprintf(stderr, "Warning, "); 862 fprintf(stderr, fmt, a1, a2, a3, a4, a5); 863 fprintf(stderr, "\n"); 864 } 865 866 Perror(str) 867 char *str; 868 { 869 fputs("disklabel: ", stderr); perror(str); 870 exit(4); 871 } 872 873 usage() 874 { 875 #ifdef BOOT 876 fprintf(stderr, "%-64s%s\n%-64s%s\n%-64s%s\n%-64s%s\n", 877 "usage: disklabel [-r] disk", "(to read label)", 878 "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 879 "or disklabel -e [-r] disk", "(to edit label)", 880 "or disklabel -R [-r] disk protofile [ xxboot bootxx ]", "(to restore label)"); 881 #else 882 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 883 "usage: disklabel [-r] disk", "(to read label)", 884 "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 885 "or disklabel -e [-r] disk", "(to edit label)", 886 "or disklabel -R [-r] disk protofile", "(to restore label)"); 887 #endif 888 exit(1); 889 } 890