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