bsdlabel.c revision 97855
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 97855 2002-06-05 08:11:28Z iedowse $"; 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 9797535Siedowse#define BIG_NEWFS_FRAG 2048U 9873034Sjwd#define BIG_NEWFS_CPG 64U 9973034Sjwd 10092057Sobrien#if defined(__i386__) || defined(__ia64__) 10192057Sobrien#define NUMBOOT 2 10297047Sbenno#elif defined(__alpha__) || defined(__sparc64__) || defined(__powerpc__) 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 *); 11997534Siedowseint getasciipartspec(char *, struct disklabel *, int, int); 12092541Simpint checklabel(struct disklabel *); 12192541Simpvoid setbootflag(struct disklabel *); 12292541Simpvoid Warning(const char *, ...) __printflike(1, 2); 12392541Simpvoid usage(void); 12492541Simpstruct disklabel *getvirginlabel(void); 12513544Sjoerg 1261558Srgrimes#define DEFEDITOR _PATH_VI 1271558Srgrimes#define streq(a,b) (strcmp(a,b) == 0) 1281558Srgrimes 1291558Srgrimeschar *dkname; 1301558Srgrimeschar *specname; 13155742Skrischar tmpfil[] = PATH_TMPFILE; 1321558Srgrimes 1331558Srgrimeschar namebuf[BBSIZE], *np = namebuf; 1341558Srgrimesstruct disklabel lab; 1351558Srgrimeschar bootarea[BBSIZE]; 1361558Srgrimes 13773034Sjwd#define MAX_PART ('z') 13873034Sjwd#define MAX_NUM_PARTS (1 + MAX_PART - 'a') 13973034Sjwdchar part_size_type[MAX_NUM_PARTS]; 14073034Sjwdchar part_offset_type[MAX_NUM_PARTS]; 14173034Sjwdint part_set[MAX_NUM_PARTS]; 14273034Sjwd 1431558Srgrimes#if NUMBOOT > 0 1441558Srgrimesint installboot; /* non-zero if we should install a boot program */ 1451558Srgrimeschar *bootbuf; /* pointer to buffer with remainder of boot prog */ 1461558Srgrimesint bootsize; /* size of remaining boot program */ 1471558Srgrimeschar *xxboot; /* primary boot */ 1481558Srgrimeschar *bootxx; /* secondary boot */ 1491558Srgrimeschar boot0[MAXPATHLEN]; 1501558Srgrimeschar boot1[MAXPATHLEN]; 1511558Srgrimes#endif 1521558Srgrimes 1531558Srgrimesenum { 1541558Srgrimes UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT 1551558Srgrimes} op = UNSPEC; 1561558Srgrimes 1571558Srgrimesint rflag; 15873034Sjwdint disable_write; /* set to disable writing to disk label */ 1591558Srgrimes 16073034Sjwd#define OPTIONS "BNRWb:enrs:w" 1611558Srgrimes 16213544Sjoergint 16392541Simpmain(int argc, char *argv[]) 1641558Srgrimes{ 16592715Simp struct disklabel *lp; 1661558Srgrimes FILE *t; 16748957Sbillf int ch, f = 0, flag, error = 0; 1681558Srgrimes char *name = 0; 1691558Srgrimes 17024359Simp while ((ch = getopt(argc, argv, OPTIONS)) != -1) 1711558Srgrimes switch (ch) { 1721558Srgrimes#if NUMBOOT > 0 1731558Srgrimes case 'B': 1741558Srgrimes ++installboot; 1751558Srgrimes break; 1761558Srgrimes case 'b': 1771558Srgrimes xxboot = optarg; 1781558Srgrimes break; 1791558Srgrimes#if NUMBOOT > 1 1801558Srgrimes case 's': 1811558Srgrimes bootxx = optarg; 1821558Srgrimes break; 1831558Srgrimes#endif 1841558Srgrimes#endif 1851558Srgrimes case 'N': 1861558Srgrimes if (op != UNSPEC) 1871558Srgrimes usage(); 1881558Srgrimes op = NOWRITE; 1891558Srgrimes break; 19073034Sjwd case 'n': 19173034Sjwd disable_write = 1; 19273034Sjwd break; 1931558Srgrimes case 'R': 1941558Srgrimes if (op != UNSPEC) 1951558Srgrimes usage(); 1961558Srgrimes op = RESTORE; 1971558Srgrimes break; 1981558Srgrimes case 'W': 1991558Srgrimes if (op != UNSPEC) 2001558Srgrimes usage(); 2011558Srgrimes op = WRITEABLE; 2021558Srgrimes break; 2031558Srgrimes case 'e': 2041558Srgrimes if (op != UNSPEC) 2051558Srgrimes usage(); 2061558Srgrimes op = EDIT; 2071558Srgrimes break; 2081558Srgrimes case 'r': 2091558Srgrimes ++rflag; 2101558Srgrimes break; 2111558Srgrimes case 'w': 2121558Srgrimes if (op != UNSPEC) 2131558Srgrimes usage(); 2141558Srgrimes op = WRITE; 2151558Srgrimes break; 2161558Srgrimes case '?': 2171558Srgrimes default: 2181558Srgrimes usage(); 2191558Srgrimes } 2201558Srgrimes argc -= optind; 2211558Srgrimes argv += optind; 2221558Srgrimes#if NUMBOOT > 0 2231558Srgrimes if (installboot) { 2241558Srgrimes rflag++; 2251558Srgrimes if (op == UNSPEC) 2261558Srgrimes op = WRITEBOOT; 2271558Srgrimes } else { 2281558Srgrimes if (op == UNSPEC) 2291558Srgrimes op = READ; 2301558Srgrimes xxboot = bootxx = 0; 2311558Srgrimes } 2321558Srgrimes#else 2331558Srgrimes if (op == UNSPEC) 2341558Srgrimes op = READ; 2351558Srgrimes#endif 2361558Srgrimes if (argc < 1) 2371558Srgrimes usage(); 2381558Srgrimes 2391558Srgrimes dkname = argv[0]; 2401558Srgrimes if (dkname[0] != '/') { 24159114Sobrien (void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); 2421558Srgrimes specname = np; 2431558Srgrimes np += strlen(specname) + 1; 2441558Srgrimes } else 2451558Srgrimes specname = dkname; 2461558Srgrimes f = open(specname, op == READ ? O_RDONLY : O_RDWR); 2471558Srgrimes if (f < 0 && errno == ENOENT && dkname[0] != '/') { 24859429Sobrien (void)sprintf(specname, "%s%s", _PATH_DEV, dkname); 2491558Srgrimes np = namebuf + strlen(specname) + 1; 2501558Srgrimes f = open(specname, op == READ ? O_RDONLY : O_RDWR); 2511558Srgrimes } 2521558Srgrimes if (f < 0) 25326542Scharnier err(4, "%s", specname); 2541558Srgrimes 2551558Srgrimes switch(op) { 2561558Srgrimes 25748957Sbillf case UNSPEC: 25848957Sbillf break; 25948957Sbillf 2601558Srgrimes case EDIT: 2611558Srgrimes if (argc != 1) 2621558Srgrimes usage(); 2631558Srgrimes lp = readlabel(f); 2641558Srgrimes error = edit(lp, f); 2651558Srgrimes break; 2661558Srgrimes 2671558Srgrimes case NOWRITE: 2681558Srgrimes flag = 0; 2691558Srgrimes if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 27026542Scharnier err(4, "ioctl DIOCWLABEL"); 2711558Srgrimes break; 2721558Srgrimes 2731558Srgrimes case READ: 2741558Srgrimes if (argc != 1) 2751558Srgrimes usage(); 2761558Srgrimes lp = readlabel(f); 2771558Srgrimes display(stdout, lp); 2781558Srgrimes error = checklabel(lp); 2791558Srgrimes break; 2801558Srgrimes 2811558Srgrimes case RESTORE: 2821558Srgrimes#if NUMBOOT > 0 2831558Srgrimes if (installboot && argc == 3) { 2841558Srgrimes makelabel(argv[2], 0, &lab); 2851558Srgrimes argc--; 28637865Sbde 28737865Sbde /* 28837865Sbde * We only called makelabel() for its side effect 28937865Sbde * of setting the bootstrap file names. Discard 29037865Sbde * all changes to `lab' so that all values in the 29137865Sbde * final label come from the ASCII label. 29237865Sbde */ 29337865Sbde bzero((char *)&lab, sizeof(lab)); 2941558Srgrimes } 2951558Srgrimes#endif 2961558Srgrimes if (argc != 2) 2971558Srgrimes usage(); 2981558Srgrimes if (!(t = fopen(argv[1], "r"))) 29926542Scharnier err(4, "%s", argv[1]); 30037865Sbde if (!getasciilabel(t, &lab)) 30137865Sbde exit(1); 30237865Sbde lp = makebootarea(bootarea, &lab, f); 30337865Sbde *lp = lab; 30437865Sbde error = writelabel(f, bootarea, lp); 3051558Srgrimes break; 3061558Srgrimes 3071558Srgrimes case WRITE: 3081558Srgrimes if (argc == 3) { 3091558Srgrimes name = argv[2]; 3101558Srgrimes argc--; 3111558Srgrimes } 3121558Srgrimes if (argc != 2) 3131558Srgrimes usage(); 3141558Srgrimes makelabel(argv[1], name, &lab); 3151558Srgrimes lp = makebootarea(bootarea, &lab, f); 3161558Srgrimes *lp = lab; 3171558Srgrimes if (checklabel(lp) == 0) 3181558Srgrimes error = writelabel(f, bootarea, lp); 3191558Srgrimes break; 3201558Srgrimes 3211558Srgrimes case WRITEABLE: 3221558Srgrimes flag = 1; 3231558Srgrimes if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 32426542Scharnier err(4, "ioctl DIOCWLABEL"); 3251558Srgrimes break; 3261558Srgrimes 3271558Srgrimes#if NUMBOOT > 0 3281558Srgrimes case WRITEBOOT: 3291558Srgrimes { 3301558Srgrimes struct disklabel tlab; 3311558Srgrimes 3321558Srgrimes lp = readlabel(f); 3331558Srgrimes tlab = *lp; 3341558Srgrimes if (argc == 2) 3351558Srgrimes makelabel(argv[1], 0, &lab); 3361558Srgrimes lp = makebootarea(bootarea, &lab, f); 3371558Srgrimes *lp = tlab; 3381558Srgrimes if (checklabel(lp) == 0) 3391558Srgrimes error = writelabel(f, bootarea, lp); 3401558Srgrimes break; 3411558Srgrimes } 3421558Srgrimes#endif 3431558Srgrimes } 3441558Srgrimes exit(error); 3451558Srgrimes} 3461558Srgrimes 3471558Srgrimes/* 3481558Srgrimes * Construct a prototype disklabel from /etc/disktab. As a side 3491558Srgrimes * effect, set the names of the primary and secondary boot files 3501558Srgrimes * if specified. 3511558Srgrimes */ 35213544Sjoergvoid 35392541Simpmakelabel(const char *type, const char *name, struct disklabel *lp) 3541558Srgrimes{ 35592541Simp struct disklabel *dp; 35613550Sjoerg 35713550Sjoerg if (strcmp(type, "auto") == 0) 35813550Sjoerg dp = getvirginlabel(); 35913550Sjoerg else 36013544Sjoerg dp = getdiskbyname(type); 36136632Scharnier if (dp == NULL) 36236632Scharnier errx(1, "%s: unknown disk type", type); 3631558Srgrimes *lp = *dp; 3641558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 3651558Srgrimes if (name) 3661558Srgrimes (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 3671558Srgrimes} 3681558Srgrimes 36913544Sjoergint 37092541Simpwritelabel(int f, const char *boot, struct disklabel *lp) 3711558Srgrimes{ 3721558Srgrimes int flag; 37338384Sdfr#ifdef __alpha__ 37438384Sdfr u_long *p, sum; 37538384Sdfr int i; 37638384Sdfr#endif 37792058Sobrien#ifdef __sparc64__ 37892058Sobrien struct sun_disklabel *sl; 37992058Sobrien u_short cksum, *sp1, *sp2; 38092058Sobrien struct partition *npp; 38192058Sobrien struct sun_dkpart *spp; 38292058Sobrien int i, secpercyl; 38338411Sbde#endif 38438384Sdfr 38573034Sjwd if (disable_write) { 38673034Sjwd Warning("write to disk label supressed - label was as follows:"); 38773034Sjwd display(stdout, lp); 38873034Sjwd return (0); 38973034Sjwd } else { 39073034Sjwd setbootflag(lp); 39173034Sjwd lp->d_magic = DISKMAGIC; 39273034Sjwd lp->d_magic2 = DISKMAGIC; 39373034Sjwd lp->d_checksum = 0; 39473034Sjwd lp->d_checksum = dkcksum(lp); 39573034Sjwd if (rflag) { 39673034Sjwd /* 39773034Sjwd * First set the kernel disk label, 39873034Sjwd * then write a label to the raw disk. 39973034Sjwd * If the SDINFO ioctl fails because it is unimplemented, 40073034Sjwd * keep going; otherwise, the kernel consistency checks 40173034Sjwd * may prevent us from changing the current (in-core) 40273034Sjwd * label. 40373034Sjwd */ 40473034Sjwd if (ioctl(f, DIOCSDINFO, lp) < 0 && 40573034Sjwd errno != ENODEV && errno != ENOTTY) { 40673034Sjwd l_perror("ioctl DIOCSDINFO"); 40773034Sjwd return (1); 40873034Sjwd } 40973034Sjwd (void)lseek(f, (off_t)0, SEEK_SET); 41073034Sjwd 41138411Sbde#ifdef __alpha__ 41273034Sjwd /* 41373034Sjwd * Generate the bootblock checksum for the SRM console. 41473034Sjwd */ 41573034Sjwd for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) 41673034Sjwd sum += p[i]; 41773034Sjwd p[63] = sum; 41838384Sdfr#endif 41992058Sobrien#ifdef __sparc64__ 42073034Sjwd /* 42192058Sobrien * Generate a Sun disklabel around the BSD label for 42292058Sobrien * PROM compatability. 42392058Sobrien */ 42492058Sobrien sl = (struct sun_disklabel *)boot; 42592058Sobrien memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); 42692058Sobrien sl->sl_rpm = lp->d_rpm; 42792058Sobrien sl->sl_pcylinders = lp->d_ncylinders + 42892058Sobrien lp->d_acylinders; /* XXX */ 42992058Sobrien sl->sl_sparespercyl = lp->d_sparespercyl; 43092058Sobrien sl->sl_interleave = lp->d_interleave; 43192058Sobrien sl->sl_ncylinders = lp->d_ncylinders; 43292058Sobrien sl->sl_acylinders = lp->d_acylinders; 43392058Sobrien sl->sl_ntracks = lp->d_ntracks; 43492058Sobrien sl->sl_nsectors = lp->d_nsectors; 43592058Sobrien sl->sl_magic = SUN_DKMAGIC; 43692058Sobrien secpercyl = sl->sl_nsectors * sl->sl_ntracks; 43792058Sobrien for (i = 0; i < 8; i++) { 43892058Sobrien spp = &sl->sl_part[i]; 43992058Sobrien npp = &lp->d_partitions[i]; 44092058Sobrien /* 44192058Sobrien * SunOS partitions must start on a cylinder 44292058Sobrien * boundary. Note this restriction is forced 44392058Sobrien * upon FreeBSD/sparc64 labels too, since we 44492058Sobrien * want to keep both labels synchronised. 44592058Sobrien */ 44692058Sobrien spp->sdkp_cyloffset = npp->p_offset / secpercyl; 44792058Sobrien spp->sdkp_nsectors = npp->p_size; 44892058Sobrien } 44992058Sobrien 45092058Sobrien /* Compute the XOR checksum. */ 45192058Sobrien sp1 = (u_short *)sl; 45292058Sobrien sp2 = (u_short *)(sl + 1); 45392058Sobrien sl->sl_cksum = cksum = 0; 45492058Sobrien while (sp1 < sp2) 45592058Sobrien cksum ^= *sp1++; 45692058Sobrien sl->sl_cksum = cksum; 45792058Sobrien#endif 45892058Sobrien /* 45973034Sjwd * write enable label sector before write (if necessary), 46073034Sjwd * disable after writing. 46173034Sjwd */ 46273034Sjwd flag = 1; 46373034Sjwd if (ioctl(f, DIOCWLABEL, &flag) < 0) 46473034Sjwd warn("ioctl DIOCWLABEL"); 46573034Sjwd if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 46673034Sjwd warn("write"); 46773034Sjwd return (1); 46873034Sjwd } 46973034Sjwd#if NUMBOOT > 0 47073034Sjwd /* 47173034Sjwd * Output the remainder of the disklabel 47273034Sjwd */ 47373034Sjwd if (bootbuf && write(f, bootbuf, bootsize) != bootsize) { 47473034Sjwd warn("write"); 47573034Sjwd return(1); 47673034Sjwd } 47773034Sjwd#endif 47873034Sjwd flag = 0; 47973034Sjwd (void) ioctl(f, DIOCWLABEL, &flag); 48073034Sjwd } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 48173034Sjwd l_perror("ioctl DIOCWDINFO"); 4821558Srgrimes return (1); 4831558Srgrimes } 4841558Srgrimes } 4851558Srgrimes return (0); 4861558Srgrimes} 4871558Srgrimes 48813544Sjoergvoid 48992541Simpl_perror(const char *s) 4901558Srgrimes{ 49136632Scharnier switch (errno) { 4921558Srgrimes 4931558Srgrimes case ESRCH: 49436756Scharnier warnx("%s: no disk label on disk;", s); 49575915Simp fprintf(stderr, "add \"-r\" to install initial label\n"); 4961558Srgrimes break; 4971558Srgrimes 4981558Srgrimes case EINVAL: 49936756Scharnier warnx("%s: label magic number or checksum is wrong!", s); 50036756Scharnier fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 5011558Srgrimes break; 5021558Srgrimes 5031558Srgrimes case EBUSY: 50436632Scharnier warnx("%s: open partition would move or shrink", s); 5051558Srgrimes break; 5061558Srgrimes 5071558Srgrimes case EXDEV: 50840475Sbde warnx("%s: '%c' partition must start at beginning of disk", 50940475Sbde s, 'a' + RAW_PART); 5101558Srgrimes break; 5111558Srgrimes 5121558Srgrimes default: 51336632Scharnier warn((char *)NULL); 5141558Srgrimes break; 5151558Srgrimes } 5161558Srgrimes} 5171558Srgrimes 5181558Srgrimes/* 5191558Srgrimes * Fetch disklabel for disk. 5201558Srgrimes * Use ioctl to get label unless -r flag is given. 5211558Srgrimes */ 5221558Srgrimesstruct disklabel * 52392541Simpreadlabel(int f) 5241558Srgrimes{ 52592541Simp struct disklabel *lp; 5261558Srgrimes 5271558Srgrimes if (rflag) { 5281558Srgrimes if (read(f, bootarea, BBSIZE) < BBSIZE) 52926542Scharnier err(4, "%s", specname); 5301558Srgrimes for (lp = (struct disklabel *)bootarea; 5311558Srgrimes lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 5321558Srgrimes lp = (struct disklabel *)((char *)lp + 16)) 5331558Srgrimes if (lp->d_magic == DISKMAGIC && 5341558Srgrimes lp->d_magic2 == DISKMAGIC) 5351558Srgrimes break; 5361558Srgrimes if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 5371558Srgrimes lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 53836756Scharnier dkcksum(lp) != 0) 53936756Scharnier errx(1, 54036756Scharnier "bad pack magic number (label is damaged, or pack is unlabeled)"); 5411558Srgrimes } else { 5421558Srgrimes lp = &lab; 5431558Srgrimes if (ioctl(f, DIOCGDINFO, lp) < 0) 54426542Scharnier err(4, "ioctl DIOCGDINFO"); 5451558Srgrimes } 5461558Srgrimes return (lp); 5471558Srgrimes} 5481558Srgrimes 5491558Srgrimes/* 5501558Srgrimes * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 5511558Srgrimes * Returns a pointer to the disklabel portion of the bootarea. 5521558Srgrimes */ 5531558Srgrimesstruct disklabel * 55492541Simpmakebootarea(char *boot, struct disklabel *dp, int f) 5551558Srgrimes{ 55638483Sbde struct disklabel *lp; 55792541Simp char *p; 5581558Srgrimes int b; 5591558Srgrimes#if NUMBOOT > 0 5601558Srgrimes char *dkbasename; 5611558Srgrimes struct stat sb; 56238411Sbde#endif 56338411Sbde#ifdef __alpha__ 56438483Sbde u_long *bootinfo; 56538411Sbde int n; 56638411Sbde#endif 56713892Sjoerg#ifdef __i386__ 56813892Sjoerg char *tmpbuf; 56913892Sjoerg int i, found; 57013544Sjoerg#endif 5711558Srgrimes 5721558Srgrimes /* XXX */ 5731558Srgrimes if (dp->d_secsize == 0) { 5741558Srgrimes dp->d_secsize = DEV_BSIZE; 5751558Srgrimes dp->d_bbsize = BBSIZE; 5761558Srgrimes } 5771558Srgrimes lp = (struct disklabel *) 5781558Srgrimes (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 5791558Srgrimes bzero((char *)lp, sizeof *lp); 5801558Srgrimes#if NUMBOOT > 0 5811558Srgrimes /* 5821558Srgrimes * If we are not installing a boot program but we are installing a 5831558Srgrimes * label on disk then we must read the current bootarea so we don't 5841558Srgrimes * clobber the existing boot. 5851558Srgrimes */ 5861558Srgrimes if (!installboot) { 5871558Srgrimes if (rflag) { 5881558Srgrimes if (read(f, boot, BBSIZE) < BBSIZE) 58926542Scharnier err(4, "%s", specname); 5901558Srgrimes bzero((char *)lp, sizeof *lp); 5911558Srgrimes } 5921558Srgrimes return (lp); 5931558Srgrimes } 5941558Srgrimes /* 5951558Srgrimes * We are installing a boot program. Determine the name(s) and 5961558Srgrimes * read them into the appropriate places in the boot area. 5971558Srgrimes */ 5981558Srgrimes if (!xxboot || !bootxx) { 5991558Srgrimes dkbasename = np; 6001558Srgrimes if ((p = rindex(dkname, '/')) == NULL) 6011558Srgrimes p = dkname; 6021558Srgrimes else 6031558Srgrimes p++; 6041558Srgrimes while (*p && !isdigit(*p)) 6051558Srgrimes *np++ = *p++; 6061558Srgrimes *np++ = '\0'; 6071558Srgrimes 6081558Srgrimes if (!xxboot) { 60941901Sjkh (void)sprintf(boot0, "%s/boot1", _PATH_BOOTDIR); 61041901Sjkh xxboot = boot0; 6111558Srgrimes } 6121558Srgrimes#if NUMBOOT > 1 6131558Srgrimes if (!bootxx) { 61441901Sjkh (void)sprintf(boot1, "%s/boot2", _PATH_BOOTDIR); 61541901Sjkh bootxx = boot1; 6161558Srgrimes } 6171558Srgrimes#endif 6181558Srgrimes } 6191558Srgrimes 6201558Srgrimes /* 6211558Srgrimes * Strange rules: 62292058Sobrien * 1. One-piece bootstrap (hp300/hp800) 62392057Sobrien * 1. One-piece bootstrap (alpha/sparc64) 6241558Srgrimes * up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest 6251558Srgrimes * is remembered and written later following the bootarea. 62692058Sobrien * 2. Two-piece bootstraps (i386/ia64) 6271558Srgrimes * up to d_secsize bytes of ``xxboot'' go in first d_secsize 6281558Srgrimes * bytes of bootarea, remaining d_bbsize-d_secsize filled 6291558Srgrimes * from ``bootxx''. 6301558Srgrimes */ 6311558Srgrimes b = open(xxboot, O_RDONLY); 6321558Srgrimes if (b < 0) 63326542Scharnier err(4, "%s", xxboot); 6341558Srgrimes#if NUMBOOT > 1 63513892Sjoerg#ifdef __i386__ 63613892Sjoerg /* 63713892Sjoerg * XXX Botch alert. 63813892Sjoerg * The i386 has the so-called fdisk table embedded into the 63913892Sjoerg * primary bootstrap. We take care to not clobber it, but 64013892Sjoerg * only if it does already contain some data. (Otherwise, 64113892Sjoerg * the xxboot provides a template.) 64213892Sjoerg */ 64313892Sjoerg if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) 64426542Scharnier err(4, "%s", xxboot); 64513892Sjoerg memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); 64697553Salfred#endif /* __i386__ */ 6471558Srgrimes if (read(b, boot, (int)dp->d_secsize) < 0) 64826542Scharnier err(4, "%s", xxboot); 6491558Srgrimes (void)close(b); 65013892Sjoerg#ifdef __i386__ 65113892Sjoerg for (i = DOSPARTOFF, found = 0; 65213892Sjoerg !found && i < DOSPARTOFF + NDOSPART*sizeof(struct dos_partition); 65313892Sjoerg i++) 65413892Sjoerg found = tmpbuf[i] != 0; 65513892Sjoerg if (found) 65613892Sjoerg memcpy((void *)&boot[DOSPARTOFF], 65713892Sjoerg (void *)&tmpbuf[DOSPARTOFF], 65813892Sjoerg NDOSPART * sizeof(struct dos_partition)); 65913892Sjoerg free(tmpbuf); 66097553Salfred#endif /* __i386__ */ 6611558Srgrimes b = open(bootxx, O_RDONLY); 6621558Srgrimes if (b < 0) 66326542Scharnier err(4, "%s", bootxx); 66437865Sbde if (fstat(b, &sb) != 0) 66537865Sbde err(4, "%s", bootxx); 66637865Sbde if (dp->d_secsize + sb.st_size > dp->d_bbsize) 66737865Sbde errx(4, "%s too large", bootxx); 66813544Sjoerg if (read(b, &boot[dp->d_secsize], 66913544Sjoerg (int)(dp->d_bbsize-dp->d_secsize)) < 0) 67026542Scharnier err(4, "%s", bootxx); 67138411Sbde#else /* !(NUMBOOT > 1) */ 67238384Sdfr#ifdef __alpha__ 67338411Sbde /* 67438411Sbde * On the alpha, the primary bootstrap starts at the 67538411Sbde * second sector of the boot area. The first sector 67638411Sbde * contains the label and must be edited to contain the 67738411Sbde * size and location of the primary bootstrap. 67838411Sbde */ 67938411Sbde n = read(b, boot + dp->d_secsize, (int)dp->d_bbsize); 68038411Sbde if (n < 0) 68138384Sdfr err(4, "%s", xxboot); 68238483Sbde bootinfo = (u_long *)(boot + 480); 68338483Sbde bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; 68438483Sbde bootinfo[1] = 1; /* start at sector 1 */ 68538483Sbde bootinfo[2] = 0; /* flags (must be zero) */ 68638411Sbde#else /* !__alpha__ */ 6871558Srgrimes if (read(b, boot, (int)dp->d_bbsize) < 0) 68826542Scharnier err(4, "%s", xxboot); 68938411Sbde#endif /* __alpha__ */ 69037865Sbde if (fstat(b, &sb) != 0) 69137865Sbde err(4, "%s", xxboot); 6921558Srgrimes bootsize = (int)sb.st_size - dp->d_bbsize; 6931558Srgrimes if (bootsize > 0) { 6941558Srgrimes /* XXX assume d_secsize is a power of two */ 6951558Srgrimes bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1); 6961558Srgrimes bootbuf = (char *)malloc((size_t)bootsize); 6971558Srgrimes if (bootbuf == 0) 69826542Scharnier err(4, "%s", xxboot); 6991558Srgrimes if (read(b, bootbuf, bootsize) < 0) { 7001558Srgrimes free(bootbuf); 70126542Scharnier err(4, "%s", xxboot); 7021558Srgrimes } 7031558Srgrimes } 70438411Sbde#endif /* NUMBOOT > 1 */ 7051558Srgrimes (void)close(b); 70638411Sbde#endif /* NUMBOOT > 0 */ 7071558Srgrimes /* 7081558Srgrimes * Make sure no part of the bootstrap is written in the area 7091558Srgrimes * reserved for the label. 7101558Srgrimes */ 7111558Srgrimes for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 71236632Scharnier if (*p) 71336632Scharnier errx(2, "bootstrap doesn't leave room for disk label"); 7141558Srgrimes return (lp); 7151558Srgrimes} 7161558Srgrimes 71713544Sjoergvoid 71892541Simpdisplay(FILE *f, const struct disklabel *lp) 7191558Srgrimes{ 72092541Simp int i, j; 72192541Simp const struct partition *pp; 7221558Srgrimes 7231558Srgrimes fprintf(f, "# %s:\n", specname); 7241558Srgrimes if ((unsigned) lp->d_type < DKMAXTYPES) 7251558Srgrimes fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 7261558Srgrimes else 72737234Sbde fprintf(f, "type: %u\n", lp->d_type); 72813544Sjoerg fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 72913544Sjoerg lp->d_typename); 73013544Sjoerg fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 73113544Sjoerg lp->d_packname); 7321558Srgrimes fprintf(f, "flags:"); 7331558Srgrimes if (lp->d_flags & D_REMOVABLE) 7341558Srgrimes fprintf(f, " removeable"); 7351558Srgrimes if (lp->d_flags & D_ECC) 7361558Srgrimes fprintf(f, " ecc"); 7371558Srgrimes if (lp->d_flags & D_BADSECT) 7381558Srgrimes fprintf(f, " badsect"); 7391558Srgrimes fprintf(f, "\n"); 74037234Sbde fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 74137234Sbde fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 74237234Sbde fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 74337234Sbde fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 74437234Sbde fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 74537234Sbde fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 74637234Sbde fprintf(f, "rpm: %u\n", lp->d_rpm); 74737234Sbde fprintf(f, "interleave: %u\n", lp->d_interleave); 74837234Sbde fprintf(f, "trackskew: %u\n", lp->d_trackskew); 74937234Sbde fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 75037234Sbde fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 75137234Sbde (u_long)lp->d_headswitch); 75213544Sjoerg fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 75337234Sbde (u_long)lp->d_trkseek); 7541558Srgrimes fprintf(f, "drivedata: "); 7551558Srgrimes for (i = NDDATA - 1; i >= 0; i--) 7561558Srgrimes if (lp->d_drivedata[i]) 7571558Srgrimes break; 7581558Srgrimes if (i < 0) 7591558Srgrimes i = 0; 7601558Srgrimes for (j = 0; j <= i; j++) 76137234Sbde fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 76237234Sbde fprintf(f, "\n\n%u partitions:\n", lp->d_npartitions); 7631558Srgrimes fprintf(f, 7645393Sgibbs "# size offset fstype [fsize bsize bps/cpg]\n"); 7651558Srgrimes pp = lp->d_partitions; 7661558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 7671558Srgrimes if (pp->p_size) { 76837234Sbde fprintf(f, " %c: %8lu %8lu ", 'a' + i, 76937234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 7701558Srgrimes if ((unsigned) pp->p_fstype < FSMAXTYPES) 7711558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 7721558Srgrimes else 7731558Srgrimes fprintf(f, "%8d", pp->p_fstype); 7741558Srgrimes switch (pp->p_fstype) { 7751558Srgrimes 7761558Srgrimes case FS_UNUSED: /* XXX */ 77737234Sbde fprintf(f, " %5lu %5lu %5.5s ", 77837234Sbde (u_long)pp->p_fsize, 77937234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 7801558Srgrimes break; 7811558Srgrimes 7821558Srgrimes case FS_BSDFFS: 78337234Sbde fprintf(f, " %5lu %5lu %5u ", 78437234Sbde (u_long)pp->p_fsize, 78537234Sbde (u_long)(pp->p_fsize * pp->p_frag), 7861558Srgrimes pp->p_cpg); 7871558Srgrimes break; 7881558Srgrimes 7895393Sgibbs case FS_BSDLFS: 79037234Sbde fprintf(f, " %5lu %5lu %5d", 79137234Sbde (u_long)pp->p_fsize, 79237234Sbde (u_long)(pp->p_fsize * pp->p_frag), 7935393Sgibbs pp->p_cpg); 7945393Sgibbs break; 7955393Sgibbs 7961558Srgrimes default: 7971558Srgrimes fprintf(f, "%20.20s", ""); 7981558Srgrimes break; 7991558Srgrimes } 80037234Sbde fprintf(f, "\t# (Cyl. %4lu", 80137234Sbde (u_long)(pp->p_offset / lp->d_secpercyl)); 8021558Srgrimes if (pp->p_offset % lp->d_secpercyl) 8031558Srgrimes putc('*', f); 8041558Srgrimes else 8051558Srgrimes putc(' ', f); 80637234Sbde fprintf(f, "- %lu", 80737234Sbde (u_long)((pp->p_offset + pp->p_size + 80837234Sbde lp->d_secpercyl - 1) / 80937234Sbde lp->d_secpercyl - 1)); 8101558Srgrimes if (pp->p_size % lp->d_secpercyl) 8111558Srgrimes putc('*', f); 8121558Srgrimes fprintf(f, ")\n"); 8131558Srgrimes } 8141558Srgrimes } 8151558Srgrimes fflush(f); 8161558Srgrimes} 8171558Srgrimes 81813544Sjoergint 81992541Simpedit(struct disklabel *lp, int f) 8201558Srgrimes{ 82192541Simp int c, fd; 8221558Srgrimes struct disklabel label; 82324180Simp FILE *fp; 8241558Srgrimes 82524180Simp if ((fd = mkstemp(tmpfil)) == -1 || 82624180Simp (fp = fdopen(fd, "w")) == NULL) { 82736632Scharnier warnx("can't create %s", tmpfil); 8281558Srgrimes return (1); 8291558Srgrimes } 83024180Simp display(fp, lp); 83124180Simp fclose(fp); 8321558Srgrimes for (;;) { 8331558Srgrimes if (!editit()) 8341558Srgrimes break; 83524180Simp fp = fopen(tmpfil, "r"); 83624180Simp if (fp == NULL) { 83736632Scharnier warnx("can't reopen %s for reading", tmpfil); 8381558Srgrimes break; 8391558Srgrimes } 8401558Srgrimes bzero((char *)&label, sizeof(label)); 84124180Simp if (getasciilabel(fp, &label)) { 8421558Srgrimes *lp = label; 8431558Srgrimes if (writelabel(f, bootarea, lp) == 0) { 84424180Simp fclose(fp); 8451558Srgrimes (void) unlink(tmpfil); 8461558Srgrimes return (0); 8471558Srgrimes } 8481558Srgrimes } 84924180Simp fclose(fp); 8501558Srgrimes printf("re-edit the label? [y]: "); fflush(stdout); 8511558Srgrimes c = getchar(); 8521558Srgrimes if (c != EOF && c != (int)'\n') 8531558Srgrimes while (getchar() != (int)'\n') 8541558Srgrimes ; 8551558Srgrimes if (c == (int)'n') 8561558Srgrimes break; 8571558Srgrimes } 8581558Srgrimes (void) unlink(tmpfil); 8591558Srgrimes return (1); 8601558Srgrimes} 8611558Srgrimes 86213544Sjoergint 86392541Simpeditit(void) 8641558Srgrimes{ 86592541Simp int pid, xpid; 8661558Srgrimes int stat, omask; 86792541Simp char *ed; 8681558Srgrimes 8691558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 8701558Srgrimes while ((pid = fork()) < 0) { 8711558Srgrimes if (errno == EPROCLIM) { 87236632Scharnier warnx("you have too many processes"); 8731558Srgrimes return(0); 8741558Srgrimes } 8751558Srgrimes if (errno != EAGAIN) { 87636632Scharnier warn("fork"); 8771558Srgrimes return(0); 8781558Srgrimes } 8791558Srgrimes sleep(1); 8801558Srgrimes } 8811558Srgrimes if (pid == 0) { 8821558Srgrimes sigsetmask(omask); 8831558Srgrimes setgid(getgid()); 8841558Srgrimes setuid(getuid()); 8851558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 8861558Srgrimes ed = DEFEDITOR; 88779452Sbrian execlp(ed, ed, tmpfil, (char *)0); 88836632Scharnier err(1, "%s", ed); 8891558Srgrimes } 8901558Srgrimes while ((xpid = wait(&stat)) >= 0) 8911558Srgrimes if (xpid == pid) 8921558Srgrimes break; 8931558Srgrimes sigsetmask(omask); 8941558Srgrimes return(!stat); 8951558Srgrimes} 8961558Srgrimes 8971558Srgrimeschar * 89892541Simpskip(char *cp) 8991558Srgrimes{ 9001558Srgrimes 9011558Srgrimes while (*cp != '\0' && isspace(*cp)) 9021558Srgrimes cp++; 9031558Srgrimes if (*cp == '\0' || *cp == '#') 90492541Simp return (NULL); 9051558Srgrimes return (cp); 9061558Srgrimes} 9071558Srgrimes 9081558Srgrimeschar * 90992541Simpword(char *cp) 9101558Srgrimes{ 91192541Simp char c; 9121558Srgrimes 9131558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 9141558Srgrimes cp++; 9151558Srgrimes if ((c = *cp) != '\0') { 9161558Srgrimes *cp++ = '\0'; 9171558Srgrimes if (c != '#') 9181558Srgrimes return (skip(cp)); 9191558Srgrimes } 92092541Simp return (NULL); 9211558Srgrimes} 9221558Srgrimes 9231558Srgrimes/* 9241558Srgrimes * Read an ascii label in from fd f, 9251558Srgrimes * in the same format as that put out by display(), 9261558Srgrimes * and fill in lp. 9271558Srgrimes */ 92813544Sjoergint 92992541Simpgetasciilabel(FILE *f, struct disklabel *lp) 9301558Srgrimes{ 93194065Sphk char *cp; 93294065Sphk const char **cpp; 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; 96197855Siedowse break; 9621558Srgrimes } 96397855Siedowse if (cpp < &dktypenames[DKMAXTYPES]) 96497855Siedowse continue; 9651558Srgrimes v = atoi(tp); 9661558Srgrimes if ((unsigned)v >= DKMAXTYPES) 9671558Srgrimes fprintf(stderr, "line %d:%s %d\n", lineno, 9681558Srgrimes "Warning, unknown disk type", v); 9691558Srgrimes lp->d_type = v; 9701558Srgrimes continue; 9711558Srgrimes } 9721558Srgrimes if (streq(cp, "flags")) { 9731558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 9741558Srgrimes tp = word(cp); 9751558Srgrimes if (streq(cp, "removeable")) 9761558Srgrimes v |= D_REMOVABLE; 9771558Srgrimes else if (streq(cp, "ecc")) 9781558Srgrimes v |= D_ECC; 9791558Srgrimes else if (streq(cp, "badsect")) 9801558Srgrimes v |= D_BADSECT; 9811558Srgrimes else { 9821558Srgrimes fprintf(stderr, 9831558Srgrimes "line %d: %s: bad flag\n", 9841558Srgrimes lineno, cp); 9851558Srgrimes errors++; 9861558Srgrimes } 9871558Srgrimes } 9881558Srgrimes lp->d_flags = v; 9891558Srgrimes continue; 9901558Srgrimes } 9911558Srgrimes if (streq(cp, "drivedata")) { 9921558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 9931558Srgrimes lp->d_drivedata[i++] = atoi(cp); 9941558Srgrimes tp = word(cp); 9951558Srgrimes } 9961558Srgrimes continue; 9971558Srgrimes } 9981558Srgrimes if (sscanf(cp, "%d partitions", &v) == 1) { 9991558Srgrimes if (v == 0 || (unsigned)v > MAXPARTITIONS) { 10001558Srgrimes fprintf(stderr, 10011558Srgrimes "line %d: bad # of partitions\n", lineno); 10021558Srgrimes lp->d_npartitions = MAXPARTITIONS; 10031558Srgrimes errors++; 10041558Srgrimes } else 10051558Srgrimes lp->d_npartitions = v; 10061558Srgrimes continue; 10071558Srgrimes } 10081558Srgrimes if (tp == NULL) 10091558Srgrimes tp = ""; 10101558Srgrimes if (streq(cp, "disk")) { 10111558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 10121558Srgrimes continue; 10131558Srgrimes } 10141558Srgrimes if (streq(cp, "label")) { 10151558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 10161558Srgrimes continue; 10171558Srgrimes } 10181558Srgrimes if (streq(cp, "bytes/sector")) { 10191558Srgrimes v = atoi(tp); 102037865Sbde if (v <= 0 || (v % DEV_BSIZE) != 0) { 10211558Srgrimes fprintf(stderr, 10221558Srgrimes "line %d: %s: bad sector size\n", 10231558Srgrimes lineno, tp); 10241558Srgrimes errors++; 10251558Srgrimes } else 10261558Srgrimes lp->d_secsize = v; 10271558Srgrimes continue; 10281558Srgrimes } 10291558Srgrimes if (streq(cp, "sectors/track")) { 10301558Srgrimes v = atoi(tp); 10311558Srgrimes if (v <= 0) { 10321558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10331558Srgrimes lineno, tp, cp); 10341558Srgrimes errors++; 10351558Srgrimes } else 10361558Srgrimes lp->d_nsectors = v; 10371558Srgrimes continue; 10381558Srgrimes } 10391558Srgrimes if (streq(cp, "sectors/cylinder")) { 10401558Srgrimes v = atoi(tp); 10411558Srgrimes if (v <= 0) { 10421558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10431558Srgrimes lineno, tp, cp); 10441558Srgrimes errors++; 10451558Srgrimes } else 10461558Srgrimes lp->d_secpercyl = v; 10471558Srgrimes continue; 10481558Srgrimes } 10491558Srgrimes if (streq(cp, "tracks/cylinder")) { 10501558Srgrimes v = atoi(tp); 10511558Srgrimes if (v <= 0) { 10521558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 10531558Srgrimes lineno, tp, cp); 10541558Srgrimes errors++; 10551558Srgrimes } else 10561558Srgrimes lp->d_ntracks = v; 10571558Srgrimes continue; 10581558Srgrimes } 10591558Srgrimes if (streq(cp, "cylinders")) { 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_ncylinders = v; 10671558Srgrimes continue; 10681558Srgrimes } 10696643Sbde if (streq(cp, "sectors/unit")) { 10706643Sbde v = atoi(tp); 10716643Sbde if (v <= 0) { 10726643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 10736643Sbde lineno, tp, cp); 10746643Sbde errors++; 10756643Sbde } else 10766643Sbde lp->d_secperunit = v; 10776643Sbde continue; 10786643Sbde } 10791558Srgrimes if (streq(cp, "rpm")) { 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_rpm = v; 10871558Srgrimes continue; 10881558Srgrimes } 10891558Srgrimes if (streq(cp, "interleave")) { 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_interleave = v; 10971558Srgrimes continue; 10981558Srgrimes } 10991558Srgrimes if (streq(cp, "trackskew")) { 11001558Srgrimes v = atoi(tp); 11011558Srgrimes if (v < 0) { 11021558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 11031558Srgrimes lineno, tp, cp); 11041558Srgrimes errors++; 11051558Srgrimes } else 11061558Srgrimes lp->d_trackskew = v; 11071558Srgrimes continue; 11081558Srgrimes } 11091558Srgrimes if (streq(cp, "cylinderskew")) { 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_cylskew = v; 11171558Srgrimes continue; 11181558Srgrimes } 11191558Srgrimes if (streq(cp, "headswitch")) { 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_headswitch = v; 11271558Srgrimes continue; 11281558Srgrimes } 11291558Srgrimes if (streq(cp, "track-to-track seek")) { 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_trkseek = v; 11371558Srgrimes continue; 11381558Srgrimes } 113973034Sjwd /* the ':' was removed above */ 114097534Siedowse if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') { 114197534Siedowse fprintf(stderr, 114297534Siedowse "line %d: %s: Unknown disklabel field\n", lineno, 114397534Siedowse cp); 114497534Siedowse errors++; 114597534Siedowse continue; 114697534Siedowse } 114797534Siedowse 114897534Siedowse /* Process a partition specification line. */ 114997534Siedowse part = *cp - 'a'; 115097534Siedowse if (part >= lp->d_npartitions) { 115197534Siedowse fprintf(stderr, 115297534Siedowse "line %d: partition name out of range a-%c: %s\n", 115397534Siedowse lineno, 'a' + lp->d_npartitions - 1, cp); 115497534Siedowse errors++; 115597534Siedowse continue; 115697534Siedowse } 115797534Siedowse part_set[part] = 1; 115897534Siedowse 115997534Siedowse if (getasciipartspec(tp, lp, part, lineno) != 0) { 116097534Siedowse errors++; 116197534Siedowse break; 116297534Siedowse } 116397534Siedowse } 116497534Siedowse errors += checklabel(lp); 116597534Siedowse return (errors == 0); 116697534Siedowse} 116797534Siedowse 116897534Siedowse#define NXTNUM(n) do { \ 11693111Spst if (tp == NULL) { \ 11703111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 117197534Siedowse return (1); \ 11723111Spst } else { \ 11733111Spst cp = tp, tp = word(cp); \ 11743111Spst (n) = atoi(cp); \ 11753111Spst } \ 117697534Siedowse} while (0) 117797534Siedowse 117873034Sjwd/* retain 1 character following number */ 117997534Siedowse#define NXTWORD(w,n) do { \ 118073034Sjwd if (tp == NULL) { \ 118173034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 118297534Siedowse return (1); \ 118373034Sjwd } else { \ 118473034Sjwd char *tmp; \ 118573034Sjwd cp = tp, tp = word(cp); \ 118673034Sjwd (n) = strtol(cp,&tmp,10); \ 118773034Sjwd if (tmp) (w) = *tmp; \ 118873034Sjwd } \ 118997534Siedowse} while (0) 11901558Srgrimes 119197534Siedowse/* 119297534Siedowse * Read a partition line into partition `part' in the specified disklabel. 119397534Siedowse * Return 0 on success, 1 on failure. 119497534Siedowse */ 119597534Siedowseint 119697534Siedowsegetasciipartspec(char *tp, struct disklabel *lp, int part, int lineno) 119797534Siedowse{ 119897534Siedowse struct partition *pp; 119997534Siedowse char *cp; 120097534Siedowse const char **cpp; 120197534Siedowse int v; 12021558Srgrimes 120397534Siedowse pp = &lp->d_partitions[part]; 120497534Siedowse cp = NULL; 12051558Srgrimes 120697534Siedowse v = 0; 120797534Siedowse NXTWORD(part_size_type[part],v); 120897534Siedowse if (v < 0 || (v == 0 && part_size_type[part] != '*')) { 120997534Siedowse fprintf(stderr, "line %d: %s: bad partition size\n", lineno, 121097534Siedowse cp); 121197534Siedowse return (1); 121297534Siedowse } 121397534Siedowse pp->p_size = v; 121497534Siedowse 121597534Siedowse v = 0; 121697534Siedowse NXTWORD(part_offset_type[part],v); 121797534Siedowse if (v < 0 || (v == 0 && part_offset_type[part] != '*' && 121897534Siedowse part_offset_type[part] != '\0')) { 121997534Siedowse fprintf(stderr, "line %d: %s: bad partition offset\n", lineno, 122097534Siedowse cp); 122197534Siedowse return (1); 122297534Siedowse } 122397534Siedowse pp->p_offset = v; 122497534Siedowse cp = tp, tp = word(cp); 122597534Siedowse for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) 122697534Siedowse if (*cpp && streq(*cpp, cp)) 122797534Siedowse break; 122897534Siedowse if (*cpp != NULL) { 122997534Siedowse pp->p_fstype = cpp - fstypenames; 123097534Siedowse } else { 123197534Siedowse if (isdigit(*cp)) 123297534Siedowse v = atoi(cp); 123397534Siedowse else 123497534Siedowse v = FSMAXTYPES; 123597534Siedowse if ((unsigned)v >= FSMAXTYPES) { 123697534Siedowse fprintf(stderr, 123797534Siedowse "line %d: Warning, unknown filesystem type %s\n", 123897534Siedowse lineno, cp); 123997534Siedowse v = FS_UNUSED; 124097534Siedowse } 124197534Siedowse pp->p_fstype = v; 124297534Siedowse } 124397534Siedowse 124497534Siedowse switch (pp->p_fstype) { 124597534Siedowse case FS_UNUSED: 124697534Siedowse /* 124797534Siedowse * allow us to accept defaults for 124897534Siedowse * fsize/frag/cpg 124997534Siedowse */ 125097534Siedowse if (tp) { 125197534Siedowse NXTNUM(pp->p_fsize); 125297534Siedowse if (pp->p_fsize == 0) 125397534Siedowse break; 125497534Siedowse NXTNUM(v); 125597534Siedowse pp->p_frag = v / pp->p_fsize; 125697534Siedowse } 125797534Siedowse /* else default to 0's */ 125897534Siedowse break; 125997534Siedowse 126097534Siedowse /* These happen to be the same */ 126197534Siedowse case FS_BSDFFS: 126297534Siedowse case FS_BSDLFS: 126397534Siedowse if (tp) { 126497534Siedowse NXTNUM(pp->p_fsize); 126597534Siedowse if (pp->p_fsize == 0) 126697534Siedowse break; 126797534Siedowse NXTNUM(v); 126897534Siedowse pp->p_frag = v / pp->p_fsize; 126997534Siedowse NXTNUM(pp->p_cpg); 127097534Siedowse } else { 127197534Siedowse /* 127297534Siedowse * FIX! poor attempt at adaptive 127397534Siedowse */ 127497534Siedowse /* 1 GB */ 127597534Siedowse if (pp->p_size < 1024*1024*1024 / lp->d_secsize) { 127697534Siedowse /* 127797534Siedowse * FIX! These are too low, but are traditional 127897534Siedowse */ 127997535Siedowse pp->p_fsize = DEFAULT_NEWFS_FRAG; 128097535Siedowse pp->p_frag = DEFAULT_NEWFS_BLOCK / 128197535Siedowse DEFAULT_NEWFS_FRAG; 128297534Siedowse pp->p_cpg = DEFAULT_NEWFS_CPG; 128397534Siedowse } else { 128497535Siedowse pp->p_fsize = BIG_NEWFS_FRAG; 128597535Siedowse pp->p_frag = BIG_NEWFS_BLOCK / 128697535Siedowse BIG_NEWFS_FRAG; 128797534Siedowse pp->p_cpg = BIG_NEWFS_CPG; 12881558Srgrimes } 12891558Srgrimes } 129097534Siedowse default: 129197534Siedowse break; 12921558Srgrimes } 129397534Siedowse return (0); 12941558Srgrimes} 12951558Srgrimes 12961558Srgrimes/* 12971558Srgrimes * Check disklabel for errors and fill in 12981558Srgrimes * derived fields according to supplied values. 12991558Srgrimes */ 130013544Sjoergint 130192541Simpchecklabel(struct disklabel *lp) 13021558Srgrimes{ 130392541Simp struct partition *pp; 13041558Srgrimes int i, errors = 0; 13051558Srgrimes char part; 130673573Simp unsigned long total_size, total_percent, current_offset; 130773034Sjwd int seen_default_offset; 130873034Sjwd int hog_part; 130973034Sjwd int j; 131073034Sjwd struct partition *pp2; 13111558Srgrimes 13121558Srgrimes if (lp->d_secsize == 0) { 131337234Sbde fprintf(stderr, "sector size 0\n"); 13141558Srgrimes return (1); 13151558Srgrimes } 13161558Srgrimes if (lp->d_nsectors == 0) { 131737234Sbde fprintf(stderr, "sectors/track 0\n"); 13181558Srgrimes return (1); 13191558Srgrimes } 13201558Srgrimes if (lp->d_ntracks == 0) { 132137234Sbde fprintf(stderr, "tracks/cylinder 0\n"); 13221558Srgrimes return (1); 13231558Srgrimes } 13241558Srgrimes if (lp->d_ncylinders == 0) { 132537234Sbde fprintf(stderr, "cylinders/unit 0\n"); 13261558Srgrimes errors++; 13271558Srgrimes } 13281558Srgrimes if (lp->d_rpm == 0) 132937234Sbde Warning("revolutions/minute 0"); 13301558Srgrimes if (lp->d_secpercyl == 0) 13311558Srgrimes lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 13321558Srgrimes if (lp->d_secperunit == 0) 13331558Srgrimes lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 13341558Srgrimes if (lp->d_bbsize == 0) { 133537234Sbde fprintf(stderr, "boot block size 0\n"); 13361558Srgrimes errors++; 13371558Srgrimes } else if (lp->d_bbsize % lp->d_secsize) 13381558Srgrimes Warning("boot block size %% sector-size != 0"); 13391558Srgrimes if (lp->d_npartitions > MAXPARTITIONS) 134037234Sbde Warning("number of partitions (%lu) > MAXPARTITIONS (%d)", 134137234Sbde (u_long)lp->d_npartitions, MAXPARTITIONS); 134273034Sjwd 134373034Sjwd /* first allocate space to the partitions, then offsets */ 134473034Sjwd total_size = 0; /* in sectors */ 134573034Sjwd total_percent = 0; /* in percent */ 134673034Sjwd hog_part = -1; 134773034Sjwd /* find all fixed partitions */ 13481558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 134973034Sjwd pp = &lp->d_partitions[i]; 135073034Sjwd if (part_set[i]) { 135173034Sjwd if (part_size_type[i] == '*') { 135294065Sphk if (i == RAW_PART) { 135373034Sjwd pp->p_size = lp->d_secperunit; 135473034Sjwd } else { 135573034Sjwd if (hog_part != -1) 135673034Sjwd Warning("Too many '*' partitions (%c and %c)", 135773034Sjwd hog_part + 'a',i + 'a'); 135873034Sjwd else 135973034Sjwd hog_part = i; 136073034Sjwd } 136173034Sjwd } else { 136273573Simp off_t size; 136373034Sjwd 136473034Sjwd size = pp->p_size; 136573034Sjwd switch (part_size_type[i]) { 136673034Sjwd case '%': 136773034Sjwd total_percent += size; 136873034Sjwd break; 136973034Sjwd case 'k': 137073034Sjwd case 'K': 137173573Simp size *= 1024ULL; 137273034Sjwd break; 137373034Sjwd case 'm': 137473034Sjwd case 'M': 137573573Simp size *= 1024ULL * 1024ULL; 137673034Sjwd break; 137773034Sjwd case 'g': 137873034Sjwd case 'G': 137973573Simp size *= 1024ULL * 1024ULL * 1024ULL; 138073034Sjwd break; 138173034Sjwd case '\0': 138273034Sjwd break; 138373034Sjwd default: 138473034Sjwd Warning("unknown size specifier '%c' (K/M/G are valid)",part_size_type[i]); 138573034Sjwd break; 138673034Sjwd } 138773034Sjwd /* don't count %'s yet */ 138873034Sjwd if (part_size_type[i] != '%') { 138973034Sjwd /* 139073034Sjwd * for all not in sectors, convert to 139173034Sjwd * sectors 139273034Sjwd */ 139373034Sjwd if (part_size_type[i] != '\0') { 139473034Sjwd if (size % lp->d_secsize != 0) 139573034Sjwd Warning("partition %c not an integer number of sectors", 139673034Sjwd i + 'a'); 139773034Sjwd size /= lp->d_secsize; 139873034Sjwd pp->p_size = size; 139973034Sjwd } 140073034Sjwd /* else already in sectors */ 140194065Sphk if (i != RAW_PART) 140273034Sjwd total_size += size; 140373034Sjwd } 140473034Sjwd } 140573034Sjwd } 140673034Sjwd } 140773034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 140873034Sjwd if (total_percent != 0) { 140973034Sjwd long free_space = lp->d_secperunit - total_size; 141073034Sjwd if (total_percent > 100) { 141194065Sphk fprintf(stderr,"total percentage %lu is greater than 100\n", 141273034Sjwd total_percent); 141373034Sjwd errors++; 141473034Sjwd } 141573034Sjwd 141673034Sjwd if (free_space > 0) { 141773034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 141873034Sjwd pp = &lp->d_partitions[i]; 141973034Sjwd if (part_set[i] && part_size_type[i] == '%') { 142073034Sjwd /* careful of overflows! and integer roundoff */ 142173034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 142273034Sjwd total_size += pp->p_size; 142373034Sjwd 142473034Sjwd /* FIX we can lose a sector or so due to roundoff per 142573034Sjwd partition. A more complex algorithm could avoid that */ 142673034Sjwd } 142773034Sjwd } 142873034Sjwd } else { 142973034Sjwd fprintf(stderr, 143094065Sphk "%ld sectors available to give to '*' and '%%' partitions\n", 143173034Sjwd free_space); 143273034Sjwd errors++; 143373034Sjwd /* fix? set all % partitions to size 0? */ 143473034Sjwd } 143573034Sjwd } 143673034Sjwd /* give anything remaining to the hog partition */ 143773034Sjwd if (hog_part != -1) { 143873034Sjwd lp->d_partitions[hog_part].p_size = lp->d_secperunit - total_size; 143973034Sjwd total_size = lp->d_secperunit; 144073034Sjwd } 144173034Sjwd 144273034Sjwd /* Now set the offsets for each partition */ 144373034Sjwd current_offset = 0; /* in sectors */ 144473034Sjwd seen_default_offset = 0; 144573034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 14461558Srgrimes part = 'a' + i; 14471558Srgrimes pp = &lp->d_partitions[i]; 144873034Sjwd if (part_set[i]) { 144973034Sjwd if (part_offset_type[i] == '*') { 145094065Sphk if (i == RAW_PART) { 145173034Sjwd pp->p_offset = 0; 145273034Sjwd } else { 145373034Sjwd pp->p_offset = current_offset; 145473034Sjwd seen_default_offset = 1; 145573034Sjwd } 145673034Sjwd } else { 145773034Sjwd /* allow them to be out of order for old-style tables */ 145873034Sjwd if (pp->p_offset < current_offset && 145994065Sphk seen_default_offset && i != RAW_PART) { 146073034Sjwd fprintf(stderr, 146194065Sphk"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 146294065Sphk (long)pp->p_offset,i+'a',current_offset); 146373034Sjwd fprintf(stderr, 146473034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 146573034Sjwd errors++; 146673034Sjwd } else if (pp->p_offset != current_offset && 146794065Sphk i != RAW_PART && seen_default_offset) { 146873034Sjwd /* 146973034Sjwd * this may give unneeded warnings if 147073034Sjwd * partitions are out-of-order 147173034Sjwd */ 147273034Sjwd Warning( 147373034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 147494065Sphk (long)pp->p_offset, i + 'a', current_offset); 147573034Sjwd } 147673034Sjwd } 147794065Sphk if (i != RAW_PART) 147873034Sjwd current_offset = pp->p_offset + pp->p_size; 147973034Sjwd } 148073034Sjwd } 148173034Sjwd 148273034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 148373034Sjwd part = 'a' + i; 148473034Sjwd pp = &lp->d_partitions[i]; 14851558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 148637234Sbde Warning("partition %c: size 0, but offset %lu", 148737234Sbde part, (u_long)pp->p_offset); 148892058Sobrien#ifdef __sparc64__ 148992058Sobrien /* See comment in writelabel(). */ 149092058Sobrien if (pp->p_offset % lp->d_secpercyl != 0) { 149192058Sobrien fprintf(stderr, "partition %c: does not start on a " 149292058Sobrien "cylinder boundary!\n", part); 149392058Sobrien errors++; 149492058Sobrien } 149592058Sobrien#endif 14961558Srgrimes#ifdef notdef 14971558Srgrimes if (pp->p_size % lp->d_secpercyl) 14981558Srgrimes Warning("partition %c: size %% cylinder-size != 0", 14991558Srgrimes part); 15001558Srgrimes if (pp->p_offset % lp->d_secpercyl) 15011558Srgrimes Warning("partition %c: offset %% cylinder-size != 0", 15021558Srgrimes part); 15031558Srgrimes#endif 15041558Srgrimes if (pp->p_offset > lp->d_secperunit) { 15051558Srgrimes fprintf(stderr, 15061558Srgrimes "partition %c: offset past end of unit\n", part); 15071558Srgrimes errors++; 15081558Srgrimes } 15091558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 15101558Srgrimes fprintf(stderr, 151113544Sjoerg "partition %c: partition extends past end of unit\n", 15121558Srgrimes part); 15131558Srgrimes errors++; 15141558Srgrimes } 151594065Sphk if (i == RAW_PART) 151673034Sjwd { 151773034Sjwd if (pp->p_fstype != FS_UNUSED) 151873034Sjwd Warning("partition %c is not marked as unused!",part); 151973034Sjwd if (pp->p_offset != 0) 152073034Sjwd Warning("partition %c doesn't start at 0!",part); 152173034Sjwd if (pp->p_size != lp->d_secperunit) 152273034Sjwd Warning("partition %c doesn't cover the whole unit!",part); 152373034Sjwd 152473034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 152573034Sjwd (pp->p_size != lp->d_secperunit)) { 152673034Sjwd Warning("An incorrect partition %c may cause problems for " 152773034Sjwd "standard system utilities",part); 152873034Sjwd } 152973034Sjwd } 153073034Sjwd 153173034Sjwd /* check for overlaps */ 153273034Sjwd /* this will check for all possible overlaps once and only once */ 153373034Sjwd for (j = 0; j < i; j++) { 153494065Sphk if (j != RAW_PART && i != RAW_PART && 153573034Sjwd part_set[i] && part_set[j]) { 153673034Sjwd pp2 = &lp->d_partitions[j]; 153773034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 153873034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 153973034Sjwd pp2->p_offset >= pp->p_offset)) { 154073034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 154173034Sjwd j + 'a', i + 'a'); 154273034Sjwd errors++; 154373034Sjwd } 154473034Sjwd } 154573034Sjwd } 15461558Srgrimes } 15471558Srgrimes for (; i < MAXPARTITIONS; i++) { 15481558Srgrimes part = 'a' + i; 15491558Srgrimes pp = &lp->d_partitions[i]; 15501558Srgrimes if (pp->p_size || pp->p_offset) 155137234Sbde Warning("unused partition %c: size %d offset %lu", 155237234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 15531558Srgrimes } 15541558Srgrimes return (errors); 15551558Srgrimes} 15561558Srgrimes 15571558Srgrimes/* 155813550Sjoerg * When operating on a "virgin" disk, try getting an initial label 155913550Sjoerg * from the associated device driver. This might work for all device 156013550Sjoerg * drivers that are able to fetch some initial device parameters 156113550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 156213550Sjoerg * most IDE drives, or vn devices. 156313550Sjoerg * 156413550Sjoerg * The device name must be given in its "canonical" form. 156513550Sjoerg */ 156613550Sjoergstruct disklabel * 156713550Sjoerggetvirginlabel(void) 156813550Sjoerg{ 156913550Sjoerg static struct disklabel lab; 157013550Sjoerg char namebuf[BBSIZE]; 157113550Sjoerg int f; 157213550Sjoerg 157313550Sjoerg if (dkname[0] == '/') { 157437773Sbde warnx("\"auto\" requires the usage of a canonical disk name"); 157516431Sbde return (NULL); 157613550Sjoerg } 157759429Sobrien (void)snprintf(namebuf, BBSIZE, "%s%s", _PATH_DEV, dkname); 157837773Sbde if ((f = open(namebuf, O_RDONLY)) == -1) { 157937773Sbde warn("cannot open %s", namebuf); 158016431Sbde return (NULL); 158113550Sjoerg } 158268044Sjkh 158368044Sjkh /* 158468044Sjkh * Try to use the new get-virgin-label ioctl. If it fails, 158568044Sjkh * fallback to the old get-disdk-info ioctl. 158668044Sjkh */ 158791603Sphk if (ioctl(f, DIOCGDVIRGIN, &lab) == 0) 158891603Sphk goto out; 158991603Sphk if (ioctl(f, DIOCGDINFO, &lab) == 0) 159091603Sphk goto out; 159191603Sphk close(f); 159291603Sphk (void)snprintf(namebuf, BBSIZE, "%s%s%c", _PATH_DEV, dkname, 159391603Sphk 'a' + RAW_PART); 159491603Sphk if ((f = open(namebuf, O_RDONLY)) == -1) { 159591603Sphk warn("cannot open %s", namebuf); 159691603Sphk return (NULL); 159713550Sjoerg } 159891603Sphk if (ioctl(f, DIOCGDINFO, &lab) == 0) 159991603Sphk goto out; 160013550Sjoerg close(f); 160191603Sphk warn("No virgin disklabel found %s", namebuf); 160291603Sphk return (NULL); 160391603Sphk out: 160491603Sphk close(f); 160516431Sbde return (&lab); 160613550Sjoerg} 160713550Sjoerg 160813550Sjoerg/* 16091558Srgrimes * If we are installing a boot program that doesn't fit in d_bbsize 16101558Srgrimes * we need to mark those partitions that the boot overflows into. 16111558Srgrimes * This allows newfs to prevent creation of a filesystem where it might 16121558Srgrimes * clobber bootstrap code. 16131558Srgrimes */ 161413544Sjoergvoid 161592541Simpsetbootflag(struct disklabel *lp) 16161558Srgrimes{ 161792541Simp struct partition *pp; 16181558Srgrimes int i, errors = 0; 16191558Srgrimes char part; 16201558Srgrimes u_long boffset; 16211558Srgrimes 16221558Srgrimes if (bootbuf == 0) 16231558Srgrimes return; 16241558Srgrimes boffset = bootsize / lp->d_secsize; 16251558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 16261558Srgrimes part = 'a' + i; 16271558Srgrimes pp = &lp->d_partitions[i]; 16281558Srgrimes if (pp->p_size == 0) 16291558Srgrimes continue; 16301558Srgrimes if (boffset <= pp->p_offset) { 16311558Srgrimes if (pp->p_fstype == FS_BOOT) 16321558Srgrimes pp->p_fstype = FS_UNUSED; 16331558Srgrimes } else if (pp->p_fstype != FS_BOOT) { 16341558Srgrimes if (pp->p_fstype != FS_UNUSED) { 16351558Srgrimes fprintf(stderr, 16361558Srgrimes "boot overlaps used partition %c\n", 16371558Srgrimes part); 16381558Srgrimes errors++; 16391558Srgrimes } else { 16401558Srgrimes pp->p_fstype = FS_BOOT; 16411558Srgrimes Warning("boot overlaps partition %c, %s", 16421558Srgrimes part, "marked as FS_BOOT"); 16431558Srgrimes } 16441558Srgrimes } 16451558Srgrimes } 164636632Scharnier if (errors) 164736632Scharnier errx(4, "cannot install boot program"); 16481558Srgrimes} 16491558Srgrimes 16501558Srgrimes/*VARARGS1*/ 165113544Sjoergvoid 165292541SimpWarning(const char *fmt, ...) 16531558Srgrimes{ 165413544Sjoerg va_list ap; 16551558Srgrimes 16561558Srgrimes fprintf(stderr, "Warning, "); 165713544Sjoerg va_start(ap, fmt); 165813544Sjoerg vfprintf(stderr, fmt, ap); 16591558Srgrimes fprintf(stderr, "\n"); 166013544Sjoerg va_end(ap); 16611558Srgrimes} 16621558Srgrimes 166313544Sjoergvoid 166492541Simpusage(void) 16651558Srgrimes{ 16661558Srgrimes#if NUMBOOT > 0 166726542Scharnier 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", 166826542Scharnier "usage: disklabel [-r] disk", 166926542Scharnier "\t\t(to read label)", 167073034Sjwd " disklabel -w [-r] [-n] disk type [ packid ]", 167126542Scharnier "\t\t(to write label with existing boot program)", 167273034Sjwd " disklabel -e [-r] [-n] disk", 167326542Scharnier "\t\t(to edit label)", 167473034Sjwd " disklabel -R [-r] [-n] disk protofile", 167526542Scharnier "\t\t(to restore label with existing boot program)", 16761558Srgrimes#if NUMBOOT > 1 167773034Sjwd " disklabel -B [-n] [ -b boot1 [ -s boot2 ] ] disk [ type ]", 167826542Scharnier "\t\t(to install boot program with existing label)", 167973034Sjwd " disklabel -w -B [-n] [ -b boot1 [ -s boot2 ] ] disk type [ packid ]", 168026542Scharnier "\t\t(to write label and boot program)", 168173034Sjwd " disklabel -R -B [-n] [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]", 168226542Scharnier "\t\t(to restore label and boot program)", 16831558Srgrimes#else 168473034Sjwd " disklabel -B [-n] [ -b bootprog ] disk [ type ]", 168526542Scharnier "\t\t(to install boot program with existing on-disk label)", 168673034Sjwd " disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", 168726542Scharnier "\t\t(to write label and install boot program)", 168873034Sjwd " disklabel -R -B [-n] [ -b bootprog ] disk protofile [ type ]", 168926542Scharnier "\t\t(to restore label and install boot program)", 16901558Srgrimes#endif 169126542Scharnier " disklabel [-NW] disk", 169226542Scharnier "\t\t(to write disable/enable label)"); 16931558Srgrimes#else 169426542Scharnier fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 169526542Scharnier "usage: disklabel [-r] disk", "(to read label)", 169673034Sjwd " disklabel -w [-r] [-n] disk type [ packid ]", 169726542Scharnier "\t\t(to write label)", 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)", 170226542Scharnier " disklabel [-NW] disk", 170326542Scharnier "\t\t(to write disable/enable label)"); 17041558Srgrimes#endif 17051558Srgrimes exit(1); 17061558Srgrimes} 1707