1331722Seadler/* 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$"); 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 66227231Sae#define MAXPARTITIONS 20 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 *); 83227270Saestatic int geom_class_available(const char *); 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; 108219449Suqsstatic ssize_t 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; 132114550Sphk 133228417Sedstatic enum { 134109872Sphk UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT 1351558Srgrimes} op = UNSPEC; 1361558Srgrimes 137112307Sru 138114571Sphkstatic int disable_write; /* set to disable writing to disk label */ 139127650Sluigistatic int is_file; /* work on a file (abs. pathname), "-f" opt. */ 1401558Srgrimes 14113544Sjoergint 14292541Simpmain(int argc, char *argv[]) 1431558Srgrimes{ 1441558Srgrimes FILE *t; 145183143Slulf int ch, error, fd; 146183143Slulf const char *name; 147183143Slulf 148183143Slulf error = 0; 149183143Slulf name = NULL; 1501558Srgrimes 151163539Smaxim while ((ch = getopt(argc, argv, "ABb:efm:nRrw")) != -1) 1521558Srgrimes switch (ch) { 153114574Sphk case 'A': 154114574Sphk allfields = 1; 155114574Sphk break; 1561558Srgrimes case 'B': 1571558Srgrimes ++installboot; 1581558Srgrimes break; 1591558Srgrimes case 'b': 1601558Srgrimes xxboot = optarg; 1611558Srgrimes break; 162127650Sluigi case 'f': 163127650Sluigi is_file=1; 164127650Sluigi break; 165112307Sru case 'm': 166115948Sphk if (!strcmp(optarg, "i386") || 167115948Sphk !strcmp(optarg, "amd64") || 168115948Sphk !strcmp(optarg, "pc98")) { 169115696Sphk labelsoffset = 1; 170115696Sphk labeloffset = 0; 171114550Sphk bbsize = 8192; 172114571Sphk } else { 173114571Sphk errx(1, "Unsupported architecture"); 174114550Sphk } 175112307Sru break; 17673034Sjwd case 'n': 17773034Sjwd disable_write = 1; 17873034Sjwd break; 1791558Srgrimes case 'R': 1801558Srgrimes if (op != UNSPEC) 1811558Srgrimes usage(); 1821558Srgrimes op = RESTORE; 1831558Srgrimes break; 1841558Srgrimes case 'e': 1851558Srgrimes if (op != UNSPEC) 1861558Srgrimes usage(); 1871558Srgrimes op = EDIT; 1881558Srgrimes break; 1891558Srgrimes case 'r': 190114571Sphk /* 191229778Suqs * We accept and ignore -r for compatibility with 192229778Suqs * historical disklabel usage. 193114571Sphk */ 1941558Srgrimes break; 1951558Srgrimes case 'w': 1961558Srgrimes if (op != UNSPEC) 1971558Srgrimes usage(); 1981558Srgrimes op = WRITE; 1991558Srgrimes break; 2001558Srgrimes case '?': 2011558Srgrimes default: 2021558Srgrimes usage(); 2031558Srgrimes } 2041558Srgrimes argc -= optind; 2051558Srgrimes argv += optind; 206114571Sphk 2071558Srgrimes if (argc < 1) 2081558Srgrimes usage(); 209115995Sphk if (labelsoffset < 0 || labeloffset < 0) 210115995Sphk errx(1, "a -m <architecture> option must be specified"); 2111558Srgrimes 212114569Sphk /* Figure out the names of the thing we're working on */ 213127650Sluigi if (is_file) { 214139856Srse specname = argv[0]; 215114569Sphk } else { 216183143Slulf specname = g_device_path(argv[0]); 217183143Slulf if (specname == NULL) { 218183143Slulf warn("unable to get correct path for %s", argv[0]); 219183143Slulf return(1); 220183143Slulf } 221183143Slulf fd = open(specname, O_RDONLY); 222183143Slulf if (fd < 0) { 223183143Slulf warn("error opening %s", specname); 224183143Slulf return(1); 225183143Slulf } 226183143Slulf pname = g_providername(fd); 227183143Slulf if (pname == NULL) { 228183487Slulf warn("error getting providername for %s", specname); 229183496Slulf close(fd); 230183143Slulf return(1); 231183143Slulf } 232183496Slulf close(fd); 2331558Srgrimes } 2341558Srgrimes 235114571Sphk if (installboot && op == UNSPEC) 236114571Sphk op = WRITEBOOT; 237114571Sphk else if (op == UNSPEC) 238114571Sphk op = READ; 239114571Sphk 2401558Srgrimes switch(op) { 2411558Srgrimes 24248957Sbillf case UNSPEC: 24348957Sbillf break; 24448957Sbillf 2451558Srgrimes case EDIT: 2461558Srgrimes if (argc != 1) 2471558Srgrimes usage(); 248114571Sphk readlabel(1); 249121222Sphk fixlabel(&lab); 250114571Sphk error = edit(); 2511558Srgrimes break; 2521558Srgrimes 2531558Srgrimes case READ: 2541558Srgrimes if (argc != 1) 2551558Srgrimes usage(); 256114571Sphk readlabel(1); 257114571Sphk display(stdout, NULL); 258114571Sphk error = checklabel(NULL); 2591558Srgrimes break; 2601558Srgrimes 2611558Srgrimes case RESTORE: 2621558Srgrimes if (argc != 2) 2631558Srgrimes usage(); 2641558Srgrimes if (!(t = fopen(argv[1], "r"))) 265114569Sphk err(4, "fopen %s", argv[1]); 266114571Sphk readlabel(0); 26737865Sbde if (!getasciilabel(t, &lab)) 26837865Sbde exit(1); 269114571Sphk error = writelabel(); 2701558Srgrimes break; 2711558Srgrimes 2721558Srgrimes case WRITE: 273114571Sphk if (argc == 2) 274114571Sphk name = argv[1]; 275114571Sphk else if (argc == 1) 276114571Sphk name = "auto"; 277114571Sphk else 2781558Srgrimes usage(); 279114571Sphk readlabel(0); 280114571Sphk makelabel(name, &lab); 281121222Sphk fixlabel(&lab); 282114571Sphk if (checklabel(NULL) == 0) 283114571Sphk error = writelabel(); 2841558Srgrimes break; 2851558Srgrimes 2861558Srgrimes case WRITEBOOT: 2871558Srgrimes 288114571Sphk readlabel(1); 289121222Sphk fixlabel(&lab); 2901558Srgrimes if (argc == 2) 291114571Sphk makelabel(argv[1], &lab); 292114571Sphk if (checklabel(NULL) == 0) 293114571Sphk error = writelabel(); 2941558Srgrimes break; 2951558Srgrimes } 2961558Srgrimes exit(error); 2971558Srgrimes} 2981558Srgrimes 299121222Sphkstatic void 300121222Sphkfixlabel(struct disklabel *lp) 301121222Sphk{ 302121222Sphk struct partition *dp; 303121222Sphk int i; 304121222Sphk 305174501Smarcel for (i = 0; i < lp->d_npartitions; i++) { 306121222Sphk if (i == RAW_PART) 307121222Sphk continue; 308121222Sphk if (lp->d_partitions[i].p_size) 309121222Sphk return; 310121222Sphk } 311121222Sphk 312121222Sphk dp = &lp->d_partitions[0]; 313121222Sphk dp->p_offset = BBSIZE / secsize; 314121222Sphk dp->p_size = lp->d_secperunit - dp->p_offset; 315121222Sphk} 316121222Sphk 3171558Srgrimes/* 318111286Sru * Construct a prototype disklabel from /etc/disktab. 3191558Srgrimes */ 320114571Sphkstatic void 321114571Sphkmakelabel(const char *type, struct disklabel *lp) 3221558Srgrimes{ 32392541Simp struct disklabel *dp; 32413550Sjoerg 32513550Sjoerg if (strcmp(type, "auto") == 0) 32613550Sjoerg dp = getvirginlabel(); 32713550Sjoerg else 32813544Sjoerg dp = getdiskbyname(type); 32936632Scharnier if (dp == NULL) 33036632Scharnier errx(1, "%s: unknown disk type", type); 3311558Srgrimes *lp = *dp; 3321558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 3331558Srgrimes} 3341558Srgrimes 335114571Sphkstatic void 336114571Sphkreadboot(void) 3371558Srgrimes{ 338209614Sjh int fd; 339114571Sphk struct stat st; 340114571Sphk 341114571Sphk if (xxboot == NULL) 342114571Sphk xxboot = "/boot/boot"; 343114571Sphk fd = open(xxboot, O_RDONLY); 344114571Sphk if (fd < 0) 345114571Sphk err(1, "cannot open %s", xxboot); 346114571Sphk fstat(fd, &st); 347219448Suqs if (st.st_size <= BBSIZE) { 348209614Sjh if (read(fd, bootarea, st.st_size) != st.st_size) 349114571Sphk err(1, "read error %s", xxboot); 350216095Skevlo close(fd); 351114571Sphk return; 352133347Sdes } 353114571Sphk errx(1, "boot code %s is wrong size", xxboot); 354114571Sphk} 355114571Sphk 356114571Sphkstatic int 357227270Saegeom_class_available(const char *name) 358211873Sjh{ 359211873Sjh struct gclass *class; 360211873Sjh struct gmesh mesh; 361211873Sjh int error; 362211873Sjh 363211873Sjh error = geom_gettree(&mesh); 364211873Sjh if (error != 0) 365211873Sjh errc(1, error, "Cannot get GEOM tree"); 366211873Sjh 367211873Sjh LIST_FOREACH(class, &mesh.lg_class, lg_class) { 368227270Sae if (strcmp(class->lg_name, name) == 0) { 369211873Sjh geom_deletetree(&mesh); 370211873Sjh return (1); 371211873Sjh } 372211873Sjh } 373211873Sjh 374211873Sjh geom_deletetree(&mesh); 375211873Sjh 376211873Sjh return (0); 377211873Sjh} 378211873Sjh 379211873Sjhstatic int 380114571Sphkwritelabel(void) 381114571Sphk{ 382211873Sjh int i, fd, serrno; 383114569Sphk struct gctl_req *grq; 384114569Sphk char const *errstr; 385114571Sphk struct disklabel *lp = &lab; 38638384Sdfr 38773034Sjwd if (disable_write) { 388229778Suqs warnx("write to disk label suppressed - label was as follows:"); 389114571Sphk display(stdout, NULL); 39073034Sjwd return (0); 391109878Sphk } 392109878Sphk 393109878Sphk lp->d_magic = DISKMAGIC; 394109878Sphk lp->d_magic2 = DISKMAGIC; 395109878Sphk lp->d_checksum = 0; 396109878Sphk lp->d_checksum = dkcksum(lp); 397114571Sphk if (installboot) 398114571Sphk readboot(); 399114673Sphk for (i = 0; i < lab.d_npartitions; i++) 400114673Sphk if (lab.d_partitions[i].p_size) 401196383Smarcel lab.d_partitions[i].p_offset += lba_offset; 402229049Ssobomax bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * lab.d_secsize, 403115696Sphk lp); 404114569Sphk 405114569Sphk fd = open(specname, O_RDWR); 406114569Sphk if (fd < 0) { 407127650Sluigi if (is_file) { 408127650Sluigi warn("cannot open file %s for writing label", specname); 409127650Sluigi return(1); 410211873Sjh } else 411211873Sjh serrno = errno; 412211873Sjh 413227270Sae if (geom_class_available("PART") != 0) { 414227296Sae /* 415227296Sae * Since we weren't able open provider for 416227270Sae * writing, then recommend user to use gpart(8). 417227270Sae */ 418227270Sae warnc(serrno, 419227270Sae "cannot open provider %s for writing label", 420227270Sae specname); 421227270Sae warnx("Try to use gpart(8)."); 422227270Sae return (1); 423227270Sae } 424227270Sae 425211873Sjh /* Give up if GEOM_BSD is not available. */ 426227270Sae if (geom_class_available("BSD") == 0) { 427211873Sjh warnc(serrno, "%s", specname); 428211873Sjh return (1); 429127650Sluigi } 430183143Slulf 431115624Sphk grq = gctl_get_handle(); 432115624Sphk gctl_ro_param(grq, "verb", -1, "write label"); 433114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 434183143Slulf gctl_ro_param(grq, "geom", -1, pname); 435133347Sdes gctl_ro_param(grq, "label", 148+16*8, 436229049Ssobomax bootarea + labeloffset + labelsoffset * lab.d_secsize); 437114569Sphk errstr = gctl_issue(grq); 438114571Sphk if (errstr != NULL) { 439114571Sphk warnx("%s", errstr); 440114571Sphk gctl_free(grq); 441114571Sphk return(1); 442114571Sphk } 443114569Sphk gctl_free(grq); 444114569Sphk if (installboot) { 445115624Sphk grq = gctl_get_handle(); 446115624Sphk gctl_ro_param(grq, "verb", -1, "write bootcode"); 447114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 448183143Slulf gctl_ro_param(grq, "geom", -1, pname); 449114571Sphk gctl_ro_param(grq, "bootcode", BBSIZE, bootarea); 450114569Sphk errstr = gctl_issue(grq); 451114571Sphk if (errstr != NULL) { 452114571Sphk warnx("%s", errstr); 453114571Sphk gctl_free(grq); 454114571Sphk return (1); 455114571Sphk } 456114569Sphk gctl_free(grq); 457114569Sphk } 458114569Sphk } else { 459114571Sphk if (write(fd, bootarea, bbsize) != bbsize) { 460114569Sphk warn("write %s", specname); 461114569Sphk close (fd); 462114569Sphk return (1); 463114569Sphk } 464114569Sphk close (fd); 465109878Sphk } 4661558Srgrimes return (0); 4671558Srgrimes} 4681558Srgrimes 469127650Sluigistatic void 470127650Sluigiget_file_parms(int f) 471127650Sluigi{ 472127650Sluigi int i; 473127650Sluigi struct stat sb; 474127650Sluigi 475127650Sluigi if (fstat(f, &sb) != 0) 476127650Sluigi err(4, "fstat failed"); 477127650Sluigi i = sb.st_mode & S_IFMT; 478127650Sluigi if (i != S_IFREG && i != S_IFLNK) 479127650Sluigi errx(4, "%s is not a valid file or link", specname); 480127650Sluigi secsize = DEV_BSIZE; 481127650Sluigi mediasize = sb.st_size; 482127650Sluigi} 483127650Sluigi 4841558Srgrimes/* 4851558Srgrimes * Fetch disklabel for disk. 4861558Srgrimes */ 487114571Sphkstatic int 488114571Sphkreadlabel(int flag) 4891558Srgrimes{ 490209614Sjh ssize_t nbytes; 491196383Smarcel uint32_t lba; 492114673Sphk int f, i; 493114569Sphk int error; 4941558Srgrimes 495114569Sphk f = open(specname, O_RDONLY); 496114569Sphk if (f < 0) 497215704Sbrucec err(1, "%s", specname); 498127650Sluigi if (is_file) 499127650Sluigi get_file_parms(f); 500183143Slulf else { 501183143Slulf mediasize = g_mediasize(f); 502183143Slulf secsize = g_sectorsize(f); 503183143Slulf if (secsize < 0 || mediasize < 0) 504183143Slulf err(4, "cannot get disk geometry"); 505115696Sphk } 506134973Sbrooks if (mediasize > (off_t)0xffffffff * secsize) 507134973Sbrooks errx(1, 508134973Sbrooks "disks with more than 2^32-1 sectors are not supported"); 509114550Sphk (void)lseek(f, (off_t)0, SEEK_SET); 510209614Sjh nbytes = read(f, bootarea, BBSIZE); 511209614Sjh if (nbytes == -1) 512114569Sphk err(4, "%s read", specname); 513209614Sjh if (nbytes != BBSIZE) 514209614Sjh errx(4, "couldn't read %d bytes from %s", BBSIZE, specname); 515114569Sphk close (f); 516115696Sphk error = bsd_disklabel_le_dec( 517115696Sphk bootarea + (labeloffset + labelsoffset * secsize), 518115696Sphk &lab, MAXPARTITIONS); 519114571Sphk if (flag && error) 520114571Sphk errx(1, "%s: no valid label found", specname); 521114673Sphk 522183143Slulf if (is_file) 523183143Slulf return(0); 524196383Smarcel 525196383Smarcel /* 526196383Smarcel * Compensate for absolute block addressing by finding the 527196383Smarcel * smallest partition offset and if the offset of the 'c' 528196383Smarcel * partition is equal to that, subtract it from all offsets. 529196383Smarcel */ 530196383Smarcel lba = ~0; 531196383Smarcel for (i = 0; i < lab.d_npartitions; i++) { 532196383Smarcel if (lab.d_partitions[i].p_size) 533196383Smarcel lba = MIN(lba, lab.d_partitions[i].p_offset); 534114673Sphk } 535196383Smarcel if (lba != 0 && lab.d_partitions[RAW_PART].p_offset == lba) { 536196383Smarcel for (i = 0; i < lab.d_npartitions; i++) { 537114673Sphk if (lab.d_partitions[i].p_size) 538196383Smarcel lab.d_partitions[i].p_offset -= lba; 539196383Smarcel } 540196383Smarcel /* 541196383Smarcel * Save the offset so that we can write the label 542196383Smarcel * back with absolute block addresses. 543196383Smarcel */ 544196383Smarcel lba_offset = lba; 545196383Smarcel } 546114571Sphk return (error); 5471558Srgrimes} 5481558Srgrimes 5491558Srgrimes 550114571Sphkstatic void 55192541Simpdisplay(FILE *f, const struct disklabel *lp) 5521558Srgrimes{ 55392541Simp int i, j; 55492541Simp const struct partition *pp; 5551558Srgrimes 556114571Sphk if (lp == NULL) 557114571Sphk lp = &lab; 558114571Sphk 5591558Srgrimes fprintf(f, "# %s:\n", specname); 560114574Sphk if (allfields) { 561114574Sphk if (lp->d_type < DKMAXTYPES) 562114574Sphk fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 563114574Sphk else 564114574Sphk fprintf(f, "type: %u\n", lp->d_type); 565114574Sphk fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 566114574Sphk lp->d_typename); 567114574Sphk fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 568114574Sphk lp->d_packname); 569114574Sphk fprintf(f, "flags:"); 570114574Sphk if (lp->d_flags & D_REMOVABLE) 571114574Sphk fprintf(f, " removeable"); 572114574Sphk if (lp->d_flags & D_ECC) 573114574Sphk fprintf(f, " ecc"); 574114574Sphk if (lp->d_flags & D_BADSECT) 575114574Sphk fprintf(f, " badsect"); 576114574Sphk fprintf(f, "\n"); 577114574Sphk fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 578114574Sphk fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 579114574Sphk fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 580114574Sphk fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 581114574Sphk fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 582114574Sphk fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 583114574Sphk fprintf(f, "rpm: %u\n", lp->d_rpm); 584114574Sphk fprintf(f, "interleave: %u\n", lp->d_interleave); 585114574Sphk fprintf(f, "trackskew: %u\n", lp->d_trackskew); 586114574Sphk fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 587114574Sphk fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 588114574Sphk (u_long)lp->d_headswitch); 589114574Sphk fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 590114574Sphk (u_long)lp->d_trkseek); 591114574Sphk fprintf(f, "drivedata: "); 592114574Sphk for (i = NDDATA - 1; i >= 0; i--) 593114574Sphk if (lp->d_drivedata[i]) 594114574Sphk break; 595114574Sphk if (i < 0) 596114574Sphk i = 0; 597114574Sphk for (j = 0; j <= i; j++) 598114574Sphk fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 599114574Sphk fprintf(f, "\n\n"); 600114574Sphk } 601114574Sphk fprintf(f, "%u partitions:\n", lp->d_npartitions); 6021558Srgrimes fprintf(f, 603219449Suqs "# size offset fstype [fsize bsize bps/cpg]\n"); 6041558Srgrimes pp = lp->d_partitions; 6051558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 6061558Srgrimes if (pp->p_size) { 607219449Suqs fprintf(f, " %c: %10lu %10lu ", 'a' + i, 60837234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 609107041Sjulian if (pp->p_fstype < FSMAXTYPES) 6101558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 6111558Srgrimes else 6121558Srgrimes fprintf(f, "%8d", pp->p_fstype); 6131558Srgrimes switch (pp->p_fstype) { 6141558Srgrimes 6151558Srgrimes case FS_UNUSED: /* XXX */ 616219449Suqs fprintf(f, " %5lu %5lu %2s", 61737234Sbde (u_long)pp->p_fsize, 61837234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 6191558Srgrimes break; 6201558Srgrimes 6211558Srgrimes case FS_BSDFFS: 622219449Suqs fprintf(f, " %5lu %5lu %5u", 62337234Sbde (u_long)pp->p_fsize, 62437234Sbde (u_long)(pp->p_fsize * pp->p_frag), 6251558Srgrimes pp->p_cpg); 6261558Srgrimes break; 6271558Srgrimes 6285393Sgibbs case FS_BSDLFS: 62937234Sbde fprintf(f, " %5lu %5lu %5d", 63037234Sbde (u_long)pp->p_fsize, 63137234Sbde (u_long)(pp->p_fsize * pp->p_frag), 6325393Sgibbs pp->p_cpg); 6335393Sgibbs break; 6345393Sgibbs 6351558Srgrimes default: 6361558Srgrimes fprintf(f, "%20.20s", ""); 6371558Srgrimes break; 6381558Srgrimes } 639114574Sphk if (i == RAW_PART) { 640114574Sphk fprintf(f, " # \"raw\" part, don't edit"); 641114574Sphk } 642114571Sphk fprintf(f, "\n"); 6431558Srgrimes } 6441558Srgrimes } 6451558Srgrimes fflush(f); 6461558Srgrimes} 6471558Srgrimes 648114571Sphkstatic int 649114571Sphkedit(void) 6501558Srgrimes{ 65192541Simp int c, fd; 6521558Srgrimes struct disklabel label; 65324180Simp FILE *fp; 6541558Srgrimes 65524180Simp if ((fd = mkstemp(tmpfil)) == -1 || 65624180Simp (fp = fdopen(fd, "w")) == NULL) { 65736632Scharnier warnx("can't create %s", tmpfil); 6581558Srgrimes return (1); 6591558Srgrimes } 660114571Sphk display(fp, NULL); 66124180Simp fclose(fp); 6621558Srgrimes for (;;) { 6631558Srgrimes if (!editit()) 6641558Srgrimes break; 66524180Simp fp = fopen(tmpfil, "r"); 66624180Simp if (fp == NULL) { 66736632Scharnier warnx("can't reopen %s for reading", tmpfil); 6681558Srgrimes break; 6691558Srgrimes } 6701558Srgrimes bzero((char *)&label, sizeof(label)); 671114571Sphk c = getasciilabel(fp, &label); 672114571Sphk fclose(fp); 673114571Sphk if (c) { 674114571Sphk lab = label; 675114571Sphk if (writelabel() == 0) { 6761558Srgrimes (void) unlink(tmpfil); 6771558Srgrimes return (0); 6781558Srgrimes } 6791558Srgrimes } 680114571Sphk printf("re-edit the label? [y]: "); 681114571Sphk fflush(stdout); 6821558Srgrimes c = getchar(); 6831558Srgrimes if (c != EOF && c != (int)'\n') 6841558Srgrimes while (getchar() != (int)'\n') 6851558Srgrimes ; 6861558Srgrimes if (c == (int)'n') 6871558Srgrimes break; 6881558Srgrimes } 6891558Srgrimes (void) unlink(tmpfil); 6901558Srgrimes return (1); 6911558Srgrimes} 6921558Srgrimes 693114571Sphkstatic int 69492541Simpeditit(void) 6951558Srgrimes{ 69692541Simp int pid, xpid; 69799365Smarkm int locstat, omask; 69899365Smarkm const char *ed; 699208132Skevlo uid_t uid; 700208132Skevlo gid_t gid; 7011558Srgrimes 7021558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 7031558Srgrimes while ((pid = fork()) < 0) { 7041558Srgrimes if (errno == EPROCLIM) { 70536632Scharnier warnx("you have too many processes"); 7061558Srgrimes return(0); 7071558Srgrimes } 7081558Srgrimes if (errno != EAGAIN) { 70936632Scharnier warn("fork"); 7101558Srgrimes return(0); 7111558Srgrimes } 7121558Srgrimes sleep(1); 7131558Srgrimes } 7141558Srgrimes if (pid == 0) { 7151558Srgrimes sigsetmask(omask); 716208132Skevlo gid = getgid(); 717208132Skevlo if (setresgid(gid, gid, gid) == -1) 718208132Skevlo err(1, "setresgid"); 719208132Skevlo uid = getuid(); 720208132Skevlo if (setresuid(uid, uid, uid) == -1) 721208132Skevlo err(1, "setresuid"); 7221558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 7231558Srgrimes ed = DEFEDITOR; 72479452Sbrian execlp(ed, ed, tmpfil, (char *)0); 72536632Scharnier err(1, "%s", ed); 7261558Srgrimes } 72799365Smarkm while ((xpid = wait(&locstat)) >= 0) 7281558Srgrimes if (xpid == pid) 7291558Srgrimes break; 7301558Srgrimes sigsetmask(omask); 73199365Smarkm return(!locstat); 7321558Srgrimes} 7331558Srgrimes 734114571Sphkstatic char * 73592541Simpskip(char *cp) 7361558Srgrimes{ 7371558Srgrimes 7381558Srgrimes while (*cp != '\0' && isspace(*cp)) 7391558Srgrimes cp++; 7401558Srgrimes if (*cp == '\0' || *cp == '#') 74192541Simp return (NULL); 7421558Srgrimes return (cp); 7431558Srgrimes} 7441558Srgrimes 745114571Sphkstatic char * 74692541Simpword(char *cp) 7471558Srgrimes{ 74892541Simp char c; 7491558Srgrimes 7501558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 7511558Srgrimes cp++; 7521558Srgrimes if ((c = *cp) != '\0') { 7531558Srgrimes *cp++ = '\0'; 7541558Srgrimes if (c != '#') 7551558Srgrimes return (skip(cp)); 7561558Srgrimes } 75792541Simp return (NULL); 7581558Srgrimes} 7591558Srgrimes 7601558Srgrimes/* 7611558Srgrimes * Read an ascii label in from fd f, 7621558Srgrimes * in the same format as that put out by display(), 7631558Srgrimes * and fill in lp. 7641558Srgrimes */ 765114571Sphkstatic int 76692541Simpgetasciilabel(FILE *f, struct disklabel *lp) 7671558Srgrimes{ 768211342Sjh char *cp, *endp; 76994065Sphk const char **cpp; 770107041Sjulian u_int part; 77194065Sphk char *tp, line[BUFSIZ]; 772107041Sjulian u_long v; 773107041Sjulian int lineno = 0, errors = 0; 77492541Simp int i; 7751558Srgrimes 776114862Sphk makelabel("auto", lp); 777109378Sdes bzero(&part_set, sizeof(part_set)); 778109378Sdes bzero(&part_size_type, sizeof(part_size_type)); 779109378Sdes bzero(&part_offset_type, sizeof(part_offset_type)); 7801558Srgrimes lp->d_bbsize = BBSIZE; /* XXX */ 78196475Sphk lp->d_sbsize = 0; /* XXX */ 7821558Srgrimes while (fgets(line, sizeof(line) - 1, f)) { 7831558Srgrimes lineno++; 784298193Saraujo if ((cp = strchr(line,'\n')) != NULL) 7851558Srgrimes *cp = '\0'; 7861558Srgrimes cp = skip(line); 7871558Srgrimes if (cp == NULL) 7881558Srgrimes continue; 789229403Sed tp = strchr(cp, ':'); 7901558Srgrimes if (tp == NULL) { 7911558Srgrimes fprintf(stderr, "line %d: syntax error\n", lineno); 7921558Srgrimes errors++; 7931558Srgrimes continue; 7941558Srgrimes } 7951558Srgrimes *tp++ = '\0', tp = skip(tp); 796114571Sphk if (!strcmp(cp, "type")) { 7971558Srgrimes if (tp == NULL) 79899365Smarkm tp = unknown; 7991558Srgrimes cpp = dktypenames; 8001558Srgrimes for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 801114571Sphk if (*cpp && !strcmp(*cpp, tp)) { 8021558Srgrimes lp->d_type = cpp - dktypenames; 80397855Siedowse break; 8041558Srgrimes } 80597855Siedowse if (cpp < &dktypenames[DKMAXTYPES]) 80697855Siedowse continue; 807211342Sjh errno = 0; 808211342Sjh v = strtoul(tp, &endp, 10); 809211342Sjh if (errno != 0 || *endp != '\0') 810211342Sjh v = DKMAXTYPES; 811107041Sjulian if (v >= DKMAXTYPES) 812107041Sjulian fprintf(stderr, "line %d:%s %lu\n", lineno, 8131558Srgrimes "Warning, unknown disk type", v); 814211342Sjh else 815211342Sjh lp->d_type = v; 8161558Srgrimes continue; 8171558Srgrimes } 818114571Sphk if (!strcmp(cp, "flags")) { 8191558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 8201558Srgrimes tp = word(cp); 821114571Sphk if (!strcmp(cp, "removeable")) 8221558Srgrimes v |= D_REMOVABLE; 823114571Sphk else if (!strcmp(cp, "ecc")) 8241558Srgrimes v |= D_ECC; 825114571Sphk else if (!strcmp(cp, "badsect")) 8261558Srgrimes v |= D_BADSECT; 8271558Srgrimes else { 8281558Srgrimes fprintf(stderr, 8291558Srgrimes "line %d: %s: bad flag\n", 8301558Srgrimes lineno, cp); 8311558Srgrimes errors++; 8321558Srgrimes } 8331558Srgrimes } 8341558Srgrimes lp->d_flags = v; 8351558Srgrimes continue; 8361558Srgrimes } 837114571Sphk if (!strcmp(cp, "drivedata")) { 8381558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 839107041Sjulian lp->d_drivedata[i++] = strtoul(cp, NULL, 10); 8401558Srgrimes tp = word(cp); 8411558Srgrimes } 8421558Srgrimes continue; 8431558Srgrimes } 844107041Sjulian if (sscanf(cp, "%lu partitions", &v) == 1) { 845227262Sae if (v > MAXPARTITIONS) { 8461558Srgrimes fprintf(stderr, 8471558Srgrimes "line %d: bad # of partitions\n", lineno); 8481558Srgrimes lp->d_npartitions = MAXPARTITIONS; 8491558Srgrimes errors++; 850227248Sae } else if (v < DEFPARTITIONS) { 851227248Sae fprintf(stderr, 852227248Sae "line %d: bad # of partitions\n", lineno); 853227248Sae lp->d_npartitions = DEFPARTITIONS; 854227248Sae errors++; 8551558Srgrimes } else 8561558Srgrimes lp->d_npartitions = v; 8571558Srgrimes continue; 8581558Srgrimes } 8591558Srgrimes if (tp == NULL) 86099365Smarkm tp = blank; 861114571Sphk if (!strcmp(cp, "disk")) { 8621558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 8631558Srgrimes continue; 8641558Srgrimes } 865114571Sphk if (!strcmp(cp, "label")) { 8661558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 8671558Srgrimes continue; 8681558Srgrimes } 869114571Sphk if (!strcmp(cp, "bytes/sector")) { 870107041Sjulian v = strtoul(tp, NULL, 10); 871107041Sjulian if (v == 0 || (v % DEV_BSIZE) != 0) { 8721558Srgrimes fprintf(stderr, 8731558Srgrimes "line %d: %s: bad sector size\n", 8741558Srgrimes lineno, tp); 8751558Srgrimes errors++; 8761558Srgrimes } else 8771558Srgrimes lp->d_secsize = v; 8781558Srgrimes continue; 8791558Srgrimes } 880114571Sphk if (!strcmp(cp, "sectors/track")) { 881107041Sjulian v = strtoul(tp, NULL, 10); 882107041Sjulian#if (ULONG_MAX != 0xffffffffUL) 883133347Sdes if (v == 0 || v > 0xffffffff) 884107041Sjulian#else 885133347Sdes if (v == 0) 886107041Sjulian#endif 887133347Sdes { 8881558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8891558Srgrimes lineno, tp, cp); 8901558Srgrimes errors++; 8911558Srgrimes } else 8921558Srgrimes lp->d_nsectors = v; 8931558Srgrimes continue; 8941558Srgrimes } 895114571Sphk if (!strcmp(cp, "sectors/cylinder")) { 896107041Sjulian v = strtoul(tp, NULL, 10); 897107041Sjulian if (v == 0) { 8981558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8991558Srgrimes lineno, tp, cp); 9001558Srgrimes errors++; 9011558Srgrimes } else 9021558Srgrimes lp->d_secpercyl = v; 9031558Srgrimes continue; 9041558Srgrimes } 905114571Sphk if (!strcmp(cp, "tracks/cylinder")) { 906107041Sjulian v = strtoul(tp, NULL, 10); 907107041Sjulian if (v == 0) { 9081558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9091558Srgrimes lineno, tp, cp); 9101558Srgrimes errors++; 9111558Srgrimes } else 9121558Srgrimes lp->d_ntracks = v; 9131558Srgrimes continue; 9141558Srgrimes } 915114571Sphk if (!strcmp(cp, "cylinders")) { 916107041Sjulian v = strtoul(tp, NULL, 10); 917107041Sjulian if (v == 0) { 9181558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9191558Srgrimes lineno, tp, cp); 9201558Srgrimes errors++; 9211558Srgrimes } else 9221558Srgrimes lp->d_ncylinders = v; 9231558Srgrimes continue; 9241558Srgrimes } 925114571Sphk if (!strcmp(cp, "sectors/unit")) { 926107041Sjulian v = strtoul(tp, NULL, 10); 927107041Sjulian if (v == 0) { 9286643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 9296643Sbde lineno, tp, cp); 9306643Sbde errors++; 9316643Sbde } else 9326643Sbde lp->d_secperunit = v; 9336643Sbde continue; 9346643Sbde } 935114571Sphk if (!strcmp(cp, "rpm")) { 936107041Sjulian v = strtoul(tp, NULL, 10); 937107041Sjulian if (v == 0 || v > USHRT_MAX) { 9381558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9391558Srgrimes lineno, tp, cp); 9401558Srgrimes errors++; 9411558Srgrimes } else 9421558Srgrimes lp->d_rpm = v; 9431558Srgrimes continue; 9441558Srgrimes } 945114571Sphk if (!strcmp(cp, "interleave")) { 946107041Sjulian v = strtoul(tp, NULL, 10); 947107041Sjulian if (v == 0 || v > USHRT_MAX) { 9481558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9491558Srgrimes lineno, tp, cp); 9501558Srgrimes errors++; 9511558Srgrimes } else 9521558Srgrimes lp->d_interleave = v; 9531558Srgrimes continue; 9541558Srgrimes } 955114571Sphk if (!strcmp(cp, "trackskew")) { 956107041Sjulian v = strtoul(tp, NULL, 10); 957107041Sjulian if (v > USHRT_MAX) { 9581558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9591558Srgrimes lineno, tp, cp); 9601558Srgrimes errors++; 9611558Srgrimes } else 9621558Srgrimes lp->d_trackskew = v; 9631558Srgrimes continue; 9641558Srgrimes } 965114571Sphk if (!strcmp(cp, "cylinderskew")) { 966107041Sjulian v = strtoul(tp, NULL, 10); 967107041Sjulian if (v > USHRT_MAX) { 9681558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9691558Srgrimes lineno, tp, cp); 9701558Srgrimes errors++; 9711558Srgrimes } else 9721558Srgrimes lp->d_cylskew = v; 9731558Srgrimes continue; 9741558Srgrimes } 975114571Sphk if (!strcmp(cp, "headswitch")) { 976107041Sjulian v = strtoul(tp, NULL, 10); 977107041Sjulian lp->d_headswitch = v; 9781558Srgrimes continue; 9791558Srgrimes } 980114571Sphk if (!strcmp(cp, "track-to-track seek")) { 981107041Sjulian v = strtoul(tp, NULL, 10); 982107041Sjulian lp->d_trkseek = v; 9831558Srgrimes continue; 9841558Srgrimes } 98573034Sjwd /* the ':' was removed above */ 98697534Siedowse if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') { 98797534Siedowse fprintf(stderr, 98897534Siedowse "line %d: %s: Unknown disklabel field\n", lineno, 98997534Siedowse cp); 99097534Siedowse errors++; 99197534Siedowse continue; 99297534Siedowse } 99397534Siedowse 99497534Siedowse /* Process a partition specification line. */ 99597534Siedowse part = *cp - 'a'; 99697534Siedowse if (part >= lp->d_npartitions) { 99797534Siedowse fprintf(stderr, 99897534Siedowse "line %d: partition name out of range a-%c: %s\n", 99997534Siedowse lineno, 'a' + lp->d_npartitions - 1, cp); 100097534Siedowse errors++; 100197534Siedowse continue; 100297534Siedowse } 100397534Siedowse part_set[part] = 1; 100497534Siedowse 100597534Siedowse if (getasciipartspec(tp, lp, part, lineno) != 0) { 100697534Siedowse errors++; 100797534Siedowse break; 100897534Siedowse } 100997534Siedowse } 101097534Siedowse errors += checklabel(lp); 101197534Siedowse return (errors == 0); 101297534Siedowse} 101397534Siedowse 101497534Siedowse#define NXTNUM(n) do { \ 10153111Spst if (tp == NULL) { \ 10163111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 101797534Siedowse return (1); \ 10183111Spst } else { \ 10193111Spst cp = tp, tp = word(cp); \ 1020107041Sjulian (n) = strtoul(cp, NULL, 10); \ 10213111Spst } \ 102297534Siedowse} while (0) 102397534Siedowse 102473034Sjwd/* retain 1 character following number */ 102597534Siedowse#define NXTWORD(w,n) do { \ 102673034Sjwd if (tp == NULL) { \ 102773034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 102897534Siedowse return (1); \ 102973034Sjwd } else { \ 1030133347Sdes char *tmp; \ 103173034Sjwd cp = tp, tp = word(cp); \ 1032133347Sdes (n) = strtoul(cp, &tmp, 10); \ 103373034Sjwd if (tmp) (w) = *tmp; \ 103473034Sjwd } \ 103597534Siedowse} while (0) 10361558Srgrimes 103797534Siedowse/* 103897534Siedowse * Read a partition line into partition `part' in the specified disklabel. 103997534Siedowse * Return 0 on success, 1 on failure. 104097534Siedowse */ 1041114571Sphkstatic int 104297534Siedowsegetasciipartspec(char *tp, struct disklabel *lp, int part, int lineno) 104397534Siedowse{ 104497534Siedowse struct partition *pp; 1045211342Sjh char *cp, *endp; 104697534Siedowse const char **cpp; 1047107041Sjulian u_long v; 10481558Srgrimes 104997534Siedowse pp = &lp->d_partitions[part]; 105097534Siedowse cp = NULL; 10511558Srgrimes 105297534Siedowse v = 0; 105397534Siedowse NXTWORD(part_size_type[part],v); 1054107041Sjulian if (v == 0 && part_size_type[part] != '*') { 1055107041Sjulian fprintf(stderr, 1056107041Sjulian "line %d: %s: bad partition size\n", lineno, cp); 105797534Siedowse return (1); 105897534Siedowse } 105997534Siedowse pp->p_size = v; 106097534Siedowse 106197534Siedowse v = 0; 106297534Siedowse NXTWORD(part_offset_type[part],v); 1063107041Sjulian if (v == 0 && part_offset_type[part] != '*' && 1064107041Sjulian part_offset_type[part] != '\0') { 1065107041Sjulian fprintf(stderr, 1066107041Sjulian "line %d: %s: bad partition offset\n", lineno, cp); 106797534Siedowse return (1); 106897534Siedowse } 106997534Siedowse pp->p_offset = v; 1070112945Syar if (tp == NULL) { 1071112945Syar fprintf(stderr, "line %d: missing file system type\n", lineno); 1072112945Syar return (1); 1073112945Syar } 107497534Siedowse cp = tp, tp = word(cp); 107597534Siedowse for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) 1076114571Sphk if (*cpp && !strcmp(*cpp, cp)) 107797534Siedowse break; 107897534Siedowse if (*cpp != NULL) { 107997534Siedowse pp->p_fstype = cpp - fstypenames; 108097534Siedowse } else { 1081211342Sjh if (isdigit(*cp)) { 1082211342Sjh errno = 0; 1083211342Sjh v = strtoul(cp, &endp, 10); 1084211342Sjh if (errno != 0 || *endp != '\0') 1085211342Sjh v = FSMAXTYPES; 1086211342Sjh } else 108797534Siedowse v = FSMAXTYPES; 1088107041Sjulian if (v >= FSMAXTYPES) { 108997534Siedowse fprintf(stderr, 1090102231Strhodes "line %d: Warning, unknown file system type %s\n", 109197534Siedowse lineno, cp); 109297534Siedowse v = FS_UNUSED; 109397534Siedowse } 109497534Siedowse pp->p_fstype = v; 109597534Siedowse } 109697534Siedowse 109797534Siedowse switch (pp->p_fstype) { 109897534Siedowse case FS_UNUSED: 1099120821Siedowse case FS_BSDFFS: 1100120821Siedowse case FS_BSDLFS: 1101120821Siedowse /* accept defaults for fsize/frag/cpg */ 110297534Siedowse if (tp) { 110397534Siedowse NXTNUM(pp->p_fsize); 110497534Siedowse if (pp->p_fsize == 0) 110597534Siedowse break; 110697534Siedowse NXTNUM(v); 110797534Siedowse pp->p_frag = v / pp->p_fsize; 1108120821Siedowse if (tp != NULL) 1109120821Siedowse NXTNUM(pp->p_cpg); 111097534Siedowse } 111197534Siedowse /* else default to 0's */ 111297534Siedowse break; 111397534Siedowse default: 111497534Siedowse break; 11151558Srgrimes } 111697534Siedowse return (0); 11171558Srgrimes} 11181558Srgrimes 11191558Srgrimes/* 11201558Srgrimes * Check disklabel for errors and fill in 11211558Srgrimes * derived fields according to supplied values. 11221558Srgrimes */ 1123114571Sphkstatic int 112492541Simpchecklabel(struct disklabel *lp) 11251558Srgrimes{ 112692541Simp struct partition *pp; 11271558Srgrimes int i, errors = 0; 11281558Srgrimes char part; 1129149061Siedowse u_long base_offset, needed, total_size, total_percent, current_offset; 1130149061Siedowse long free_space; 113173034Sjwd int seen_default_offset; 113273034Sjwd int hog_part; 113373034Sjwd int j; 113473034Sjwd struct partition *pp2; 11351558Srgrimes 1136114571Sphk if (lp == NULL) 1137114571Sphk lp = &lab; 1138114571Sphk 1139114574Sphk if (allfields) { 1140114574Sphk 1141114574Sphk if (lp->d_secsize == 0) { 1142114574Sphk fprintf(stderr, "sector size 0\n"); 1143114574Sphk return (1); 1144114574Sphk } 1145114574Sphk if (lp->d_nsectors == 0) { 1146114574Sphk fprintf(stderr, "sectors/track 0\n"); 1147114574Sphk return (1); 1148114574Sphk } 1149114574Sphk if (lp->d_ntracks == 0) { 1150114574Sphk fprintf(stderr, "tracks/cylinder 0\n"); 1151114574Sphk return (1); 1152114574Sphk } 1153114574Sphk if (lp->d_ncylinders == 0) { 1154114574Sphk fprintf(stderr, "cylinders/unit 0\n"); 1155114574Sphk errors++; 1156114574Sphk } 1157114574Sphk if (lp->d_rpm == 0) 1158114574Sphk warnx("revolutions/minute 0"); 1159114574Sphk if (lp->d_secpercyl == 0) 1160114574Sphk lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1161114574Sphk if (lp->d_secperunit == 0) 1162114574Sphk lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1163114574Sphk if (lp->d_bbsize == 0) { 1164114574Sphk fprintf(stderr, "boot block size 0\n"); 1165114574Sphk errors++; 1166114574Sphk } else if (lp->d_bbsize % lp->d_secsize) 1167114574Sphk warnx("boot block size %% sector-size != 0"); 1168227248Sae if (lp->d_npartitions > MAXPARTITIONS) { 1169114574Sphk warnx("number of partitions (%lu) > MAXPARTITIONS (%d)", 1170114574Sphk (u_long)lp->d_npartitions, MAXPARTITIONS); 1171227248Sae errors++; 1172227248Sae } 1173227248Sae if (lp->d_npartitions < DEFPARTITIONS) { 1174227248Sae warnx("number of partitions (%lu) < DEFPARTITIONS (%d)", 1175227248Sae (u_long)lp->d_npartitions, DEFPARTITIONS); 1176227248Sae errors++; 1177227248Sae } 1178114574Sphk } else { 1179114574Sphk struct disklabel *vl; 1180114574Sphk 1181114574Sphk vl = getvirginlabel(); 1182227248Sae if (lp->d_secsize == 0) 1183227248Sae lp->d_secsize = vl->d_secsize; 1184227248Sae if (lp->d_nsectors == 0) 1185227248Sae lp->d_nsectors = vl->d_nsectors; 1186227248Sae if (lp->d_ntracks == 0) 1187227248Sae lp->d_ntracks = vl->d_ntracks; 1188227248Sae if (lp->d_ncylinders == 0) 1189227248Sae lp->d_ncylinders = vl->d_ncylinders; 1190227248Sae if (lp->d_rpm == 0) 1191227248Sae lp->d_rpm = vl->d_rpm; 1192227248Sae if (lp->d_interleave == 0) 1193227248Sae lp->d_interleave = vl->d_interleave; 1194227248Sae if (lp->d_secpercyl == 0) 1195227248Sae lp->d_secpercyl = vl->d_secpercyl; 1196234122Sae if (lp->d_secperunit == 0 || 1197234122Sae lp->d_secperunit > vl->d_secperunit) 1198227248Sae lp->d_secperunit = vl->d_secperunit; 1199227248Sae if (lp->d_bbsize == 0) 1200227248Sae lp->d_bbsize = vl->d_bbsize; 1201227262Sae if (lp->d_npartitions < DEFPARTITIONS || 1202227248Sae lp->d_npartitions > MAXPARTITIONS) 1203227248Sae lp->d_npartitions = vl->d_npartitions; 12041558Srgrimes } 120573034Sjwd 1206114574Sphk 120773034Sjwd /* first allocate space to the partitions, then offsets */ 120873034Sjwd total_size = 0; /* in sectors */ 120973034Sjwd total_percent = 0; /* in percent */ 121073034Sjwd hog_part = -1; 121173034Sjwd /* find all fixed partitions */ 12121558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 121373034Sjwd pp = &lp->d_partitions[i]; 121473034Sjwd if (part_set[i]) { 121573034Sjwd if (part_size_type[i] == '*') { 121694065Sphk if (i == RAW_PART) { 121773034Sjwd pp->p_size = lp->d_secperunit; 121873034Sjwd } else { 121973034Sjwd if (hog_part != -1) 1220114574Sphk warnx("Too many '*' partitions (%c and %c)", 122173034Sjwd hog_part + 'a',i + 'a'); 122273034Sjwd else 122373034Sjwd hog_part = i; 122473034Sjwd } 122573034Sjwd } else { 122673573Simp off_t size; 122773034Sjwd 122873034Sjwd size = pp->p_size; 122973034Sjwd switch (part_size_type[i]) { 123073034Sjwd case '%': 123173034Sjwd total_percent += size; 123273034Sjwd break; 1233133348Sdes case 't': 1234133348Sdes case 'T': 1235133348Sdes size *= 1024ULL; 1236133348Sdes /* FALLTHROUGH */ 1237133348Sdes case 'g': 1238133348Sdes case 'G': 1239133348Sdes size *= 1024ULL; 1240133348Sdes /* FALLTHROUGH */ 1241133348Sdes case 'm': 1242133348Sdes case 'M': 1243133348Sdes size *= 1024ULL; 1244133348Sdes /* FALLTHROUGH */ 124573034Sjwd case 'k': 124673034Sjwd case 'K': 124773573Simp size *= 1024ULL; 124873034Sjwd break; 124973034Sjwd case '\0': 125073034Sjwd break; 125173034Sjwd default: 1252133384Sdes warnx("unknown multiplier suffix '%c' for partition %c (should be K, M, G or T)", 1253133348Sdes part_size_type[i], i + 'a'); 125473034Sjwd break; 125573034Sjwd } 125673034Sjwd /* don't count %'s yet */ 125773034Sjwd if (part_size_type[i] != '%') { 125873034Sjwd /* 125973034Sjwd * for all not in sectors, convert to 126073034Sjwd * sectors 126173034Sjwd */ 126273034Sjwd if (part_size_type[i] != '\0') { 126373034Sjwd if (size % lp->d_secsize != 0) 1264114574Sphk warnx("partition %c not an integer number of sectors", 126573034Sjwd i + 'a'); 126673034Sjwd size /= lp->d_secsize; 126773034Sjwd pp->p_size = size; 126873034Sjwd } 126973034Sjwd /* else already in sectors */ 127094065Sphk if (i != RAW_PART) 127173034Sjwd total_size += size; 127273034Sjwd } 127373034Sjwd } 127473034Sjwd } 127573034Sjwd } 1276149061Siedowse 1277149061Siedowse /* Find out the total free space, excluding the boot block area. */ 1278149061Siedowse base_offset = BBSIZE / secsize; 1279149061Siedowse free_space = 0; 1280149061Siedowse for (i = 0; i < lp->d_npartitions; i++) { 1281149061Siedowse pp = &lp->d_partitions[i]; 1282149061Siedowse if (!part_set[i] || i == RAW_PART || 1283149061Siedowse part_size_type[i] == '%' || part_size_type[i] == '*') 1284149061Siedowse continue; 1285149061Siedowse if (pp->p_offset > base_offset) 1286149061Siedowse free_space += pp->p_offset - base_offset; 1287149061Siedowse if (pp->p_offset + pp->p_size > base_offset) 1288149061Siedowse base_offset = pp->p_offset + pp->p_size; 1289149061Siedowse } 1290149061Siedowse if (base_offset < lp->d_secperunit) 1291149061Siedowse free_space += lp->d_secperunit - base_offset; 1292149061Siedowse 129373034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 129473034Sjwd if (total_percent != 0) { 129573034Sjwd if (total_percent > 100) { 129694065Sphk fprintf(stderr,"total percentage %lu is greater than 100\n", 129773034Sjwd total_percent); 129873034Sjwd errors++; 129973034Sjwd } 130073034Sjwd 130173034Sjwd if (free_space > 0) { 130273034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 130373034Sjwd pp = &lp->d_partitions[i]; 130473034Sjwd if (part_set[i] && part_size_type[i] == '%') { 130573034Sjwd /* careful of overflows! and integer roundoff */ 130673034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 130773034Sjwd total_size += pp->p_size; 130873034Sjwd 130973034Sjwd /* FIX we can lose a sector or so due to roundoff per 131073034Sjwd partition. A more complex algorithm could avoid that */ 131173034Sjwd } 131273034Sjwd } 131373034Sjwd } else { 131473034Sjwd fprintf(stderr, 131594065Sphk "%ld sectors available to give to '*' and '%%' partitions\n", 131673034Sjwd free_space); 131773034Sjwd errors++; 131873034Sjwd /* fix? set all % partitions to size 0? */ 131973034Sjwd } 132073034Sjwd } 132173034Sjwd /* give anything remaining to the hog partition */ 132273034Sjwd if (hog_part != -1) { 1323149061Siedowse /* 1324149061Siedowse * Find the range of offsets usable by '*' partitions around 1325149061Siedowse * the hog partition and how much space they need. 1326149061Siedowse */ 1327149061Siedowse needed = 0; 1328149061Siedowse base_offset = BBSIZE / secsize; 1329149061Siedowse for (i = hog_part - 1; i >= 0; i--) { 1330149061Siedowse pp = &lp->d_partitions[i]; 1331149061Siedowse if (!part_set[i] || i == RAW_PART) 1332149061Siedowse continue; 1333149061Siedowse if (part_offset_type[i] == '*') { 1334149061Siedowse needed += pp->p_size; 1335149061Siedowse continue; 1336149061Siedowse } 1337149061Siedowse base_offset = pp->p_offset + pp->p_size; 1338149061Siedowse break; 1339149061Siedowse } 1340149061Siedowse current_offset = lp->d_secperunit; 1341149061Siedowse for (i = lp->d_npartitions - 1; i > hog_part; i--) { 1342149061Siedowse pp = &lp->d_partitions[i]; 1343149061Siedowse if (!part_set[i] || i == RAW_PART) 1344149061Siedowse continue; 1345149061Siedowse if (part_offset_type[i] == '*') { 1346149061Siedowse needed += pp->p_size; 1347149061Siedowse continue; 1348149061Siedowse } 1349149061Siedowse current_offset = pp->p_offset; 1350149061Siedowse } 1351149061Siedowse 1352149061Siedowse if (current_offset - base_offset <= needed) { 1353149061Siedowse fprintf(stderr, "Cannot find space for partition %c\n", 1354149061Siedowse hog_part + 'a'); 1355149061Siedowse fprintf(stderr, 1356149061Siedowse "Need more than %lu sectors between %lu and %lu\n", 1357149061Siedowse needed, base_offset, current_offset); 1358149061Siedowse errors++; 1359149061Siedowse lp->d_partitions[hog_part].p_size = 0; 1360149061Siedowse } else { 1361149061Siedowse lp->d_partitions[hog_part].p_size = current_offset - 1362149061Siedowse base_offset - needed; 1363149061Siedowse total_size += lp->d_partitions[hog_part].p_size; 1364149061Siedowse } 136573034Sjwd } 136673034Sjwd 136773034Sjwd /* Now set the offsets for each partition */ 1368149061Siedowse current_offset = BBSIZE / secsize; /* in sectors */ 136973034Sjwd seen_default_offset = 0; 137073034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 13711558Srgrimes part = 'a' + i; 13721558Srgrimes pp = &lp->d_partitions[i]; 137373034Sjwd if (part_set[i]) { 137473034Sjwd if (part_offset_type[i] == '*') { 137594065Sphk if (i == RAW_PART) { 137673034Sjwd pp->p_offset = 0; 137773034Sjwd } else { 137873034Sjwd pp->p_offset = current_offset; 137973034Sjwd seen_default_offset = 1; 138073034Sjwd } 138173034Sjwd } else { 138273034Sjwd /* allow them to be out of order for old-style tables */ 1383133347Sdes if (pp->p_offset < current_offset && 1384107534Sgrog seen_default_offset && i != RAW_PART && 1385107534Sgrog pp->p_fstype != FS_VINUM) { 138673034Sjwd fprintf(stderr, 138794065Sphk"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 138894065Sphk (long)pp->p_offset,i+'a',current_offset); 138973034Sjwd fprintf(stderr, 139073034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 139173034Sjwd errors++; 139273034Sjwd } else if (pp->p_offset != current_offset && 139394065Sphk i != RAW_PART && seen_default_offset) { 1394133347Sdes /* 1395133347Sdes * this may give unneeded warnings if 139673034Sjwd * partitions are out-of-order 139773034Sjwd */ 1398114574Sphk warnx( 139973034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 140094065Sphk (long)pp->p_offset, i + 'a', current_offset); 140173034Sjwd } 140273034Sjwd } 140394065Sphk if (i != RAW_PART) 1404133347Sdes current_offset = pp->p_offset + pp->p_size; 140573034Sjwd } 140673034Sjwd } 140773034Sjwd 140873034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 140973034Sjwd part = 'a' + i; 141073034Sjwd pp = &lp->d_partitions[i]; 14111558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 1412114574Sphk warnx("partition %c: size 0, but offset %lu", 141337234Sbde part, (u_long)pp->p_offset); 14141558Srgrimes#ifdef notdef 14151558Srgrimes if (pp->p_size % lp->d_secpercyl) 1416114574Sphk warnx("partition %c: size %% cylinder-size != 0", 14171558Srgrimes part); 14181558Srgrimes if (pp->p_offset % lp->d_secpercyl) 1419114574Sphk warnx("partition %c: offset %% cylinder-size != 0", 14201558Srgrimes part); 14211558Srgrimes#endif 14221558Srgrimes if (pp->p_offset > lp->d_secperunit) { 14231558Srgrimes fprintf(stderr, 14241558Srgrimes "partition %c: offset past end of unit\n", part); 14251558Srgrimes errors++; 14261558Srgrimes } 14271558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 14281558Srgrimes fprintf(stderr, 142913544Sjoerg "partition %c: partition extends past end of unit\n", 14301558Srgrimes part); 14311558Srgrimes errors++; 14321558Srgrimes } 1433114574Sphk if (i == RAW_PART) { 143473034Sjwd if (pp->p_fstype != FS_UNUSED) 1435114574Sphk warnx("partition %c is not marked as unused!",part); 143673034Sjwd if (pp->p_offset != 0) 1437114574Sphk warnx("partition %c doesn't start at 0!",part); 143873034Sjwd if (pp->p_size != lp->d_secperunit) 1439114574Sphk warnx("partition %c doesn't cover the whole unit!",part); 144073034Sjwd 144173034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 144273034Sjwd (pp->p_size != lp->d_secperunit)) { 1443114574Sphk warnx("An incorrect partition %c may cause problems for " 144473034Sjwd "standard system utilities",part); 144573034Sjwd } 144673034Sjwd } 144773034Sjwd 144873034Sjwd /* check for overlaps */ 144973034Sjwd /* this will check for all possible overlaps once and only once */ 145073034Sjwd for (j = 0; j < i; j++) { 1451107534Sgrog pp2 = &lp->d_partitions[j]; 1452133347Sdes if (j != RAW_PART && i != RAW_PART && 1453107534Sgrog pp->p_fstype != FS_VINUM && 1454107534Sgrog pp2->p_fstype != FS_VINUM && 145573034Sjwd part_set[i] && part_set[j]) { 145673034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 145773034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 145873034Sjwd pp2->p_offset >= pp->p_offset)) { 145973034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 146073034Sjwd j + 'a', i + 'a'); 146173034Sjwd errors++; 146273034Sjwd } 146373034Sjwd } 146473034Sjwd } 14651558Srgrimes } 1466174501Smarcel for (; i < lp->d_npartitions; i++) { 14671558Srgrimes part = 'a' + i; 14681558Srgrimes pp = &lp->d_partitions[i]; 14691558Srgrimes if (pp->p_size || pp->p_offset) 1470114574Sphk warnx("unused partition %c: size %d offset %lu", 147137234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 14721558Srgrimes } 14731558Srgrimes return (errors); 14741558Srgrimes} 14751558Srgrimes 14761558Srgrimes/* 147713550Sjoerg * When operating on a "virgin" disk, try getting an initial label 147813550Sjoerg * from the associated device driver. This might work for all device 147913550Sjoerg * drivers that are able to fetch some initial device parameters 148013550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 148113550Sjoerg * most IDE drives, or vn devices. 148213550Sjoerg * 148313550Sjoerg * The device name must be given in its "canonical" form. 148413550Sjoerg */ 1485114571Sphkstatic struct disklabel * 148613550Sjoerggetvirginlabel(void) 148713550Sjoerg{ 148899365Smarkm static struct disklabel loclab; 1489103669Sphk struct partition *dp; 149013550Sjoerg int f; 1491114574Sphk u_int u; 149213550Sjoerg 1493114571Sphk if ((f = open(specname, O_RDONLY)) == -1) { 1494114571Sphk warn("cannot open %s", specname); 149516431Sbde return (NULL); 149613550Sjoerg } 149768044Sjkh 1498127650Sluigi if (is_file) 1499127650Sluigi get_file_parms(f); 1500183143Slulf else { 1501183143Slulf mediasize = g_mediasize(f); 1502183143Slulf secsize = g_sectorsize(f); 1503183143Slulf if (secsize < 0 || mediasize < 0) { 1504183143Slulf close (f); 1505183143Slulf return (NULL); 1506183143Slulf } 1507103669Sphk } 1508103669Sphk memset(&loclab, 0, sizeof loclab); 1509103669Sphk loclab.d_magic = DISKMAGIC; 1510103669Sphk loclab.d_magic2 = DISKMAGIC; 1511103669Sphk loclab.d_secsize = secsize; 1512103669Sphk loclab.d_secperunit = mediasize / secsize; 1513103669Sphk 151468044Sjkh /* 1515229778Suqs * Nobody in these enlightened days uses the CHS geometry for 1516229778Suqs * anything, but nonetheless try to get it right. If we fail 1517103669Sphk * to get any good ideas from the device, construct something 1518103669Sphk * which is IBM-PC friendly. 151968044Sjkh */ 1520103669Sphk if (ioctl(f, DIOCGFWSECTORS, &u) == 0) 1521103669Sphk loclab.d_nsectors = u; 1522103669Sphk else 1523103669Sphk loclab.d_nsectors = 63; 1524103669Sphk if (ioctl(f, DIOCGFWHEADS, &u) == 0) 1525103669Sphk loclab.d_ntracks = u; 1526103669Sphk else if (loclab.d_secperunit <= 63*1*1024) 1527103669Sphk loclab.d_ntracks = 1; 1528103669Sphk else if (loclab.d_secperunit <= 63*16*1024) 1529103669Sphk loclab.d_ntracks = 16; 1530103669Sphk else 1531103669Sphk loclab.d_ntracks = 255; 1532103669Sphk loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors; 1533103669Sphk loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl; 1534174501Smarcel loclab.d_npartitions = DEFPARTITIONS; 1535103669Sphk 1536103669Sphk /* Various (unneeded) compat stuff */ 1537103669Sphk loclab.d_rpm = 3600; 1538103669Sphk loclab.d_bbsize = BBSIZE; 1539114574Sphk loclab.d_interleave = 1; 1540103669Sphk strncpy(loclab.d_typename, "amnesiac", 1541103669Sphk sizeof(loclab.d_typename)); 1542103669Sphk 1543103669Sphk dp = &loclab.d_partitions[RAW_PART]; 1544103669Sphk dp->p_size = loclab.d_secperunit; 1545103669Sphk loclab.d_checksum = dkcksum(&loclab); 1546103669Sphk close (f); 154799365Smarkm return (&loclab); 154813550Sjoerg} 154913550Sjoerg 1550114571Sphkstatic void 155192541Simpusage(void) 15521558Srgrimes{ 1553112307Sru 1554112307Sru fprintf(stderr, 1555112307Sru "%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", 1556114569Sphk "usage: bsdlabel disk", 1557112307Sru "\t\t(to read label)", 1558114571Sphk " bsdlabel -w [-n] [-m machine] disk [type]", 1559112307Sru "\t\t(to write label with existing boot program)", 1560114569Sphk " bsdlabel -e [-n] [-m machine] disk", 1561112307Sru "\t\t(to edit label)", 1562114569Sphk " bsdlabel -R [-n] [-m machine] disk protofile", 1563112307Sru "\t\t(to restore label with existing boot program)", 1564113680Sphk " bsdlabel -B [-b boot] [-m machine] disk", 1565112307Sru "\t\t(to install boot program with existing on-disk label)", 1566114571Sphk " bsdlabel -w -B [-n] [-b boot] [-m machine] disk [type]", 1567112307Sru "\t\t(to write label and install boot program)", 1568113680Sphk " bsdlabel -R -B [-n] [-b boot] [-m machine] disk protofile", 1569109878Sphk "\t\t(to restore label and install boot program)" 1570109878Sphk ); 15711558Srgrimes exit(1); 15721558Srgrimes} 1573