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$"); 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 66227556Sae#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 *); 83227556Saestatic 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 1331558Srgrimesenum { 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, "ia64") || 169115948Sphk !strcmp(optarg, "pc98")) { 170115696Sphk labelsoffset = 1; 171115696Sphk labeloffset = 0; 172114550Sphk bbsize = 8192; 173114571Sphk } else { 174114571Sphk errx(1, "Unsupported architecture"); 175114550Sphk } 176112307Sru break; 17773034Sjwd case 'n': 17873034Sjwd disable_write = 1; 17973034Sjwd break; 1801558Srgrimes case 'R': 1811558Srgrimes if (op != UNSPEC) 1821558Srgrimes usage(); 1831558Srgrimes op = RESTORE; 1841558Srgrimes break; 1851558Srgrimes case 'e': 1861558Srgrimes if (op != UNSPEC) 1871558Srgrimes usage(); 1881558Srgrimes op = EDIT; 1891558Srgrimes break; 1901558Srgrimes case 'r': 191114571Sphk /* 192114571Sphk * We accept and ignode -r for compatibility with 193114571Sphk * historically disklabel usage. 194114571Sphk */ 1951558Srgrimes break; 1961558Srgrimes case 'w': 1971558Srgrimes if (op != UNSPEC) 1981558Srgrimes usage(); 1991558Srgrimes op = WRITE; 2001558Srgrimes break; 2011558Srgrimes case '?': 2021558Srgrimes default: 2031558Srgrimes usage(); 2041558Srgrimes } 2051558Srgrimes argc -= optind; 2061558Srgrimes argv += optind; 207114571Sphk 2081558Srgrimes if (argc < 1) 2091558Srgrimes usage(); 210115995Sphk if (labelsoffset < 0 || labeloffset < 0) 211115995Sphk errx(1, "a -m <architecture> option must be specified"); 2121558Srgrimes 213114569Sphk /* Figure out the names of the thing we're working on */ 214127650Sluigi if (is_file) { 215139856Srse specname = argv[0]; 216114569Sphk } else { 217183143Slulf specname = g_device_path(argv[0]); 218183143Slulf if (specname == NULL) { 219183143Slulf warn("unable to get correct path for %s", argv[0]); 220183143Slulf return(1); 221183143Slulf } 222183143Slulf fd = open(specname, O_RDONLY); 223183143Slulf if (fd < 0) { 224183143Slulf warn("error opening %s", specname); 225183143Slulf return(1); 226183143Slulf } 227183143Slulf pname = g_providername(fd); 228183143Slulf if (pname == NULL) { 229183487Slulf warn("error getting providername for %s", specname); 230183496Slulf close(fd); 231183143Slulf return(1); 232183143Slulf } 233183496Slulf close(fd); 2341558Srgrimes } 2351558Srgrimes 236114571Sphk if (installboot && op == UNSPEC) 237114571Sphk op = WRITEBOOT; 238114571Sphk else if (op == UNSPEC) 239114571Sphk op = READ; 240114571Sphk 2411558Srgrimes switch(op) { 2421558Srgrimes 24348957Sbillf case UNSPEC: 24448957Sbillf break; 24548957Sbillf 2461558Srgrimes case EDIT: 2471558Srgrimes if (argc != 1) 2481558Srgrimes usage(); 249114571Sphk readlabel(1); 250121222Sphk fixlabel(&lab); 251114571Sphk error = edit(); 2521558Srgrimes break; 2531558Srgrimes 2541558Srgrimes case READ: 2551558Srgrimes if (argc != 1) 2561558Srgrimes usage(); 257114571Sphk readlabel(1); 258114571Sphk display(stdout, NULL); 259114571Sphk error = checklabel(NULL); 2601558Srgrimes break; 2611558Srgrimes 2621558Srgrimes case RESTORE: 2631558Srgrimes if (argc != 2) 2641558Srgrimes usage(); 2651558Srgrimes if (!(t = fopen(argv[1], "r"))) 266114569Sphk err(4, "fopen %s", argv[1]); 267114571Sphk readlabel(0); 26837865Sbde if (!getasciilabel(t, &lab)) 26937865Sbde exit(1); 270114571Sphk error = writelabel(); 2711558Srgrimes break; 2721558Srgrimes 2731558Srgrimes case WRITE: 274114571Sphk if (argc == 2) 275114571Sphk name = argv[1]; 276114571Sphk else if (argc == 1) 277114571Sphk name = "auto"; 278114571Sphk else 2791558Srgrimes usage(); 280114571Sphk readlabel(0); 281114571Sphk makelabel(name, &lab); 282121222Sphk fixlabel(&lab); 283114571Sphk if (checklabel(NULL) == 0) 284114571Sphk error = writelabel(); 2851558Srgrimes break; 2861558Srgrimes 2871558Srgrimes case WRITEBOOT: 2881558Srgrimes 289114571Sphk readlabel(1); 290121222Sphk fixlabel(&lab); 2911558Srgrimes if (argc == 2) 292114571Sphk makelabel(argv[1], &lab); 293114571Sphk if (checklabel(NULL) == 0) 294114571Sphk error = writelabel(); 2951558Srgrimes break; 2961558Srgrimes } 2971558Srgrimes exit(error); 2981558Srgrimes} 2991558Srgrimes 300121222Sphkstatic void 301121222Sphkfixlabel(struct disklabel *lp) 302121222Sphk{ 303121222Sphk struct partition *dp; 304121222Sphk int i; 305121222Sphk 306174501Smarcel for (i = 0; i < lp->d_npartitions; i++) { 307121222Sphk if (i == RAW_PART) 308121222Sphk continue; 309121222Sphk if (lp->d_partitions[i].p_size) 310121222Sphk return; 311121222Sphk } 312121222Sphk 313121222Sphk dp = &lp->d_partitions[0]; 314121222Sphk dp->p_offset = BBSIZE / secsize; 315121222Sphk dp->p_size = lp->d_secperunit - dp->p_offset; 316121222Sphk} 317121222Sphk 3181558Srgrimes/* 319111286Sru * Construct a prototype disklabel from /etc/disktab. 3201558Srgrimes */ 321114571Sphkstatic void 322114571Sphkmakelabel(const char *type, struct disklabel *lp) 3231558Srgrimes{ 32492541Simp struct disklabel *dp; 32513550Sjoerg 32613550Sjoerg if (strcmp(type, "auto") == 0) 32713550Sjoerg dp = getvirginlabel(); 32813550Sjoerg else 32913544Sjoerg dp = getdiskbyname(type); 33036632Scharnier if (dp == NULL) 33136632Scharnier errx(1, "%s: unknown disk type", type); 3321558Srgrimes *lp = *dp; 3331558Srgrimes bzero(lp->d_packname, sizeof(lp->d_packname)); 3341558Srgrimes} 3351558Srgrimes 336114571Sphkstatic void 337114571Sphkreadboot(void) 3381558Srgrimes{ 339209614Sjh int fd; 340114571Sphk struct stat st; 341114571Sphk 342114571Sphk if (xxboot == NULL) 343114571Sphk xxboot = "/boot/boot"; 344114571Sphk fd = open(xxboot, O_RDONLY); 345114571Sphk if (fd < 0) 346114571Sphk err(1, "cannot open %s", xxboot); 347114571Sphk fstat(fd, &st); 348219448Suqs if (st.st_size <= BBSIZE) { 349209614Sjh if (read(fd, bootarea, st.st_size) != st.st_size) 350114571Sphk err(1, "read error %s", xxboot); 351216095Skevlo close(fd); 352114571Sphk return; 353133347Sdes } 354114571Sphk errx(1, "boot code %s is wrong size", xxboot); 355114571Sphk} 356114571Sphk 357114571Sphkstatic int 358227556Saegeom_class_available(const char *name) 359211873Sjh{ 360211873Sjh struct gclass *class; 361211873Sjh struct gmesh mesh; 362211873Sjh int error; 363211873Sjh 364211873Sjh error = geom_gettree(&mesh); 365211873Sjh if (error != 0) 366211873Sjh errc(1, error, "Cannot get GEOM tree"); 367211873Sjh 368211873Sjh LIST_FOREACH(class, &mesh.lg_class, lg_class) { 369227556Sae if (strcmp(class->lg_name, name) == 0) { 370211873Sjh geom_deletetree(&mesh); 371211873Sjh return (1); 372211873Sjh } 373211873Sjh } 374211873Sjh 375211873Sjh geom_deletetree(&mesh); 376211873Sjh 377211873Sjh return (0); 378211873Sjh} 379211873Sjh 380211873Sjhstatic int 381114571Sphkwritelabel(void) 382114571Sphk{ 383211873Sjh int i, fd, serrno; 384114569Sphk struct gctl_req *grq; 385114569Sphk char const *errstr; 386114571Sphk struct disklabel *lp = &lab; 38738384Sdfr 38873034Sjwd if (disable_write) { 389114574Sphk warnx("write to disk label supressed - label was as follows:"); 390114571Sphk display(stdout, NULL); 39173034Sjwd return (0); 392109878Sphk } 393109878Sphk 394109878Sphk lp->d_magic = DISKMAGIC; 395109878Sphk lp->d_magic2 = DISKMAGIC; 396109878Sphk lp->d_checksum = 0; 397109878Sphk lp->d_checksum = dkcksum(lp); 398114571Sphk if (installboot) 399114571Sphk readboot(); 400114673Sphk for (i = 0; i < lab.d_npartitions; i++) 401114673Sphk if (lab.d_partitions[i].p_size) 402196383Smarcel lab.d_partitions[i].p_offset += lba_offset; 403115696Sphk bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * secsize, 404115696Sphk lp); 405114569Sphk 406114569Sphk fd = open(specname, O_RDWR); 407114569Sphk if (fd < 0) { 408127650Sluigi if (is_file) { 409127650Sluigi warn("cannot open file %s for writing label", specname); 410127650Sluigi return(1); 411211873Sjh } else 412211873Sjh serrno = errno; 413211873Sjh 414227556Sae if (geom_class_available("PART") != 0) { 415227556Sae /* 416227556Sae * Since we weren't able open provider for 417227556Sae * writing, then recommend user to use gpart(8). 418227556Sae */ 419227556Sae warnc(serrno, 420227556Sae "cannot open provider %s for writing label", 421227556Sae specname); 422227556Sae warnx("Try to use gpart(8)."); 423227556Sae return (1); 424227556Sae } 425227556Sae 426211873Sjh /* Give up if GEOM_BSD is not available. */ 427227556Sae if (geom_class_available("BSD") == 0) { 428211873Sjh warnc(serrno, "%s", specname); 429211873Sjh return (1); 430127650Sluigi } 431183143Slulf 432115624Sphk grq = gctl_get_handle(); 433115624Sphk gctl_ro_param(grq, "verb", -1, "write label"); 434114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 435183143Slulf gctl_ro_param(grq, "geom", -1, pname); 436133347Sdes gctl_ro_param(grq, "label", 148+16*8, 437115696Sphk bootarea + labeloffset + labelsoffset * secsize); 438114569Sphk errstr = gctl_issue(grq); 439114571Sphk if (errstr != NULL) { 440114571Sphk warnx("%s", errstr); 441114571Sphk gctl_free(grq); 442114571Sphk return(1); 443114571Sphk } 444114569Sphk gctl_free(grq); 445114569Sphk if (installboot) { 446115624Sphk grq = gctl_get_handle(); 447115624Sphk gctl_ro_param(grq, "verb", -1, "write bootcode"); 448114569Sphk gctl_ro_param(grq, "class", -1, "BSD"); 449183143Slulf gctl_ro_param(grq, "geom", -1, pname); 450114571Sphk gctl_ro_param(grq, "bootcode", BBSIZE, bootarea); 451114569Sphk errstr = gctl_issue(grq); 452114571Sphk if (errstr != NULL) { 453114571Sphk warnx("%s", errstr); 454114571Sphk gctl_free(grq); 455114571Sphk return (1); 456114571Sphk } 457114569Sphk gctl_free(grq); 458114569Sphk } 459114569Sphk } else { 460114571Sphk if (write(fd, bootarea, bbsize) != bbsize) { 461114569Sphk warn("write %s", specname); 462114569Sphk close (fd); 463114569Sphk return (1); 464114569Sphk } 465114569Sphk close (fd); 466109878Sphk } 4671558Srgrimes return (0); 4681558Srgrimes} 4691558Srgrimes 470127650Sluigistatic void 471127650Sluigiget_file_parms(int f) 472127650Sluigi{ 473127650Sluigi int i; 474127650Sluigi struct stat sb; 475127650Sluigi 476127650Sluigi if (fstat(f, &sb) != 0) 477127650Sluigi err(4, "fstat failed"); 478127650Sluigi i = sb.st_mode & S_IFMT; 479127650Sluigi if (i != S_IFREG && i != S_IFLNK) 480127650Sluigi errx(4, "%s is not a valid file or link", specname); 481127650Sluigi secsize = DEV_BSIZE; 482127650Sluigi mediasize = sb.st_size; 483127650Sluigi} 484127650Sluigi 4851558Srgrimes/* 4861558Srgrimes * Fetch disklabel for disk. 4871558Srgrimes */ 488114571Sphkstatic int 489114571Sphkreadlabel(int flag) 4901558Srgrimes{ 491209614Sjh ssize_t nbytes; 492196383Smarcel uint32_t lba; 493114673Sphk int f, i; 494114569Sphk int error; 4951558Srgrimes 496114569Sphk f = open(specname, O_RDONLY); 497114569Sphk if (f < 0) 498215704Sbrucec err(1, "%s", specname); 499127650Sluigi if (is_file) 500127650Sluigi get_file_parms(f); 501183143Slulf else { 502183143Slulf mediasize = g_mediasize(f); 503183143Slulf secsize = g_sectorsize(f); 504183143Slulf if (secsize < 0 || mediasize < 0) 505183143Slulf err(4, "cannot get disk geometry"); 506115696Sphk } 507134973Sbrooks if (mediasize > (off_t)0xffffffff * secsize) 508134973Sbrooks errx(1, 509134973Sbrooks "disks with more than 2^32-1 sectors are not supported"); 510114550Sphk (void)lseek(f, (off_t)0, SEEK_SET); 511209614Sjh nbytes = read(f, bootarea, BBSIZE); 512209614Sjh if (nbytes == -1) 513114569Sphk err(4, "%s read", specname); 514209614Sjh if (nbytes != BBSIZE) 515209614Sjh errx(4, "couldn't read %d bytes from %s", BBSIZE, specname); 516114569Sphk close (f); 517115696Sphk error = bsd_disklabel_le_dec( 518115696Sphk bootarea + (labeloffset + labelsoffset * secsize), 519115696Sphk &lab, MAXPARTITIONS); 520114571Sphk if (flag && error) 521114571Sphk errx(1, "%s: no valid label found", specname); 522114673Sphk 523183143Slulf if (is_file) 524183143Slulf return(0); 525196383Smarcel 526196383Smarcel /* 527196383Smarcel * Compensate for absolute block addressing by finding the 528196383Smarcel * smallest partition offset and if the offset of the 'c' 529196383Smarcel * partition is equal to that, subtract it from all offsets. 530196383Smarcel */ 531196383Smarcel lba = ~0; 532196383Smarcel for (i = 0; i < lab.d_npartitions; i++) { 533196383Smarcel if (lab.d_partitions[i].p_size) 534196383Smarcel lba = MIN(lba, lab.d_partitions[i].p_offset); 535114673Sphk } 536196383Smarcel if (lba != 0 && lab.d_partitions[RAW_PART].p_offset == lba) { 537196383Smarcel for (i = 0; i < lab.d_npartitions; i++) { 538114673Sphk if (lab.d_partitions[i].p_size) 539196383Smarcel lab.d_partitions[i].p_offset -= lba; 540196383Smarcel } 541196383Smarcel /* 542196383Smarcel * Save the offset so that we can write the label 543196383Smarcel * back with absolute block addresses. 544196383Smarcel */ 545196383Smarcel lba_offset = lba; 546196383Smarcel } 547114571Sphk return (error); 5481558Srgrimes} 5491558Srgrimes 5501558Srgrimes 551114571Sphkstatic void 55292541Simpdisplay(FILE *f, const struct disklabel *lp) 5531558Srgrimes{ 55492541Simp int i, j; 55592541Simp const struct partition *pp; 5561558Srgrimes 557114571Sphk if (lp == NULL) 558114571Sphk lp = &lab; 559114571Sphk 5601558Srgrimes fprintf(f, "# %s:\n", specname); 561114574Sphk if (allfields) { 562114574Sphk if (lp->d_type < DKMAXTYPES) 563114574Sphk fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 564114574Sphk else 565114574Sphk fprintf(f, "type: %u\n", lp->d_type); 566114574Sphk fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), 567114574Sphk lp->d_typename); 568114574Sphk fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), 569114574Sphk lp->d_packname); 570114574Sphk fprintf(f, "flags:"); 571114574Sphk if (lp->d_flags & D_REMOVABLE) 572114574Sphk fprintf(f, " removeable"); 573114574Sphk if (lp->d_flags & D_ECC) 574114574Sphk fprintf(f, " ecc"); 575114574Sphk if (lp->d_flags & D_BADSECT) 576114574Sphk fprintf(f, " badsect"); 577114574Sphk fprintf(f, "\n"); 578114574Sphk fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize); 579114574Sphk fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors); 580114574Sphk fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks); 581114574Sphk fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl); 582114574Sphk fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders); 583114574Sphk fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit); 584114574Sphk fprintf(f, "rpm: %u\n", lp->d_rpm); 585114574Sphk fprintf(f, "interleave: %u\n", lp->d_interleave); 586114574Sphk fprintf(f, "trackskew: %u\n", lp->d_trackskew); 587114574Sphk fprintf(f, "cylinderskew: %u\n", lp->d_cylskew); 588114574Sphk fprintf(f, "headswitch: %lu\t\t# milliseconds\n", 589114574Sphk (u_long)lp->d_headswitch); 590114574Sphk fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", 591114574Sphk (u_long)lp->d_trkseek); 592114574Sphk fprintf(f, "drivedata: "); 593114574Sphk for (i = NDDATA - 1; i >= 0; i--) 594114574Sphk if (lp->d_drivedata[i]) 595114574Sphk break; 596114574Sphk if (i < 0) 597114574Sphk i = 0; 598114574Sphk for (j = 0; j <= i; j++) 599114574Sphk fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]); 600114574Sphk fprintf(f, "\n\n"); 601114574Sphk } 602114574Sphk fprintf(f, "%u partitions:\n", lp->d_npartitions); 6031558Srgrimes fprintf(f, 604219449Suqs "# size offset fstype [fsize bsize bps/cpg]\n"); 6051558Srgrimes pp = lp->d_partitions; 6061558Srgrimes for (i = 0; i < lp->d_npartitions; i++, pp++) { 6071558Srgrimes if (pp->p_size) { 608219449Suqs fprintf(f, " %c: %10lu %10lu ", 'a' + i, 60937234Sbde (u_long)pp->p_size, (u_long)pp->p_offset); 610107041Sjulian if (pp->p_fstype < FSMAXTYPES) 6111558Srgrimes fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 6121558Srgrimes else 6131558Srgrimes fprintf(f, "%8d", pp->p_fstype); 6141558Srgrimes switch (pp->p_fstype) { 6151558Srgrimes 6161558Srgrimes case FS_UNUSED: /* XXX */ 617219449Suqs fprintf(f, " %5lu %5lu %2s", 61837234Sbde (u_long)pp->p_fsize, 61937234Sbde (u_long)(pp->p_fsize * pp->p_frag), ""); 6201558Srgrimes break; 6211558Srgrimes 6221558Srgrimes case FS_BSDFFS: 623219449Suqs fprintf(f, " %5lu %5lu %5u", 62437234Sbde (u_long)pp->p_fsize, 62537234Sbde (u_long)(pp->p_fsize * pp->p_frag), 6261558Srgrimes pp->p_cpg); 6271558Srgrimes break; 6281558Srgrimes 6295393Sgibbs case FS_BSDLFS: 63037234Sbde fprintf(f, " %5lu %5lu %5d", 63137234Sbde (u_long)pp->p_fsize, 63237234Sbde (u_long)(pp->p_fsize * pp->p_frag), 6335393Sgibbs pp->p_cpg); 6345393Sgibbs break; 6355393Sgibbs 6361558Srgrimes default: 6371558Srgrimes fprintf(f, "%20.20s", ""); 6381558Srgrimes break; 6391558Srgrimes } 640114574Sphk if (i == RAW_PART) { 641114574Sphk fprintf(f, " # \"raw\" part, don't edit"); 642114574Sphk } 643114571Sphk fprintf(f, "\n"); 6441558Srgrimes } 6451558Srgrimes } 6461558Srgrimes fflush(f); 6471558Srgrimes} 6481558Srgrimes 649114571Sphkstatic int 650114571Sphkedit(void) 6511558Srgrimes{ 65292541Simp int c, fd; 6531558Srgrimes struct disklabel label; 65424180Simp FILE *fp; 6551558Srgrimes 65624180Simp if ((fd = mkstemp(tmpfil)) == -1 || 65724180Simp (fp = fdopen(fd, "w")) == NULL) { 65836632Scharnier warnx("can't create %s", tmpfil); 6591558Srgrimes return (1); 6601558Srgrimes } 661114571Sphk display(fp, NULL); 66224180Simp fclose(fp); 6631558Srgrimes for (;;) { 6641558Srgrimes if (!editit()) 6651558Srgrimes break; 66624180Simp fp = fopen(tmpfil, "r"); 66724180Simp if (fp == NULL) { 66836632Scharnier warnx("can't reopen %s for reading", tmpfil); 6691558Srgrimes break; 6701558Srgrimes } 6711558Srgrimes bzero((char *)&label, sizeof(label)); 672114571Sphk c = getasciilabel(fp, &label); 673114571Sphk fclose(fp); 674114571Sphk if (c) { 675114571Sphk lab = label; 676114571Sphk if (writelabel() == 0) { 6771558Srgrimes (void) unlink(tmpfil); 6781558Srgrimes return (0); 6791558Srgrimes } 6801558Srgrimes } 681114571Sphk printf("re-edit the label? [y]: "); 682114571Sphk fflush(stdout); 6831558Srgrimes c = getchar(); 6841558Srgrimes if (c != EOF && c != (int)'\n') 6851558Srgrimes while (getchar() != (int)'\n') 6861558Srgrimes ; 6871558Srgrimes if (c == (int)'n') 6881558Srgrimes break; 6891558Srgrimes } 6901558Srgrimes (void) unlink(tmpfil); 6911558Srgrimes return (1); 6921558Srgrimes} 6931558Srgrimes 694114571Sphkstatic int 69592541Simpeditit(void) 6961558Srgrimes{ 69792541Simp int pid, xpid; 69899365Smarkm int locstat, omask; 69999365Smarkm const char *ed; 700208132Skevlo uid_t uid; 701208132Skevlo gid_t gid; 7021558Srgrimes 7031558Srgrimes omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 7041558Srgrimes while ((pid = fork()) < 0) { 7051558Srgrimes if (errno == EPROCLIM) { 70636632Scharnier warnx("you have too many processes"); 7071558Srgrimes return(0); 7081558Srgrimes } 7091558Srgrimes if (errno != EAGAIN) { 71036632Scharnier warn("fork"); 7111558Srgrimes return(0); 7121558Srgrimes } 7131558Srgrimes sleep(1); 7141558Srgrimes } 7151558Srgrimes if (pid == 0) { 7161558Srgrimes sigsetmask(omask); 717208132Skevlo gid = getgid(); 718208132Skevlo if (setresgid(gid, gid, gid) == -1) 719208132Skevlo err(1, "setresgid"); 720208132Skevlo uid = getuid(); 721208132Skevlo if (setresuid(uid, uid, uid) == -1) 722208132Skevlo err(1, "setresuid"); 7231558Srgrimes if ((ed = getenv("EDITOR")) == (char *)0) 7241558Srgrimes ed = DEFEDITOR; 72579452Sbrian execlp(ed, ed, tmpfil, (char *)0); 72636632Scharnier err(1, "%s", ed); 7271558Srgrimes } 72899365Smarkm while ((xpid = wait(&locstat)) >= 0) 7291558Srgrimes if (xpid == pid) 7301558Srgrimes break; 7311558Srgrimes sigsetmask(omask); 73299365Smarkm return(!locstat); 7331558Srgrimes} 7341558Srgrimes 735114571Sphkstatic char * 73692541Simpskip(char *cp) 7371558Srgrimes{ 7381558Srgrimes 7391558Srgrimes while (*cp != '\0' && isspace(*cp)) 7401558Srgrimes cp++; 7411558Srgrimes if (*cp == '\0' || *cp == '#') 74292541Simp return (NULL); 7431558Srgrimes return (cp); 7441558Srgrimes} 7451558Srgrimes 746114571Sphkstatic char * 74792541Simpword(char *cp) 7481558Srgrimes{ 74992541Simp char c; 7501558Srgrimes 7511558Srgrimes while (*cp != '\0' && !isspace(*cp) && *cp != '#') 7521558Srgrimes cp++; 7531558Srgrimes if ((c = *cp) != '\0') { 7541558Srgrimes *cp++ = '\0'; 7551558Srgrimes if (c != '#') 7561558Srgrimes return (skip(cp)); 7571558Srgrimes } 75892541Simp return (NULL); 7591558Srgrimes} 7601558Srgrimes 7611558Srgrimes/* 7621558Srgrimes * Read an ascii label in from fd f, 7631558Srgrimes * in the same format as that put out by display(), 7641558Srgrimes * and fill in lp. 7651558Srgrimes */ 766114571Sphkstatic int 76792541Simpgetasciilabel(FILE *f, struct disklabel *lp) 7681558Srgrimes{ 769211342Sjh char *cp, *endp; 77094065Sphk const char **cpp; 771107041Sjulian u_int part; 77294065Sphk char *tp, line[BUFSIZ]; 773107041Sjulian u_long v; 774107041Sjulian int lineno = 0, errors = 0; 77592541Simp int i; 7761558Srgrimes 777114862Sphk makelabel("auto", lp); 778109378Sdes bzero(&part_set, sizeof(part_set)); 779109378Sdes bzero(&part_size_type, sizeof(part_size_type)); 780109378Sdes bzero(&part_offset_type, sizeof(part_offset_type)); 7811558Srgrimes lp->d_bbsize = BBSIZE; /* XXX */ 78296475Sphk lp->d_sbsize = 0; /* XXX */ 7831558Srgrimes while (fgets(line, sizeof(line) - 1, f)) { 7841558Srgrimes lineno++; 78513544Sjoerg if ((cp = index(line,'\n')) != 0) 7861558Srgrimes *cp = '\0'; 7871558Srgrimes cp = skip(line); 7881558Srgrimes if (cp == NULL) 7891558Srgrimes continue; 7901558Srgrimes tp = index(cp, ':'); 7911558Srgrimes if (tp == NULL) { 7921558Srgrimes fprintf(stderr, "line %d: syntax error\n", lineno); 7931558Srgrimes errors++; 7941558Srgrimes continue; 7951558Srgrimes } 7961558Srgrimes *tp++ = '\0', tp = skip(tp); 797114571Sphk if (!strcmp(cp, "type")) { 7981558Srgrimes if (tp == NULL) 79999365Smarkm tp = unknown; 8001558Srgrimes cpp = dktypenames; 8011558Srgrimes for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 802114571Sphk if (*cpp && !strcmp(*cpp, tp)) { 8031558Srgrimes lp->d_type = cpp - dktypenames; 80497855Siedowse break; 8051558Srgrimes } 80697855Siedowse if (cpp < &dktypenames[DKMAXTYPES]) 80797855Siedowse continue; 808211342Sjh errno = 0; 809211342Sjh v = strtoul(tp, &endp, 10); 810211342Sjh if (errno != 0 || *endp != '\0') 811211342Sjh v = DKMAXTYPES; 812107041Sjulian if (v >= DKMAXTYPES) 813107041Sjulian fprintf(stderr, "line %d:%s %lu\n", lineno, 8141558Srgrimes "Warning, unknown disk type", v); 815211342Sjh else 816211342Sjh lp->d_type = v; 8171558Srgrimes continue; 8181558Srgrimes } 819114571Sphk if (!strcmp(cp, "flags")) { 8201558Srgrimes for (v = 0; (cp = tp) && *cp != '\0';) { 8211558Srgrimes tp = word(cp); 822114571Sphk if (!strcmp(cp, "removeable")) 8231558Srgrimes v |= D_REMOVABLE; 824114571Sphk else if (!strcmp(cp, "ecc")) 8251558Srgrimes v |= D_ECC; 826114571Sphk else if (!strcmp(cp, "badsect")) 8271558Srgrimes v |= D_BADSECT; 8281558Srgrimes else { 8291558Srgrimes fprintf(stderr, 8301558Srgrimes "line %d: %s: bad flag\n", 8311558Srgrimes lineno, cp); 8321558Srgrimes errors++; 8331558Srgrimes } 8341558Srgrimes } 8351558Srgrimes lp->d_flags = v; 8361558Srgrimes continue; 8371558Srgrimes } 838114571Sphk if (!strcmp(cp, "drivedata")) { 8391558Srgrimes for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 840107041Sjulian lp->d_drivedata[i++] = strtoul(cp, NULL, 10); 8411558Srgrimes tp = word(cp); 8421558Srgrimes } 8431558Srgrimes continue; 8441558Srgrimes } 845107041Sjulian if (sscanf(cp, "%lu partitions", &v) == 1) { 846227556Sae if (v > MAXPARTITIONS) { 8471558Srgrimes fprintf(stderr, 8481558Srgrimes "line %d: bad # of partitions\n", lineno); 8491558Srgrimes lp->d_npartitions = MAXPARTITIONS; 8501558Srgrimes errors++; 851227556Sae } else if (v < DEFPARTITIONS) { 852227556Sae fprintf(stderr, 853227556Sae "line %d: bad # of partitions\n", lineno); 854227556Sae lp->d_npartitions = DEFPARTITIONS; 855227556Sae errors++; 8561558Srgrimes } else 8571558Srgrimes lp->d_npartitions = v; 8581558Srgrimes continue; 8591558Srgrimes } 8601558Srgrimes if (tp == NULL) 86199365Smarkm tp = blank; 862114571Sphk if (!strcmp(cp, "disk")) { 8631558Srgrimes strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 8641558Srgrimes continue; 8651558Srgrimes } 866114571Sphk if (!strcmp(cp, "label")) { 8671558Srgrimes strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 8681558Srgrimes continue; 8691558Srgrimes } 870114571Sphk if (!strcmp(cp, "bytes/sector")) { 871107041Sjulian v = strtoul(tp, NULL, 10); 872107041Sjulian if (v == 0 || (v % DEV_BSIZE) != 0) { 8731558Srgrimes fprintf(stderr, 8741558Srgrimes "line %d: %s: bad sector size\n", 8751558Srgrimes lineno, tp); 8761558Srgrimes errors++; 8771558Srgrimes } else 8781558Srgrimes lp->d_secsize = v; 8791558Srgrimes continue; 8801558Srgrimes } 881114571Sphk if (!strcmp(cp, "sectors/track")) { 882107041Sjulian v = strtoul(tp, NULL, 10); 883107041Sjulian#if (ULONG_MAX != 0xffffffffUL) 884133347Sdes if (v == 0 || v > 0xffffffff) 885107041Sjulian#else 886133347Sdes if (v == 0) 887107041Sjulian#endif 888133347Sdes { 8891558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 8901558Srgrimes lineno, tp, cp); 8911558Srgrimes errors++; 8921558Srgrimes } else 8931558Srgrimes lp->d_nsectors = v; 8941558Srgrimes continue; 8951558Srgrimes } 896114571Sphk if (!strcmp(cp, "sectors/cylinder")) { 897107041Sjulian v = strtoul(tp, NULL, 10); 898107041Sjulian if (v == 0) { 8991558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9001558Srgrimes lineno, tp, cp); 9011558Srgrimes errors++; 9021558Srgrimes } else 9031558Srgrimes lp->d_secpercyl = v; 9041558Srgrimes continue; 9051558Srgrimes } 906114571Sphk if (!strcmp(cp, "tracks/cylinder")) { 907107041Sjulian v = strtoul(tp, NULL, 10); 908107041Sjulian if (v == 0) { 9091558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9101558Srgrimes lineno, tp, cp); 9111558Srgrimes errors++; 9121558Srgrimes } else 9131558Srgrimes lp->d_ntracks = v; 9141558Srgrimes continue; 9151558Srgrimes } 916114571Sphk if (!strcmp(cp, "cylinders")) { 917107041Sjulian v = strtoul(tp, NULL, 10); 918107041Sjulian if (v == 0) { 9191558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9201558Srgrimes lineno, tp, cp); 9211558Srgrimes errors++; 9221558Srgrimes } else 9231558Srgrimes lp->d_ncylinders = v; 9241558Srgrimes continue; 9251558Srgrimes } 926114571Sphk if (!strcmp(cp, "sectors/unit")) { 927107041Sjulian v = strtoul(tp, NULL, 10); 928107041Sjulian if (v == 0) { 9296643Sbde fprintf(stderr, "line %d: %s: bad %s\n", 9306643Sbde lineno, tp, cp); 9316643Sbde errors++; 9326643Sbde } else 9336643Sbde lp->d_secperunit = v; 9346643Sbde continue; 9356643Sbde } 936114571Sphk if (!strcmp(cp, "rpm")) { 937107041Sjulian v = strtoul(tp, NULL, 10); 938107041Sjulian if (v == 0 || v > USHRT_MAX) { 9391558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9401558Srgrimes lineno, tp, cp); 9411558Srgrimes errors++; 9421558Srgrimes } else 9431558Srgrimes lp->d_rpm = v; 9441558Srgrimes continue; 9451558Srgrimes } 946114571Sphk if (!strcmp(cp, "interleave")) { 947107041Sjulian v = strtoul(tp, NULL, 10); 948107041Sjulian if (v == 0 || v > USHRT_MAX) { 9491558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9501558Srgrimes lineno, tp, cp); 9511558Srgrimes errors++; 9521558Srgrimes } else 9531558Srgrimes lp->d_interleave = v; 9541558Srgrimes continue; 9551558Srgrimes } 956114571Sphk if (!strcmp(cp, "trackskew")) { 957107041Sjulian v = strtoul(tp, NULL, 10); 958107041Sjulian if (v > USHRT_MAX) { 9591558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9601558Srgrimes lineno, tp, cp); 9611558Srgrimes errors++; 9621558Srgrimes } else 9631558Srgrimes lp->d_trackskew = v; 9641558Srgrimes continue; 9651558Srgrimes } 966114571Sphk if (!strcmp(cp, "cylinderskew")) { 967107041Sjulian v = strtoul(tp, NULL, 10); 968107041Sjulian if (v > USHRT_MAX) { 9691558Srgrimes fprintf(stderr, "line %d: %s: bad %s\n", 9701558Srgrimes lineno, tp, cp); 9711558Srgrimes errors++; 9721558Srgrimes } else 9731558Srgrimes lp->d_cylskew = v; 9741558Srgrimes continue; 9751558Srgrimes } 976114571Sphk if (!strcmp(cp, "headswitch")) { 977107041Sjulian v = strtoul(tp, NULL, 10); 978107041Sjulian lp->d_headswitch = v; 9791558Srgrimes continue; 9801558Srgrimes } 981114571Sphk if (!strcmp(cp, "track-to-track seek")) { 982107041Sjulian v = strtoul(tp, NULL, 10); 983107041Sjulian lp->d_trkseek = v; 9841558Srgrimes continue; 9851558Srgrimes } 98673034Sjwd /* the ':' was removed above */ 98797534Siedowse if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') { 98897534Siedowse fprintf(stderr, 98997534Siedowse "line %d: %s: Unknown disklabel field\n", lineno, 99097534Siedowse cp); 99197534Siedowse errors++; 99297534Siedowse continue; 99397534Siedowse } 99497534Siedowse 99597534Siedowse /* Process a partition specification line. */ 99697534Siedowse part = *cp - 'a'; 99797534Siedowse if (part >= lp->d_npartitions) { 99897534Siedowse fprintf(stderr, 99997534Siedowse "line %d: partition name out of range a-%c: %s\n", 100097534Siedowse lineno, 'a' + lp->d_npartitions - 1, cp); 100197534Siedowse errors++; 100297534Siedowse continue; 100397534Siedowse } 100497534Siedowse part_set[part] = 1; 100597534Siedowse 100697534Siedowse if (getasciipartspec(tp, lp, part, lineno) != 0) { 100797534Siedowse errors++; 100897534Siedowse break; 100997534Siedowse } 101097534Siedowse } 101197534Siedowse errors += checklabel(lp); 101297534Siedowse return (errors == 0); 101397534Siedowse} 101497534Siedowse 101597534Siedowse#define NXTNUM(n) do { \ 10163111Spst if (tp == NULL) { \ 10173111Spst fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 101897534Siedowse return (1); \ 10193111Spst } else { \ 10203111Spst cp = tp, tp = word(cp); \ 1021107041Sjulian (n) = strtoul(cp, NULL, 10); \ 10223111Spst } \ 102397534Siedowse} while (0) 102497534Siedowse 102573034Sjwd/* retain 1 character following number */ 102697534Siedowse#define NXTWORD(w,n) do { \ 102773034Sjwd if (tp == NULL) { \ 102873034Sjwd fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 102997534Siedowse return (1); \ 103073034Sjwd } else { \ 1031133347Sdes char *tmp; \ 103273034Sjwd cp = tp, tp = word(cp); \ 1033133347Sdes (n) = strtoul(cp, &tmp, 10); \ 103473034Sjwd if (tmp) (w) = *tmp; \ 103573034Sjwd } \ 103697534Siedowse} while (0) 10371558Srgrimes 103897534Siedowse/* 103997534Siedowse * Read a partition line into partition `part' in the specified disklabel. 104097534Siedowse * Return 0 on success, 1 on failure. 104197534Siedowse */ 1042114571Sphkstatic int 104397534Siedowsegetasciipartspec(char *tp, struct disklabel *lp, int part, int lineno) 104497534Siedowse{ 104597534Siedowse struct partition *pp; 1046211342Sjh char *cp, *endp; 104797534Siedowse const char **cpp; 1048107041Sjulian u_long v; 10491558Srgrimes 105097534Siedowse pp = &lp->d_partitions[part]; 105197534Siedowse cp = NULL; 10521558Srgrimes 105397534Siedowse v = 0; 105497534Siedowse NXTWORD(part_size_type[part],v); 1055107041Sjulian if (v == 0 && part_size_type[part] != '*') { 1056107041Sjulian fprintf(stderr, 1057107041Sjulian "line %d: %s: bad partition size\n", lineno, cp); 105897534Siedowse return (1); 105997534Siedowse } 106097534Siedowse pp->p_size = v; 106197534Siedowse 106297534Siedowse v = 0; 106397534Siedowse NXTWORD(part_offset_type[part],v); 1064107041Sjulian if (v == 0 && part_offset_type[part] != '*' && 1065107041Sjulian part_offset_type[part] != '\0') { 1066107041Sjulian fprintf(stderr, 1067107041Sjulian "line %d: %s: bad partition offset\n", lineno, cp); 106897534Siedowse return (1); 106997534Siedowse } 107097534Siedowse pp->p_offset = v; 1071112945Syar if (tp == NULL) { 1072112945Syar fprintf(stderr, "line %d: missing file system type\n", lineno); 1073112945Syar return (1); 1074112945Syar } 107597534Siedowse cp = tp, tp = word(cp); 107697534Siedowse for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) 1077114571Sphk if (*cpp && !strcmp(*cpp, cp)) 107897534Siedowse break; 107997534Siedowse if (*cpp != NULL) { 108097534Siedowse pp->p_fstype = cpp - fstypenames; 108197534Siedowse } else { 1082211342Sjh if (isdigit(*cp)) { 1083211342Sjh errno = 0; 1084211342Sjh v = strtoul(cp, &endp, 10); 1085211342Sjh if (errno != 0 || *endp != '\0') 1086211342Sjh v = FSMAXTYPES; 1087211342Sjh } else 108897534Siedowse v = FSMAXTYPES; 1089107041Sjulian if (v >= FSMAXTYPES) { 109097534Siedowse fprintf(stderr, 1091102231Strhodes "line %d: Warning, unknown file system type %s\n", 109297534Siedowse lineno, cp); 109397534Siedowse v = FS_UNUSED; 109497534Siedowse } 109597534Siedowse pp->p_fstype = v; 109697534Siedowse } 109797534Siedowse 109897534Siedowse switch (pp->p_fstype) { 109997534Siedowse case FS_UNUSED: 1100120821Siedowse case FS_BSDFFS: 1101120821Siedowse case FS_BSDLFS: 1102120821Siedowse /* accept defaults for fsize/frag/cpg */ 110397534Siedowse if (tp) { 110497534Siedowse NXTNUM(pp->p_fsize); 110597534Siedowse if (pp->p_fsize == 0) 110697534Siedowse break; 110797534Siedowse NXTNUM(v); 110897534Siedowse pp->p_frag = v / pp->p_fsize; 1109120821Siedowse if (tp != NULL) 1110120821Siedowse NXTNUM(pp->p_cpg); 111197534Siedowse } 111297534Siedowse /* else default to 0's */ 111397534Siedowse break; 111497534Siedowse default: 111597534Siedowse break; 11161558Srgrimes } 111797534Siedowse return (0); 11181558Srgrimes} 11191558Srgrimes 11201558Srgrimes/* 11211558Srgrimes * Check disklabel for errors and fill in 11221558Srgrimes * derived fields according to supplied values. 11231558Srgrimes */ 1124114571Sphkstatic int 112592541Simpchecklabel(struct disklabel *lp) 11261558Srgrimes{ 112792541Simp struct partition *pp; 11281558Srgrimes int i, errors = 0; 11291558Srgrimes char part; 1130149061Siedowse u_long base_offset, needed, total_size, total_percent, current_offset; 1131149061Siedowse long free_space; 113273034Sjwd int seen_default_offset; 113373034Sjwd int hog_part; 113473034Sjwd int j; 113573034Sjwd struct partition *pp2; 11361558Srgrimes 1137114571Sphk if (lp == NULL) 1138114571Sphk lp = &lab; 1139114571Sphk 1140114574Sphk if (allfields) { 1141114574Sphk 1142114574Sphk if (lp->d_secsize == 0) { 1143114574Sphk fprintf(stderr, "sector size 0\n"); 1144114574Sphk return (1); 1145114574Sphk } 1146114574Sphk if (lp->d_nsectors == 0) { 1147114574Sphk fprintf(stderr, "sectors/track 0\n"); 1148114574Sphk return (1); 1149114574Sphk } 1150114574Sphk if (lp->d_ntracks == 0) { 1151114574Sphk fprintf(stderr, "tracks/cylinder 0\n"); 1152114574Sphk return (1); 1153114574Sphk } 1154114574Sphk if (lp->d_ncylinders == 0) { 1155114574Sphk fprintf(stderr, "cylinders/unit 0\n"); 1156114574Sphk errors++; 1157114574Sphk } 1158114574Sphk if (lp->d_rpm == 0) 1159114574Sphk warnx("revolutions/minute 0"); 1160114574Sphk if (lp->d_secpercyl == 0) 1161114574Sphk lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1162114574Sphk if (lp->d_secperunit == 0) 1163114574Sphk lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1164114574Sphk if (lp->d_bbsize == 0) { 1165114574Sphk fprintf(stderr, "boot block size 0\n"); 1166114574Sphk errors++; 1167114574Sphk } else if (lp->d_bbsize % lp->d_secsize) 1168114574Sphk warnx("boot block size %% sector-size != 0"); 1169227556Sae if (lp->d_npartitions > MAXPARTITIONS) { 1170114574Sphk warnx("number of partitions (%lu) > MAXPARTITIONS (%d)", 1171114574Sphk (u_long)lp->d_npartitions, MAXPARTITIONS); 1172227556Sae errors++; 1173227556Sae } 1174227556Sae if (lp->d_npartitions < DEFPARTITIONS) { 1175227556Sae warnx("number of partitions (%lu) < DEFPARTITIONS (%d)", 1176227556Sae (u_long)lp->d_npartitions, DEFPARTITIONS); 1177227556Sae errors++; 1178227556Sae } 1179114574Sphk } else { 1180114574Sphk struct disklabel *vl; 1181114574Sphk 1182114574Sphk vl = getvirginlabel(); 1183227556Sae if (lp->d_secsize == 0) 1184227556Sae lp->d_secsize = vl->d_secsize; 1185227556Sae if (lp->d_nsectors == 0) 1186227556Sae lp->d_nsectors = vl->d_nsectors; 1187227556Sae if (lp->d_ntracks == 0) 1188227556Sae lp->d_ntracks = vl->d_ntracks; 1189227556Sae if (lp->d_ncylinders == 0) 1190227556Sae lp->d_ncylinders = vl->d_ncylinders; 1191227556Sae if (lp->d_rpm == 0) 1192227556Sae lp->d_rpm = vl->d_rpm; 1193227556Sae if (lp->d_interleave == 0) 1194227556Sae lp->d_interleave = vl->d_interleave; 1195227556Sae if (lp->d_secpercyl == 0) 1196227556Sae lp->d_secpercyl = vl->d_secpercyl; 1197234410Sae if (lp->d_secperunit == 0 || 1198234410Sae lp->d_secperunit > vl->d_secperunit) 1199227556Sae lp->d_secperunit = vl->d_secperunit; 1200227556Sae if (lp->d_bbsize == 0) 1201227556Sae lp->d_bbsize = vl->d_bbsize; 1202227556Sae if (lp->d_npartitions < DEFPARTITIONS || 1203227556Sae lp->d_npartitions > MAXPARTITIONS) 1204227556Sae lp->d_npartitions = vl->d_npartitions; 12051558Srgrimes } 120673034Sjwd 1207114574Sphk 120873034Sjwd /* first allocate space to the partitions, then offsets */ 120973034Sjwd total_size = 0; /* in sectors */ 121073034Sjwd total_percent = 0; /* in percent */ 121173034Sjwd hog_part = -1; 121273034Sjwd /* find all fixed partitions */ 12131558Srgrimes for (i = 0; i < lp->d_npartitions; i++) { 121473034Sjwd pp = &lp->d_partitions[i]; 121573034Sjwd if (part_set[i]) { 121673034Sjwd if (part_size_type[i] == '*') { 121794065Sphk if (i == RAW_PART) { 121873034Sjwd pp->p_size = lp->d_secperunit; 121973034Sjwd } else { 122073034Sjwd if (hog_part != -1) 1221114574Sphk warnx("Too many '*' partitions (%c and %c)", 122273034Sjwd hog_part + 'a',i + 'a'); 122373034Sjwd else 122473034Sjwd hog_part = i; 122573034Sjwd } 122673034Sjwd } else { 122773573Simp off_t size; 122873034Sjwd 122973034Sjwd size = pp->p_size; 123073034Sjwd switch (part_size_type[i]) { 123173034Sjwd case '%': 123273034Sjwd total_percent += size; 123373034Sjwd break; 1234133348Sdes case 't': 1235133348Sdes case 'T': 1236133348Sdes size *= 1024ULL; 1237133348Sdes /* FALLTHROUGH */ 1238133348Sdes case 'g': 1239133348Sdes case 'G': 1240133348Sdes size *= 1024ULL; 1241133348Sdes /* FALLTHROUGH */ 1242133348Sdes case 'm': 1243133348Sdes case 'M': 1244133348Sdes size *= 1024ULL; 1245133348Sdes /* FALLTHROUGH */ 124673034Sjwd case 'k': 124773034Sjwd case 'K': 124873573Simp size *= 1024ULL; 124973034Sjwd break; 125073034Sjwd case '\0': 125173034Sjwd break; 125273034Sjwd default: 1253133384Sdes warnx("unknown multiplier suffix '%c' for partition %c (should be K, M, G or T)", 1254133348Sdes part_size_type[i], i + 'a'); 125573034Sjwd break; 125673034Sjwd } 125773034Sjwd /* don't count %'s yet */ 125873034Sjwd if (part_size_type[i] != '%') { 125973034Sjwd /* 126073034Sjwd * for all not in sectors, convert to 126173034Sjwd * sectors 126273034Sjwd */ 126373034Sjwd if (part_size_type[i] != '\0') { 126473034Sjwd if (size % lp->d_secsize != 0) 1265114574Sphk warnx("partition %c not an integer number of sectors", 126673034Sjwd i + 'a'); 126773034Sjwd size /= lp->d_secsize; 126873034Sjwd pp->p_size = size; 126973034Sjwd } 127073034Sjwd /* else already in sectors */ 127194065Sphk if (i != RAW_PART) 127273034Sjwd total_size += size; 127373034Sjwd } 127473034Sjwd } 127573034Sjwd } 127673034Sjwd } 1277149061Siedowse 1278149061Siedowse /* Find out the total free space, excluding the boot block area. */ 1279149061Siedowse base_offset = BBSIZE / secsize; 1280149061Siedowse free_space = 0; 1281149061Siedowse for (i = 0; i < lp->d_npartitions; i++) { 1282149061Siedowse pp = &lp->d_partitions[i]; 1283149061Siedowse if (!part_set[i] || i == RAW_PART || 1284149061Siedowse part_size_type[i] == '%' || part_size_type[i] == '*') 1285149061Siedowse continue; 1286149061Siedowse if (pp->p_offset > base_offset) 1287149061Siedowse free_space += pp->p_offset - base_offset; 1288149061Siedowse if (pp->p_offset + pp->p_size > base_offset) 1289149061Siedowse base_offset = pp->p_offset + pp->p_size; 1290149061Siedowse } 1291149061Siedowse if (base_offset < lp->d_secperunit) 1292149061Siedowse free_space += lp->d_secperunit - base_offset; 1293149061Siedowse 129473034Sjwd /* handle % partitions - note %'s don't need to add up to 100! */ 129573034Sjwd if (total_percent != 0) { 129673034Sjwd if (total_percent > 100) { 129794065Sphk fprintf(stderr,"total percentage %lu is greater than 100\n", 129873034Sjwd total_percent); 129973034Sjwd errors++; 130073034Sjwd } 130173034Sjwd 130273034Sjwd if (free_space > 0) { 130373034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 130473034Sjwd pp = &lp->d_partitions[i]; 130573034Sjwd if (part_set[i] && part_size_type[i] == '%') { 130673034Sjwd /* careful of overflows! and integer roundoff */ 130773034Sjwd pp->p_size = ((double)pp->p_size/100) * free_space; 130873034Sjwd total_size += pp->p_size; 130973034Sjwd 131073034Sjwd /* FIX we can lose a sector or so due to roundoff per 131173034Sjwd partition. A more complex algorithm could avoid that */ 131273034Sjwd } 131373034Sjwd } 131473034Sjwd } else { 131573034Sjwd fprintf(stderr, 131694065Sphk "%ld sectors available to give to '*' and '%%' partitions\n", 131773034Sjwd free_space); 131873034Sjwd errors++; 131973034Sjwd /* fix? set all % partitions to size 0? */ 132073034Sjwd } 132173034Sjwd } 132273034Sjwd /* give anything remaining to the hog partition */ 132373034Sjwd if (hog_part != -1) { 1324149061Siedowse /* 1325149061Siedowse * Find the range of offsets usable by '*' partitions around 1326149061Siedowse * the hog partition and how much space they need. 1327149061Siedowse */ 1328149061Siedowse needed = 0; 1329149061Siedowse base_offset = BBSIZE / secsize; 1330149061Siedowse for (i = hog_part - 1; i >= 0; i--) { 1331149061Siedowse pp = &lp->d_partitions[i]; 1332149061Siedowse if (!part_set[i] || i == RAW_PART) 1333149061Siedowse continue; 1334149061Siedowse if (part_offset_type[i] == '*') { 1335149061Siedowse needed += pp->p_size; 1336149061Siedowse continue; 1337149061Siedowse } 1338149061Siedowse base_offset = pp->p_offset + pp->p_size; 1339149061Siedowse break; 1340149061Siedowse } 1341149061Siedowse current_offset = lp->d_secperunit; 1342149061Siedowse for (i = lp->d_npartitions - 1; i > hog_part; i--) { 1343149061Siedowse pp = &lp->d_partitions[i]; 1344149061Siedowse if (!part_set[i] || i == RAW_PART) 1345149061Siedowse continue; 1346149061Siedowse if (part_offset_type[i] == '*') { 1347149061Siedowse needed += pp->p_size; 1348149061Siedowse continue; 1349149061Siedowse } 1350149061Siedowse current_offset = pp->p_offset; 1351149061Siedowse } 1352149061Siedowse 1353149061Siedowse if (current_offset - base_offset <= needed) { 1354149061Siedowse fprintf(stderr, "Cannot find space for partition %c\n", 1355149061Siedowse hog_part + 'a'); 1356149061Siedowse fprintf(stderr, 1357149061Siedowse "Need more than %lu sectors between %lu and %lu\n", 1358149061Siedowse needed, base_offset, current_offset); 1359149061Siedowse errors++; 1360149061Siedowse lp->d_partitions[hog_part].p_size = 0; 1361149061Siedowse } else { 1362149061Siedowse lp->d_partitions[hog_part].p_size = current_offset - 1363149061Siedowse base_offset - needed; 1364149061Siedowse total_size += lp->d_partitions[hog_part].p_size; 1365149061Siedowse } 136673034Sjwd } 136773034Sjwd 136873034Sjwd /* Now set the offsets for each partition */ 1369149061Siedowse current_offset = BBSIZE / secsize; /* in sectors */ 137073034Sjwd seen_default_offset = 0; 137173034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 13721558Srgrimes part = 'a' + i; 13731558Srgrimes pp = &lp->d_partitions[i]; 137473034Sjwd if (part_set[i]) { 137573034Sjwd if (part_offset_type[i] == '*') { 137694065Sphk if (i == RAW_PART) { 137773034Sjwd pp->p_offset = 0; 137873034Sjwd } else { 137973034Sjwd pp->p_offset = current_offset; 138073034Sjwd seen_default_offset = 1; 138173034Sjwd } 138273034Sjwd } else { 138373034Sjwd /* allow them to be out of order for old-style tables */ 1384133347Sdes if (pp->p_offset < current_offset && 1385107534Sgrog seen_default_offset && i != RAW_PART && 1386107534Sgrog pp->p_fstype != FS_VINUM) { 138773034Sjwd fprintf(stderr, 138894065Sphk"Offset %ld for partition %c overlaps previous partition which ends at %lu\n", 138994065Sphk (long)pp->p_offset,i+'a',current_offset); 139073034Sjwd fprintf(stderr, 139173034Sjwd"Labels with any *'s for offset must be in ascending order by sector\n"); 139273034Sjwd errors++; 139373034Sjwd } else if (pp->p_offset != current_offset && 139494065Sphk i != RAW_PART && seen_default_offset) { 1395133347Sdes /* 1396133347Sdes * this may give unneeded warnings if 139773034Sjwd * partitions are out-of-order 139873034Sjwd */ 1399114574Sphk warnx( 140073034Sjwd"Offset %ld for partition %c doesn't match expected value %ld", 140194065Sphk (long)pp->p_offset, i + 'a', current_offset); 140273034Sjwd } 140373034Sjwd } 140494065Sphk if (i != RAW_PART) 1405133347Sdes current_offset = pp->p_offset + pp->p_size; 140673034Sjwd } 140773034Sjwd } 140873034Sjwd 140973034Sjwd for (i = 0; i < lp->d_npartitions; i++) { 141073034Sjwd part = 'a' + i; 141173034Sjwd pp = &lp->d_partitions[i]; 14121558Srgrimes if (pp->p_size == 0 && pp->p_offset != 0) 1413114574Sphk warnx("partition %c: size 0, but offset %lu", 141437234Sbde part, (u_long)pp->p_offset); 14151558Srgrimes#ifdef notdef 14161558Srgrimes if (pp->p_size % lp->d_secpercyl) 1417114574Sphk warnx("partition %c: size %% cylinder-size != 0", 14181558Srgrimes part); 14191558Srgrimes if (pp->p_offset % lp->d_secpercyl) 1420114574Sphk warnx("partition %c: offset %% cylinder-size != 0", 14211558Srgrimes part); 14221558Srgrimes#endif 14231558Srgrimes if (pp->p_offset > lp->d_secperunit) { 14241558Srgrimes fprintf(stderr, 14251558Srgrimes "partition %c: offset past end of unit\n", part); 14261558Srgrimes errors++; 14271558Srgrimes } 14281558Srgrimes if (pp->p_offset + pp->p_size > lp->d_secperunit) { 14291558Srgrimes fprintf(stderr, 143013544Sjoerg "partition %c: partition extends past end of unit\n", 14311558Srgrimes part); 14321558Srgrimes errors++; 14331558Srgrimes } 1434114574Sphk if (i == RAW_PART) { 143573034Sjwd if (pp->p_fstype != FS_UNUSED) 1436114574Sphk warnx("partition %c is not marked as unused!",part); 143773034Sjwd if (pp->p_offset != 0) 1438114574Sphk warnx("partition %c doesn't start at 0!",part); 143973034Sjwd if (pp->p_size != lp->d_secperunit) 1440114574Sphk warnx("partition %c doesn't cover the whole unit!",part); 144173034Sjwd 144273034Sjwd if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) || 144373034Sjwd (pp->p_size != lp->d_secperunit)) { 1444114574Sphk warnx("An incorrect partition %c may cause problems for " 144573034Sjwd "standard system utilities",part); 144673034Sjwd } 144773034Sjwd } 144873034Sjwd 144973034Sjwd /* check for overlaps */ 145073034Sjwd /* this will check for all possible overlaps once and only once */ 145173034Sjwd for (j = 0; j < i; j++) { 1452107534Sgrog pp2 = &lp->d_partitions[j]; 1453133347Sdes if (j != RAW_PART && i != RAW_PART && 1454107534Sgrog pp->p_fstype != FS_VINUM && 1455107534Sgrog pp2->p_fstype != FS_VINUM && 145673034Sjwd part_set[i] && part_set[j]) { 145773034Sjwd if (pp2->p_offset < pp->p_offset + pp->p_size && 145873034Sjwd (pp2->p_offset + pp2->p_size > pp->p_offset || 145973034Sjwd pp2->p_offset >= pp->p_offset)) { 146073034Sjwd fprintf(stderr,"partitions %c and %c overlap!\n", 146173034Sjwd j + 'a', i + 'a'); 146273034Sjwd errors++; 146373034Sjwd } 146473034Sjwd } 146573034Sjwd } 14661558Srgrimes } 1467174501Smarcel for (; i < lp->d_npartitions; i++) { 14681558Srgrimes part = 'a' + i; 14691558Srgrimes pp = &lp->d_partitions[i]; 14701558Srgrimes if (pp->p_size || pp->p_offset) 1471114574Sphk warnx("unused partition %c: size %d offset %lu", 147237234Sbde 'a' + i, pp->p_size, (u_long)pp->p_offset); 14731558Srgrimes } 14741558Srgrimes return (errors); 14751558Srgrimes} 14761558Srgrimes 14771558Srgrimes/* 147813550Sjoerg * When operating on a "virgin" disk, try getting an initial label 147913550Sjoerg * from the associated device driver. This might work for all device 148013550Sjoerg * drivers that are able to fetch some initial device parameters 148113550Sjoerg * without even having access to a (BSD) disklabel, like SCSI disks, 148213550Sjoerg * most IDE drives, or vn devices. 148313550Sjoerg * 148413550Sjoerg * The device name must be given in its "canonical" form. 148513550Sjoerg */ 1486114571Sphkstatic struct disklabel * 148713550Sjoerggetvirginlabel(void) 148813550Sjoerg{ 148999365Smarkm static struct disklabel loclab; 1490103669Sphk struct partition *dp; 149113550Sjoerg int f; 1492114574Sphk u_int u; 149313550Sjoerg 1494114571Sphk if ((f = open(specname, O_RDONLY)) == -1) { 1495114571Sphk warn("cannot open %s", specname); 149616431Sbde return (NULL); 149713550Sjoerg } 149868044Sjkh 1499127650Sluigi if (is_file) 1500127650Sluigi get_file_parms(f); 1501183143Slulf else { 1502183143Slulf mediasize = g_mediasize(f); 1503183143Slulf secsize = g_sectorsize(f); 1504183143Slulf if (secsize < 0 || mediasize < 0) { 1505183143Slulf close (f); 1506183143Slulf return (NULL); 1507183143Slulf } 1508103669Sphk } 1509103669Sphk memset(&loclab, 0, sizeof loclab); 1510103669Sphk loclab.d_magic = DISKMAGIC; 1511103669Sphk loclab.d_magic2 = DISKMAGIC; 1512103669Sphk loclab.d_secsize = secsize; 1513103669Sphk loclab.d_secperunit = mediasize / secsize; 1514103669Sphk 151568044Sjkh /* 1516103669Sphk * Nobody in these enligthened days uses the CHS geometry for 1517103669Sphk * anything, but nontheless try to get it right. If we fail 1518103669Sphk * to get any good ideas from the device, construct something 1519103669Sphk * which is IBM-PC friendly. 152068044Sjkh */ 1521103669Sphk if (ioctl(f, DIOCGFWSECTORS, &u) == 0) 1522103669Sphk loclab.d_nsectors = u; 1523103669Sphk else 1524103669Sphk loclab.d_nsectors = 63; 1525103669Sphk if (ioctl(f, DIOCGFWHEADS, &u) == 0) 1526103669Sphk loclab.d_ntracks = u; 1527103669Sphk else if (loclab.d_secperunit <= 63*1*1024) 1528103669Sphk loclab.d_ntracks = 1; 1529103669Sphk else if (loclab.d_secperunit <= 63*16*1024) 1530103669Sphk loclab.d_ntracks = 16; 1531103669Sphk else 1532103669Sphk loclab.d_ntracks = 255; 1533103669Sphk loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors; 1534103669Sphk loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl; 1535174501Smarcel loclab.d_npartitions = DEFPARTITIONS; 1536103669Sphk 1537103669Sphk /* Various (unneeded) compat stuff */ 1538103669Sphk loclab.d_rpm = 3600; 1539103669Sphk loclab.d_bbsize = BBSIZE; 1540114574Sphk loclab.d_interleave = 1; 1541103669Sphk strncpy(loclab.d_typename, "amnesiac", 1542103669Sphk sizeof(loclab.d_typename)); 1543103669Sphk 1544103669Sphk dp = &loclab.d_partitions[RAW_PART]; 1545103669Sphk dp->p_size = loclab.d_secperunit; 1546103669Sphk loclab.d_checksum = dkcksum(&loclab); 1547103669Sphk close (f); 154899365Smarkm return (&loclab); 154913550Sjoerg} 155013550Sjoerg 1551114571Sphkstatic void 155292541Simpusage(void) 15531558Srgrimes{ 1554112307Sru 1555112307Sru fprintf(stderr, 1556112307Sru "%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", 1557114569Sphk "usage: bsdlabel disk", 1558112307Sru "\t\t(to read label)", 1559114571Sphk " bsdlabel -w [-n] [-m machine] disk [type]", 1560112307Sru "\t\t(to write label with existing boot program)", 1561114569Sphk " bsdlabel -e [-n] [-m machine] disk", 1562112307Sru "\t\t(to edit label)", 1563114569Sphk " bsdlabel -R [-n] [-m machine] disk protofile", 1564112307Sru "\t\t(to restore label with existing boot program)", 1565113680Sphk " bsdlabel -B [-b boot] [-m machine] disk", 1566112307Sru "\t\t(to install boot program with existing on-disk label)", 1567114571Sphk " bsdlabel -w -B [-n] [-b boot] [-m machine] disk [type]", 1568112307Sru "\t\t(to write label and install boot program)", 1569113680Sphk " bsdlabel -R -B [-n] [-b boot] [-m machine] disk protofile", 1570109878Sphk "\t\t(to restore label and install boot program)" 1571109878Sphk ); 15721558Srgrimes exit(1); 15731558Srgrimes} 1574