bsdlabel.c revision 73034
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1987, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * This code is derived from software contributed to Berkeley by 61558Srgrimes * Symmetric Computer Systems. 71558Srgrimes * 81558Srgrimes * Redistribution and use in source and binary forms, with or without 91558Srgrimes * modification, are permitted provided that the following conditions 101558Srgrimes * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. All advertising materials mentioning features or use of this software 171558Srgrimes * must display the following acknowledgement: 181558Srgrimes * This product includes software developed by the University of 191558Srgrimes * California, Berkeley and its contributors. 201558Srgrimes * 4. Neither the name of the University nor the names of its contributors 211558Srgrimes * may be used to endorse or promote products derived from this software 221558Srgrimes * without specific prior written permission. 231558Srgrimes * 241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341558Srgrimes * SUCH DAMAGE. 351558Srgrimes */ 361558Srgrimes 371558Srgrimes#ifndef lint 3836632Scharnierstatic const char copyright[] = 391558Srgrimes"@(#) Copyright (c) 1987, 1993\n\ 401558Srgrimes The Regents of the University of California. All rights reserved.\n"; 411558Srgrimes#endif /* not lint */ 421558Srgrimes 431558Srgrimes#ifndef lint 4436632Scharnier#if 0 451558Srgrimesstatic char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; 461558Srgrimes/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 4736632Scharnier#endif 4836632Scharnierstatic const char rcsid[] = 4950476Speter "$FreeBSD: head/sbin/bsdlabel/bsdlabel.c 73034 2001-02-25 16:47:44Z jwd $"; 501558Srgrimes#endif /* not lint */ 511558Srgrimes 521558Srgrimes#include <sys/param.h> 531558Srgrimes#include <sys/file.h> 541558Srgrimes#include <sys/stat.h> 5513544Sjoerg#include <sys/wait.h> 561558Srgrimes#define DKTYPENAMES 571558Srgrimes#include <sys/disklabel.h> 581558Srgrimes#include <ufs/ffs/fs.h> 591558Srgrimes#include <unistd.h> 601558Srgrimes#include <string.h> 611558Srgrimes#include <stdio.h> 6213544Sjoerg#include <stdlib.h> 6313544Sjoerg#include <signal.h> 6413544Sjoerg#include <stdarg.h> 651558Srgrimes#include <ctype.h> 6626542Scharnier#include <err.h> 6759216Simp#include <errno.h> 681558Srgrimes#include "pathnames.h" 691558Srgrimes 701558Srgrimes/* 711558Srgrimes * Disklabel: read and write disklabels. 721558Srgrimes * The label is usually placed on one of the first sectors of the disk. 731558Srgrimes * Many machines also place a bootstrap in the same area, 741558Srgrimes * in which case the label is embedded in the bootstrap. 751558Srgrimes * The bootstrap source must leave space at the proper offset 761558Srgrimes * for the label on such machines. 771558Srgrimes */ 781558Srgrimes 791558Srgrimes#ifndef BBSIZE 801558Srgrimes#define BBSIZE 8192 /* size of boot area, with label */ 811558Srgrimes#endif 821558Srgrimes 8373034Sjwd/* FIX! These are too low, but are traditional */ 8473034Sjwd#define DEFAULT_NEWFS_BLOCK 8192U 8573034Sjwd#define DEFAULT_NEWFS_FRAG 1024U 8673034Sjwd#define DEFAULT_NEWFS_CPG 16U 8773034Sjwd 8873034Sjwd#define BIG_NEWFS_BLOCK 16384U 8973034Sjwd#define BIG_NEWFS_FRAG 4096U 9073034Sjwd#define BIG_NEWFS_CPG 64U 9173034Sjwd 921558Srgrimes#ifdef tahoe 931558Srgrimes#define NUMBOOT 0 941558Srgrimes#else 9538411Sbde#if defined(__alpha__) || defined(hp300) || defined(hp800) 961558Srgrimes#define NUMBOOT 1 971558Srgrimes#else 981558Srgrimes#define NUMBOOT 2 991558Srgrimes#endif 1001558Srgrimes#endif 1011558Srgrimes 10213544Sjoergvoid makelabel __P((char *, char *, struct disklabel *)); 10313544Sjoergint writelabel __P((int, char *, struct disklabel *)); 10413544Sjoergvoid l_perror __P((char *)); 10513544Sjoergstruct disklabel * readlabel __P((int)); 10613544Sjoergstruct disklabel * makebootarea __P((char *, struct disklabel *, int)); 10713544Sjoergvoid display __P((FILE *, struct disklabel *)); 10813544Sjoergint edit __P((struct disklabel *, int)); 10913544Sjoergint editit __P((void)); 11013544Sjoergchar * skip __P((char *)); 11113544Sjoergchar * word __P((char *)); 11213544Sjoergint getasciilabel __P((FILE *, struct disklabel *)); 11313544Sjoergint checklabel __P((struct disklabel *)); 11413544Sjoergvoid setbootflag __P((struct disklabel *)); 11513544Sjoergvoid Warning (char *, ...); 11613544Sjoergvoid usage __P((void)); 11713550Sjoergstruct disklabel * getvirginlabel __P((void)); 11813544Sjoerg 1191558Srgrimes#define DEFEDITOR _PATH_VI 1201558Srgrimes#define streq(a,b) (strcmp(a,b) == 0) 1211558Srgrimes 1221558Srgrimeschar *dkname; 1231558Srgrimeschar *specname; 12455742Skrischar tmpfil[] = PATH_TMPFILE; 1251558Srgrimes 1261558Srgrimeschar namebuf[BBSIZE], *np = namebuf; 1271558Srgrimesstruct disklabel lab; 1281558Srgrimeschar bootarea[BBSIZE]; 1291558Srgrimes 13073034Sjwd/* partition 'c' is the full disk and is special */ 13173034Sjwd#define FULL_DISK_PART 2 13273034Sjwd#define MAX_PART ('z') 13373034Sjwd#define MAX_NUM_PARTS (1 + MAX_PART - 'a') 13473034Sjwdchar part_size_type[MAX_NUM_PARTS]; 13573034Sjwdchar part_offset_type[MAX_NUM_PARTS]; 13673034Sjwdint part_set[MAX_NUM_PARTS]; 13773034Sjwd 1381558Srgrimes#if NUMBOOT > 0 1391558Srgrimesint installboot; /* non-zero if we should install a boot program */ 1401558Srgrimeschar *bootbuf; /* pointer to buffer with remainder of boot prog */ 1411558Srgrimesint bootsize; /* size of remaining boot program */ 1421558Srgrimeschar *xxboot; /* primary boot */ 1431558Srgrimeschar *bootxx; /* secondary boot */ 1441558Srgrimeschar boot0[MAXPATHLEN]; 1451558Srgrimeschar boot1[MAXPATHLEN]; 1461558Srgrimes#endif 1471558Srgrimes 1481558Srgrimesenum { 1491558Srgrimes UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT 1501558Srgrimes} op = UNSPEC; 1511558Srgrimes 1521558Srgrimesint rflag; 15373034Sjwdint disable_write; /* set to disable writing to disk label */ 1541558Srgrimes 1551558Srgrimes#ifdef DEBUG 1561558Srgrimesint debug; 15773034Sjwd#define OPTIONS "BNRWb:denrs:w" 1581558Srgrimes#else 15973034Sjwd#define OPTIONS "BNRWb:enrs:w" 1601558Srgrimes#endif 1611558Srgrimes 16213544Sjoergint 1631558Srgrimesmain(argc, argv) 1641558Srgrimes int argc; 1651558Srgrimes char *argv[]; 1661558Srgrimes{ 1671558Srgrimes register struct disklabel *lp; 1681558Srgrimes FILE *t; 16948957Sbillf int ch, f = 0, flag, error = 0; 1701558Srgrimes char *name = 0; 1711558Srgrimes 17224359Simp while ((ch = getopt(argc, argv, OPTIONS)) != -1) 1731558Srgrimes switch (ch) { 1741558Srgrimes#if NUMBOOT > 0 1751558Srgrimes case 'B': 1761558Srgrimes ++installboot; 1771558Srgrimes break; 1781558Srgrimes case 'b': 1791558Srgrimes xxboot = optarg; 1801558Srgrimes break; 1811558Srgrimes#if NUMBOOT > 1 1821558Srgrimes case 's': 1831558Srgrimes bootxx = optarg; 1841558Srgrimes break; 1851558Srgrimes#endif 1861558Srgrimes#endif 1871558Srgrimes case 'N': 1881558Srgrimes if (op != UNSPEC) 1891558Srgrimes usage(); 1901558Srgrimes op = NOWRITE; 1911558Srgrimes break; 19273034Sjwd case 'n': 19373034Sjwd disable_write = 1; 19473034Sjwd break; 1951558Srgrimes case 'R': 1961558Srgrimes if (op != UNSPEC) 1971558Srgrimes usage(); 1981558Srgrimes op = RESTORE; 1991558Srgrimes break; 2001558Srgrimes case 'W': 2011558Srgrimes if (op != UNSPEC) 2021558Srgrimes usage(); 2031558Srgrimes op = WRITEABLE; 2041558Srgrimes break; 2051558Srgrimes case 'e': 2061558Srgrimes if (op != UNSPEC) 2071558Srgrimes usage(); 2081558Srgrimes op = EDIT; 2091558Srgrimes break; 2101558Srgrimes case 'r': 2111558Srgrimes ++rflag; 2121558Srgrimes break; 2131558Srgrimes case 'w': 2141558Srgrimes if (op != UNSPEC) 2151558Srgrimes usage(); 2161558Srgrimes op = WRITE; 2171558Srgrimes break; 2181558Srgrimes#ifdef DEBUG 2191558Srgrimes case 'd': 2201558Srgrimes debug++; 2211558Srgrimes break; 2221558Srgrimes#endif 2231558Srgrimes case '?': 2241558Srgrimes default: 2251558Srgrimes usage(); 2261558Srgrimes } 2271558Srgrimes argc -= optind; 2281558Srgrimes argv += optind; 2291558Srgrimes#if NUMBOOT > 0 2301558Srgrimes if (installboot) { 2311558Srgrimes rflag++; 2321558Srgrimes if (op == UNSPEC) 2331558Srgrimes op = WRITEBOOT; 2341558Srgrimes } else { 2351558Srgrimes if (op == UNSPEC) 2361558Srgrimes op = READ; 2371558Srgrimes xxboot = bootxx = 0; 2381558Srgrimes } 2391558Srgrimes#else 2401558Srgrimes if (op == UNSPEC) 2411558Srgrimes op = READ; 2421558Srgrimes#endif 2431558Srgrimes if (argc < 1) 2441558Srgrimes usage(); 2451558Srgrimes 2461558Srgrimes dkname = argv[0]; 2471558Srgrimes if (dkname[0] != '/') { 24859114Sobrien (void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); 2491558Srgrimes specname = np; 2501558Srgrimes np += strlen(specname) + 1; 2511558Srgrimes } else 2521558Srgrimes specname = dkname; 2531558Srgrimes f = open(specname, op == READ ? O_RDONLY : O_RDWR); 2541558Srgrimes if (f < 0 && errno == ENOENT && dkname[0] != '/') { 25559429Sobrien (void)sprintf(specname, "%s%s", _PATH_DEV, dkname); 2561558Srgrimes np = namebuf + strlen(specname) + 1; 2571558Srgrimes f = open(specname, op == READ ? O_RDONLY : O_RDWR); 2581558Srgrimes } 2591558Srgrimes if (f < 0) 26026542Scharnier err(4, "%s", specname); 2611558Srgrimes 2621558Srgrimes switch(op) { 2631558Srgrimes 26448957Sbillf case UNSPEC: 26548957Sbillf break; 26648957Sbillf 2671558Srgrimes case EDIT: 2681558Srgrimes if (argc != 1) 2691558Srgrimes usage(); 2701558Srgrimes lp = readlabel(f); 2711558Srgrimes error = edit(lp, f); 2721558Srgrimes break; 2731558Srgrimes 2741558Srgrimes case NOWRITE: 2751558Srgrimes flag = 0; 2761558Srgrimes if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 27726542Scharnier err(4, "ioctl DIOCWLABEL"); 2781558Srgrimes break; 2791558Srgrimes 2801558Srgrimes case READ: 2811558Srgrimes if (argc != 1) 2821558Srgrimes usage(); 2831558Srgrimes lp = readlabel(f); 2841558Srgrimes display(stdout, lp); 2851558Srgrimes error = checklabel(lp); 2861558Srgrimes break; 2871558Srgrimes 2881558Srgrimes case RESTORE: 2891558Srgrimes#if NUMBOOT > 0 2901558Srgrimes if (installboot && argc == 3) { 2911558Srgrimes makelabel(argv[2], 0, &lab); 2921558Srgrimes argc--; 29337865Sbde 29437865Sbde /* 29537865Sbde * We only called makelabel() for its side effect 29637865Sbde * of setting the bootstrap file names. Discard 29737865Sbde * all changes to `lab' so that all values in the 29837865Sbde * final label come from the ASCII label. 29937865Sbde */ 30037865Sbde bzero((char *)&lab, sizeof(lab)); 3011558Srgrimes } 3021558Srgrimes#endif 3031558Srgrimes if (argc != 2) 3041558Srgrimes usage(); 3051558Srgrimes if (!(t = fopen(argv[1], "r"))) 30626542Scharnier err(4, "%s", argv[1]); 30737865Sbde if (!getasciilabel(t, &lab)) 30837865Sbde exit(1); 30937865Sbde lp = makebootarea(bootarea, &lab, f); 31037865Sbde *lp = lab; 31137865Sbde error = writelabel(f, bootarea, lp); 3121558Srgrimes break; 3131558Srgrimes 3141558Srgrimes case WRITE: 3151558Srgrimes if (argc == 3) { 3161558Srgrimes name = argv[2]; 3171558Srgrimes argc--; 3181558Srgrimes } 3191558Srgrimes if (argc != 2) 3201558Srgrimes usage(); 3211558Srgrimes makelabel(argv[1], name, &lab); 3221558Srgrimes lp = makebootarea(bootarea, &lab, f); 3231558Srgrimes *lp = lab; 3241558Srgrimes if (checklabel(lp) == 0) 3251558Srgrimes error = writelabel(f, bootarea, lp); 3261558Srgrimes break; 3271558Srgrimes 3281558Srgrimes case WRITEABLE: 3291558Srgrimes flag = 1; 3301558Srgrimes if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 33126542Scharnier err(4, "ioctl DIOCWLABEL"); 3321558Srgrimes break; 3331558Srgrimes 3341558Srgrimes#if NUMBOOT > 0 3351558Srgrimes case WRITEBOOT: 3361558Srgrimes { 3371558Srgrimes struct disklabel tlab; 3381558Srgrimes 3391558Srgrimes lp = readlabel(f); 3401558Srgrimes tlab = *lp; 3411558Srgrimes if (argc == 2) 3421558Srgrimes makelabel(argv[1], 0, &lab); 3431558Srgrimes lp = makebootarea(bootarea, &lab, f); 3441558Srgrimes *lp = tlab; 3451558Srgrimes if (checklabel(lp) == 0) 3461558Srgrimes error = writelabel(f, bootarea, lp); 3471558Srgrimes break; 3481558Srgrimes } 3491558Srgrimes#endif 3501558Srgrimes } 3511558Srgrimes exit(error); 3521558Srgrimes} 3531558Srgrimes 3541558Srgrimes/* 3551558Srgrimes * Construct a prototype disklabel from /etc/disktab. As a side 3561558Srgrimes * effect, set the names of the primary and secondary boot files 3571558Srgrimes * if specified. 3581558Srgrimes */ 35913544Sjoergvoid 3601558Srgrimesmakelabel(type, name, lp) 3611558Srgrimes char *type, *name; 3621558Srgrimes register struct disklabel *lp; 3631558Srgrimes{ 3641558Srgrimes register struct disklabel *dp; 36513550Sjoerg 36613550Sjoerg if (strcmp(type, "auto") == 0) 36713550Sjoerg dp = getvirginlabel(); 36813550Sjoerg else 36913544Sjoerg dp = getdiskbyname(type); 37036632Scharnier if (dp == NULL) 37136632Scharnier errx(1, "%s: unknown disk type", type); 3721558Srgrimes *lp = *dp; 3731558Srgrimes#if NUMBOOT > 0 3741558Srgrimes /* 3751558Srgrimes * Set bootstrap name(s). 3761558Srgrimes * 1. If set from command line, use those, 3771558Srgrimes * 2. otherwise, check if disktab specifies them (b0 or b1), 3781558Srgrimes * 3. otherwise, makebootarea() will choose ones based on the name 3791558Srgrimes * of the disk special file. E.g. /dev/ra0 -> raboot, bootra 3801558Srgrimes */ 3811558Srgrimes if (!xxboot && lp->d_boot0) { 3821558Srgrimes if (*lp->d_boot0 != '/') 3831558Srgrimes (void)sprintf(boot0, "%s/%s", 3841558Srgrimes _PATH_BOOTDIR, lp->d_boot0); 3851558Srgrimes else 3861558Srgrimes (void)strcpy(boot0, lp->d_boot0); 3871558Srgrimes xxboot = boot0; 3881558Srgrimes } 3891558Srgrimes#if NUMBOOT > 1 3901558Srgrimes if (!bootxx && lp->d_boot1) { 3911558Srgrimes if (*lp->d_boot1 != '/') 3921558Srgrimes (void)sprintf(boot1, "%s/%s", 3931558Srgrimes _PATH_BOOTDIR, lp->d_boot1); 3941558Srgrimes else 3951558Srgrimes (void)strcpy(boot1, lp->d_boot1); 3961558Srgrimes bootxx = boot1; 3971558Srgrimes } 3981558Srgrimes#endif 3991558Srgrimes#endif 4001558Srgrimes /* d_packname is union d_boot[01], so zero */ 4011558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 4021558Srgrimes if (name) 4031558Srgrimes (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 4041558Srgrimes} 4051558Srgrimes 40613544Sjoergint 4071558Srgrimeswritelabel(f, boot, lp) 4081558Srgrimes int f; 4091558Srgrimes char *boot; 4101558Srgrimes register struct disklabel *lp; 4111558Srgrimes{ 4121558Srgrimes int flag; 41338384Sdfr#ifdef __alpha__ 41438384Sdfr u_long *p, sum; 41538384Sdfr int i; 41638384Sdfr#endif 41738411Sbde#ifdef vax 41838411Sbde register int i; 41938411Sbde#endif 42038384Sdfr 42173034Sjwd if (disable_write) { 42273034Sjwd Warning("write to disk label supressed - label was as follows:"); 42373034Sjwd display(stdout, lp); 42473034Sjwd return (0); 42573034Sjwd } else { 42673034Sjwd setbootflag(lp); 42773034Sjwd lp->d_magic = DISKMAGIC; 42873034Sjwd lp->d_magic2 = DISKMAGIC; 42973034Sjwd lp->d_checksum = 0; 43073034Sjwd lp->d_checksum = dkcksum(lp); 43173034Sjwd if (rflag) { 43273034Sjwd /* 43373034Sjwd * First set the kernel disk label, 43473034Sjwd * then write a label to the raw disk. 43573034Sjwd * If the SDINFO ioctl fails because it is unimplemented, 43673034Sjwd * keep going; otherwise, the kernel consistency checks 43773034Sjwd * may prevent us from changing the current (in-core) 43873034Sjwd * label. 43973034Sjwd */ 44073034Sjwd if (ioctl(f, DIOCSDINFO, lp) < 0 && 44173034Sjwd errno != ENODEV && errno != ENOTTY) { 44273034Sjwd l_perror("ioctl DIOCSDINFO"); 44373034Sjwd return (1); 44473034Sjwd } 44573034Sjwd (void)lseek(f, (off_t)0, SEEK_SET); 44673034Sjwd 44738411Sbde#ifdef __alpha__ 44873034Sjwd /* 44973034Sjwd * Generate the bootblock checksum for the SRM console. 45073034Sjwd */ 45173034Sjwd for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) 45273034Sjwd sum += p[i]; 45373034Sjwd p[63] = sum; 45438384Sdfr#endif 45573034Sjwd 45673034Sjwd /* 45773034Sjwd * write enable label sector before write (if necessary), 45873034Sjwd * disable after writing. 45973034Sjwd */ 46073034Sjwd flag = 1; 46173034Sjwd if (ioctl(f, DIOCWLABEL, &flag) < 0) 46273034Sjwd warn("ioctl DIOCWLABEL"); 46373034Sjwd if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 46473034Sjwd warn("write"); 46573034Sjwd return (1); 46673034Sjwd } 46773034Sjwd#if NUMBOOT > 0 46873034Sjwd /* 46973034Sjwd * Output the remainder of the disklabel 47073034Sjwd */ 47173034Sjwd if (bootbuf && write(f, bootbuf, bootsize) != bootsize) { 47273034Sjwd warn("write"); 47373034Sjwd return(1); 47473034Sjwd } 47573034Sjwd#endif 47673034Sjwd flag = 0; 47773034Sjwd (void) ioctl(f, DIOCWLABEL, &flag); 47873034Sjwd } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 47973034Sjwd l_perror("ioctl DIOCWDINFO"); 4801558Srgrimes return (1); 4811558Srgrimes } 48273034Sjwd#ifdef vax 48373034Sjwd if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 48473034Sjwd daddr_t alt; 48573034Sjwd 48673034Sjwd alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 48773034Sjwd for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 48873034Sjwd (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), 48973034Sjwd SEEK_SET); 49073034Sjwd if (write(f, boot, lp->d_secsize) < lp->d_secsize) 49173034Sjwd warn("alternate label %d write", i/2); 49273034Sjwd } 4931558Srgrimes } 4941558Srgrimes#endif 4951558Srgrimes } 4961558Srgrimes return (0); 4971558Srgrimes} 4981558Srgrimes 49913544Sjoergvoid 5001558Srgrimesl_perror(s) 5011558Srgrimes char *s; 5021558Srgrimes{ 50336632Scharnier switch (errno) { 5041558Srgrimes 5051558Srgrimes case ESRCH: 50636756Scharnier warnx("%s: no disk label on disk;", s); 50736756Scharnier fprintf(stderr, 50840475Sbde "use \"disklabel -r\" to install initial label\n"); 5091558Srgrimes break; 5101558Srgrimes 5111558Srgrimes case EINVAL: 51236756Scharnier warnx("%s: label magic number or checksum is wrong!", s); 51336756Scharnier fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 5141558Srgrimes break; 5151558Srgrimes 5161558Srgrimes case EBUSY: 51736632Scharnier warnx("%s: open partition would move or shrink", s); 5181558Srgrimes break; 5191558Srgrimes 5201558Srgrimes case EXDEV: 52140475Sbde warnx("%s: '%c' partition must start at beginning of disk", 52240475Sbde s, 'a' + RAW_PART); 5231558Srgrimes break; 5241558Srgrimes 5251558Srgrimes default: 52636632Scharnier warn((char *)NULL); 5271558Srgrimes break; 5281558Srgrimes } 5291558Srgrimes} 5301558Srgrimes 5311558Srgrimes/* 5321558Srgrimes * Fetch disklabel for disk. 5331558Srgrimes * Use ioctl to get label unless -r flag is given. 5341558Srgrimes */ 5351558Srgrimesstruct disklabel * 5361558Srgrimesreadlabel(f) 5371558Srgrimes int f; 5381558Srgrimes{ 5391558Srgrimes register struct disklabel *lp; 5401558Srgrimes 5411558Srgrimes if (rflag) { 5421558Srgrimes if (read(f, bootarea, BBSIZE) < BBSIZE) 54326542Scharnier err(4, "%s", specname); 5441558Srgrimes for (lp = (struct disklabel *)bootarea; 5451558Srgrimes lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 5461558Srgrimes lp = (struct disklabel *)((char *)lp + 16)) 5471558Srgrimes if (lp->d_magic == DISKMAGIC && 5481558Srgrimes lp->d_magic2 == DISKMAGIC) 5491558Srgrimes break; 5501558Srgrimes if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 5511558Srgrimes lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 55236756Scharnier dkcksum(lp) != 0) 55336756Scharnier errx(1, 55436756Scharnier "bad pack magic number (label is damaged, or pack is unlabeled)"); 5551558Srgrimes } else { 5561558Srgrimes lp = &lab; 5571558Srgrimes if (ioctl(f, DIOCGDINFO, lp) < 0) 55826542Scharnier err(4, "ioctl DIOCGDINFO"); 5591558Srgrimes } 5601558Srgrimes return (lp); 5611558Srgrimes} 5621558Srgrimes 5631558Srgrimes/* 5641558Srgrimes * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 5651558Srgrimes * Returns a pointer to the disklabel portion of the bootarea. 5661558Srgrimes */ 5671558Srgrimesstruct disklabel * 5681558Srgrimesmakebootarea(boot, dp, f) 5691558Srgrimes char *boot; 5701558Srgrimes register struct disklabel *dp; 5711558Srgrimes int f; 5721558Srgrimes{ 57338483Sbde struct disklabel *lp; 5741558Srgrimes register char *p; 5751558Srgrimes int b; 5761558Srgrimes#if NUMBOOT > 0 5771558Srgrimes char *dkbasename; 5781558Srgrimes struct stat sb; 57938411Sbde#endif 58038411Sbde#ifdef __alpha__ 58138483Sbde u_long *bootinfo; 58238411Sbde int n; 58338411Sbde#endif 58413892Sjoerg#ifdef __i386__ 58513892Sjoerg char *tmpbuf; 58613892Sjoerg int i, found; 58713544Sjoerg#endif 5881558Srgrimes 5891558Srgrimes /* XXX */ 5901558Srgrimes if (dp->d_secsize == 0) { 5911558Srgrimes dp->d_secsize = DEV_BSIZE; 5921558Srgrimes dp->d_bbsize = BBSIZE; 5931558Srgrimes } 5941558Srgrimes lp = (struct disklabel *) 5951558Srgrimes (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 5961558Srgrimes bzero((char *)lp, sizeof *lp); 5971558Srgrimes#if NUMBOOT > 0 5981558Srgrimes /* 5991558Srgrimes * If we are not installing a boot program but we are installing a 6001558Srgrimes * label on disk then we must read the current bootarea so we don't 6011558Srgrimes * clobber the existing boot. 6021558Srgrimes */ 6031558Srgrimes if (!installboot) { 6041558Srgrimes if (rflag) { 6051558Srgrimes if (read(f, boot, BBSIZE) < BBSIZE) 60626542Scharnier err(4, "%s", specname); 6071558Srgrimes bzero((char *)lp, sizeof *lp); 6081558Srgrimes } 6091558Srgrimes return (lp); 6101558Srgrimes } 6111558Srgrimes /* 6121558Srgrimes * We are installing a boot program. Determine the name(s) and 6131558Srgrimes * read them into the appropriate places in the boot area. 6141558Srgrimes */ 6151558Srgrimes if (!xxboot || !bootxx) { 6161558Srgrimes dkbasename = np; 6171558Srgrimes if ((p = rindex(dkname, '/')) == NULL) 6181558Srgrimes p = dkname; 6191558Srgrimes else 6201558Srgrimes p++; 6211558Srgrimes while (*p && !isdigit(*p)) 6221558Srgrimes *np++ = *p++; 6231558Srgrimes *np++ = '\0'; 6241558Srgrimes 6251558Srgrimes if (!xxboot) { 62641901Sjkh (void)sprintf(boot0, "%s/boot1", _PATH_BOOTDIR); 62741901Sjkh xxboot = boot0; 6281558Srgrimes } 6291558Srgrimes#if NUMBOOT > 1 6301558Srgrimes if (!bootxx) { 63141901Sjkh (void)sprintf(boot1, "%s/boot2", _PATH_BOOTDIR); 63241901Sjkh bootxx = boot1; 6331558Srgrimes } 6341558Srgrimes#endif 6351558Srgrimes } 6361558Srgrimes#ifdef DEBUG 6371558Srgrimes if (debug) 6381558Srgrimes fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n", 6391558Srgrimes xxboot, bootxx ? bootxx : "NONE"); 6401558Srgrimes#endif 6411558Srgrimes 6421558Srgrimes /* 6431558Srgrimes * Strange rules: 6441558Srgrimes * 1. One-piece bootstrap (hp300/hp800) 6451558Srgrimes * up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest 6461558Srgrimes * is remembered and written later following the bootarea. 6471558Srgrimes * 2. Two-piece bootstraps (vax/i386?/mips?) 6481558Srgrimes * up to d_secsize bytes of ``xxboot'' go in first d_secsize 6491558Srgrimes * bytes of bootarea, remaining d_bbsize-d_secsize filled 6501558Srgrimes * from ``bootxx''. 6511558Srgrimes */ 6521558Srgrimes b = open(xxboot, O_RDONLY); 6531558Srgrimes if (b < 0) 65426542Scharnier err(4, "%s", xxboot); 6551558Srgrimes#if NUMBOOT > 1 65613892Sjoerg#ifdef __i386__ 65713892Sjoerg /* 65813892Sjoerg * XXX Botch alert. 65913892Sjoerg * The i386 has the so-called fdisk table embedded into the 66013892Sjoerg * primary bootstrap. We take care to not clobber it, but 66113892Sjoerg * only if it does already contain some data. (Otherwise, 66213892Sjoerg * the xxboot provides a template.) 66313892Sjoerg */ 66413892Sjoerg if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) 66526542Scharnier err(4, "%s", xxboot); 66613892Sjoerg memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); 66713892Sjoerg#endif /* i386 */ 6681558Srgrimes if (read(b, boot, (int)dp->d_secsize) < 0) 66926542Scharnier err(4, "%s", xxboot); 6701558Srgrimes (void)close(b); 67113892Sjoerg#ifdef __i386__ 67213892Sjoerg for (i = DOSPARTOFF, found = 0; 67313892Sjoerg !found && i < DOSPARTOFF + NDOSPART*sizeof(struct dos_partition); 67413892Sjoerg i++) 67513892Sjoerg found = tmpbuf[i] != 0; 67613892Sjoerg if (found) 67713892Sjoerg memcpy((void *)&boot[DOSPARTOFF], 67813892Sjoerg (void *)&tmpbuf[DOSPARTOFF], 67913892Sjoerg NDOSPART * sizeof(struct dos_partition)); 68013892Sjoerg free(tmpbuf); 68113892Sjoerg#endif /* i386 */ 6821558Srgrimes b = open(bootxx, O_RDONLY); 6831558Srgrimes if (b < 0) 68426542Scharnier err(4, "%s", bootxx); 68537865Sbde if (fstat(b, &sb) != 0) 68637865Sbde err(4, "%s", bootxx); 68737865Sbde if (dp->d_secsize + sb.st_size > dp->d_bbsize) 68837865Sbde errx(4, "%s too large", bootxx); 68913544Sjoerg if (read(b, &boot[dp->d_secsize], 69013544Sjoerg (int)(dp->d_bbsize-dp->d_secsize)) < 0) 69126542Scharnier err(4, "%s", bootxx); 69238411Sbde#else /* !(NUMBOOT > 1) */ 69338384Sdfr#ifdef __alpha__ 69438411Sbde /* 69538411Sbde * On the alpha, the primary bootstrap starts at the 69638411Sbde * second sector of the boot area. The first sector 69738411Sbde * contains the label and must be edited to contain the 69838411Sbde * size and location of the primary bootstrap. 69938411Sbde */ 70038411Sbde n = read(b, boot + dp->d_secsize, (int)dp->d_bbsize); 70138411Sbde if (n < 0) 70238384Sdfr err(4, "%s", xxboot); 70338483Sbde bootinfo = (u_long *)(boot + 480); 70438483Sbde bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; 70538483Sbde bootinfo[1] = 1; /* start at sector 1 */ 70638483Sbde bootinfo[2] = 0; /* flags (must be zero) */ 70738411Sbde#else /* !__alpha__ */ 7081558Srgrimes if (read(b, boot, (int)dp->d_bbsize) < 0) 70926542Scharnier err(4, "%s", xxboot); 71038411Sbde#endif /* __alpha__ */ 71137865Sbde if (fstat(b, &sb) != 0) 71237865Sbde err(4, "%s", xxboot); 7131558Srgrimes bootsize = (int)sb.st_size - dp->d_bbsize; 7141558Srgrimes if (bootsize > 0) { 7151558Srgrimes /* XXX assume d_secsize is a power of two */ 7161558Srgrimes bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1); 7171558Srgrimes bootbuf = (char *)malloc((size_t)bootsize); 7181558Srgrimes if (bootbuf == 0) 71926542Scharnier err(4, "%s", xxboot); 7201558Srgrimes if (read(b, bootbuf, bootsize) < 0) { 7211558Srgrimes free(bootbuf); 72226542Scharnier err(4, "%s", xxboot); 7231558Srgrimes } 7241558Srgrimes } 72538411Sbde#endif /* NUMBOOT > 1 */ 7261558Srgrimes (void)close(b); 72738411Sbde#endif /* NUMBOOT > 0 */ 7281558Srgrimes /* 7291558Srgrimes * Make sure no part of the bootstrap is written in the area 7301558Srgrimes * reserved for the label. 7311558Srgrimes */ 7321558Srgrimes for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 73336632Scharnier if (*p) 73436632Scharnier errx(2, "bootstrap doesn't leave room for disk label"); 7351558Srgrimes return (lp); 7361558Srgrimes} 7371558Srgrimes 73813544Sjoergvoid 7391558Srgrimesdisplay(f, lp) 7401558Srgrimes FILE *f; 7411558Srgrimes register struct disklabel *lp; 7421558Srgrimes{ 7431558Srgrimes register int i, j; 7441558Srgrimes register struct partition *pp; 7451558Srgrimes 7461558Srgrimes fprintf(f, "# %s:\n", specname); 7471558Srgrimes if ((unsigned) lp->d_type < DKMAXTYPES) 7481558Srgrimes fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 7491558Srgrimes else 75037234Sbde fprintf(f, "type: %u\n", lp->d_type); 75113544Sjoerg fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 75213544Sjoerg lp->d_typename); 75313544Sjoerg fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 75413544Sjoerg lp->d_packname); 7551558Srgrimes fprintf(f, "flags:"); 7561558Srgrimes if (lp->d_flags & D_REMOVABLE) 7571558Srgrimes fprintf(f, " removeable"); 7581558Srgrimes if (lp->d_flags & D_ECC) 7591558Srgrimes fprintf(f, " ecc"); 7601558Srgrimes if (lp->d_flags & D_BADSECT) 7611558Srgrimes fprintf(f, " badsect"); 7621558Srgrimes fprintf(f, "\n"); 76337234Sbde fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 76437234Sbde fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 76537234Sbde fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 76637234Sbde fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 76737234Sbde fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 76837234Sbde fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 76937234Sbde fprintf(f, "rpm: %u\n", lp->d_rpm); 77037234Sbde fprintf(f, "interleave: %u\n", lp->d_interleave); 77137234Sbde fprintf(f, "trackskew: %u\n", lp->d_trackskew); 77237234Sbde fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 77337234Sbde fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 77437234Sbde (u_long)lp->d_headswitch); 77513544Sjoerg fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 77637234Sbde (u_long)lp->d_trkseek); 7771558Srgrimes fprintf(f, "drivedata: "); 7781558Srgrimes for (i = NDDATA - 1; i >= 0; i--) 7791558Srgrimes if (lp->d_drivedata[i]) 7801558Srgrimes break; 7811558Srgrimes if (i < 0) 7821558Srgrimes i = 0; 7831558Srgrimes for (j = 0; j <= i; j++) 78437234Sbde fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 78537234Sbde fprintf(f, "\n\n%u partitions:\n", lp->d_npartitions); 7861558Srgrimes fprintf(f, 7875393Sgibbs "# size offset fstype [fsize bsize bps/cpg]\n"); 7881558Srgrimes pp = lp->d_partitions; 7891558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 7901558Srgrimes if (pp->p_size) { 79137234Sbde fprintf(f, " %c: %8lu %8lu ", 'a' + i, 79237234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 7931558Srgrimes if ((unsigned) pp->p_fstype < FSMAXTYPES) 7941558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 7951558Srgrimes else 7961558Srgrimes fprintf(f, "%8d", pp->p_fstype); 7971558Srgrimes switch (pp->p_fstype) { 7981558Srgrimes 7991558Srgrimes case FS_UNUSED: /* XXX */ 80037234Sbde fprintf(f, " %5lu %5lu %5.5s ", 80137234Sbde (u_long)pp->p_fsize, 80237234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 8031558Srgrimes break; 8041558Srgrimes 8051558Srgrimes case FS_BSDFFS: 80637234Sbde fprintf(f, " %5lu %5lu %5u ", 80737234Sbde (u_long)pp->p_fsize, 80837234Sbde (u_long)(pp->p_fsize * pp->p_frag), 8091558Srgrimes pp->p_cpg); 8101558Srgrimes break; 8111558Srgrimes 8125393Sgibbs case FS_BSDLFS: 81337234Sbde fprintf(f, " %5lu %5lu %5d", 81437234Sbde (u_long)pp->p_fsize, 81537234Sbde (u_long)(pp->p_fsize * pp->p_frag), 8165393Sgibbs pp->p_cpg); 8175393Sgibbs break; 8185393Sgibbs 8191558Srgrimes default: 8201558Srgrimes fprintf(f, "%20.20s", ""); 8211558Srgrimes break; 8221558Srgrimes } 82337234Sbde fprintf(f, "\t# (Cyl. %4lu", 82437234Sbde (u_long)(pp->p_offset / lp->d_secpercyl)); 8251558Srgrimes if (pp->p_offset % lp->d_secpercyl) 8261558Srgrimes putc('*', f); 8271558Srgrimes else 8281558Srgrimes putc(' ', f); 82937234Sbde fprintf(f, "- %lu", 83037234Sbde (u_long)((pp->p_offset + pp->p_size + 83137234Sbde lp->d_secpercyl - 1) / 83237234Sbde lp->d_secpercyl - 1)); 8331558Srgrimes if (pp->p_size % lp->d_secpercyl) 8341558Srgrimes putc('*', f); 8351558Srgrimes fprintf(f, ")\n"); 8361558Srgrimes } 8371558Srgrimes } 8381558Srgrimes fflush(f); 8391558Srgrimes} 8401558Srgrimes 84113544Sjoergint 8421558Srgrimesedit(lp, f) 8431558Srgrimes struct disklabel *lp; 8441558Srgrimes int f; 8451558Srgrimes{ 84624180Simp register int c, fd; 8471558Srgrimes struct disklabel label; 84824180Simp FILE *fp; 8491558Srgrimes 85024180Simp if ((fd = mkstemp(tmpfil)) == -1 || 85124180Simp (fp = fdopen(fd, "w")) == NULL) { 85236632Scharnier warnx("can't create %s", tmpfil); 8531558Srgrimes return (1); 8541558Srgrimes } 85524180Simp display(fp, lp); 85624180Simp fclose(fp); 8571558Srgrimes for (;;) { 8581558Srgrimes if (!editit()) 8591558Srgrimes break; 86024180Simp fp = fopen(tmpfil, "r"); 86124180Simp if (fp == NULL) { 86236632Scharnier warnx("can't reopen %s for reading", tmpfil); 8631558Srgrimes break; 8641558Srgrimes } 8651558Srgrimes bzero((char *)&label, sizeof(label)); 86624180Simp if (getasciilabel(fp, &label)) { 8671558Srgrimes *lp = label; 8681558Srgrimes if (writelabel(f, bootarea, lp) == 0) { 86924180Simp fclose(fp); 8701558Srgrimes (void) unlink(tmpfil); 8711558Srgrimes return (0); 8721558Srgrimes } 8731558Srgrimes } 87424180Simp fclose(fp); 8751558Srgrimes printf("re-edit the label? [y]: "); fflush(stdout); 8761558Srgrimes c = getchar(); 8771558Srgrimes if (c != EOF && c != (int)'\n') 8781558Srgrimes while (getchar() != (int)'\n') 8791558Srgrimes ; 8801558Srgrimes if (c == (int)'n') 8811558Srgrimes break; 8821558Srgrimes } 8831558Srgrimes (void) unlink(tmpfil); 8841558Srgrimes return (1); 8851558Srgrimes} 8861558Srgrimes 88713544Sjoergint 8881558Srgrimeseditit() 8891558Srgrimes{ 8901558Srgrimes register int pid, xpid; 8911558Srgrimes int stat, omask; 8921558Srgrimes 8931558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 8941558Srgrimes while ((pid = fork()) < 0) { 8951558Srgrimes if (errno == EPROCLIM) { 89636632Scharnier warnx("you have too many processes"); 8971558Srgrimes return(0); 8981558Srgrimes } 8991558Srgrimes if (errno != EAGAIN) { 90036632Scharnier warn("fork"); 9011558Srgrimes return(0); 9021558Srgrimes } 9031558Srgrimes sleep(1); 9041558Srgrimes } 9051558Srgrimes if (pid == 0) { 9061558Srgrimes register char *ed; 9071558Srgrimes 9081558Srgrimes sigsetmask(omask); 9091558Srgrimes setgid(getgid()); 9101558Srgrimes setuid(getuid()); 9111558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 9121558Srgrimes ed = DEFEDITOR; 9131558Srgrimes execlp(ed, ed, tmpfil, 0); 91436632Scharnier err(1, "%s", ed); 9151558Srgrimes } 9161558Srgrimes while ((xpid = wait(&stat)) >= 0) 9171558Srgrimes if (xpid == pid) 9181558Srgrimes break; 9191558Srgrimes sigsetmask(omask); 9201558Srgrimes return(!stat); 9211558Srgrimes} 9221558Srgrimes 9231558Srgrimeschar * 9241558Srgrimesskip(cp) 9251558Srgrimes register char *cp; 9261558Srgrimes{ 9271558Srgrimes 9281558Srgrimes while (*cp != '\0' && isspace(*cp)) 9291558Srgrimes cp++; 9301558Srgrimes if (*cp == '\0' || *cp == '#') 9311558Srgrimes return ((char *)NULL); 9321558Srgrimes return (cp); 9331558Srgrimes} 9341558Srgrimes 9351558Srgrimeschar * 9361558Srgrimesword(cp) 9371558Srgrimes register char *cp; 9381558Srgrimes{ 9391558Srgrimes register char c; 9401558Srgrimes 9411558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 9421558Srgrimes cp++; 9431558Srgrimes if ((c = *cp) != '\0') { 9441558Srgrimes *cp++ = '\0'; 9451558Srgrimes if (c != '#') 9461558Srgrimes return (skip(cp)); 9471558Srgrimes } 9481558Srgrimes return ((char *)NULL); 9491558Srgrimes} 9501558Srgrimes 9511558Srgrimes/* 9521558Srgrimes * Read an ascii label in from fd f, 9531558Srgrimes * in the same format as that put out by display(), 9541558Srgrimes * and fill in lp. 9551558Srgrimes */ 95613544Sjoergint 9571558Srgrimesgetasciilabel(f, lp) 9581558Srgrimes FILE *f; 9591558Srgrimes register struct disklabel *lp; 9601558Srgrimes{ 9611558Srgrimes register char **cpp, *cp; 9621558Srgrimes register struct partition *pp; 96373034Sjwd int i; 96473034Sjwd unsigned int part; 9651558Srgrimes char *tp, *s, line[BUFSIZ]; 9661558Srgrimes int v, lineno = 0, errors = 0; 9671558Srgrimes 9681558Srgrimes lp->d_bbsize = BBSIZE; /* XXX */ 9691558Srgrimes lp->d_sbsize = SBSIZE; /* XXX */ 9701558Srgrimes while (fgets(line, sizeof(line) - 1, f)) { 9711558Srgrimes lineno++; 97213544Sjoerg if ((cp = index(line,'\n')) != 0) 9731558Srgrimes *cp = '\0'; 9741558Srgrimes cp = skip(line); 9751558Srgrimes if (cp == NULL) 9761558Srgrimes continue; 9771558Srgrimes tp = index(cp, ':'); 9781558Srgrimes if (tp == NULL) { 9791558Srgrimes fprintf(stderr, "line %d: syntax error\n", lineno); 9801558Srgrimes errors++; 9811558Srgrimes continue; 9821558Srgrimes } 9831558Srgrimes *tp++ = '\0', tp = skip(tp); 9841558Srgrimes if (streq(cp, "type")) { 9851558Srgrimes if (tp == NULL) 9861558Srgrimes tp = "unknown"; 9871558Srgrimes cpp = dktypenames; 9881558Srgrimes for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 9891558Srgrimes if ((s = *cpp) && streq(s, tp)) { 9901558Srgrimes lp->d_type = cpp - dktypenames; 9911558Srgrimes goto next; 9921558Srgrimes } 9931558Srgrimes v = atoi(tp); 9941558Srgrimes if ((unsigned)v >= DKMAXTYPES) 9951558Srgrimes fprintf(stderr, "line %d:%s %d\n", lineno, 9961558Srgrimes "Warning, unknown disk type", v); 9971558Srgrimes lp->d_type = v; 9981558Srgrimes continue; 9991558Srgrimes } 10001558Srgrimes if (streq(cp, "flags")) { 10011558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 10021558Srgrimes tp = word(cp); 10031558Srgrimes if (streq(cp, "removeable")) 10041558Srgrimes v |= D_REMOVABLE; 10051558Srgrimes else if (streq(cp, "ecc")) 10061558Srgrimes v |= D_ECC; 10071558Srgrimes else if (streq(cp, "badsect")) 10081558Srgrimes v |= D_BADSECT; 10091558Srgrimes else { 10101558Srgrimes fprintf(stderr, 10111558Srgrimes "line %d: %s: bad flag\n", 10121558Srgrimes lineno, cp); 10131558Srgrimes errors++; 10141558Srgrimes } 10151558Srgrimes } 10161558Srgrimes lp->d_flags = v; 10171558Srgrimes continue; 10181558Srgrimes } 10191558Srgrimes if (streq(cp, "drivedata")) { 10201558Srgrimes register int i; 10211558Srgrimes 10221558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 10231558Srgrimes lp->d_drivedata[i++] = atoi(cp); 10241558Srgrimes tp = word(cp); 10251558Srgrimes } 10261558Srgrimes continue; 10271558Srgrimes } 10281558Srgrimes if (sscanf(cp, "%d partitions", &v) == 1) { 10291558Srgrimes if (v == 0 || (unsigned)v > MAXPARTITIONS) { 10301558Srgrimes fprintf(stderr, 10311558Srgrimes "line %d: bad # of partitions\n", lineno); 10321558Srgrimes lp->d_npartitions = MAXPARTITIONS; 10331558Srgrimes errors++; 10341558Srgrimes } else 10351558Srgrimes lp->d_npartitions = v; 10361558Srgrimes continue; 10371558Srgrimes } 10381558Srgrimes if (tp == NULL) 10391558Srgrimes tp = ""; 10401558Srgrimes if (streq(cp, "disk")) { 10411558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 10421558Srgrimes continue; 10431558Srgrimes } 10441558Srgrimes if (streq(cp, "label")) { 10451558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 10461558Srgrimes continue; 10471558Srgrimes } 10481558Srgrimes if (streq(cp, "bytes/sector")) { 10491558Srgrimes v = atoi(tp); 105037865Sbde if (v <= 0 || (v % DEV_BSIZE) != 0) { 10511558Srgrimes fprintf(stderr, 10521558Srgrimes "line %d: %s: bad sector size\n", 10531558Srgrimes lineno, tp); 10541558Srgrimes errors++; 10551558Srgrimes } else 10561558Srgrimes lp->d_secsize = v; 10571558Srgrimes continue; 10581558Srgrimes } 10591558Srgrimes if (streq(cp, "sectors/track")) { 10601558Srgrimes v = atoi(tp); 10611558Srgrimes if (v <= 0) { 10621558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10631558Srgrimes lineno, tp, cp); 10641558Srgrimes errors++; 10651558Srgrimes } else 10661558Srgrimes lp->d_nsectors = v; 10671558Srgrimes continue; 10681558Srgrimes } 10691558Srgrimes if (streq(cp, "sectors/cylinder")) { 10701558Srgrimes v = atoi(tp); 10711558Srgrimes if (v <= 0) { 10721558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10731558Srgrimes lineno, tp, cp); 10741558Srgrimes errors++; 10751558Srgrimes } else 10761558Srgrimes lp->d_secpercyl = v; 10771558Srgrimes continue; 10781558Srgrimes } 10791558Srgrimes if (streq(cp, "tracks/cylinder")) { 10801558Srgrimes v = atoi(tp); 10811558Srgrimes if (v <= 0) { 10821558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10831558Srgrimes lineno, tp, cp); 10841558Srgrimes errors++; 10851558Srgrimes } else 10861558Srgrimes lp->d_ntracks = v; 10871558Srgrimes continue; 10881558Srgrimes } 10891558Srgrimes if (streq(cp, "cylinders")) { 10901558Srgrimes v = atoi(tp); 10911558Srgrimes if (v <= 0) { 10921558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10931558Srgrimes lineno, tp, cp); 10941558Srgrimes errors++; 10951558Srgrimes } else 10961558Srgrimes lp->d_ncylinders = v; 10971558Srgrimes continue; 10981558Srgrimes } 10996643Sbde if (streq(cp, "sectors/unit")) { 11006643Sbde v = atoi(tp); 11016643Sbde if (v <= 0) { 11026643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 11036643Sbde lineno, tp, cp); 11046643Sbde errors++; 11056643Sbde } else 11066643Sbde lp->d_secperunit = v; 11076643Sbde continue; 11086643Sbde } 11091558Srgrimes if (streq(cp, "rpm")) { 11101558Srgrimes v = atoi(tp); 11111558Srgrimes if (v <= 0) { 11121558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11131558Srgrimes lineno, tp, cp); 11141558Srgrimes errors++; 11151558Srgrimes } else 11161558Srgrimes lp->d_rpm = v; 11171558Srgrimes continue; 11181558Srgrimes } 11191558Srgrimes if (streq(cp, "interleave")) { 11201558Srgrimes v = atoi(tp); 11211558Srgrimes if (v <= 0) { 11221558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11231558Srgrimes lineno, tp, cp); 11241558Srgrimes errors++; 11251558Srgrimes } else 11261558Srgrimes lp->d_interleave = v; 11271558Srgrimes continue; 11281558Srgrimes } 11291558Srgrimes if (streq(cp, "trackskew")) { 11301558Srgrimes v = atoi(tp); 11311558Srgrimes if (v < 0) { 11321558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11331558Srgrimes lineno, tp, cp); 11341558Srgrimes errors++; 11351558Srgrimes } else 11361558Srgrimes lp->d_trackskew = v; 11371558Srgrimes continue; 11381558Srgrimes } 11391558Srgrimes if (streq(cp, "cylinderskew")) { 11401558Srgrimes v = atoi(tp); 11411558Srgrimes if (v < 0) { 11421558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11431558Srgrimes lineno, tp, cp); 11441558Srgrimes errors++; 11451558Srgrimes } else 11461558Srgrimes lp->d_cylskew = v; 11471558Srgrimes continue; 11481558Srgrimes } 11491558Srgrimes if (streq(cp, "headswitch")) { 11501558Srgrimes v = atoi(tp); 11511558Srgrimes if (v < 0) { 11521558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11531558Srgrimes lineno, tp, cp); 11541558Srgrimes errors++; 11551558Srgrimes } else 11561558Srgrimes lp->d_headswitch = v; 11571558Srgrimes continue; 11581558Srgrimes } 11591558Srgrimes if (streq(cp, "track-to-track seek")) { 11601558Srgrimes v = atoi(tp); 11611558Srgrimes if (v < 0) { 11621558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11631558Srgrimes lineno, tp, cp); 11641558Srgrimes errors++; 11651558Srgrimes } else 11661558Srgrimes lp->d_trkseek = v; 11671558Srgrimes continue; 11681558Srgrimes } 116973034Sjwd /* the ':' was removed above */ 117073034Sjwd if ('a' <= *cp && *cp <= MAX_PART && cp[1] == '\0') { 117173034Sjwd part = *cp - 'a'; 117273034Sjwd if (part >= lp->d_npartitions) { 11731558Srgrimes fprintf(stderr, 117473034Sjwd "line %d: partition name out of range a-%c: %s\n", 117573034Sjwd lineno, 'a' + lp->d_npartitions - 1, cp); 11761558Srgrimes errors++; 11771558Srgrimes continue; 11781558Srgrimes } 11791558Srgrimes pp = &lp->d_partitions[part]; 118073034Sjwd part_set[part] = 1; 11811558Srgrimes#define NXTNUM(n) { \ 11823111Spst if (tp == NULL) { \ 11833111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 11843111Spst errors++; \ 11853111Spst break; \ 11863111Spst } else { \ 11873111Spst cp = tp, tp = word(cp); \ 11883111Spst if (tp == NULL) \ 11893111Spst tp = cp; \ 11903111Spst (n) = atoi(cp); \ 11913111Spst } \ 11921558Srgrimes } 119373034Sjwd/* retain 1 character following number */ 119473034Sjwd#define NXTWORD(w,n) { \ 119573034Sjwd if (tp == NULL) { \ 119673034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 119773034Sjwd errors++; \ 119873034Sjwd break; \ 119973034Sjwd } else { \ 120073034Sjwd char *tmp; \ 120173034Sjwd cp = tp, tp = word(cp); \ 120273034Sjwd if (tp == NULL) \ 120373034Sjwd tp = cp; \ 120473034Sjwd (n) = strtol(cp,&tmp,10); \ 120573034Sjwd if (tmp) (w) = *tmp; \ 120673034Sjwd } \ 120773034Sjwd } 120873034Sjwd v = 0; 120973034Sjwd NXTWORD(part_size_type[part],v); 121073034Sjwd if (v < 0 || (v == 0 && part_size_type[part] != '*')) { 12111558Srgrimes fprintf(stderr, 12121558Srgrimes "line %d: %s: bad partition size\n", 12131558Srgrimes lineno, cp); 12141558Srgrimes errors++; 121573034Sjwd break; 121673034Sjwd } else { 12171558Srgrimes pp->p_size = v; 12181558Srgrimes 121973034Sjwd v = 0; 122073034Sjwd NXTWORD(part_offset_type[part],v); 122173034Sjwd if (v < 0 || (v == 0 && 122273034Sjwd part_offset_type[part] != '*' && 122373034Sjwd part_offset_type[part] != '\0')) { 122473034Sjwd fprintf(stderr, 122573034Sjwd "line %d: %s: bad partition offset\n", 122673034Sjwd lineno, cp); 122773034Sjwd errors++; 12281558Srgrimes break; 122973034Sjwd } else { 123073034Sjwd pp->p_offset = v; 123173034Sjwd cp = tp, tp = word(cp); 123273034Sjwd cpp = fstypenames; 123373034Sjwd for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 123473034Sjwd if ((s = *cpp) && streq(s, cp)) { 123573034Sjwd pp->p_fstype = cpp - 123673034Sjwd fstypenames; 123773034Sjwd goto gottype; 123873034Sjwd } 123973034Sjwd if (isdigit(*cp)) 124073034Sjwd v = atoi(cp); 124173034Sjwd else 124273034Sjwd v = FSMAXTYPES; 124373034Sjwd if ((unsigned)v >= FSMAXTYPES) { 124473034Sjwd fprintf(stderr, 124573034Sjwd "line %d: Warning, unknown " 124673034Sjwd "filesystem type %s\n", 124773034Sjwd lineno, cp); 124873034Sjwd v = FS_UNUSED; 124973034Sjwd } 125073034Sjwd pp->p_fstype = v; 125173034Sjwd gottype:; 125273034Sjwd /* 125373034Sjwd * Note: NXTNUM will break us out of the 125473034Sjwd * switch only! 125573034Sjwd */ 125673034Sjwd switch (pp->p_fstype) { 125773034Sjwd case FS_UNUSED: 125873034Sjwd /* 125973034Sjwd * allow us to accept defaults for 126073034Sjwd * fsize/frag/cpg 126173034Sjwd */ 126273034Sjwd if (tp) { 126373034Sjwd NXTNUM(pp->p_fsize); 126473034Sjwd if (pp->p_fsize == 0) 126573034Sjwd break; 126673034Sjwd NXTNUM(v); 126773034Sjwd pp->p_frag = v / pp->p_fsize; 126873034Sjwd } 126973034Sjwd /* else default to 0's */ 127073034Sjwd break; 12711558Srgrimes 127273034Sjwd /* These happen to be the same */ 127373034Sjwd case FS_BSDFFS: 127473034Sjwd case FS_BSDLFS: 127573034Sjwd if (tp) { 127673034Sjwd NXTNUM(pp->p_fsize); 127773034Sjwd if (pp->p_fsize == 0) 127873034Sjwd break; 127973034Sjwd NXTNUM(v); 128073034Sjwd pp->p_frag = v / pp->p_fsize; 128173034Sjwd NXTNUM(pp->p_cpg); 128273034Sjwd } else { 128373034Sjwd /* 128473034Sjwd * FIX! poor attempt at 128573034Sjwd * adaptive 128673034Sjwd */ 128773034Sjwd /* 1 GB */ 128873034Sjwd if (pp->p_size < 1*1024*1024*1024/lp->d_secsize) { 128973034Sjwd/* FIX! These are too low, but are traditional */ 129073034Sjwd pp->p_fsize = DEFAULT_NEWFS_BLOCK; 129173034Sjwd pp->p_frag = (unsigned char) DEFAULT_NEWFS_FRAG; 129273034Sjwd pp->p_cpg = DEFAULT_NEWFS_CPG; 129373034Sjwd } else { 129473034Sjwd pp->p_fsize = BIG_NEWFS_BLOCK; 129573034Sjwd pp->p_frag = (unsigned char) BIG_NEWFS_FRAG; 129673034Sjwd pp->p_cpg = BIG_NEWFS_CPG; 129773034Sjwd } 129873034Sjwd } 129973034Sjwd break; 130073034Sjwd default: 130173034Sjwd break; 130273034Sjwd } 13031558Srgrimes 130473034Sjwd /* 130573034Sjwd * note: we may not have 130673034Sjwd * gotten all the entries for 130773034Sjwd * the fs though if we didn't, 130873034Sjwd * errors will be set. 130973034Sjwd */ 131073034Sjwd } 13111558Srgrimes } 13121558Srgrimes continue; 13131558Srgrimes } 13141558Srgrimes fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 13151558Srgrimes lineno, cp); 13161558Srgrimes errors++; 131773034Sjwd next:; 13181558Srgrimes } 13191558Srgrimes errors += checklabel(lp); 13201558Srgrimes return (errors == 0); 13211558Srgrimes} 13221558Srgrimes 13231558Srgrimes/* 13241558Srgrimes * Check disklabel for errors and fill in 13251558Srgrimes * derived fields according to supplied values. 13261558Srgrimes */ 132713544Sjoergint 13281558Srgrimeschecklabel(lp) 13291558Srgrimes register struct disklabel *lp; 13301558Srgrimes{ 13311558Srgrimes register struct partition *pp; 13321558Srgrimes int i, errors = 0; 13331558Srgrimes char part; 133473034Sjwd unsigned long total_size,total_percent,current_offset; 133573034Sjwd int seen_default_offset; 133673034Sjwd int hog_part; 133773034Sjwd int j; 133873034Sjwd struct partition *pp2; 13391558Srgrimes 13401558Srgrimes if (lp->d_secsize == 0) { 134137234Sbde fprintf(stderr, "sector size 0\n"); 13421558Srgrimes return (1); 13431558Srgrimes } 13441558Srgrimes if (lp->d_nsectors == 0) { 134537234Sbde fprintf(stderr, "sectors/track 0\n"); 13461558Srgrimes return (1); 13471558Srgrimes } 13481558Srgrimes if (lp->d_ntracks == 0) { 134937234Sbde fprintf(stderr, "tracks/cylinder 0\n"); 13501558Srgrimes return (1); 13511558Srgrimes } 13521558Srgrimes if (lp->d_ncylinders == 0) { 135337234Sbde fprintf(stderr, "cylinders/unit 0\n"); 13541558Srgrimes errors++; 13551558Srgrimes } 13561558Srgrimes if (lp->d_rpm == 0) 135737234Sbde Warning("revolutions/minute 0"); 13581558Srgrimes if (lp->d_secpercyl == 0) 13591558Srgrimes lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 13601558Srgrimes if (lp->d_secperunit == 0) 13611558Srgrimes lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 13621558Srgrimes if (lp->d_bbsize == 0) { 136337234Sbde fprintf(stderr, "boot block size 0\n"); 13641558Srgrimes errors++; 13651558Srgrimes } else if (lp->d_bbsize % lp->d_secsize) 13661558Srgrimes Warning("boot block size %% sector-size != 0"); 13671558Srgrimes if (lp->d_sbsize == 0) { 136837234Sbde fprintf(stderr, "super block size 0\n"); 13691558Srgrimes errors++; 13701558Srgrimes } else if (lp->d_sbsize % lp->d_secsize) 13711558Srgrimes Warning("super block size %% sector-size != 0"); 13721558Srgrimes if (lp->d_npartitions > MAXPARTITIONS) 137337234Sbde Warning("number of partitions (%lu) > MAXPARTITIONS (%d)", 137437234Sbde (u_long)lp->d_npartitions, MAXPARTITIONS); 137573034Sjwd 137673034Sjwd /* first allocate space to the partitions, then offsets */ 137773034Sjwd total_size = 0; /* in sectors */ 137873034Sjwd total_percent = 0; /* in percent */ 137973034Sjwd hog_part = -1; 138073034Sjwd /* find all fixed partitions */ 13811558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 138273034Sjwd pp = &lp->d_partitions[i]; 138373034Sjwd if (part_set[i]) { 138473034Sjwd if (part_size_type[i] == '*') { 138573034Sjwd /* partition 2 ('c') is special */ 138673034Sjwd if (i == FULL_DISK_PART) { 138773034Sjwd pp->p_size = lp->d_secperunit; 138873034Sjwd } else { 138973034Sjwd if (hog_part != -1) 139073034Sjwd Warning("Too many '*' partitions (%c and %c)", 139173034Sjwd hog_part + 'a',i + 'a'); 139273034Sjwd else 139373034Sjwd hog_part = i; 139473034Sjwd } 139573034Sjwd } else { 139673034Sjwd char *type; 139773034Sjwd unsigned long size; 139873034Sjwd 139973034Sjwd size = pp->p_size; 140073034Sjwd switch (part_size_type[i]) { 140173034Sjwd case '%': 140273034Sjwd total_percent += size; 140373034Sjwd break; 140473034Sjwd case 'k': 140573034Sjwd case 'K': 140673034Sjwd size *= 1024UL; 140773034Sjwd break; 140873034Sjwd case 'm': 140973034Sjwd case 'M': 141073034Sjwd size *= ((unsigned long) 1024*1024); 141173034Sjwd break; 141273034Sjwd case 'g': 141373034Sjwd case 'G': 141473034Sjwd size *= ((unsigned long) 1024*1024*1024); 141573034Sjwd break; 141673034Sjwd case '\0': 141773034Sjwd break; 141873034Sjwd default: 141973034Sjwd Warning("unknown size specifier '%c' (K/M/G are valid)",part_size_type[i]); 142073034Sjwd break; 142173034Sjwd } 142273034Sjwd /* don't count %'s yet */ 142373034Sjwd if (part_size_type[i] != '%') { 142473034Sjwd /* 142573034Sjwd * for all not in sectors, convert to 142673034Sjwd * sectors 142773034Sjwd */ 142873034Sjwd if (part_size_type[i] != '\0') { 142973034Sjwd if (size % lp->d_secsize != 0) 143073034Sjwd Warning("partition %c not an integer number of sectors", 143173034Sjwd i + 'a'); 143273034Sjwd size /= lp->d_secsize; 143373034Sjwd pp->p_size = size; 143473034Sjwd } 143573034Sjwd /* else already in sectors */ 143673034Sjwd /* partition 2 ('c') is special */ 143773034Sjwd if (i != FULL_DISK_PART) 143873034Sjwd total_size += size; 143973034Sjwd } 144073034Sjwd } 144173034Sjwd } 144273034Sjwd } 144373034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 144473034Sjwd if (total_percent != 0) { 144573034Sjwd long free_space = lp->d_secperunit - total_size; 144673034Sjwd if (total_percent > 100) { 144773034Sjwd fprintf(stderr,"total percentage %d is greater than 100\n", 144873034Sjwd total_percent); 144973034Sjwd errors++; 145073034Sjwd } 145173034Sjwd 145273034Sjwd if (free_space > 0) { 145373034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 145473034Sjwd pp = &lp->d_partitions[i]; 145573034Sjwd if (part_set[i] && part_size_type[i] == '%') { 145673034Sjwd unsigned long old_size = pp->p_size; 145773034Sjwd /* careful of overflows! and integer roundoff */ 145873034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 145973034Sjwd total_size += pp->p_size; 146073034Sjwd 146173034Sjwd /* FIX we can lose a sector or so due to roundoff per 146273034Sjwd partition. A more complex algorithm could avoid that */ 146373034Sjwd } 146473034Sjwd } 146573034Sjwd } else { 146673034Sjwd fprintf(stderr, 146773034Sjwd "%ld sectors available to give to '*' and '%' partitions\n", 146873034Sjwd free_space); 146973034Sjwd errors++; 147073034Sjwd /* fix? set all % partitions to size 0? */ 147173034Sjwd } 147273034Sjwd } 147373034Sjwd /* give anything remaining to the hog partition */ 147473034Sjwd if (hog_part != -1) { 147573034Sjwd lp->d_partitions[hog_part].p_size = lp->d_secperunit - total_size; 147673034Sjwd total_size = lp->d_secperunit; 147773034Sjwd } 147873034Sjwd 147973034Sjwd /* Now set the offsets for each partition */ 148073034Sjwd current_offset = 0; /* in sectors */ 148173034Sjwd seen_default_offset = 0; 148273034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 14831558Srgrimes part = 'a' + i; 14841558Srgrimes pp = &lp->d_partitions[i]; 148573034Sjwd if (part_set[i]) { 148673034Sjwd if (part_offset_type[i] == '*') { 148773034Sjwd /* partition 2 ('c') is special */ 148873034Sjwd if (i == FULL_DISK_PART) { 148973034Sjwd pp->p_offset = 0; 149073034Sjwd } else { 149173034Sjwd pp->p_offset = current_offset; 149273034Sjwd seen_default_offset = 1; 149373034Sjwd } 149473034Sjwd } else { 149573034Sjwd /* allow them to be out of order for old-style tables */ 149673034Sjwd /* partition 2 ('c') is special */ 149773034Sjwd if (pp->p_offset < current_offset && 149873034Sjwd seen_default_offset && i != FULL_DISK_PART) { 149973034Sjwd fprintf(stderr, 150073034Sjwd"Offset %ld for partition %c overlaps previous partition which ends at %ld\n", 150173034Sjwd pp->p_offset,i+'a',current_offset); 150273034Sjwd fprintf(stderr, 150373034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 150473034Sjwd errors++; 150573034Sjwd } else if (pp->p_offset != current_offset && 150673034Sjwd i != FULL_DISK_PART && seen_default_offset) { 150773034Sjwd /* 150873034Sjwd * this may give unneeded warnings if 150973034Sjwd * partitions are out-of-order 151073034Sjwd */ 151173034Sjwd Warning( 151273034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 151373034Sjwd pp->p_offset, i + 'a', current_offset); 151473034Sjwd } 151573034Sjwd } 151673034Sjwd /* partition 2 ('c') is special */ 151773034Sjwd if (i != FULL_DISK_PART) 151873034Sjwd current_offset = pp->p_offset + pp->p_size; 151973034Sjwd } 152073034Sjwd } 152173034Sjwd 152273034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 152373034Sjwd part = 'a' + i; 152473034Sjwd pp = &lp->d_partitions[i]; 15251558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 152637234Sbde Warning("partition %c: size 0, but offset %lu", 152737234Sbde part, (u_long)pp->p_offset); 15281558Srgrimes#ifdef notdef 15291558Srgrimes if (pp->p_size % lp->d_secpercyl) 15301558Srgrimes Warning("partition %c: size %% cylinder-size != 0", 15311558Srgrimes part); 15321558Srgrimes if (pp->p_offset % lp->d_secpercyl) 15331558Srgrimes Warning("partition %c: offset %% cylinder-size != 0", 15341558Srgrimes part); 15351558Srgrimes#endif 15361558Srgrimes if (pp->p_offset > lp->d_secperunit) { 15371558Srgrimes fprintf(stderr, 15381558Srgrimes "partition %c: offset past end of unit\n", part); 15391558Srgrimes errors++; 15401558Srgrimes } 15411558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 15421558Srgrimes fprintf(stderr, 154313544Sjoerg "partition %c: partition extends past end of unit\n", 15441558Srgrimes part); 15451558Srgrimes errors++; 15461558Srgrimes } 154773034Sjwd if (i == FULL_DISK_PART) 154873034Sjwd { 154973034Sjwd if (pp->p_fstype != FS_UNUSED) 155073034Sjwd Warning("partition %c is not marked as unused!",part); 155173034Sjwd if (pp->p_offset != 0) 155273034Sjwd Warning("partition %c doesn't start at 0!",part); 155373034Sjwd if (pp->p_size != lp->d_secperunit) 155473034Sjwd Warning("partition %c doesn't cover the whole unit!",part); 155573034Sjwd 155673034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 155773034Sjwd (pp->p_size != lp->d_secperunit)) { 155873034Sjwd Warning("An incorrect partition %c may cause problems for " 155973034Sjwd "standard system utilities",part); 156073034Sjwd } 156173034Sjwd } 156273034Sjwd 156373034Sjwd /* check for overlaps */ 156473034Sjwd /* this will check for all possible overlaps once and only once */ 156573034Sjwd for (j = 0; j < i; j++) { 156673034Sjwd /* partition 2 ('c') is special */ 156773034Sjwd if (j != FULL_DISK_PART && i != FULL_DISK_PART && 156873034Sjwd part_set[i] && part_set[j]) { 156973034Sjwd pp2 = &lp->d_partitions[j]; 157073034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 157173034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 157273034Sjwd pp2->p_offset >= pp->p_offset)) { 157373034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 157473034Sjwd j + 'a', i + 'a'); 157573034Sjwd errors++; 157673034Sjwd } 157773034Sjwd } 157873034Sjwd } 15791558Srgrimes } 15801558Srgrimes for (; i < MAXPARTITIONS; i++) { 15811558Srgrimes part = 'a' + i; 15821558Srgrimes pp = &lp->d_partitions[i]; 15831558Srgrimes if (pp->p_size || pp->p_offset) 158437234Sbde Warning("unused partition %c: size %d offset %lu", 158537234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 15861558Srgrimes } 15871558Srgrimes return (errors); 15881558Srgrimes} 15891558Srgrimes 15901558Srgrimes/* 159113550Sjoerg * When operating on a "virgin" disk, try getting an initial label 159213550Sjoerg * from the associated device driver. This might work for all device 159313550Sjoerg * drivers that are able to fetch some initial device parameters 159413550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 159513550Sjoerg * most IDE drives, or vn devices. 159613550Sjoerg * 159713550Sjoerg * The device name must be given in its "canonical" form. 159813550Sjoerg */ 159913550Sjoergstruct disklabel * 160013550Sjoerggetvirginlabel(void) 160113550Sjoerg{ 160213550Sjoerg static struct disklabel lab; 160313550Sjoerg char namebuf[BBSIZE]; 160413550Sjoerg int f; 160513550Sjoerg 160613550Sjoerg if (dkname[0] == '/') { 160737773Sbde warnx("\"auto\" requires the usage of a canonical disk name"); 160816431Sbde return (NULL); 160913550Sjoerg } 161059429Sobrien (void)snprintf(namebuf, BBSIZE, "%s%s", _PATH_DEV, dkname); 161137773Sbde if ((f = open(namebuf, O_RDONLY)) == -1) { 161237773Sbde warn("cannot open %s", namebuf); 161316431Sbde return (NULL); 161413550Sjoerg } 161568044Sjkh 161668044Sjkh /* 161768044Sjkh * Try to use the new get-virgin-label ioctl. If it fails, 161868044Sjkh * fallback to the old get-disdk-info ioctl. 161968044Sjkh */ 162068044Sjkh if (ioctl(f, DIOCGDVIRGIN, &lab) < 0) { 162173034Sjwd if (ioctl(f, DIOCGDINFO, &lab) < 0) { 162273034Sjwd warn("ioctl DIOCGDINFO"); 162373034Sjwd close(f); 162473034Sjwd return (NULL); 162573034Sjwd } 162613550Sjoerg } 162713550Sjoerg close(f); 162837773Sbde lab.d_boot0 = NULL; 162937773Sbde lab.d_boot1 = NULL; 163016431Sbde return (&lab); 163113550Sjoerg} 163213550Sjoerg 163313550Sjoerg/* 16341558Srgrimes * If we are installing a boot program that doesn't fit in d_bbsize 16351558Srgrimes * we need to mark those partitions that the boot overflows into. 16361558Srgrimes * This allows newfs to prevent creation of a filesystem where it might 16371558Srgrimes * clobber bootstrap code. 16381558Srgrimes */ 163913544Sjoergvoid 16401558Srgrimessetbootflag(lp) 16411558Srgrimes register struct disklabel *lp; 16421558Srgrimes{ 16431558Srgrimes register struct partition *pp; 16441558Srgrimes int i, errors = 0; 16451558Srgrimes char part; 16461558Srgrimes u_long boffset; 16471558Srgrimes 16481558Srgrimes if (bootbuf == 0) 16491558Srgrimes return; 16501558Srgrimes boffset = bootsize / lp->d_secsize; 16511558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 16521558Srgrimes part = 'a' + i; 16531558Srgrimes pp = &lp->d_partitions[i]; 16541558Srgrimes if (pp->p_size == 0) 16551558Srgrimes continue; 16561558Srgrimes if (boffset <= pp->p_offset) { 16571558Srgrimes if (pp->p_fstype == FS_BOOT) 16581558Srgrimes pp->p_fstype = FS_UNUSED; 16591558Srgrimes } else if (pp->p_fstype != FS_BOOT) { 16601558Srgrimes if (pp->p_fstype != FS_UNUSED) { 16611558Srgrimes fprintf(stderr, 16621558Srgrimes "boot overlaps used partition %c\n", 16631558Srgrimes part); 16641558Srgrimes errors++; 16651558Srgrimes } else { 16661558Srgrimes pp->p_fstype = FS_BOOT; 16671558Srgrimes Warning("boot overlaps partition %c, %s", 16681558Srgrimes part, "marked as FS_BOOT"); 16691558Srgrimes } 16701558Srgrimes } 16711558Srgrimes } 167236632Scharnier if (errors) 167336632Scharnier errx(4, "cannot install boot program"); 16741558Srgrimes} 16751558Srgrimes 16761558Srgrimes/*VARARGS1*/ 167713544Sjoergvoid 167813544SjoergWarning(char *fmt, ...) 16791558Srgrimes{ 168013544Sjoerg va_list ap; 16811558Srgrimes 16821558Srgrimes fprintf(stderr, "Warning, "); 168313544Sjoerg va_start(ap, fmt); 168413544Sjoerg vfprintf(stderr, fmt, ap); 16851558Srgrimes fprintf(stderr, "\n"); 168613544Sjoerg va_end(ap); 16871558Srgrimes} 16881558Srgrimes 168913544Sjoergvoid 16901558Srgrimesusage() 16911558Srgrimes{ 16921558Srgrimes#if NUMBOOT > 0 169326542Scharnier 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", 169426542Scharnier "usage: disklabel [-r] disk", 169526542Scharnier "\t\t(to read label)", 169673034Sjwd " disklabel -w [-r] [-n] disk type [ packid ]", 169726542Scharnier "\t\t(to write label with existing boot program)", 169873034Sjwd " disklabel -e [-r] [-n] disk", 169926542Scharnier "\t\t(to edit label)", 170073034Sjwd " disklabel -R [-r] [-n] disk protofile", 170126542Scharnier "\t\t(to restore label with existing boot program)", 17021558Srgrimes#if NUMBOOT > 1 170373034Sjwd " disklabel -B [-n] [ -b boot1 [ -s boot2 ] ] disk [ type ]", 170426542Scharnier "\t\t(to install boot program with existing label)", 170573034Sjwd " disklabel -w -B [-n] [ -b boot1 [ -s boot2 ] ] disk type [ packid ]", 170626542Scharnier "\t\t(to write label and boot program)", 170773034Sjwd " disklabel -R -B [-n] [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]", 170826542Scharnier "\t\t(to restore label and boot program)", 17091558Srgrimes#else 171073034Sjwd " disklabel -B [-n] [ -b bootprog ] disk [ type ]", 171126542Scharnier "\t\t(to install boot program with existing on-disk label)", 171273034Sjwd " disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", 171326542Scharnier "\t\t(to write label and install boot program)", 171473034Sjwd " disklabel -R -B [-n] [ -b bootprog ] disk protofile [ type ]", 171526542Scharnier "\t\t(to restore label and install boot program)", 17161558Srgrimes#endif 171726542Scharnier " disklabel [-NW] disk", 171826542Scharnier "\t\t(to write disable/enable label)"); 17191558Srgrimes#else 172026542Scharnier fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 172126542Scharnier "usage: disklabel [-r] disk", "(to read label)", 172273034Sjwd " disklabel -w [-r] [-n] disk type [ packid ]", 172326542Scharnier "\t\t(to write label)", 172473034Sjwd " disklabel -e [-r] [-n] disk", 172526542Scharnier "\t\t(to edit label)", 172673034Sjwd " disklabel -R [-r] [-n] disk protofile", 172726542Scharnier "\t\t(to restore label)", 172826542Scharnier " disklabel [-NW] disk", 172926542Scharnier "\t\t(to write disable/enable label)"); 17301558Srgrimes#endif 17311558Srgrimes exit(1); 17321558Srgrimes} 1733