bsdlabel.c revision 109891
1/* 2 * Copyright (c) 1994, 1995 Gordon W. Ross 3 * Copyright (c) 1994 Theo de Raadt 4 * All rights reserved. 5 * Copyright (c) 1987, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Symmetric Computer Systems. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * This product includes software developed by Theo de Raadt. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $ 41 */ 42 43#ifndef lint 44static const char copyright[] = 45"@(#) Copyright (c) 1987, 1993\n\ 46 The Regents of the University of California. All rights reserved.\n"; 47#endif /* not lint */ 48 49#ifndef lint 50#if 0 51static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; 52/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 53#endif 54#endif /* not lint */ 55 56#include <sys/cdefs.h> 57__FBSDID("$FreeBSD: head/sbin/bsdlabel/bsdlabel.c 109891 2003-01-26 18:33:54Z phk $"); 58 59#include <sys/param.h> 60#include <sys/file.h> 61#include <sys/stat.h> 62#include <sys/wait.h> 63#include <sys/disk.h> 64#define DKTYPENAMES 65#define FSTYPENAMES 66#include <sys/disklabel.h> 67#ifdef PC98 68#include <sys/diskpc98.h> 69#else 70#include <sys/diskmbr.h> 71#endif 72 73#include <unistd.h> 74#include <string.h> 75#include <stdio.h> 76#include <stdlib.h> 77#include <signal.h> 78#include <stdarg.h> 79#include <ctype.h> 80#include <err.h> 81#include <errno.h> 82 83#include "pathnames.h" 84 85/* 86 * Disklabel: read and write disklabels. 87 * The label is usually placed on one of the first sectors of the disk. 88 * Many machines also place a bootstrap in the same area, 89 * in which case the label is embedded in the bootstrap. 90 * The bootstrap source must leave space at the proper offset 91 * for the label on such machines. 92 */ 93 94#ifndef BBSIZE 95#define BBSIZE 8192 /* size of boot area, with label */ 96#endif 97 98/* FIX! These are too low, but are traditional */ 99#define DEFAULT_NEWFS_BLOCK 8192U 100#define DEFAULT_NEWFS_FRAG 1024U 101#define DEFAULT_NEWFS_CPG 16U 102 103#define BIG_NEWFS_BLOCK 16384U 104#define BIG_NEWFS_FRAG 2048U 105#define BIG_NEWFS_CPG 64U 106 107#if defined(__i386__) 108#elif defined(__alpha__) 109#elif defined(__ia64__) 110#else 111#error I do not know about this architecture, and shall probably not be compiled for it. 112#endif 113 114void makelabel(const char *, const char *, struct disklabel *); 115int writelabel(int, const char *, struct disklabel *); 116void l_perror(const char *); 117struct disklabel *readlabel(int); 118struct disklabel *makebootarea(char *, struct disklabel *, int); 119void display(FILE *, const struct disklabel *); 120int edit(struct disklabel *, int); 121int editit(void); 122char *skip(char *); 123char *word(char *); 124int getasciilabel(FILE *, struct disklabel *); 125int getasciipartspec(char *, struct disklabel *, int, int); 126int checklabel(struct disklabel *); 127void Warning(const char *, ...) __printflike(1, 2); 128void usage(void); 129struct disklabel *getvirginlabel(void); 130 131#define DEFEDITOR _PATH_VI 132#define streq(a,b) (strcmp(a,b) == 0) 133 134char *dkname; 135char *specname; 136char tmpfil[] = PATH_TMPFILE; 137 138char namebuf[BBSIZE], *np = namebuf; 139struct disklabel lab; 140char bootarea[BBSIZE]; 141char blank[] = ""; 142char unknown[] = "unknown"; 143 144#define MAX_PART ('z') 145#define MAX_NUM_PARTS (1 + MAX_PART - 'a') 146char part_size_type[MAX_NUM_PARTS]; 147char part_offset_type[MAX_NUM_PARTS]; 148int part_set[MAX_NUM_PARTS]; 149 150int installboot; /* non-zero if we should install a boot program */ 151char *xxboot; /* primary boot */ 152char boot0[MAXPATHLEN]; 153 154enum { 155 UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT 156} op = UNSPEC; 157 158int rflag; 159int disable_write; /* set to disable writing to disk label */ 160 161#define OPTIONS "BRb:enrs:w" 162 163int 164main(int argc, char *argv[]) 165{ 166 struct disklabel *lp; 167 FILE *t; 168 int ch, f = 0, error = 0; 169 char *name = 0; 170 171 while ((ch = getopt(argc, argv, OPTIONS)) != -1) 172 switch (ch) { 173 case 'B': 174 ++installboot; 175 break; 176 case 'b': 177 xxboot = optarg; 178 break; 179 case 'n': 180 disable_write = 1; 181 break; 182 case 'R': 183 if (op != UNSPEC) 184 usage(); 185 op = RESTORE; 186 break; 187 case 'e': 188 if (op != UNSPEC) 189 usage(); 190 op = EDIT; 191 break; 192 case 'r': 193 ++rflag; 194 break; 195 case 'w': 196 if (op != UNSPEC) 197 usage(); 198 op = WRITE; 199 break; 200 case '?': 201 default: 202 usage(); 203 } 204 argc -= optind; 205 argv += optind; 206 if (installboot) { 207 rflag++; 208 if (op == UNSPEC) 209 op = WRITEBOOT; 210 } else { 211 if (op == UNSPEC) 212 op = READ; 213 xxboot = 0; 214 } 215 if (argc < 1) 216 usage(); 217 218 dkname = argv[0]; 219 if (dkname[0] != '/') { 220 (void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); 221 specname = np; 222 np += strlen(specname) + 1; 223 } else 224 specname = dkname; 225 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 226 if (f < 0 && errno == ENOENT && dkname[0] != '/') { 227 (void)sprintf(specname, "%s%s", _PATH_DEV, dkname); 228 np = namebuf + strlen(specname) + 1; 229 f = open(specname, op == READ ? O_RDONLY : O_RDWR); 230 } 231 if (f < 0) 232 err(4, "%s", specname); 233 234 switch(op) { 235 236 case UNSPEC: 237 break; 238 239 case EDIT: 240 if (argc != 1) 241 usage(); 242 lp = readlabel(f); 243 error = edit(lp, f); 244 break; 245 246 case READ: 247 if (argc != 1) 248 usage(); 249 lp = readlabel(f); 250 display(stdout, lp); 251 error = checklabel(lp); 252 break; 253 254 case RESTORE: 255 if (installboot && argc == 3) { 256 makelabel(argv[2], 0, &lab); 257 argc--; 258 259 /* 260 * We only called makelabel() for its side effect 261 * of setting the bootstrap file names. Discard 262 * all changes to `lab' so that all values in the 263 * final label come from the ASCII label. 264 */ 265 bzero((char *)&lab, sizeof(lab)); 266 } 267 if (argc != 2) 268 usage(); 269 if (!(t = fopen(argv[1], "r"))) 270 err(4, "%s", argv[1]); 271 if (!getasciilabel(t, &lab)) 272 exit(1); 273 lp = makebootarea(bootarea, &lab, f); 274 *lp = lab; 275 error = writelabel(f, bootarea, lp); 276 break; 277 278 case WRITE: 279 if (argc == 3) { 280 name = argv[2]; 281 argc--; 282 } 283 if (argc != 2) 284 usage(); 285 makelabel(argv[1], name, &lab); 286 lp = makebootarea(bootarea, &lab, f); 287 *lp = lab; 288 if (checklabel(lp) == 0) 289 error = writelabel(f, bootarea, lp); 290 break; 291 292 case WRITEBOOT: 293 { 294 struct disklabel tlab; 295 296 lp = readlabel(f); 297 tlab = *lp; 298 if (argc == 2) 299 makelabel(argv[1], 0, &lab); 300 lp = makebootarea(bootarea, &lab, f); 301 *lp = tlab; 302 if (checklabel(lp) == 0) 303 error = writelabel(f, bootarea, lp); 304 break; 305 } 306 } 307 exit(error); 308} 309 310/* 311 * Construct a prototype disklabel from /etc/disktab. As a side 312 * effect, set the names of the primary and secondary boot files 313 * if specified. 314 */ 315void 316makelabel(const char *type, const char *name, struct disklabel *lp) 317{ 318 struct disklabel *dp; 319 320 if (strcmp(type, "auto") == 0) 321 dp = getvirginlabel(); 322 else 323 dp = getdiskbyname(type); 324 if (dp == NULL) 325 errx(1, "%s: unknown disk type", type); 326 *lp = *dp; 327 bzero(lp->d_packname, sizeof(lp->d_packname)); 328 if (name) 329 (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 330} 331 332int 333writelabel(int f, const char *boot, struct disklabel *lp) 334{ 335#ifdef __alpha__ 336 u_long *p, sum; 337 int i; 338#endif 339 340 if (disable_write) { 341 Warning("write to disk label supressed - label was as follows:"); 342 display(stdout, lp); 343 return (0); 344 } 345 346 lp->d_magic = DISKMAGIC; 347 lp->d_magic2 = DISKMAGIC; 348 lp->d_checksum = 0; 349 lp->d_checksum = dkcksum(lp); 350 if (!rflag) { 351 if (ioctl(f, DIOCWDINFO, lp) < 0) { 352 l_perror("ioctl DIOCWDINFO"); 353 return (1); 354 } 355 return (0); 356 } 357 358 /* 359 * First set the kernel disk label, 360 * then write a label to the raw disk. 361 * If the SDINFO ioctl fails because it is unimplemented, 362 * keep going; otherwise, the kernel consistency checks 363 * may prevent us from changing the current (in-core) 364 * label. 365 */ 366 if (ioctl(f, DIOCSDINFO, lp) < 0 && 367 errno != ENODEV && errno != ENOTTY) { 368 l_perror("ioctl DIOCSDINFO"); 369 return (1); 370 } 371 (void)lseek(f, (off_t)0, SEEK_SET); 372 373#ifdef __alpha__ 374 /* 375 * Generate the bootblock checksum for the SRM console. 376 */ 377 for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) 378 sum += p[i]; 379 p[63] = sum; 380#endif 381 if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) { 382 warn("write"); 383 return (1); 384 } 385 return (0); 386} 387 388void 389l_perror(const char *s) 390{ 391 switch (errno) { 392 393 case ESRCH: 394 warnx("%s: no disk label on disk;", s); 395 fprintf(stderr, "add \"-r\" to install initial label\n"); 396 break; 397 398 case EINVAL: 399 warnx("%s: label magic number or checksum is wrong!", s); 400 fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 401 break; 402 403 case EBUSY: 404 warnx("%s: open partition would move or shrink", s); 405 break; 406 407 case EXDEV: 408 warnx("%s: '%c' partition must start at beginning of disk", 409 s, 'a' + RAW_PART); 410 break; 411 412 default: 413 warn((char *)NULL); 414 break; 415 } 416} 417 418/* 419 * Fetch disklabel for disk. 420 * Use ioctl to get label unless -r flag is given. 421 */ 422struct disklabel * 423readlabel(int f) 424{ 425 struct disklabel *lp; 426 427 if (rflag) { 428 if (read(f, bootarea, BBSIZE) < BBSIZE) 429 err(4, "%s", specname); 430 for (lp = (struct disklabel *)bootarea; 431 lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 432 lp = (struct disklabel *)((char *)lp + 16)) 433 if (lp->d_magic == DISKMAGIC && 434 lp->d_magic2 == DISKMAGIC) 435 break; 436 if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 437 lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 438 dkcksum(lp) != 0) 439 errx(1, 440 "bad pack magic number (label is damaged, or pack is unlabeled)"); 441 } else { 442 lp = &lab; 443 if (ioctl(f, DIOCGDINFO, lp) < 0) 444 err(4, "ioctl DIOCGDINFO"); 445 } 446 return (lp); 447} 448 449/* 450 * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 451 * Returns a pointer to the disklabel portion of the bootarea. 452 */ 453struct disklabel * 454makebootarea(char *boot, struct disklabel *dp, int f) 455{ 456 struct disklabel *lp; 457 char *p; 458 int b; 459 char *dkbasename; 460 struct stat sb; 461#ifdef __alpha__ 462 u_long *bootinfo; 463 int n; 464#endif 465#ifdef __i386__ 466 char *tmpbuf; 467 int i, found, dps; 468#endif 469 470 /* XXX */ 471 if (dp->d_secsize == 0) { 472 dp->d_secsize = DEV_BSIZE; 473 dp->d_bbsize = BBSIZE; 474 } 475 lp = (struct disklabel *) 476 (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 477 bzero((char *)lp, sizeof *lp); 478 /* 479 * If we are not installing a boot program but we are installing a 480 * label on disk then we must read the current bootarea so we don't 481 * clobber the existing boot. 482 */ 483 if (!installboot) { 484 if (rflag) { 485 if (read(f, boot, BBSIZE) < BBSIZE) 486 err(4, "%s", specname); 487 bzero((char *)lp, sizeof *lp); 488 } 489 return (lp); 490 } 491 /* 492 * We are installing a boot program. Determine the name(s) and 493 * read them into the appropriate places in the boot area. 494 */ 495 if (!xxboot) { 496 dkbasename = np; 497 if ((p = rindex(dkname, '/')) == NULL) 498 p = dkname; 499 else 500 p++; 501 while (*p && !isdigit(*p)) 502 *np++ = *p++; 503 *np++ = '\0'; 504 505 if (!xxboot) { 506 (void)sprintf(boot0, "%s/boot", _PATH_BOOTDIR); 507 xxboot = boot0; 508 } 509 } 510 511 b = open(xxboot, O_RDONLY); 512 if (b < 0) 513 err(4, "%s", xxboot); 514 if (fstat(b, &sb) != 0) 515 err(4, "%s", xxboot); 516#ifdef __i386__ 517 if (sb.st_size > BBSIZE) 518 errx(4, "%s too large", xxboot); 519 /* 520 * XXX Botch alert. 521 * The i386/PC98 has the so-called fdisk table embedded into the 522 * primary bootstrap. We take care to not clobber it, but 523 * only if it does already contain some data. (Otherwise, 524 * the xxboot provides a template.) 525 */ 526 if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) 527 err(4, "%s", xxboot); 528 memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); 529 530 if (read(b, boot, BBSIZE) < 0) 531 err(4, "%s", xxboot); 532 533 /* XXX: rely on some very precise overlaps in definitions */ 534#ifdef PC98 535 dps = sizeof(struct pc98_partition); 536#else 537 dps = sizeof(struct dos_partition); 538#endif 539 for (i = DOSPARTOFF, found = 0; 540 !found && i < (int)(DOSPARTOFF + NDOSPART * dps); 541 i++) 542 found = tmpbuf[i] != 0; 543 if (found) 544 memcpy((void *)&boot[DOSPARTOFF], 545 (void *)&tmpbuf[DOSPARTOFF], 546 NDOSPART * dps); 547 free(tmpbuf); 548#endif /* __i386__ */ 549 550#ifdef __alpha__ 551 if (sb.st_size > BBSIZE - dp->d_secsize) 552 errx(4, "%s too large", xxboot); 553 /* 554 * On the alpha, the primary bootstrap starts at the 555 * second sector of the boot area. The first sector 556 * contains the label and must be edited to contain the 557 * size and location of the primary bootstrap. 558 */ 559 n = read(b, boot + dp->d_secsize, BBSIZE - dp->d_secsize); 560 if (n < 0) 561 err(4, "%s", xxboot); 562 bootinfo = (u_long *)(boot + 480); 563 bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; 564 bootinfo[1] = 1; /* start at sector 1 */ 565 bootinfo[2] = 0; /* flags (must be zero) */ 566#endif /* __alpha__ */ 567 568 (void)close(b); 569 /* 570 * Make sure no part of the bootstrap is written in the area 571 * reserved for the label. 572 */ 573 for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 574 if (*p) 575 errx(2, "bootstrap doesn't leave room for disk label"); 576 return (lp); 577} 578 579void 580display(FILE *f, const struct disklabel *lp) 581{ 582 int i, j; 583 const struct partition *pp; 584 585 fprintf(f, "# %s:\n", specname); 586 if (lp->d_type < DKMAXTYPES) 587 fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 588 else 589 fprintf(f, "type: %u\n", lp->d_type); 590 fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 591 lp->d_typename); 592 fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 593 lp->d_packname); 594 fprintf(f, "flags:"); 595 if (lp->d_flags & D_REMOVABLE) 596 fprintf(f, " removeable"); 597 if (lp->d_flags & D_ECC) 598 fprintf(f, " ecc"); 599 if (lp->d_flags & D_BADSECT) 600 fprintf(f, " badsect"); 601 fprintf(f, "\n"); 602 fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 603 fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 604 fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 605 fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 606 fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 607 fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 608 fprintf(f, "rpm: %u\n", lp->d_rpm); 609 fprintf(f, "interleave: %u\n", lp->d_interleave); 610 fprintf(f, "trackskew: %u\n", lp->d_trackskew); 611 fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 612 fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 613 (u_long)lp->d_headswitch); 614 fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 615 (u_long)lp->d_trkseek); 616 fprintf(f, "drivedata: "); 617 for (i = NDDATA - 1; i >= 0; i--) 618 if (lp->d_drivedata[i]) 619 break; 620 if (i < 0) 621 i = 0; 622 for (j = 0; j <= i; j++) 623 fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 624 fprintf(f, "\n\n%u partitions:\n", lp->d_npartitions); 625 fprintf(f, 626 "# size offset fstype [fsize bsize bps/cpg]\n"); 627 pp = lp->d_partitions; 628 for (i = 0; i < lp->d_npartitions; i++, pp++) { 629 if (pp->p_size) { 630 fprintf(f, " %c: %8lu %8lu ", 'a' + i, 631 (u_long)pp->p_size, (u_long)pp->p_offset); 632 if (pp->p_fstype < FSMAXTYPES) 633 fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 634 else 635 fprintf(f, "%8d", pp->p_fstype); 636 switch (pp->p_fstype) { 637 638 case FS_UNUSED: /* XXX */ 639 fprintf(f, " %5lu %5lu %5.5s ", 640 (u_long)pp->p_fsize, 641 (u_long)(pp->p_fsize * pp->p_frag), ""); 642 break; 643 644 case FS_BSDFFS: 645 fprintf(f, " %5lu %5lu %5u ", 646 (u_long)pp->p_fsize, 647 (u_long)(pp->p_fsize * pp->p_frag), 648 pp->p_cpg); 649 break; 650 651 case FS_BSDLFS: 652 fprintf(f, " %5lu %5lu %5d", 653 (u_long)pp->p_fsize, 654 (u_long)(pp->p_fsize * pp->p_frag), 655 pp->p_cpg); 656 break; 657 658 default: 659 fprintf(f, "%20.20s", ""); 660 break; 661 } 662 fprintf(f, "\t# (Cyl. %4lu", 663 (u_long)(pp->p_offset / lp->d_secpercyl)); 664 if (pp->p_offset % lp->d_secpercyl) 665 putc('*', f); 666 else 667 putc(' ', f); 668 fprintf(f, "- %lu", 669 (u_long)((pp->p_offset + pp->p_size + 670 lp->d_secpercyl - 1) / 671 lp->d_secpercyl - 1)); 672 if (pp->p_size % lp->d_secpercyl) 673 putc('*', f); 674 fprintf(f, ")\n"); 675 } 676 } 677 fflush(f); 678} 679 680int 681edit(struct disklabel *lp, int f) 682{ 683 int c, fd; 684 struct disklabel label; 685 FILE *fp; 686 687 if ((fd = mkstemp(tmpfil)) == -1 || 688 (fp = fdopen(fd, "w")) == NULL) { 689 warnx("can't create %s", tmpfil); 690 return (1); 691 } 692 display(fp, lp); 693 fclose(fp); 694 for (;;) { 695 if (!editit()) 696 break; 697 fp = fopen(tmpfil, "r"); 698 if (fp == NULL) { 699 warnx("can't reopen %s for reading", tmpfil); 700 break; 701 } 702 bzero((char *)&label, sizeof(label)); 703 if (getasciilabel(fp, &label)) { 704 *lp = label; 705 if (writelabel(f, bootarea, lp) == 0) { 706 fclose(fp); 707 (void) unlink(tmpfil); 708 return (0); 709 } 710 } 711 fclose(fp); 712 printf("re-edit the label? [y]: "); fflush(stdout); 713 c = getchar(); 714 if (c != EOF && c != (int)'\n') 715 while (getchar() != (int)'\n') 716 ; 717 if (c == (int)'n') 718 break; 719 } 720 (void) unlink(tmpfil); 721 return (1); 722} 723 724int 725editit(void) 726{ 727 int pid, xpid; 728 int locstat, omask; 729 const char *ed; 730 731 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 732 while ((pid = fork()) < 0) { 733 if (errno == EPROCLIM) { 734 warnx("you have too many processes"); 735 return(0); 736 } 737 if (errno != EAGAIN) { 738 warn("fork"); 739 return(0); 740 } 741 sleep(1); 742 } 743 if (pid == 0) { 744 sigsetmask(omask); 745 setgid(getgid()); 746 setuid(getuid()); 747 if ((ed = getenv("EDITOR")) == (char *)0) 748 ed = DEFEDITOR; 749 execlp(ed, ed, tmpfil, (char *)0); 750 err(1, "%s", ed); 751 } 752 while ((xpid = wait(&locstat)) >= 0) 753 if (xpid == pid) 754 break; 755 sigsetmask(omask); 756 return(!locstat); 757} 758 759char * 760skip(char *cp) 761{ 762 763 while (*cp != '\0' && isspace(*cp)) 764 cp++; 765 if (*cp == '\0' || *cp == '#') 766 return (NULL); 767 return (cp); 768} 769 770char * 771word(char *cp) 772{ 773 char c; 774 775 while (*cp != '\0' && !isspace(*cp) && *cp != '#') 776 cp++; 777 if ((c = *cp) != '\0') { 778 *cp++ = '\0'; 779 if (c != '#') 780 return (skip(cp)); 781 } 782 return (NULL); 783} 784 785/* 786 * Read an ascii label in from fd f, 787 * in the same format as that put out by display(), 788 * and fill in lp. 789 */ 790int 791getasciilabel(FILE *f, struct disklabel *lp) 792{ 793 char *cp; 794 const char **cpp; 795 u_int part; 796 char *tp, line[BUFSIZ]; 797 u_long v; 798 int lineno = 0, errors = 0; 799 int i; 800 801 bzero(&part_set, sizeof(part_set)); 802 bzero(&part_size_type, sizeof(part_size_type)); 803 bzero(&part_offset_type, sizeof(part_offset_type)); 804 lp->d_bbsize = BBSIZE; /* XXX */ 805 lp->d_sbsize = 0; /* XXX */ 806 while (fgets(line, sizeof(line) - 1, f)) { 807 lineno++; 808 if ((cp = index(line,'\n')) != 0) 809 *cp = '\0'; 810 cp = skip(line); 811 if (cp == NULL) 812 continue; 813 tp = index(cp, ':'); 814 if (tp == NULL) { 815 fprintf(stderr, "line %d: syntax error\n", lineno); 816 errors++; 817 continue; 818 } 819 *tp++ = '\0', tp = skip(tp); 820 if (streq(cp, "type")) { 821 if (tp == NULL) 822 tp = unknown; 823 cpp = dktypenames; 824 for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 825 if (*cpp && streq(*cpp, tp)) { 826 lp->d_type = cpp - dktypenames; 827 break; 828 } 829 if (cpp < &dktypenames[DKMAXTYPES]) 830 continue; 831 v = strtoul(tp, NULL, 10); 832 if (v >= DKMAXTYPES) 833 fprintf(stderr, "line %d:%s %lu\n", lineno, 834 "Warning, unknown disk type", v); 835 lp->d_type = v; 836 continue; 837 } 838 if (streq(cp, "flags")) { 839 for (v = 0; (cp = tp) && *cp != '\0';) { 840 tp = word(cp); 841 if (streq(cp, "removeable")) 842 v |= D_REMOVABLE; 843 else if (streq(cp, "ecc")) 844 v |= D_ECC; 845 else if (streq(cp, "badsect")) 846 v |= D_BADSECT; 847 else { 848 fprintf(stderr, 849 "line %d: %s: bad flag\n", 850 lineno, cp); 851 errors++; 852 } 853 } 854 lp->d_flags = v; 855 continue; 856 } 857 if (streq(cp, "drivedata")) { 858 for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 859 lp->d_drivedata[i++] = strtoul(cp, NULL, 10); 860 tp = word(cp); 861 } 862 continue; 863 } 864 if (sscanf(cp, "%lu partitions", &v) == 1) { 865 if (v == 0 || v > MAXPARTITIONS) { 866 fprintf(stderr, 867 "line %d: bad # of partitions\n", lineno); 868 lp->d_npartitions = MAXPARTITIONS; 869 errors++; 870 } else 871 lp->d_npartitions = v; 872 continue; 873 } 874 if (tp == NULL) 875 tp = blank; 876 if (streq(cp, "disk")) { 877 strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 878 continue; 879 } 880 if (streq(cp, "label")) { 881 strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 882 continue; 883 } 884 if (streq(cp, "bytes/sector")) { 885 v = strtoul(tp, NULL, 10); 886 if (v == 0 || (v % DEV_BSIZE) != 0) { 887 fprintf(stderr, 888 "line %d: %s: bad sector size\n", 889 lineno, tp); 890 errors++; 891 } else 892 lp->d_secsize = v; 893 continue; 894 } 895 if (streq(cp, "sectors/track")) { 896 v = strtoul(tp, NULL, 10); 897#if (ULONG_MAX != 0xffffffffUL) 898 if (v == 0 || v > 0xffffffff) { 899#else 900 if (v == 0) { 901#endif 902 fprintf(stderr, "line %d: %s: bad %s\n", 903 lineno, tp, cp); 904 errors++; 905 } else 906 lp->d_nsectors = v; 907 continue; 908 } 909 if (streq(cp, "sectors/cylinder")) { 910 v = strtoul(tp, NULL, 10); 911 if (v == 0) { 912 fprintf(stderr, "line %d: %s: bad %s\n", 913 lineno, tp, cp); 914 errors++; 915 } else 916 lp->d_secpercyl = v; 917 continue; 918 } 919 if (streq(cp, "tracks/cylinder")) { 920 v = strtoul(tp, NULL, 10); 921 if (v == 0) { 922 fprintf(stderr, "line %d: %s: bad %s\n", 923 lineno, tp, cp); 924 errors++; 925 } else 926 lp->d_ntracks = v; 927 continue; 928 } 929 if (streq(cp, "cylinders")) { 930 v = strtoul(tp, NULL, 10); 931 if (v == 0) { 932 fprintf(stderr, "line %d: %s: bad %s\n", 933 lineno, tp, cp); 934 errors++; 935 } else 936 lp->d_ncylinders = v; 937 continue; 938 } 939 if (streq(cp, "sectors/unit")) { 940 v = strtoul(tp, NULL, 10); 941 if (v == 0) { 942 fprintf(stderr, "line %d: %s: bad %s\n", 943 lineno, tp, cp); 944 errors++; 945 } else 946 lp->d_secperunit = v; 947 continue; 948 } 949 if (streq(cp, "rpm")) { 950 v = strtoul(tp, NULL, 10); 951 if (v == 0 || v > USHRT_MAX) { 952 fprintf(stderr, "line %d: %s: bad %s\n", 953 lineno, tp, cp); 954 errors++; 955 } else 956 lp->d_rpm = v; 957 continue; 958 } 959 if (streq(cp, "interleave")) { 960 v = strtoul(tp, NULL, 10); 961 if (v == 0 || v > USHRT_MAX) { 962 fprintf(stderr, "line %d: %s: bad %s\n", 963 lineno, tp, cp); 964 errors++; 965 } else 966 lp->d_interleave = v; 967 continue; 968 } 969 if (streq(cp, "trackskew")) { 970 v = strtoul(tp, NULL, 10); 971 if (v > USHRT_MAX) { 972 fprintf(stderr, "line %d: %s: bad %s\n", 973 lineno, tp, cp); 974 errors++; 975 } else 976 lp->d_trackskew = v; 977 continue; 978 } 979 if (streq(cp, "cylinderskew")) { 980 v = strtoul(tp, NULL, 10); 981 if (v > USHRT_MAX) { 982 fprintf(stderr, "line %d: %s: bad %s\n", 983 lineno, tp, cp); 984 errors++; 985 } else 986 lp->d_cylskew = v; 987 continue; 988 } 989 if (streq(cp, "headswitch")) { 990 v = strtoul(tp, NULL, 10); 991 lp->d_headswitch = v; 992 continue; 993 } 994 if (streq(cp, "track-to-track seek")) { 995 v = strtoul(tp, NULL, 10); 996 lp->d_trkseek = v; 997 continue; 998 } 999 /* the ':' was removed above */ 1000 if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') { 1001 fprintf(stderr, 1002 "line %d: %s: Unknown disklabel field\n", lineno, 1003 cp); 1004 errors++; 1005 continue; 1006 } 1007 1008 /* Process a partition specification line. */ 1009 part = *cp - 'a'; 1010 if (part >= lp->d_npartitions) { 1011 fprintf(stderr, 1012 "line %d: partition name out of range a-%c: %s\n", 1013 lineno, 'a' + lp->d_npartitions - 1, cp); 1014 errors++; 1015 continue; 1016 } 1017 part_set[part] = 1; 1018 1019 if (getasciipartspec(tp, lp, part, lineno) != 0) { 1020 errors++; 1021 break; 1022 } 1023 } 1024 errors += checklabel(lp); 1025 return (errors == 0); 1026} 1027 1028#define NXTNUM(n) do { \ 1029 if (tp == NULL) { \ 1030 fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 1031 return (1); \ 1032 } else { \ 1033 cp = tp, tp = word(cp); \ 1034 (n) = strtoul(cp, NULL, 10); \ 1035 } \ 1036} while (0) 1037 1038/* retain 1 character following number */ 1039#define NXTWORD(w,n) do { \ 1040 if (tp == NULL) { \ 1041 fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 1042 return (1); \ 1043 } else { \ 1044 char *tmp; \ 1045 cp = tp, tp = word(cp); \ 1046 (n) = strtoul(cp, &tmp, 10); \ 1047 if (tmp) (w) = *tmp; \ 1048 } \ 1049} while (0) 1050 1051/* 1052 * Read a partition line into partition `part' in the specified disklabel. 1053 * Return 0 on success, 1 on failure. 1054 */ 1055int 1056getasciipartspec(char *tp, struct disklabel *lp, int part, int lineno) 1057{ 1058 struct partition *pp; 1059 char *cp; 1060 const char **cpp; 1061 u_long v; 1062 1063 pp = &lp->d_partitions[part]; 1064 cp = NULL; 1065 1066 v = 0; 1067 NXTWORD(part_size_type[part],v); 1068 if (v == 0 && part_size_type[part] != '*') { 1069 fprintf(stderr, 1070 "line %d: %s: bad partition size\n", lineno, cp); 1071 return (1); 1072 } 1073 pp->p_size = v; 1074 1075 v = 0; 1076 NXTWORD(part_offset_type[part],v); 1077 if (v == 0 && part_offset_type[part] != '*' && 1078 part_offset_type[part] != '\0') { 1079 fprintf(stderr, 1080 "line %d: %s: bad partition offset\n", lineno, cp); 1081 return (1); 1082 } 1083 pp->p_offset = v; 1084 cp = tp, tp = word(cp); 1085 for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) 1086 if (*cpp && streq(*cpp, cp)) 1087 break; 1088 if (*cpp != NULL) { 1089 pp->p_fstype = cpp - fstypenames; 1090 } else { 1091 if (isdigit(*cp)) 1092 v = strtoul(cp, NULL, 10); 1093 else 1094 v = FSMAXTYPES; 1095 if (v >= FSMAXTYPES) { 1096 fprintf(stderr, 1097 "line %d: Warning, unknown file system type %s\n", 1098 lineno, cp); 1099 v = FS_UNUSED; 1100 } 1101 pp->p_fstype = v; 1102 } 1103 1104 switch (pp->p_fstype) { 1105 case FS_UNUSED: 1106 /* 1107 * allow us to accept defaults for 1108 * fsize/frag/cpg 1109 */ 1110 if (tp) { 1111 NXTNUM(pp->p_fsize); 1112 if (pp->p_fsize == 0) 1113 break; 1114 NXTNUM(v); 1115 pp->p_frag = v / pp->p_fsize; 1116 } 1117 /* else default to 0's */ 1118 break; 1119 1120 /* These happen to be the same */ 1121 case FS_BSDFFS: 1122 case FS_BSDLFS: 1123 if (tp) { 1124 NXTNUM(pp->p_fsize); 1125 if (pp->p_fsize == 0) 1126 break; 1127 NXTNUM(v); 1128 pp->p_frag = v / pp->p_fsize; 1129 NXTNUM(pp->p_cpg); 1130 } else { 1131 /* 1132 * FIX! poor attempt at adaptive 1133 */ 1134 /* 1 GB */ 1135 if (pp->p_size < 1024*1024*1024 / lp->d_secsize) { 1136 /* 1137 * FIX! These are too low, but are traditional 1138 */ 1139 pp->p_fsize = DEFAULT_NEWFS_FRAG; 1140 pp->p_frag = DEFAULT_NEWFS_BLOCK / 1141 DEFAULT_NEWFS_FRAG; 1142 pp->p_cpg = DEFAULT_NEWFS_CPG; 1143 } else { 1144 pp->p_fsize = BIG_NEWFS_FRAG; 1145 pp->p_frag = BIG_NEWFS_BLOCK / 1146 BIG_NEWFS_FRAG; 1147 pp->p_cpg = BIG_NEWFS_CPG; 1148 } 1149 } 1150 default: 1151 break; 1152 } 1153 return (0); 1154} 1155 1156/* 1157 * Check disklabel for errors and fill in 1158 * derived fields according to supplied values. 1159 */ 1160int 1161checklabel(struct disklabel *lp) 1162{ 1163 struct partition *pp; 1164 int i, errors = 0; 1165 char part; 1166 u_long total_size, total_percent, current_offset; 1167 int seen_default_offset; 1168 int hog_part; 1169 int j; 1170 struct partition *pp2; 1171 1172 if (lp->d_secsize == 0) { 1173 fprintf(stderr, "sector size 0\n"); 1174 return (1); 1175 } 1176 if (lp->d_nsectors == 0) { 1177 fprintf(stderr, "sectors/track 0\n"); 1178 return (1); 1179 } 1180 if (lp->d_ntracks == 0) { 1181 fprintf(stderr, "tracks/cylinder 0\n"); 1182 return (1); 1183 } 1184 if (lp->d_ncylinders == 0) { 1185 fprintf(stderr, "cylinders/unit 0\n"); 1186 errors++; 1187 } 1188 if (lp->d_rpm == 0) 1189 Warning("revolutions/minute 0"); 1190 if (lp->d_secpercyl == 0) 1191 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1192 if (lp->d_secperunit == 0) 1193 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1194 if (lp->d_bbsize == 0) { 1195 fprintf(stderr, "boot block size 0\n"); 1196 errors++; 1197 } else if (lp->d_bbsize % lp->d_secsize) 1198 Warning("boot block size %% sector-size != 0"); 1199 if (lp->d_npartitions > MAXPARTITIONS) 1200 Warning("number of partitions (%lu) > MAXPARTITIONS (%d)", 1201 (u_long)lp->d_npartitions, MAXPARTITIONS); 1202 1203 /* first allocate space to the partitions, then offsets */ 1204 total_size = 0; /* in sectors */ 1205 total_percent = 0; /* in percent */ 1206 hog_part = -1; 1207 /* find all fixed partitions */ 1208 for (i = 0; i < lp->d_npartitions; i++) { 1209 pp = &lp->d_partitions[i]; 1210 if (part_set[i]) { 1211 if (part_size_type[i] == '*') { 1212 if (i == RAW_PART) { 1213 pp->p_size = lp->d_secperunit; 1214 } else { 1215 if (hog_part != -1) 1216 Warning("Too many '*' partitions (%c and %c)", 1217 hog_part + 'a',i + 'a'); 1218 else 1219 hog_part = i; 1220 } 1221 } else { 1222 off_t size; 1223 1224 size = pp->p_size; 1225 switch (part_size_type[i]) { 1226 case '%': 1227 total_percent += size; 1228 break; 1229 case 'k': 1230 case 'K': 1231 size *= 1024ULL; 1232 break; 1233 case 'm': 1234 case 'M': 1235 size *= 1024ULL * 1024ULL; 1236 break; 1237 case 'g': 1238 case 'G': 1239 size *= 1024ULL * 1024ULL * 1024ULL; 1240 break; 1241 case '\0': 1242 break; 1243 default: 1244 Warning("unknown size specifier '%c' (K/M/G are valid)",part_size_type[i]); 1245 break; 1246 } 1247 /* don't count %'s yet */ 1248 if (part_size_type[i] != '%') { 1249 /* 1250 * for all not in sectors, convert to 1251 * sectors 1252 */ 1253 if (part_size_type[i] != '\0') { 1254 if (size % lp->d_secsize != 0) 1255 Warning("partition %c not an integer number of sectors", 1256 i + 'a'); 1257 size /= lp->d_secsize; 1258 pp->p_size = size; 1259 } 1260 /* else already in sectors */ 1261 if (i != RAW_PART) 1262 total_size += size; 1263 } 1264 } 1265 } 1266 } 1267 /* handle % partitions - note %'s don't need to add up to 100! */ 1268 if (total_percent != 0) { 1269 long free_space = lp->d_secperunit - total_size; 1270 if (total_percent > 100) { 1271 fprintf(stderr,"total percentage %lu is greater than 100\n", 1272 total_percent); 1273 errors++; 1274 } 1275 1276 if (free_space > 0) { 1277 for (i = 0; i < lp->d_npartitions; i++) { 1278 pp = &lp->d_partitions[i]; 1279 if (part_set[i] && part_size_type[i] == '%') { 1280 /* careful of overflows! and integer roundoff */ 1281 pp->p_size = ((double)pp->p_size/100) * free_space; 1282 total_size += pp->p_size; 1283 1284 /* FIX we can lose a sector or so due to roundoff per 1285 partition. A more complex algorithm could avoid that */ 1286 } 1287 } 1288 } else { 1289 fprintf(stderr, 1290 "%ld sectors available to give to '*' and '%%' partitions\n", 1291 free_space); 1292 errors++; 1293 /* fix? set all % partitions to size 0? */ 1294 } 1295 } 1296 /* give anything remaining to the hog partition */ 1297 if (hog_part != -1) { 1298 lp->d_partitions[hog_part].p_size = lp->d_secperunit - total_size; 1299 total_size = lp->d_secperunit; 1300 } 1301 1302 /* Now set the offsets for each partition */ 1303 current_offset = 0; /* in sectors */ 1304 seen_default_offset = 0; 1305 for (i = 0; i < lp->d_npartitions; i++) { 1306 part = 'a' + i; 1307 pp = &lp->d_partitions[i]; 1308 if (part_set[i]) { 1309 if (part_offset_type[i] == '*') { 1310 if (i == RAW_PART) { 1311 pp->p_offset = 0; 1312 } else { 1313 pp->p_offset = current_offset; 1314 seen_default_offset = 1; 1315 } 1316 } else { 1317 /* allow them to be out of order for old-style tables */ 1318 if (pp->p_offset < current_offset && 1319 seen_default_offset && i != RAW_PART && 1320 pp->p_fstype != FS_VINUM) { 1321 fprintf(stderr, 1322"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 1323 (long)pp->p_offset,i+'a',current_offset); 1324 fprintf(stderr, 1325"Labels with any *'s for offset must be in ascending order by sector\n"); 1326 errors++; 1327 } else if (pp->p_offset != current_offset && 1328 i != RAW_PART && seen_default_offset) { 1329 /* 1330 * this may give unneeded warnings if 1331 * partitions are out-of-order 1332 */ 1333 Warning( 1334"Offset %ld for partition %c doesn't match expected value %ld", 1335 (long)pp->p_offset, i + 'a', current_offset); 1336 } 1337 } 1338 if (i != RAW_PART) 1339 current_offset = pp->p_offset + pp->p_size; 1340 } 1341 } 1342 1343 for (i = 0; i < lp->d_npartitions; i++) { 1344 part = 'a' + i; 1345 pp = &lp->d_partitions[i]; 1346 if (pp->p_size == 0 && pp->p_offset != 0) 1347 Warning("partition %c: size 0, but offset %lu", 1348 part, (u_long)pp->p_offset); 1349#ifdef notdef 1350 if (pp->p_size % lp->d_secpercyl) 1351 Warning("partition %c: size %% cylinder-size != 0", 1352 part); 1353 if (pp->p_offset % lp->d_secpercyl) 1354 Warning("partition %c: offset %% cylinder-size != 0", 1355 part); 1356#endif 1357 if (pp->p_offset > lp->d_secperunit) { 1358 fprintf(stderr, 1359 "partition %c: offset past end of unit\n", part); 1360 errors++; 1361 } 1362 if (pp->p_offset + pp->p_size > lp->d_secperunit) { 1363 fprintf(stderr, 1364 "partition %c: partition extends past end of unit\n", 1365 part); 1366 errors++; 1367 } 1368 if (i == RAW_PART) 1369 { 1370 if (pp->p_fstype != FS_UNUSED) 1371 Warning("partition %c is not marked as unused!",part); 1372 if (pp->p_offset != 0) 1373 Warning("partition %c doesn't start at 0!",part); 1374 if (pp->p_size != lp->d_secperunit) 1375 Warning("partition %c doesn't cover the whole unit!",part); 1376 1377 if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 1378 (pp->p_size != lp->d_secperunit)) { 1379 Warning("An incorrect partition %c may cause problems for " 1380 "standard system utilities",part); 1381 } 1382 } 1383 1384 /* check for overlaps */ 1385 /* this will check for all possible overlaps once and only once */ 1386 for (j = 0; j < i; j++) { 1387 pp2 = &lp->d_partitions[j]; 1388 if (j != RAW_PART && i != RAW_PART && 1389 pp->p_fstype != FS_VINUM && 1390 pp2->p_fstype != FS_VINUM && 1391 part_set[i] && part_set[j]) { 1392 if (pp2->p_offset < pp->p_offset + pp->p_size && 1393 (pp2->p_offset + pp2->p_size > pp->p_offset || 1394 pp2->p_offset >= pp->p_offset)) { 1395 fprintf(stderr,"partitions %c and %c overlap!\n", 1396 j + 'a', i + 'a'); 1397 errors++; 1398 } 1399 } 1400 } 1401 } 1402 for (; i < MAXPARTITIONS; i++) { 1403 part = 'a' + i; 1404 pp = &lp->d_partitions[i]; 1405 if (pp->p_size || pp->p_offset) 1406 Warning("unused partition %c: size %d offset %lu", 1407 'a' + i, pp->p_size, (u_long)pp->p_offset); 1408 } 1409 return (errors); 1410} 1411 1412/* 1413 * When operating on a "virgin" disk, try getting an initial label 1414 * from the associated device driver. This might work for all device 1415 * drivers that are able to fetch some initial device parameters 1416 * without even having access to a (BSD) disklabel, like SCSI disks, 1417 * most IDE drives, or vn devices. 1418 * 1419 * The device name must be given in its "canonical" form. 1420 */ 1421struct disklabel * 1422getvirginlabel(void) 1423{ 1424 static struct disklabel loclab; 1425 struct partition *dp; 1426 char lnamebuf[BBSIZE]; 1427 int f; 1428 u_int secsize, u; 1429 off_t mediasize; 1430 1431 if (dkname[0] == '/') { 1432 warnx("\"auto\" requires the usage of a canonical disk name"); 1433 return (NULL); 1434 } 1435 (void)snprintf(lnamebuf, BBSIZE, "%s%s", _PATH_DEV, dkname); 1436 if ((f = open(lnamebuf, O_RDONLY)) == -1) { 1437 warn("cannot open %s", lnamebuf); 1438 return (NULL); 1439 } 1440 1441 /* New world order */ 1442 if ((ioctl(f, DIOCGMEDIASIZE, &mediasize) != 0) || 1443 (ioctl(f, DIOCGSECTORSIZE, &secsize) != 0)) { 1444 close (f); 1445 return (NULL); 1446 } 1447 memset(&loclab, 0, sizeof loclab); 1448 loclab.d_magic = DISKMAGIC; 1449 loclab.d_magic2 = DISKMAGIC; 1450 loclab.d_secsize = secsize; 1451 loclab.d_secperunit = mediasize / secsize; 1452 1453 /* 1454 * Nobody in these enligthened days uses the CHS geometry for 1455 * anything, but nontheless try to get it right. If we fail 1456 * to get any good ideas from the device, construct something 1457 * which is IBM-PC friendly. 1458 */ 1459 if (ioctl(f, DIOCGFWSECTORS, &u) == 0) 1460 loclab.d_nsectors = u; 1461 else 1462 loclab.d_nsectors = 63; 1463 if (ioctl(f, DIOCGFWHEADS, &u) == 0) 1464 loclab.d_ntracks = u; 1465 else if (loclab.d_secperunit <= 63*1*1024) 1466 loclab.d_ntracks = 1; 1467 else if (loclab.d_secperunit <= 63*16*1024) 1468 loclab.d_ntracks = 16; 1469 else 1470 loclab.d_ntracks = 255; 1471 loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors; 1472 loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl; 1473 loclab.d_npartitions = MAXPARTITIONS; 1474 1475 /* Various (unneeded) compat stuff */ 1476 loclab.d_rpm = 3600; 1477 loclab.d_bbsize = BBSIZE; 1478 loclab.d_interleave = 1;; 1479 strncpy(loclab.d_typename, "amnesiac", 1480 sizeof(loclab.d_typename)); 1481 1482 dp = &loclab.d_partitions[RAW_PART]; 1483 dp->p_size = loclab.d_secperunit; 1484 loclab.d_checksum = dkcksum(&loclab); 1485 close (f); 1486 return (&loclab); 1487} 1488 1489 1490/*VARARGS1*/ 1491void 1492Warning(const char *fmt, ...) 1493{ 1494 va_list ap; 1495 1496 fprintf(stderr, "Warning, "); 1497 va_start(ap, fmt); 1498 vfprintf(stderr, fmt, ap); 1499 fprintf(stderr, "\n"); 1500 va_end(ap); 1501} 1502 1503void 1504usage(void) 1505{ 1506 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 1507 "usage: disklabel [-r] disk", 1508 "\t\t(to read label)", 1509 " disklabel -w [-r] [-n] disk type [ packid ]", 1510 "\t\t(to write label with existing boot program)", 1511 " disklabel -e [-r] [-n] disk", 1512 "\t\t(to edit label)", 1513 " disklabel -R [-r] [-n] disk protofile", 1514 "\t\t(to restore label with existing boot program)", 1515 " disklabel -B [-n] [ -b bootprog ] disk [ type ]", 1516 "\t\t(to install boot program with existing on-disk label)", 1517 " disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", 1518 "\t\t(to write label and install boot program)", 1519 " disklabel -R -B [-n] [ -b bootprog ] disk protofile [ type ]", 1520 "\t\t(to restore label and install boot program)" 1521 ); 1522 exit(1); 1523} 1524