setup.c revision 125036
10SN/A/* 29330SN/A * Copyright (c) 1980, 1986, 1993 30SN/A * The Regents of the University of California. All rights reserved. 40SN/A * 50SN/A * Redistribution and use in source and binary forms, with or without 60SN/A * modification, are permitted provided that the following conditions 72362SN/A * are met: 80SN/A * 1. Redistributions of source code must retain the above copyright 92362SN/A * notice, this list of conditions and the following disclaimer. 100SN/A * 2. Redistributions in binary form must reproduce the above copyright 110SN/A * notice, this list of conditions and the following disclaimer in the 120SN/A * documentation and/or other materials provided with the distribution. 130SN/A * 3. All advertising materials mentioning features or use of this software 140SN/A * must display the following acknowledgement: 150SN/A * This product includes software developed by the University of 160SN/A * California, Berkeley and its contributors. 170SN/A * 4. Neither the name of the University nor the names of its contributors 180SN/A * may be used to endorse or promote products derived from this software 190SN/A * without specific prior written permission. 200SN/A * 212362SN/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 222362SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232362SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 240SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 250SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 260SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 270SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 280SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 290SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 300SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 310SN/A * SUCH DAMAGE. 320SN/A */ 330SN/A 340SN/A#if 0 350SN/A#ifndef lint 360SN/Astatic const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; 370SN/A#endif /* not lint */ 380SN/A#endif 390SN/A#include <sys/cdefs.h> 400SN/A__FBSDID("$FreeBSD: head/sbin/fsck_ffs/setup.c 125036 2004-01-26 15:05:30Z cperciva $"); 410SN/A 420SN/A#include <sys/param.h> 430SN/A#include <sys/stat.h> 440SN/A#define FSTYPENAMES 450SN/A#include <sys/disklabel.h> 460SN/A#include <sys/file.h> 470SN/A#include <sys/sysctl.h> 480SN/A 490SN/A#include <ufs/ufs/dinode.h> 500SN/A#include <ufs/ffs/fs.h> 510SN/A 520SN/A#include <ctype.h> 530SN/A#include <err.h> 540SN/A#include <errno.h> 550SN/A#include <limits.h> 560SN/A#include <stdint.h> 570SN/A#include <string.h> 580SN/A 590SN/A#include "fsck.h" 600SN/A 610SN/Astruct bufarea asblk; 620SN/A#define altsblock (*asblk.b_un.b_fs) 630SN/A#define POWEROF2(num) (((num) & ((num) - 1)) == 0) 640SN/A 650SN/Astatic void badsb(int listerr, const char *s); 660SN/Astatic int calcsb(char *dev, int devfd, struct fs *fs); 670SN/Astatic struct disklabel *getdisklabel(char *s, int fd); 680SN/A 690SN/A/* 704487SN/A * Read in a superblock finding an alternate if necessary. 710SN/A * Return 1 if successful, 0 if unsuccessful, -1 if file system 724487SN/A * is already clean (preen mode only). 730SN/A */ 740SN/Aint 750SN/Asetup(char *dev) 760SN/A{ 770SN/A long cg, asked, i, j; 780SN/A long bmapsize; 790SN/A struct stat statb; 800SN/A struct fs proto; 810SN/A size_t size; 820SN/A 830SN/A havesb = 0; 840SN/A fswritefd = -1; 850SN/A cursnapshot = 0; 860SN/A if (stat(dev, &statb) < 0) { 870SN/A printf("Can't stat %s: %s\n", dev, strerror(errno)); 880SN/A if (bkgrdflag) { 890SN/A unlink(snapname); 900SN/A bkgrdflag = 0; 910SN/A } 920SN/A return (0); 930SN/A } 940SN/A if ((statb.st_mode & S_IFMT) != S_IFCHR && 950SN/A (statb.st_mode & S_IFMT) != S_IFBLK) { 960SN/A if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) { 970SN/A unlink(snapname); 980SN/A printf("background fsck lacks a snapshot\n"); 990SN/A exit(EEXIT); 1000SN/A } 1010SN/A if ((statb.st_flags & SF_SNAPSHOT) != 0 && cvtlevel == 0) { 1020SN/A cursnapshot = statb.st_ino; 1030SN/A } else { 1040SN/A if (cvtlevel == 0 || 1054487SN/A (statb.st_flags & SF_SNAPSHOT) == 0) { 1060SN/A if (preen && bkgrdflag) { 1070SN/A unlink(snapname); 1080SN/A bkgrdflag = 0; 1090SN/A } 1100SN/A pfatal("%s is not a disk device", dev); 1110SN/A if (reply("CONTINUE") == 0) { 1120SN/A if (bkgrdflag) { 1130SN/A unlink(snapname); 1140SN/A bkgrdflag = 0; 1150SN/A } 1160SN/A return (0); 1170SN/A } 1180SN/A } else { 1190SN/A if (bkgrdflag) { 1200SN/A unlink(snapname); 1210SN/A bkgrdflag = 0; 1220SN/A } 1234487SN/A pfatal("cannot convert a snapshot"); 1240SN/A exit(EEXIT); 1250SN/A } 1260SN/A } 1270SN/A } 1280SN/A if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 1290SN/A if (bkgrdflag) { 1300SN/A unlink(snapname); 1310SN/A bkgrdflag = 0; 1320SN/A } 1330SN/A printf("Can't open %s: %s\n", dev, strerror(errno)); 1340SN/A return (0); 1350SN/A } 1360SN/A if (bkgrdflag) { 1370SN/A unlink(snapname); 1380SN/A size = MIBSIZE; 1390SN/A if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0|| 1400SN/A sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0|| 1410SN/A sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0|| 1420SN/A sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 || 1430SN/A sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) { 1440SN/A pfatal("kernel lacks background fsck support\n"); 1450SN/A exit(EEXIT); 1460SN/A } 1470SN/A cmd.version = FFS_CMD_VERSION; 1480SN/A cmd.handle = fsreadfd; 1490SN/A fswritefd = -1; 1500SN/A } 1510SN/A if (preen == 0) 1520SN/A printf("** %s", dev); 15311287Sweijun if (bkgrdflag == 0 && 15411287Sweijun (nflag || (fswritefd = open(dev, O_WRONLY)) < 0)) { 15511287Sweijun fswritefd = -1; 15611287Sweijun if (preen) 15711287Sweijun pfatal("NO WRITE ACCESS"); 1580SN/A printf(" (NO WRITE)"); 1590SN/A } 1600SN/A if (preen == 0) 1610SN/A printf("\n"); 1620SN/A /* 16311287Sweijun * Read in the superblock, looking for alternates if necessary 16411287Sweijun */ 16511287Sweijun if (readsb(1) == 0) { 16611287Sweijun skipclean = 0; 16711287Sweijun if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) 16811287Sweijun return(0); 16911287Sweijun if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 17011287Sweijun return (0); 17111287Sweijun for (cg = 0; cg < proto.fs_ncg; cg++) { 17211287Sweijun bflag = fsbtodb(&proto, cgsblock(&proto, cg)); 17311287Sweijun if (readsb(0) != 0) 17411287Sweijun break; 17511287Sweijun } 17611287Sweijun if (cg >= proto.fs_ncg) { 17711287Sweijun printf("%s %s\n%s %s\n%s %s\n", 17811287Sweijun "SEARCH FOR ALTERNATE SUPER-BLOCK", 17911287Sweijun "FAILED. YOU MUST USE THE", 18011287Sweijun "-b OPTION TO FSCK TO SPECIFY THE", 18111287Sweijun "LOCATION OF AN ALTERNATE", 18211287Sweijun "SUPER-BLOCK TO SUPPLY NEEDED", 18311287Sweijun "INFORMATION; SEE fsck(8)."); 18411287Sweijun bflag = 0; 18511287Sweijun return(0); 18611287Sweijun } 18711287Sweijun pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 1880SN/A bflag = 0; 1890SN/A } 1900SN/A if (skipclean && preen && sblock.fs_clean) { 1910SN/A pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n"); 1920SN/A return (-1); 1930SN/A } 1940SN/A maxfsblock = sblock.fs_size; 1950SN/A maxino = sblock.fs_ncg * sblock.fs_ipg; 1960SN/A /* 1970SN/A * Check and potentially fix certain fields in the super block. 1980SN/A */ 1990SN/A if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { 2000SN/A pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); 2010SN/A if (reply("SET TO DEFAULT") == 1) { 2020SN/A sblock.fs_optim = FS_OPTTIME; 2030SN/A sbdirty(); 2040SN/A } 2050SN/A } 2060SN/A if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { 2070SN/A pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 2080SN/A sblock.fs_minfree); 2090SN/A if (reply("SET TO DEFAULT") == 1) { 2100SN/A sblock.fs_minfree = 10; 2110SN/A sbdirty(); 2120SN/A } 2130SN/A } 2140SN/A if (sblock.fs_magic == FS_UFS1_MAGIC && 2150SN/A sblock.fs_old_inodefmt < FS_44INODEFMT) { 2160SN/A pwarn("Format of file system is too old.\n"); 2170SN/A pwarn("Must update to modern format using a version of fsck\n"); 2180SN/A pfatal("from before 2002 with the command ``fsck -c 2''\n"); 2190SN/A exit(EEXIT); 2200SN/A } 2210SN/A if (asblk.b_dirty && !bflag) { 2220SN/A memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize); 2230SN/A flush(fswritefd, &asblk); 2240SN/A } 2250SN/A /* 2260SN/A * read in the summary info. 2270SN/A */ 2280SN/A asked = 0; 2290SN/A sblock.fs_csp = calloc(1, sblock.fs_cssize); 2300SN/A if (sblock.fs_csp == NULL) { 2310SN/A printf("cannot alloc %u bytes for cg summary info\n", 2320SN/A (unsigned)sblock.fs_cssize); 2330SN/A goto badsb; 2340SN/A } 2350SN/A for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2360SN/A size = sblock.fs_cssize - i < sblock.fs_bsize ? 2370SN/A sblock.fs_cssize - i : sblock.fs_bsize; 2380SN/A if (bread(fsreadfd, (char *)sblock.fs_csp + i, 2390SN/A fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2400SN/A size) != 0 && !asked) { 2410SN/A pfatal("BAD SUMMARY INFORMATION"); 2420SN/A if (reply("CONTINUE") == 0) { 2430SN/A ckfini(0); 2440SN/A exit(EEXIT); 2450SN/A } 2460SN/A asked++; 2470SN/A } 24811287Sweijun } 24911287Sweijun /* 25011287Sweijun * allocate and initialize the necessary maps 25111287Sweijun */ 25211287Sweijun bmapsize = roundup(howmany(maxfsblock, CHAR_BIT), sizeof(short)); 25311287Sweijun blockmap = calloc((unsigned)bmapsize, sizeof (char)); 25411287Sweijun if (blockmap == NULL) { 25511287Sweijun printf("cannot alloc %u bytes for blockmap\n", 2560SN/A (unsigned)bmapsize); 2570SN/A goto badsb; 2580SN/A } 2590SN/A inostathead = calloc((unsigned)(sblock.fs_ncg), 2600SN/A sizeof(struct inostatlist)); 2610SN/A if (inostathead == NULL) { 2620SN/A printf("cannot alloc %u bytes for inostathead\n", 2630SN/A (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg))); 2640SN/A goto badsb; 2650SN/A } 2660SN/A numdirs = MAX(sblock.fs_cstotal.cs_ndir, 128); 2670SN/A dirhash = numdirs; 2680SN/A inplast = 0; 2690SN/A listmax = numdirs + 10; 2700SN/A inpsort = (struct inoinfo **)calloc((unsigned)listmax, 2710SN/A sizeof(struct inoinfo *)); 2720SN/A inphead = (struct inoinfo **)calloc((unsigned)numdirs, 2730SN/A sizeof(struct inoinfo *)); 2740SN/A if (inpsort == NULL || inphead == NULL) { 2750SN/A printf("cannot alloc %ju bytes for inphead\n", 2760SN/A (uintmax_t)numdirs * sizeof(struct inoinfo *)); 2770SN/A goto badsb; 2780SN/A } 2790SN/A bufinit(); 2800SN/A if (sblock.fs_flags & FS_DOSOFTDEP) 2810SN/A usedsoftdep = 1; 2820SN/A else 2830SN/A usedsoftdep = 0; 2840SN/A return (1); 2850SN/A 2860SN/Abadsb: 2870SN/A ckfini(0); 2880SN/A return (0); 2895620SN/A} 2900SN/A 2915620SN/A/* 2920SN/A * Possible superblock locations ordered from most to least likely. 2930SN/A */ 2940SN/Astatic int sblock_try[] = SBLOCKSEARCH; 2950SN/A 2960SN/A#define BAD_MAGIC_MSG \ 2970SN/A"The previous newfs operation on this volume did not complete.\n" \ 2985620SN/A"You must complete newfs before mounting this volume.\n" 2990SN/A 3000SN/A/* 3010SN/A * Read in the super block and its summary info. 3020SN/A */ 3030SN/Aint 3040SN/Areadsb(int listerr) 3050SN/A{ 3060SN/A ufs2_daddr_t super; 3070SN/A int i; 3080SN/A 3090SN/A if (bflag) { 3100SN/A super = bflag; 3110SN/A if ((bread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) 3120SN/A return (0); 3130SN/A if (sblock.fs_magic == FS_BAD2_MAGIC) { 3145620SN/A fprintf(stderr, BAD_MAGIC_MSG); 3150SN/A exit(11); 3160SN/A } 3170SN/A if (sblock.fs_magic != FS_UFS1_MAGIC && 3180SN/A sblock.fs_magic != FS_UFS2_MAGIC) { 3190SN/A fprintf(stderr, "%d is not a file system superblock\n", 3205620SN/A bflag); 3210SN/A return (0); 3220SN/A } 3230SN/A } else { 3240SN/A for (i = 0; sblock_try[i] != -1; i++) { 3250SN/A super = sblock_try[i] / dev_bsize; 3260SN/A if ((bread(fsreadfd, (char *)&sblock, super, 3270SN/A (long)SBLOCKSIZE))) 3280SN/A return (0); 3290SN/A if (sblock.fs_magic == FS_BAD2_MAGIC) { 3300SN/A fprintf(stderr, BAD_MAGIC_MSG); 3310SN/A exit(11); 3320SN/A } 3330SN/A if ((sblock.fs_magic == FS_UFS1_MAGIC || 3340SN/A (sblock.fs_magic == FS_UFS2_MAGIC && 3350SN/A sblock.fs_sblockloc == sblock_try[i])) && 3360SN/A sblock.fs_ncg >= 1 && 3375620SN/A sblock.fs_bsize >= MINBSIZE && 3380SN/A sblock.fs_bsize >= sizeof(struct fs)) 3390SN/A break; 3400SN/A } 3410SN/A if (sblock_try[i] == -1) { 3420SN/A fprintf(stderr, "Cannot find file system superblock\n"); 3430SN/A return (0); 3440SN/A } 3450SN/A } 3460SN/A /* 3470SN/A * Compute block size that the file system is based on, 3480SN/A * according to fsbtodb, and adjust superblock block number 3490SN/A * so we can tell if this is an alternate later. 3505996SN/A */ 3511243SN/A super *= dev_bsize; 3521243SN/A dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 3531243SN/A sblk.b_bno = super / dev_bsize; 3540SN/A sblk.b_size = SBLOCKSIZE; 3550SN/A if (bflag) 3560SN/A goto out; 3571243SN/A /* 3580SN/A * Compare all fields that should not differ in alternate super block. 3590SN/A * When an alternate super-block is specified this check is skipped. 3601243SN/A */ 3615996SN/A getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); 3625996SN/A if (asblk.b_errs) 3631243SN/A return (0); 3641243SN/A if (altsblock.fs_sblkno != sblock.fs_sblkno || 3651243SN/A altsblock.fs_cblkno != sblock.fs_cblkno || 3661243SN/A altsblock.fs_iblkno != sblock.fs_iblkno || 3675996SN/A altsblock.fs_dblkno != sblock.fs_dblkno || 3685996SN/A altsblock.fs_ncg != sblock.fs_ncg || 3695996SN/A altsblock.fs_bsize != sblock.fs_bsize || 3705996SN/A altsblock.fs_fsize != sblock.fs_fsize || 3715996SN/A altsblock.fs_frag != sblock.fs_frag || 3725996SN/A altsblock.fs_bmask != sblock.fs_bmask || 3735996SN/A altsblock.fs_fmask != sblock.fs_fmask || 3741243SN/A altsblock.fs_bshift != sblock.fs_bshift || 3751243SN/A altsblock.fs_fshift != sblock.fs_fshift || 3761243SN/A altsblock.fs_fragshift != sblock.fs_fragshift || 3771243SN/A altsblock.fs_fsbtodb != sblock.fs_fsbtodb || 3781243SN/A altsblock.fs_sbsize != sblock.fs_sbsize || 3791243SN/A altsblock.fs_nindir != sblock.fs_nindir || 3801243SN/A altsblock.fs_inopb != sblock.fs_inopb || 3811243SN/A altsblock.fs_cssize != sblock.fs_cssize || 3821243SN/A altsblock.fs_ipg != sblock.fs_ipg || 3830SN/A altsblock.fs_fpg != sblock.fs_fpg || 3840SN/A altsblock.fs_magic != sblock.fs_magic) { 3850SN/A badsb(listerr, 3860SN/A "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); 3870SN/A return (0); 3880SN/A } 3890SN/Aout: 39010475Sweijun /* 39110475Sweijun * If not yet done, update UFS1 superblock with new wider fields. 39210475Sweijun */ 39311099Smartin if (sblock.fs_magic == FS_UFS1_MAGIC && 3940SN/A sblock.fs_maxbsize != sblock.fs_bsize) { 39510475Sweijun sblock.fs_maxbsize = sblock.fs_bsize; 39610475Sweijun sblock.fs_time = sblock.fs_old_time; 3970SN/A sblock.fs_size = sblock.fs_old_size; 3980SN/A sblock.fs_dsize = sblock.fs_old_dsize; 39910475Sweijun sblock.fs_csaddr = sblock.fs_old_csaddr; 40013418Schegar sblock.fs_cstotal.cs_ndir = sblock.fs_old_cstotal.cs_ndir; 40110475Sweijun sblock.fs_cstotal.cs_nbfree = sblock.fs_old_cstotal.cs_nbfree; 40210475Sweijun sblock.fs_cstotal.cs_nifree = sblock.fs_old_cstotal.cs_nifree; 4030SN/A sblock.fs_cstotal.cs_nffree = sblock.fs_old_cstotal.cs_nffree; 40410475Sweijun } 40510475Sweijun havesb = 1; 40610475Sweijun return (1); 40710475Sweijun} 40810475Sweijun 40910475Sweijunstatic void 41010475Sweijunbadsb(int listerr, const char *s) 41110475Sweijun{ 41210475Sweijun 41310475Sweijun if (!listerr) 4140SN/A return; 4150SN/A if (preen) 4160SN/A printf("%s: ", cdevname); 4170SN/A pfatal("BAD SUPER BLOCK: %s\n", s); 4180SN/A} 4190SN/A 4200SN/Avoid 4210SN/Asblock_init(void) 4220SN/A{ 4230SN/A struct disklabel *lp; 4240SN/A 4250SN/A fswritefd = -1; 4260SN/A fsmodified = 0; 4270SN/A lfdir = 0; 4280SN/A initbarea(&sblk); 4290SN/A initbarea(&asblk); 4300SN/A sblk.b_un.b_buf = malloc(SBLOCKSIZE); 4310SN/A asblk.b_un.b_buf = malloc(SBLOCKSIZE); 4320SN/A if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 4330SN/A errx(EEXIT, "cannot allocate space for superblock"); 4340SN/A if ((lp = getdisklabel(NULL, fsreadfd))) 4350SN/A dev_bsize = secsize = lp->d_secsize; 4360SN/A else 4370SN/A dev_bsize = secsize = DEV_BSIZE; 4380SN/A} 4390SN/A 4400SN/A/* 4410SN/A * Calculate a prototype superblock based on information in the disk label. 4420SN/A * When done the cgsblock macro can be calculated and the fs_ncg field 4430SN/A * can be used. Do NOT attempt to use other macros without verifying that 4440SN/A * their needed information is available! 4450SN/A */ 4460SN/Astatic int 4470SN/Acalcsb(char *dev, int devfd, struct fs *fs) 4480SN/A{ 4490SN/A struct disklabel *lp; 4500SN/A struct partition *pp; 4510SN/A char *cp; 4520SN/A int i, nspf; 4530SN/A 4540SN/A cp = strchr(dev, '\0') - 1; 4550SN/A if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) { 4560SN/A pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 4570SN/A return (0); 4580SN/A } 4590SN/A lp = getdisklabel(dev, devfd); 4600SN/A if (isdigit(*cp)) 4610SN/A pp = &lp->d_partitions[0]; 4620SN/A else 4630SN/A pp = &lp->d_partitions[*cp - 'a']; 4640SN/A if (pp->p_fstype != FS_BSDFFS) { 4650SN/A pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", 4660SN/A dev, pp->p_fstype < FSMAXTYPES ? 4670SN/A fstypenames[pp->p_fstype] : "unknown"); 4680SN/A return (0); 4690SN/A } 4700SN/A if (pp->p_fsize == 0 || pp->p_frag == 0 || 4710SN/A pp->p_cpg == 0 || pp->p_size == 0) { 4720SN/A pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n", 4730SN/A dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype], 4740SN/A pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size); 4750SN/A return (0); 4763388SN/A } 4770SN/A memset(fs, 0, sizeof(struct fs)); 4780SN/A fs->fs_fsize = pp->p_fsize; 4790SN/A fs->fs_frag = pp->p_frag; 4800SN/A fs->fs_size = pp->p_size; 4810SN/A fs->fs_sblkno = roundup( 4820SN/A howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), 4830SN/A fs->fs_frag); 4840SN/A nspf = fs->fs_fsize / lp->d_secsize; 4850SN/A for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1) 4860SN/A fs->fs_fsbtodb++; 4870SN/A dev_bsize = lp->d_secsize; 4880SN/A if (fs->fs_magic == FS_UFS2_MAGIC) { 4890SN/A fs->fs_fpg = pp->p_cpg; 4900SN/A fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg); 4910SN/A } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ { 4920SN/A fs->fs_old_cpg = pp->p_cpg; 4930SN/A fs->fs_old_cgmask = 0xffffffff; 4940SN/A for (i = lp->d_ntracks; i > 1; i >>= 1) 4950SN/A fs->fs_old_cgmask <<= 1; 4960SN/A if (!POWEROF2(lp->d_ntracks)) 4970SN/A fs->fs_old_cgmask <<= 1; 4980SN/A fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf), 4998565SN/A fs->fs_frag); 5000SN/A fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf; 5010SN/A fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl, 5020SN/A fs->fs_old_cpg); 5030SN/A } 5040SN/A return (1); 5050SN/A} 5060SN/A 5070SN/Astatic struct disklabel * 5080SN/Agetdisklabel(char *s, int fd) 5090SN/A{ 5100SN/A static struct disklabel lab; 5110SN/A 5120SN/A if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { 5130SN/A if (s == NULL) 5140SN/A return ((struct disklabel *)NULL); 5150SN/A pwarn("ioctl (GCINFO): %s\n", strerror(errno)); 5160SN/A errx(EEXIT, "%s: can't read disk label", s); 5170SN/A } 5180SN/A return (&lab); 5190SN/A} 5200SN/A