bsdlabel.c revision 121222
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 43115449Sobrien#if 0 441558Srgrimes#ifndef lint 4536632Scharnierstatic const char copyright[] = 461558Srgrimes"@(#) Copyright (c) 1987, 1993\n\ 471558Srgrimes The Regents of the University of California. All rights reserved.\n"; 481558Srgrimes#endif /* not lint */ 491558Srgrimes 501558Srgrimes#ifndef lint 511558Srgrimesstatic char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; 521558Srgrimes/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 53115449Sobrien#endif /* not lint */ 5436632Scharnier#endif 5599365Smarkm#include <sys/cdefs.h> 5699365Smarkm__FBSDID("$FreeBSD: head/sbin/bsdlabel/bsdlabel.c 121222 2003-10-18 19:32:35Z phk $"); 5799365Smarkm 581558Srgrimes#include <sys/param.h> 59114552Sphk#include <stdint.h> 601558Srgrimes#include <sys/file.h> 611558Srgrimes#include <sys/stat.h> 6213544Sjoerg#include <sys/wait.h> 63103669Sphk#include <sys/disk.h> 641558Srgrimes#define DKTYPENAMES 65101994Sbmilekic#define FSTYPENAMES 661558Srgrimes#include <sys/disklabel.h> 67112307Sru 681558Srgrimes#include <unistd.h> 691558Srgrimes#include <string.h> 701558Srgrimes#include <stdio.h> 71114569Sphk#include <libgeom.h> 7213544Sjoerg#include <stdlib.h> 7313544Sjoerg#include <signal.h> 7413544Sjoerg#include <stdarg.h> 751558Srgrimes#include <ctype.h> 7626542Scharnier#include <err.h> 7759216Simp#include <errno.h> 7899365Smarkm 791558Srgrimes#include "pathnames.h" 801558Srgrimes 81114571Sphkstatic void makelabel(const char *, struct disklabel *); 82114571Sphkstatic int writelabel(void); 83114571Sphkstatic int readlabel(int flag); 84114571Sphkstatic void display(FILE *, const struct disklabel *); 85114571Sphkstatic int edit(void); 86114571Sphkstatic int editit(void); 87121222Sphkstatic void fixlabel(struct disklabel *); 88114571Sphkstatic char *skip(char *); 89114571Sphkstatic char *word(char *); 90114571Sphkstatic int getasciilabel(FILE *, struct disklabel *); 91114571Sphkstatic int getasciipartspec(char *, struct disklabel *, int, int); 92114571Sphkstatic int checklabel(struct disklabel *); 93114571Sphkstatic void usage(void); 94114571Sphkstatic struct disklabel *getvirginlabel(void); 9513544Sjoerg 961558Srgrimes#define DEFEDITOR _PATH_VI 971558Srgrimes 98114571Sphkstatic char *dkname; 99114571Sphkstatic char *specname; 100114571Sphkstatic char tmpfil[] = PATH_TMPFILE; 1011558Srgrimes 102114571Sphkstatic struct disklabel lab; 103114571Sphkstatic u_char bootarea[BBSIZE]; 104114574Sphkstatic off_t mediasize; 105114574Sphkstatic u_int secsize; 106114571Sphkstatic char blank[] = ""; 107114571Sphkstatic char unknown[] = "unknown"; 1081558Srgrimes 10973034Sjwd#define MAX_PART ('z') 11073034Sjwd#define MAX_NUM_PARTS (1 + MAX_PART - 'a') 111114571Sphkstatic char part_size_type[MAX_NUM_PARTS]; 112114571Sphkstatic char part_offset_type[MAX_NUM_PARTS]; 113114571Sphkstatic int part_set[MAX_NUM_PARTS]; 11473034Sjwd 115114571Sphkstatic int installboot; /* non-zero if we should install a boot program */ 116114574Sphkstatic int allfields; /* present all fields in edit */ 117114571Sphkstatic char const *xxboot; /* primary boot */ 1181558Srgrimes 119114673Sphkstatic off_t mbroffset; 120115995Sphk#ifndef LABELSECTOR 121115995Sphk#define LABELSECTOR -1 122115995Sphk#endif 123115995Sphk#ifndef LABELOFFSET 124115995Sphk#define LABELOFFSET -1 125115995Sphk#endif 126115696Sphkstatic int labelsoffset = LABELSECTOR; 127115696Sphkstatic int labeloffset = LABELOFFSET; 128114551Sphkstatic int bbsize = BBSIZE; 129114551Sphkstatic int alphacksum = 130114551Sphk#if defined(__alpha__) 131114551Sphk 1; 132114551Sphk#else 133114551Sphk 0; 134114551Sphk#endif 135114550Sphk 1361558Srgrimesenum { 137109872Sphk UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT 1381558Srgrimes} op = UNSPEC; 1391558Srgrimes 140112307Sru 141114571Sphkstatic int disable_write; /* set to disable writing to disk label */ 1421558Srgrimes 14313544Sjoergint 14492541Simpmain(int argc, char *argv[]) 1451558Srgrimes{ 1461558Srgrimes FILE *t; 147114569Sphk int ch, error = 0; 148114571Sphk char const *name = 0; 1491558Srgrimes 150114574Sphk while ((ch = getopt(argc, argv, "ABb:em:nRrs:w")) != -1) 1511558Srgrimes switch (ch) { 152114574Sphk case 'A': 153114574Sphk allfields = 1; 154114574Sphk break; 1551558Srgrimes case 'B': 1561558Srgrimes ++installboot; 1571558Srgrimes break; 1581558Srgrimes case 'b': 1591558Srgrimes xxboot = optarg; 1601558Srgrimes break; 161112307Sru case 'm': 162115948Sphk if (!strcmp(optarg, "i386") || 163115948Sphk !strcmp(optarg, "amd64") || 164115948Sphk !strcmp(optarg, "ia64") || 165115948Sphk !strcmp(optarg, "pc98")) { 166115696Sphk labelsoffset = 1; 167115696Sphk labeloffset = 0; 168114550Sphk bbsize = 8192; 169114551Sphk alphacksum = 0; 170114550Sphk } else if (!strcmp(optarg, "alpha")) { 171115696Sphk labelsoffset = 0; 172114550Sphk labeloffset = 64; 173114550Sphk bbsize = 8192; 174114550Sphk alphacksum = 1; 175114571Sphk } else { 176114571Sphk errx(1, "Unsupported architecture"); 177114550Sphk } 178112307Sru break; 17973034Sjwd case 'n': 18073034Sjwd disable_write = 1; 18173034Sjwd break; 1821558Srgrimes case 'R': 1831558Srgrimes if (op != UNSPEC) 1841558Srgrimes usage(); 1851558Srgrimes op = RESTORE; 1861558Srgrimes break; 1871558Srgrimes case 'e': 1881558Srgrimes if (op != UNSPEC) 1891558Srgrimes usage(); 1901558Srgrimes op = EDIT; 1911558Srgrimes break; 1921558Srgrimes case 'r': 193114571Sphk /* 194114571Sphk * We accept and ignode -r for compatibility with 195114571Sphk * historically disklabel usage. 196114571Sphk */ 1971558Srgrimes break; 1981558Srgrimes case 'w': 1991558Srgrimes if (op != UNSPEC) 2001558Srgrimes usage(); 2011558Srgrimes op = WRITE; 2021558Srgrimes break; 2031558Srgrimes case '?': 2041558Srgrimes default: 2051558Srgrimes usage(); 2061558Srgrimes } 2071558Srgrimes argc -= optind; 2081558Srgrimes argv += optind; 209114571Sphk 2101558Srgrimes if (argc < 1) 2111558Srgrimes usage(); 212115995Sphk if (labelsoffset < 0 || labeloffset < 0) 213115995Sphk errx(1, "a -m <architecture> option must be specified"); 2141558Srgrimes 215114569Sphk /* Figure out the names of the thing we're working on */ 216114569Sphk if (argv[0][0] != '/') { 217114569Sphk dkname = argv[0]; 218114569Sphk asprintf(&specname, "%s%s", _PATH_DEV, argv[0]); 219114569Sphk } else { 220114569Sphk dkname = strrchr(argv[0], '/'); 221114569Sphk dkname++; 222114569Sphk specname = argv[0]; 2231558Srgrimes } 2241558Srgrimes 225114571Sphk if (installboot && op == UNSPEC) 226114571Sphk op = WRITEBOOT; 227114571Sphk else if (op == UNSPEC) 228114571Sphk op = READ; 229114571Sphk 2301558Srgrimes switch(op) { 2311558Srgrimes 23248957Sbillf case UNSPEC: 23348957Sbillf break; 23448957Sbillf 2351558Srgrimes case EDIT: 2361558Srgrimes if (argc != 1) 2371558Srgrimes usage(); 238114571Sphk readlabel(1); 239121222Sphk fixlabel(&lab); 240114571Sphk error = edit(); 2411558Srgrimes break; 2421558Srgrimes 2431558Srgrimes case READ: 2441558Srgrimes if (argc != 1) 2451558Srgrimes usage(); 246114571Sphk readlabel(1); 247114571Sphk display(stdout, NULL); 248114571Sphk error = checklabel(NULL); 2491558Srgrimes break; 2501558Srgrimes 2511558Srgrimes case RESTORE: 2521558Srgrimes if (argc != 2) 2531558Srgrimes usage(); 2541558Srgrimes if (!(t = fopen(argv[1], "r"))) 255114569Sphk err(4, "fopen %s", argv[1]); 256114571Sphk readlabel(0); 25737865Sbde if (!getasciilabel(t, &lab)) 25837865Sbde exit(1); 259114571Sphk error = writelabel(); 2601558Srgrimes break; 2611558Srgrimes 2621558Srgrimes case WRITE: 263114571Sphk if (argc == 2) 264114571Sphk name = argv[1]; 265114571Sphk else if (argc == 1) 266114571Sphk name = "auto"; 267114571Sphk else 2681558Srgrimes usage(); 269114571Sphk readlabel(0); 270114571Sphk makelabel(name, &lab); 271121222Sphk fixlabel(&lab); 272114571Sphk if (checklabel(NULL) == 0) 273114571Sphk error = writelabel(); 2741558Srgrimes break; 2751558Srgrimes 2761558Srgrimes case WRITEBOOT: 2771558Srgrimes 278114571Sphk readlabel(1); 279121222Sphk fixlabel(&lab); 2801558Srgrimes if (argc == 2) 281114571Sphk makelabel(argv[1], &lab); 282114571Sphk if (checklabel(NULL) == 0) 283114571Sphk error = writelabel(); 2841558Srgrimes break; 2851558Srgrimes } 2861558Srgrimes exit(error); 2871558Srgrimes} 2881558Srgrimes 289121222Sphkstatic void 290121222Sphkfixlabel(struct disklabel *lp) 291121222Sphk{ 292121222Sphk struct partition *dp; 293121222Sphk int i; 294121222Sphk 295121222Sphk for (i = 0; i < MAXPARTITIONS; i++) { 296121222Sphk if (i == RAW_PART) 297121222Sphk continue; 298121222Sphk if (lp->d_partitions[i].p_size) 299121222Sphk return; 300121222Sphk } 301121222Sphk 302121222Sphk dp = &lp->d_partitions[0]; 303121222Sphk dp->p_offset = BBSIZE / secsize; 304121222Sphk dp->p_size = lp->d_secperunit - dp->p_offset; 305121222Sphk} 306121222Sphk 3071558Srgrimes/* 308111286Sru * Construct a prototype disklabel from /etc/disktab. 3091558Srgrimes */ 310114571Sphkstatic void 311114571Sphkmakelabel(const char *type, struct disklabel *lp) 3121558Srgrimes{ 31392541Simp struct disklabel *dp; 31413550Sjoerg 31513550Sjoerg if (strcmp(type, "auto") == 0) 31613550Sjoerg dp = getvirginlabel(); 31713550Sjoerg else 31813544Sjoerg dp = getdiskbyname(type); 31936632Scharnier if (dp == NULL) 32036632Scharnier errx(1, "%s: unknown disk type", type); 3211558Srgrimes *lp = *dp; 3221558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 3231558Srgrimes} 3241558Srgrimes 325114571Sphkstatic void 326114571Sphkreadboot(void) 3271558Srgrimes{ 328114571Sphk int fd, i; 329114571Sphk struct stat st; 330114571Sphk 331114571Sphk if (xxboot == NULL) 332114571Sphk xxboot = "/boot/boot"; 333114571Sphk fd = open(xxboot, O_RDONLY); 334114571Sphk if (fd < 0) 335114571Sphk err(1, "cannot open %s", xxboot); 336114571Sphk fstat(fd, &st); 337114860Sphk if (alphacksum && st.st_size <= BBSIZE - 512) { 338114860Sphk i = read(fd, bootarea + 512, st.st_size); 339114860Sphk if (i != st.st_size) 340114571Sphk err(1, "read error %s", xxboot); 341114571Sphk return; 342114860Sphk } else if ((!alphacksum) && st.st_size <= BBSIZE) { 343114860Sphk i = read(fd, bootarea, st.st_size); 344114860Sphk if (i != st.st_size) 345114571Sphk err(1, "read error %s", xxboot); 346114571Sphk return; 347114860Sphk } 348114571Sphk errx(1, "boot code %s is wrong size", xxboot); 349114571Sphk} 350114571Sphk 351114571Sphkstatic int 352114571Sphkwritelabel(void) 353114571Sphk{ 354112307Sru uint64_t *p, sum; 355114569Sphk int i, fd; 356114569Sphk struct gctl_req *grq; 357114569Sphk char const *errstr; 358114571Sphk struct disklabel *lp = &lab; 35938384Sdfr 36073034Sjwd if (disable_write) { 361114574Sphk warnx("write to disk label supressed - label was as follows:"); 362114571Sphk display(stdout, NULL); 36373034Sjwd return (0); 364109878Sphk } 365109878Sphk 366109878Sphk lp->d_magic = DISKMAGIC; 367109878Sphk lp->d_magic2 = DISKMAGIC; 368109878Sphk lp->d_checksum = 0; 369109878Sphk lp->d_checksum = dkcksum(lp); 370114571Sphk if (installboot) 371114571Sphk readboot(); 372114673Sphk for (i = 0; i < lab.d_npartitions; i++) 373114673Sphk if (lab.d_partitions[i].p_size) 374114673Sphk lab.d_partitions[i].p_offset += mbroffset; 375115696Sphk bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * secsize, 376115696Sphk lp); 377114552Sphk if (alphacksum) { 378114569Sphk /* Generate the bootblock checksum for the SRM console. */ 379114571Sphk for (p = (uint64_t *)bootarea, i = 0, sum = 0; i < 63; i++) 380112307Sru sum += p[i]; 381112307Sru p[63] = sum; 382112307Sru } 383114569Sphk 384114569Sphk fd = open(specname, O_RDWR); 385114569Sphk if (fd < 0) { 386115624Sphk grq = gctl_get_handle(); 387115624Sphk gctl_ro_param(grq, "verb", -1, "write label"); 388114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 389114569Sphk gctl_ro_param(grq, "geom", -1, dkname); 390115696Sphk gctl_ro_param(grq, "label", 148+16*8, 391115696Sphk bootarea + labeloffset + labelsoffset * secsize); 392114569Sphk errstr = gctl_issue(grq); 393114571Sphk if (errstr != NULL) { 394114571Sphk warnx("%s", errstr); 395114571Sphk gctl_free(grq); 396114571Sphk return(1); 397114571Sphk } 398114569Sphk gctl_free(grq); 399114569Sphk if (installboot) { 400115624Sphk grq = gctl_get_handle(); 401115624Sphk gctl_ro_param(grq, "verb", -1, "write bootcode"); 402114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 403114569Sphk gctl_ro_param(grq, "geom", -1, dkname); 404114571Sphk gctl_ro_param(grq, "bootcode", BBSIZE, bootarea); 405114569Sphk errstr = gctl_issue(grq); 406114571Sphk if (errstr != NULL) { 407114571Sphk warnx("%s", errstr); 408114571Sphk gctl_free(grq); 409114571Sphk return (1); 410114571Sphk } 411114569Sphk gctl_free(grq); 412114569Sphk } 413114569Sphk } else { 414114571Sphk if (write(fd, bootarea, bbsize) != bbsize) { 415114569Sphk warn("write %s", specname); 416114569Sphk close (fd); 417114569Sphk return (1); 418114569Sphk } 419114569Sphk close (fd); 420109878Sphk } 4211558Srgrimes return (0); 4221558Srgrimes} 4231558Srgrimes 4241558Srgrimes/* 4251558Srgrimes * Fetch disklabel for disk. 4261558Srgrimes * Use ioctl to get label unless -r flag is given. 4271558Srgrimes */ 428114571Sphkstatic int 429114571Sphkreadlabel(int flag) 4301558Srgrimes{ 431114673Sphk int f, i; 432114569Sphk int error; 433114673Sphk struct gctl_req *grq; 434114673Sphk char const *errstr; 4351558Srgrimes 436114569Sphk f = open(specname, O_RDONLY); 437114569Sphk if (f < 0) 438114569Sphk err(1, specname); 439115696Sphk /* New world order */ 440115696Sphk if ((ioctl(f, DIOCGMEDIASIZE, &mediasize) != 0) || 441115696Sphk (ioctl(f, DIOCGSECTORSIZE, &secsize) != 0)) { 442115696Sphk err(4, "cannot get disk geometry"); 443115696Sphk } 444114550Sphk (void)lseek(f, (off_t)0, SEEK_SET); 445114571Sphk if (read(f, bootarea, BBSIZE) != BBSIZE) 446114569Sphk err(4, "%s read", specname); 447114569Sphk close (f); 448115696Sphk error = bsd_disklabel_le_dec( 449115696Sphk bootarea + (labeloffset + labelsoffset * secsize), 450115696Sphk &lab, MAXPARTITIONS); 451114571Sphk if (flag && error) 452114571Sphk errx(1, "%s: no valid label found", specname); 453114673Sphk 454115624Sphk grq = gctl_get_handle(); 455115624Sphk gctl_ro_param(grq, "verb", -1, "read mbroffset"); 456114673Sphk gctl_ro_param(grq, "class", -1, "BSD"); 457114673Sphk gctl_ro_param(grq, "geom", -1, dkname); 458114673Sphk gctl_rw_param(grq, "mbroffset", sizeof(mbroffset), &mbroffset); 459114673Sphk errstr = gctl_issue(grq); 460114673Sphk if (errstr != NULL) { 461114673Sphk mbroffset = 0; 462114673Sphk gctl_free(grq); 463114673Sphk return (error); 464114673Sphk } 465114673Sphk mbroffset /= lab.d_secsize; 466114673Sphk if (lab.d_partitions[RAW_PART].p_offset == mbroffset) 467114673Sphk for (i = 0; i < lab.d_npartitions; i++) 468114673Sphk if (lab.d_partitions[i].p_size) 469114673Sphk lab.d_partitions[i].p_offset -= mbroffset; 470114571Sphk return (error); 4711558Srgrimes} 4721558Srgrimes 4731558Srgrimes 474114571Sphkstatic void 47592541Simpdisplay(FILE *f, const struct disklabel *lp) 4761558Srgrimes{ 47792541Simp int i, j; 47892541Simp const struct partition *pp; 4791558Srgrimes 480114571Sphk if (lp == NULL) 481114571Sphk lp = &lab; 482114571Sphk 4831558Srgrimes fprintf(f, "# %s:\n", specname); 484114574Sphk if (allfields) { 485114574Sphk if (lp->d_type < DKMAXTYPES) 486114574Sphk fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 487114574Sphk else 488114574Sphk fprintf(f, "type: %u\n", lp->d_type); 489114574Sphk fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 490114574Sphk lp->d_typename); 491114574Sphk fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 492114574Sphk lp->d_packname); 493114574Sphk fprintf(f, "flags:"); 494114574Sphk if (lp->d_flags & D_REMOVABLE) 495114574Sphk fprintf(f, " removeable"); 496114574Sphk if (lp->d_flags & D_ECC) 497114574Sphk fprintf(f, " ecc"); 498114574Sphk if (lp->d_flags & D_BADSECT) 499114574Sphk fprintf(f, " badsect"); 500114574Sphk fprintf(f, "\n"); 501114574Sphk fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 502114574Sphk fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 503114574Sphk fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 504114574Sphk fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 505114574Sphk fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 506114574Sphk fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 507114574Sphk fprintf(f, "rpm: %u\n", lp->d_rpm); 508114574Sphk fprintf(f, "interleave: %u\n", lp->d_interleave); 509114574Sphk fprintf(f, "trackskew: %u\n", lp->d_trackskew); 510114574Sphk fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 511114574Sphk fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 512114574Sphk (u_long)lp->d_headswitch); 513114574Sphk fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 514114574Sphk (u_long)lp->d_trkseek); 515114574Sphk fprintf(f, "drivedata: "); 516114574Sphk for (i = NDDATA - 1; i >= 0; i--) 517114574Sphk if (lp->d_drivedata[i]) 518114574Sphk break; 519114574Sphk if (i < 0) 520114574Sphk i = 0; 521114574Sphk for (j = 0; j <= i; j++) 522114574Sphk fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 523114574Sphk fprintf(f, "\n\n"); 524114574Sphk } 525114574Sphk fprintf(f, "%u partitions:\n", lp->d_npartitions); 5261558Srgrimes fprintf(f, 5275393Sgibbs "# size offset fstype [fsize bsize bps/cpg]\n"); 5281558Srgrimes pp = lp->d_partitions; 5291558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 5301558Srgrimes if (pp->p_size) { 53137234Sbde fprintf(f, " %c: %8lu %8lu ", 'a' + i, 53237234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 533107041Sjulian if (pp->p_fstype < FSMAXTYPES) 5341558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 5351558Srgrimes else 5361558Srgrimes fprintf(f, "%8d", pp->p_fstype); 5371558Srgrimes switch (pp->p_fstype) { 5381558Srgrimes 5391558Srgrimes case FS_UNUSED: /* XXX */ 54037234Sbde fprintf(f, " %5lu %5lu %5.5s ", 54137234Sbde (u_long)pp->p_fsize, 54237234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 5431558Srgrimes break; 5441558Srgrimes 5451558Srgrimes case FS_BSDFFS: 54637234Sbde fprintf(f, " %5lu %5lu %5u ", 54737234Sbde (u_long)pp->p_fsize, 54837234Sbde (u_long)(pp->p_fsize * pp->p_frag), 5491558Srgrimes pp->p_cpg); 5501558Srgrimes break; 5511558Srgrimes 5525393Sgibbs case FS_BSDLFS: 55337234Sbde fprintf(f, " %5lu %5lu %5d", 55437234Sbde (u_long)pp->p_fsize, 55537234Sbde (u_long)(pp->p_fsize * pp->p_frag), 5565393Sgibbs pp->p_cpg); 5575393Sgibbs break; 5585393Sgibbs 5591558Srgrimes default: 5601558Srgrimes fprintf(f, "%20.20s", ""); 5611558Srgrimes break; 5621558Srgrimes } 563114574Sphk if (i == RAW_PART) { 564114574Sphk fprintf(f, " # \"raw\" part, don't edit"); 565114574Sphk } 566114571Sphk fprintf(f, "\n"); 5671558Srgrimes } 5681558Srgrimes } 5691558Srgrimes fflush(f); 5701558Srgrimes} 5711558Srgrimes 572114571Sphkstatic int 573114571Sphkedit(void) 5741558Srgrimes{ 57592541Simp int c, fd; 5761558Srgrimes struct disklabel label; 57724180Simp FILE *fp; 5781558Srgrimes 57924180Simp if ((fd = mkstemp(tmpfil)) == -1 || 58024180Simp (fp = fdopen(fd, "w")) == NULL) { 58136632Scharnier warnx("can't create %s", tmpfil); 5821558Srgrimes return (1); 5831558Srgrimes } 584114571Sphk display(fp, NULL); 58524180Simp fclose(fp); 5861558Srgrimes for (;;) { 5871558Srgrimes if (!editit()) 5881558Srgrimes break; 58924180Simp fp = fopen(tmpfil, "r"); 59024180Simp if (fp == NULL) { 59136632Scharnier warnx("can't reopen %s for reading", tmpfil); 5921558Srgrimes break; 5931558Srgrimes } 5941558Srgrimes bzero((char *)&label, sizeof(label)); 595114571Sphk c = getasciilabel(fp, &label); 596114571Sphk fclose(fp); 597114571Sphk if (c) { 598114571Sphk lab = label; 599114571Sphk if (writelabel() == 0) { 6001558Srgrimes (void) unlink(tmpfil); 6011558Srgrimes return (0); 6021558Srgrimes } 6031558Srgrimes } 604114571Sphk printf("re-edit the label? [y]: "); 605114571Sphk fflush(stdout); 6061558Srgrimes c = getchar(); 6071558Srgrimes if (c != EOF && c != (int)'\n') 6081558Srgrimes while (getchar() != (int)'\n') 6091558Srgrimes ; 6101558Srgrimes if (c == (int)'n') 6111558Srgrimes break; 6121558Srgrimes } 6131558Srgrimes (void) unlink(tmpfil); 6141558Srgrimes return (1); 6151558Srgrimes} 6161558Srgrimes 617114571Sphkstatic int 61892541Simpeditit(void) 6191558Srgrimes{ 62092541Simp int pid, xpid; 62199365Smarkm int locstat, omask; 62299365Smarkm const char *ed; 6231558Srgrimes 6241558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 6251558Srgrimes while ((pid = fork()) < 0) { 6261558Srgrimes if (errno == EPROCLIM) { 62736632Scharnier warnx("you have too many processes"); 6281558Srgrimes return(0); 6291558Srgrimes } 6301558Srgrimes if (errno != EAGAIN) { 63136632Scharnier warn("fork"); 6321558Srgrimes return(0); 6331558Srgrimes } 6341558Srgrimes sleep(1); 6351558Srgrimes } 6361558Srgrimes if (pid == 0) { 6371558Srgrimes sigsetmask(omask); 6381558Srgrimes setgid(getgid()); 6391558Srgrimes setuid(getuid()); 6401558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 6411558Srgrimes ed = DEFEDITOR; 64279452Sbrian execlp(ed, ed, tmpfil, (char *)0); 64336632Scharnier err(1, "%s", ed); 6441558Srgrimes } 64599365Smarkm while ((xpid = wait(&locstat)) >= 0) 6461558Srgrimes if (xpid == pid) 6471558Srgrimes break; 6481558Srgrimes sigsetmask(omask); 64999365Smarkm return(!locstat); 6501558Srgrimes} 6511558Srgrimes 652114571Sphkstatic char * 65392541Simpskip(char *cp) 6541558Srgrimes{ 6551558Srgrimes 6561558Srgrimes while (*cp != '\0' && isspace(*cp)) 6571558Srgrimes cp++; 6581558Srgrimes if (*cp == '\0' || *cp == '#') 65992541Simp return (NULL); 6601558Srgrimes return (cp); 6611558Srgrimes} 6621558Srgrimes 663114571Sphkstatic char * 66492541Simpword(char *cp) 6651558Srgrimes{ 66692541Simp char c; 6671558Srgrimes 6681558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 6691558Srgrimes cp++; 6701558Srgrimes if ((c = *cp) != '\0') { 6711558Srgrimes *cp++ = '\0'; 6721558Srgrimes if (c != '#') 6731558Srgrimes return (skip(cp)); 6741558Srgrimes } 67592541Simp return (NULL); 6761558Srgrimes} 6771558Srgrimes 6781558Srgrimes/* 6791558Srgrimes * Read an ascii label in from fd f, 6801558Srgrimes * in the same format as that put out by display(), 6811558Srgrimes * and fill in lp. 6821558Srgrimes */ 683114571Sphkstatic int 68492541Simpgetasciilabel(FILE *f, struct disklabel *lp) 6851558Srgrimes{ 68694065Sphk char *cp; 68794065Sphk const char **cpp; 688107041Sjulian u_int part; 68994065Sphk char *tp, line[BUFSIZ]; 690107041Sjulian u_long v; 691107041Sjulian int lineno = 0, errors = 0; 69292541Simp int i; 6931558Srgrimes 694114862Sphk makelabel("auto", lp); 695109378Sdes bzero(&part_set, sizeof(part_set)); 696109378Sdes bzero(&part_size_type, sizeof(part_size_type)); 697109378Sdes bzero(&part_offset_type, sizeof(part_offset_type)); 6981558Srgrimes lp->d_bbsize = BBSIZE; /* XXX */ 69996475Sphk lp->d_sbsize = 0; /* XXX */ 7001558Srgrimes while (fgets(line, sizeof(line) - 1, f)) { 7011558Srgrimes lineno++; 70213544Sjoerg if ((cp = index(line,'\n')) != 0) 7031558Srgrimes *cp = '\0'; 7041558Srgrimes cp = skip(line); 7051558Srgrimes if (cp == NULL) 7061558Srgrimes continue; 7071558Srgrimes tp = index(cp, ':'); 7081558Srgrimes if (tp == NULL) { 7091558Srgrimes fprintf(stderr, "line %d: syntax error\n", lineno); 7101558Srgrimes errors++; 7111558Srgrimes continue; 7121558Srgrimes } 7131558Srgrimes *tp++ = '\0', tp = skip(tp); 714114571Sphk if (!strcmp(cp, "type")) { 7151558Srgrimes if (tp == NULL) 71699365Smarkm tp = unknown; 7171558Srgrimes cpp = dktypenames; 7181558Srgrimes for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 719114571Sphk if (*cpp && !strcmp(*cpp, tp)) { 7201558Srgrimes lp->d_type = cpp - dktypenames; 72197855Siedowse break; 7221558Srgrimes } 72397855Siedowse if (cpp < &dktypenames[DKMAXTYPES]) 72497855Siedowse continue; 725107041Sjulian v = strtoul(tp, NULL, 10); 726107041Sjulian if (v >= DKMAXTYPES) 727107041Sjulian fprintf(stderr, "line %d:%s %lu\n", lineno, 7281558Srgrimes "Warning, unknown disk type", v); 7291558Srgrimes lp->d_type = v; 7301558Srgrimes continue; 7311558Srgrimes } 732114571Sphk if (!strcmp(cp, "flags")) { 7331558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 7341558Srgrimes tp = word(cp); 735114571Sphk if (!strcmp(cp, "removeable")) 7361558Srgrimes v |= D_REMOVABLE; 737114571Sphk else if (!strcmp(cp, "ecc")) 7381558Srgrimes v |= D_ECC; 739114571Sphk else if (!strcmp(cp, "badsect")) 7401558Srgrimes v |= D_BADSECT; 7411558Srgrimes else { 7421558Srgrimes fprintf(stderr, 7431558Srgrimes "line %d: %s: bad flag\n", 7441558Srgrimes lineno, cp); 7451558Srgrimes errors++; 7461558Srgrimes } 7471558Srgrimes } 7481558Srgrimes lp->d_flags = v; 7491558Srgrimes continue; 7501558Srgrimes } 751114571Sphk if (!strcmp(cp, "drivedata")) { 7521558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 753107041Sjulian lp->d_drivedata[i++] = strtoul(cp, NULL, 10); 7541558Srgrimes tp = word(cp); 7551558Srgrimes } 7561558Srgrimes continue; 7571558Srgrimes } 758107041Sjulian if (sscanf(cp, "%lu partitions", &v) == 1) { 759107041Sjulian if (v == 0 || v > MAXPARTITIONS) { 7601558Srgrimes fprintf(stderr, 7611558Srgrimes "line %d: bad # of partitions\n", lineno); 7621558Srgrimes lp->d_npartitions = MAXPARTITIONS; 7631558Srgrimes errors++; 7641558Srgrimes } else 7651558Srgrimes lp->d_npartitions = v; 7661558Srgrimes continue; 7671558Srgrimes } 7681558Srgrimes if (tp == NULL) 76999365Smarkm tp = blank; 770114571Sphk if (!strcmp(cp, "disk")) { 7711558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 7721558Srgrimes continue; 7731558Srgrimes } 774114571Sphk if (!strcmp(cp, "label")) { 7751558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 7761558Srgrimes continue; 7771558Srgrimes } 778114571Sphk if (!strcmp(cp, "bytes/sector")) { 779107041Sjulian v = strtoul(tp, NULL, 10); 780107041Sjulian if (v == 0 || (v % DEV_BSIZE) != 0) { 7811558Srgrimes fprintf(stderr, 7821558Srgrimes "line %d: %s: bad sector size\n", 7831558Srgrimes lineno, tp); 7841558Srgrimes errors++; 7851558Srgrimes } else 7861558Srgrimes lp->d_secsize = v; 7871558Srgrimes continue; 7881558Srgrimes } 789114571Sphk if (!strcmp(cp, "sectors/track")) { 790107041Sjulian v = strtoul(tp, NULL, 10); 791107041Sjulian#if (ULONG_MAX != 0xffffffffUL) 792107041Sjulian if (v == 0 || v > 0xffffffff) { 793107041Sjulian#else 794107041Sjulian if (v == 0) { 795107041Sjulian#endif 7961558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 7971558Srgrimes lineno, tp, cp); 7981558Srgrimes errors++; 7991558Srgrimes } else 8001558Srgrimes lp->d_nsectors = v; 8011558Srgrimes continue; 8021558Srgrimes } 803114571Sphk if (!strcmp(cp, "sectors/cylinder")) { 804107041Sjulian v = strtoul(tp, NULL, 10); 805107041Sjulian if (v == 0) { 8061558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8071558Srgrimes lineno, tp, cp); 8081558Srgrimes errors++; 8091558Srgrimes } else 8101558Srgrimes lp->d_secpercyl = v; 8111558Srgrimes continue; 8121558Srgrimes } 813114571Sphk if (!strcmp(cp, "tracks/cylinder")) { 814107041Sjulian v = strtoul(tp, NULL, 10); 815107041Sjulian if (v == 0) { 8161558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8171558Srgrimes lineno, tp, cp); 8181558Srgrimes errors++; 8191558Srgrimes } else 8201558Srgrimes lp->d_ntracks = v; 8211558Srgrimes continue; 8221558Srgrimes } 823114571Sphk if (!strcmp(cp, "cylinders")) { 824107041Sjulian v = strtoul(tp, NULL, 10); 825107041Sjulian if (v == 0) { 8261558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8271558Srgrimes lineno, tp, cp); 8281558Srgrimes errors++; 8291558Srgrimes } else 8301558Srgrimes lp->d_ncylinders = v; 8311558Srgrimes continue; 8321558Srgrimes } 833114571Sphk if (!strcmp(cp, "sectors/unit")) { 834107041Sjulian v = strtoul(tp, NULL, 10); 835107041Sjulian if (v == 0) { 8366643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 8376643Sbde lineno, tp, cp); 8386643Sbde errors++; 8396643Sbde } else 8406643Sbde lp->d_secperunit = v; 8416643Sbde continue; 8426643Sbde } 843114571Sphk if (!strcmp(cp, "rpm")) { 844107041Sjulian v = strtoul(tp, NULL, 10); 845107041Sjulian if (v == 0 || v > USHRT_MAX) { 8461558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8471558Srgrimes lineno, tp, cp); 8481558Srgrimes errors++; 8491558Srgrimes } else 8501558Srgrimes lp->d_rpm = v; 8511558Srgrimes continue; 8521558Srgrimes } 853114571Sphk if (!strcmp(cp, "interleave")) { 854107041Sjulian v = strtoul(tp, NULL, 10); 855107041Sjulian if (v == 0 || v > USHRT_MAX) { 8561558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8571558Srgrimes lineno, tp, cp); 8581558Srgrimes errors++; 8591558Srgrimes } else 8601558Srgrimes lp->d_interleave = v; 8611558Srgrimes continue; 8621558Srgrimes } 863114571Sphk if (!strcmp(cp, "trackskew")) { 864107041Sjulian v = strtoul(tp, NULL, 10); 865107041Sjulian if (v > USHRT_MAX) { 8661558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8671558Srgrimes lineno, tp, cp); 8681558Srgrimes errors++; 8691558Srgrimes } else 8701558Srgrimes lp->d_trackskew = v; 8711558Srgrimes continue; 8721558Srgrimes } 873114571Sphk if (!strcmp(cp, "cylinderskew")) { 874107041Sjulian v = strtoul(tp, NULL, 10); 875107041Sjulian if (v > USHRT_MAX) { 8761558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8771558Srgrimes lineno, tp, cp); 8781558Srgrimes errors++; 8791558Srgrimes } else 8801558Srgrimes lp->d_cylskew = v; 8811558Srgrimes continue; 8821558Srgrimes } 883114571Sphk if (!strcmp(cp, "headswitch")) { 884107041Sjulian v = strtoul(tp, NULL, 10); 885107041Sjulian lp->d_headswitch = v; 8861558Srgrimes continue; 8871558Srgrimes } 888114571Sphk if (!strcmp(cp, "track-to-track seek")) { 889107041Sjulian v = strtoul(tp, NULL, 10); 890107041Sjulian lp->d_trkseek = v; 8911558Srgrimes continue; 8921558Srgrimes } 89373034Sjwd /* the ':' was removed above */ 89497534Siedowse if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') { 89597534Siedowse fprintf(stderr, 89697534Siedowse "line %d: %s: Unknown disklabel field\n", lineno, 89797534Siedowse cp); 89897534Siedowse errors++; 89997534Siedowse continue; 90097534Siedowse } 90197534Siedowse 90297534Siedowse /* Process a partition specification line. */ 90397534Siedowse part = *cp - 'a'; 90497534Siedowse if (part >= lp->d_npartitions) { 90597534Siedowse fprintf(stderr, 90697534Siedowse "line %d: partition name out of range a-%c: %s\n", 90797534Siedowse lineno, 'a' + lp->d_npartitions - 1, cp); 90897534Siedowse errors++; 90997534Siedowse continue; 91097534Siedowse } 91197534Siedowse part_set[part] = 1; 91297534Siedowse 91397534Siedowse if (getasciipartspec(tp, lp, part, lineno) != 0) { 91497534Siedowse errors++; 91597534Siedowse break; 91697534Siedowse } 91797534Siedowse } 91897534Siedowse errors += checklabel(lp); 91997534Siedowse return (errors == 0); 92097534Siedowse} 92197534Siedowse 92297534Siedowse#define NXTNUM(n) do { \ 9233111Spst if (tp == NULL) { \ 9243111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 92597534Siedowse return (1); \ 9263111Spst } else { \ 9273111Spst cp = tp, tp = word(cp); \ 928107041Sjulian (n) = strtoul(cp, NULL, 10); \ 9293111Spst } \ 93097534Siedowse} while (0) 93197534Siedowse 93273034Sjwd/* retain 1 character following number */ 93397534Siedowse#define NXTWORD(w,n) do { \ 93473034Sjwd if (tp == NULL) { \ 93573034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 93697534Siedowse return (1); \ 93773034Sjwd } else { \ 93873034Sjwd char *tmp; \ 93973034Sjwd cp = tp, tp = word(cp); \ 940107041Sjulian (n) = strtoul(cp, &tmp, 10); \ 94173034Sjwd if (tmp) (w) = *tmp; \ 94273034Sjwd } \ 94397534Siedowse} while (0) 9441558Srgrimes 94597534Siedowse/* 94697534Siedowse * Read a partition line into partition `part' in the specified disklabel. 94797534Siedowse * Return 0 on success, 1 on failure. 94897534Siedowse */ 949114571Sphkstatic int 95097534Siedowsegetasciipartspec(char *tp, struct disklabel *lp, int part, int lineno) 95197534Siedowse{ 95297534Siedowse struct partition *pp; 95397534Siedowse char *cp; 95497534Siedowse const char **cpp; 955107041Sjulian u_long v; 9561558Srgrimes 95797534Siedowse pp = &lp->d_partitions[part]; 95897534Siedowse cp = NULL; 9591558Srgrimes 96097534Siedowse v = 0; 96197534Siedowse NXTWORD(part_size_type[part],v); 962107041Sjulian if (v == 0 && part_size_type[part] != '*') { 963107041Sjulian fprintf(stderr, 964107041Sjulian "line %d: %s: bad partition size\n", lineno, cp); 96597534Siedowse return (1); 96697534Siedowse } 96797534Siedowse pp->p_size = v; 96897534Siedowse 96997534Siedowse v = 0; 97097534Siedowse NXTWORD(part_offset_type[part],v); 971107041Sjulian if (v == 0 && part_offset_type[part] != '*' && 972107041Sjulian part_offset_type[part] != '\0') { 973107041Sjulian fprintf(stderr, 974107041Sjulian "line %d: %s: bad partition offset\n", lineno, cp); 97597534Siedowse return (1); 97697534Siedowse } 97797534Siedowse pp->p_offset = v; 978112945Syar if (tp == NULL) { 979112945Syar fprintf(stderr, "line %d: missing file system type\n", lineno); 980112945Syar return (1); 981112945Syar } 98297534Siedowse cp = tp, tp = word(cp); 98397534Siedowse for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) 984114571Sphk if (*cpp && !strcmp(*cpp, cp)) 98597534Siedowse break; 98697534Siedowse if (*cpp != NULL) { 98797534Siedowse pp->p_fstype = cpp - fstypenames; 98897534Siedowse } else { 98997534Siedowse if (isdigit(*cp)) 990107041Sjulian v = strtoul(cp, NULL, 10); 99197534Siedowse else 99297534Siedowse v = FSMAXTYPES; 993107041Sjulian if (v >= FSMAXTYPES) { 99497534Siedowse fprintf(stderr, 995102231Strhodes "line %d: Warning, unknown file system type %s\n", 99697534Siedowse lineno, cp); 99797534Siedowse v = FS_UNUSED; 99897534Siedowse } 99997534Siedowse pp->p_fstype = v; 100097534Siedowse } 100197534Siedowse 100297534Siedowse switch (pp->p_fstype) { 100397534Siedowse case FS_UNUSED: 1004120821Siedowse case FS_BSDFFS: 1005120821Siedowse case FS_BSDLFS: 1006120821Siedowse /* accept defaults for fsize/frag/cpg */ 100797534Siedowse if (tp) { 100897534Siedowse NXTNUM(pp->p_fsize); 100997534Siedowse if (pp->p_fsize == 0) 101097534Siedowse break; 101197534Siedowse NXTNUM(v); 101297534Siedowse pp->p_frag = v / pp->p_fsize; 1013120821Siedowse if (tp != NULL) 1014120821Siedowse NXTNUM(pp->p_cpg); 101597534Siedowse } 101697534Siedowse /* else default to 0's */ 101797534Siedowse break; 101897534Siedowse default: 101997534Siedowse break; 10201558Srgrimes } 102197534Siedowse return (0); 10221558Srgrimes} 10231558Srgrimes 10241558Srgrimes/* 10251558Srgrimes * Check disklabel for errors and fill in 10261558Srgrimes * derived fields according to supplied values. 10271558Srgrimes */ 1028114571Sphkstatic int 102992541Simpchecklabel(struct disklabel *lp) 10301558Srgrimes{ 103192541Simp struct partition *pp; 10321558Srgrimes int i, errors = 0; 10331558Srgrimes char part; 1034107041Sjulian u_long total_size, total_percent, current_offset; 103573034Sjwd int seen_default_offset; 103673034Sjwd int hog_part; 103773034Sjwd int j; 103873034Sjwd struct partition *pp2; 10391558Srgrimes 1040114571Sphk if (lp == NULL) 1041114571Sphk lp = &lab; 1042114571Sphk 1043114574Sphk if (allfields) { 1044114574Sphk 1045114574Sphk if (lp->d_secsize == 0) { 1046114574Sphk fprintf(stderr, "sector size 0\n"); 1047114574Sphk return (1); 1048114574Sphk } 1049114574Sphk if (lp->d_nsectors == 0) { 1050114574Sphk fprintf(stderr, "sectors/track 0\n"); 1051114574Sphk return (1); 1052114574Sphk } 1053114574Sphk if (lp->d_ntracks == 0) { 1054114574Sphk fprintf(stderr, "tracks/cylinder 0\n"); 1055114574Sphk return (1); 1056114574Sphk } 1057114574Sphk if (lp->d_ncylinders == 0) { 1058114574Sphk fprintf(stderr, "cylinders/unit 0\n"); 1059114574Sphk errors++; 1060114574Sphk } 1061114574Sphk if (lp->d_rpm == 0) 1062114574Sphk warnx("revolutions/minute 0"); 1063114574Sphk if (lp->d_secpercyl == 0) 1064114574Sphk lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1065114574Sphk if (lp->d_secperunit == 0) 1066114574Sphk lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1067114574Sphk if (lp->d_bbsize == 0) { 1068114574Sphk fprintf(stderr, "boot block size 0\n"); 1069114574Sphk errors++; 1070114574Sphk } else if (lp->d_bbsize % lp->d_secsize) 1071114574Sphk warnx("boot block size %% sector-size != 0"); 1072114574Sphk if (lp->d_npartitions > MAXPARTITIONS) 1073114574Sphk warnx("number of partitions (%lu) > MAXPARTITIONS (%d)", 1074114574Sphk (u_long)lp->d_npartitions, MAXPARTITIONS); 1075114574Sphk } else { 1076114574Sphk struct disklabel *vl; 1077114574Sphk 1078114574Sphk vl = getvirginlabel(); 1079114574Sphk lp->d_secsize = vl->d_secsize; 1080114574Sphk lp->d_nsectors = vl->d_nsectors; 1081114574Sphk lp->d_ntracks = vl->d_ntracks; 1082114574Sphk lp->d_ncylinders = vl->d_ncylinders; 1083114574Sphk lp->d_rpm = vl->d_rpm; 1084114574Sphk lp->d_interleave = vl->d_interleave; 1085114574Sphk lp->d_secpercyl = vl->d_secpercyl; 1086114574Sphk lp->d_secperunit = vl->d_secperunit; 1087114574Sphk lp->d_bbsize = vl->d_bbsize; 1088114574Sphk lp->d_npartitions = vl->d_npartitions; 10891558Srgrimes } 109073034Sjwd 1091114574Sphk 109273034Sjwd /* first allocate space to the partitions, then offsets */ 109373034Sjwd total_size = 0; /* in sectors */ 109473034Sjwd total_percent = 0; /* in percent */ 109573034Sjwd hog_part = -1; 109673034Sjwd /* find all fixed partitions */ 10971558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 109873034Sjwd pp = &lp->d_partitions[i]; 109973034Sjwd if (part_set[i]) { 110073034Sjwd if (part_size_type[i] == '*') { 110194065Sphk if (i == RAW_PART) { 110273034Sjwd pp->p_size = lp->d_secperunit; 110373034Sjwd } else { 110473034Sjwd if (hog_part != -1) 1105114574Sphk warnx("Too many '*' partitions (%c and %c)", 110673034Sjwd hog_part + 'a',i + 'a'); 110773034Sjwd else 110873034Sjwd hog_part = i; 110973034Sjwd } 111073034Sjwd } else { 111173573Simp off_t size; 111273034Sjwd 111373034Sjwd size = pp->p_size; 111473034Sjwd switch (part_size_type[i]) { 111573034Sjwd case '%': 111673034Sjwd total_percent += size; 111773034Sjwd break; 111873034Sjwd case 'k': 111973034Sjwd case 'K': 112073573Simp size *= 1024ULL; 112173034Sjwd break; 112273034Sjwd case 'm': 112373034Sjwd case 'M': 112473573Simp size *= 1024ULL * 1024ULL; 112573034Sjwd break; 112673034Sjwd case 'g': 112773034Sjwd case 'G': 112873573Simp size *= 1024ULL * 1024ULL * 1024ULL; 112973034Sjwd break; 113073034Sjwd case '\0': 113173034Sjwd break; 113273034Sjwd default: 1133114574Sphk warnx("unknown size specifier '%c' (K/M/G are valid)",part_size_type[i]); 113473034Sjwd break; 113573034Sjwd } 113673034Sjwd /* don't count %'s yet */ 113773034Sjwd if (part_size_type[i] != '%') { 113873034Sjwd /* 113973034Sjwd * for all not in sectors, convert to 114073034Sjwd * sectors 114173034Sjwd */ 114273034Sjwd if (part_size_type[i] != '\0') { 114373034Sjwd if (size % lp->d_secsize != 0) 1144114574Sphk warnx("partition %c not an integer number of sectors", 114573034Sjwd i + 'a'); 114673034Sjwd size /= lp->d_secsize; 114773034Sjwd pp->p_size = size; 114873034Sjwd } 114973034Sjwd /* else already in sectors */ 115094065Sphk if (i != RAW_PART) 115173034Sjwd total_size += size; 115273034Sjwd } 115373034Sjwd } 115473034Sjwd } 115573034Sjwd } 115673034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 115773034Sjwd if (total_percent != 0) { 115873034Sjwd long free_space = lp->d_secperunit - total_size; 115973034Sjwd if (total_percent > 100) { 116094065Sphk fprintf(stderr,"total percentage %lu is greater than 100\n", 116173034Sjwd total_percent); 116273034Sjwd errors++; 116373034Sjwd } 116473034Sjwd 116573034Sjwd if (free_space > 0) { 116673034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 116773034Sjwd pp = &lp->d_partitions[i]; 116873034Sjwd if (part_set[i] && part_size_type[i] == '%') { 116973034Sjwd /* careful of overflows! and integer roundoff */ 117073034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 117173034Sjwd total_size += pp->p_size; 117273034Sjwd 117373034Sjwd /* FIX we can lose a sector or so due to roundoff per 117473034Sjwd partition. A more complex algorithm could avoid that */ 117573034Sjwd } 117673034Sjwd } 117773034Sjwd } else { 117873034Sjwd fprintf(stderr, 117994065Sphk "%ld sectors available to give to '*' and '%%' partitions\n", 118073034Sjwd free_space); 118173034Sjwd errors++; 118273034Sjwd /* fix? set all % partitions to size 0? */ 118373034Sjwd } 118473034Sjwd } 118573034Sjwd /* give anything remaining to the hog partition */ 118673034Sjwd if (hog_part != -1) { 118773034Sjwd lp->d_partitions[hog_part].p_size = lp->d_secperunit - total_size; 118873034Sjwd total_size = lp->d_secperunit; 118973034Sjwd } 119073034Sjwd 119173034Sjwd /* Now set the offsets for each partition */ 119273034Sjwd current_offset = 0; /* in sectors */ 119373034Sjwd seen_default_offset = 0; 119473034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 11951558Srgrimes part = 'a' + i; 11961558Srgrimes pp = &lp->d_partitions[i]; 119773034Sjwd if (part_set[i]) { 119873034Sjwd if (part_offset_type[i] == '*') { 119994065Sphk if (i == RAW_PART) { 120073034Sjwd pp->p_offset = 0; 120173034Sjwd } else { 120273034Sjwd pp->p_offset = current_offset; 120373034Sjwd seen_default_offset = 1; 120473034Sjwd } 120573034Sjwd } else { 120673034Sjwd /* allow them to be out of order for old-style tables */ 120773034Sjwd if (pp->p_offset < current_offset && 1208107534Sgrog seen_default_offset && i != RAW_PART && 1209107534Sgrog pp->p_fstype != FS_VINUM) { 121073034Sjwd fprintf(stderr, 121194065Sphk"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 121294065Sphk (long)pp->p_offset,i+'a',current_offset); 121373034Sjwd fprintf(stderr, 121473034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 121573034Sjwd errors++; 121673034Sjwd } else if (pp->p_offset != current_offset && 121794065Sphk i != RAW_PART && seen_default_offset) { 121873034Sjwd /* 121973034Sjwd * this may give unneeded warnings if 122073034Sjwd * partitions are out-of-order 122173034Sjwd */ 1222114574Sphk warnx( 122373034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 122494065Sphk (long)pp->p_offset, i + 'a', current_offset); 122573034Sjwd } 122673034Sjwd } 122794065Sphk if (i != RAW_PART) 122873034Sjwd current_offset = pp->p_offset + pp->p_size; 122973034Sjwd } 123073034Sjwd } 123173034Sjwd 123273034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 123373034Sjwd part = 'a' + i; 123473034Sjwd pp = &lp->d_partitions[i]; 12351558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 1236114574Sphk warnx("partition %c: size 0, but offset %lu", 123737234Sbde part, (u_long)pp->p_offset); 12381558Srgrimes#ifdef notdef 12391558Srgrimes if (pp->p_size % lp->d_secpercyl) 1240114574Sphk warnx("partition %c: size %% cylinder-size != 0", 12411558Srgrimes part); 12421558Srgrimes if (pp->p_offset % lp->d_secpercyl) 1243114574Sphk warnx("partition %c: offset %% cylinder-size != 0", 12441558Srgrimes part); 12451558Srgrimes#endif 12461558Srgrimes if (pp->p_offset > lp->d_secperunit) { 12471558Srgrimes fprintf(stderr, 12481558Srgrimes "partition %c: offset past end of unit\n", part); 12491558Srgrimes errors++; 12501558Srgrimes } 12511558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 12521558Srgrimes fprintf(stderr, 125313544Sjoerg "partition %c: partition extends past end of unit\n", 12541558Srgrimes part); 12551558Srgrimes errors++; 12561558Srgrimes } 1257114574Sphk if (i == RAW_PART) { 125873034Sjwd if (pp->p_fstype != FS_UNUSED) 1259114574Sphk warnx("partition %c is not marked as unused!",part); 126073034Sjwd if (pp->p_offset != 0) 1261114574Sphk warnx("partition %c doesn't start at 0!",part); 126273034Sjwd if (pp->p_size != lp->d_secperunit) 1263114574Sphk warnx("partition %c doesn't cover the whole unit!",part); 126473034Sjwd 126573034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 126673034Sjwd (pp->p_size != lp->d_secperunit)) { 1267114574Sphk warnx("An incorrect partition %c may cause problems for " 126873034Sjwd "standard system utilities",part); 126973034Sjwd } 127073034Sjwd } 127173034Sjwd 127273034Sjwd /* check for overlaps */ 127373034Sjwd /* this will check for all possible overlaps once and only once */ 127473034Sjwd for (j = 0; j < i; j++) { 1275107534Sgrog pp2 = &lp->d_partitions[j]; 1276107534Sgrog if (j != RAW_PART && i != RAW_PART && 1277107534Sgrog pp->p_fstype != FS_VINUM && 1278107534Sgrog pp2->p_fstype != FS_VINUM && 127973034Sjwd part_set[i] && part_set[j]) { 128073034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 128173034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 128273034Sjwd pp2->p_offset >= pp->p_offset)) { 128373034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 128473034Sjwd j + 'a', i + 'a'); 128573034Sjwd errors++; 128673034Sjwd } 128773034Sjwd } 128873034Sjwd } 12891558Srgrimes } 12901558Srgrimes for (; i < MAXPARTITIONS; i++) { 12911558Srgrimes part = 'a' + i; 12921558Srgrimes pp = &lp->d_partitions[i]; 12931558Srgrimes if (pp->p_size || pp->p_offset) 1294114574Sphk warnx("unused partition %c: size %d offset %lu", 129537234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 12961558Srgrimes } 12971558Srgrimes return (errors); 12981558Srgrimes} 12991558Srgrimes 13001558Srgrimes/* 130113550Sjoerg * When operating on a "virgin" disk, try getting an initial label 130213550Sjoerg * from the associated device driver. This might work for all device 130313550Sjoerg * drivers that are able to fetch some initial device parameters 130413550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 130513550Sjoerg * most IDE drives, or vn devices. 130613550Sjoerg * 130713550Sjoerg * The device name must be given in its "canonical" form. 130813550Sjoerg */ 1309114571Sphkstatic struct disklabel * 131013550Sjoerggetvirginlabel(void) 131113550Sjoerg{ 131299365Smarkm static struct disklabel loclab; 1313103669Sphk struct partition *dp; 131413550Sjoerg int f; 1315114574Sphk u_int u; 131613550Sjoerg 1317114571Sphk if ((f = open(specname, O_RDONLY)) == -1) { 1318114571Sphk warn("cannot open %s", specname); 131916431Sbde return (NULL); 132013550Sjoerg } 132168044Sjkh 1322103669Sphk /* New world order */ 1323103669Sphk if ((ioctl(f, DIOCGMEDIASIZE, &mediasize) != 0) || 1324103669Sphk (ioctl(f, DIOCGSECTORSIZE, &secsize) != 0)) { 1325103669Sphk close (f); 1326103669Sphk return (NULL); 1327103669Sphk } 1328103669Sphk memset(&loclab, 0, sizeof loclab); 1329103669Sphk loclab.d_magic = DISKMAGIC; 1330103669Sphk loclab.d_magic2 = DISKMAGIC; 1331103669Sphk loclab.d_secsize = secsize; 1332103669Sphk loclab.d_secperunit = mediasize / secsize; 1333103669Sphk 133468044Sjkh /* 1335103669Sphk * Nobody in these enligthened days uses the CHS geometry for 1336103669Sphk * anything, but nontheless try to get it right. If we fail 1337103669Sphk * to get any good ideas from the device, construct something 1338103669Sphk * which is IBM-PC friendly. 133968044Sjkh */ 1340103669Sphk if (ioctl(f, DIOCGFWSECTORS, &u) == 0) 1341103669Sphk loclab.d_nsectors = u; 1342103669Sphk else 1343103669Sphk loclab.d_nsectors = 63; 1344103669Sphk if (ioctl(f, DIOCGFWHEADS, &u) == 0) 1345103669Sphk loclab.d_ntracks = u; 1346103669Sphk else if (loclab.d_secperunit <= 63*1*1024) 1347103669Sphk loclab.d_ntracks = 1; 1348103669Sphk else if (loclab.d_secperunit <= 63*16*1024) 1349103669Sphk loclab.d_ntracks = 16; 1350103669Sphk else 1351103669Sphk loclab.d_ntracks = 255; 1352103669Sphk loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors; 1353103669Sphk loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl; 1354103669Sphk loclab.d_npartitions = MAXPARTITIONS; 1355103669Sphk 1356103669Sphk /* Various (unneeded) compat stuff */ 1357103669Sphk loclab.d_rpm = 3600; 1358103669Sphk loclab.d_bbsize = BBSIZE; 1359114574Sphk loclab.d_interleave = 1; 1360103669Sphk strncpy(loclab.d_typename, "amnesiac", 1361103669Sphk sizeof(loclab.d_typename)); 1362103669Sphk 1363103669Sphk dp = &loclab.d_partitions[RAW_PART]; 1364103669Sphk dp->p_size = loclab.d_secperunit; 1365103669Sphk loclab.d_checksum = dkcksum(&loclab); 1366103669Sphk close (f); 136799365Smarkm return (&loclab); 136813550Sjoerg} 136913550Sjoerg 1370114571Sphkstatic void 137192541Simpusage(void) 13721558Srgrimes{ 1373112307Sru 1374112307Sru fprintf(stderr, 1375112307Sru "%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", 1376114569Sphk "usage: bsdlabel disk", 1377112307Sru "\t\t(to read label)", 1378114571Sphk " bsdlabel -w [-n] [-m machine] disk [type]", 1379112307Sru "\t\t(to write label with existing boot program)", 1380114569Sphk " bsdlabel -e [-n] [-m machine] disk", 1381112307Sru "\t\t(to edit label)", 1382114569Sphk " bsdlabel -R [-n] [-m machine] disk protofile", 1383112307Sru "\t\t(to restore label with existing boot program)", 1384113680Sphk " bsdlabel -B [-b boot] [-m machine] disk", 1385112307Sru "\t\t(to install boot program with existing on-disk label)", 1386114571Sphk " bsdlabel -w -B [-n] [-b boot] [-m machine] disk [type]", 1387112307Sru "\t\t(to write label and install boot program)", 1388113680Sphk " bsdlabel -R -B [-n] [-b boot] [-m machine] disk protofile", 1389109878Sphk "\t\t(to restore label and install boot program)" 1390109878Sphk ); 13911558Srgrimes exit(1); 13921558Srgrimes} 1393