bsdlabel.c revision 96475
11558Srgrimes/* 292058Sobrien * Copyright (c) 1994, 1995 Gordon W. Ross 392058Sobrien * Copyright (c) 1994 Theo de Raadt 492058Sobrien * All rights reserved. 51558Srgrimes * Copyright (c) 1987, 1993 61558Srgrimes * The Regents of the University of California. All rights reserved. 71558Srgrimes * 81558Srgrimes * This code is derived from software contributed to Berkeley by 91558Srgrimes * Symmetric Computer Systems. 101558Srgrimes * 111558Srgrimes * Redistribution and use in source and binary forms, with or without 121558Srgrimes * modification, are permitted provided that the following conditions 131558Srgrimes * are met: 141558Srgrimes * 1. Redistributions of source code must retain the above copyright 151558Srgrimes * notice, this list of conditions and the following disclaimer. 161558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171558Srgrimes * notice, this list of conditions and the following disclaimer in the 181558Srgrimes * documentation and/or other materials provided with the distribution. 191558Srgrimes * 3. All advertising materials mentioning features or use of this software 201558Srgrimes * must display the following acknowledgement: 211558Srgrimes * This product includes software developed by the University of 221558Srgrimes * California, Berkeley and its contributors. 2392058Sobrien * This product includes software developed by Theo de Raadt. 241558Srgrimes * 4. Neither the name of the University nor the names of its contributors 251558Srgrimes * may be used to endorse or promote products derived from this software 261558Srgrimes * without specific prior written permission. 271558Srgrimes * 281558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 291558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 301558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 311558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 321558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 331558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 341558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 351558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 361558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 371558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 381558Srgrimes * SUCH DAMAGE. 3992058Sobrien * 4092058Sobrien * from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $ 411558Srgrimes */ 421558Srgrimes 431558Srgrimes#ifndef lint 4436632Scharnierstatic const char copyright[] = 451558Srgrimes"@(#) Copyright (c) 1987, 1993\n\ 461558Srgrimes The Regents of the University of California. All rights reserved.\n"; 471558Srgrimes#endif /* not lint */ 481558Srgrimes 491558Srgrimes#ifndef lint 5036632Scharnier#if 0 511558Srgrimesstatic char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; 521558Srgrimes/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 5336632Scharnier#endif 5436632Scharnierstatic const char rcsid[] = 5550476Speter "$FreeBSD: head/sbin/bsdlabel/bsdlabel.c 96475 2002-05-12 20:49:41Z phk $"; 561558Srgrimes#endif /* not lint */ 571558Srgrimes 581558Srgrimes#include <sys/param.h> 591558Srgrimes#include <sys/file.h> 601558Srgrimes#include <sys/stat.h> 6113544Sjoerg#include <sys/wait.h> 621558Srgrimes#define DKTYPENAMES 631558Srgrimes#include <sys/disklabel.h> 6492058Sobrien#ifdef __sparc64__ 6592058Sobrien#include <sys/sun_disklabel.h> 6692058Sobrien#endif 671558Srgrimes#include <unistd.h> 681558Srgrimes#include <string.h> 691558Srgrimes#include <stdio.h> 7013544Sjoerg#include <stdlib.h> 7113544Sjoerg#include <signal.h> 7213544Sjoerg#include <stdarg.h> 731558Srgrimes#include <ctype.h> 7426542Scharnier#include <err.h> 7559216Simp#include <errno.h> 761558Srgrimes#include "pathnames.h" 771558Srgrimes 781558Srgrimes/* 791558Srgrimes * Disklabel: read and write disklabels. 801558Srgrimes * The label is usually placed on one of the first sectors of the disk. 811558Srgrimes * Many machines also place a bootstrap in the same area, 821558Srgrimes * in which case the label is embedded in the bootstrap. 831558Srgrimes * The bootstrap source must leave space at the proper offset 841558Srgrimes * for the label on such machines. 851558Srgrimes */ 861558Srgrimes 871558Srgrimes#ifndef BBSIZE 881558Srgrimes#define BBSIZE 8192 /* size of boot area, with label */ 891558Srgrimes#endif 901558Srgrimes 9173034Sjwd/* FIX! These are too low, but are traditional */ 9273034Sjwd#define DEFAULT_NEWFS_BLOCK 8192U 9373034Sjwd#define DEFAULT_NEWFS_FRAG 1024U 9473034Sjwd#define DEFAULT_NEWFS_CPG 16U 9573034Sjwd 9673034Sjwd#define BIG_NEWFS_BLOCK 16384U 9773034Sjwd#define BIG_NEWFS_FRAG 4096U 9873034Sjwd#define BIG_NEWFS_CPG 64U 9973034Sjwd 10092057Sobrien#if defined(__i386__) || defined(__ia64__) 10192057Sobrien#define NUMBOOT 2 10292057Sobrien#elif defined(__alpha__) || defined(__sparc64__) 1031558Srgrimes#define NUMBOOT 1 1041558Srgrimes#else 10592057Sobrien#error I do not know about this architecture. 1061558Srgrimes#endif 1071558Srgrimes 10892541Simpvoid makelabel(const char *, const char *, struct disklabel *); 10992541Simpint writelabel(int, const char *, struct disklabel *); 11092541Simpvoid l_perror(const char *); 11192541Simpstruct disklabel *readlabel(int); 11292541Simpstruct disklabel *makebootarea(char *, struct disklabel *, int); 11392541Simpvoid display(FILE *, const struct disklabel *); 11492541Simpint edit(struct disklabel *, int); 11592541Simpint editit(void); 11692541Simpchar *skip(char *); 11792541Simpchar *word(char *); 11892541Simpint getasciilabel(FILE *, struct disklabel *); 11992541Simpint checklabel(struct disklabel *); 12092541Simpvoid setbootflag(struct disklabel *); 12192541Simpvoid Warning(const char *, ...) __printflike(1, 2); 12292541Simpvoid usage(void); 12392541Simpstruct disklabel *getvirginlabel(void); 12413544Sjoerg 1251558Srgrimes#define DEFEDITOR _PATH_VI 1261558Srgrimes#define streq(a,b) (strcmp(a,b) == 0) 1271558Srgrimes 1281558Srgrimeschar *dkname; 1291558Srgrimeschar *specname; 13055742Skrischar tmpfil[] = PATH_TMPFILE; 1311558Srgrimes 1321558Srgrimeschar namebuf[BBSIZE], *np = namebuf; 1331558Srgrimesstruct disklabel lab; 1341558Srgrimeschar bootarea[BBSIZE]; 1351558Srgrimes 13673034Sjwd#define MAX_PART ('z') 13773034Sjwd#define MAX_NUM_PARTS (1 + MAX_PART - 'a') 13873034Sjwdchar part_size_type[MAX_NUM_PARTS]; 13973034Sjwdchar part_offset_type[MAX_NUM_PARTS]; 14073034Sjwdint part_set[MAX_NUM_PARTS]; 14173034Sjwd 1421558Srgrimes#if NUMBOOT > 0 1431558Srgrimesint installboot; /* non-zero if we should install a boot program */ 1441558Srgrimeschar *bootbuf; /* pointer to buffer with remainder of boot prog */ 1451558Srgrimesint bootsize; /* size of remaining boot program */ 1461558Srgrimeschar *xxboot; /* primary boot */ 1471558Srgrimeschar *bootxx; /* secondary boot */ 1481558Srgrimeschar boot0[MAXPATHLEN]; 1491558Srgrimeschar boot1[MAXPATHLEN]; 1501558Srgrimes#endif 1511558Srgrimes 1521558Srgrimesenum { 1531558Srgrimes UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT 1541558Srgrimes} op = UNSPEC; 1551558Srgrimes 1561558Srgrimesint rflag; 15773034Sjwdint disable_write; /* set to disable writing to disk label */ 1581558Srgrimes 15973034Sjwd#define OPTIONS "BNRWb:enrs:w" 1601558Srgrimes 16113544Sjoergint 16292541Simpmain(int argc, char *argv[]) 1631558Srgrimes{ 16492715Simp struct disklabel *lp; 1651558Srgrimes FILE *t; 16648957Sbillf int ch, f = 0, flag, error = 0; 1671558Srgrimes char *name = 0; 1681558Srgrimes 16924359Simp while ((ch = getopt(argc, argv, OPTIONS)) != -1) 1701558Srgrimes switch (ch) { 1711558Srgrimes#if NUMBOOT > 0 1721558Srgrimes case 'B': 1731558Srgrimes ++installboot; 1741558Srgrimes break; 1751558Srgrimes case 'b': 1761558Srgrimes xxboot = optarg; 1771558Srgrimes break; 1781558Srgrimes#if NUMBOOT > 1 1791558Srgrimes case 's': 1801558Srgrimes bootxx = optarg; 1811558Srgrimes break; 1821558Srgrimes#endif 1831558Srgrimes#endif 1841558Srgrimes case 'N': 1851558Srgrimes if (op != UNSPEC) 1861558Srgrimes usage(); 1871558Srgrimes op = NOWRITE; 1881558Srgrimes break; 18973034Sjwd case 'n': 19073034Sjwd disable_write = 1; 19173034Sjwd break; 1921558Srgrimes case 'R': 1931558Srgrimes if (op != UNSPEC) 1941558Srgrimes usage(); 1951558Srgrimes op = RESTORE; 1961558Srgrimes break; 1971558Srgrimes case 'W': 1981558Srgrimes if (op != UNSPEC) 1991558Srgrimes usage(); 2001558Srgrimes op = WRITEABLE; 2011558Srgrimes break; 2021558Srgrimes case 'e': 2031558Srgrimes if (op != UNSPEC) 2041558Srgrimes usage(); 2051558Srgrimes op = EDIT; 2061558Srgrimes break; 2071558Srgrimes case 'r': 2081558Srgrimes ++rflag; 2091558Srgrimes break; 2101558Srgrimes case 'w': 2111558Srgrimes if (op != UNSPEC) 2121558Srgrimes usage(); 2131558Srgrimes op = WRITE; 2141558Srgrimes break; 2151558Srgrimes case '?': 2161558Srgrimes default: 2171558Srgrimes usage(); 2181558Srgrimes } 2191558Srgrimes argc -= optind; 2201558Srgrimes argv += optind; 2211558Srgrimes#if NUMBOOT > 0 2221558Srgrimes if (installboot) { 2231558Srgrimes rflag++; 2241558Srgrimes if (op == UNSPEC) 2251558Srgrimes op = WRITEBOOT; 2261558Srgrimes } else { 2271558Srgrimes if (op == UNSPEC) 2281558Srgrimes op = READ; 2291558Srgrimes xxboot = bootxx = 0; 2301558Srgrimes } 2311558Srgrimes#else 2321558Srgrimes if (op == UNSPEC) 2331558Srgrimes op = READ; 2341558Srgrimes#endif 2351558Srgrimes if (argc < 1) 2361558Srgrimes usage(); 2371558Srgrimes 2381558Srgrimes dkname = argv[0]; 2391558Srgrimes if (dkname[0] != '/') { 24059114Sobrien (void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); 2411558Srgrimes specname = np; 2421558Srgrimes np += strlen(specname) + 1; 2431558Srgrimes } else 2441558Srgrimes specname = dkname; 2451558Srgrimes f = open(specname, op == READ ? O_RDONLY : O_RDWR); 2461558Srgrimes if (f < 0 && errno == ENOENT && dkname[0] != '/') { 24759429Sobrien (void)sprintf(specname, "%s%s", _PATH_DEV, dkname); 2481558Srgrimes np = namebuf + strlen(specname) + 1; 2491558Srgrimes f = open(specname, op == READ ? O_RDONLY : O_RDWR); 2501558Srgrimes } 2511558Srgrimes if (f < 0) 25226542Scharnier err(4, "%s", specname); 2531558Srgrimes 2541558Srgrimes switch(op) { 2551558Srgrimes 25648957Sbillf case UNSPEC: 25748957Sbillf break; 25848957Sbillf 2591558Srgrimes case EDIT: 2601558Srgrimes if (argc != 1) 2611558Srgrimes usage(); 2621558Srgrimes lp = readlabel(f); 2631558Srgrimes error = edit(lp, f); 2641558Srgrimes break; 2651558Srgrimes 2661558Srgrimes case NOWRITE: 2671558Srgrimes flag = 0; 2681558Srgrimes if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 26926542Scharnier err(4, "ioctl DIOCWLABEL"); 2701558Srgrimes break; 2711558Srgrimes 2721558Srgrimes case READ: 2731558Srgrimes if (argc != 1) 2741558Srgrimes usage(); 2751558Srgrimes lp = readlabel(f); 2761558Srgrimes display(stdout, lp); 2771558Srgrimes error = checklabel(lp); 2781558Srgrimes break; 2791558Srgrimes 2801558Srgrimes case RESTORE: 2811558Srgrimes#if NUMBOOT > 0 2821558Srgrimes if (installboot && argc == 3) { 2831558Srgrimes makelabel(argv[2], 0, &lab); 2841558Srgrimes argc--; 28537865Sbde 28637865Sbde /* 28737865Sbde * We only called makelabel() for its side effect 28837865Sbde * of setting the bootstrap file names. Discard 28937865Sbde * all changes to `lab' so that all values in the 29037865Sbde * final label come from the ASCII label. 29137865Sbde */ 29237865Sbde bzero((char *)&lab, sizeof(lab)); 2931558Srgrimes } 2941558Srgrimes#endif 2951558Srgrimes if (argc != 2) 2961558Srgrimes usage(); 2971558Srgrimes if (!(t = fopen(argv[1], "r"))) 29826542Scharnier err(4, "%s", argv[1]); 29937865Sbde if (!getasciilabel(t, &lab)) 30037865Sbde exit(1); 30137865Sbde lp = makebootarea(bootarea, &lab, f); 30237865Sbde *lp = lab; 30337865Sbde error = writelabel(f, bootarea, lp); 3041558Srgrimes break; 3051558Srgrimes 3061558Srgrimes case WRITE: 3071558Srgrimes if (argc == 3) { 3081558Srgrimes name = argv[2]; 3091558Srgrimes argc--; 3101558Srgrimes } 3111558Srgrimes if (argc != 2) 3121558Srgrimes usage(); 3131558Srgrimes makelabel(argv[1], name, &lab); 3141558Srgrimes lp = makebootarea(bootarea, &lab, f); 3151558Srgrimes *lp = lab; 3161558Srgrimes if (checklabel(lp) == 0) 3171558Srgrimes error = writelabel(f, bootarea, lp); 3181558Srgrimes break; 3191558Srgrimes 3201558Srgrimes case WRITEABLE: 3211558Srgrimes flag = 1; 3221558Srgrimes if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 32326542Scharnier err(4, "ioctl DIOCWLABEL"); 3241558Srgrimes break; 3251558Srgrimes 3261558Srgrimes#if NUMBOOT > 0 3271558Srgrimes case WRITEBOOT: 3281558Srgrimes { 3291558Srgrimes struct disklabel tlab; 3301558Srgrimes 3311558Srgrimes lp = readlabel(f); 3321558Srgrimes tlab = *lp; 3331558Srgrimes if (argc == 2) 3341558Srgrimes makelabel(argv[1], 0, &lab); 3351558Srgrimes lp = makebootarea(bootarea, &lab, f); 3361558Srgrimes *lp = tlab; 3371558Srgrimes if (checklabel(lp) == 0) 3381558Srgrimes error = writelabel(f, bootarea, lp); 3391558Srgrimes break; 3401558Srgrimes } 3411558Srgrimes#endif 3421558Srgrimes } 3431558Srgrimes exit(error); 3441558Srgrimes} 3451558Srgrimes 3461558Srgrimes/* 3471558Srgrimes * Construct a prototype disklabel from /etc/disktab. As a side 3481558Srgrimes * effect, set the names of the primary and secondary boot files 3491558Srgrimes * if specified. 3501558Srgrimes */ 35113544Sjoergvoid 35292541Simpmakelabel(const char *type, const char *name, struct disklabel *lp) 3531558Srgrimes{ 35492541Simp struct disklabel *dp; 35513550Sjoerg 35613550Sjoerg if (strcmp(type, "auto") == 0) 35713550Sjoerg dp = getvirginlabel(); 35813550Sjoerg else 35913544Sjoerg dp = getdiskbyname(type); 36036632Scharnier if (dp == NULL) 36136632Scharnier errx(1, "%s: unknown disk type", type); 3621558Srgrimes *lp = *dp; 3631558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 3641558Srgrimes if (name) 3651558Srgrimes (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 3661558Srgrimes} 3671558Srgrimes 36813544Sjoergint 36992541Simpwritelabel(int f, const char *boot, struct disklabel *lp) 3701558Srgrimes{ 3711558Srgrimes int flag; 37238384Sdfr#ifdef __alpha__ 37338384Sdfr u_long *p, sum; 37438384Sdfr int i; 37538384Sdfr#endif 37692058Sobrien#ifdef __sparc64__ 37792058Sobrien struct sun_disklabel *sl; 37892058Sobrien u_short cksum, *sp1, *sp2; 37992058Sobrien struct partition *npp; 38092058Sobrien struct sun_dkpart *spp; 38192058Sobrien int i, secpercyl; 38238411Sbde#endif 38338384Sdfr 38473034Sjwd if (disable_write) { 38573034Sjwd Warning("write to disk label supressed - label was as follows:"); 38673034Sjwd display(stdout, lp); 38773034Sjwd return (0); 38873034Sjwd } else { 38973034Sjwd setbootflag(lp); 39073034Sjwd lp->d_magic = DISKMAGIC; 39173034Sjwd lp->d_magic2 = DISKMAGIC; 39273034Sjwd lp->d_checksum = 0; 39373034Sjwd lp->d_checksum = dkcksum(lp); 39473034Sjwd if (rflag) { 39573034Sjwd /* 39673034Sjwd * First set the kernel disk label, 39773034Sjwd * then write a label to the raw disk. 39873034Sjwd * If the SDINFO ioctl fails because it is unimplemented, 39973034Sjwd * keep going; otherwise, the kernel consistency checks 40073034Sjwd * may prevent us from changing the current (in-core) 40173034Sjwd * label. 40273034Sjwd */ 40373034Sjwd if (ioctl(f, DIOCSDINFO, lp) < 0 && 40473034Sjwd errno != ENODEV && errno != ENOTTY) { 40573034Sjwd l_perror("ioctl DIOCSDINFO"); 40673034Sjwd return (1); 40773034Sjwd } 40873034Sjwd (void)lseek(f, (off_t)0, SEEK_SET); 40973034Sjwd 41038411Sbde#ifdef __alpha__ 41173034Sjwd /* 41273034Sjwd * Generate the bootblock checksum for the SRM console. 41373034Sjwd */ 41473034Sjwd for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) 41573034Sjwd sum += p[i]; 41673034Sjwd p[63] = sum; 41738384Sdfr#endif 41892058Sobrien#ifdef __sparc64__ 41973034Sjwd /* 42092058Sobrien * Generate a Sun disklabel around the BSD label for 42192058Sobrien * PROM compatability. 42292058Sobrien */ 42392058Sobrien sl = (struct sun_disklabel *)boot; 42492058Sobrien memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); 42592058Sobrien sl->sl_rpm = lp->d_rpm; 42692058Sobrien sl->sl_pcylinders = lp->d_ncylinders + 42792058Sobrien lp->d_acylinders; /* XXX */ 42892058Sobrien sl->sl_sparespercyl = lp->d_sparespercyl; 42992058Sobrien sl->sl_interleave = lp->d_interleave; 43092058Sobrien sl->sl_ncylinders = lp->d_ncylinders; 43192058Sobrien sl->sl_acylinders = lp->d_acylinders; 43292058Sobrien sl->sl_ntracks = lp->d_ntracks; 43392058Sobrien sl->sl_nsectors = lp->d_nsectors; 43492058Sobrien sl->sl_magic = SUN_DKMAGIC; 43592058Sobrien secpercyl = sl->sl_nsectors * sl->sl_ntracks; 43692058Sobrien for (i = 0; i < 8; i++) { 43792058Sobrien spp = &sl->sl_part[i]; 43892058Sobrien npp = &lp->d_partitions[i]; 43992058Sobrien /* 44092058Sobrien * SunOS partitions must start on a cylinder 44192058Sobrien * boundary. Note this restriction is forced 44292058Sobrien * upon FreeBSD/sparc64 labels too, since we 44392058Sobrien * want to keep both labels synchronised. 44492058Sobrien */ 44592058Sobrien spp->sdkp_cyloffset = npp->p_offset / secpercyl; 44692058Sobrien spp->sdkp_nsectors = npp->p_size; 44792058Sobrien } 44892058Sobrien 44992058Sobrien /* Compute the XOR checksum. */ 45092058Sobrien sp1 = (u_short *)sl; 45192058Sobrien sp2 = (u_short *)(sl + 1); 45292058Sobrien sl->sl_cksum = cksum = 0; 45392058Sobrien while (sp1 < sp2) 45492058Sobrien cksum ^= *sp1++; 45592058Sobrien sl->sl_cksum = cksum; 45692058Sobrien#endif 45792058Sobrien /* 45873034Sjwd * write enable label sector before write (if necessary), 45973034Sjwd * disable after writing. 46073034Sjwd */ 46173034Sjwd flag = 1; 46273034Sjwd if (ioctl(f, DIOCWLABEL, &flag) < 0) 46373034Sjwd warn("ioctl DIOCWLABEL"); 46473034Sjwd if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 46573034Sjwd warn("write"); 46673034Sjwd return (1); 46773034Sjwd } 46873034Sjwd#if NUMBOOT > 0 46973034Sjwd /* 47073034Sjwd * Output the remainder of the disklabel 47173034Sjwd */ 47273034Sjwd if (bootbuf && write(f, bootbuf, bootsize) != bootsize) { 47373034Sjwd warn("write"); 47473034Sjwd return(1); 47573034Sjwd } 47673034Sjwd#endif 47773034Sjwd flag = 0; 47873034Sjwd (void) ioctl(f, DIOCWLABEL, &flag); 47973034Sjwd } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 48073034Sjwd l_perror("ioctl DIOCWDINFO"); 4811558Srgrimes return (1); 4821558Srgrimes } 4831558Srgrimes } 4841558Srgrimes return (0); 4851558Srgrimes} 4861558Srgrimes 48713544Sjoergvoid 48892541Simpl_perror(const char *s) 4891558Srgrimes{ 49036632Scharnier switch (errno) { 4911558Srgrimes 4921558Srgrimes case ESRCH: 49336756Scharnier warnx("%s: no disk label on disk;", s); 49475915Simp fprintf(stderr, "add \"-r\" to install initial label\n"); 4951558Srgrimes break; 4961558Srgrimes 4971558Srgrimes case EINVAL: 49836756Scharnier warnx("%s: label magic number or checksum is wrong!", s); 49936756Scharnier fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 5001558Srgrimes break; 5011558Srgrimes 5021558Srgrimes case EBUSY: 50336632Scharnier warnx("%s: open partition would move or shrink", s); 5041558Srgrimes break; 5051558Srgrimes 5061558Srgrimes case EXDEV: 50740475Sbde warnx("%s: '%c' partition must start at beginning of disk", 50840475Sbde s, 'a' + RAW_PART); 5091558Srgrimes break; 5101558Srgrimes 5111558Srgrimes default: 51236632Scharnier warn((char *)NULL); 5131558Srgrimes break; 5141558Srgrimes } 5151558Srgrimes} 5161558Srgrimes 5171558Srgrimes/* 5181558Srgrimes * Fetch disklabel for disk. 5191558Srgrimes * Use ioctl to get label unless -r flag is given. 5201558Srgrimes */ 5211558Srgrimesstruct disklabel * 52292541Simpreadlabel(int f) 5231558Srgrimes{ 52492541Simp struct disklabel *lp; 5251558Srgrimes 5261558Srgrimes if (rflag) { 5271558Srgrimes if (read(f, bootarea, BBSIZE) < BBSIZE) 52826542Scharnier err(4, "%s", specname); 5291558Srgrimes for (lp = (struct disklabel *)bootarea; 5301558Srgrimes lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 5311558Srgrimes lp = (struct disklabel *)((char *)lp + 16)) 5321558Srgrimes if (lp->d_magic == DISKMAGIC && 5331558Srgrimes lp->d_magic2 == DISKMAGIC) 5341558Srgrimes break; 5351558Srgrimes if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 5361558Srgrimes lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 53736756Scharnier dkcksum(lp) != 0) 53836756Scharnier errx(1, 53936756Scharnier "bad pack magic number (label is damaged, or pack is unlabeled)"); 5401558Srgrimes } else { 5411558Srgrimes lp = &lab; 5421558Srgrimes if (ioctl(f, DIOCGDINFO, lp) < 0) 54326542Scharnier err(4, "ioctl DIOCGDINFO"); 5441558Srgrimes } 5451558Srgrimes return (lp); 5461558Srgrimes} 5471558Srgrimes 5481558Srgrimes/* 5491558Srgrimes * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 5501558Srgrimes * Returns a pointer to the disklabel portion of the bootarea. 5511558Srgrimes */ 5521558Srgrimesstruct disklabel * 55392541Simpmakebootarea(char *boot, struct disklabel *dp, int f) 5541558Srgrimes{ 55538483Sbde struct disklabel *lp; 55692541Simp char *p; 5571558Srgrimes int b; 5581558Srgrimes#if NUMBOOT > 0 5591558Srgrimes char *dkbasename; 5601558Srgrimes struct stat sb; 56138411Sbde#endif 56238411Sbde#ifdef __alpha__ 56338483Sbde u_long *bootinfo; 56438411Sbde int n; 56538411Sbde#endif 56613892Sjoerg#ifdef __i386__ 56713892Sjoerg char *tmpbuf; 56813892Sjoerg int i, found; 56913544Sjoerg#endif 5701558Srgrimes 5711558Srgrimes /* XXX */ 5721558Srgrimes if (dp->d_secsize == 0) { 5731558Srgrimes dp->d_secsize = DEV_BSIZE; 5741558Srgrimes dp->d_bbsize = BBSIZE; 5751558Srgrimes } 5761558Srgrimes lp = (struct disklabel *) 5771558Srgrimes (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 5781558Srgrimes bzero((char *)lp, sizeof *lp); 5791558Srgrimes#if NUMBOOT > 0 5801558Srgrimes /* 5811558Srgrimes * If we are not installing a boot program but we are installing a 5821558Srgrimes * label on disk then we must read the current bootarea so we don't 5831558Srgrimes * clobber the existing boot. 5841558Srgrimes */ 5851558Srgrimes if (!installboot) { 5861558Srgrimes if (rflag) { 5871558Srgrimes if (read(f, boot, BBSIZE) < BBSIZE) 58826542Scharnier err(4, "%s", specname); 5891558Srgrimes bzero((char *)lp, sizeof *lp); 5901558Srgrimes } 5911558Srgrimes return (lp); 5921558Srgrimes } 5931558Srgrimes /* 5941558Srgrimes * We are installing a boot program. Determine the name(s) and 5951558Srgrimes * read them into the appropriate places in the boot area. 5961558Srgrimes */ 5971558Srgrimes if (!xxboot || !bootxx) { 5981558Srgrimes dkbasename = np; 5991558Srgrimes if ((p = rindex(dkname, '/')) == NULL) 6001558Srgrimes p = dkname; 6011558Srgrimes else 6021558Srgrimes p++; 6031558Srgrimes while (*p && !isdigit(*p)) 6041558Srgrimes *np++ = *p++; 6051558Srgrimes *np++ = '\0'; 6061558Srgrimes 6071558Srgrimes if (!xxboot) { 60841901Sjkh (void)sprintf(boot0, "%s/boot1", _PATH_BOOTDIR); 60941901Sjkh xxboot = boot0; 6101558Srgrimes } 6111558Srgrimes#if NUMBOOT > 1 6121558Srgrimes if (!bootxx) { 61341901Sjkh (void)sprintf(boot1, "%s/boot2", _PATH_BOOTDIR); 61441901Sjkh bootxx = boot1; 6151558Srgrimes } 6161558Srgrimes#endif 6171558Srgrimes } 6181558Srgrimes 6191558Srgrimes /* 6201558Srgrimes * Strange rules: 62192058Sobrien * 1. One-piece bootstrap (hp300/hp800) 62292057Sobrien * 1. One-piece bootstrap (alpha/sparc64) 6231558Srgrimes * up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest 6241558Srgrimes * is remembered and written later following the bootarea. 62592058Sobrien * 2. Two-piece bootstraps (i386/ia64) 6261558Srgrimes * up to d_secsize bytes of ``xxboot'' go in first d_secsize 6271558Srgrimes * bytes of bootarea, remaining d_bbsize-d_secsize filled 6281558Srgrimes * from ``bootxx''. 6291558Srgrimes */ 6301558Srgrimes b = open(xxboot, O_RDONLY); 6311558Srgrimes if (b < 0) 63226542Scharnier err(4, "%s", xxboot); 6331558Srgrimes#if NUMBOOT > 1 63413892Sjoerg#ifdef __i386__ 63513892Sjoerg /* 63613892Sjoerg * XXX Botch alert. 63713892Sjoerg * The i386 has the so-called fdisk table embedded into the 63813892Sjoerg * primary bootstrap. We take care to not clobber it, but 63913892Sjoerg * only if it does already contain some data. (Otherwise, 64013892Sjoerg * the xxboot provides a template.) 64113892Sjoerg */ 64213892Sjoerg if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) 64326542Scharnier err(4, "%s", xxboot); 64413892Sjoerg memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); 64513892Sjoerg#endif /* i386 */ 6461558Srgrimes if (read(b, boot, (int)dp->d_secsize) < 0) 64726542Scharnier err(4, "%s", xxboot); 6481558Srgrimes (void)close(b); 64913892Sjoerg#ifdef __i386__ 65013892Sjoerg for (i = DOSPARTOFF, found = 0; 65113892Sjoerg !found && i < DOSPARTOFF + NDOSPART*sizeof(struct dos_partition); 65213892Sjoerg i++) 65313892Sjoerg found = tmpbuf[i] != 0; 65413892Sjoerg if (found) 65513892Sjoerg memcpy((void *)&boot[DOSPARTOFF], 65613892Sjoerg (void *)&tmpbuf[DOSPARTOFF], 65713892Sjoerg NDOSPART * sizeof(struct dos_partition)); 65813892Sjoerg free(tmpbuf); 65913892Sjoerg#endif /* i386 */ 6601558Srgrimes b = open(bootxx, O_RDONLY); 6611558Srgrimes if (b < 0) 66226542Scharnier err(4, "%s", bootxx); 66337865Sbde if (fstat(b, &sb) != 0) 66437865Sbde err(4, "%s", bootxx); 66537865Sbde if (dp->d_secsize + sb.st_size > dp->d_bbsize) 66637865Sbde errx(4, "%s too large", bootxx); 66713544Sjoerg if (read(b, &boot[dp->d_secsize], 66813544Sjoerg (int)(dp->d_bbsize-dp->d_secsize)) < 0) 66926542Scharnier err(4, "%s", bootxx); 67038411Sbde#else /* !(NUMBOOT > 1) */ 67138384Sdfr#ifdef __alpha__ 67238411Sbde /* 67338411Sbde * On the alpha, the primary bootstrap starts at the 67438411Sbde * second sector of the boot area. The first sector 67538411Sbde * contains the label and must be edited to contain the 67638411Sbde * size and location of the primary bootstrap. 67738411Sbde */ 67838411Sbde n = read(b, boot + dp->d_secsize, (int)dp->d_bbsize); 67938411Sbde if (n < 0) 68038384Sdfr err(4, "%s", xxboot); 68138483Sbde bootinfo = (u_long *)(boot + 480); 68238483Sbde bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; 68338483Sbde bootinfo[1] = 1; /* start at sector 1 */ 68438483Sbde bootinfo[2] = 0; /* flags (must be zero) */ 68538411Sbde#else /* !__alpha__ */ 6861558Srgrimes if (read(b, boot, (int)dp->d_bbsize) < 0) 68726542Scharnier err(4, "%s", xxboot); 68838411Sbde#endif /* __alpha__ */ 68937865Sbde if (fstat(b, &sb) != 0) 69037865Sbde err(4, "%s", xxboot); 6911558Srgrimes bootsize = (int)sb.st_size - dp->d_bbsize; 6921558Srgrimes if (bootsize > 0) { 6931558Srgrimes /* XXX assume d_secsize is a power of two */ 6941558Srgrimes bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1); 6951558Srgrimes bootbuf = (char *)malloc((size_t)bootsize); 6961558Srgrimes if (bootbuf == 0) 69726542Scharnier err(4, "%s", xxboot); 6981558Srgrimes if (read(b, bootbuf, bootsize) < 0) { 6991558Srgrimes free(bootbuf); 70026542Scharnier err(4, "%s", xxboot); 7011558Srgrimes } 7021558Srgrimes } 70338411Sbde#endif /* NUMBOOT > 1 */ 7041558Srgrimes (void)close(b); 70538411Sbde#endif /* NUMBOOT > 0 */ 7061558Srgrimes /* 7071558Srgrimes * Make sure no part of the bootstrap is written in the area 7081558Srgrimes * reserved for the label. 7091558Srgrimes */ 7101558Srgrimes for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 71136632Scharnier if (*p) 71236632Scharnier errx(2, "bootstrap doesn't leave room for disk label"); 7131558Srgrimes return (lp); 7141558Srgrimes} 7151558Srgrimes 71613544Sjoergvoid 71792541Simpdisplay(FILE *f, const struct disklabel *lp) 7181558Srgrimes{ 71992541Simp int i, j; 72092541Simp const struct partition *pp; 7211558Srgrimes 7221558Srgrimes fprintf(f, "# %s:\n", specname); 7231558Srgrimes if ((unsigned) lp->d_type < DKMAXTYPES) 7241558Srgrimes fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 7251558Srgrimes else 72637234Sbde fprintf(f, "type: %u\n", lp->d_type); 72713544Sjoerg fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 72813544Sjoerg lp->d_typename); 72913544Sjoerg fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 73013544Sjoerg lp->d_packname); 7311558Srgrimes fprintf(f, "flags:"); 7321558Srgrimes if (lp->d_flags & D_REMOVABLE) 7331558Srgrimes fprintf(f, " removeable"); 7341558Srgrimes if (lp->d_flags & D_ECC) 7351558Srgrimes fprintf(f, " ecc"); 7361558Srgrimes if (lp->d_flags & D_BADSECT) 7371558Srgrimes fprintf(f, " badsect"); 7381558Srgrimes fprintf(f, "\n"); 73937234Sbde fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 74037234Sbde fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 74137234Sbde fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 74237234Sbde fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 74337234Sbde fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 74437234Sbde fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 74537234Sbde fprintf(f, "rpm: %u\n", lp->d_rpm); 74637234Sbde fprintf(f, "interleave: %u\n", lp->d_interleave); 74737234Sbde fprintf(f, "trackskew: %u\n", lp->d_trackskew); 74837234Sbde fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 74937234Sbde fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 75037234Sbde (u_long)lp->d_headswitch); 75113544Sjoerg fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 75237234Sbde (u_long)lp->d_trkseek); 7531558Srgrimes fprintf(f, "drivedata: "); 7541558Srgrimes for (i = NDDATA - 1; i >= 0; i--) 7551558Srgrimes if (lp->d_drivedata[i]) 7561558Srgrimes break; 7571558Srgrimes if (i < 0) 7581558Srgrimes i = 0; 7591558Srgrimes for (j = 0; j <= i; j++) 76037234Sbde fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 76137234Sbde fprintf(f, "\n\n%u partitions:\n", lp->d_npartitions); 7621558Srgrimes fprintf(f, 7635393Sgibbs "# size offset fstype [fsize bsize bps/cpg]\n"); 7641558Srgrimes pp = lp->d_partitions; 7651558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 7661558Srgrimes if (pp->p_size) { 76737234Sbde fprintf(f, " %c: %8lu %8lu ", 'a' + i, 76837234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 7691558Srgrimes if ((unsigned) pp->p_fstype < FSMAXTYPES) 7701558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 7711558Srgrimes else 7721558Srgrimes fprintf(f, "%8d", pp->p_fstype); 7731558Srgrimes switch (pp->p_fstype) { 7741558Srgrimes 7751558Srgrimes case FS_UNUSED: /* XXX */ 77637234Sbde fprintf(f, " %5lu %5lu %5.5s ", 77737234Sbde (u_long)pp->p_fsize, 77837234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 7791558Srgrimes break; 7801558Srgrimes 7811558Srgrimes case FS_BSDFFS: 78237234Sbde fprintf(f, " %5lu %5lu %5u ", 78337234Sbde (u_long)pp->p_fsize, 78437234Sbde (u_long)(pp->p_fsize * pp->p_frag), 7851558Srgrimes pp->p_cpg); 7861558Srgrimes break; 7871558Srgrimes 7885393Sgibbs case FS_BSDLFS: 78937234Sbde fprintf(f, " %5lu %5lu %5d", 79037234Sbde (u_long)pp->p_fsize, 79137234Sbde (u_long)(pp->p_fsize * pp->p_frag), 7925393Sgibbs pp->p_cpg); 7935393Sgibbs break; 7945393Sgibbs 7951558Srgrimes default: 7961558Srgrimes fprintf(f, "%20.20s", ""); 7971558Srgrimes break; 7981558Srgrimes } 79937234Sbde fprintf(f, "\t# (Cyl. %4lu", 80037234Sbde (u_long)(pp->p_offset / lp->d_secpercyl)); 8011558Srgrimes if (pp->p_offset % lp->d_secpercyl) 8021558Srgrimes putc('*', f); 8031558Srgrimes else 8041558Srgrimes putc(' ', f); 80537234Sbde fprintf(f, "- %lu", 80637234Sbde (u_long)((pp->p_offset + pp->p_size + 80737234Sbde lp->d_secpercyl - 1) / 80837234Sbde lp->d_secpercyl - 1)); 8091558Srgrimes if (pp->p_size % lp->d_secpercyl) 8101558Srgrimes putc('*', f); 8111558Srgrimes fprintf(f, ")\n"); 8121558Srgrimes } 8131558Srgrimes } 8141558Srgrimes fflush(f); 8151558Srgrimes} 8161558Srgrimes 81713544Sjoergint 81892541Simpedit(struct disklabel *lp, int f) 8191558Srgrimes{ 82092541Simp int c, fd; 8211558Srgrimes struct disklabel label; 82224180Simp FILE *fp; 8231558Srgrimes 82424180Simp if ((fd = mkstemp(tmpfil)) == -1 || 82524180Simp (fp = fdopen(fd, "w")) == NULL) { 82636632Scharnier warnx("can't create %s", tmpfil); 8271558Srgrimes return (1); 8281558Srgrimes } 82924180Simp display(fp, lp); 83024180Simp fclose(fp); 8311558Srgrimes for (;;) { 8321558Srgrimes if (!editit()) 8331558Srgrimes break; 83424180Simp fp = fopen(tmpfil, "r"); 83524180Simp if (fp == NULL) { 83636632Scharnier warnx("can't reopen %s for reading", tmpfil); 8371558Srgrimes break; 8381558Srgrimes } 8391558Srgrimes bzero((char *)&label, sizeof(label)); 84024180Simp if (getasciilabel(fp, &label)) { 8411558Srgrimes *lp = label; 8421558Srgrimes if (writelabel(f, bootarea, lp) == 0) { 84324180Simp fclose(fp); 8441558Srgrimes (void) unlink(tmpfil); 8451558Srgrimes return (0); 8461558Srgrimes } 8471558Srgrimes } 84824180Simp fclose(fp); 8491558Srgrimes printf("re-edit the label? [y]: "); fflush(stdout); 8501558Srgrimes c = getchar(); 8511558Srgrimes if (c != EOF && c != (int)'\n') 8521558Srgrimes while (getchar() != (int)'\n') 8531558Srgrimes ; 8541558Srgrimes if (c == (int)'n') 8551558Srgrimes break; 8561558Srgrimes } 8571558Srgrimes (void) unlink(tmpfil); 8581558Srgrimes return (1); 8591558Srgrimes} 8601558Srgrimes 86113544Sjoergint 86292541Simpeditit(void) 8631558Srgrimes{ 86492541Simp int pid, xpid; 8651558Srgrimes int stat, omask; 86692541Simp char *ed; 8671558Srgrimes 8681558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 8691558Srgrimes while ((pid = fork()) < 0) { 8701558Srgrimes if (errno == EPROCLIM) { 87136632Scharnier warnx("you have too many processes"); 8721558Srgrimes return(0); 8731558Srgrimes } 8741558Srgrimes if (errno != EAGAIN) { 87536632Scharnier warn("fork"); 8761558Srgrimes return(0); 8771558Srgrimes } 8781558Srgrimes sleep(1); 8791558Srgrimes } 8801558Srgrimes if (pid == 0) { 8811558Srgrimes sigsetmask(omask); 8821558Srgrimes setgid(getgid()); 8831558Srgrimes setuid(getuid()); 8841558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 8851558Srgrimes ed = DEFEDITOR; 88679452Sbrian execlp(ed, ed, tmpfil, (char *)0); 88736632Scharnier err(1, "%s", ed); 8881558Srgrimes } 8891558Srgrimes while ((xpid = wait(&stat)) >= 0) 8901558Srgrimes if (xpid == pid) 8911558Srgrimes break; 8921558Srgrimes sigsetmask(omask); 8931558Srgrimes return(!stat); 8941558Srgrimes} 8951558Srgrimes 8961558Srgrimeschar * 89792541Simpskip(char *cp) 8981558Srgrimes{ 8991558Srgrimes 9001558Srgrimes while (*cp != '\0' && isspace(*cp)) 9011558Srgrimes cp++; 9021558Srgrimes if (*cp == '\0' || *cp == '#') 90392541Simp return (NULL); 9041558Srgrimes return (cp); 9051558Srgrimes} 9061558Srgrimes 9071558Srgrimeschar * 90892541Simpword(char *cp) 9091558Srgrimes{ 91092541Simp char c; 9111558Srgrimes 9121558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 9131558Srgrimes cp++; 9141558Srgrimes if ((c = *cp) != '\0') { 9151558Srgrimes *cp++ = '\0'; 9161558Srgrimes if (c != '#') 9171558Srgrimes return (skip(cp)); 9181558Srgrimes } 91992541Simp return (NULL); 9201558Srgrimes} 9211558Srgrimes 9221558Srgrimes/* 9231558Srgrimes * Read an ascii label in from fd f, 9241558Srgrimes * in the same format as that put out by display(), 9251558Srgrimes * and fill in lp. 9261558Srgrimes */ 92713544Sjoergint 92892541Simpgetasciilabel(FILE *f, struct disklabel *lp) 9291558Srgrimes{ 93094065Sphk char *cp; 93194065Sphk const char **cpp; 93292541Simp struct partition *pp; 93373034Sjwd unsigned int part; 93494065Sphk char *tp, line[BUFSIZ]; 9351558Srgrimes int v, lineno = 0, errors = 0; 93692541Simp int i; 9371558Srgrimes 9381558Srgrimes lp->d_bbsize = BBSIZE; /* XXX */ 93996475Sphk lp->d_sbsize = 0; /* XXX */ 9401558Srgrimes while (fgets(line, sizeof(line) - 1, f)) { 9411558Srgrimes lineno++; 94213544Sjoerg if ((cp = index(line,'\n')) != 0) 9431558Srgrimes *cp = '\0'; 9441558Srgrimes cp = skip(line); 9451558Srgrimes if (cp == NULL) 9461558Srgrimes continue; 9471558Srgrimes tp = index(cp, ':'); 9481558Srgrimes if (tp == NULL) { 9491558Srgrimes fprintf(stderr, "line %d: syntax error\n", lineno); 9501558Srgrimes errors++; 9511558Srgrimes continue; 9521558Srgrimes } 9531558Srgrimes *tp++ = '\0', tp = skip(tp); 9541558Srgrimes if (streq(cp, "type")) { 9551558Srgrimes if (tp == NULL) 9561558Srgrimes tp = "unknown"; 9571558Srgrimes cpp = dktypenames; 9581558Srgrimes for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 95994065Sphk if (*cpp && streq(*cpp, tp)) { 9601558Srgrimes lp->d_type = cpp - dktypenames; 9611558Srgrimes goto next; 9621558Srgrimes } 9631558Srgrimes v = atoi(tp); 9641558Srgrimes if ((unsigned)v >= DKMAXTYPES) 9651558Srgrimes fprintf(stderr, "line %d:%s %d\n", lineno, 9661558Srgrimes "Warning, unknown disk type", v); 9671558Srgrimes lp->d_type = v; 9681558Srgrimes continue; 9691558Srgrimes } 9701558Srgrimes if (streq(cp, "flags")) { 9711558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 9721558Srgrimes tp = word(cp); 9731558Srgrimes if (streq(cp, "removeable")) 9741558Srgrimes v |= D_REMOVABLE; 9751558Srgrimes else if (streq(cp, "ecc")) 9761558Srgrimes v |= D_ECC; 9771558Srgrimes else if (streq(cp, "badsect")) 9781558Srgrimes v |= D_BADSECT; 9791558Srgrimes else { 9801558Srgrimes fprintf(stderr, 9811558Srgrimes "line %d: %s: bad flag\n", 9821558Srgrimes lineno, cp); 9831558Srgrimes errors++; 9841558Srgrimes } 9851558Srgrimes } 9861558Srgrimes lp->d_flags = v; 9871558Srgrimes continue; 9881558Srgrimes } 9891558Srgrimes if (streq(cp, "drivedata")) { 9901558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 9911558Srgrimes lp->d_drivedata[i++] = atoi(cp); 9921558Srgrimes tp = word(cp); 9931558Srgrimes } 9941558Srgrimes continue; 9951558Srgrimes } 9961558Srgrimes if (sscanf(cp, "%d partitions", &v) == 1) { 9971558Srgrimes if (v == 0 || (unsigned)v > MAXPARTITIONS) { 9981558Srgrimes fprintf(stderr, 9991558Srgrimes "line %d: bad # of partitions\n", lineno); 10001558Srgrimes lp->d_npartitions = MAXPARTITIONS; 10011558Srgrimes errors++; 10021558Srgrimes } else 10031558Srgrimes lp->d_npartitions = v; 10041558Srgrimes continue; 10051558Srgrimes } 10061558Srgrimes if (tp == NULL) 10071558Srgrimes tp = ""; 10081558Srgrimes if (streq(cp, "disk")) { 10091558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 10101558Srgrimes continue; 10111558Srgrimes } 10121558Srgrimes if (streq(cp, "label")) { 10131558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 10141558Srgrimes continue; 10151558Srgrimes } 10161558Srgrimes if (streq(cp, "bytes/sector")) { 10171558Srgrimes v = atoi(tp); 101837865Sbde if (v <= 0 || (v % DEV_BSIZE) != 0) { 10191558Srgrimes fprintf(stderr, 10201558Srgrimes "line %d: %s: bad sector size\n", 10211558Srgrimes lineno, tp); 10221558Srgrimes errors++; 10231558Srgrimes } else 10241558Srgrimes lp->d_secsize = v; 10251558Srgrimes continue; 10261558Srgrimes } 10271558Srgrimes if (streq(cp, "sectors/track")) { 10281558Srgrimes v = atoi(tp); 10291558Srgrimes if (v <= 0) { 10301558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10311558Srgrimes lineno, tp, cp); 10321558Srgrimes errors++; 10331558Srgrimes } else 10341558Srgrimes lp->d_nsectors = v; 10351558Srgrimes continue; 10361558Srgrimes } 10371558Srgrimes if (streq(cp, "sectors/cylinder")) { 10381558Srgrimes v = atoi(tp); 10391558Srgrimes if (v <= 0) { 10401558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10411558Srgrimes lineno, tp, cp); 10421558Srgrimes errors++; 10431558Srgrimes } else 10441558Srgrimes lp->d_secpercyl = v; 10451558Srgrimes continue; 10461558Srgrimes } 10471558Srgrimes if (streq(cp, "tracks/cylinder")) { 10481558Srgrimes v = atoi(tp); 10491558Srgrimes if (v <= 0) { 10501558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10511558Srgrimes lineno, tp, cp); 10521558Srgrimes errors++; 10531558Srgrimes } else 10541558Srgrimes lp->d_ntracks = v; 10551558Srgrimes continue; 10561558Srgrimes } 10571558Srgrimes if (streq(cp, "cylinders")) { 10581558Srgrimes v = atoi(tp); 10591558Srgrimes if (v <= 0) { 10601558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10611558Srgrimes lineno, tp, cp); 10621558Srgrimes errors++; 10631558Srgrimes } else 10641558Srgrimes lp->d_ncylinders = v; 10651558Srgrimes continue; 10661558Srgrimes } 10676643Sbde if (streq(cp, "sectors/unit")) { 10686643Sbde v = atoi(tp); 10696643Sbde if (v <= 0) { 10706643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 10716643Sbde lineno, tp, cp); 10726643Sbde errors++; 10736643Sbde } else 10746643Sbde lp->d_secperunit = v; 10756643Sbde continue; 10766643Sbde } 10771558Srgrimes if (streq(cp, "rpm")) { 10781558Srgrimes v = atoi(tp); 10791558Srgrimes if (v <= 0) { 10801558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10811558Srgrimes lineno, tp, cp); 10821558Srgrimes errors++; 10831558Srgrimes } else 10841558Srgrimes lp->d_rpm = v; 10851558Srgrimes continue; 10861558Srgrimes } 10871558Srgrimes if (streq(cp, "interleave")) { 10881558Srgrimes v = atoi(tp); 10891558Srgrimes if (v <= 0) { 10901558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10911558Srgrimes lineno, tp, cp); 10921558Srgrimes errors++; 10931558Srgrimes } else 10941558Srgrimes lp->d_interleave = v; 10951558Srgrimes continue; 10961558Srgrimes } 10971558Srgrimes if (streq(cp, "trackskew")) { 10981558Srgrimes v = atoi(tp); 10991558Srgrimes if (v < 0) { 11001558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11011558Srgrimes lineno, tp, cp); 11021558Srgrimes errors++; 11031558Srgrimes } else 11041558Srgrimes lp->d_trackskew = v; 11051558Srgrimes continue; 11061558Srgrimes } 11071558Srgrimes if (streq(cp, "cylinderskew")) { 11081558Srgrimes v = atoi(tp); 11091558Srgrimes if (v < 0) { 11101558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11111558Srgrimes lineno, tp, cp); 11121558Srgrimes errors++; 11131558Srgrimes } else 11141558Srgrimes lp->d_cylskew = v; 11151558Srgrimes continue; 11161558Srgrimes } 11171558Srgrimes if (streq(cp, "headswitch")) { 11181558Srgrimes v = atoi(tp); 11191558Srgrimes if (v < 0) { 11201558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11211558Srgrimes lineno, tp, cp); 11221558Srgrimes errors++; 11231558Srgrimes } else 11241558Srgrimes lp->d_headswitch = v; 11251558Srgrimes continue; 11261558Srgrimes } 11271558Srgrimes if (streq(cp, "track-to-track seek")) { 11281558Srgrimes v = atoi(tp); 11291558Srgrimes if (v < 0) { 11301558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11311558Srgrimes lineno, tp, cp); 11321558Srgrimes errors++; 11331558Srgrimes } else 11341558Srgrimes lp->d_trkseek = v; 11351558Srgrimes continue; 11361558Srgrimes } 113773034Sjwd /* the ':' was removed above */ 113873034Sjwd if ('a' <= *cp && *cp <= MAX_PART && cp[1] == '\0') { 113973034Sjwd part = *cp - 'a'; 114073034Sjwd if (part >= lp->d_npartitions) { 11411558Srgrimes fprintf(stderr, 114273034Sjwd "line %d: partition name out of range a-%c: %s\n", 114373034Sjwd lineno, 'a' + lp->d_npartitions - 1, cp); 11441558Srgrimes errors++; 11451558Srgrimes continue; 11461558Srgrimes } 11471558Srgrimes pp = &lp->d_partitions[part]; 114873034Sjwd part_set[part] = 1; 11491558Srgrimes#define NXTNUM(n) { \ 11503111Spst if (tp == NULL) { \ 11513111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 11523111Spst errors++; \ 11533111Spst break; \ 11543111Spst } else { \ 11553111Spst cp = tp, tp = word(cp); \ 11563111Spst if (tp == NULL) \ 11573111Spst tp = cp; \ 11583111Spst (n) = atoi(cp); \ 11593111Spst } \ 11601558Srgrimes } 116173034Sjwd/* retain 1 character following number */ 116273034Sjwd#define NXTWORD(w,n) { \ 116373034Sjwd if (tp == NULL) { \ 116473034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 116573034Sjwd errors++; \ 116673034Sjwd break; \ 116773034Sjwd } else { \ 116873034Sjwd char *tmp; \ 116973034Sjwd cp = tp, tp = word(cp); \ 117073034Sjwd if (tp == NULL) \ 117173034Sjwd tp = cp; \ 117273034Sjwd (n) = strtol(cp,&tmp,10); \ 117373034Sjwd if (tmp) (w) = *tmp; \ 117473034Sjwd } \ 117573034Sjwd } 117673034Sjwd v = 0; 117773034Sjwd NXTWORD(part_size_type[part],v); 117873034Sjwd if (v < 0 || (v == 0 && part_size_type[part] != '*')) { 11791558Srgrimes fprintf(stderr, 11801558Srgrimes "line %d: %s: bad partition size\n", 11811558Srgrimes lineno, cp); 11821558Srgrimes errors++; 118373034Sjwd break; 118473034Sjwd } else { 11851558Srgrimes pp->p_size = v; 11861558Srgrimes 118773034Sjwd v = 0; 118873034Sjwd NXTWORD(part_offset_type[part],v); 118973034Sjwd if (v < 0 || (v == 0 && 119073034Sjwd part_offset_type[part] != '*' && 119173034Sjwd part_offset_type[part] != '\0')) { 119273034Sjwd fprintf(stderr, 119373034Sjwd "line %d: %s: bad partition offset\n", 119473034Sjwd lineno, cp); 119573034Sjwd errors++; 11961558Srgrimes break; 119773034Sjwd } else { 119873034Sjwd pp->p_offset = v; 119973034Sjwd cp = tp, tp = word(cp); 120073034Sjwd cpp = fstypenames; 120173034Sjwd for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 120294065Sphk if (*cpp && streq(*cpp, cp)) { 120373034Sjwd pp->p_fstype = cpp - 120473034Sjwd fstypenames; 120573034Sjwd goto gottype; 120673034Sjwd } 120773034Sjwd if (isdigit(*cp)) 120873034Sjwd v = atoi(cp); 120973034Sjwd else 121073034Sjwd v = FSMAXTYPES; 121173034Sjwd if ((unsigned)v >= FSMAXTYPES) { 121273034Sjwd fprintf(stderr, 121373034Sjwd "line %d: Warning, unknown " 121473034Sjwd "filesystem type %s\n", 121573034Sjwd lineno, cp); 121673034Sjwd v = FS_UNUSED; 121773034Sjwd } 121873034Sjwd pp->p_fstype = v; 121973034Sjwd gottype:; 122073034Sjwd /* 122173034Sjwd * Note: NXTNUM will break us out of the 122273034Sjwd * switch only! 122373034Sjwd */ 122473034Sjwd switch (pp->p_fstype) { 122573034Sjwd case FS_UNUSED: 122673034Sjwd /* 122773034Sjwd * allow us to accept defaults for 122873034Sjwd * fsize/frag/cpg 122973034Sjwd */ 123073034Sjwd if (tp) { 123173034Sjwd NXTNUM(pp->p_fsize); 123273034Sjwd if (pp->p_fsize == 0) 123373034Sjwd break; 123473034Sjwd NXTNUM(v); 123573034Sjwd pp->p_frag = v / pp->p_fsize; 123673034Sjwd } 123773034Sjwd /* else default to 0's */ 123873034Sjwd break; 12391558Srgrimes 124073034Sjwd /* These happen to be the same */ 124173034Sjwd case FS_BSDFFS: 124273034Sjwd case FS_BSDLFS: 124373034Sjwd if (tp) { 124473034Sjwd NXTNUM(pp->p_fsize); 124573034Sjwd if (pp->p_fsize == 0) 124673034Sjwd break; 124773034Sjwd NXTNUM(v); 124873034Sjwd pp->p_frag = v / pp->p_fsize; 124973034Sjwd NXTNUM(pp->p_cpg); 125073034Sjwd } else { 125173034Sjwd /* 125273034Sjwd * FIX! poor attempt at 125373034Sjwd * adaptive 125473034Sjwd */ 125573034Sjwd /* 1 GB */ 125673034Sjwd if (pp->p_size < 1*1024*1024*1024/lp->d_secsize) { 125773034Sjwd/* FIX! These are too low, but are traditional */ 125873034Sjwd pp->p_fsize = DEFAULT_NEWFS_BLOCK; 125973034Sjwd pp->p_frag = (unsigned char) DEFAULT_NEWFS_FRAG; 126073034Sjwd pp->p_cpg = DEFAULT_NEWFS_CPG; 126173034Sjwd } else { 126273034Sjwd pp->p_fsize = BIG_NEWFS_BLOCK; 126373034Sjwd pp->p_frag = (unsigned char) BIG_NEWFS_FRAG; 126473034Sjwd pp->p_cpg = BIG_NEWFS_CPG; 126573034Sjwd } 126673034Sjwd } 126773034Sjwd break; 126873034Sjwd default: 126973034Sjwd break; 127073034Sjwd } 12711558Srgrimes 127273034Sjwd /* 127373034Sjwd * note: we may not have 127473034Sjwd * gotten all the entries for 127573034Sjwd * the fs though if we didn't, 127673034Sjwd * errors will be set. 127773034Sjwd */ 127873034Sjwd } 12791558Srgrimes } 12801558Srgrimes continue; 12811558Srgrimes } 12821558Srgrimes fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 12831558Srgrimes lineno, cp); 12841558Srgrimes errors++; 128573034Sjwd next:; 12861558Srgrimes } 12871558Srgrimes errors += checklabel(lp); 12881558Srgrimes return (errors == 0); 12891558Srgrimes} 12901558Srgrimes 12911558Srgrimes/* 12921558Srgrimes * Check disklabel for errors and fill in 12931558Srgrimes * derived fields according to supplied values. 12941558Srgrimes */ 129513544Sjoergint 129692541Simpchecklabel(struct disklabel *lp) 12971558Srgrimes{ 129892541Simp struct partition *pp; 12991558Srgrimes int i, errors = 0; 13001558Srgrimes char part; 130173573Simp unsigned long total_size, total_percent, current_offset; 130273034Sjwd int seen_default_offset; 130373034Sjwd int hog_part; 130473034Sjwd int j; 130573034Sjwd struct partition *pp2; 13061558Srgrimes 13071558Srgrimes if (lp->d_secsize == 0) { 130837234Sbde fprintf(stderr, "sector size 0\n"); 13091558Srgrimes return (1); 13101558Srgrimes } 13111558Srgrimes if (lp->d_nsectors == 0) { 131237234Sbde fprintf(stderr, "sectors/track 0\n"); 13131558Srgrimes return (1); 13141558Srgrimes } 13151558Srgrimes if (lp->d_ntracks == 0) { 131637234Sbde fprintf(stderr, "tracks/cylinder 0\n"); 13171558Srgrimes return (1); 13181558Srgrimes } 13191558Srgrimes if (lp->d_ncylinders == 0) { 132037234Sbde fprintf(stderr, "cylinders/unit 0\n"); 13211558Srgrimes errors++; 13221558Srgrimes } 13231558Srgrimes if (lp->d_rpm == 0) 132437234Sbde Warning("revolutions/minute 0"); 13251558Srgrimes if (lp->d_secpercyl == 0) 13261558Srgrimes lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 13271558Srgrimes if (lp->d_secperunit == 0) 13281558Srgrimes lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 13291558Srgrimes if (lp->d_bbsize == 0) { 133037234Sbde fprintf(stderr, "boot block size 0\n"); 13311558Srgrimes errors++; 13321558Srgrimes } else if (lp->d_bbsize % lp->d_secsize) 13331558Srgrimes Warning("boot block size %% sector-size != 0"); 13341558Srgrimes if (lp->d_npartitions > MAXPARTITIONS) 133537234Sbde Warning("number of partitions (%lu) > MAXPARTITIONS (%d)", 133637234Sbde (u_long)lp->d_npartitions, MAXPARTITIONS); 133773034Sjwd 133873034Sjwd /* first allocate space to the partitions, then offsets */ 133973034Sjwd total_size = 0; /* in sectors */ 134073034Sjwd total_percent = 0; /* in percent */ 134173034Sjwd hog_part = -1; 134273034Sjwd /* find all fixed partitions */ 13431558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 134473034Sjwd pp = &lp->d_partitions[i]; 134573034Sjwd if (part_set[i]) { 134673034Sjwd if (part_size_type[i] == '*') { 134794065Sphk if (i == RAW_PART) { 134873034Sjwd pp->p_size = lp->d_secperunit; 134973034Sjwd } else { 135073034Sjwd if (hog_part != -1) 135173034Sjwd Warning("Too many '*' partitions (%c and %c)", 135273034Sjwd hog_part + 'a',i + 'a'); 135373034Sjwd else 135473034Sjwd hog_part = i; 135573034Sjwd } 135673034Sjwd } else { 135773573Simp off_t size; 135873034Sjwd 135973034Sjwd size = pp->p_size; 136073034Sjwd switch (part_size_type[i]) { 136173034Sjwd case '%': 136273034Sjwd total_percent += size; 136373034Sjwd break; 136473034Sjwd case 'k': 136573034Sjwd case 'K': 136673573Simp size *= 1024ULL; 136773034Sjwd break; 136873034Sjwd case 'm': 136973034Sjwd case 'M': 137073573Simp size *= 1024ULL * 1024ULL; 137173034Sjwd break; 137273034Sjwd case 'g': 137373034Sjwd case 'G': 137473573Simp size *= 1024ULL * 1024ULL * 1024ULL; 137573034Sjwd break; 137673034Sjwd case '\0': 137773034Sjwd break; 137873034Sjwd default: 137973034Sjwd Warning("unknown size specifier '%c' (K/M/G are valid)",part_size_type[i]); 138073034Sjwd break; 138173034Sjwd } 138273034Sjwd /* don't count %'s yet */ 138373034Sjwd if (part_size_type[i] != '%') { 138473034Sjwd /* 138573034Sjwd * for all not in sectors, convert to 138673034Sjwd * sectors 138773034Sjwd */ 138873034Sjwd if (part_size_type[i] != '\0') { 138973034Sjwd if (size % lp->d_secsize != 0) 139073034Sjwd Warning("partition %c not an integer number of sectors", 139173034Sjwd i + 'a'); 139273034Sjwd size /= lp->d_secsize; 139373034Sjwd pp->p_size = size; 139473034Sjwd } 139573034Sjwd /* else already in sectors */ 139694065Sphk if (i != RAW_PART) 139773034Sjwd total_size += size; 139873034Sjwd } 139973034Sjwd } 140073034Sjwd } 140173034Sjwd } 140273034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 140373034Sjwd if (total_percent != 0) { 140473034Sjwd long free_space = lp->d_secperunit - total_size; 140573034Sjwd if (total_percent > 100) { 140694065Sphk fprintf(stderr,"total percentage %lu is greater than 100\n", 140773034Sjwd total_percent); 140873034Sjwd errors++; 140973034Sjwd } 141073034Sjwd 141173034Sjwd if (free_space > 0) { 141273034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 141373034Sjwd pp = &lp->d_partitions[i]; 141473034Sjwd if (part_set[i] && part_size_type[i] == '%') { 141573034Sjwd /* careful of overflows! and integer roundoff */ 141673034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 141773034Sjwd total_size += pp->p_size; 141873034Sjwd 141973034Sjwd /* FIX we can lose a sector or so due to roundoff per 142073034Sjwd partition. A more complex algorithm could avoid that */ 142173034Sjwd } 142273034Sjwd } 142373034Sjwd } else { 142473034Sjwd fprintf(stderr, 142594065Sphk "%ld sectors available to give to '*' and '%%' partitions\n", 142673034Sjwd free_space); 142773034Sjwd errors++; 142873034Sjwd /* fix? set all % partitions to size 0? */ 142973034Sjwd } 143073034Sjwd } 143173034Sjwd /* give anything remaining to the hog partition */ 143273034Sjwd if (hog_part != -1) { 143373034Sjwd lp->d_partitions[hog_part].p_size = lp->d_secperunit - total_size; 143473034Sjwd total_size = lp->d_secperunit; 143573034Sjwd } 143673034Sjwd 143773034Sjwd /* Now set the offsets for each partition */ 143873034Sjwd current_offset = 0; /* in sectors */ 143973034Sjwd seen_default_offset = 0; 144073034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 14411558Srgrimes part = 'a' + i; 14421558Srgrimes pp = &lp->d_partitions[i]; 144373034Sjwd if (part_set[i]) { 144473034Sjwd if (part_offset_type[i] == '*') { 144594065Sphk if (i == RAW_PART) { 144673034Sjwd pp->p_offset = 0; 144773034Sjwd } else { 144873034Sjwd pp->p_offset = current_offset; 144973034Sjwd seen_default_offset = 1; 145073034Sjwd } 145173034Sjwd } else { 145273034Sjwd /* allow them to be out of order for old-style tables */ 145373034Sjwd if (pp->p_offset < current_offset && 145494065Sphk seen_default_offset && i != RAW_PART) { 145573034Sjwd fprintf(stderr, 145694065Sphk"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 145794065Sphk (long)pp->p_offset,i+'a',current_offset); 145873034Sjwd fprintf(stderr, 145973034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 146073034Sjwd errors++; 146173034Sjwd } else if (pp->p_offset != current_offset && 146294065Sphk i != RAW_PART && seen_default_offset) { 146373034Sjwd /* 146473034Sjwd * this may give unneeded warnings if 146573034Sjwd * partitions are out-of-order 146673034Sjwd */ 146773034Sjwd Warning( 146873034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 146994065Sphk (long)pp->p_offset, i + 'a', current_offset); 147073034Sjwd } 147173034Sjwd } 147294065Sphk if (i != RAW_PART) 147373034Sjwd current_offset = pp->p_offset + pp->p_size; 147473034Sjwd } 147573034Sjwd } 147673034Sjwd 147773034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 147873034Sjwd part = 'a' + i; 147973034Sjwd pp = &lp->d_partitions[i]; 14801558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 148137234Sbde Warning("partition %c: size 0, but offset %lu", 148237234Sbde part, (u_long)pp->p_offset); 148392058Sobrien#ifdef __sparc64__ 148492058Sobrien /* See comment in writelabel(). */ 148592058Sobrien if (pp->p_offset % lp->d_secpercyl != 0) { 148692058Sobrien fprintf(stderr, "partition %c: does not start on a " 148792058Sobrien "cylinder boundary!\n", part); 148892058Sobrien errors++; 148992058Sobrien } 149092058Sobrien#endif 14911558Srgrimes#ifdef notdef 14921558Srgrimes if (pp->p_size % lp->d_secpercyl) 14931558Srgrimes Warning("partition %c: size %% cylinder-size != 0", 14941558Srgrimes part); 14951558Srgrimes if (pp->p_offset % lp->d_secpercyl) 14961558Srgrimes Warning("partition %c: offset %% cylinder-size != 0", 14971558Srgrimes part); 14981558Srgrimes#endif 14991558Srgrimes if (pp->p_offset > lp->d_secperunit) { 15001558Srgrimes fprintf(stderr, 15011558Srgrimes "partition %c: offset past end of unit\n", part); 15021558Srgrimes errors++; 15031558Srgrimes } 15041558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 15051558Srgrimes fprintf(stderr, 150613544Sjoerg "partition %c: partition extends past end of unit\n", 15071558Srgrimes part); 15081558Srgrimes errors++; 15091558Srgrimes } 151094065Sphk if (i == RAW_PART) 151173034Sjwd { 151273034Sjwd if (pp->p_fstype != FS_UNUSED) 151373034Sjwd Warning("partition %c is not marked as unused!",part); 151473034Sjwd if (pp->p_offset != 0) 151573034Sjwd Warning("partition %c doesn't start at 0!",part); 151673034Sjwd if (pp->p_size != lp->d_secperunit) 151773034Sjwd Warning("partition %c doesn't cover the whole unit!",part); 151873034Sjwd 151973034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 152073034Sjwd (pp->p_size != lp->d_secperunit)) { 152173034Sjwd Warning("An incorrect partition %c may cause problems for " 152273034Sjwd "standard system utilities",part); 152373034Sjwd } 152473034Sjwd } 152573034Sjwd 152673034Sjwd /* check for overlaps */ 152773034Sjwd /* this will check for all possible overlaps once and only once */ 152873034Sjwd for (j = 0; j < i; j++) { 152994065Sphk if (j != RAW_PART && i != RAW_PART && 153073034Sjwd part_set[i] && part_set[j]) { 153173034Sjwd pp2 = &lp->d_partitions[j]; 153273034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 153373034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 153473034Sjwd pp2->p_offset >= pp->p_offset)) { 153573034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 153673034Sjwd j + 'a', i + 'a'); 153773034Sjwd errors++; 153873034Sjwd } 153973034Sjwd } 154073034Sjwd } 15411558Srgrimes } 15421558Srgrimes for (; i < MAXPARTITIONS; i++) { 15431558Srgrimes part = 'a' + i; 15441558Srgrimes pp = &lp->d_partitions[i]; 15451558Srgrimes if (pp->p_size || pp->p_offset) 154637234Sbde Warning("unused partition %c: size %d offset %lu", 154737234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 15481558Srgrimes } 15491558Srgrimes return (errors); 15501558Srgrimes} 15511558Srgrimes 15521558Srgrimes/* 155313550Sjoerg * When operating on a "virgin" disk, try getting an initial label 155413550Sjoerg * from the associated device driver. This might work for all device 155513550Sjoerg * drivers that are able to fetch some initial device parameters 155613550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 155713550Sjoerg * most IDE drives, or vn devices. 155813550Sjoerg * 155913550Sjoerg * The device name must be given in its "canonical" form. 156013550Sjoerg */ 156113550Sjoergstruct disklabel * 156213550Sjoerggetvirginlabel(void) 156313550Sjoerg{ 156413550Sjoerg static struct disklabel lab; 156513550Sjoerg char namebuf[BBSIZE]; 156613550Sjoerg int f; 156713550Sjoerg 156813550Sjoerg if (dkname[0] == '/') { 156937773Sbde warnx("\"auto\" requires the usage of a canonical disk name"); 157016431Sbde return (NULL); 157113550Sjoerg } 157259429Sobrien (void)snprintf(namebuf, BBSIZE, "%s%s", _PATH_DEV, dkname); 157337773Sbde if ((f = open(namebuf, O_RDONLY)) == -1) { 157437773Sbde warn("cannot open %s", namebuf); 157516431Sbde return (NULL); 157613550Sjoerg } 157768044Sjkh 157868044Sjkh /* 157968044Sjkh * Try to use the new get-virgin-label ioctl. If it fails, 158068044Sjkh * fallback to the old get-disdk-info ioctl. 158168044Sjkh */ 158291603Sphk if (ioctl(f, DIOCGDVIRGIN, &lab) == 0) 158391603Sphk goto out; 158491603Sphk if (ioctl(f, DIOCGDINFO, &lab) == 0) 158591603Sphk goto out; 158691603Sphk close(f); 158791603Sphk (void)snprintf(namebuf, BBSIZE, "%s%s%c", _PATH_DEV, dkname, 158891603Sphk 'a' + RAW_PART); 158991603Sphk if ((f = open(namebuf, O_RDONLY)) == -1) { 159091603Sphk warn("cannot open %s", namebuf); 159191603Sphk return (NULL); 159213550Sjoerg } 159391603Sphk if (ioctl(f, DIOCGDINFO, &lab) == 0) 159491603Sphk goto out; 159513550Sjoerg close(f); 159691603Sphk warn("No virgin disklabel found %s", namebuf); 159791603Sphk return (NULL); 159891603Sphk out: 159991603Sphk close(f); 160016431Sbde return (&lab); 160113550Sjoerg} 160213550Sjoerg 160313550Sjoerg/* 16041558Srgrimes * If we are installing a boot program that doesn't fit in d_bbsize 16051558Srgrimes * we need to mark those partitions that the boot overflows into. 16061558Srgrimes * This allows newfs to prevent creation of a filesystem where it might 16071558Srgrimes * clobber bootstrap code. 16081558Srgrimes */ 160913544Sjoergvoid 161092541Simpsetbootflag(struct disklabel *lp) 16111558Srgrimes{ 161292541Simp struct partition *pp; 16131558Srgrimes int i, errors = 0; 16141558Srgrimes char part; 16151558Srgrimes u_long boffset; 16161558Srgrimes 16171558Srgrimes if (bootbuf == 0) 16181558Srgrimes return; 16191558Srgrimes boffset = bootsize / lp->d_secsize; 16201558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 16211558Srgrimes part = 'a' + i; 16221558Srgrimes pp = &lp->d_partitions[i]; 16231558Srgrimes if (pp->p_size == 0) 16241558Srgrimes continue; 16251558Srgrimes if (boffset <= pp->p_offset) { 16261558Srgrimes if (pp->p_fstype == FS_BOOT) 16271558Srgrimes pp->p_fstype = FS_UNUSED; 16281558Srgrimes } else if (pp->p_fstype != FS_BOOT) { 16291558Srgrimes if (pp->p_fstype != FS_UNUSED) { 16301558Srgrimes fprintf(stderr, 16311558Srgrimes "boot overlaps used partition %c\n", 16321558Srgrimes part); 16331558Srgrimes errors++; 16341558Srgrimes } else { 16351558Srgrimes pp->p_fstype = FS_BOOT; 16361558Srgrimes Warning("boot overlaps partition %c, %s", 16371558Srgrimes part, "marked as FS_BOOT"); 16381558Srgrimes } 16391558Srgrimes } 16401558Srgrimes } 164136632Scharnier if (errors) 164236632Scharnier errx(4, "cannot install boot program"); 16431558Srgrimes} 16441558Srgrimes 16451558Srgrimes/*VARARGS1*/ 164613544Sjoergvoid 164792541SimpWarning(const char *fmt, ...) 16481558Srgrimes{ 164913544Sjoerg va_list ap; 16501558Srgrimes 16511558Srgrimes fprintf(stderr, "Warning, "); 165213544Sjoerg va_start(ap, fmt); 165313544Sjoerg vfprintf(stderr, fmt, ap); 16541558Srgrimes fprintf(stderr, "\n"); 165513544Sjoerg va_end(ap); 16561558Srgrimes} 16571558Srgrimes 165813544Sjoergvoid 165992541Simpusage(void) 16601558Srgrimes{ 16611558Srgrimes#if NUMBOOT > 0 166226542Scharnier 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", 166326542Scharnier "usage: disklabel [-r] disk", 166426542Scharnier "\t\t(to read label)", 166573034Sjwd " disklabel -w [-r] [-n] disk type [ packid ]", 166626542Scharnier "\t\t(to write label with existing boot program)", 166773034Sjwd " disklabel -e [-r] [-n] disk", 166826542Scharnier "\t\t(to edit label)", 166973034Sjwd " disklabel -R [-r] [-n] disk protofile", 167026542Scharnier "\t\t(to restore label with existing boot program)", 16711558Srgrimes#if NUMBOOT > 1 167273034Sjwd " disklabel -B [-n] [ -b boot1 [ -s boot2 ] ] disk [ type ]", 167326542Scharnier "\t\t(to install boot program with existing label)", 167473034Sjwd " disklabel -w -B [-n] [ -b boot1 [ -s boot2 ] ] disk type [ packid ]", 167526542Scharnier "\t\t(to write label and boot program)", 167673034Sjwd " disklabel -R -B [-n] [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]", 167726542Scharnier "\t\t(to restore label and boot program)", 16781558Srgrimes#else 167973034Sjwd " disklabel -B [-n] [ -b bootprog ] disk [ type ]", 168026542Scharnier "\t\t(to install boot program with existing on-disk label)", 168173034Sjwd " disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", 168226542Scharnier "\t\t(to write label and install boot program)", 168373034Sjwd " disklabel -R -B [-n] [ -b bootprog ] disk protofile [ type ]", 168426542Scharnier "\t\t(to restore label and install boot program)", 16851558Srgrimes#endif 168626542Scharnier " disklabel [-NW] disk", 168726542Scharnier "\t\t(to write disable/enable label)"); 16881558Srgrimes#else 168926542Scharnier fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 169026542Scharnier "usage: disklabel [-r] disk", "(to read label)", 169173034Sjwd " disklabel -w [-r] [-n] disk type [ packid ]", 169226542Scharnier "\t\t(to write label)", 169373034Sjwd " disklabel -e [-r] [-n] disk", 169426542Scharnier "\t\t(to edit label)", 169573034Sjwd " disklabel -R [-r] [-n] disk protofile", 169626542Scharnier "\t\t(to restore label)", 169726542Scharnier " disklabel [-NW] disk", 169826542Scharnier "\t\t(to write disable/enable label)"); 16991558Srgrimes#endif 17001558Srgrimes exit(1); 17011558Srgrimes} 1702