18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1980, 1986, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 68fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 78fae3551SRodney W. Grimes * are met: 88fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 98fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 108fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 128fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 138fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 148fae3551SRodney W. Grimes * must display the following acknowledgement: 158fae3551SRodney W. Grimes * This product includes software developed by the University of 168fae3551SRodney W. Grimes * California, Berkeley and its contributors. 178fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 188fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 198fae3551SRodney W. Grimes * without specific prior written permission. 208fae3551SRodney W. Grimes * 218fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 228fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 258fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 268fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 278fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 288fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 298fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 308fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 318fae3551SRodney W. Grimes * SUCH DAMAGE. 328fae3551SRodney W. Grimes */ 338fae3551SRodney W. Grimes 348fae3551SRodney W. Grimes #ifndef lint 356b100474SJulian Elischer #if 0 36780a5c1eSPeter Wemm static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; 376b100474SJulian Elischer #endif 386b100474SJulian Elischer static const char rcsid[] = 397f3dea24SPeter Wemm "$FreeBSD$"; 408fae3551SRodney W. Grimes #endif /* not lint */ 418fae3551SRodney W. Grimes 428fae3551SRodney W. Grimes #define DKTYPENAMES 438fae3551SRodney W. Grimes #include <sys/param.h> 448fae3551SRodney W. Grimes #include <sys/stat.h> 458fae3551SRodney W. Grimes #include <sys/disklabel.h> 468fae3551SRodney W. Grimes #include <sys/file.h> 47bf58d635SIan Dowse #include <sys/sysctl.h> 48780a5c1eSPeter Wemm 49780a5c1eSPeter Wemm #include <ufs/ufs/dinode.h> 50780a5c1eSPeter Wemm #include <ufs/ffs/fs.h> 51780a5c1eSPeter Wemm 52780a5c1eSPeter Wemm #include <ctype.h> 53780a5c1eSPeter Wemm #include <err.h> 548fae3551SRodney W. Grimes #include <errno.h> 558fae3551SRodney W. Grimes #include <string.h> 56780a5c1eSPeter Wemm 578fae3551SRodney W. Grimes #include "fsck.h" 588fae3551SRodney W. Grimes 598fae3551SRodney W. Grimes struct bufarea asblk; 608fae3551SRodney W. Grimes #define altsblock (*asblk.b_un.b_fs) 618fae3551SRodney W. Grimes #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 628fae3551SRodney W. Grimes 63b70cd7eeSWarner Losh static void badsb(int listerr, char *s); 64b70cd7eeSWarner Losh static int calcsb(char *dev, int devfd, struct fs *fs); 65b70cd7eeSWarner Losh static struct disklabel *getdisklabel(char *s, int fd); 668fae3551SRodney W. Grimes 67780a5c1eSPeter Wemm /* 68780a5c1eSPeter Wemm * Read in a superblock finding an alternate if necessary. 69780a5c1eSPeter Wemm * Return 1 if successful, 0 if unsuccessful, -1 if filesystem 70780a5c1eSPeter Wemm * is already clean (preen mode only). 71780a5c1eSPeter Wemm */ 7231f4ab50SBruce Evans int 73b70cd7eeSWarner Losh setup(char *dev) 748fae3551SRodney W. Grimes { 75bf58d635SIan Dowse long cg, asked, i, j; 7638375c40SKirk McKusick long bmapsize; 778fae3551SRodney W. Grimes off_t sizepb; 788fae3551SRodney W. Grimes struct stat statb; 798fae3551SRodney W. Grimes struct fs proto; 80bf58d635SIan Dowse size_t size; 818fae3551SRodney W. Grimes 828fae3551SRodney W. Grimes havesb = 0; 838fae3551SRodney W. Grimes fswritefd = -1; 84142d8d2fSKirk McKusick cursnapshot = 0; 858fae3551SRodney W. Grimes if (stat(dev, &statb) < 0) { 868fae3551SRodney W. Grimes printf("Can't stat %s: %s\n", dev, strerror(errno)); 877578c6abSKirk McKusick if (bkgrdflag) { 887578c6abSKirk McKusick unlink(snapname); 897578c6abSKirk McKusick bkgrdflag = 0; 907578c6abSKirk McKusick } 918fae3551SRodney W. Grimes return (0); 928fae3551SRodney W. Grimes } 93ff180522SPoul-Henning Kamp if ((statb.st_mode & S_IFMT) != S_IFCHR && 94ff180522SPoul-Henning Kamp (statb.st_mode & S_IFMT) != S_IFBLK) { 957578c6abSKirk McKusick if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) { 967578c6abSKirk McKusick unlink(snapname); 977578c6abSKirk McKusick printf("background fsck lacks a snapshot\n"); 987578c6abSKirk McKusick exit(EEXIT); 997578c6abSKirk McKusick } 1007578c6abSKirk McKusick if ((statb.st_flags & SF_SNAPSHOT) != 0 && cvtlevel == 0) { 101142d8d2fSKirk McKusick cursnapshot = statb.st_ino; 102142d8d2fSKirk McKusick } else { 1037578c6abSKirk McKusick if (cvtlevel == 0 || 1047578c6abSKirk McKusick (statb.st_flags & SF_SNAPSHOT) == 0) { 1057578c6abSKirk McKusick if (preen && bkgrdflag) { 1067578c6abSKirk McKusick unlink(snapname); 1077578c6abSKirk McKusick bkgrdflag = 0; 1087578c6abSKirk McKusick } 109ff180522SPoul-Henning Kamp pfatal("%s is not a disk device", dev); 1107578c6abSKirk McKusick if (reply("CONTINUE") == 0) { 1117578c6abSKirk McKusick if (bkgrdflag) { 1127578c6abSKirk McKusick unlink(snapname); 1137578c6abSKirk McKusick bkgrdflag = 0; 1147578c6abSKirk McKusick } 1158fae3551SRodney W. Grimes return (0); 1168fae3551SRodney W. Grimes } 1177578c6abSKirk McKusick } else { 1187578c6abSKirk McKusick if (bkgrdflag) { 1197578c6abSKirk McKusick unlink(snapname); 1207578c6abSKirk McKusick bkgrdflag = 0; 1217578c6abSKirk McKusick } 1227578c6abSKirk McKusick pfatal("cannot convert a snapshot"); 1237578c6abSKirk McKusick exit(EEXIT); 1247578c6abSKirk McKusick } 1257578c6abSKirk McKusick } 126142d8d2fSKirk McKusick } 1278fae3551SRodney W. Grimes if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 1287578c6abSKirk McKusick if (bkgrdflag) { 1297578c6abSKirk McKusick unlink(snapname); 1307578c6abSKirk McKusick bkgrdflag = 0; 1317578c6abSKirk McKusick } 1328fae3551SRodney W. Grimes printf("Can't open %s: %s\n", dev, strerror(errno)); 1338fae3551SRodney W. Grimes return (0); 1348fae3551SRodney W. Grimes } 1357578c6abSKirk McKusick if (bkgrdflag) { 1367578c6abSKirk McKusick unlink(snapname); 1377578c6abSKirk McKusick size = MIBSIZE; 1387578c6abSKirk McKusick if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0|| 1397578c6abSKirk McKusick sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0|| 1407578c6abSKirk McKusick sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0|| 1417578c6abSKirk McKusick sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 || 1427578c6abSKirk McKusick sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) { 1437578c6abSKirk McKusick pfatal("kernel lacks background fsck support\n"); 1447578c6abSKirk McKusick exit(EEXIT); 1457578c6abSKirk McKusick } 1467578c6abSKirk McKusick cmd.version = FFS_CMD_VERSION; 1477578c6abSKirk McKusick cmd.handle = fsreadfd; 1487578c6abSKirk McKusick fswritefd = -1; 1497578c6abSKirk McKusick } 1508fae3551SRodney W. Grimes if (preen == 0) 1518fae3551SRodney W. Grimes printf("** %s", dev); 1527578c6abSKirk McKusick if (bkgrdflag == 0 && 1537578c6abSKirk McKusick (nflag || (fswritefd = open(dev, O_WRONLY)) < 0)) { 1548fae3551SRodney W. Grimes fswritefd = -1; 1558fae3551SRodney W. Grimes if (preen) 1568fae3551SRodney W. Grimes pfatal("NO WRITE ACCESS"); 1578fae3551SRodney W. Grimes printf(" (NO WRITE)"); 1588fae3551SRodney W. Grimes } 1598fae3551SRodney W. Grimes if (preen == 0) 1608fae3551SRodney W. Grimes printf("\n"); 1618fae3551SRodney W. Grimes /* 1628fae3551SRodney W. Grimes * Read in the superblock, looking for alternates if necessary 1638fae3551SRodney W. Grimes */ 1648fae3551SRodney W. Grimes if (readsb(1) == 0) { 165780a5c1eSPeter Wemm skipclean = 0; 1668fae3551SRodney W. Grimes if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) 1678fae3551SRodney W. Grimes return(0); 1688fae3551SRodney W. Grimes if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 1698fae3551SRodney W. Grimes return (0); 1708fae3551SRodney W. Grimes for (cg = 0; cg < proto.fs_ncg; cg++) { 1718fae3551SRodney W. Grimes bflag = fsbtodb(&proto, cgsblock(&proto, cg)); 1728fae3551SRodney W. Grimes if (readsb(0) != 0) 1738fae3551SRodney W. Grimes break; 1748fae3551SRodney W. Grimes } 1758fae3551SRodney W. Grimes if (cg >= proto.fs_ncg) { 1768fae3551SRodney W. Grimes printf("%s %s\n%s %s\n%s %s\n", 1778fae3551SRodney W. Grimes "SEARCH FOR ALTERNATE SUPER-BLOCK", 1788fae3551SRodney W. Grimes "FAILED. YOU MUST USE THE", 1798fae3551SRodney W. Grimes "-b OPTION TO FSCK TO SPECIFY THE", 1808fae3551SRodney W. Grimes "LOCATION OF AN ALTERNATE", 1818fae3551SRodney W. Grimes "SUPER-BLOCK TO SUPPLY NEEDED", 1828fae3551SRodney W. Grimes "INFORMATION; SEE fsck(8)."); 1831e30185aSBruce Evans bflag = 0; 1848fae3551SRodney W. Grimes return(0); 1858fae3551SRodney W. Grimes } 1868fae3551SRodney W. Grimes pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 1871e30185aSBruce Evans bflag = 0; 1888fae3551SRodney W. Grimes } 18938375c40SKirk McKusick if (skipclean && preen && sblock.fs_clean) { 190d33e92f9SJulian Elischer pwarn("FILESYSTEM CLEAN; SKIPPING CHECKS\n"); 191d33e92f9SJulian Elischer return (-1); 192d33e92f9SJulian Elischer } 1938fae3551SRodney W. Grimes maxfsblock = sblock.fs_size; 1948fae3551SRodney W. Grimes maxino = sblock.fs_ncg * sblock.fs_ipg; 1958fae3551SRodney W. Grimes /* 1968fae3551SRodney W. Grimes * Check and potentially fix certain fields in the super block. 1978fae3551SRodney W. Grimes */ 1988fae3551SRodney W. Grimes if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { 1998fae3551SRodney W. Grimes pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); 2008fae3551SRodney W. Grimes if (reply("SET TO DEFAULT") == 1) { 2018fae3551SRodney W. Grimes sblock.fs_optim = FS_OPTTIME; 2028fae3551SRodney W. Grimes sbdirty(); 2038fae3551SRodney W. Grimes } 2048fae3551SRodney W. Grimes } 2058fae3551SRodney W. Grimes if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { 2068fae3551SRodney W. Grimes pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 2078fae3551SRodney W. Grimes sblock.fs_minfree); 2088fae3551SRodney W. Grimes if (reply("SET TO DEFAULT") == 1) { 2098fae3551SRodney W. Grimes sblock.fs_minfree = 10; 2108fae3551SRodney W. Grimes sbdirty(); 2118fae3551SRodney W. Grimes } 2128fae3551SRodney W. Grimes } 213381ee4c2SPoul-Henning Kamp if (sblock.fs_inodefmt < FS_44INODEFMT) { 214381ee4c2SPoul-Henning Kamp pwarn("Format of filesystem is too old.\n"); 215381ee4c2SPoul-Henning Kamp pwarn("Must update to modern format using a version of fsck\n"); 216381ee4c2SPoul-Henning Kamp pfatal("from before 2002 with the command ``fsck -c 2''\n"); 217381ee4c2SPoul-Henning Kamp exit(EEXIT); 2188fae3551SRodney W. Grimes } 219780a5c1eSPeter Wemm if (asblk.b_dirty && !bflag) { 220780a5c1eSPeter Wemm memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize); 2218fae3551SRodney W. Grimes flush(fswritefd, &asblk); 2228fae3551SRodney W. Grimes } 2238fae3551SRodney W. Grimes /* 2248fae3551SRodney W. Grimes * read in the summary info. 2258fae3551SRodney W. Grimes */ 2268fae3551SRodney W. Grimes asked = 0; 227f55ff3f3SIan Dowse sblock.fs_csp = calloc(1, sblock.fs_cssize); 2288fae3551SRodney W. Grimes for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 2298fae3551SRodney W. Grimes size = sblock.fs_cssize - i < sblock.fs_bsize ? 2308fae3551SRodney W. Grimes sblock.fs_cssize - i : sblock.fs_bsize; 231f55ff3f3SIan Dowse if (bread(fsreadfd, (char *)sblock.fs_csp + i, 2328fae3551SRodney W. Grimes fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 2338fae3551SRodney W. Grimes size) != 0 && !asked) { 2348fae3551SRodney W. Grimes pfatal("BAD SUMMARY INFORMATION"); 235b1897c19SJulian Elischer if (reply("CONTINUE") == 0) { 236b1897c19SJulian Elischer ckfini(0); 237780a5c1eSPeter Wemm exit(EEXIT); 238b1897c19SJulian Elischer } 2398fae3551SRodney W. Grimes asked++; 2408fae3551SRodney W. Grimes } 2418fae3551SRodney W. Grimes } 2428fae3551SRodney W. Grimes /* 2438fae3551SRodney W. Grimes * allocate and initialize the necessary maps 2448fae3551SRodney W. Grimes */ 2458fae3551SRodney W. Grimes bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short)); 2468fae3551SRodney W. Grimes blockmap = calloc((unsigned)bmapsize, sizeof (char)); 2478fae3551SRodney W. Grimes if (blockmap == NULL) { 2488fae3551SRodney W. Grimes printf("cannot alloc %u bytes for blockmap\n", 2498fae3551SRodney W. Grimes (unsigned)bmapsize); 2508fae3551SRodney W. Grimes goto badsb; 2518fae3551SRodney W. Grimes } 252d33e92f9SJulian Elischer inostathead = calloc((unsigned)(sblock.fs_ncg), 253d33e92f9SJulian Elischer sizeof(struct inostatlist)); 254d33e92f9SJulian Elischer if (inostathead == NULL) { 255d33e92f9SJulian Elischer printf("cannot alloc %u bytes for inostathead\n", 256d33e92f9SJulian Elischer (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg))); 2578fae3551SRodney W. Grimes goto badsb; 2588fae3551SRodney W. Grimes } 2598fae3551SRodney W. Grimes numdirs = sblock.fs_cstotal.cs_ndir; 260e50342e6SKirk McKusick dirhash = numdirs; 261c5d3d7fdSPoul-Henning Kamp if (numdirs == 0) { 262c5d3d7fdSPoul-Henning Kamp printf("numdirs is zero, try using an alternate superblock\n"); 263c5d3d7fdSPoul-Henning Kamp goto badsb; 264c5d3d7fdSPoul-Henning Kamp } 2658fae3551SRodney W. Grimes inplast = 0; 2668fae3551SRodney W. Grimes listmax = numdirs + 10; 2678fae3551SRodney W. Grimes inpsort = (struct inoinfo **)calloc((unsigned)listmax, 2688fae3551SRodney W. Grimes sizeof(struct inoinfo *)); 2698fae3551SRodney W. Grimes inphead = (struct inoinfo **)calloc((unsigned)numdirs, 2708fae3551SRodney W. Grimes sizeof(struct inoinfo *)); 2718fae3551SRodney W. Grimes if (inpsort == NULL || inphead == NULL) { 2728fae3551SRodney W. Grimes printf("cannot alloc %u bytes for inphead\n", 2738fae3551SRodney W. Grimes (unsigned)numdirs * sizeof(struct inoinfo *)); 2748fae3551SRodney W. Grimes goto badsb; 2758fae3551SRodney W. Grimes } 2768fae3551SRodney W. Grimes bufinit(); 277b1897c19SJulian Elischer if (sblock.fs_flags & FS_DOSOFTDEP) 278b1897c19SJulian Elischer usedsoftdep = 1; 279b1897c19SJulian Elischer else 280b1897c19SJulian Elischer usedsoftdep = 0; 2818fae3551SRodney W. Grimes return (1); 2828fae3551SRodney W. Grimes 2838fae3551SRodney W. Grimes badsb: 284780a5c1eSPeter Wemm ckfini(0); 2858fae3551SRodney W. Grimes return (0); 2868fae3551SRodney W. Grimes } 2878fae3551SRodney W. Grimes 2888fae3551SRodney W. Grimes /* 2898fae3551SRodney W. Grimes * Read in the super block and its summary info. 2908fae3551SRodney W. Grimes */ 29138375c40SKirk McKusick int 292b70cd7eeSWarner Losh readsb(int listerr) 2938fae3551SRodney W. Grimes { 294780a5c1eSPeter Wemm ufs_daddr_t super = bflag ? bflag : SBOFF / dev_bsize; 2958fae3551SRodney W. Grimes 2968fae3551SRodney W. Grimes if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0) 2978fae3551SRodney W. Grimes return (0); 2988fae3551SRodney W. Grimes sblk.b_bno = super; 2998fae3551SRodney W. Grimes sblk.b_size = SBSIZE; 3008fae3551SRodney W. Grimes /* 3018fae3551SRodney W. Grimes * run a few consistency checks of the super block 3028fae3551SRodney W. Grimes */ 3038fae3551SRodney W. Grimes if (sblock.fs_magic != FS_MAGIC) 3048fae3551SRodney W. Grimes { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); } 3058fae3551SRodney W. Grimes if (sblock.fs_ncg < 1) 3068fae3551SRodney W. Grimes { badsb(listerr, "NCG OUT OF RANGE"); return (0); } 3078fae3551SRodney W. Grimes if (sblock.fs_cpg < 1) 3088fae3551SRodney W. Grimes { badsb(listerr, "CPG OUT OF RANGE"); return (0); } 3098fae3551SRodney W. Grimes if (sblock.fs_sbsize > SBSIZE) 3108fae3551SRodney W. Grimes { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); } 3118fae3551SRodney W. Grimes /* 3128fae3551SRodney W. Grimes * Compute block size that the filesystem is based on, 3138fae3551SRodney W. Grimes * according to fsbtodb, and adjust superblock block number 3148fae3551SRodney W. Grimes * so we can tell if this is an alternate later. 3158fae3551SRodney W. Grimes */ 3168fae3551SRodney W. Grimes super *= dev_bsize; 3178fae3551SRodney W. Grimes dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 3188fae3551SRodney W. Grimes sblk.b_bno = super / dev_bsize; 3198fae3551SRodney W. Grimes if (bflag) { 3208fae3551SRodney W. Grimes havesb = 1; 3218fae3551SRodney W. Grimes return (1); 3228fae3551SRodney W. Grimes } 3238fae3551SRodney W. Grimes /* 324cdd5d266SKirk McKusick * Compare all fields that should not differ in alternate super block. 3258fae3551SRodney W. Grimes * When an alternate super-block is specified this check is skipped. 3268fae3551SRodney W. Grimes */ 3278fae3551SRodney W. Grimes getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); 3288fae3551SRodney W. Grimes if (asblk.b_errs) 3298fae3551SRodney W. Grimes return (0); 330cdd5d266SKirk McKusick if (altsblock.fs_sblkno != sblock.fs_sblkno || 331cdd5d266SKirk McKusick altsblock.fs_cblkno != sblock.fs_cblkno || 332cdd5d266SKirk McKusick altsblock.fs_iblkno != sblock.fs_iblkno || 333cdd5d266SKirk McKusick altsblock.fs_dblkno != sblock.fs_dblkno || 334cdd5d266SKirk McKusick altsblock.fs_cgoffset != sblock.fs_cgoffset || 335cdd5d266SKirk McKusick altsblock.fs_cgmask != sblock.fs_cgmask || 336cdd5d266SKirk McKusick altsblock.fs_ncg != sblock.fs_ncg || 337cdd5d266SKirk McKusick altsblock.fs_bsize != sblock.fs_bsize || 338cdd5d266SKirk McKusick altsblock.fs_fsize != sblock.fs_fsize || 339cdd5d266SKirk McKusick altsblock.fs_frag != sblock.fs_frag || 340cdd5d266SKirk McKusick altsblock.fs_bmask != sblock.fs_bmask || 341cdd5d266SKirk McKusick altsblock.fs_fmask != sblock.fs_fmask || 342cdd5d266SKirk McKusick altsblock.fs_bshift != sblock.fs_bshift || 343cdd5d266SKirk McKusick altsblock.fs_fshift != sblock.fs_fshift || 344cdd5d266SKirk McKusick altsblock.fs_fragshift != sblock.fs_fragshift || 345cdd5d266SKirk McKusick altsblock.fs_fsbtodb != sblock.fs_fsbtodb || 346cdd5d266SKirk McKusick altsblock.fs_sbsize != sblock.fs_sbsize || 347cdd5d266SKirk McKusick altsblock.fs_nindir != sblock.fs_nindir || 348cdd5d266SKirk McKusick altsblock.fs_inopb != sblock.fs_inopb || 349cdd5d266SKirk McKusick altsblock.fs_cssize != sblock.fs_cssize || 350cdd5d266SKirk McKusick altsblock.fs_cpg != sblock.fs_cpg || 351cdd5d266SKirk McKusick altsblock.fs_ipg != sblock.fs_ipg || 352cdd5d266SKirk McKusick altsblock.fs_fpg != sblock.fs_fpg || 353cdd5d266SKirk McKusick altsblock.fs_magic != sblock.fs_magic) { 3548fae3551SRodney W. Grimes badsb(listerr, 3558fae3551SRodney W. Grimes "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); 3568fae3551SRodney W. Grimes return (0); 3578fae3551SRodney W. Grimes } 3588fae3551SRodney W. Grimes havesb = 1; 3598fae3551SRodney W. Grimes return (1); 3608fae3551SRodney W. Grimes } 3618fae3551SRodney W. Grimes 36231f4ab50SBruce Evans static void 363b70cd7eeSWarner Losh badsb(int listerr, char *s) 3648fae3551SRodney W. Grimes { 3658fae3551SRodney W. Grimes 3668fae3551SRodney W. Grimes if (!listerr) 3678fae3551SRodney W. Grimes return; 3688fae3551SRodney W. Grimes if (preen) 3698fae3551SRodney W. Grimes printf("%s: ", cdevname); 3708fae3551SRodney W. Grimes pfatal("BAD SUPER BLOCK: %s\n", s); 3718fae3551SRodney W. Grimes } 3728fae3551SRodney W. Grimes 373d164d805SIan Dowse void 374b70cd7eeSWarner Losh sblock_init(void) 37538375c40SKirk McKusick { 37638375c40SKirk McKusick struct disklabel *lp; 37738375c40SKirk McKusick 37838375c40SKirk McKusick fswritefd = -1; 37938375c40SKirk McKusick fsmodified = 0; 38038375c40SKirk McKusick lfdir = 0; 38138375c40SKirk McKusick initbarea(&sblk); 38238375c40SKirk McKusick initbarea(&asblk); 38338375c40SKirk McKusick sblk.b_un.b_buf = malloc(SBSIZE); 38438375c40SKirk McKusick asblk.b_un.b_buf = malloc(SBSIZE); 38538375c40SKirk McKusick if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 38638375c40SKirk McKusick errx(EEXIT, "cannot allocate space for superblock"); 38738375c40SKirk McKusick if ((lp = getdisklabel(NULL, fsreadfd))) 38838375c40SKirk McKusick dev_bsize = secsize = lp->d_secsize; 38938375c40SKirk McKusick else 39038375c40SKirk McKusick dev_bsize = secsize = DEV_BSIZE; 39138375c40SKirk McKusick } 39238375c40SKirk McKusick 3938fae3551SRodney W. Grimes /* 3948fae3551SRodney W. Grimes * Calculate a prototype superblock based on information in the disk label. 3958fae3551SRodney W. Grimes * When done the cgsblock macro can be calculated and the fs_ncg field 3968fae3551SRodney W. Grimes * can be used. Do NOT attempt to use other macros without verifying that 3978fae3551SRodney W. Grimes * their needed information is available! 3988fae3551SRodney W. Grimes */ 399780a5c1eSPeter Wemm static int 400b70cd7eeSWarner Losh calcsb(char *dev, int devfd, struct fs *fs) 4018fae3551SRodney W. Grimes { 4023d438ad6SDavid E. O'Brien struct disklabel *lp; 4033d438ad6SDavid E. O'Brien struct partition *pp; 4043d438ad6SDavid E. O'Brien char *cp; 4058fae3551SRodney W. Grimes int i; 4068fae3551SRodney W. Grimes 407780a5c1eSPeter Wemm cp = strchr(dev, '\0') - 1; 40831f4ab50SBruce Evans if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) { 4098fae3551SRodney W. Grimes pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 4108fae3551SRodney W. Grimes return (0); 4118fae3551SRodney W. Grimes } 4128fae3551SRodney W. Grimes lp = getdisklabel(dev, devfd); 4138fae3551SRodney W. Grimes if (isdigit(*cp)) 4148fae3551SRodney W. Grimes pp = &lp->d_partitions[0]; 4158fae3551SRodney W. Grimes else 4168fae3551SRodney W. Grimes pp = &lp->d_partitions[*cp - 'a']; 4178fae3551SRodney W. Grimes if (pp->p_fstype != FS_BSDFFS) { 4188fae3551SRodney W. Grimes pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", 4198fae3551SRodney W. Grimes dev, pp->p_fstype < FSMAXTYPES ? 4208fae3551SRodney W. Grimes fstypenames[pp->p_fstype] : "unknown"); 4218fae3551SRodney W. Grimes return (0); 4228fae3551SRodney W. Grimes } 423d33e92f9SJulian Elischer if (pp->p_fsize == 0 || pp->p_frag == 0 || 424d33e92f9SJulian Elischer pp->p_cpg == 0 || pp->p_size == 0) { 425d33e92f9SJulian Elischer pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n", 426d33e92f9SJulian Elischer dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype], 427d33e92f9SJulian Elischer pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size); 428cc52d04fSBruce Evans return (0); 429cc52d04fSBruce Evans } 430780a5c1eSPeter Wemm memset(fs, 0, sizeof(struct fs)); 4318fae3551SRodney W. Grimes fs->fs_fsize = pp->p_fsize; 4328fae3551SRodney W. Grimes fs->fs_frag = pp->p_frag; 4338fae3551SRodney W. Grimes fs->fs_cpg = pp->p_cpg; 4348fae3551SRodney W. Grimes fs->fs_size = pp->p_size; 4358fae3551SRodney W. Grimes fs->fs_ntrak = lp->d_ntracks; 4368fae3551SRodney W. Grimes fs->fs_nsect = lp->d_nsectors; 4378fae3551SRodney W. Grimes fs->fs_spc = lp->d_secpercyl; 4388fae3551SRodney W. Grimes fs->fs_nspf = fs->fs_fsize / lp->d_secsize; 4398fae3551SRodney W. Grimes fs->fs_cgmask = 0xffffffff; 4408fae3551SRodney W. Grimes for (i = fs->fs_ntrak; i > 1; i >>= 1) 4418fae3551SRodney W. Grimes fs->fs_cgmask <<= 1; 4428fae3551SRodney W. Grimes if (!POWEROF2(fs->fs_ntrak)) 4438fae3551SRodney W. Grimes fs->fs_cgmask <<= 1; 4448fae3551SRodney W. Grimes fs->fs_cgoffset = roundup( 4458fae3551SRodney W. Grimes howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag); 4468fae3551SRodney W. Grimes fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs); 4478fae3551SRodney W. Grimes fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg); 4488fae3551SRodney W. Grimes for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1) 4498fae3551SRodney W. Grimes fs->fs_fsbtodb++; 4508fae3551SRodney W. Grimes dev_bsize = lp->d_secsize; 4518fae3551SRodney W. Grimes return (1); 4528fae3551SRodney W. Grimes } 4538fae3551SRodney W. Grimes 454780a5c1eSPeter Wemm static struct disklabel * 455b70cd7eeSWarner Losh getdisklabel(char *s, int fd) 4568fae3551SRodney W. Grimes { 4578fae3551SRodney W. Grimes static struct disklabel lab; 4588fae3551SRodney W. Grimes 4598fae3551SRodney W. Grimes if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { 4608fae3551SRodney W. Grimes if (s == NULL) 4618fae3551SRodney W. Grimes return ((struct disklabel *)NULL); 4628fae3551SRodney W. Grimes pwarn("ioctl (GCINFO): %s\n", strerror(errno)); 463780a5c1eSPeter Wemm errx(EEXIT, "%s: can't read disk label", s); 4648fae3551SRodney W. Grimes } 4658fae3551SRodney W. Grimes return (&lab); 4668fae3551SRodney W. Grimes } 467