bsdlabel.c revision 6643
1139804Simp/* 246197Sphk * Copyright (c) 1987, 1993 346197Sphk * The Regents of the University of California. All rights reserved. 446197Sphk * 546197Sphk * This code is derived from software contributed to Berkeley by 646197Sphk * Symmetric Computer Systems. 746197Sphk * 846197Sphk * Redistribution and use in source and binary forms, with or without 946155Sphk * modification, are permitted provided that the following conditions 10116182Sobrien * are met: 11116182Sobrien * 1. Redistributions of source code must retain the above copyright 12116182Sobrien * notice, this list of conditions and the following disclaimer. 13131177Spjd * 2. Redistributions in binary form must reproduce the above copyright 14131177Spjd * notice, this list of conditions and the following disclaimer in the 1546155Sphk * documentation and/or other materials provided with the distribution. 1646155Sphk * 3. All advertising materials mentioning features or use of this software 1746155Sphk * must display the following acknowledgement: 1846155Sphk * This product includes software developed by the University of 1946155Sphk * California, Berkeley and its contributors. 2046155Sphk * 4. Neither the name of the University nor the names of its contributors 2146155Sphk * may be used to endorse or promote products derived from this software 22164032Srwatson * without specific prior written permission. 2346155Sphk * 24124882Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25177785Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2646155Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2787275Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2887275Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29168401Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30113275Smike * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31147185Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32113275Smike * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3346155Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34113275Smike * SUCH DAMAGE. 3557163Srwatson */ 36113275Smike 3746155Sphk#ifndef lint 3846155Sphkstatic char copyright[] = 3946155Sphk"@(#) Copyright (c) 1987, 1993\n\ 40163606Srwatson The Regents of the University of California. All rights reserved.\n"; 41163606Srwatson#endif /* not lint */ 4246155Sphk 4346155Sphk#ifndef lint 4489414Sarrstatic char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; 4557163Srwatson/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ 4657163Srwatson#endif /* not lint */ 4757163Srwatson 4889414Sarr#include <sys/param.h> 4957163Srwatson#include <sys/signal.h> 5057163Srwatson#include <sys/errno.h> 5157163Srwatson#include <sys/file.h> 5261235Srwatson#include <sys/ioctl.h> 5389414Sarr#include <sys/stat.h> 5461235Srwatson#define DKTYPENAMES 5561235Srwatson#include <sys/disklabel.h> 5661235Srwatson#include <ufs/ffs/fs.h> 5768024Srwatson#include <unistd.h> 5889414Sarr#include <string.h> 5968024Srwatson#include <stdio.h> 6068024Srwatson#include <ctype.h> 6168024Srwatson#include "pathnames.h" 62147185Spjd 63147185Spjd/* 64147185Spjd * Disklabel: read and write disklabels. 65147185Spjd * The label is usually placed on one of the first sectors of the disk. 66125804Srwatson * Many machines also place a bootstrap in the same area, 67128664Sbmilekic * in which case the label is embedded in the bootstrap. 68128664Sbmilekic * The bootstrap source must leave space at the proper offset 69128664Sbmilekic * for the label on such machines. 70128664Sbmilekic */ 71128664Sbmilekic 72141543Scperciva#ifdef tahoe 73141543Scperciva#define RAWPARTITION 'a' 74141543Scperciva#else 75141543Scperciva#define RAWPARTITION 'c' 76141543Scperciva#endif 77168396Spjd 78168396Spjd#ifndef BBSIZE 79168396Spjd#define BBSIZE 8192 /* size of boot area, with label */ 80168396Spjd#endif 81168396Spjd 82179881Sdelphij#ifdef tahoe 83179881Sdelphij#define NUMBOOT 0 84168401Spjd#else 85179881Sdelphij#if defined(hp300) || defined(hp800) 86113275Smike#define NUMBOOT 1 87113275Smike#else 88168401Spjd#define NUMBOOT 2 89168401Spjd#endif 90168401Spjd#endif 91168401Spjd 92168401Spjd#define DEFEDITOR _PATH_VI 93168401Spjd#define streq(a,b) (strcmp(a,b) == 0) 94168401Spjd 95168401Spjdchar *dkname; 96168401Spjdchar *specname; 97168401Spjdchar tmpfil[] = _PATH_TMP; 98168401Spjd 99168401Spjdextern int errno; 100168401Spjdchar namebuf[BBSIZE], *np = namebuf; 101168401Spjdstruct disklabel lab; 102168401Spjdstruct disklabel *readlabel(), *makebootarea(); 103168401Spjdchar bootarea[BBSIZE]; 104113275Smike 105124882Srwatson#if NUMBOOT > 0 106113275Smikeint installboot; /* non-zero if we should install a boot program */ 107113275Smikechar *bootbuf; /* pointer to buffer with remainder of boot prog */ 108113275Smikeint bootsize; /* size of remaining boot program */ 109113275Smikechar *xxboot; /* primary boot */ 110113275Smikechar *bootxx; /* secondary boot */ 111113275Smikechar boot0[MAXPATHLEN]; 112179881Sdelphijchar boot1[MAXPATHLEN]; 113179881Sdelphij#endif 114113275Smike 115113275Smikeenum { 116113275Smike UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT 117113275Smike} op = UNSPEC; 11882710Sdillon 119114168Smikeint rflag; 120114168Smike 121114168Smike#ifdef DEBUG 12282710Sdillonint debug; 12346155Sphk#define OPTIONS "BNRWb:ders:w" 124114168Smike#else 12546155Sphk#define OPTIONS "BNRWb:ers:w" 126113275Smike#endif 127179881Sdelphij 128168401Spjd 12946155Sphkmain(argc, argv) 130113275Smike int argc; 131179881Sdelphij char *argv[]; 13246155Sphk{ 133114168Smike extern char *optarg; 13446155Sphk extern int optind; 13584828Sjhb register struct disklabel *lp; 13684828Sjhb FILE *t; 13784828Sjhb int ch, f, flag, error = 0; 13884828Sjhb char *name = 0; 139114168Smike 14093818Sjhb while ((ch = getopt(argc, argv, OPTIONS)) != EOF) 141113275Smike switch (ch) { 142114168Smike#if NUMBOOT > 0 143113275Smike case 'B': 144113275Smike ++installboot; 145150652Scsjp break; 146150652Scsjp case 'b': 147113275Smike xxboot = optarg; 148150652Scsjp break; 149113275Smike#if NUMBOOT > 1 150150652Scsjp case 's': 151113275Smike bootxx = optarg; 152175294Sattilio break; 153113275Smike#endif 154150652Scsjp#endif 155114168Smike case 'N': 15684828Sjhb if (op != UNSPEC) 157113275Smike usage(); 158113275Smike op = NOWRITE; 159113275Smike break; 160113275Smike case 'R': 161168401Spjd if (op != UNSPEC) 162168401Spjd usage(); 163168401Spjd op = RESTORE; 164168401Spjd break; 165168401Spjd case 'W': 166168401Spjd if (op != UNSPEC) 167113275Smike usage(); 168179881Sdelphij op = WRITEABLE; 169168401Spjd break; 170179881Sdelphij case 'e': 171179881Sdelphij if (op != UNSPEC) 172179881Sdelphij usage(); 173179881Sdelphij op = EDIT; 174179881Sdelphij break; 175179881Sdelphij case 'r': 176179881Sdelphij ++rflag; 177179881Sdelphij break; 178179881Sdelphij case 'w': 179179881Sdelphij if (op != UNSPEC) 180179881Sdelphij usage(); 181179881Sdelphij op = WRITE; 182179881Sdelphij break; 183179881Sdelphij#ifdef DEBUG 184179881Sdelphij case 'd': 185179881Sdelphij debug++; 186113275Smike break; 187113275Smike#endif 188168401Spjd case '?': 189168401Spjd default: 190168401Spjd usage(); 191168401Spjd } 192168401Spjd argc -= optind; 193113275Smike argv += optind; 194113275Smike#if NUMBOOT > 0 195113275Smike if (installboot) { 196113275Smike rflag++; 197113275Smike if (op == UNSPEC) 198113275Smike op = WRITEBOOT; 199113275Smike } else { 200113275Smike if (op == UNSPEC) 201113275Smike op = READ; 202113275Smike xxboot = bootxx = 0; 203168401Spjd } 204113275Smike#else 205113275Smike if (op == UNSPEC) 206168401Spjd op = READ; 207168401Spjd#endif 208168401Spjd if (argc < 1) 209168401Spjd usage(); 210168401Spjd 211113275Smike dkname = argv[0]; 212150652Scsjp if (dkname[0] != '/') { 213113275Smike (void)sprintf(np, "%sr%s%c", _PATH_DEV, dkname, RAWPARTITION); 214150652Scsjp specname = np; 215113275Smike np += strlen(specname) + 1; 216113275Smike } else 217113275Smike specname = dkname; 218113275Smike f = open(specname, op == READ ? O_RDONLY : O_RDWR); 219113275Smike if (f < 0 && errno == ENOENT && dkname[0] != '/') { 220113275Smike (void)sprintf(specname, "%sr%s", _PATH_DEV, dkname); 221113275Smike np = namebuf + strlen(specname) + 1; 222114168Smike f = open(specname, op == READ ? O_RDONLY : O_RDWR); 223114168Smike } 224114168Smike if (f < 0) 225113275Smike Perror(specname); 226113275Smike 227114168Smike switch(op) { 228113275Smike 229113275Smike case EDIT: 230113275Smike if (argc != 1) 231113275Smike usage(); 232150652Scsjp lp = readlabel(f); 233167309Spjd error = edit(lp, f); 234126023Snectar break; 235126023Snectar 236126023Snectar case NOWRITE: 237126023Snectar flag = 0; 238126023Snectar if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 239126023Snectar Perror("ioctl DIOCWLABEL"); 240126023Snectar break; 241126023Snectar 242164032Srwatson case READ: 243126023Snectar if (argc != 1) 244126023Snectar usage(); 245126023Snectar lp = readlabel(f); 246113275Smike display(stdout, lp); 247168401Spjd error = checklabel(lp); 248113275Smike break; 249113275Smike 250168401Spjd case RESTORE: 251113275Smike#if NUMBOOT > 0 252113275Smike if (installboot && argc == 3) { 253113275Smike makelabel(argv[2], 0, &lab); 254113275Smike argc--; 255168401Spjd } 256113275Smike#endif 257150652Scsjp if (argc != 2) 258175202Sattilio usage(); 259113275Smike lp = makebootarea(bootarea, &lab, f); 260113275Smike if (!(t = fopen(argv[1], "r"))) 261113275Smike Perror(argv[1]); 262172930Srwatson if (getasciilabel(t, lp)) 263113275Smike error = writelabel(f, bootarea, lp); 264113275Smike break; 265175294Sattilio 266113275Smike case WRITE: 267150652Scsjp if (argc == 3) { 268113275Smike name = argv[2]; 26984828Sjhb argc--; 27084828Sjhb } 27184828Sjhb if (argc != 2) 272113275Smike usage(); 27384828Sjhb makelabel(argv[1], name, &lab); 274113630Sjhb lp = makebootarea(bootarea, &lab, f); 27584828Sjhb *lp = lab; 27684828Sjhb if (checklabel(lp) == 0) 27784828Sjhb error = writelabel(f, bootarea, lp); 27846155Sphk break; 279113275Smike 280175294Sattilio case WRITEABLE: 281150652Scsjp flag = 1; 282113275Smike if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) 283113275Smike Perror("ioctl DIOCWLABEL"); 284113275Smike break; 28546155Sphk 28646155Sphk#if NUMBOOT > 0 28746155Sphk case WRITEBOOT: 288113275Smike { 289113275Smike struct disklabel tlab; 290113275Smike 291168399Spjd lp = readlabel(f); 292113275Smike tlab = *lp; 293113275Smike if (argc == 2) 294113275Smike makelabel(argv[1], 0, &lab); 295113275Smike lp = makebootarea(bootarea, &lab, f); 296168401Spjd *lp = tlab; 297113275Smike if (checklabel(lp) == 0) 298113275Smike error = writelabel(f, bootarea, lp); 299113275Smike break; 300168489Spjd } 301168489Spjd#endif 302168489Spjd } 303168489Spjd exit(error); 304113275Smike} 305113275Smike 306113275Smike/* 307113275Smike * Construct a prototype disklabel from /etc/disktab. As a side 308113275Smike * effect, set the names of the primary and secondary boot files 309113275Smike * if specified. 31072786Srwatson */ 31172786Srwatsonmakelabel(type, name, lp) 31272786Srwatson char *type, *name; 31372786Srwatson register struct disklabel *lp; 31487275Srwatson{ 31572786Srwatson register struct disklabel *dp; 31672786Srwatson char *strcpy(); 317168483Spjd 318124882Srwatson dp = getdiskbyname(type); 319144660Sjeff if (dp == NULL) { 32087275Srwatson fprintf(stderr, "%s: unknown disk type\n", type); 32172786Srwatson exit(1); 32287275Srwatson } 32372786Srwatson *lp = *dp; 32472786Srwatson#if NUMBOOT > 0 325124882Srwatson /* 326124882Srwatson * Set bootstrap name(s). 327124882Srwatson * 1. If set from command line, use those, 328168489Spjd * 2. otherwise, check if disktab specifies them (b0 or b1), 329124882Srwatson * 3. otherwise, makebootarea() will choose ones based on the name 330150652Scsjp * of the disk special file. E.g. /dev/ra0 -> raboot, bootra 331124882Srwatson */ 332124882Srwatson if (!xxboot && lp->d_boot0) { 333124882Srwatson if (*lp->d_boot0 != '/') 334168489Spjd (void)sprintf(boot0, "%s/%s", 335168489Spjd _PATH_BOOTDIR, lp->d_boot0); 336168489Spjd else 337168489Spjd (void)strcpy(boot0, lp->d_boot0); 338168489Spjd xxboot = boot0; 339168489Spjd } 340168489Spjd#if NUMBOOT > 1 341168489Spjd if (!bootxx && lp->d_boot1) { 342168489Spjd if (*lp->d_boot1 != '/') 343150652Scsjp (void)sprintf(boot1, "%s/%s", 344124882Srwatson _PATH_BOOTDIR, lp->d_boot1); 345150652Scsjp else 346124882Srwatson (void)strcpy(boot1, lp->d_boot1); 347124882Srwatson bootxx = boot1; 348124882Srwatson } 349124882Srwatson#endif 350124882Srwatson#endif 351124882Srwatson /* d_packname is union d_boot[01], so zero */ 352124882Srwatson bzero(lp->d_packname, sizeof(lp->d_packname)); 35372786Srwatson if (name) 35472786Srwatson (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); 35572786Srwatson} 35672786Srwatson 35787275Srwatsonwritelabel(f, boot, lp) 358168489Spjd int f; 359168489Spjd char *boot; 36072786Srwatson register struct disklabel *lp; 36187275Srwatson{ 36272786Srwatson register int i; 36372786Srwatson int flag; 36487275Srwatson 36587275Srwatson setbootflag(lp); 36687275Srwatson lp->d_magic = DISKMAGIC; 36787275Srwatson lp->d_magic2 = DISKMAGIC; 36887275Srwatson lp->d_checksum = 0; 36987275Srwatson lp->d_checksum = dkcksum(lp); 37087275Srwatson if (rflag) { 37146155Sphk /* 37272786Srwatson * First set the kernel disk label, 37346155Sphk * then write a label to the raw disk. 37446155Sphk * If the SDINFO ioctl fails because it is unimplemented, 37546155Sphk * keep going; otherwise, the kernel consistency checks 37672786Srwatson * may prevent us from changing the current (in-core) 37746155Sphk * label. 378167309Spjd */ 37946155Sphk if (ioctl(f, DIOCSDINFO, lp) < 0 && 38046155Sphk errno != ENODEV && errno != ENOTTY) { 38146155Sphk l_perror("ioctl DIOCSDINFO"); 38246155Sphk return (1); 383167309Spjd } 38472786Srwatson (void)lseek(f, (off_t)0, SEEK_SET); 38546155Sphk /* 38672786Srwatson * write enable label sector before write (if necessary), 38746155Sphk * disable after writing. 38846155Sphk */ 38981114Srwatson flag = 1; 39081114Srwatson if (ioctl(f, DIOCWLABEL, &flag) < 0) 39181114Srwatson perror("ioctl DIOCWLABEL"); 39281114Srwatson if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { 39381114Srwatson perror("write"); 39481114Srwatson return (1); 39581114Srwatson } 39672786Srwatson#if NUMBOOT > 0 39746155Sphk /* 39846155Sphk * Output the remainder of the disklabel 39946155Sphk */ 40046155Sphk if (bootbuf && write(f, bootbuf, bootsize) != bootsize) { 40146155Sphk perror("write"); 40272786Srwatson return(1); 40346155Sphk } 40446155Sphk#endif 40546155Sphk flag = 0; 40672786Srwatson (void) ioctl(f, DIOCWLABEL, &flag); 40746155Sphk } else if (ioctl(f, DIOCWDINFO, lp) < 0) { 40846155Sphk l_perror("ioctl DIOCWDINFO"); 40946155Sphk return (1); 41046155Sphk } 41146155Sphk#ifdef vax 41281114Srwatson if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 41346155Sphk daddr_t alt; 41472786Srwatson 41546155Sphk alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 41672786Srwatson for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 41746155Sphk (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), 41846155Sphk SEEK_SET); 41946155Sphk if (write(f, boot, lp->d_secsize) < lp->d_secsize) { 42046155Sphk int oerrno = errno; 42146155Sphk fprintf(stderr, "alternate label %d ", i/2); 42246155Sphk errno = oerrno; 42372786Srwatson perror("write"); 42446155Sphk } 425114168Smike } 42646155Sphk } 42746155Sphk#endif 428114168Smike return (0); 42961235Srwatson} 43061235Srwatson 43161235Srwatsonl_perror(s) 43246155Sphk char *s; 43372786Srwatson{ 43446155Sphk int saverrno = errno; 43546155Sphk 43646155Sphk fprintf(stderr, "disklabel: %s: ", s); 43746155Sphk 43846155Sphk switch (saverrno) { 43972786Srwatson 44072786Srwatson case ESRCH: 44172786Srwatson fprintf(stderr, "No disk label on disk;\n"); 44272786Srwatson fprintf(stderr, 44372786Srwatson "use \"disklabel -r\" to install initial label\n"); 444114168Smike break; 44572786Srwatson 44672786Srwatson case EINVAL: 44772786Srwatson fprintf(stderr, "Label magic number or checksum is wrong!\n"); 44872786Srwatson fprintf(stderr, "(disklabel or kernel is out of date?)\n"); 44972786Srwatson break; 45072786Srwatson 45172786Srwatson case EBUSY: 45272786Srwatson fprintf(stderr, "Open partition would move or shrink\n"); 45372786Srwatson break; 45472786Srwatson 45572786Srwatson case EXDEV: 45672786Srwatson fprintf(stderr, 45772786Srwatson "Labeled partition or 'a' partition must start at beginning of disk\n"); 45872786Srwatson break; 45972786Srwatson 46072786Srwatson default: 461114168Smike errno = saverrno; 46272786Srwatson perror((char *)NULL); 46372786Srwatson break; 46472786Srwatson } 46572786Srwatson} 46691384Srobert 46791384Srobert/* 46891384Srobert * Fetch disklabel for disk. 46991384Srobert * Use ioctl to get label unless -r flag is given. 47091391Srobert */ 471114168Smikestruct disklabel * 47291384Srobertreadlabel(f) 47391384Srobert int f; 47491391Srobert{ 47591391Srobert register struct disklabel *lp; 476105354Srobert 47791391Srobert if (rflag) { 478114168Smike if (read(f, bootarea, BBSIZE) < BBSIZE) 479105354Srobert Perror(specname); 48091384Srobert for (lp = (struct disklabel *)bootarea; 481113275Smike lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); 482125804Srwatson lp = (struct disklabel *)((char *)lp + 16)) 483147185Spjd if (lp->d_magic == DISKMAGIC && 484147185Spjd lp->d_magic2 == DISKMAGIC) 485147185Spjd break; 486147185Spjd if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || 487147185Spjd lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || 488125804Srwatson dkcksum(lp) != 0) { 489125804Srwatson fprintf(stderr, 490147185Spjd "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); 491125804Srwatson /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */ 492147185Spjd exit (1); 493147185Spjd } 494147185Spjd } else { 495125804Srwatson lp = &lab; 496147185Spjd if (ioctl(f, DIOCGDINFO, lp) < 0) 497147185Spjd Perror("ioctl DIOCGDINFO"); 498147185Spjd } 499147185Spjd return (lp); 500147185Spjd} 501147185Spjd 502147185Spjd/* 503147185Spjd * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' 504147185Spjd * Returns a pointer to the disklabel portion of the bootarea. 505147185Spjd */ 506147185Spjdstruct disklabel * 507147185Spjdmakebootarea(boot, dp, f) 508147185Spjd char *boot; 509147185Spjd register struct disklabel *dp; 510147185Spjd int f; 511147185Spjd{ 512147185Spjd struct disklabel *lp; 513147185Spjd register char *p; 514147185Spjd int b; 515147185Spjd#if NUMBOOT > 0 516147185Spjd char *dkbasename; 517147185Spjd struct stat sb; 518147185Spjd#endif 519147185Spjd 520147185Spjd /* XXX */ 521147185Spjd if (dp->d_secsize == 0) { 522147185Spjd dp->d_secsize = DEV_BSIZE; 523147185Spjd dp->d_bbsize = BBSIZE; 524147185Spjd } 525147185Spjd lp = (struct disklabel *) 526147185Spjd (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); 527147185Spjd bzero((char *)lp, sizeof *lp); 528147185Spjd#if NUMBOOT > 0 529147185Spjd /* 530147185Spjd * If we are not installing a boot program but we are installing a 531147185Spjd * label on disk then we must read the current bootarea so we don't 532147185Spjd * clobber the existing boot. 533147185Spjd */ 534147185Spjd if (!installboot) { 535147185Spjd if (rflag) { 536147185Spjd if (read(f, boot, BBSIZE) < BBSIZE) 537147185Spjd Perror(specname); 538147185Spjd bzero((char *)lp, sizeof *lp); 539125804Srwatson } 540147185Spjd return (lp); 541147185Spjd } 542147185Spjd /* 543147185Spjd * We are installing a boot program. Determine the name(s) and 544147185Spjd * read them into the appropriate places in the boot area. 545147185Spjd */ 546147185Spjd if (!xxboot || !bootxx) { 547147185Spjd dkbasename = np; 548147185Spjd if ((p = rindex(dkname, '/')) == NULL) 549147185Spjd p = dkname; 550147185Spjd else 551147185Spjd p++; 552147185Spjd while (*p && !isdigit(*p)) 553147185Spjd *np++ = *p++; 554147185Spjd *np++ = '\0'; 555147185Spjd 556147185Spjd if (!xxboot) { 557147185Spjd (void)sprintf(np, "%s/%sboot", 558147185Spjd _PATH_BOOTDIR, dkbasename); 559147185Spjd if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 560147185Spjd dkbasename++; 561147185Spjd xxboot = np; 562147185Spjd (void)sprintf(xxboot, "%s/%sboot", 563147185Spjd _PATH_BOOTDIR, dkbasename); 564147185Spjd np += strlen(xxboot) + 1; 565147185Spjd } 566147185Spjd#if NUMBOOT > 1 567147185Spjd if (!bootxx) { 568125804Srwatson (void)sprintf(np, "%s/boot%s", 569125804Srwatson _PATH_BOOTDIR, dkbasename); 570164032Srwatson if (access(np, F_OK) < 0 && dkbasename[0] == 'r') 571164032Srwatson dkbasename++; 572164032Srwatson bootxx = np; 573164032Srwatson (void)sprintf(bootxx, "%s/boot%s", 574164032Srwatson _PATH_BOOTDIR, dkbasename); 575164032Srwatson np += strlen(bootxx) + 1; 576164032Srwatson } 577164032Srwatson#endif 578164032Srwatson } 579164032Srwatson#ifdef DEBUG 580164032Srwatson if (debug) 581164032Srwatson fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n", 582164032Srwatson xxboot, bootxx ? bootxx : "NONE"); 583164032Srwatson#endif 584164032Srwatson 585164032Srwatson /* 586164032Srwatson * Strange rules: 587164032Srwatson * 1. One-piece bootstrap (hp300/hp800) 588166827Srwatson * up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest 589164032Srwatson * is remembered and written later following the bootarea. 590164032Srwatson * 2. Two-piece bootstraps (vax/i386?/mips?) 591164032Srwatson * up to d_secsize bytes of ``xxboot'' go in first d_secsize 592164032Srwatson * bytes of bootarea, remaining d_bbsize-d_secsize filled 593164032Srwatson * from ``bootxx''. 594164032Srwatson */ 595164032Srwatson b = open(xxboot, O_RDONLY); 596164032Srwatson if (b < 0) 597164032Srwatson Perror(xxboot); 598166827Srwatson#if NUMBOOT > 1 599164032Srwatson if (read(b, boot, (int)dp->d_secsize) < 0) 600164032Srwatson Perror(xxboot); 601164032Srwatson (void)close(b); 602164032Srwatson b = open(bootxx, O_RDONLY); 603164032Srwatson if (b < 0) 604164032Srwatson Perror(bootxx); 605164032Srwatson if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) 606164032Srwatson Perror(bootxx); 607164032Srwatson#else 608164032Srwatson if (read(b, boot, (int)dp->d_bbsize) < 0) 609164032Srwatson Perror(xxboot); 610164032Srwatson (void)fstat(b, &sb); 611164032Srwatson bootsize = (int)sb.st_size - dp->d_bbsize; 612164032Srwatson if (bootsize > 0) { 613164032Srwatson /* XXX assume d_secsize is a power of two */ 614164032Srwatson bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1); 615164032Srwatson bootbuf = (char *)malloc((size_t)bootsize); 616164032Srwatson if (bootbuf == 0) 617164032Srwatson Perror(xxboot); 618164032Srwatson if (read(b, bootbuf, bootsize) < 0) { 619164032Srwatson free(bootbuf); 620164032Srwatson Perror(xxboot); 621164032Srwatson } 622164032Srwatson } 623164032Srwatson#endif 624164032Srwatson (void)close(b); 625164032Srwatson#endif 626164032Srwatson /* 627164032Srwatson * Make sure no part of the bootstrap is written in the area 628164032Srwatson * reserved for the label. 629164032Srwatson */ 630164032Srwatson for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++) 631164032Srwatson if (*p) { 632164032Srwatson fprintf(stderr, 633164032Srwatson "Bootstrap doesn't leave room for disk label\n"); 634164032Srwatson exit(2); 635164032Srwatson } 636164032Srwatson return (lp); 637164032Srwatson} 638164032Srwatson 639164032Srwatsondisplay(f, lp) 640164032Srwatson FILE *f; 641164032Srwatson register struct disklabel *lp; 642164032Srwatson{ 643164032Srwatson register int i, j; 644164032Srwatson register struct partition *pp; 645164032Srwatson 646164032Srwatson fprintf(f, "# %s:\n", specname); 647164032Srwatson if ((unsigned) lp->d_type < DKMAXTYPES) 648164032Srwatson fprintf(f, "type: %s\n", dktypenames[lp->d_type]); 649164032Srwatson else 650164032Srwatson fprintf(f, "type: %d\n", lp->d_type); 651164032Srwatson fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); 652164032Srwatson fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname); 653164032Srwatson fprintf(f, "flags:"); 654164032Srwatson if (lp->d_flags & D_REMOVABLE) 655164032Srwatson fprintf(f, " removeable"); 656164032Srwatson if (lp->d_flags & D_ECC) 657164032Srwatson fprintf(f, " ecc"); 658164032Srwatson if (lp->d_flags & D_BADSECT) 659164032Srwatson fprintf(f, " badsect"); 660164032Srwatson fprintf(f, "\n"); 661164032Srwatson fprintf(f, "bytes/sector: %d\n", lp->d_secsize); 662164032Srwatson fprintf(f, "sectors/track: %d\n", lp->d_nsectors); 663166831Srwatson fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); 664166831Srwatson fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); 665164032Srwatson fprintf(f, "cylinders: %d\n", lp->d_ncylinders); 666166832Srwatson fprintf(f, "sectors/unit: %d\n", lp->d_secperunit); 667166832Srwatson fprintf(f, "rpm: %d\n", lp->d_rpm); 668164032Srwatson fprintf(f, "interleave: %d\n", lp->d_interleave); 669164032Srwatson fprintf(f, "trackskew: %d\n", lp->d_trackskew); 670164032Srwatson fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); 671164032Srwatson fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); 672164032Srwatson fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); 673164032Srwatson fprintf(f, "drivedata: "); 674164032Srwatson for (i = NDDATA - 1; i >= 0; i--) 675164032Srwatson if (lp->d_drivedata[i]) 676164032Srwatson break; 677164032Srwatson if (i < 0) 678164032Srwatson i = 0; 679164032Srwatson for (j = 0; j <= i; j++) 680164032Srwatson fprintf(f, "%d ", lp->d_drivedata[j]); 681164032Srwatson fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); 682164032Srwatson fprintf(f, 683164032Srwatson "# size offset fstype [fsize bsize bps/cpg]\n"); 684167152Spjd pp = lp->d_partitions; 685164032Srwatson for (i = 0; i < lp->d_npartitions; i++, pp++) { 686164032Srwatson if (pp->p_size) { 687164032Srwatson fprintf(f, " %c: %8d %8d ", 'a' + i, 688172860Srwatson pp->p_size, pp->p_offset); 689164032Srwatson if ((unsigned) pp->p_fstype < FSMAXTYPES) 690164032Srwatson fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); 691164032Srwatson else 692164032Srwatson fprintf(f, "%8d", pp->p_fstype); 693164032Srwatson switch (pp->p_fstype) { 694164032Srwatson 695164032Srwatson case FS_UNUSED: /* XXX */ 696164032Srwatson fprintf(f, " %5d %5d %5.5s ", 697164032Srwatson pp->p_fsize, pp->p_fsize * pp->p_frag, ""); 698164032Srwatson break; 699164032Srwatson 700164032Srwatson case FS_BSDFFS: 701164032Srwatson fprintf(f, " %5d %5d %5d ", 702164032Srwatson pp->p_fsize, pp->p_fsize * pp->p_frag, 703168396Spjd pp->p_cpg); 704168396Spjd break; 705168396Spjd 706168396Spjd case FS_BSDLFS: 707168396Spjd fprintf(f, " %5d %5d %5d", 708168396Spjd pp->p_fsize, pp->p_fsize * pp->p_frag, 709168699Spjd pp->p_cpg); 710168396Spjd break; 711168396Spjd 712168396Spjd default: 713168396Spjd fprintf(f, "%20.20s", ""); 714168396Spjd break; 715168396Spjd } 716168591Srwatson fprintf(f, "\t# (Cyl. %4d", 717168591Srwatson pp->p_offset / lp->d_secpercyl); 718164032Srwatson if (pp->p_offset % lp->d_secpercyl) 719164032Srwatson putc('*', f); 720168591Srwatson else 721164032Srwatson putc(' ', f); 722164032Srwatson fprintf(f, "- %d", 723164032Srwatson (pp->p_offset + 724175630Sbz pp->p_size + lp->d_secpercyl - 1) / 725175630Sbz lp->d_secpercyl - 1); 726175630Sbz if (pp->p_size % lp->d_secpercyl) 727175630Sbz putc('*', f); 728175630Sbz fprintf(f, ")\n"); 729175630Sbz } 730164032Srwatson } 731164032Srwatson fflush(f); 732164032Srwatson} 733164032Srwatson 734164032Srwatsonedit(lp, f) 735164032Srwatson struct disklabel *lp; 736164032Srwatson int f; 737164032Srwatson{ 738164032Srwatson register int c; 739164032Srwatson struct disklabel label; 740164032Srwatson FILE *fd; 741164032Srwatson char *mktemp(); 742164032Srwatson 743164032Srwatson (void) mktemp(tmpfil); 744164032Srwatson fd = fopen(tmpfil, "w"); 745164032Srwatson if (fd == NULL) { 746164032Srwatson fprintf(stderr, "%s: Can't create\n", tmpfil); 747164032Srwatson return (1); 748164032Srwatson } 749164032Srwatson (void)fchmod(fileno(fd), 0600); 750164032Srwatson display(fd, lp); 751164032Srwatson fclose(fd); 752164032Srwatson for (;;) { 753164032Srwatson if (!editit()) 754164032Srwatson break; 755164032Srwatson fd = fopen(tmpfil, "r"); 756168401Spjd if (fd == NULL) { 757168401Spjd fprintf(stderr, "%s: Can't reopen for reading\n", 758168401Spjd tmpfil); 759168401Spjd break; 760168401Spjd } 761168401Spjd bzero((char *)&label, sizeof(label)); 762168401Spjd if (getasciilabel(fd, &label)) { 763168401Spjd *lp = label; 764168401Spjd if (writelabel(f, bootarea, lp) == 0) { 765168401Spjd (void) unlink(tmpfil); 766168401Spjd return (0); 767168401Spjd } 768168401Spjd } 769168401Spjd printf("re-edit the label? [y]: "); fflush(stdout); 770168401Spjd c = getchar(); 771168401Spjd if (c != EOF && c != (int)'\n') 772168401Spjd while (getchar() != (int)'\n') 773168401Spjd ; 774168401Spjd if (c == (int)'n') 775168401Spjd break; 776168401Spjd } 777168401Spjd (void) unlink(tmpfil); 778168401Spjd return (1); 779168401Spjd} 780168401Spjd 781168401Spjdeditit() 782168401Spjd{ 783168401Spjd register int pid, xpid; 784168401Spjd int stat, omask; 785168401Spjd extern char *getenv(); 786168401Spjd 787168401Spjd omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); 788168401Spjd while ((pid = fork()) < 0) { 789168401Spjd extern int errno; 790168401Spjd 791168401Spjd if (errno == EPROCLIM) { 792168401Spjd fprintf(stderr, "You have too many processes\n"); 793168401Spjd return(0); 794168401Spjd } 795168401Spjd if (errno != EAGAIN) { 796168401Spjd perror("fork"); 797168401Spjd return(0); 798168401Spjd } 799168401Spjd sleep(1); 800168401Spjd } 801168401Spjd if (pid == 0) { 802168401Spjd register char *ed; 803168401Spjd 804168401Spjd sigsetmask(omask); 805168401Spjd setgid(getgid()); 806168401Spjd setuid(getuid()); 807168401Spjd if ((ed = getenv("EDITOR")) == (char *)0) 808168401Spjd ed = DEFEDITOR; 809168401Spjd execlp(ed, ed, tmpfil, 0); 810168401Spjd perror(ed); 811168401Spjd exit(1); 812168401Spjd } 813168401Spjd while ((xpid = wait(&stat)) >= 0) 814168401Spjd if (xpid == pid) 815168401Spjd break; 816168401Spjd sigsetmask(omask); 817168401Spjd return(!stat); 818168401Spjd} 819168401Spjd 820168401Spjdchar * 821168401Spjdskip(cp) 822168401Spjd register char *cp; 823168401Spjd{ 824168401Spjd 825168401Spjd while (*cp != '\0' && isspace(*cp)) 826168401Spjd cp++; 827168401Spjd if (*cp == '\0' || *cp == '#') 828168401Spjd return ((char *)NULL); 829168401Spjd return (cp); 830168401Spjd} 831168401Spjd 832168401Spjdchar * 833168401Spjdword(cp) 834168401Spjd register char *cp; 835168401Spjd{ 836168401Spjd register char c; 837168401Spjd 838168401Spjd while (*cp != '\0' && !isspace(*cp) && *cp != '#') 839168401Spjd cp++; 840168401Spjd if ((c = *cp) != '\0') { 841168401Spjd *cp++ = '\0'; 842168401Spjd if (c != '#') 843168401Spjd return (skip(cp)); 844168401Spjd } 845168401Spjd return ((char *)NULL); 846168401Spjd} 847168401Spjd 848168401Spjd/* 849168401Spjd * Read an ascii label in from fd f, 850168401Spjd * in the same format as that put out by display(), 851168401Spjd * and fill in lp. 852168401Spjd */ 853168401Spjdgetasciilabel(f, lp) 854168401Spjd FILE *f; 855168401Spjd register struct disklabel *lp; 856168401Spjd{ 857168401Spjd register char **cpp, *cp; 858168401Spjd register struct partition *pp; 859168401Spjd char *tp, *s, line[BUFSIZ]; 860168401Spjd int v, lineno = 0, errors = 0; 861168401Spjd 862168401Spjd lp->d_bbsize = BBSIZE; /* XXX */ 863168401Spjd lp->d_sbsize = SBSIZE; /* XXX */ 864168401Spjd while (fgets(line, sizeof(line) - 1, f)) { 865168401Spjd lineno++; 866168401Spjd if (cp = index(line,'\n')) 867168401Spjd *cp = '\0'; 868168401Spjd cp = skip(line); 869168401Spjd if (cp == NULL) 870168401Spjd continue; 871168401Spjd tp = index(cp, ':'); 872168401Spjd if (tp == NULL) { 873168401Spjd fprintf(stderr, "line %d: syntax error\n", lineno); 874168401Spjd errors++; 875168401Spjd continue; 876168401Spjd } 877168401Spjd *tp++ = '\0', tp = skip(tp); 878168401Spjd if (streq(cp, "type")) { 879168401Spjd if (tp == NULL) 880168401Spjd tp = "unknown"; 881168401Spjd cpp = dktypenames; 882168401Spjd for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) 883168401Spjd if ((s = *cpp) && streq(s, tp)) { 884168401Spjd lp->d_type = cpp - dktypenames; 885168401Spjd goto next; 886168401Spjd } 887168401Spjd v = atoi(tp); 888168401Spjd if ((unsigned)v >= DKMAXTYPES) 889168401Spjd fprintf(stderr, "line %d:%s %d\n", lineno, 890168401Spjd "Warning, unknown disk type", v); 891168401Spjd lp->d_type = v; 892168401Spjd continue; 893168401Spjd } 894168401Spjd if (streq(cp, "flags")) { 895168401Spjd for (v = 0; (cp = tp) && *cp != '\0';) { 896168401Spjd tp = word(cp); 897168401Spjd if (streq(cp, "removeable")) 898168401Spjd v |= D_REMOVABLE; 899168401Spjd else if (streq(cp, "ecc")) 900168401Spjd v |= D_ECC; 901168401Spjd else if (streq(cp, "badsect")) 902168401Spjd v |= D_BADSECT; 903168401Spjd else { 904168401Spjd fprintf(stderr, 905168401Spjd "line %d: %s: bad flag\n", 906168401Spjd lineno, cp); 907168401Spjd errors++; 908168401Spjd } 909168401Spjd } 910168401Spjd lp->d_flags = v; 911168401Spjd continue; 912168401Spjd } 913168401Spjd if (streq(cp, "drivedata")) { 914168401Spjd register int i; 915168401Spjd 916168401Spjd for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { 917168401Spjd lp->d_drivedata[i++] = atoi(cp); 918168401Spjd tp = word(cp); 919168401Spjd } 920168401Spjd continue; 921168401Spjd } 922168401Spjd if (sscanf(cp, "%d partitions", &v) == 1) { 923168401Spjd if (v == 0 || (unsigned)v > MAXPARTITIONS) { 924168401Spjd fprintf(stderr, 925168401Spjd "line %d: bad # of partitions\n", lineno); 926168401Spjd lp->d_npartitions = MAXPARTITIONS; 927168401Spjd errors++; 928168401Spjd } else 929168401Spjd lp->d_npartitions = v; 930168401Spjd continue; 931168401Spjd } 932168401Spjd if (tp == NULL) 933168401Spjd tp = ""; 934168401Spjd if (streq(cp, "disk")) { 935168401Spjd strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); 936168401Spjd continue; 937168401Spjd } 938168401Spjd if (streq(cp, "label")) { 939168401Spjd strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); 940168401Spjd continue; 941168401Spjd } 942168401Spjd if (streq(cp, "bytes/sector")) { 943113275Smike v = atoi(tp); 944113275Smike if (v <= 0 || (v % 512) != 0) { 945113275Smike fprintf(stderr, 946113275Smike "line %d: %s: bad sector size\n", 947113275Smike lineno, tp); 948113275Smike errors++; 949113275Smike } else 950127020Spjd lp->d_secsize = v; 951125806Srwatson continue; 952113275Smike } 953168401Spjd if (streq(cp, "sectors/track")) { 954168401Spjd v = atoi(tp); 955168401Spjd if (v <= 0) { 956113275Smike fprintf(stderr, "line %d: %s: bad %s\n", 957168401Spjd lineno, tp, cp); 958113275Smike errors++; 959113275Smike } else 960167309Spjd lp->d_nsectors = v; 961113275Smike continue; 962113275Smike } 963113275Smike if (streq(cp, "sectors/cylinder")) { 964168487Spjd v = atoi(tp); 965113275Smike if (v <= 0) { 966168487Spjd fprintf(stderr, "line %d: %s: bad %s\n", 967113275Smike lineno, tp, cp); 968113275Smike errors++; 969113275Smike } else 970113275Smike lp->d_secpercyl = v; 971168401Spjd continue; 972113275Smike } 973113275Smike if (streq(cp, "tracks/cylinder")) { 974113275Smike v = atoi(tp); 975167354Spjd if (v <= 0) { 976113275Smike fprintf(stderr, "line %d: %s: bad %s\n", 977113275Smike lineno, tp, cp); 978113275Smike errors++; 979113275Smike } else 980126004Spjd lp->d_ntracks = v; 981126004Spjd continue; 982126004Spjd } 983126004Spjd if (streq(cp, "cylinders")) { 984126004Spjd v = atoi(tp); 985126004Spjd if (v <= 0) { 986126004Spjd fprintf(stderr, "line %d: %s: bad %s\n", 987126004Spjd lineno, tp, cp); 988126004Spjd errors++; 989126004Spjd } else 990126004Spjd lp->d_ncylinders = v; 991126004Spjd continue; 992126004Spjd } 993 if (streq(cp, "sectors/unit")) { 994 v = atoi(tp); 995 if (v <= 0) { 996 fprintf(stderr, "line %d: %s: bad %s\n", 997 lineno, tp, cp); 998 errors++; 999 } else 1000 lp->d_secperunit = v; 1001 continue; 1002 } 1003 if (streq(cp, "rpm")) { 1004 v = atoi(tp); 1005 if (v <= 0) { 1006 fprintf(stderr, "line %d: %s: bad %s\n", 1007 lineno, tp, cp); 1008 errors++; 1009 } else 1010 lp->d_rpm = v; 1011 continue; 1012 } 1013 if (streq(cp, "interleave")) { 1014 v = atoi(tp); 1015 if (v <= 0) { 1016 fprintf(stderr, "line %d: %s: bad %s\n", 1017 lineno, tp, cp); 1018 errors++; 1019 } else 1020 lp->d_interleave = v; 1021 continue; 1022 } 1023 if (streq(cp, "trackskew")) { 1024 v = atoi(tp); 1025 if (v < 0) { 1026 fprintf(stderr, "line %d: %s: bad %s\n", 1027 lineno, tp, cp); 1028 errors++; 1029 } else 1030 lp->d_trackskew = v; 1031 continue; 1032 } 1033 if (streq(cp, "cylinderskew")) { 1034 v = atoi(tp); 1035 if (v < 0) { 1036 fprintf(stderr, "line %d: %s: bad %s\n", 1037 lineno, tp, cp); 1038 errors++; 1039 } else 1040 lp->d_cylskew = v; 1041 continue; 1042 } 1043 if (streq(cp, "headswitch")) { 1044 v = atoi(tp); 1045 if (v < 0) { 1046 fprintf(stderr, "line %d: %s: bad %s\n", 1047 lineno, tp, cp); 1048 errors++; 1049 } else 1050 lp->d_headswitch = v; 1051 continue; 1052 } 1053 if (streq(cp, "track-to-track seek")) { 1054 v = atoi(tp); 1055 if (v < 0) { 1056 fprintf(stderr, "line %d: %s: bad %s\n", 1057 lineno, tp, cp); 1058 errors++; 1059 } else 1060 lp->d_trkseek = v; 1061 continue; 1062 } 1063 if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { 1064 unsigned part = *cp - 'a'; 1065 1066 if (part > lp->d_npartitions) { 1067 fprintf(stderr, 1068 "line %d: bad partition name\n", lineno); 1069 errors++; 1070 continue; 1071 } 1072 pp = &lp->d_partitions[part]; 1073#define NXTNUM(n) { \ 1074 if (tp == NULL) { \ 1075 fprintf(stderr, "line %d: too few numeric fields\n", lineno); \ 1076 errors++; \ 1077 break; \ 1078 } else { \ 1079 cp = tp, tp = word(cp); \ 1080 if (tp == NULL) \ 1081 tp = cp; \ 1082 (n) = atoi(cp); \ 1083 } \ 1084 } 1085 1086 NXTNUM(v); 1087 if (v < 0) { 1088 fprintf(stderr, 1089 "line %d: %s: bad partition size\n", 1090 lineno, cp); 1091 errors++; 1092 } else 1093 pp->p_size = v; 1094 NXTNUM(v); 1095 if (v < 0) { 1096 fprintf(stderr, 1097 "line %d: %s: bad partition offset\n", 1098 lineno, cp); 1099 errors++; 1100 } else 1101 pp->p_offset = v; 1102 cp = tp, tp = word(cp); 1103 cpp = fstypenames; 1104 for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) 1105 if ((s = *cpp) && streq(s, cp)) { 1106 pp->p_fstype = cpp - fstypenames; 1107 goto gottype; 1108 } 1109 if (isdigit(*cp)) 1110 v = atoi(cp); 1111 else 1112 v = FSMAXTYPES; 1113 if ((unsigned)v >= FSMAXTYPES) { 1114 fprintf(stderr, "line %d: %s %s\n", lineno, 1115 "Warning, unknown filesystem type", cp); 1116 v = FS_UNUSED; 1117 } 1118 pp->p_fstype = v; 1119 gottype: 1120 1121 switch (pp->p_fstype) { 1122 1123 case FS_UNUSED: /* XXX */ 1124 NXTNUM(pp->p_fsize); 1125 if (pp->p_fsize == 0) 1126 break; 1127 NXTNUM(v); 1128 pp->p_frag = v / pp->p_fsize; 1129 break; 1130 1131 case FS_BSDFFS: 1132 NXTNUM(pp->p_fsize); 1133 if (pp->p_fsize == 0) 1134 break; 1135 NXTNUM(v); 1136 pp->p_frag = v / pp->p_fsize; 1137 NXTNUM(pp->p_cpg); 1138 break; 1139 1140 case FS_BSDLFS: 1141 NXTNUM(pp->p_fsize); 1142 if (pp->p_fsize == 0) 1143 break; 1144 NXTNUM(v); 1145 pp->p_frag = v / pp->p_fsize; 1146 NXTNUM(pp->p_cpg); 1147 break; 1148 1149 default: 1150 break; 1151 } 1152 continue; 1153 } 1154 fprintf(stderr, "line %d: %s: Unknown disklabel field\n", 1155 lineno, cp); 1156 errors++; 1157 next: 1158 ; 1159 } 1160 errors += checklabel(lp); 1161 return (errors == 0); 1162} 1163 1164/* 1165 * Check disklabel for errors and fill in 1166 * derived fields according to supplied values. 1167 */ 1168checklabel(lp) 1169 register struct disklabel *lp; 1170{ 1171 register struct partition *pp; 1172 int i, errors = 0; 1173 char part; 1174 1175 if (lp->d_secsize == 0) { 1176 fprintf(stderr, "sector size %d\n", lp->d_secsize); 1177 return (1); 1178 } 1179 if (lp->d_nsectors == 0) { 1180 fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); 1181 return (1); 1182 } 1183 if (lp->d_ntracks == 0) { 1184 fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); 1185 return (1); 1186 } 1187 if (lp->d_ncylinders == 0) { 1188 fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); 1189 errors++; 1190 } 1191 if (lp->d_rpm == 0) 1192 Warning("revolutions/minute %d", lp->d_rpm); 1193 if (lp->d_secpercyl == 0) 1194 lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; 1195 if (lp->d_secperunit == 0) 1196 lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; 1197 if (lp->d_bbsize == 0) { 1198 fprintf(stderr, "boot block size %d\n", lp->d_bbsize); 1199 errors++; 1200 } else if (lp->d_bbsize % lp->d_secsize) 1201 Warning("boot block size %% sector-size != 0"); 1202 if (lp->d_sbsize == 0) { 1203 fprintf(stderr, "super block size %d\n", lp->d_sbsize); 1204 errors++; 1205 } else if (lp->d_sbsize % lp->d_secsize) 1206 Warning("super block size %% sector-size != 0"); 1207 if (lp->d_npartitions > MAXPARTITIONS) 1208 Warning("number of partitions (%d) > MAXPARTITIONS (%d)", 1209 lp->d_npartitions, MAXPARTITIONS); 1210 for (i = 0; i < lp->d_npartitions; i++) { 1211 part = 'a' + i; 1212 pp = &lp->d_partitions[i]; 1213 if (pp->p_size == 0 && pp->p_offset != 0) 1214 Warning("partition %c: size 0, but offset %d", 1215 part, pp->p_offset); 1216#ifdef notdef 1217 if (pp->p_size % lp->d_secpercyl) 1218 Warning("partition %c: size %% cylinder-size != 0", 1219 part); 1220 if (pp->p_offset % lp->d_secpercyl) 1221 Warning("partition %c: offset %% cylinder-size != 0", 1222 part); 1223#endif 1224 if (pp->p_offset > lp->d_secperunit) { 1225 fprintf(stderr, 1226 "partition %c: offset past end of unit\n", part); 1227 errors++; 1228 } 1229 if (pp->p_offset + pp->p_size > lp->d_secperunit) { 1230 fprintf(stderr, 1231 "partition %c: partition extends past end of unit\n", 1232 part); 1233 errors++; 1234 } 1235 } 1236 for (; i < MAXPARTITIONS; i++) { 1237 part = 'a' + i; 1238 pp = &lp->d_partitions[i]; 1239 if (pp->p_size || pp->p_offset) 1240 Warning("unused partition %c: size %d offset %d", 1241 'a' + i, pp->p_size, pp->p_offset); 1242 } 1243 return (errors); 1244} 1245 1246/* 1247 * If we are installing a boot program that doesn't fit in d_bbsize 1248 * we need to mark those partitions that the boot overflows into. 1249 * This allows newfs to prevent creation of a filesystem where it might 1250 * clobber bootstrap code. 1251 */ 1252setbootflag(lp) 1253 register struct disklabel *lp; 1254{ 1255 register struct partition *pp; 1256 int i, errors = 0; 1257 char part; 1258 u_long boffset; 1259 1260 if (bootbuf == 0) 1261 return; 1262 boffset = bootsize / lp->d_secsize; 1263 for (i = 0; i < lp->d_npartitions; i++) { 1264 part = 'a' + i; 1265 pp = &lp->d_partitions[i]; 1266 if (pp->p_size == 0) 1267 continue; 1268 if (boffset <= pp->p_offset) { 1269 if (pp->p_fstype == FS_BOOT) 1270 pp->p_fstype = FS_UNUSED; 1271 } else if (pp->p_fstype != FS_BOOT) { 1272 if (pp->p_fstype != FS_UNUSED) { 1273 fprintf(stderr, 1274 "boot overlaps used partition %c\n", 1275 part); 1276 errors++; 1277 } else { 1278 pp->p_fstype = FS_BOOT; 1279 Warning("boot overlaps partition %c, %s", 1280 part, "marked as FS_BOOT"); 1281 } 1282 } 1283 } 1284 if (errors) { 1285 fprintf(stderr, "Cannot install boot program\n"); 1286 exit(4); 1287 } 1288} 1289 1290/*VARARGS1*/ 1291Warning(fmt, a1, a2, a3, a4, a5) 1292 char *fmt; 1293{ 1294 1295 fprintf(stderr, "Warning, "); 1296 fprintf(stderr, fmt, a1, a2, a3, a4, a5); 1297 fprintf(stderr, "\n"); 1298} 1299 1300Perror(str) 1301 char *str; 1302{ 1303 fputs("disklabel: ", stderr); perror(str); 1304 exit(4); 1305} 1306 1307usage() 1308{ 1309#if NUMBOOT > 0 1310 fprintf(stderr, 1311"%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n", 1312"usage: disklabel [-r] disk", 1313 "(to read label)", 1314"or disklabel -w [-r] disk type [ packid ]", 1315 "(to write label with existing boot program)", 1316"or disklabel -e [-r] disk", 1317 "(to edit label)", 1318"or disklabel -R [-r] disk protofile", 1319 "(to restore label with existing boot program)", 1320#if NUMBOOT > 1 1321"or disklabel -B [ -b boot1 [ -s boot2 ] ] disk [ type ]", 1322 "(to install boot program with existing label)", 1323"or disklabel -w -B [ -b boot1 [ -s boot2 ] ] disk type [ packid ]", 1324 "(to write label and boot program)", 1325"or disklabel -R -B [ -b boot1 [ -s boot2 ] ] disk protofile [ type ]", 1326 "(to restore label and boot program)", 1327#else 1328"or disklabel -B [ -b bootprog ] disk [ type ]", 1329 "(to install boot program with existing on-disk label)", 1330"or disklabel -w -B [ -b bootprog ] disk type [ packid ]", 1331 "(to write label and install boot program)", 1332"or disklabel -R -B [ -b bootprog ] disk protofile [ type ]", 1333 "(to restore label and install boot program)", 1334#endif 1335"or disklabel [-NW] disk", 1336 "(to write disable/enable label)"); 1337#else 1338 fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n", 1339"usage: disklabel [-r] disk", "(to read label)", 1340"or disklabel -w [-r] disk type [ packid ]", "(to write label)", 1341"or disklabel -e [-r] disk", "(to edit label)", 1342"or disklabel -R [-r] disk protofile", "(to restore label)", 1343"or disklabel [-NW] disk", "(to write disable/enable label)"); 1344#endif 1345 exit(1); 1346} 1347