1 /* 2 * Copyright (c) 1987 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Symmetric Computer Systems. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 char copyright[] = 23 "@(#) Copyright (c) 1987 The Regents of the University of California.\n\ 24 All rights reserved.\n"; 25 #endif /* not lint */ 26 27 #ifndef lint 28 static char sccsid[] = "@(#)disklabel.c 5.18 (Berkeley) 05/15/90"; 29 /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 30 #endif /* not lint */ 31 32 #include <sys/param.h> 33 #include <sys/signal.h> 34 #include <sys/errno.h> 35 #include <sys/file.h> 36 #include <sys/ioctl.h> 37 #include <ufs/fs.h> 38 #include <string.h> 39 #define DKTYPENAMES 40 #include <sys/disklabel.h> 41 #include <stdio.h> 42 #include <ctype.h> 43 #include "pathnames.h" 44 45 /* 46 * Disklabel: read and write disklabels. 47 * The label is usually placed on one of the first sectors of the disk. 48 * Many machines (VAX 11/750) also place a bootstrap in the same area, 49 * in which case the label is embedded in the bootstrap. 50 * The bootstrap source must leave space at the proper offset 51 * for the label on such machines. 52 */ 53 54 #ifdef vax 55 #define RAWPARTITION 'c' 56 #else 57 #define RAWPARTITION 'a' 58 #endif 59 60 #ifndef BBSIZE 61 #define BBSIZE 8192 /* size of boot area, with label */ 62 #endif 63 64 #ifdef vax 65 #define BOOT /* also have bootstrap in "boot area" */ 66 #define BOOTDIR _PATH_BOOTDIR /* source of boot binaries */ 67 #else 68 #ifdef lint 69 #define BOOT 70 #endif 71 #endif 72 73 #define DEFEDITOR _PATH_VI 74 #define streq(a,b) (strcmp(a,b) == 0) 75 76 #ifdef BOOT 77 char *xxboot; 78 char *bootxx; 79 #endif 80 81 char *dkname; 82 char *specname; 83 char tmpfil[] = _PATH_TMP; 84 85 extern int errno; 86 char namebuf[BBSIZE], *np = namebuf; 87 struct disklabel lab; 88 struct disklabel *readlabel(), *makebootarea(); 89 char bootarea[BBSIZE]; 90 char boot0[MAXPATHLEN]; 91 char boot1[MAXPATHLEN]; 92 93 enum { UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE } op = UNSPEC; 94 95 int rflag; 96 97 #ifdef DEBUG 98 int debug; 99 #endif 100 101 main(argc, argv) 102 int argc; 103 char *argv[]; 104 { 105 extern int optind; 106 register struct disklabel *lp; 107 FILE *t; 108 int ch, f, error = 0; 109 char *name = 0, *type; 110 111 while ((ch = getopt(argc, argv, "NRWerw")) != EOF) 112 switch (ch) { 113 case 'N': 114 if (op != UNSPEC) 115 usage(); 116 op = NOWRITE; 117 break; 118 case 'R': 119 if (op != UNSPEC) 120 usage(); 121 op = RESTORE; 122 break; 123 case 'W': 124 if (op != UNSPEC) 125 usage(); 126 op = WRITEABLE; 127 break; 128 case 'e': 129 if (op != UNSPEC) 130 usage(); 131 op = EDIT; 132 break; 133 case 'r': 134 ++rflag; 135 break; 136 case 'w': 137 if (op != UNSPEC) 138 usage(); 139 op = WRITE; 140 break; 141 #ifdef DEBUG 142 case 'd': 143 debug++; 144 break; 145 #endif 146 case '?': 147 default: 148 usage(); 149 } 150 argc -= optind; 151 argv += optind; 152 if (op == UNSPEC) 153 op = READ; 154 if (argc < 1) 155 usage(); 156 157 dkname = argv[0]; 158 if (dkname[0] != '/') { 159 (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION); 160 specname = np; 161 np += strlen(specname) + 1; 162 } else 163 specname = dkname; 164 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 165 if (f < 0 && errno == ENOENT && dkname[0] != '/') { 166 (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname); 167 np = namebuf + strlen(specname) + 1; 168 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 169 } 170 if (f < 0) 171 Perror(specname); 172 173 switch(op) { 174 case EDIT: 175 if (argc != 1) 176 usage(); 177 lp = readlabel(f); 178 error = edit(lp, f); 179 break; 180 case NOWRITE: { 181 int flag = 0; 182 if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 183 Perror("ioctl DIOCWLABEL"); 184 break; 185 } 186 case READ: 187 if (argc != 1) 188 usage(); 189 lp = readlabel(f); 190 display(stdout, lp); 191 error = checklabel(lp); 192 break; 193 case RESTORE: 194 #ifdef BOOT 195 if (rflag) { 196 if (argc == 4) { /* [ priboot secboot ] */ 197 xxboot = argv[2]; 198 bootxx = argv[3]; 199 lab.d_secsize = DEV_BSIZE; /* XXX */ 200 lab.d_bbsize = BBSIZE; /* XXX */ 201 } 202 else if (argc == 3) /* [ disktype ] */ 203 makelabel(argv[2], (char *)NULL, &lab); 204 else { 205 fprintf(stderr, 206 "Must specify either disktype or bootfiles with -r flag of RESTORE option\n"); 207 exit(1); 208 } 209 } 210 else 211 #endif 212 if (argc != 2) 213 usage(); 214 lp = makebootarea(bootarea, &lab); 215 if (!(t = fopen(argv[1],"r"))) 216 Perror(argv[1]); 217 if (getasciilabel(t, lp)) 218 error = writelabel(f, bootarea, lp); 219 break; 220 case WRITE: 221 type = argv[1]; 222 #ifdef BOOT 223 if (argc > 5 || argc < 2) 224 usage(); 225 if (argc > 3) { 226 bootxx = argv[--argc]; 227 xxboot = argv[--argc]; 228 } 229 #else 230 if (argc > 3 || argc < 2) 231 usage(); 232 #endif 233 if (argc > 2) 234 name = argv[--argc]; 235 makelabel(type, name, &lab); 236 lp = makebootarea(bootarea, &lab); 237 *lp = lab; 238 if (checklabel(lp) == 0) 239 error = writelabel(f, bootarea, lp); 240 break; 241 case WRITEABLE: { 242 int flag = 1; 243 if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 244 Perror("ioctl DIOCWLABEL"); 245 break; 246 } 247 } 248 exit(error); 249 } 250 251 /* 252 * Construct a prototype disklabel from /etc/disktab. As a side 253 * effect, set the names of the primary and secondary boot files 254 * if specified. 255 */ 256 makelabel(type, name, lp) 257 char *type, *name; 258 register struct disklabel *lp; 259 { 260 register struct disklabel *dp; 261 char *strcpy(); 262 263 dp = getdiskbyname(type); 264 if (dp == NULL) { 265 fprintf(stderr, "%s: unknown disk type\n", type); 266 exit(1); 267 } 268 *lp = *dp; 269 #ifdef BOOT 270 /* 271 * Check if disktab specifies the bootstraps (b0 or b1). 272 */ 273 if (!xxboot && lp->d_boot0) { 274 if (*lp->d_boot0 != '/') 275 (void)sprintf(boot0, "%s/%s", BOOTDIR, lp->d_boot0); 276 else 277 (void)strcpy(boot0, lp->d_boot0); 278 xxboot = boot0; 279 } 280 if (!bootxx && lp->d_boot1) { 281 if (*lp->d_boot1 != '/') 282 (void)sprintf(boot1, "%s/%s", BOOTDIR, lp->d_boot1); 283 else 284 (void)strcpy(boot1, lp->d_boot1); 285 bootxx = boot1; 286 } 287 /* 288 * If bootstraps not specified anywhere, makebootarea() 289 * will choose ones based on the name of the disk special 290 * file. E.g. /dev/ra0 -> raboot, bootra 291 */ 292 #endif /*BOOT*/ 293 /* d_packname is union d_boot[01], so zero */ 294 bzero(lp->d_packname, sizeof(lp->d_packname)); 295 if (name) 296 (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 297 } 298 299 writelabel(f, boot, lp) 300 int f; 301 char *boot; 302 register struct disklabel *lp; 303 { 304 register int i; 305 int flag; 306 off_t lseek(); 307 308 lp->d_magic = DISKMAGIC; 309 lp->d_magic2 = DISKMAGIC; 310 lp->d_checksum = 0; 311 lp->d_checksum = dkcksum(lp); 312 if (rflag) { 313 /* 314 * First set the kernel disk label, 315 * then write a label to the raw disk. 316 * If the SDINFO ioctl fails because it is unimplemented, 317 * keep going; otherwise, the kernel consistency checks 318 * may prevent us from changing the current (in-core) 319 * label. 320 */ 321 if (ioctl(f, DIOCSDINFO, lp) < 0 && 322 errno != ENODEV && errno != ENOTTY) { 323 l_perror("ioctl DIOCSDINFO"); 324 return (1); 325 } 326 (void)lseek(f, (off_t)0, L_SET); 327 /* 328 * write enable label sector before write (if necessary), 329 * disable after writing. 330 */ 331 flag = 1; 332 if (ioctl(f, DIOCWLABEL, &flag) < 0) 333 perror("ioctl DIOCWLABEL"); 334 if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 335 perror("write"); 336 return (1); 337 } 338 flag = 0; 339 (void) ioctl(f, DIOCWLABEL, &flag); 340 } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 341 l_perror("ioctl DIOCWDINFO"); 342 return (1); 343 } 344 #ifdef vax 345 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 346 daddr_t alt; 347 348 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 349 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 350 (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), L_SET); 351 if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 352 int oerrno = errno; 353 fprintf(stderr, "alternate label %d ", i/2); 354 errno = oerrno; 355 perror("write"); 356 } 357 } 358 } 359 #endif 360 return (0); 361 } 362 363 l_perror(s) 364 char *s; 365 { 366 int saverrno = errno; 367 368 fprintf(stderr, "disklabel: %s: ", s); 369 370 switch (saverrno) { 371 372 case ESRCH: 373 fprintf(stderr, "No disk label on disk;\n"); 374 fprintf(stderr, 375 "use \"disklabel -r\" to install initial label\n"); 376 break; 377 378 case EINVAL: 379 fprintf(stderr, "Label magic number or checksum is wrong!\n"); 380 fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 381 break; 382 383 case EBUSY: 384 fprintf(stderr, "Open partition would move or shrink\n"); 385 break; 386 387 case EXDEV: 388 fprintf(stderr, 389 "Labeled partition or 'a' partition must start at beginning of disk\n"); 390 break; 391 392 default: 393 errno = saverrno; 394 perror((char *)NULL); 395 break; 396 } 397 } 398 399 /* 400 * Fetch disklabel for disk. 401 * Use ioctl to get label unless -r flag is given. 402 */ 403 struct disklabel * 404 readlabel(f) 405 int f; 406 { 407 register struct disklabel *lp; 408 409 if (rflag) { 410 if (read(f, bootarea, BBSIZE) < BBSIZE) 411 Perror(specname); 412 for (lp = (struct disklabel *)bootarea; 413 lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 414 lp = (struct disklabel *)((char *)lp + 16)) 415 if (lp->d_magic == DISKMAGIC && 416 lp->d_magic2 == DISKMAGIC) 417 break; 418 if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 419 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 420 dkcksum(lp) != 0) { 421 fprintf(stderr, 422 "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 423 /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */ 424 exit (1); 425 } 426 } else { 427 lp = &lab; 428 if (ioctl(f, DIOCGDINFO, lp) < 0) 429 Perror("ioctl DIOCGDINFO"); 430 } 431 return (lp); 432 } 433 434 struct disklabel * 435 makebootarea(boot, dp) 436 char *boot; 437 register struct disklabel *dp; 438 { 439 struct disklabel *lp; 440 register char *p; 441 int b; 442 #ifdef BOOT 443 char *dkbasename; 444 #endif /*BOOT*/ 445 446 lp = (struct disklabel *)(boot + (LABELSECTOR * dp->d_secsize) + 447 LABELOFFSET); 448 #ifdef BOOT 449 if (!rflag) 450 return (lp); 451 452 if (xxboot == NULL || bootxx == NULL) { 453 dkbasename = np; 454 if ((p = rindex(dkname, '/')) == NULL) 455 p = dkname; 456 else 457 p++; 458 while (*p && !isdigit(*p)) 459 *np++ = *p++; 460 *np++ = '\0'; 461 462 if (xxboot == NULL) { 463 (void)sprintf(np, "%s/%sboot", BOOTDIR, dkbasename); 464 if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 465 dkbasename++; 466 xxboot = np; 467 (void)sprintf(xxboot, "%s/%sboot", BOOTDIR, dkbasename); 468 np += strlen(xxboot) + 1; 469 } 470 if (bootxx == NULL) { 471 (void)sprintf(np, "%s/boot%s", BOOTDIR, dkbasename); 472 if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 473 dkbasename++; 474 bootxx = np; 475 (void)sprintf(bootxx, "%s/boot%s", BOOTDIR, dkbasename); 476 np += strlen(bootxx) + 1; 477 } 478 } 479 #ifdef DEBUG 480 if (debug) 481 fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n", 482 xxboot, bootxx); 483 #endif 484 485 b = open(xxboot, O_RDONLY); 486 if (b < 0) 487 Perror(xxboot); 488 if (read(b, boot, (int)dp->d_secsize) < 0) 489 Perror(xxboot); 490 close(b); 491 b = open(bootxx, O_RDONLY); 492 if (b < 0) 493 Perror(bootxx); 494 if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 495 Perror(bootxx); 496 (void)close(b); 497 #endif /*BOOT*/ 498 499 for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 500 if (*p) { 501 fprintf(stderr, 502 "Bootstrap doesn't leave room for disk label\n"); 503 exit(2); 504 } 505 return (lp); 506 } 507 508 display(f, lp) 509 FILE *f; 510 register struct disklabel *lp; 511 { 512 register int i, j; 513 register struct partition *pp; 514 515 fprintf(f, "# %s:\n", specname); 516 if ((unsigned) lp->d_type < DKMAXTYPES) 517 fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 518 else 519 fprintf(f, "type: %d\n", lp->d_type); 520 fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 521 fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname); 522 fprintf(f, "flags:"); 523 if (lp->d_flags & D_REMOVABLE) 524 fprintf(f, " removeable"); 525 if (lp->d_flags & D_ECC) 526 fprintf(f, " ecc"); 527 if (lp->d_flags & D_BADSECT) 528 fprintf(f, " badsect"); 529 fprintf(f, "\n"); 530 fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 531 fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 532 fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 533 fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 534 fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 535 fprintf(f, "rpm: %d\n", lp->d_rpm); 536 fprintf(f, "interleave: %d\n", lp->d_interleave); 537 fprintf(f, "trackskew: %d\n", lp->d_trackskew); 538 fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 539 fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 540 fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 541 fprintf(f, "drivedata: "); 542 for (i = NDDATA - 1; i >= 0; i--) 543 if (lp->d_drivedata[i]) 544 break; 545 if (i < 0) 546 i = 0; 547 for (j = 0; j <= i; j++) 548 fprintf(f, "%d ", lp->d_drivedata[j]); 549 fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 550 fprintf(f, 551 "# size offset fstype [fsize bsize cpg]\n"); 552 pp = lp->d_partitions; 553 for (i = 0; i < lp->d_npartitions; i++, pp++) { 554 if (pp->p_size) { 555 fprintf(f, " %c: %8d %8d ", 'a' + i, 556 pp->p_size, pp->p_offset); 557 if ((unsigned) pp->p_fstype < FSMAXTYPES) 558 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 559 else 560 fprintf(f, "%8d", pp->p_fstype); 561 switch (pp->p_fstype) { 562 563 case FS_UNUSED: /* XXX */ 564 fprintf(f, " %5d %5d %5.5s ", 565 pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 566 break; 567 568 case FS_BSDFFS: 569 fprintf(f, " %5d %5d %5d ", 570 pp->p_fsize, pp->p_fsize * pp->p_frag, 571 pp->p_cpg); 572 break; 573 574 default: 575 fprintf(f, "%20.20s", ""); 576 break; 577 } 578 fprintf(f, "\t# (Cyl. %4d", 579 pp->p_offset / lp->d_secpercyl); 580 if (pp->p_offset % lp->d_secpercyl) 581 putc('*', f); 582 else 583 putc(' ', f); 584 fprintf(f, "- %d", 585 (pp->p_offset + 586 pp->p_size + lp->d_secpercyl - 1) / 587 lp->d_secpercyl - 1); 588 if (pp->p_size % lp->d_secpercyl) 589 putc('*', f); 590 fprintf(f, ")\n"); 591 } 592 } 593 fflush(f); 594 } 595 596 edit(lp, f) 597 struct disklabel *lp; 598 int f; 599 { 600 register int c; 601 struct disklabel label; 602 FILE *fd; 603 char *mktemp(); 604 605 (void) mktemp(tmpfil); 606 fd = fopen(tmpfil, "w"); 607 if (fd == NULL) { 608 fprintf(stderr, "%s: Can't create\n", tmpfil); 609 return (1); 610 } 611 (void)fchmod(fd, 0600); 612 display(fd, lp); 613 fclose(fd); 614 for (;;) { 615 if (!editit()) 616 break; 617 fd = fopen(tmpfil, "r"); 618 if (fd == NULL) { 619 fprintf(stderr, "%s: Can't reopen for reading\n", 620 tmpfil); 621 break; 622 } 623 bzero((char *)&label, sizeof(label)); 624 if (getasciilabel(fd, &label)) { 625 *lp = label; 626 if (writelabel(f, bootarea, lp) == 0) { 627 (void) unlink(tmpfil); 628 return (0); 629 } 630 } 631 printf("re-edit the label? [y]: "); fflush(stdout); 632 c = getchar(); 633 if (c != EOF && c != (int)'\n') 634 while (getchar() != (int)'\n') 635 ; 636 if (c == (int)'n') 637 break; 638 } 639 (void) unlink(tmpfil); 640 return (1); 641 } 642 643 editit() 644 { 645 register int pid, xpid; 646 int stat, omask; 647 extern char *getenv(); 648 649 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 650 while ((pid = fork()) < 0) { 651 extern int errno; 652 653 if (errno == EPROCLIM) { 654 fprintf(stderr, "You have too many processes\n"); 655 return(0); 656 } 657 if (errno != EAGAIN) { 658 perror("fork"); 659 return(0); 660 } 661 sleep(1); 662 } 663 if (pid == 0) { 664 register char *ed; 665 666 sigsetmask(omask); 667 setgid(getgid()); 668 setuid(getuid()); 669 if ((ed = getenv("EDITOR")) == (char *)0) 670 ed = DEFEDITOR; 671 execlp(ed, ed, tmpfil, 0); 672 perror(ed); 673 exit(1); 674 } 675 while ((xpid = wait(&stat)) >= 0) 676 if (xpid == pid) 677 break; 678 sigsetmask(omask); 679 return(!stat); 680 } 681 682 char * 683 skip(cp) 684 register char *cp; 685 { 686 687 while (*cp != '\0' && isspace(*cp)) 688 cp++; 689 if (*cp == '\0' || *cp == '#') 690 return ((char *)NULL); 691 return (cp); 692 } 693 694 char * 695 word(cp) 696 register char *cp; 697 { 698 register char c; 699 700 while (*cp != '\0' && !isspace(*cp) && *cp != '#') 701 cp++; 702 if ((c = *cp) != '\0') { 703 *cp++ = '\0'; 704 if (c != '#') 705 return (skip(cp)); 706 } 707 return ((char *)NULL); 708 } 709 710 /* 711 * Read an ascii label in from fd f, 712 * in the same format as that put out by display(), 713 * and fill in lp. 714 */ 715 getasciilabel(f, lp) 716 FILE *f; 717 register struct disklabel *lp; 718 { 719 register char **cpp, *cp; 720 register struct partition *pp; 721 char *tp, *s, line[BUFSIZ]; 722 int v, lineno = 0, errors = 0; 723 724 lp->d_bbsize = BBSIZE; /* XXX */ 725 lp->d_sbsize = SBSIZE; /* XXX */ 726 while (fgets(line, sizeof(line) - 1, f)) { 727 lineno++; 728 if (cp = index(line,'\n')) 729 *cp = '\0'; 730 cp = skip(line); 731 if (cp == NULL) 732 continue; 733 tp = index(cp, ':'); 734 if (tp == NULL) { 735 fprintf(stderr, "line %d: syntax error\n", lineno); 736 errors++; 737 continue; 738 } 739 *tp++ = '\0', tp = skip(tp); 740 if (streq(cp, "type")) { 741 if (tp == NULL) 742 tp = "unknown"; 743 cpp = dktypenames; 744 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 745 if ((s = *cpp) && streq(s, tp)) { 746 lp->d_type = cpp - dktypenames; 747 goto next; 748 } 749 v = atoi(tp); 750 if ((unsigned)v >= DKMAXTYPES) 751 fprintf(stderr, "line %d:%s %d\n", lineno, 752 "Warning, unknown disk type", v); 753 lp->d_type = v; 754 continue; 755 } 756 if (streq(cp, "flags")) { 757 for (v = 0; (cp = tp) && *cp != '\0';) { 758 tp = word(cp); 759 if (streq(cp, "removeable")) 760 v |= D_REMOVABLE; 761 else if (streq(cp, "ecc")) 762 v |= D_ECC; 763 else if (streq(cp, "badsect")) 764 v |= D_BADSECT; 765 else { 766 fprintf(stderr, 767 "line %d: %s: bad flag\n", 768 lineno, cp); 769 errors++; 770 } 771 } 772 lp->d_flags = v; 773 continue; 774 } 775 if (streq(cp, "drivedata")) { 776 register int i; 777 778 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 779 lp->d_drivedata[i++] = atoi(cp); 780 tp = word(cp); 781 } 782 continue; 783 } 784 if (sscanf(cp, "%d partitions", &v) == 1) { 785 if (v == 0 || (unsigned)v > MAXPARTITIONS) { 786 fprintf(stderr, 787 "line %d: bad # of partitions\n", lineno); 788 lp->d_npartitions = MAXPARTITIONS; 789 errors++; 790 } else 791 lp->d_npartitions = v; 792 continue; 793 } 794 if (tp == NULL) 795 tp = ""; 796 if (streq(cp, "disk")) { 797 strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 798 continue; 799 } 800 if (streq(cp, "label")) { 801 strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 802 continue; 803 } 804 if (streq(cp, "bytes/sector")) { 805 v = atoi(tp); 806 if (v <= 0 || (v % 512) != 0) { 807 fprintf(stderr, 808 "line %d: %s: bad sector size\n", 809 lineno, tp); 810 errors++; 811 } else 812 lp->d_secsize = v; 813 continue; 814 } 815 if (streq(cp, "sectors/track")) { 816 v = atoi(tp); 817 if (v <= 0) { 818 fprintf(stderr, "line %d: %s: bad %s\n", 819 lineno, tp, cp); 820 errors++; 821 } else 822 lp->d_nsectors = v; 823 continue; 824 } 825 if (streq(cp, "sectors/cylinder")) { 826 v = atoi(tp); 827 if (v <= 0) { 828 fprintf(stderr, "line %d: %s: bad %s\n", 829 lineno, tp, cp); 830 errors++; 831 } else 832 lp->d_secpercyl = v; 833 continue; 834 } 835 if (streq(cp, "tracks/cylinder")) { 836 v = atoi(tp); 837 if (v <= 0) { 838 fprintf(stderr, "line %d: %s: bad %s\n", 839 lineno, tp, cp); 840 errors++; 841 } else 842 lp->d_ntracks = v; 843 continue; 844 } 845 if (streq(cp, "cylinders")) { 846 v = atoi(tp); 847 if (v <= 0) { 848 fprintf(stderr, "line %d: %s: bad %s\n", 849 lineno, tp, cp); 850 errors++; 851 } else 852 lp->d_ncylinders = v; 853 continue; 854 } 855 if (streq(cp, "rpm")) { 856 v = atoi(tp); 857 if (v <= 0) { 858 fprintf(stderr, "line %d: %s: bad %s\n", 859 lineno, tp, cp); 860 errors++; 861 } else 862 lp->d_rpm = v; 863 continue; 864 } 865 if (streq(cp, "interleave")) { 866 v = atoi(tp); 867 if (v <= 0) { 868 fprintf(stderr, "line %d: %s: bad %s\n", 869 lineno, tp, cp); 870 errors++; 871 } else 872 lp->d_interleave = v; 873 continue; 874 } 875 if (streq(cp, "trackskew")) { 876 v = atoi(tp); 877 if (v < 0) { 878 fprintf(stderr, "line %d: %s: bad %s\n", 879 lineno, tp, cp); 880 errors++; 881 } else 882 lp->d_trackskew = v; 883 continue; 884 } 885 if (streq(cp, "cylinderskew")) { 886 v = atoi(tp); 887 if (v < 0) { 888 fprintf(stderr, "line %d: %s: bad %s\n", 889 lineno, tp, cp); 890 errors++; 891 } else 892 lp->d_cylskew = v; 893 continue; 894 } 895 if (streq(cp, "headswitch")) { 896 v = atoi(tp); 897 if (v < 0) { 898 fprintf(stderr, "line %d: %s: bad %s\n", 899 lineno, tp, cp); 900 errors++; 901 } else 902 lp->d_headswitch = v; 903 continue; 904 } 905 if (streq(cp, "track-to-track seek")) { 906 v = atoi(tp); 907 if (v < 0) { 908 fprintf(stderr, "line %d: %s: bad %s\n", 909 lineno, tp, cp); 910 errors++; 911 } else 912 lp->d_trkseek = v; 913 continue; 914 } 915 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 916 unsigned part = *cp - 'a'; 917 918 if (part > lp->d_npartitions) { 919 fprintf(stderr, 920 "line %d: bad partition name\n", lineno); 921 errors++; 922 continue; 923 } 924 pp = &lp->d_partitions[part]; 925 #define NXTNUM(n) { \ 926 cp = tp, tp = word(cp); \ 927 if (tp == NULL) \ 928 tp = cp; \ 929 (n) = atoi(cp); \ 930 } 931 932 NXTNUM(v); 933 if (v < 0) { 934 fprintf(stderr, 935 "line %d: %s: bad partition size\n", 936 lineno, cp); 937 errors++; 938 } else 939 pp->p_size = v; 940 NXTNUM(v); 941 if (v < 0) { 942 fprintf(stderr, 943 "line %d: %s: bad partition offset\n", 944 lineno, cp); 945 errors++; 946 } else 947 pp->p_offset = v; 948 cp = tp, tp = word(cp); 949 cpp = fstypenames; 950 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 951 if ((s = *cpp) && streq(s, cp)) { 952 pp->p_fstype = cpp - fstypenames; 953 goto gottype; 954 } 955 if (isdigit(*cp)) 956 v = atoi(cp); 957 else 958 v = FSMAXTYPES; 959 if ((unsigned)v >= FSMAXTYPES) { 960 fprintf(stderr, "line %d: %s %s\n", lineno, 961 "Warning, unknown filesystem type", cp); 962 v = FS_UNUSED; 963 } 964 pp->p_fstype = v; 965 gottype: 966 967 switch (pp->p_fstype) { 968 969 case FS_UNUSED: /* XXX */ 970 NXTNUM(pp->p_fsize); 971 if (pp->p_fsize == 0) 972 break; 973 NXTNUM(v); 974 pp->p_frag = v / pp->p_fsize; 975 break; 976 977 case FS_BSDFFS: 978 NXTNUM(pp->p_fsize); 979 if (pp->p_fsize == 0) 980 break; 981 NXTNUM(v); 982 pp->p_frag = v / pp->p_fsize; 983 NXTNUM(pp->p_cpg); 984 break; 985 986 default: 987 break; 988 } 989 continue; 990 } 991 fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 992 lineno, cp); 993 errors++; 994 next: 995 ; 996 } 997 errors += checklabel(lp); 998 return (errors == 0); 999 } 1000 1001 /* 1002 * Check disklabel for errors and fill in 1003 * derived fields according to supplied values. 1004 */ 1005 checklabel(lp) 1006 register struct disklabel *lp; 1007 { 1008 register struct partition *pp; 1009 int i, errors = 0; 1010 char part; 1011 1012 if (lp->d_secsize == 0) { 1013 fprintf(stderr, "sector size %d\n", lp->d_secsize); 1014 return (1); 1015 } 1016 if (lp->d_nsectors == 0) { 1017 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 1018 return (1); 1019 } 1020 if (lp->d_ntracks == 0) { 1021 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 1022 return (1); 1023 } 1024 if (lp->d_ncylinders == 0) { 1025 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 1026 errors++; 1027 } 1028 if (lp->d_rpm == 0) 1029 Warning("revolutions/minute %d\n", lp->d_rpm); 1030 if (lp->d_secpercyl == 0) 1031 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1032 if (lp->d_secperunit == 0) 1033 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1034 if (lp->d_bbsize == 0) { 1035 fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 1036 errors++; 1037 } else if (lp->d_bbsize % lp->d_secsize) 1038 Warning("boot block size %% sector-size != 0\n"); 1039 if (lp->d_sbsize == 0) { 1040 fprintf(stderr, "super block size %d\n", lp->d_sbsize); 1041 errors++; 1042 } else if (lp->d_sbsize % lp->d_secsize) 1043 Warning("super block size %% sector-size != 0\n"); 1044 if (lp->d_npartitions > MAXPARTITIONS) 1045 Warning("number of partitions (%d) > MAXPARTITIONS (%d)\n", 1046 lp->d_npartitions, MAXPARTITIONS); 1047 for (i = 0; i < lp->d_npartitions; i++) { 1048 part = 'a' + i; 1049 pp = &lp->d_partitions[i]; 1050 if (pp->p_size == 0 && pp->p_offset != 0) 1051 Warning("partition %c: size 0, but offset %d\n", 1052 part, pp->p_offset); 1053 #ifdef notdef 1054 if (pp->p_size % lp->d_secpercyl) 1055 Warning("partition %c: size %% cylinder-size != 0\n", 1056 part); 1057 if (pp->p_offset % lp->d_secpercyl) 1058 Warning("partition %c: offset %% cylinder-size != 0\n", 1059 part); 1060 #endif 1061 if (pp->p_offset > lp->d_secperunit) { 1062 fprintf(stderr, 1063 "partition %c: offset past end of unit\n", part); 1064 errors++; 1065 } 1066 if (pp->p_offset + pp->p_size > lp->d_secperunit) { 1067 fprintf(stderr, 1068 "partition %c: partition extends past end of unit\n", 1069 part); 1070 errors++; 1071 } 1072 } 1073 for (; i < MAXPARTITIONS; i++) { 1074 part = 'a' + i; 1075 pp = &lp->d_partitions[i]; 1076 if (pp->p_size || pp->p_offset) 1077 Warning("unused partition %c: size %d offset %d\n", 1078 'a' + i, pp->p_size, pp->p_offset); 1079 } 1080 return (errors); 1081 } 1082 1083 /*VARARGS1*/ 1084 Warning(fmt, a1, a2, a3, a4, a5) 1085 char *fmt; 1086 { 1087 1088 fprintf(stderr, "Warning, "); 1089 fprintf(stderr, fmt, a1, a2, a3, a4, a5); 1090 fprintf(stderr, "\n"); 1091 } 1092 1093 Perror(str) 1094 char *str; 1095 { 1096 fputs("disklabel: ", stderr); perror(str); 1097 exit(4); 1098 } 1099 1100 usage() 1101 { 1102 #ifdef BOOT 1103 fprintf(stderr, "%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n%-62s%s\n", 1104 "usage: disklabel [-r] disk", "(to read label)", 1105 "or disklabel -w [-r] disk type [ packid ] [ xxboot bootxx ]", "(to write label)", 1106 "or disklabel -e [-r] disk", "(to edit label)", 1107 "or disklabel -R [-r] disk protofile [ type | xxboot bootxx ]", "(to restore label)", 1108 "or disklabel [-NW] disk", "(to write disable/enable label)"); 1109 #else 1110 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 1111 "usage: disklabel [-r] disk", "(to read label)", 1112 "or disklabel -w [-r] disk type [ packid ]", "(to write label)", 1113 "or disklabel -e [-r] disk", "(to edit label)", 1114 "or disklabel -R [-r] disk protofile", "(to restore label)", 1115 "or disklabel [-NW] disk", "(to write disable/enable label)"); 1116 #endif 1117 exit(1); 1118 } 1119