setup.c revision 114589
1173319Sedwin/* 2153761Swollman * Copyright (c) 1980, 1986, 1993 3153761Swollman * The Regents of the University of California. All rights reserved. 42742Swollman * 52742Swollman * Redistribution and use in source and binary forms, with or without 62742Swollman * modification, are permitted provided that the following conditions 72742Swollman * are met: 82742Swollman * 1. Redistributions of source code must retain the above copyright 92742Swollman * notice, this list of conditions and the following disclaimer. 10149514Swollman * 2. Redistributions in binary form must reproduce the above copyright 112742Swollman * notice, this list of conditions and the following disclaimer in the 1258787Sru * documentation and/or other materials provided with the distribution. 132742Swollman * 3. All advertising materials mentioning features or use of this software 142742Swollman * must display the following acknowledgement: 152742Swollman * This product includes software developed by the University of 162742Swollman * California, Berkeley and its contributors. 172742Swollman * 4. Neither the name of the University nor the names of its contributors 1858787Sru * may be used to endorse or promote products derived from this software 1958787Sru * without specific prior written permission. 2058787Sru * 2158787Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2258787Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2358787Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2458787Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2558787Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2658787Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2758787Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2858787Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29149514Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30149514Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31149514Swollman * SUCH DAMAGE. 32149514Swollman */ 33158421Swollman 3414343Swollman#if 0 3514343Swollman#ifndef lint 3614343Swollmanstatic const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; 3714343Swollman#endif /* not lint */ 38158421Swollman#endif 3914343Swollman#include <sys/cdefs.h> 4075267Swollman__FBSDID("$FreeBSD: head/sbin/fsck_ffs/setup.c 114589 2003-05-03 18:41:59Z obrien $"); 4117200Swollman 4275267Swollman#include <sys/param.h> 4375267Swollman#include <sys/stat.h> 4417200Swollman#define FSTYPENAMES 4517200Swollman#include <sys/disklabel.h> 4617200Swollman#include <sys/file.h> 4717200Swollman#include <sys/sysctl.h> 4817200Swollman 4917200Swollman#include <ufs/ufs/dinode.h> 5017200Swollman#include <ufs/ffs/fs.h> 5117200Swollman 5217200Swollman#include <ctype.h> 5317200Swollman#include <err.h> 5417200Swollman#include <errno.h> 5517200Swollman#include <limits.h> 5617200Swollman#include <stdint.h> 57149514Swollman#include <string.h> 58149514Swollman 5975267Swollman#include "fsck.h" 6075267Swollman 6175267Swollmanstruct bufarea asblk; 6275267Swollman#define altsblock (*asblk.b_un.b_fs) 6375267Swollman#define POWEROF2(num) (((num) & ((num) - 1)) == 0) 6475267Swollman 6575267Swollmanstatic void badsb(int listerr, const char *s); 6675267Swollmanstatic int calcsb(char *dev, int devfd, struct fs *fs); 6775267Swollmanstatic struct disklabel *getdisklabel(char *s, int fd); 6875267Swollman 6917200Swollman/* 702742Swollman * Read in a superblock finding an alternate if necessary. 712742Swollman * Return 1 if successful, 0 if unsuccessful, -1 if file system 7219878Swollman * is already clean (preen mode only). 7319878Swollman */ 742742Swollmanint 752742Swollmansetup(char *dev) 762742Swollman{ 772742Swollman long cg, asked, i, j; 782742Swollman long bmapsize; 7967578Swollman struct stat statb; 8067578Swollman struct fs proto; 8167578Swollman size_t size; 8267578Swollman 8367578Swollman havesb = 0; 8467578Swollman fswritefd = -1; 8567578Swollman cursnapshot = 0; 8667578Swollman if (stat(dev, &statb) < 0) { 8767578Swollman printf("Can't stat %s: %s\n", dev, strerror(errno)); 88149514Swollman if (bkgrdflag) { 8967578Swollman unlink(snapname); 9067578Swollman bkgrdflag = 0; 9186222Swollman } 9267578Swollman return (0); 9367578Swollman } 9467578Swollman if ((statb.st_mode & S_IFMT) != S_IFCHR && 9567578Swollman (statb.st_mode & S_IFMT) != S_IFBLK) { 9686222Swollman if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) { 9767578Swollman unlink(snapname); 98114173Swollman printf("background fsck lacks a snapshot\n"); 99114173Swollman exit(EEXIT); 100114173Swollman } 101114173Swollman if ((statb.st_flags & SF_SNAPSHOT) != 0 && cvtlevel == 0) { 102114173Swollman cursnapshot = statb.st_ino; 103114173Swollman } else { 104114173Swollman if (cvtlevel == 0 || 105114173Swollman (statb.st_flags & SF_SNAPSHOT) == 0) { 106114173Swollman if (preen && bkgrdflag) { 107114173Swollman unlink(snapname); 108114173Swollman bkgrdflag = 0; 109114173Swollman } 110114173Swollman pfatal("%s is not a disk device", dev); 111114173Swollman if (reply("CONTINUE") == 0) { 112114173Swollman if (bkgrdflag) { 113114173Swollman unlink(snapname); 114114173Swollman bkgrdflag = 0; 115149590Swollman } 116149590Swollman return (0); 117149590Swollman } 118149590Swollman } else { 119149590Swollman if (bkgrdflag) { 120149590Swollman unlink(snapname); 1212742Swollman bkgrdflag = 0; 12275267Swollman } 1232742Swollman pfatal("cannot convert a snapshot"); 1242742Swollman exit(EEXIT); 12567578Swollman } 1262742Swollman } 127149514Swollman } 1282742Swollman if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 1292742Swollman if (bkgrdflag) { 1302742Swollman unlink(snapname); 1312742Swollman bkgrdflag = 0; 132149514Swollman } 133149514Swollman printf("Can't open %s: %s\n", dev, strerror(errno)); 134149514Swollman return (0); 1352742Swollman } 136153761Swollman if (bkgrdflag) { 137153761Swollman unlink(snapname); 138153761Swollman size = MIBSIZE; 139153761Swollman if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0|| 140153761Swollman sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0|| 141153761Swollman sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0|| 142153761Swollman sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 || 143153761Swollman sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) { 144153761Swollman pfatal("kernel lacks background fsck support\n"); 145153761Swollman exit(EEXIT); 146153761Swollman } 147153761Swollman cmd.version = FFS_CMD_VERSION; 148153761Swollman cmd.handle = fsreadfd; 149153761Swollman fswritefd = -1; 150153761Swollman } 151153761Swollman if (preen == 0) 152153761Swollman printf("** %s", dev); 153153761Swollman if (bkgrdflag == 0 && 154153761Swollman (nflag || (fswritefd = open(dev, O_WRONLY)) < 0)) { 155153761Swollman fswritefd = -1; 15619878Swollman if (preen) 1572742Swollman pfatal("NO WRITE ACCESS"); 1582742Swollman printf(" (NO WRITE)"); 1592742Swollman } 1602742Swollman if (preen == 0) 1612742Swollman printf("\n"); 1622742Swollman /* 1632742Swollman * Read in the superblock, looking for alternates if necessary 1642742Swollman */ 1652742Swollman if (readsb(1) == 0) { 1662742Swollman skipclean = 0; 1672742Swollman if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) 16814343Swollman return(0); 16914343Swollman if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 17014343Swollman return (0); 17114343Swollman for (cg = 0; cg < proto.fs_ncg; cg++) { 17219878Swollman bflag = fsbtodb(&proto, cgsblock(&proto, cg)); 1732742Swollman if (readsb(0) != 0) 1742742Swollman break; 1752742Swollman } 1762742Swollman if (cg >= proto.fs_ncg) { 1772742Swollman printf("%s %s\n%s %s\n%s %s\n", 1782742Swollman "SEARCH FOR ALTERNATE SUPER-BLOCK", 1792742Swollman "FAILED. YOU MUST USE THE", 1802742Swollman "-b OPTION TO FSCK TO SPECIFY THE", 1812742Swollman "LOCATION OF AN ALTERNATE", 1822742Swollman "SUPER-BLOCK TO SUPPLY NEEDED", 1832742Swollman "INFORMATION; SEE fsck(8)."); 1842742Swollman bflag = 0; 1852742Swollman return(0); 1862742Swollman } 1872742Swollman pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 18819878Swollman bflag = 0; 1892742Swollman } 1902742Swollman if (skipclean && preen && sblock.fs_clean) { 1912742Swollman pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 1922742Swollman return (-1); 1932742Swollman } 19419878Swollman maxfsblock = sblock.fs_size; 1952742Swollman maxino = sblock.fs_ncg * sblock.fs_ipg; 1962742Swollman /* 19719878Swollman * Check and potentially fix certain fields in the super block. 1982742Swollman */ 1992742Swollman if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { 2002742Swollman pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); 2012742Swollman if (reply("SET TO DEFAULT") == 1) { 2022742Swollman sblock.fs_optim = FS_OPTTIME; 2032742Swollman sbdirty(); 2042742Swollman } 2052742Swollman } 2062742Swollman if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { 20719878Swollman pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 2082742Swollman sblock.fs_minfree); 2092742Swollman if (reply("SET TO DEFAULT") == 1) { 2102742Swollman sblock.fs_minfree = 10; 2112742Swollman sbdirty(); 2122742Swollman } 2132742Swollman } 2142742Swollman if (sblock.fs_magic == FS_UFS1_MAGIC && 2152742Swollman sblock.fs_old_inodefmt < FS_44INODEFMT) { 2162742Swollman pwarn("Format of file system is too old.\n"); 21719878Swollman pwarn("Must update to modern format using a version of fsck\n"); 2182742Swollman pfatal("from before 2002 with the command ``fsck -c 2''\n"); 2192742Swollman exit(EEXIT); 2202742Swollman } 2212742Swollman if (asblk.b_dirty && !bflag) { 2222742Swollman memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize); 2232742Swollman flush(fswritefd, &asblk); 2242742Swollman } 2252742Swollman /* 2262742Swollman * read in the summary info. 22714343Swollman */ 22875267Swollman asked = 0; 22975267Swollman sblock.fs_csp = calloc(1, sblock.fs_cssize); 23075267Swollman for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 23175267Swollman size = sblock.fs_cssize - i < sblock.fs_bsize ? 232158421Swollman sblock.fs_cssize - i : sblock.fs_bsize; 233149514Swollman if (bread(fsreadfd, (char *)sblock.fs_csp + i, 234149514Swollman fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 235149514Swollman size) != 0 && !asked) { 236149514Swollman pfatal("BAD SUMMARY INFORMATION"); 237149514Swollman if (reply("CONTINUE") == 0) { 238149514Swollman ckfini(0); 239149514Swollman exit(EEXIT); 240149514Swollman } 241149514Swollman asked++; 242149514Swollman } 243149514Swollman } 244149514Swollman /* 245149514Swollman * allocate and initialize the necessary maps 246149514Swollman */ 247149514Swollman bmapsize = roundup(howmany(maxfsblock, CHAR_BIT), sizeof(short)); 248149514Swollman blockmap = calloc((unsigned)bmapsize, sizeof (char)); 249149514Swollman if (blockmap == NULL) { 250149514Swollman printf("cannot alloc %u bytes for blockmap\n", 251149514Swollman (unsigned)bmapsize); 2522742Swollman goto badsb; 25386222Swollman } 25475267Swollman inostathead = calloc((unsigned)(sblock.fs_ncg), 25567578Swollman sizeof(struct inostatlist)); 256149590Swollman if (inostathead == NULL) { 257149590Swollman printf("cannot alloc %u bytes for inostathead\n", 258114173Swollman (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg))); 259114173Swollman goto badsb; 260114173Swollman } 26167578Swollman numdirs = MAX(sblock.fs_cstotal.cs_ndir, 128); 262149514Swollman dirhash = numdirs; 263149514Swollman inplast = 0; 264149514Swollman listmax = numdirs + 10; 265149514Swollman inpsort = (struct inoinfo **)calloc((unsigned)listmax, 266149514Swollman sizeof(struct inoinfo *)); 267149514Swollman inphead = (struct inoinfo **)calloc((unsigned)numdirs, 268149514Swollman sizeof(struct inoinfo *)); 269153670Swollman if (inpsort == NULL || inphead == NULL) { 270153670Swollman printf("cannot alloc %ju bytes for inphead\n", 271153670Swollman (uintmax_t)numdirs * sizeof(struct inoinfo *)); 272153670Swollman goto badsb; 273153670Swollman } 274153670Swollman bufinit(); 275153670Swollman if (sblock.fs_flags & FS_DOSOFTDEP) 276153670Swollman usedsoftdep = 1; 277158421Swollman else 278153670Swollman usedsoftdep = 0; 27914343Swollman return (1); 28014343Swollman 28114343Swollmanbadsb: 28214343Swollman ckfini(0); 28314343Swollman return (0); 28414343Swollman} 28514343Swollman 286149514Swollman/* 28714343Swollman * Possible superblock locations ordered from most to least likely. 28814343Swollman */ 28914343Swollmanstatic int sblock_try[] = SBLOCKSEARCH; 29014343Swollman 29114343Swollman/* 2922742Swollman * Read in the super block and its summary info. 29386222Swollman */ 29467578Swollmanint 295136638Swollmanreadsb(int listerr) 296136638Swollman{ 297136638Swollman ufs2_daddr_t super; 298114173Swollman int i; 299114173Swollman 300114173Swollman if (bflag) { 301114173Swollman super = bflag; 302114173Swollman if ((bread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) 30367578Swollman return (0); 304158421Swollman if (sblock.fs_magic != FS_UFS1_MAGIC && 305158421Swollman sblock.fs_magic != FS_UFS2_MAGIC) { 306158421Swollman fprintf(stderr, "%d is not a file system superblock\n", 307158421Swollman bflag); 308158421Swollman return (0); 309158421Swollman } 310169811Swollman } else { 311169811Swollman for (i = 0; sblock_try[i] != -1; i++) { 312169811Swollman super = sblock_try[i] / dev_bsize; 313169811Swollman if ((bread(fsreadfd, (char *)&sblock, super, 314169811Swollman (long)SBLOCKSIZE))) 315158421Swollman return (0); 31614343Swollman if ((sblock.fs_magic == FS_UFS1_MAGIC || 31714343Swollman (sblock.fs_magic == FS_UFS2_MAGIC && 31814343Swollman sblock.fs_sblockloc == sblock_try[i])) && 31914343Swollman sblock.fs_ncg >= 1 && 32014343Swollman sblock.fs_bsize >= MINBSIZE && 32114343Swollman sblock.fs_bsize >= sizeof(struct fs)) 32214343Swollman break; 32314343Swollman } 324149514Swollman if (sblock_try[i] == -1) { 32514343Swollman fprintf(stderr, "Cannot find file system superblock\n"); 32614343Swollman return (0); 32714343Swollman } 32814343Swollman } 32914343Swollman /* 33014343Swollman * Compute block size that the file system is based on, 33114343Swollman * according to fsbtodb, and adjust superblock block number 33286222Swollman * so we can tell if this is an alternate later. 333149514Swollman */ 33486222Swollman super *= dev_bsize; 33586222Swollman dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 336158421Swollman sblk.b_bno = super / dev_bsize; 337158421Swollman sblk.b_size = SBLOCKSIZE; 338158421Swollman if (bflag) 339158421Swollman goto out; 340158421Swollman /* 341158421Swollman * Compare all fields that should not differ in alternate super block. 342158421Swollman * When an alternate super-block is specified this check is skipped. 343158421Swollman */ 344158421Swollman getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); 345158421Swollman if (asblk.b_errs) 3462742Swollman return (0); 34786222Swollman if (altsblock.fs_sblkno != sblock.fs_sblkno || 34867578Swollman altsblock.fs_cblkno != sblock.fs_cblkno || 349136638Swollman altsblock.fs_iblkno != sblock.fs_iblkno || 35086222Swollman altsblock.fs_dblkno != sblock.fs_dblkno || 351171948Sedwin altsblock.fs_ncg != sblock.fs_ncg || 35275267Swollman altsblock.fs_bsize != sblock.fs_bsize || 35375267Swollman altsblock.fs_fsize != sblock.fs_fsize || 35467578Swollman altsblock.fs_frag != sblock.fs_frag || 35514343Swollman altsblock.fs_bmask != sblock.fs_bmask || 35614343Swollman altsblock.fs_fmask != sblock.fs_fmask || 35714343Swollman altsblock.fs_bshift != sblock.fs_bshift || 35814343Swollman altsblock.fs_fshift != sblock.fs_fshift || 35914343Swollman altsblock.fs_fragshift != sblock.fs_fragshift || 36014343Swollman altsblock.fs_fsbtodb != sblock.fs_fsbtodb || 3612742Swollman altsblock.fs_sbsize != sblock.fs_sbsize || 362149514Swollman altsblock.fs_nindir != sblock.fs_nindir || 36315309Swollman altsblock.fs_inopb != sblock.fs_inopb || 36415309Swollman altsblock.fs_cssize != sblock.fs_cssize || 36515309Swollman altsblock.fs_ipg != sblock.fs_ipg || 36615309Swollman altsblock.fs_fpg != sblock.fs_fpg || 36715309Swollman altsblock.fs_magic != sblock.fs_magic) { 3682742Swollman badsb(listerr, 36914343Swollman "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); 37067578Swollman return (0); 371136638Swollman } 372171948Sedwinout: 373171948Sedwin /* 374136638Swollman * If not yet done, update UFS1 superblock with new wider fields. 37567578Swollman */ 37614343Swollman if (sblock.fs_magic == FS_UFS1_MAGIC && 37714343Swollman sblock.fs_maxbsize != sblock.fs_bsize) { 37814343Swollman sblock.fs_maxbsize = sblock.fs_bsize; 37914343Swollman sblock.fs_time = sblock.fs_old_time; 38014343Swollman sblock.fs_size = sblock.fs_old_size; 38114343Swollman sblock.fs_dsize = sblock.fs_old_dsize; 38214343Swollman sblock.fs_csaddr = sblock.fs_old_csaddr; 383149514Swollman sblock.fs_cstotal.cs_ndir = sblock.fs_old_cstotal.cs_ndir; 38414343Swollman sblock.fs_cstotal.cs_nbfree = sblock.fs_old_cstotal.cs_nbfree; 38514343Swollman sblock.fs_cstotal.cs_nifree = sblock.fs_old_cstotal.cs_nifree; 38614343Swollman sblock.fs_cstotal.cs_nffree = sblock.fs_old_cstotal.cs_nffree; 3878029Swollman } 38814343Swollman havesb = 1; 38914343Swollman return (1); 39014343Swollman} 39186222Swollman 39214343Swollmanstatic void 39319878Swollmanbadsb(int listerr, const char *s) 39475267Swollman{ 39575267Swollman 39675267Swollman if (!listerr) 39775267Swollman return; 39814343Swollman if (preen) 39986222Swollman printf("%s: ", cdevname); 40086222Swollman pfatal("BAD SUPER BLOCK: %s\n", s); 40186222Swollman} 40286222Swollman 40386222Swollmanvoid 40486222Swollmansblock_init(void) 40586222Swollman{ 40614343Swollman struct disklabel *lp; 40775267Swollman 40875267Swollman fswritefd = -1; 40914343Swollman fsmodified = 0; 41014343Swollman lfdir = 0; 41114343Swollman initbarea(&sblk); 41214343Swollman initbarea(&asblk); 413136638Swollman sblk.b_un.b_buf = malloc(SBLOCKSIZE); 41414343Swollman asblk.b_un.b_buf = malloc(SBLOCKSIZE); 41575267Swollman if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 41675267Swollman errx(EEXIT, "cannot allocate space for superblock"); 41714343Swollman if ((lp = getdisklabel(NULL, fsreadfd))) 41814343Swollman dev_bsize = secsize = lp->d_secsize; 41914343Swollman else 420136638Swollman dev_bsize = secsize = DEV_BSIZE; 42114343Swollman} 42275267Swollman 42375267Swollman/* 42414343Swollman * Calculate a prototype superblock based on information in the disk label. 425158421Swollman * When done the cgsblock macro can be calculated and the fs_ncg field 426158421Swollman * can be used. Do NOT attempt to use other macros without verifying that 42714343Swollman * their needed information is available! 42814343Swollman */ 42914343Swollmanstatic int 430136638Swollmancalcsb(char *dev, int devfd, struct fs *fs) 43114343Swollman{ 43275267Swollman struct disklabel *lp; 43375267Swollman struct partition *pp; 43414343Swollman char *cp; 43514343Swollman int i, nspf; 43614343Swollman 43714343Swollman cp = strchr(dev, '\0') - 1; 43814343Swollman if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) { 439136638Swollman pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 44014343Swollman return (0); 44175267Swollman } 44275267Swollman lp = getdisklabel(dev, devfd); 44314343Swollman if (isdigit(*cp)) 44414343Swollman pp = &lp->d_partitions[0]; 44514343Swollman else 44614343Swollman pp = &lp->d_partitions[*cp - 'a']; 44714343Swollman if (pp->p_fstype != FS_BSDFFS) { 448136638Swollman pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", 44914343Swollman dev, pp->p_fstype < FSMAXTYPES ? 450149514Swollman fstypenames[pp->p_fstype] : "unknown"); 451149514Swollman return (0); 45214343Swollman } 45314343Swollman if (pp->p_fsize == 0 || pp->p_frag == 0 || 45414343Swollman pp->p_cpg == 0 || pp->p_size == 0) { 455149514Swollman pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n", 456149514Swollman dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype], 457149514Swollman pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size); 458149514Swollman return (0); 459149514Swollman } 460149514Swollman memset(fs, 0, sizeof(struct fs)); 461149514Swollman fs->fs_fsize = pp->p_fsize; 462149514Swollman fs->fs_frag = pp->p_frag; 463149514Swollman fs->fs_size = pp->p_size; 464149514Swollman fs->fs_sblkno = roundup( 465149514Swollman howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), 466149514Swollman fs->fs_frag); 467149514Swollman nspf = fs->fs_fsize / lp->d_secsize; 468149514Swollman for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1) 469149514Swollman fs->fs_fsbtodb++; 4702742Swollman dev_bsize = lp->d_secsize; 47114343Swollman if (fs->fs_magic == FS_UFS2_MAGIC) { 47214343Swollman fs->fs_fpg = pp->p_cpg; 47314343Swollman fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg); 47414343Swollman } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ { 47514343Swollman fs->fs_old_cpg = pp->p_cpg; 47614343Swollman fs->fs_old_cgmask = 0xffffffff; 47714343Swollman for (i = lp->d_ntracks; i > 1; i >>= 1) 47814343Swollman fs->fs_old_cgmask <<= 1; 47914343Swollman if (!POWEROF2(lp->d_ntracks)) 48014343Swollman fs->fs_old_cgmask <<= 1; 48114343Swollman fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf), 48214343Swollman fs->fs_frag); 48314343Swollman fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf; 48414343Swollman fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl, 48514343Swollman fs->fs_old_cpg); 48614343Swollman } 4872742Swollman return (1); 48814343Swollman} 48914343Swollman 49014343Swollmanstatic struct disklabel * 491114173Swollmangetdisklabel(char *s, int fd) 492114173Swollman{ 493114173Swollman static struct disklabel lab; 494114173Swollman 495114173Swollman if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { 496114173Swollman if (s == NULL) 497114173Swollman return ((struct disklabel *)NULL); 498114173Swollman pwarn("ioctl (GCINFO): %s\n", strerror(errno)); 499114173Swollman errx(EEXIT, "%s: can't read disk label", s); 500114173Swollman } 501114173Swollman return (&lab); 502114173Swollman} 503114173Swollman