bsdlabel.c revision 216095
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 216095 2010-12-01 08:07:32Z kevlo $"); 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 66174501Smarcel#define MAXPARTITIONS 26 671558Srgrimes#include <sys/disklabel.h> 68112307Sru 691558Srgrimes#include <unistd.h> 701558Srgrimes#include <string.h> 711558Srgrimes#include <stdio.h> 72114569Sphk#include <libgeom.h> 7313544Sjoerg#include <stdlib.h> 7413544Sjoerg#include <signal.h> 7513544Sjoerg#include <stdarg.h> 761558Srgrimes#include <ctype.h> 7726542Scharnier#include <err.h> 7859216Simp#include <errno.h> 7999365Smarkm 801558Srgrimes#include "pathnames.h" 811558Srgrimes 82114571Sphkstatic void makelabel(const char *, struct disklabel *); 83211873Sjhstatic int geom_bsd_available(void); 84114571Sphkstatic int writelabel(void); 85133347Sdesstatic int readlabel(int flag); 86114571Sphkstatic void display(FILE *, const struct disklabel *); 87133347Sdesstatic int edit(void); 88114571Sphkstatic int editit(void); 89121222Sphkstatic void fixlabel(struct disklabel *); 90114571Sphkstatic char *skip(char *); 91114571Sphkstatic char *word(char *); 92114571Sphkstatic int getasciilabel(FILE *, struct disklabel *); 93114571Sphkstatic int getasciipartspec(char *, struct disklabel *, int, int); 94114571Sphkstatic int checklabel(struct disklabel *); 95114571Sphkstatic void usage(void); 96114571Sphkstatic struct disklabel *getvirginlabel(void); 9713544Sjoerg 981558Srgrimes#define DEFEDITOR _PATH_VI 99174501Smarcel#define DEFPARTITIONS 8 1001558Srgrimes 101114571Sphkstatic char *specname; 102183143Slulfstatic char *pname; 103114571Sphkstatic char tmpfil[] = PATH_TMPFILE; 1041558Srgrimes 105114571Sphkstatic struct disklabel lab; 106114571Sphkstatic u_char bootarea[BBSIZE]; 107114574Sphkstatic off_t mediasize; 108114574Sphkstatic u_int secsize; 109114571Sphkstatic char blank[] = ""; 110114571Sphkstatic char unknown[] = "unknown"; 1111558Srgrimes 11273034Sjwd#define MAX_PART ('z') 11373034Sjwd#define MAX_NUM_PARTS (1 + MAX_PART - 'a') 114114571Sphkstatic char part_size_type[MAX_NUM_PARTS]; 115114571Sphkstatic char part_offset_type[MAX_NUM_PARTS]; 116114571Sphkstatic int part_set[MAX_NUM_PARTS]; 11773034Sjwd 118114571Sphkstatic int installboot; /* non-zero if we should install a boot program */ 119114574Sphkstatic int allfields; /* present all fields in edit */ 120114571Sphkstatic char const *xxboot; /* primary boot */ 1211558Srgrimes 122196383Smarcelstatic uint32_t lba_offset; 123115995Sphk#ifndef LABELSECTOR 124115995Sphk#define LABELSECTOR -1 125115995Sphk#endif 126115995Sphk#ifndef LABELOFFSET 127115995Sphk#define LABELOFFSET -1 128115995Sphk#endif 129115696Sphkstatic int labelsoffset = LABELSECTOR; 130115696Sphkstatic int labeloffset = LABELOFFSET; 131114551Sphkstatic int bbsize = BBSIZE; 132114551Sphkstatic int alphacksum = 133114551Sphk#if defined(__alpha__) 134114551Sphk 1; 135114551Sphk#else 136114551Sphk 0; 137114551Sphk#endif 138114550Sphk 1391558Srgrimesenum { 140109872Sphk UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT 1411558Srgrimes} op = UNSPEC; 1421558Srgrimes 143112307Sru 144114571Sphkstatic int disable_write; /* set to disable writing to disk label */ 145127650Sluigistatic int is_file; /* work on a file (abs. pathname), "-f" opt. */ 1461558Srgrimes 14713544Sjoergint 14892541Simpmain(int argc, char *argv[]) 1491558Srgrimes{ 1501558Srgrimes FILE *t; 151183143Slulf int ch, error, fd; 152183143Slulf const char *name; 153183143Slulf 154183143Slulf error = 0; 155183143Slulf name = NULL; 1561558Srgrimes 157163539Smaxim while ((ch = getopt(argc, argv, "ABb:efm:nRrw")) != -1) 1581558Srgrimes switch (ch) { 159114574Sphk case 'A': 160114574Sphk allfields = 1; 161114574Sphk break; 1621558Srgrimes case 'B': 1631558Srgrimes ++installboot; 1641558Srgrimes break; 1651558Srgrimes case 'b': 1661558Srgrimes xxboot = optarg; 1671558Srgrimes break; 168127650Sluigi case 'f': 169127650Sluigi is_file=1; 170127650Sluigi break; 171112307Sru case 'm': 172115948Sphk if (!strcmp(optarg, "i386") || 173115948Sphk !strcmp(optarg, "amd64") || 174115948Sphk !strcmp(optarg, "ia64") || 175115948Sphk !strcmp(optarg, "pc98")) { 176115696Sphk labelsoffset = 1; 177115696Sphk labeloffset = 0; 178114550Sphk bbsize = 8192; 179114551Sphk alphacksum = 0; 180114550Sphk } else if (!strcmp(optarg, "alpha")) { 181115696Sphk labelsoffset = 0; 182114550Sphk labeloffset = 64; 183114550Sphk bbsize = 8192; 184114550Sphk alphacksum = 1; 185114571Sphk } else { 186114571Sphk errx(1, "Unsupported architecture"); 187114550Sphk } 188112307Sru break; 18973034Sjwd case 'n': 19073034Sjwd disable_write = 1; 19173034Sjwd break; 1921558Srgrimes case 'R': 1931558Srgrimes if (op != UNSPEC) 1941558Srgrimes usage(); 1951558Srgrimes op = RESTORE; 1961558Srgrimes break; 1971558Srgrimes case 'e': 1981558Srgrimes if (op != UNSPEC) 1991558Srgrimes usage(); 2001558Srgrimes op = EDIT; 2011558Srgrimes break; 2021558Srgrimes case 'r': 203114571Sphk /* 204114571Sphk * We accept and ignode -r for compatibility with 205114571Sphk * historically disklabel usage. 206114571Sphk */ 2071558Srgrimes break; 2081558Srgrimes case 'w': 2091558Srgrimes if (op != UNSPEC) 2101558Srgrimes usage(); 2111558Srgrimes op = WRITE; 2121558Srgrimes break; 2131558Srgrimes case '?': 2141558Srgrimes default: 2151558Srgrimes usage(); 2161558Srgrimes } 2171558Srgrimes argc -= optind; 2181558Srgrimes argv += optind; 219114571Sphk 2201558Srgrimes if (argc < 1) 2211558Srgrimes usage(); 222115995Sphk if (labelsoffset < 0 || labeloffset < 0) 223115995Sphk errx(1, "a -m <architecture> option must be specified"); 2241558Srgrimes 225114569Sphk /* Figure out the names of the thing we're working on */ 226127650Sluigi if (is_file) { 227139856Srse specname = argv[0]; 228114569Sphk } else { 229183143Slulf specname = g_device_path(argv[0]); 230183143Slulf if (specname == NULL) { 231183143Slulf warn("unable to get correct path for %s", argv[0]); 232183143Slulf return(1); 233183143Slulf } 234183143Slulf fd = open(specname, O_RDONLY); 235183143Slulf if (fd < 0) { 236183143Slulf warn("error opening %s", specname); 237183143Slulf return(1); 238183143Slulf } 239183143Slulf pname = g_providername(fd); 240183143Slulf if (pname == NULL) { 241183487Slulf warn("error getting providername for %s", specname); 242183496Slulf close(fd); 243183143Slulf return(1); 244183143Slulf } 245183496Slulf close(fd); 2461558Srgrimes } 2471558Srgrimes 248114571Sphk if (installboot && op == UNSPEC) 249114571Sphk op = WRITEBOOT; 250114571Sphk else if (op == UNSPEC) 251114571Sphk op = READ; 252114571Sphk 2531558Srgrimes switch(op) { 2541558Srgrimes 25548957Sbillf case UNSPEC: 25648957Sbillf break; 25748957Sbillf 2581558Srgrimes case EDIT: 2591558Srgrimes if (argc != 1) 2601558Srgrimes usage(); 261114571Sphk readlabel(1); 262121222Sphk fixlabel(&lab); 263114571Sphk error = edit(); 2641558Srgrimes break; 2651558Srgrimes 2661558Srgrimes case READ: 2671558Srgrimes if (argc != 1) 2681558Srgrimes usage(); 269114571Sphk readlabel(1); 270114571Sphk display(stdout, NULL); 271114571Sphk error = checklabel(NULL); 2721558Srgrimes break; 2731558Srgrimes 2741558Srgrimes case RESTORE: 2751558Srgrimes if (argc != 2) 2761558Srgrimes usage(); 2771558Srgrimes if (!(t = fopen(argv[1], "r"))) 278114569Sphk err(4, "fopen %s", argv[1]); 279114571Sphk readlabel(0); 28037865Sbde if (!getasciilabel(t, &lab)) 28137865Sbde exit(1); 282114571Sphk error = writelabel(); 2831558Srgrimes break; 2841558Srgrimes 2851558Srgrimes case WRITE: 286114571Sphk if (argc == 2) 287114571Sphk name = argv[1]; 288114571Sphk else if (argc == 1) 289114571Sphk name = "auto"; 290114571Sphk else 2911558Srgrimes usage(); 292114571Sphk readlabel(0); 293114571Sphk makelabel(name, &lab); 294121222Sphk fixlabel(&lab); 295114571Sphk if (checklabel(NULL) == 0) 296114571Sphk error = writelabel(); 2971558Srgrimes break; 2981558Srgrimes 2991558Srgrimes case WRITEBOOT: 3001558Srgrimes 301114571Sphk readlabel(1); 302121222Sphk fixlabel(&lab); 3031558Srgrimes if (argc == 2) 304114571Sphk makelabel(argv[1], &lab); 305114571Sphk if (checklabel(NULL) == 0) 306114571Sphk error = writelabel(); 3071558Srgrimes break; 3081558Srgrimes } 3091558Srgrimes exit(error); 3101558Srgrimes} 3111558Srgrimes 312121222Sphkstatic void 313121222Sphkfixlabel(struct disklabel *lp) 314121222Sphk{ 315121222Sphk struct partition *dp; 316121222Sphk int i; 317121222Sphk 318174501Smarcel for (i = 0; i < lp->d_npartitions; i++) { 319121222Sphk if (i == RAW_PART) 320121222Sphk continue; 321121222Sphk if (lp->d_partitions[i].p_size) 322121222Sphk return; 323121222Sphk } 324121222Sphk 325121222Sphk dp = &lp->d_partitions[0]; 326121222Sphk dp->p_offset = BBSIZE / secsize; 327121222Sphk dp->p_size = lp->d_secperunit - dp->p_offset; 328121222Sphk} 329121222Sphk 3301558Srgrimes/* 331111286Sru * Construct a prototype disklabel from /etc/disktab. 3321558Srgrimes */ 333114571Sphkstatic void 334114571Sphkmakelabel(const char *type, struct disklabel *lp) 3351558Srgrimes{ 33692541Simp struct disklabel *dp; 33713550Sjoerg 33813550Sjoerg if (strcmp(type, "auto") == 0) 33913550Sjoerg dp = getvirginlabel(); 34013550Sjoerg else 34113544Sjoerg dp = getdiskbyname(type); 34236632Scharnier if (dp == NULL) 34336632Scharnier errx(1, "%s: unknown disk type", type); 3441558Srgrimes *lp = *dp; 3451558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 3461558Srgrimes} 3471558Srgrimes 348114571Sphkstatic void 349114571Sphkreadboot(void) 3501558Srgrimes{ 351209614Sjh int fd; 352114571Sphk struct stat st; 353127044Sjhb uint64_t *p; 354114571Sphk 355114571Sphk if (xxboot == NULL) 356114571Sphk xxboot = "/boot/boot"; 357114571Sphk fd = open(xxboot, O_RDONLY); 358114571Sphk if (fd < 0) 359114571Sphk err(1, "cannot open %s", xxboot); 360114571Sphk fstat(fd, &st); 361114860Sphk if (alphacksum && st.st_size <= BBSIZE - 512) { 362209614Sjh if (read(fd, bootarea + 512, st.st_size) != st.st_size) 363114571Sphk err(1, "read error %s", xxboot); 364127044Sjhb 365127044Sjhb /* 366127044Sjhb * Set the location and length so SRM can find the 367127044Sjhb * boot blocks. 368127044Sjhb */ 369127044Sjhb p = (uint64_t *)bootarea; 370127044Sjhb p[60] = (st.st_size + secsize - 1) / secsize; 371127044Sjhb p[61] = 1; 372127044Sjhb p[62] = 0; 373216095Skevlo close(fd); 374114571Sphk return; 375114860Sphk } else if ((!alphacksum) && st.st_size <= BBSIZE) { 376209614Sjh if (read(fd, bootarea, st.st_size) != st.st_size) 377114571Sphk err(1, "read error %s", xxboot); 378216095Skevlo close(fd); 379114571Sphk return; 380133347Sdes } 381114571Sphk errx(1, "boot code %s is wrong size", xxboot); 382114571Sphk} 383114571Sphk 384114571Sphkstatic int 385211873Sjhgeom_bsd_available(void) 386211873Sjh{ 387211873Sjh struct gclass *class; 388211873Sjh struct gmesh mesh; 389211873Sjh int error; 390211873Sjh 391211873Sjh error = geom_gettree(&mesh); 392211873Sjh if (error != 0) 393211873Sjh errc(1, error, "Cannot get GEOM tree"); 394211873Sjh 395211873Sjh LIST_FOREACH(class, &mesh.lg_class, lg_class) { 396211873Sjh if (strcmp(class->lg_name, "BSD") == 0) { 397211873Sjh geom_deletetree(&mesh); 398211873Sjh return (1); 399211873Sjh } 400211873Sjh } 401211873Sjh 402211873Sjh geom_deletetree(&mesh); 403211873Sjh 404211873Sjh return (0); 405211873Sjh} 406211873Sjh 407211873Sjhstatic int 408114571Sphkwritelabel(void) 409114571Sphk{ 410112307Sru uint64_t *p, sum; 411211873Sjh int i, fd, serrno; 412114569Sphk struct gctl_req *grq; 413114569Sphk char const *errstr; 414114571Sphk struct disklabel *lp = &lab; 41538384Sdfr 41673034Sjwd if (disable_write) { 417114574Sphk warnx("write to disk label supressed - label was as follows:"); 418114571Sphk display(stdout, NULL); 41973034Sjwd return (0); 420109878Sphk } 421109878Sphk 422109878Sphk lp->d_magic = DISKMAGIC; 423109878Sphk lp->d_magic2 = DISKMAGIC; 424109878Sphk lp->d_checksum = 0; 425109878Sphk lp->d_checksum = dkcksum(lp); 426114571Sphk if (installboot) 427114571Sphk readboot(); 428114673Sphk for (i = 0; i < lab.d_npartitions; i++) 429114673Sphk if (lab.d_partitions[i].p_size) 430196383Smarcel lab.d_partitions[i].p_offset += lba_offset; 431115696Sphk bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * secsize, 432115696Sphk lp); 433114552Sphk if (alphacksum) { 434114569Sphk /* Generate the bootblock checksum for the SRM console. */ 435114571Sphk for (p = (uint64_t *)bootarea, i = 0, sum = 0; i < 63; i++) 436112307Sru sum += p[i]; 437112307Sru p[63] = sum; 438112307Sru } 439114569Sphk 440114569Sphk fd = open(specname, O_RDWR); 441114569Sphk if (fd < 0) { 442127650Sluigi if (is_file) { 443127650Sluigi warn("cannot open file %s for writing label", specname); 444127650Sluigi return(1); 445211873Sjh } else 446211873Sjh serrno = errno; 447211873Sjh 448211873Sjh /* Give up if GEOM_BSD is not available. */ 449211873Sjh if (geom_bsd_available() == 0) { 450211873Sjh warnc(serrno, "%s", specname); 451211873Sjh return (1); 452127650Sluigi } 453183143Slulf 454115624Sphk grq = gctl_get_handle(); 455115624Sphk gctl_ro_param(grq, "verb", -1, "write label"); 456114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 457183143Slulf gctl_ro_param(grq, "geom", -1, pname); 458133347Sdes gctl_ro_param(grq, "label", 148+16*8, 459115696Sphk bootarea + labeloffset + labelsoffset * secsize); 460114569Sphk errstr = gctl_issue(grq); 461114571Sphk if (errstr != NULL) { 462114571Sphk warnx("%s", errstr); 463114571Sphk gctl_free(grq); 464114571Sphk return(1); 465114571Sphk } 466114569Sphk gctl_free(grq); 467114569Sphk if (installboot) { 468115624Sphk grq = gctl_get_handle(); 469115624Sphk gctl_ro_param(grq, "verb", -1, "write bootcode"); 470114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 471183143Slulf gctl_ro_param(grq, "geom", -1, pname); 472114571Sphk gctl_ro_param(grq, "bootcode", BBSIZE, bootarea); 473114569Sphk errstr = gctl_issue(grq); 474114571Sphk if (errstr != NULL) { 475114571Sphk warnx("%s", errstr); 476114571Sphk gctl_free(grq); 477114571Sphk return (1); 478114571Sphk } 479114569Sphk gctl_free(grq); 480114569Sphk } 481114569Sphk } else { 482114571Sphk if (write(fd, bootarea, bbsize) != bbsize) { 483114569Sphk warn("write %s", specname); 484114569Sphk close (fd); 485114569Sphk return (1); 486114569Sphk } 487114569Sphk close (fd); 488109878Sphk } 4891558Srgrimes return (0); 4901558Srgrimes} 4911558Srgrimes 492127650Sluigistatic void 493127650Sluigiget_file_parms(int f) 494127650Sluigi{ 495127650Sluigi int i; 496127650Sluigi struct stat sb; 497127650Sluigi 498127650Sluigi if (fstat(f, &sb) != 0) 499127650Sluigi err(4, "fstat failed"); 500127650Sluigi i = sb.st_mode & S_IFMT; 501127650Sluigi if (i != S_IFREG && i != S_IFLNK) 502127650Sluigi errx(4, "%s is not a valid file or link", specname); 503127650Sluigi secsize = DEV_BSIZE; 504127650Sluigi mediasize = sb.st_size; 505127650Sluigi} 506127650Sluigi 5071558Srgrimes/* 5081558Srgrimes * Fetch disklabel for disk. 5091558Srgrimes */ 510114571Sphkstatic int 511114571Sphkreadlabel(int flag) 5121558Srgrimes{ 513209614Sjh ssize_t nbytes; 514196383Smarcel uint32_t lba; 515114673Sphk int f, i; 516114569Sphk int error; 5171558Srgrimes 518114569Sphk f = open(specname, O_RDONLY); 519114569Sphk if (f < 0) 520215704Sbrucec err(1, "%s", specname); 521127650Sluigi if (is_file) 522127650Sluigi get_file_parms(f); 523183143Slulf else { 524183143Slulf mediasize = g_mediasize(f); 525183143Slulf secsize = g_sectorsize(f); 526183143Slulf if (secsize < 0 || mediasize < 0) 527183143Slulf err(4, "cannot get disk geometry"); 528115696Sphk } 529134973Sbrooks if (mediasize > (off_t)0xffffffff * secsize) 530134973Sbrooks errx(1, 531134973Sbrooks "disks with more than 2^32-1 sectors are not supported"); 532114550Sphk (void)lseek(f, (off_t)0, SEEK_SET); 533209614Sjh nbytes = read(f, bootarea, BBSIZE); 534209614Sjh if (nbytes == -1) 535114569Sphk err(4, "%s read", specname); 536209614Sjh if (nbytes != BBSIZE) 537209614Sjh errx(4, "couldn't read %d bytes from %s", BBSIZE, specname); 538114569Sphk close (f); 539115696Sphk error = bsd_disklabel_le_dec( 540115696Sphk bootarea + (labeloffset + labelsoffset * secsize), 541115696Sphk &lab, MAXPARTITIONS); 542114571Sphk if (flag && error) 543114571Sphk errx(1, "%s: no valid label found", specname); 544114673Sphk 545183143Slulf if (is_file) 546183143Slulf return(0); 547196383Smarcel 548196383Smarcel /* 549196383Smarcel * Compensate for absolute block addressing by finding the 550196383Smarcel * smallest partition offset and if the offset of the 'c' 551196383Smarcel * partition is equal to that, subtract it from all offsets. 552196383Smarcel */ 553196383Smarcel lba = ~0; 554196383Smarcel for (i = 0; i < lab.d_npartitions; i++) { 555196383Smarcel if (lab.d_partitions[i].p_size) 556196383Smarcel lba = MIN(lba, lab.d_partitions[i].p_offset); 557114673Sphk } 558196383Smarcel if (lba != 0 && lab.d_partitions[RAW_PART].p_offset == lba) { 559196383Smarcel for (i = 0; i < lab.d_npartitions; i++) { 560114673Sphk if (lab.d_partitions[i].p_size) 561196383Smarcel lab.d_partitions[i].p_offset -= lba; 562196383Smarcel } 563196383Smarcel /* 564196383Smarcel * Save the offset so that we can write the label 565196383Smarcel * back with absolute block addresses. 566196383Smarcel */ 567196383Smarcel lba_offset = lba; 568196383Smarcel } 569114571Sphk return (error); 5701558Srgrimes} 5711558Srgrimes 5721558Srgrimes 573114571Sphkstatic void 57492541Simpdisplay(FILE *f, const struct disklabel *lp) 5751558Srgrimes{ 57692541Simp int i, j; 57792541Simp const struct partition *pp; 5781558Srgrimes 579114571Sphk if (lp == NULL) 580114571Sphk lp = &lab; 581114571Sphk 5821558Srgrimes fprintf(f, "# %s:\n", specname); 583114574Sphk if (allfields) { 584114574Sphk if (lp->d_type < DKMAXTYPES) 585114574Sphk fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 586114574Sphk else 587114574Sphk fprintf(f, "type: %u\n", lp->d_type); 588114574Sphk fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 589114574Sphk lp->d_typename); 590114574Sphk fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 591114574Sphk lp->d_packname); 592114574Sphk fprintf(f, "flags:"); 593114574Sphk if (lp->d_flags & D_REMOVABLE) 594114574Sphk fprintf(f, " removeable"); 595114574Sphk if (lp->d_flags & D_ECC) 596114574Sphk fprintf(f, " ecc"); 597114574Sphk if (lp->d_flags & D_BADSECT) 598114574Sphk fprintf(f, " badsect"); 599114574Sphk fprintf(f, "\n"); 600114574Sphk fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 601114574Sphk fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 602114574Sphk fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 603114574Sphk fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 604114574Sphk fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 605114574Sphk fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 606114574Sphk fprintf(f, "rpm: %u\n", lp->d_rpm); 607114574Sphk fprintf(f, "interleave: %u\n", lp->d_interleave); 608114574Sphk fprintf(f, "trackskew: %u\n", lp->d_trackskew); 609114574Sphk fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 610114574Sphk fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 611114574Sphk (u_long)lp->d_headswitch); 612114574Sphk fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 613114574Sphk (u_long)lp->d_trkseek); 614114574Sphk fprintf(f, "drivedata: "); 615114574Sphk for (i = NDDATA - 1; i >= 0; i--) 616114574Sphk if (lp->d_drivedata[i]) 617114574Sphk break; 618114574Sphk if (i < 0) 619114574Sphk i = 0; 620114574Sphk for (j = 0; j <= i; j++) 621114574Sphk fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 622114574Sphk fprintf(f, "\n\n"); 623114574Sphk } 624114574Sphk fprintf(f, "%u partitions:\n", lp->d_npartitions); 6251558Srgrimes fprintf(f, 6265393Sgibbs "# size offset fstype [fsize bsize bps/cpg]\n"); 6271558Srgrimes pp = lp->d_partitions; 6281558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 6291558Srgrimes if (pp->p_size) { 63037234Sbde fprintf(f, " %c: %8lu %8lu ", 'a' + i, 63137234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 632107041Sjulian if (pp->p_fstype < FSMAXTYPES) 6331558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 6341558Srgrimes else 6351558Srgrimes fprintf(f, "%8d", pp->p_fstype); 6361558Srgrimes switch (pp->p_fstype) { 6371558Srgrimes 6381558Srgrimes case FS_UNUSED: /* XXX */ 63937234Sbde fprintf(f, " %5lu %5lu %5.5s ", 64037234Sbde (u_long)pp->p_fsize, 64137234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 6421558Srgrimes break; 6431558Srgrimes 6441558Srgrimes case FS_BSDFFS: 64537234Sbde fprintf(f, " %5lu %5lu %5u ", 64637234Sbde (u_long)pp->p_fsize, 64737234Sbde (u_long)(pp->p_fsize * pp->p_frag), 6481558Srgrimes pp->p_cpg); 6491558Srgrimes break; 6501558Srgrimes 6515393Sgibbs case FS_BSDLFS: 65237234Sbde fprintf(f, " %5lu %5lu %5d", 65337234Sbde (u_long)pp->p_fsize, 65437234Sbde (u_long)(pp->p_fsize * pp->p_frag), 6555393Sgibbs pp->p_cpg); 6565393Sgibbs break; 6575393Sgibbs 6581558Srgrimes default: 6591558Srgrimes fprintf(f, "%20.20s", ""); 6601558Srgrimes break; 6611558Srgrimes } 662114574Sphk if (i == RAW_PART) { 663114574Sphk fprintf(f, " # \"raw\" part, don't edit"); 664114574Sphk } 665114571Sphk fprintf(f, "\n"); 6661558Srgrimes } 6671558Srgrimes } 6681558Srgrimes fflush(f); 6691558Srgrimes} 6701558Srgrimes 671114571Sphkstatic int 672114571Sphkedit(void) 6731558Srgrimes{ 67492541Simp int c, fd; 6751558Srgrimes struct disklabel label; 67624180Simp FILE *fp; 6771558Srgrimes 67824180Simp if ((fd = mkstemp(tmpfil)) == -1 || 67924180Simp (fp = fdopen(fd, "w")) == NULL) { 68036632Scharnier warnx("can't create %s", tmpfil); 6811558Srgrimes return (1); 6821558Srgrimes } 683114571Sphk display(fp, NULL); 68424180Simp fclose(fp); 6851558Srgrimes for (;;) { 6861558Srgrimes if (!editit()) 6871558Srgrimes break; 68824180Simp fp = fopen(tmpfil, "r"); 68924180Simp if (fp == NULL) { 69036632Scharnier warnx("can't reopen %s for reading", tmpfil); 6911558Srgrimes break; 6921558Srgrimes } 6931558Srgrimes bzero((char *)&label, sizeof(label)); 694114571Sphk c = getasciilabel(fp, &label); 695114571Sphk fclose(fp); 696114571Sphk if (c) { 697114571Sphk lab = label; 698114571Sphk if (writelabel() == 0) { 6991558Srgrimes (void) unlink(tmpfil); 7001558Srgrimes return (0); 7011558Srgrimes } 7021558Srgrimes } 703114571Sphk printf("re-edit the label? [y]: "); 704114571Sphk fflush(stdout); 7051558Srgrimes c = getchar(); 7061558Srgrimes if (c != EOF && c != (int)'\n') 7071558Srgrimes while (getchar() != (int)'\n') 7081558Srgrimes ; 7091558Srgrimes if (c == (int)'n') 7101558Srgrimes break; 7111558Srgrimes } 7121558Srgrimes (void) unlink(tmpfil); 7131558Srgrimes return (1); 7141558Srgrimes} 7151558Srgrimes 716114571Sphkstatic int 71792541Simpeditit(void) 7181558Srgrimes{ 71992541Simp int pid, xpid; 72099365Smarkm int locstat, omask; 72199365Smarkm const char *ed; 722208132Skevlo uid_t uid; 723208132Skevlo gid_t gid; 7241558Srgrimes 7251558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 7261558Srgrimes while ((pid = fork()) < 0) { 7271558Srgrimes if (errno == EPROCLIM) { 72836632Scharnier warnx("you have too many processes"); 7291558Srgrimes return(0); 7301558Srgrimes } 7311558Srgrimes if (errno != EAGAIN) { 73236632Scharnier warn("fork"); 7331558Srgrimes return(0); 7341558Srgrimes } 7351558Srgrimes sleep(1); 7361558Srgrimes } 7371558Srgrimes if (pid == 0) { 7381558Srgrimes sigsetmask(omask); 739208132Skevlo gid = getgid(); 740208132Skevlo if (setresgid(gid, gid, gid) == -1) 741208132Skevlo err(1, "setresgid"); 742208132Skevlo uid = getuid(); 743208132Skevlo if (setresuid(uid, uid, uid) == -1) 744208132Skevlo err(1, "setresuid"); 7451558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 7461558Srgrimes ed = DEFEDITOR; 74779452Sbrian execlp(ed, ed, tmpfil, (char *)0); 74836632Scharnier err(1, "%s", ed); 7491558Srgrimes } 75099365Smarkm while ((xpid = wait(&locstat)) >= 0) 7511558Srgrimes if (xpid == pid) 7521558Srgrimes break; 7531558Srgrimes sigsetmask(omask); 75499365Smarkm return(!locstat); 7551558Srgrimes} 7561558Srgrimes 757114571Sphkstatic char * 75892541Simpskip(char *cp) 7591558Srgrimes{ 7601558Srgrimes 7611558Srgrimes while (*cp != '\0' && isspace(*cp)) 7621558Srgrimes cp++; 7631558Srgrimes if (*cp == '\0' || *cp == '#') 76492541Simp return (NULL); 7651558Srgrimes return (cp); 7661558Srgrimes} 7671558Srgrimes 768114571Sphkstatic char * 76992541Simpword(char *cp) 7701558Srgrimes{ 77192541Simp char c; 7721558Srgrimes 7731558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 7741558Srgrimes cp++; 7751558Srgrimes if ((c = *cp) != '\0') { 7761558Srgrimes *cp++ = '\0'; 7771558Srgrimes if (c != '#') 7781558Srgrimes return (skip(cp)); 7791558Srgrimes } 78092541Simp return (NULL); 7811558Srgrimes} 7821558Srgrimes 7831558Srgrimes/* 7841558Srgrimes * Read an ascii label in from fd f, 7851558Srgrimes * in the same format as that put out by display(), 7861558Srgrimes * and fill in lp. 7871558Srgrimes */ 788114571Sphkstatic int 78992541Simpgetasciilabel(FILE *f, struct disklabel *lp) 7901558Srgrimes{ 791211342Sjh char *cp, *endp; 79294065Sphk const char **cpp; 793107041Sjulian u_int part; 79494065Sphk char *tp, line[BUFSIZ]; 795107041Sjulian u_long v; 796107041Sjulian int lineno = 0, errors = 0; 79792541Simp int i; 7981558Srgrimes 799114862Sphk makelabel("auto", lp); 800109378Sdes bzero(&part_set, sizeof(part_set)); 801109378Sdes bzero(&part_size_type, sizeof(part_size_type)); 802109378Sdes bzero(&part_offset_type, sizeof(part_offset_type)); 8031558Srgrimes lp->d_bbsize = BBSIZE; /* XXX */ 80496475Sphk lp->d_sbsize = 0; /* XXX */ 8051558Srgrimes while (fgets(line, sizeof(line) - 1, f)) { 8061558Srgrimes lineno++; 80713544Sjoerg if ((cp = index(line,'\n')) != 0) 8081558Srgrimes *cp = '\0'; 8091558Srgrimes cp = skip(line); 8101558Srgrimes if (cp == NULL) 8111558Srgrimes continue; 8121558Srgrimes tp = index(cp, ':'); 8131558Srgrimes if (tp == NULL) { 8141558Srgrimes fprintf(stderr, "line %d: syntax error\n", lineno); 8151558Srgrimes errors++; 8161558Srgrimes continue; 8171558Srgrimes } 8181558Srgrimes *tp++ = '\0', tp = skip(tp); 819114571Sphk if (!strcmp(cp, "type")) { 8201558Srgrimes if (tp == NULL) 82199365Smarkm tp = unknown; 8221558Srgrimes cpp = dktypenames; 8231558Srgrimes for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 824114571Sphk if (*cpp && !strcmp(*cpp, tp)) { 8251558Srgrimes lp->d_type = cpp - dktypenames; 82697855Siedowse break; 8271558Srgrimes } 82897855Siedowse if (cpp < &dktypenames[DKMAXTYPES]) 82997855Siedowse continue; 830211342Sjh errno = 0; 831211342Sjh v = strtoul(tp, &endp, 10); 832211342Sjh if (errno != 0 || *endp != '\0') 833211342Sjh v = DKMAXTYPES; 834107041Sjulian if (v >= DKMAXTYPES) 835107041Sjulian fprintf(stderr, "line %d:%s %lu\n", lineno, 8361558Srgrimes "Warning, unknown disk type", v); 837211342Sjh else 838211342Sjh lp->d_type = v; 8391558Srgrimes continue; 8401558Srgrimes } 841114571Sphk if (!strcmp(cp, "flags")) { 8421558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 8431558Srgrimes tp = word(cp); 844114571Sphk if (!strcmp(cp, "removeable")) 8451558Srgrimes v |= D_REMOVABLE; 846114571Sphk else if (!strcmp(cp, "ecc")) 8471558Srgrimes v |= D_ECC; 848114571Sphk else if (!strcmp(cp, "badsect")) 8491558Srgrimes v |= D_BADSECT; 8501558Srgrimes else { 8511558Srgrimes fprintf(stderr, 8521558Srgrimes "line %d: %s: bad flag\n", 8531558Srgrimes lineno, cp); 8541558Srgrimes errors++; 8551558Srgrimes } 8561558Srgrimes } 8571558Srgrimes lp->d_flags = v; 8581558Srgrimes continue; 8591558Srgrimes } 860114571Sphk if (!strcmp(cp, "drivedata")) { 8611558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 862107041Sjulian lp->d_drivedata[i++] = strtoul(cp, NULL, 10); 8631558Srgrimes tp = word(cp); 8641558Srgrimes } 8651558Srgrimes continue; 8661558Srgrimes } 867107041Sjulian if (sscanf(cp, "%lu partitions", &v) == 1) { 868107041Sjulian if (v == 0 || v > MAXPARTITIONS) { 8691558Srgrimes fprintf(stderr, 8701558Srgrimes "line %d: bad # of partitions\n", lineno); 8711558Srgrimes lp->d_npartitions = MAXPARTITIONS; 8721558Srgrimes errors++; 8731558Srgrimes } else 8741558Srgrimes lp->d_npartitions = v; 8751558Srgrimes continue; 8761558Srgrimes } 8771558Srgrimes if (tp == NULL) 87899365Smarkm tp = blank; 879114571Sphk if (!strcmp(cp, "disk")) { 8801558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 8811558Srgrimes continue; 8821558Srgrimes } 883114571Sphk if (!strcmp(cp, "label")) { 8841558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 8851558Srgrimes continue; 8861558Srgrimes } 887114571Sphk if (!strcmp(cp, "bytes/sector")) { 888107041Sjulian v = strtoul(tp, NULL, 10); 889107041Sjulian if (v == 0 || (v % DEV_BSIZE) != 0) { 8901558Srgrimes fprintf(stderr, 8911558Srgrimes "line %d: %s: bad sector size\n", 8921558Srgrimes lineno, tp); 8931558Srgrimes errors++; 8941558Srgrimes } else 8951558Srgrimes lp->d_secsize = v; 8961558Srgrimes continue; 8971558Srgrimes } 898114571Sphk if (!strcmp(cp, "sectors/track")) { 899107041Sjulian v = strtoul(tp, NULL, 10); 900107041Sjulian#if (ULONG_MAX != 0xffffffffUL) 901133347Sdes if (v == 0 || v > 0xffffffff) 902107041Sjulian#else 903133347Sdes if (v == 0) 904107041Sjulian#endif 905133347Sdes { 9061558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9071558Srgrimes lineno, tp, cp); 9081558Srgrimes errors++; 9091558Srgrimes } else 9101558Srgrimes lp->d_nsectors = v; 9111558Srgrimes continue; 9121558Srgrimes } 913114571Sphk if (!strcmp(cp, "sectors/cylinder")) { 914107041Sjulian v = strtoul(tp, NULL, 10); 915107041Sjulian if (v == 0) { 9161558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9171558Srgrimes lineno, tp, cp); 9181558Srgrimes errors++; 9191558Srgrimes } else 9201558Srgrimes lp->d_secpercyl = v; 9211558Srgrimes continue; 9221558Srgrimes } 923114571Sphk if (!strcmp(cp, "tracks/cylinder")) { 924107041Sjulian v = strtoul(tp, NULL, 10); 925107041Sjulian if (v == 0) { 9261558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9271558Srgrimes lineno, tp, cp); 9281558Srgrimes errors++; 9291558Srgrimes } else 9301558Srgrimes lp->d_ntracks = v; 9311558Srgrimes continue; 9321558Srgrimes } 933114571Sphk if (!strcmp(cp, "cylinders")) { 934107041Sjulian v = strtoul(tp, NULL, 10); 935107041Sjulian if (v == 0) { 9361558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9371558Srgrimes lineno, tp, cp); 9381558Srgrimes errors++; 9391558Srgrimes } else 9401558Srgrimes lp->d_ncylinders = v; 9411558Srgrimes continue; 9421558Srgrimes } 943114571Sphk if (!strcmp(cp, "sectors/unit")) { 944107041Sjulian v = strtoul(tp, NULL, 10); 945107041Sjulian if (v == 0) { 9466643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 9476643Sbde lineno, tp, cp); 9486643Sbde errors++; 9496643Sbde } else 9506643Sbde lp->d_secperunit = v; 9516643Sbde continue; 9526643Sbde } 953114571Sphk if (!strcmp(cp, "rpm")) { 954107041Sjulian v = strtoul(tp, NULL, 10); 955107041Sjulian if (v == 0 || v > USHRT_MAX) { 9561558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9571558Srgrimes lineno, tp, cp); 9581558Srgrimes errors++; 9591558Srgrimes } else 9601558Srgrimes lp->d_rpm = v; 9611558Srgrimes continue; 9621558Srgrimes } 963114571Sphk if (!strcmp(cp, "interleave")) { 964107041Sjulian v = strtoul(tp, NULL, 10); 965107041Sjulian if (v == 0 || v > USHRT_MAX) { 9661558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9671558Srgrimes lineno, tp, cp); 9681558Srgrimes errors++; 9691558Srgrimes } else 9701558Srgrimes lp->d_interleave = v; 9711558Srgrimes continue; 9721558Srgrimes } 973114571Sphk if (!strcmp(cp, "trackskew")) { 974107041Sjulian v = strtoul(tp, NULL, 10); 975107041Sjulian if (v > USHRT_MAX) { 9761558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9771558Srgrimes lineno, tp, cp); 9781558Srgrimes errors++; 9791558Srgrimes } else 9801558Srgrimes lp->d_trackskew = v; 9811558Srgrimes continue; 9821558Srgrimes } 983114571Sphk if (!strcmp(cp, "cylinderskew")) { 984107041Sjulian v = strtoul(tp, NULL, 10); 985107041Sjulian if (v > USHRT_MAX) { 9861558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9871558Srgrimes lineno, tp, cp); 9881558Srgrimes errors++; 9891558Srgrimes } else 9901558Srgrimes lp->d_cylskew = v; 9911558Srgrimes continue; 9921558Srgrimes } 993114571Sphk if (!strcmp(cp, "headswitch")) { 994107041Sjulian v = strtoul(tp, NULL, 10); 995107041Sjulian lp->d_headswitch = v; 9961558Srgrimes continue; 9971558Srgrimes } 998114571Sphk if (!strcmp(cp, "track-to-track seek")) { 999107041Sjulian v = strtoul(tp, NULL, 10); 1000107041Sjulian lp->d_trkseek = v; 10011558Srgrimes continue; 10021558Srgrimes } 100373034Sjwd /* the ':' was removed above */ 100497534Siedowse if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') { 100597534Siedowse fprintf(stderr, 100697534Siedowse "line %d: %s: Unknown disklabel field\n", lineno, 100797534Siedowse cp); 100897534Siedowse errors++; 100997534Siedowse continue; 101097534Siedowse } 101197534Siedowse 101297534Siedowse /* Process a partition specification line. */ 101397534Siedowse part = *cp - 'a'; 101497534Siedowse if (part >= lp->d_npartitions) { 101597534Siedowse fprintf(stderr, 101697534Siedowse "line %d: partition name out of range a-%c: %s\n", 101797534Siedowse lineno, 'a' + lp->d_npartitions - 1, cp); 101897534Siedowse errors++; 101997534Siedowse continue; 102097534Siedowse } 102197534Siedowse part_set[part] = 1; 102297534Siedowse 102397534Siedowse if (getasciipartspec(tp, lp, part, lineno) != 0) { 102497534Siedowse errors++; 102597534Siedowse break; 102697534Siedowse } 102797534Siedowse } 102897534Siedowse errors += checklabel(lp); 102997534Siedowse return (errors == 0); 103097534Siedowse} 103197534Siedowse 103297534Siedowse#define NXTNUM(n) do { \ 10333111Spst if (tp == NULL) { \ 10343111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 103597534Siedowse return (1); \ 10363111Spst } else { \ 10373111Spst cp = tp, tp = word(cp); \ 1038107041Sjulian (n) = strtoul(cp, NULL, 10); \ 10393111Spst } \ 104097534Siedowse} while (0) 104197534Siedowse 104273034Sjwd/* retain 1 character following number */ 104397534Siedowse#define NXTWORD(w,n) do { \ 104473034Sjwd if (tp == NULL) { \ 104573034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 104697534Siedowse return (1); \ 104773034Sjwd } else { \ 1048133347Sdes char *tmp; \ 104973034Sjwd cp = tp, tp = word(cp); \ 1050133347Sdes (n) = strtoul(cp, &tmp, 10); \ 105173034Sjwd if (tmp) (w) = *tmp; \ 105273034Sjwd } \ 105397534Siedowse} while (0) 10541558Srgrimes 105597534Siedowse/* 105697534Siedowse * Read a partition line into partition `part' in the specified disklabel. 105797534Siedowse * Return 0 on success, 1 on failure. 105897534Siedowse */ 1059114571Sphkstatic int 106097534Siedowsegetasciipartspec(char *tp, struct disklabel *lp, int part, int lineno) 106197534Siedowse{ 106297534Siedowse struct partition *pp; 1063211342Sjh char *cp, *endp; 106497534Siedowse const char **cpp; 1065107041Sjulian u_long v; 10661558Srgrimes 106797534Siedowse pp = &lp->d_partitions[part]; 106897534Siedowse cp = NULL; 10691558Srgrimes 107097534Siedowse v = 0; 107197534Siedowse NXTWORD(part_size_type[part],v); 1072107041Sjulian if (v == 0 && part_size_type[part] != '*') { 1073107041Sjulian fprintf(stderr, 1074107041Sjulian "line %d: %s: bad partition size\n", lineno, cp); 107597534Siedowse return (1); 107697534Siedowse } 107797534Siedowse pp->p_size = v; 107897534Siedowse 107997534Siedowse v = 0; 108097534Siedowse NXTWORD(part_offset_type[part],v); 1081107041Sjulian if (v == 0 && part_offset_type[part] != '*' && 1082107041Sjulian part_offset_type[part] != '\0') { 1083107041Sjulian fprintf(stderr, 1084107041Sjulian "line %d: %s: bad partition offset\n", lineno, cp); 108597534Siedowse return (1); 108697534Siedowse } 108797534Siedowse pp->p_offset = v; 1088112945Syar if (tp == NULL) { 1089112945Syar fprintf(stderr, "line %d: missing file system type\n", lineno); 1090112945Syar return (1); 1091112945Syar } 109297534Siedowse cp = tp, tp = word(cp); 109397534Siedowse for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) 1094114571Sphk if (*cpp && !strcmp(*cpp, cp)) 109597534Siedowse break; 109697534Siedowse if (*cpp != NULL) { 109797534Siedowse pp->p_fstype = cpp - fstypenames; 109897534Siedowse } else { 1099211342Sjh if (isdigit(*cp)) { 1100211342Sjh errno = 0; 1101211342Sjh v = strtoul(cp, &endp, 10); 1102211342Sjh if (errno != 0 || *endp != '\0') 1103211342Sjh v = FSMAXTYPES; 1104211342Sjh } else 110597534Siedowse v = FSMAXTYPES; 1106107041Sjulian if (v >= FSMAXTYPES) { 110797534Siedowse fprintf(stderr, 1108102231Strhodes "line %d: Warning, unknown file system type %s\n", 110997534Siedowse lineno, cp); 111097534Siedowse v = FS_UNUSED; 111197534Siedowse } 111297534Siedowse pp->p_fstype = v; 111397534Siedowse } 111497534Siedowse 111597534Siedowse switch (pp->p_fstype) { 111697534Siedowse case FS_UNUSED: 1117120821Siedowse case FS_BSDFFS: 1118120821Siedowse case FS_BSDLFS: 1119120821Siedowse /* accept defaults for fsize/frag/cpg */ 112097534Siedowse if (tp) { 112197534Siedowse NXTNUM(pp->p_fsize); 112297534Siedowse if (pp->p_fsize == 0) 112397534Siedowse break; 112497534Siedowse NXTNUM(v); 112597534Siedowse pp->p_frag = v / pp->p_fsize; 1126120821Siedowse if (tp != NULL) 1127120821Siedowse NXTNUM(pp->p_cpg); 112897534Siedowse } 112997534Siedowse /* else default to 0's */ 113097534Siedowse break; 113197534Siedowse default: 113297534Siedowse break; 11331558Srgrimes } 113497534Siedowse return (0); 11351558Srgrimes} 11361558Srgrimes 11371558Srgrimes/* 11381558Srgrimes * Check disklabel for errors and fill in 11391558Srgrimes * derived fields according to supplied values. 11401558Srgrimes */ 1141114571Sphkstatic int 114292541Simpchecklabel(struct disklabel *lp) 11431558Srgrimes{ 114492541Simp struct partition *pp; 11451558Srgrimes int i, errors = 0; 11461558Srgrimes char part; 1147149061Siedowse u_long base_offset, needed, total_size, total_percent, current_offset; 1148149061Siedowse long free_space; 114973034Sjwd int seen_default_offset; 115073034Sjwd int hog_part; 115173034Sjwd int j; 115273034Sjwd struct partition *pp2; 11531558Srgrimes 1154114571Sphk if (lp == NULL) 1155114571Sphk lp = &lab; 1156114571Sphk 1157114574Sphk if (allfields) { 1158114574Sphk 1159114574Sphk if (lp->d_secsize == 0) { 1160114574Sphk fprintf(stderr, "sector size 0\n"); 1161114574Sphk return (1); 1162114574Sphk } 1163114574Sphk if (lp->d_nsectors == 0) { 1164114574Sphk fprintf(stderr, "sectors/track 0\n"); 1165114574Sphk return (1); 1166114574Sphk } 1167114574Sphk if (lp->d_ntracks == 0) { 1168114574Sphk fprintf(stderr, "tracks/cylinder 0\n"); 1169114574Sphk return (1); 1170114574Sphk } 1171114574Sphk if (lp->d_ncylinders == 0) { 1172114574Sphk fprintf(stderr, "cylinders/unit 0\n"); 1173114574Sphk errors++; 1174114574Sphk } 1175114574Sphk if (lp->d_rpm == 0) 1176114574Sphk warnx("revolutions/minute 0"); 1177114574Sphk if (lp->d_secpercyl == 0) 1178114574Sphk lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1179114574Sphk if (lp->d_secperunit == 0) 1180114574Sphk lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1181114574Sphk if (lp->d_bbsize == 0) { 1182114574Sphk fprintf(stderr, "boot block size 0\n"); 1183114574Sphk errors++; 1184114574Sphk } else if (lp->d_bbsize % lp->d_secsize) 1185114574Sphk warnx("boot block size %% sector-size != 0"); 1186114574Sphk if (lp->d_npartitions > MAXPARTITIONS) 1187114574Sphk warnx("number of partitions (%lu) > MAXPARTITIONS (%d)", 1188114574Sphk (u_long)lp->d_npartitions, MAXPARTITIONS); 1189114574Sphk } else { 1190114574Sphk struct disklabel *vl; 1191114574Sphk 1192114574Sphk vl = getvirginlabel(); 1193114574Sphk lp->d_secsize = vl->d_secsize; 1194114574Sphk lp->d_nsectors = vl->d_nsectors; 1195114574Sphk lp->d_ntracks = vl->d_ntracks; 1196114574Sphk lp->d_ncylinders = vl->d_ncylinders; 1197114574Sphk lp->d_rpm = vl->d_rpm; 1198114574Sphk lp->d_interleave = vl->d_interleave; 1199114574Sphk lp->d_secpercyl = vl->d_secpercyl; 1200114574Sphk lp->d_secperunit = vl->d_secperunit; 1201114574Sphk lp->d_bbsize = vl->d_bbsize; 1202114574Sphk lp->d_npartitions = vl->d_npartitions; 12031558Srgrimes } 120473034Sjwd 1205114574Sphk 120673034Sjwd /* first allocate space to the partitions, then offsets */ 120773034Sjwd total_size = 0; /* in sectors */ 120873034Sjwd total_percent = 0; /* in percent */ 120973034Sjwd hog_part = -1; 121073034Sjwd /* find all fixed partitions */ 12111558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 121273034Sjwd pp = &lp->d_partitions[i]; 121373034Sjwd if (part_set[i]) { 121473034Sjwd if (part_size_type[i] == '*') { 121594065Sphk if (i == RAW_PART) { 121673034Sjwd pp->p_size = lp->d_secperunit; 121773034Sjwd } else { 121873034Sjwd if (hog_part != -1) 1219114574Sphk warnx("Too many '*' partitions (%c and %c)", 122073034Sjwd hog_part + 'a',i + 'a'); 122173034Sjwd else 122273034Sjwd hog_part = i; 122373034Sjwd } 122473034Sjwd } else { 122573573Simp off_t size; 122673034Sjwd 122773034Sjwd size = pp->p_size; 122873034Sjwd switch (part_size_type[i]) { 122973034Sjwd case '%': 123073034Sjwd total_percent += size; 123173034Sjwd break; 1232133348Sdes case 't': 1233133348Sdes case 'T': 1234133348Sdes size *= 1024ULL; 1235133348Sdes /* FALLTHROUGH */ 1236133348Sdes case 'g': 1237133348Sdes case 'G': 1238133348Sdes size *= 1024ULL; 1239133348Sdes /* FALLTHROUGH */ 1240133348Sdes case 'm': 1241133348Sdes case 'M': 1242133348Sdes size *= 1024ULL; 1243133348Sdes /* FALLTHROUGH */ 124473034Sjwd case 'k': 124573034Sjwd case 'K': 124673573Simp size *= 1024ULL; 124773034Sjwd break; 124873034Sjwd case '\0': 124973034Sjwd break; 125073034Sjwd default: 1251133384Sdes warnx("unknown multiplier suffix '%c' for partition %c (should be K, M, G or T)", 1252133348Sdes part_size_type[i], i + 'a'); 125373034Sjwd break; 125473034Sjwd } 125573034Sjwd /* don't count %'s yet */ 125673034Sjwd if (part_size_type[i] != '%') { 125773034Sjwd /* 125873034Sjwd * for all not in sectors, convert to 125973034Sjwd * sectors 126073034Sjwd */ 126173034Sjwd if (part_size_type[i] != '\0') { 126273034Sjwd if (size % lp->d_secsize != 0) 1263114574Sphk warnx("partition %c not an integer number of sectors", 126473034Sjwd i + 'a'); 126573034Sjwd size /= lp->d_secsize; 126673034Sjwd pp->p_size = size; 126773034Sjwd } 126873034Sjwd /* else already in sectors */ 126994065Sphk if (i != RAW_PART) 127073034Sjwd total_size += size; 127173034Sjwd } 127273034Sjwd } 127373034Sjwd } 127473034Sjwd } 1275149061Siedowse 1276149061Siedowse /* Find out the total free space, excluding the boot block area. */ 1277149061Siedowse base_offset = BBSIZE / secsize; 1278149061Siedowse free_space = 0; 1279149061Siedowse for (i = 0; i < lp->d_npartitions; i++) { 1280149061Siedowse pp = &lp->d_partitions[i]; 1281149061Siedowse if (!part_set[i] || i == RAW_PART || 1282149061Siedowse part_size_type[i] == '%' || part_size_type[i] == '*') 1283149061Siedowse continue; 1284149061Siedowse if (pp->p_offset > base_offset) 1285149061Siedowse free_space += pp->p_offset - base_offset; 1286149061Siedowse if (pp->p_offset + pp->p_size > base_offset) 1287149061Siedowse base_offset = pp->p_offset + pp->p_size; 1288149061Siedowse } 1289149061Siedowse if (base_offset < lp->d_secperunit) 1290149061Siedowse free_space += lp->d_secperunit - base_offset; 1291149061Siedowse 129273034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 129373034Sjwd if (total_percent != 0) { 129473034Sjwd if (total_percent > 100) { 129594065Sphk fprintf(stderr,"total percentage %lu is greater than 100\n", 129673034Sjwd total_percent); 129773034Sjwd errors++; 129873034Sjwd } 129973034Sjwd 130073034Sjwd if (free_space > 0) { 130173034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 130273034Sjwd pp = &lp->d_partitions[i]; 130373034Sjwd if (part_set[i] && part_size_type[i] == '%') { 130473034Sjwd /* careful of overflows! and integer roundoff */ 130573034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 130673034Sjwd total_size += pp->p_size; 130773034Sjwd 130873034Sjwd /* FIX we can lose a sector or so due to roundoff per 130973034Sjwd partition. A more complex algorithm could avoid that */ 131073034Sjwd } 131173034Sjwd } 131273034Sjwd } else { 131373034Sjwd fprintf(stderr, 131494065Sphk "%ld sectors available to give to '*' and '%%' partitions\n", 131573034Sjwd free_space); 131673034Sjwd errors++; 131773034Sjwd /* fix? set all % partitions to size 0? */ 131873034Sjwd } 131973034Sjwd } 132073034Sjwd /* give anything remaining to the hog partition */ 132173034Sjwd if (hog_part != -1) { 1322149061Siedowse /* 1323149061Siedowse * Find the range of offsets usable by '*' partitions around 1324149061Siedowse * the hog partition and how much space they need. 1325149061Siedowse */ 1326149061Siedowse needed = 0; 1327149061Siedowse base_offset = BBSIZE / secsize; 1328149061Siedowse for (i = hog_part - 1; i >= 0; i--) { 1329149061Siedowse pp = &lp->d_partitions[i]; 1330149061Siedowse if (!part_set[i] || i == RAW_PART) 1331149061Siedowse continue; 1332149061Siedowse if (part_offset_type[i] == '*') { 1333149061Siedowse needed += pp->p_size; 1334149061Siedowse continue; 1335149061Siedowse } 1336149061Siedowse base_offset = pp->p_offset + pp->p_size; 1337149061Siedowse break; 1338149061Siedowse } 1339149061Siedowse current_offset = lp->d_secperunit; 1340149061Siedowse for (i = lp->d_npartitions - 1; i > hog_part; i--) { 1341149061Siedowse pp = &lp->d_partitions[i]; 1342149061Siedowse if (!part_set[i] || i == RAW_PART) 1343149061Siedowse continue; 1344149061Siedowse if (part_offset_type[i] == '*') { 1345149061Siedowse needed += pp->p_size; 1346149061Siedowse continue; 1347149061Siedowse } 1348149061Siedowse current_offset = pp->p_offset; 1349149061Siedowse } 1350149061Siedowse 1351149061Siedowse if (current_offset - base_offset <= needed) { 1352149061Siedowse fprintf(stderr, "Cannot find space for partition %c\n", 1353149061Siedowse hog_part + 'a'); 1354149061Siedowse fprintf(stderr, 1355149061Siedowse "Need more than %lu sectors between %lu and %lu\n", 1356149061Siedowse needed, base_offset, current_offset); 1357149061Siedowse errors++; 1358149061Siedowse lp->d_partitions[hog_part].p_size = 0; 1359149061Siedowse } else { 1360149061Siedowse lp->d_partitions[hog_part].p_size = current_offset - 1361149061Siedowse base_offset - needed; 1362149061Siedowse total_size += lp->d_partitions[hog_part].p_size; 1363149061Siedowse } 136473034Sjwd } 136573034Sjwd 136673034Sjwd /* Now set the offsets for each partition */ 1367149061Siedowse current_offset = BBSIZE / secsize; /* in sectors */ 136873034Sjwd seen_default_offset = 0; 136973034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 13701558Srgrimes part = 'a' + i; 13711558Srgrimes pp = &lp->d_partitions[i]; 137273034Sjwd if (part_set[i]) { 137373034Sjwd if (part_offset_type[i] == '*') { 137494065Sphk if (i == RAW_PART) { 137573034Sjwd pp->p_offset = 0; 137673034Sjwd } else { 137773034Sjwd pp->p_offset = current_offset; 137873034Sjwd seen_default_offset = 1; 137973034Sjwd } 138073034Sjwd } else { 138173034Sjwd /* allow them to be out of order for old-style tables */ 1382133347Sdes if (pp->p_offset < current_offset && 1383107534Sgrog seen_default_offset && i != RAW_PART && 1384107534Sgrog pp->p_fstype != FS_VINUM) { 138573034Sjwd fprintf(stderr, 138694065Sphk"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 138794065Sphk (long)pp->p_offset,i+'a',current_offset); 138873034Sjwd fprintf(stderr, 138973034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 139073034Sjwd errors++; 139173034Sjwd } else if (pp->p_offset != current_offset && 139294065Sphk i != RAW_PART && seen_default_offset) { 1393133347Sdes /* 1394133347Sdes * this may give unneeded warnings if 139573034Sjwd * partitions are out-of-order 139673034Sjwd */ 1397114574Sphk warnx( 139873034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 139994065Sphk (long)pp->p_offset, i + 'a', current_offset); 140073034Sjwd } 140173034Sjwd } 140294065Sphk if (i != RAW_PART) 1403133347Sdes current_offset = pp->p_offset + pp->p_size; 140473034Sjwd } 140573034Sjwd } 140673034Sjwd 140773034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 140873034Sjwd part = 'a' + i; 140973034Sjwd pp = &lp->d_partitions[i]; 14101558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 1411114574Sphk warnx("partition %c: size 0, but offset %lu", 141237234Sbde part, (u_long)pp->p_offset); 14131558Srgrimes#ifdef notdef 14141558Srgrimes if (pp->p_size % lp->d_secpercyl) 1415114574Sphk warnx("partition %c: size %% cylinder-size != 0", 14161558Srgrimes part); 14171558Srgrimes if (pp->p_offset % lp->d_secpercyl) 1418114574Sphk warnx("partition %c: offset %% cylinder-size != 0", 14191558Srgrimes part); 14201558Srgrimes#endif 14211558Srgrimes if (pp->p_offset > lp->d_secperunit) { 14221558Srgrimes fprintf(stderr, 14231558Srgrimes "partition %c: offset past end of unit\n", part); 14241558Srgrimes errors++; 14251558Srgrimes } 14261558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 14271558Srgrimes fprintf(stderr, 142813544Sjoerg "partition %c: partition extends past end of unit\n", 14291558Srgrimes part); 14301558Srgrimes errors++; 14311558Srgrimes } 1432114574Sphk if (i == RAW_PART) { 143373034Sjwd if (pp->p_fstype != FS_UNUSED) 1434114574Sphk warnx("partition %c is not marked as unused!",part); 143573034Sjwd if (pp->p_offset != 0) 1436114574Sphk warnx("partition %c doesn't start at 0!",part); 143773034Sjwd if (pp->p_size != lp->d_secperunit) 1438114574Sphk warnx("partition %c doesn't cover the whole unit!",part); 143973034Sjwd 144073034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 144173034Sjwd (pp->p_size != lp->d_secperunit)) { 1442114574Sphk warnx("An incorrect partition %c may cause problems for " 144373034Sjwd "standard system utilities",part); 144473034Sjwd } 144573034Sjwd } 144673034Sjwd 144773034Sjwd /* check for overlaps */ 144873034Sjwd /* this will check for all possible overlaps once and only once */ 144973034Sjwd for (j = 0; j < i; j++) { 1450107534Sgrog pp2 = &lp->d_partitions[j]; 1451133347Sdes if (j != RAW_PART && i != RAW_PART && 1452107534Sgrog pp->p_fstype != FS_VINUM && 1453107534Sgrog pp2->p_fstype != FS_VINUM && 145473034Sjwd part_set[i] && part_set[j]) { 145573034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 145673034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 145773034Sjwd pp2->p_offset >= pp->p_offset)) { 145873034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 145973034Sjwd j + 'a', i + 'a'); 146073034Sjwd errors++; 146173034Sjwd } 146273034Sjwd } 146373034Sjwd } 14641558Srgrimes } 1465174501Smarcel for (; i < lp->d_npartitions; i++) { 14661558Srgrimes part = 'a' + i; 14671558Srgrimes pp = &lp->d_partitions[i]; 14681558Srgrimes if (pp->p_size || pp->p_offset) 1469114574Sphk warnx("unused partition %c: size %d offset %lu", 147037234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 14711558Srgrimes } 14721558Srgrimes return (errors); 14731558Srgrimes} 14741558Srgrimes 14751558Srgrimes/* 147613550Sjoerg * When operating on a "virgin" disk, try getting an initial label 147713550Sjoerg * from the associated device driver. This might work for all device 147813550Sjoerg * drivers that are able to fetch some initial device parameters 147913550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 148013550Sjoerg * most IDE drives, or vn devices. 148113550Sjoerg * 148213550Sjoerg * The device name must be given in its "canonical" form. 148313550Sjoerg */ 1484114571Sphkstatic struct disklabel * 148513550Sjoerggetvirginlabel(void) 148613550Sjoerg{ 148799365Smarkm static struct disklabel loclab; 1488103669Sphk struct partition *dp; 148913550Sjoerg int f; 1490114574Sphk u_int u; 149113550Sjoerg 1492114571Sphk if ((f = open(specname, O_RDONLY)) == -1) { 1493114571Sphk warn("cannot open %s", specname); 149416431Sbde return (NULL); 149513550Sjoerg } 149668044Sjkh 1497127650Sluigi if (is_file) 1498127650Sluigi get_file_parms(f); 1499183143Slulf else { 1500183143Slulf mediasize = g_mediasize(f); 1501183143Slulf secsize = g_sectorsize(f); 1502183143Slulf if (secsize < 0 || mediasize < 0) { 1503183143Slulf close (f); 1504183143Slulf return (NULL); 1505183143Slulf } 1506103669Sphk } 1507103669Sphk memset(&loclab, 0, sizeof loclab); 1508103669Sphk loclab.d_magic = DISKMAGIC; 1509103669Sphk loclab.d_magic2 = DISKMAGIC; 1510103669Sphk loclab.d_secsize = secsize; 1511103669Sphk loclab.d_secperunit = mediasize / secsize; 1512103669Sphk 151368044Sjkh /* 1514103669Sphk * Nobody in these enligthened days uses the CHS geometry for 1515103669Sphk * anything, but nontheless try to get it right. If we fail 1516103669Sphk * to get any good ideas from the device, construct something 1517103669Sphk * which is IBM-PC friendly. 151868044Sjkh */ 1519103669Sphk if (ioctl(f, DIOCGFWSECTORS, &u) == 0) 1520103669Sphk loclab.d_nsectors = u; 1521103669Sphk else 1522103669Sphk loclab.d_nsectors = 63; 1523103669Sphk if (ioctl(f, DIOCGFWHEADS, &u) == 0) 1524103669Sphk loclab.d_ntracks = u; 1525103669Sphk else if (loclab.d_secperunit <= 63*1*1024) 1526103669Sphk loclab.d_ntracks = 1; 1527103669Sphk else if (loclab.d_secperunit <= 63*16*1024) 1528103669Sphk loclab.d_ntracks = 16; 1529103669Sphk else 1530103669Sphk loclab.d_ntracks = 255; 1531103669Sphk loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors; 1532103669Sphk loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl; 1533174501Smarcel loclab.d_npartitions = DEFPARTITIONS; 1534103669Sphk 1535103669Sphk /* Various (unneeded) compat stuff */ 1536103669Sphk loclab.d_rpm = 3600; 1537103669Sphk loclab.d_bbsize = BBSIZE; 1538114574Sphk loclab.d_interleave = 1; 1539103669Sphk strncpy(loclab.d_typename, "amnesiac", 1540103669Sphk sizeof(loclab.d_typename)); 1541103669Sphk 1542103669Sphk dp = &loclab.d_partitions[RAW_PART]; 1543103669Sphk dp->p_size = loclab.d_secperunit; 1544103669Sphk loclab.d_checksum = dkcksum(&loclab); 1545103669Sphk close (f); 154699365Smarkm return (&loclab); 154713550Sjoerg} 154813550Sjoerg 1549114571Sphkstatic void 155092541Simpusage(void) 15511558Srgrimes{ 1552112307Sru 1553112307Sru fprintf(stderr, 1554112307Sru "%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", 1555114569Sphk "usage: bsdlabel disk", 1556112307Sru "\t\t(to read label)", 1557114571Sphk " bsdlabel -w [-n] [-m machine] disk [type]", 1558112307Sru "\t\t(to write label with existing boot program)", 1559114569Sphk " bsdlabel -e [-n] [-m machine] disk", 1560112307Sru "\t\t(to edit label)", 1561114569Sphk " bsdlabel -R [-n] [-m machine] disk protofile", 1562112307Sru "\t\t(to restore label with existing boot program)", 1563113680Sphk " bsdlabel -B [-b boot] [-m machine] disk", 1564112307Sru "\t\t(to install boot program with existing on-disk label)", 1565114571Sphk " bsdlabel -w -B [-n] [-b boot] [-m machine] disk [type]", 1566112307Sru "\t\t(to write label and install boot program)", 1567113680Sphk " bsdlabel -R -B [-n] [-b boot] [-m machine] disk protofile", 1568109878Sphk "\t\t(to restore label and install boot program)" 1569109878Sphk ); 15701558Srgrimes exit(1); 15711558Srgrimes} 1572