1 1.39 mlelstv /* $NetBSD: setup.c,v 1.39 2019/03/31 13:16:52 mlelstv Exp $ */ 2 1.1 bouyer 3 1.1 bouyer /* 4 1.1 bouyer * Copyright (c) 1980, 1986, 1993 5 1.1 bouyer * The Regents of the University of California. All rights reserved. 6 1.1 bouyer * 7 1.1 bouyer * Redistribution and use in source and binary forms, with or without 8 1.1 bouyer * modification, are permitted provided that the following conditions 9 1.1 bouyer * are met: 10 1.1 bouyer * 1. Redistributions of source code must retain the above copyright 11 1.1 bouyer * notice, this list of conditions and the following disclaimer. 12 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 bouyer * notice, this list of conditions and the following disclaimer in the 14 1.1 bouyer * documentation and/or other materials provided with the distribution. 15 1.13 agc * 3. Neither the name of the University nor the names of its contributors 16 1.13 agc * may be used to endorse or promote products derived from this software 17 1.13 agc * without specific prior written permission. 18 1.13 agc * 19 1.13 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.13 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.13 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.13 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.13 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.13 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.13 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.13 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.13 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.13 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.13 agc * SUCH DAMAGE. 30 1.13 agc */ 31 1.13 agc 32 1.13 agc /* 33 1.13 agc * Copyright (c) 1997 Manuel Bouyer. 34 1.13 agc * 35 1.13 agc * Redistribution and use in source and binary forms, with or without 36 1.13 agc * modification, are permitted provided that the following conditions 37 1.13 agc * are met: 38 1.13 agc * 1. Redistributions of source code must retain the above copyright 39 1.13 agc * notice, this list of conditions and the following disclaimer. 40 1.13 agc * 2. Redistributions in binary form must reproduce the above copyright 41 1.13 agc * notice, this list of conditions and the following disclaimer in the 42 1.13 agc * documentation and/or other materials provided with the distribution. 43 1.1 bouyer * 44 1.15 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 45 1.15 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46 1.15 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47 1.15 bouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 48 1.15 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 49 1.15 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 50 1.15 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 51 1.15 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52 1.15 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 53 1.15 bouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 1.1 bouyer */ 55 1.1 bouyer 56 1.4 lukem #include <sys/cdefs.h> 57 1.1 bouyer #ifndef lint 58 1.1 bouyer #if 0 59 1.1 bouyer static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94"; 60 1.1 bouyer #else 61 1.39 mlelstv __RCSID("$NetBSD: setup.c,v 1.39 2019/03/31 13:16:52 mlelstv Exp $"); 62 1.1 bouyer #endif 63 1.1 bouyer #endif /* not lint */ 64 1.1 bouyer 65 1.8 christos #define FSTYPENAMES 66 1.1 bouyer #include <sys/param.h> 67 1.1 bouyer #include <sys/time.h> 68 1.36 mlelstv #include <sys/bitops.h> 69 1.1 bouyer #include <ufs/ext2fs/ext2fs_dinode.h> 70 1.1 bouyer #include <ufs/ext2fs/ext2fs.h> 71 1.1 bouyer #include <sys/stat.h> 72 1.1 bouyer #include <sys/ioctl.h> 73 1.38 mlelstv #include <sys/disk.h> 74 1.1 bouyer #include <sys/file.h> 75 1.1 bouyer 76 1.1 bouyer #include <errno.h> 77 1.1 bouyer #include <stdio.h> 78 1.1 bouyer #include <stdlib.h> 79 1.1 bouyer #include <string.h> 80 1.1 bouyer #include <ctype.h> 81 1.1 bouyer 82 1.35 jdolecek #include <util.h> 83 1.35 jdolecek 84 1.1 bouyer #include "fsck.h" 85 1.1 bouyer #include "extern.h" 86 1.1 bouyer #include "fsutil.h" 87 1.38 mlelstv #include "partutil.h" 88 1.25 lukem #include "exitvalues.h" 89 1.1 bouyer 90 1.19 christos void badsb(int, const char *); 91 1.17 xtraeme int calcsb(const char *, int, struct m_ext2fs *); 92 1.17 xtraeme static int readsb(int); 93 1.1 bouyer 94 1.38 mlelstv /* 95 1.38 mlelstv * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults, 96 1.38 mlelstv * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use 97 1.38 mlelstv * L_DFL_*. 98 1.38 mlelstv */ 99 1.38 mlelstv #define SMALL_FSSIZE ((4 * 1024 * 1024) / secsize) /* 4MB */ 100 1.38 mlelstv #define S_DFL_BSIZE 1024 101 1.38 mlelstv #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / secsize) /* 512MB */ 102 1.38 mlelstv #define M_DFL_BSIZE 1024 103 1.38 mlelstv #define L_DFL_BSIZE 4096 104 1.38 mlelstv 105 1.1 bouyer int 106 1.17 xtraeme setup(const char *dev) 107 1.1 bouyer { 108 1.4 lukem long cg, asked, i; 109 1.1 bouyer long bmapsize; 110 1.38 mlelstv struct disk_geom geo; 111 1.38 mlelstv struct dkwedge_info dkw; 112 1.1 bouyer off_t sizepb; 113 1.1 bouyer struct stat statb; 114 1.1 bouyer struct m_ext2fs proto; 115 1.1 bouyer int doskipclean; 116 1.1 bouyer u_int64_t maxfilesize; 117 1.1 bouyer 118 1.1 bouyer havesb = 0; 119 1.1 bouyer fswritefd = -1; 120 1.1 bouyer doskipclean = skipclean; 121 1.1 bouyer if (stat(dev, &statb) < 0) { 122 1.1 bouyer printf("Can't stat %s: %s\n", dev, strerror(errno)); 123 1.23 tsutsui return 0; 124 1.1 bouyer } 125 1.1 bouyer if (!S_ISCHR(statb.st_mode)) { 126 1.1 bouyer pfatal("%s is not a character device", dev); 127 1.1 bouyer if (reply("CONTINUE") == 0) 128 1.23 tsutsui return 0; 129 1.1 bouyer } 130 1.1 bouyer if ((fsreadfd = open(dev, O_RDONLY)) < 0) { 131 1.1 bouyer printf("Can't open %s: %s\n", dev, strerror(errno)); 132 1.23 tsutsui return 0; 133 1.1 bouyer } 134 1.1 bouyer if (preen == 0) 135 1.1 bouyer printf("** %s", dev); 136 1.1 bouyer if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { 137 1.1 bouyer fswritefd = -1; 138 1.1 bouyer if (preen) 139 1.1 bouyer pfatal("NO WRITE ACCESS"); 140 1.1 bouyer printf(" (NO WRITE)"); 141 1.1 bouyer } 142 1.1 bouyer if (preen == 0) 143 1.1 bouyer printf("\n"); 144 1.1 bouyer fsmodified = 0; 145 1.1 bouyer lfdir = 0; 146 1.1 bouyer initbarea(&sblk); 147 1.1 bouyer initbarea(&asblk); 148 1.6 bouyer sblk.b_un.b_buf = malloc(SBSIZE); 149 1.6 bouyer asblk.b_un.b_buf = malloc(SBSIZE); 150 1.1 bouyer if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 151 1.25 lukem errexit("cannot allocate space for superblock"); 152 1.38 mlelstv if (getdiskinfo(dev, fsreadfd, NULL, &geo, &dkw) != -1) 153 1.38 mlelstv dev_bsize = secsize = geo.dg_secsize; 154 1.1 bouyer else 155 1.1 bouyer dev_bsize = secsize = DEV_BSIZE; 156 1.1 bouyer /* 157 1.1 bouyer * Read in the superblock, looking for alternates if necessary 158 1.1 bouyer */ 159 1.1 bouyer if (readsb(1) == 0) { 160 1.1 bouyer if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) 161 1.23 tsutsui return 0; 162 1.1 bouyer if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) 163 1.23 tsutsui return 0; 164 1.1 bouyer for (cg = 1; cg < proto.e2fs_ncg; cg++) { 165 1.31 dholland bflag = EXT2_FSBTODB(&proto, 166 1.23 tsutsui cg * proto.e2fs.e2fs_bpg + 167 1.23 tsutsui proto.e2fs.e2fs_first_dblock); 168 1.1 bouyer if (readsb(0) != 0) 169 1.1 bouyer break; 170 1.1 bouyer } 171 1.1 bouyer if (cg >= proto.e2fs_ncg) { 172 1.1 bouyer printf("%s %s\n%s %s\n%s %s\n", 173 1.23 tsutsui "SEARCH FOR ALTERNATE SUPER-BLOCK", 174 1.23 tsutsui "FAILED. YOU MUST USE THE", 175 1.23 tsutsui "-b OPTION TO FSCK_FFS TO SPECIFY THE", 176 1.23 tsutsui "LOCATION OF AN ALTERNATE", 177 1.23 tsutsui "SUPER-BLOCK TO SUPPLY NEEDED", 178 1.23 tsutsui "INFORMATION; SEE fsck_ext2fs(8)."); 179 1.23 tsutsui return 0; 180 1.1 bouyer } 181 1.1 bouyer doskipclean = 0; 182 1.1 bouyer pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); 183 1.1 bouyer } 184 1.1 bouyer if (debug) 185 1.1 bouyer printf("state = %d\n", sblock.e2fs.e2fs_state); 186 1.1 bouyer if (sblock.e2fs.e2fs_state == E2FS_ISCLEAN) { 187 1.1 bouyer if (doskipclean) { 188 1.1 bouyer pwarn("%sile system is clean; not checking\n", 189 1.23 tsutsui preen ? "f" : "** F"); 190 1.23 tsutsui return -1; 191 1.1 bouyer } 192 1.1 bouyer if (!preen) 193 1.1 bouyer pwarn("** File system is already clean\n"); 194 1.1 bouyer } 195 1.1 bouyer maxfsblock = sblock.e2fs.e2fs_bcount; 196 1.1 bouyer maxino = sblock.e2fs_ncg * sblock.e2fs.e2fs_ipg; 197 1.1 bouyer sizepb = sblock.e2fs_bsize; 198 1.29 dholland maxfilesize = sblock.e2fs_bsize * EXT2FS_NDADDR - 1; 199 1.29 dholland for (i = 0; i < EXT2FS_NIADDR; i++) { 200 1.30 dholland sizepb *= EXT2_NINDIR(&sblock); 201 1.1 bouyer maxfilesize += sizepb; 202 1.1 bouyer } 203 1.1 bouyer /* 204 1.1 bouyer * Check and potentially fix certain fields in the super block. 205 1.1 bouyer */ 206 1.20 christos if (/* (sblock.e2fs.e2fs_rbcount < 0) || */ 207 1.23 tsutsui (sblock.e2fs.e2fs_rbcount > sblock.e2fs.e2fs_bcount)) { 208 1.1 bouyer pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK", 209 1.23 tsutsui sblock.e2fs.e2fs_rbcount); 210 1.1 bouyer if (reply("SET TO DEFAULT") == 1) { 211 1.23 tsutsui sblock.e2fs.e2fs_rbcount = 212 1.23 tsutsui sblock.e2fs.e2fs_bcount * MINFREE / 100; 213 1.1 bouyer sbdirty(); 214 1.6 bouyer dirty(&asblk); 215 1.1 bouyer } 216 1.1 bouyer } 217 1.1 bouyer if (sblock.e2fs.e2fs_bpg != sblock.e2fs.e2fs_fpg) { 218 1.1 bouyer pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK", 219 1.23 tsutsui sblock.e2fs.e2fs_fpg, sblock.e2fs.e2fs_bpg); 220 1.1 bouyer return 0; 221 1.1 bouyer } 222 1.1 bouyer if (asblk.b_dirty && !bflag) { 223 1.6 bouyer copyback_sb(&asblk); 224 1.1 bouyer flush(fswritefd, &asblk); 225 1.1 bouyer } 226 1.1 bouyer /* 227 1.1 bouyer * read in the summary info. 228 1.1 bouyer */ 229 1.1 bouyer 230 1.1 bouyer sblock.e2fs_gd = malloc(sblock.e2fs_ngdb * sblock.e2fs_bsize); 231 1.9 bouyer if (sblock.e2fs_gd == NULL) 232 1.25 lukem errexit("out of memory"); 233 1.1 bouyer asked = 0; 234 1.23 tsutsui for (i = 0; i < sblock.e2fs_ngdb; i++) { 235 1.23 tsutsui if (bread(fsreadfd, 236 1.23 tsutsui (char *)&sblock.e2fs_gd[i * sblock.e2fs_bsize / 237 1.23 tsutsui sizeof(struct ext2_gd)], 238 1.31 dholland EXT2_FSBTODB(&sblock, ((sblock.e2fs_bsize > 1024) ? 0 : 1) + 239 1.23 tsutsui i + 1), 240 1.23 tsutsui sblock.e2fs_bsize) != 0 && !asked) { 241 1.1 bouyer pfatal("BAD SUMMARY INFORMATION"); 242 1.1 bouyer if (reply("CONTINUE") == 0) 243 1.25 lukem exit(FSCK_EXIT_CHECK_FAILED); 244 1.1 bouyer asked++; 245 1.1 bouyer } 246 1.1 bouyer } 247 1.1 bouyer /* 248 1.1 bouyer * allocate and initialize the necessary maps 249 1.1 bouyer */ 250 1.1 bouyer bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); 251 1.23 tsutsui blockmap = calloc((unsigned int)bmapsize, sizeof(char)); 252 1.1 bouyer if (blockmap == NULL) { 253 1.1 bouyer printf("cannot alloc %u bytes for blockmap\n", 254 1.23 tsutsui (unsigned int)bmapsize); 255 1.1 bouyer goto badsblabel; 256 1.1 bouyer } 257 1.23 tsutsui statemap = calloc((unsigned int)(maxino + 2), sizeof(char)); 258 1.1 bouyer if (statemap == NULL) { 259 1.1 bouyer printf("cannot alloc %u bytes for statemap\n", 260 1.23 tsutsui (unsigned int)(maxino + 1)); 261 1.1 bouyer goto badsblabel; 262 1.1 bouyer } 263 1.23 tsutsui typemap = calloc((unsigned int)(maxino + 1), sizeof(char)); 264 1.11 bouyer if (typemap == NULL) { 265 1.11 bouyer printf("cannot alloc %u bytes for typemap\n", 266 1.23 tsutsui (unsigned int)(maxino + 1)); 267 1.23 tsutsui goto badsblabel; 268 1.11 bouyer } 269 1.23 tsutsui lncntp = calloc((unsigned)(maxino + 1), sizeof(int16_t)); 270 1.1 bouyer if (lncntp == NULL) { 271 1.23 tsutsui printf("cannot alloc %u bytes for lncntp\n", 272 1.23 tsutsui (unsigned int)((maxino + 1) * sizeof(int16_t))); 273 1.1 bouyer goto badsblabel; 274 1.1 bouyer } 275 1.1 bouyer for (numdirs = 0, cg = 0; cg < sblock.e2fs_ncg; cg++) { 276 1.6 bouyer numdirs += fs2h16(sblock.e2fs_gd[cg].ext2bgd_ndirs); 277 1.1 bouyer } 278 1.1 bouyer inplast = 0; 279 1.1 bouyer listmax = numdirs + 10; 280 1.23 tsutsui inpsort = calloc((unsigned int)listmax, sizeof(struct inoinfo *)); 281 1.23 tsutsui inphead = calloc((unsigned int)numdirs, sizeof(struct inoinfo *)); 282 1.1 bouyer if (inpsort == NULL || inphead == NULL) { 283 1.23 tsutsui printf("cannot alloc %u bytes for inphead\n", 284 1.23 tsutsui (unsigned int)(numdirs * sizeof(struct inoinfo *))); 285 1.1 bouyer goto badsblabel; 286 1.1 bouyer } 287 1.1 bouyer bufinit(); 288 1.23 tsutsui return 1; 289 1.1 bouyer 290 1.1 bouyer badsblabel: 291 1.1 bouyer ckfini(0); 292 1.23 tsutsui return 0; 293 1.1 bouyer } 294 1.1 bouyer 295 1.1 bouyer /* 296 1.6 bouyer * Read in the super block and its summary info, convert to host byte order. 297 1.1 bouyer */ 298 1.1 bouyer static int 299 1.17 xtraeme readsb(int listerr) 300 1.1 bouyer { 301 1.1 bouyer daddr_t super = bflag ? bflag : SBOFF / dev_bsize; 302 1.1 bouyer 303 1.6 bouyer if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super, (long)SBSIZE) != 0) 304 1.23 tsutsui return 0; 305 1.1 bouyer sblk.b_bno = super; 306 1.1 bouyer sblk.b_size = SBSIZE; 307 1.6 bouyer 308 1.6 bouyer /* Copy the superblock in memory */ 309 1.12 bouyer e2fs_sbload(sblk.b_un.b_fs, &sblock.e2fs); 310 1.6 bouyer 311 1.1 bouyer /* 312 1.1 bouyer * run a few consistency checks of the super block 313 1.1 bouyer */ 314 1.1 bouyer if (sblock.e2fs.e2fs_magic != E2FS_MAGIC) { 315 1.23 tsutsui badsb(listerr, "MAGIC NUMBER WRONG"); 316 1.23 tsutsui return 0; 317 1.1 bouyer } 318 1.1 bouyer if (sblock.e2fs.e2fs_log_bsize > 2) { 319 1.23 tsutsui badsb(listerr, "BAD LOG_BSIZE"); 320 1.23 tsutsui return 0; 321 1.1 bouyer } 322 1.26 tsutsui if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 323 1.26 tsutsui (!powerof2(sblock.e2fs.e2fs_inode_size) || 324 1.34 jdolecek sblock.e2fs.e2fs_inode_size < EXT2_REV0_DINODE_SIZE || 325 1.26 tsutsui sblock.e2fs.e2fs_inode_size > 326 1.26 tsutsui (1024 << sblock.e2fs.e2fs_log_bsize))) { 327 1.26 tsutsui badsb(listerr, "BAD INODE_SIZE"); 328 1.26 tsutsui return 0; 329 1.26 tsutsui } 330 1.1 bouyer 331 1.1 bouyer /* compute the dynamic fields of the in-memory sb */ 332 1.1 bouyer /* compute dynamic sb infos */ 333 1.1 bouyer sblock.e2fs_ncg = 334 1.23 tsutsui howmany(sblock.e2fs.e2fs_bcount - sblock.e2fs.e2fs_first_dblock, 335 1.23 tsutsui sblock.e2fs.e2fs_bpg); 336 1.36 mlelstv sblock.e2fs_fsbtodb = sblock.e2fs.e2fs_log_bsize + ilog2(1024 / dev_bsize); 337 1.1 bouyer sblock.e2fs_bsize = 1024 << sblock.e2fs.e2fs_log_bsize; 338 1.1 bouyer sblock.e2fs_bshift = LOG_MINBSIZE + sblock.e2fs.e2fs_log_bsize; 339 1.1 bouyer sblock.e2fs_qbmask = sblock.e2fs_bsize - 1; 340 1.1 bouyer sblock.e2fs_bmask = ~sblock.e2fs_qbmask; 341 1.1 bouyer sblock.e2fs_ngdb = howmany(sblock.e2fs_ncg, 342 1.23 tsutsui sblock.e2fs_bsize / sizeof(struct ext2_gd)); 343 1.26 tsutsui sblock.e2fs_ipb = sblock.e2fs_bsize / EXT2_DINODE_SIZE(&sblock); 344 1.21 tsutsui sblock.e2fs_itpg = howmany(sblock.e2fs.e2fs_ipg, sblock.e2fs_ipb); 345 1.1 bouyer 346 1.1 bouyer /* 347 1.1 bouyer * Compute block size that the filesystem is based on, 348 1.1 bouyer * according to fsbtodb, and adjust superblock block number 349 1.1 bouyer * so we can tell if this is an alternate later. 350 1.1 bouyer */ 351 1.1 bouyer super *= dev_bsize; 352 1.31 dholland dev_bsize = sblock.e2fs_bsize / EXT2_FSBTODB(&sblock, 1); 353 1.1 bouyer sblk.b_bno = super / dev_bsize; 354 1.6 bouyer 355 1.21 tsutsui if (sblock.e2fs_ncg == 1) { 356 1.21 tsutsui /* no alternate superblock; assume it's okay */ 357 1.21 tsutsui havesb = 1; 358 1.23 tsutsui return 1; 359 1.21 tsutsui } 360 1.6 bouyer getblk(&asblk, 1 * sblock.e2fs.e2fs_bpg + sblock.e2fs.e2fs_first_dblock, 361 1.6 bouyer (long)SBSIZE); 362 1.6 bouyer if (asblk.b_errs) 363 1.23 tsutsui return 0; 364 1.1 bouyer if (bflag) { 365 1.1 bouyer havesb = 1; 366 1.23 tsutsui return 1; 367 1.1 bouyer } 368 1.1 bouyer 369 1.1 bouyer /* 370 1.1 bouyer * Set all possible fields that could differ, then do check 371 1.1 bouyer * of whole super block against an alternate super block. 372 1.1 bouyer * When an alternate super-block is specified this check is skipped. 373 1.1 bouyer */ 374 1.6 bouyer asblk.b_un.b_fs->e2fs_rbcount = sblk.b_un.b_fs->e2fs_rbcount; 375 1.6 bouyer asblk.b_un.b_fs->e2fs_fbcount = sblk.b_un.b_fs->e2fs_fbcount; 376 1.6 bouyer asblk.b_un.b_fs->e2fs_ficount = sblk.b_un.b_fs->e2fs_ficount; 377 1.6 bouyer asblk.b_un.b_fs->e2fs_mtime = sblk.b_un.b_fs->e2fs_mtime; 378 1.6 bouyer asblk.b_un.b_fs->e2fs_wtime = sblk.b_un.b_fs->e2fs_wtime; 379 1.6 bouyer asblk.b_un.b_fs->e2fs_mnt_count = sblk.b_un.b_fs->e2fs_mnt_count; 380 1.23 tsutsui asblk.b_un.b_fs->e2fs_max_mnt_count = 381 1.23 tsutsui sblk.b_un.b_fs->e2fs_max_mnt_count; 382 1.6 bouyer asblk.b_un.b_fs->e2fs_state = sblk.b_un.b_fs->e2fs_state; 383 1.6 bouyer asblk.b_un.b_fs->e2fs_beh = sblk.b_un.b_fs->e2fs_beh; 384 1.6 bouyer asblk.b_un.b_fs->e2fs_lastfsck = sblk.b_un.b_fs->e2fs_lastfsck; 385 1.6 bouyer asblk.b_un.b_fs->e2fs_fsckintv = sblk.b_un.b_fs->e2fs_fsckintv; 386 1.6 bouyer asblk.b_un.b_fs->e2fs_ruid = sblk.b_un.b_fs->e2fs_ruid; 387 1.6 bouyer asblk.b_un.b_fs->e2fs_rgid = sblk.b_un.b_fs->e2fs_rgid; 388 1.10 bouyer asblk.b_un.b_fs->e2fs_block_group_nr = 389 1.10 bouyer sblk.b_un.b_fs->e2fs_block_group_nr; 390 1.18 ws asblk.b_un.b_fs->e2fs_features_rocompat &= ~EXT2F_ROCOMPAT_LARGEFILE; 391 1.18 ws asblk.b_un.b_fs->e2fs_features_rocompat |= 392 1.18 ws sblk.b_un.b_fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE; 393 1.36 mlelstv memcpy(asblk.b_un.b_fs->e2fs_fsmnt, sblk.b_un.b_fs->e2fs_fsmnt, 394 1.36 mlelstv sizeof(asblk.b_un.b_fs->e2fs_fsmnt)); 395 1.39 mlelstv asblk.b_un.b_fs->e4fs_kbytes_written = 396 1.39 mlelstv sblk.b_un.b_fs->e4fs_kbytes_written; 397 1.12 bouyer if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 398 1.33 jdolecek ((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP_FSCK) || 399 1.33 jdolecek (sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP_FSCK))) { 400 1.10 bouyer if (debug) { 401 1.10 bouyer printf("compat 0x%08x, incompat 0x%08x, compat_ro " 402 1.10 bouyer "0x%08x\n", 403 1.12 bouyer sblock.e2fs.e2fs_features_compat, 404 1.12 bouyer sblock.e2fs.e2fs_features_incompat, 405 1.12 bouyer sblock.e2fs.e2fs_features_rocompat); 406 1.35 jdolecek 407 1.35 jdolecek if ((sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP_FSCK)) { 408 1.35 jdolecek char buf[512]; 409 1.35 jdolecek 410 1.35 jdolecek snprintb(buf, sizeof(buf), EXT2F_ROCOMPAT_BITS, 411 1.35 jdolecek sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP_FSCK); 412 1.35 jdolecek printf("unsupported rocompat features: %s\n", buf); 413 1.35 jdolecek } 414 1.35 jdolecek if ((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP_FSCK)) { 415 1.35 jdolecek char buf[512]; 416 1.35 jdolecek 417 1.35 jdolecek snprintb(buf, sizeof(buf), EXT2F_INCOMPAT_BITS, 418 1.35 jdolecek sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP_FSCK); 419 1.35 jdolecek printf("unsupported incompat features: %s\n", buf); 420 1.35 jdolecek } 421 1.10 bouyer } 422 1.23 tsutsui badsb(listerr, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK"); 423 1.10 bouyer return 0; 424 1.10 bouyer } 425 1.6 bouyer if (memcmp(sblk.b_un.b_fs, asblk.b_un.b_fs, SBSIZE)) { 426 1.1 bouyer if (debug) { 427 1.6 bouyer u_int32_t *nlp, *olp, *endlp; 428 1.1 bouyer 429 1.1 bouyer printf("superblock mismatches\n"); 430 1.6 bouyer nlp = (u_int32_t *)asblk.b_un.b_fs; 431 1.6 bouyer olp = (u_int32_t *)sblk.b_un.b_fs; 432 1.23 tsutsui endlp = olp + (SBSIZE / sizeof(*olp)); 433 1.1 bouyer for ( ; olp < endlp; olp++, nlp++) { 434 1.1 bouyer if (*olp == *nlp) 435 1.1 bouyer continue; 436 1.23 tsutsui printf("offset %ld, original %ld, " 437 1.23 tsutsui "alternate %ld\n", 438 1.23 tsutsui (long)(olp - (u_int32_t *)sblk.b_un.b_fs), 439 1.23 tsutsui (long)fs2h32(*olp), 440 1.23 tsutsui (long)fs2h32(*nlp)); 441 1.1 bouyer } 442 1.1 bouyer } 443 1.1 bouyer badsb(listerr, 444 1.23 tsutsui "VALUES IN SUPER BLOCK DISAGREE WITH " 445 1.23 tsutsui "THOSE IN FIRST ALTERNATE"); 446 1.23 tsutsui return 0; 447 1.1 bouyer } 448 1.1 bouyer havesb = 1; 449 1.23 tsutsui return 1; 450 1.1 bouyer } 451 1.1 bouyer 452 1.1 bouyer void 453 1.17 xtraeme copyback_sb(struct bufarea *bp) 454 1.6 bouyer { 455 1.6 bouyer /* Copy the in-memory superblock back to buffer */ 456 1.24 tsutsui bp->b_un.b_fs->e2fs_icount = h2fs32(sblock.e2fs.e2fs_icount); 457 1.24 tsutsui bp->b_un.b_fs->e2fs_bcount = h2fs32(sblock.e2fs.e2fs_bcount); 458 1.24 tsutsui bp->b_un.b_fs->e2fs_rbcount = h2fs32(sblock.e2fs.e2fs_rbcount); 459 1.24 tsutsui bp->b_un.b_fs->e2fs_fbcount = h2fs32(sblock.e2fs.e2fs_fbcount); 460 1.24 tsutsui bp->b_un.b_fs->e2fs_ficount = h2fs32(sblock.e2fs.e2fs_ficount); 461 1.6 bouyer bp->b_un.b_fs->e2fs_first_dblock = 462 1.24 tsutsui h2fs32(sblock.e2fs.e2fs_first_dblock); 463 1.24 tsutsui bp->b_un.b_fs->e2fs_log_bsize = h2fs32(sblock.e2fs.e2fs_log_bsize); 464 1.24 tsutsui bp->b_un.b_fs->e2fs_fsize = h2fs32(sblock.e2fs.e2fs_fsize); 465 1.24 tsutsui bp->b_un.b_fs->e2fs_bpg = h2fs32(sblock.e2fs.e2fs_bpg); 466 1.24 tsutsui bp->b_un.b_fs->e2fs_fpg = h2fs32(sblock.e2fs.e2fs_fpg); 467 1.24 tsutsui bp->b_un.b_fs->e2fs_ipg = h2fs32(sblock.e2fs.e2fs_ipg); 468 1.24 tsutsui bp->b_un.b_fs->e2fs_mtime = h2fs32(sblock.e2fs.e2fs_mtime); 469 1.24 tsutsui bp->b_un.b_fs->e2fs_wtime = h2fs32(sblock.e2fs.e2fs_wtime); 470 1.24 tsutsui bp->b_un.b_fs->e2fs_lastfsck = h2fs32(sblock.e2fs.e2fs_lastfsck); 471 1.24 tsutsui bp->b_un.b_fs->e2fs_fsckintv = h2fs32(sblock.e2fs.e2fs_fsckintv); 472 1.24 tsutsui bp->b_un.b_fs->e2fs_creator = h2fs32(sblock.e2fs.e2fs_creator); 473 1.24 tsutsui bp->b_un.b_fs->e2fs_rev = h2fs32(sblock.e2fs.e2fs_rev); 474 1.24 tsutsui bp->b_un.b_fs->e2fs_mnt_count = h2fs16(sblock.e2fs.e2fs_mnt_count); 475 1.6 bouyer bp->b_un.b_fs->e2fs_max_mnt_count = 476 1.24 tsutsui h2fs16(sblock.e2fs.e2fs_max_mnt_count); 477 1.24 tsutsui bp->b_un.b_fs->e2fs_magic = h2fs16(sblock.e2fs.e2fs_magic); 478 1.24 tsutsui bp->b_un.b_fs->e2fs_state = h2fs16(sblock.e2fs.e2fs_state); 479 1.24 tsutsui bp->b_un.b_fs->e2fs_beh = h2fs16(sblock.e2fs.e2fs_beh); 480 1.24 tsutsui bp->b_un.b_fs->e2fs_ruid = h2fs16(sblock.e2fs.e2fs_ruid); 481 1.24 tsutsui bp->b_un.b_fs->e2fs_rgid = h2fs16(sblock.e2fs.e2fs_rgid); 482 1.6 bouyer } 483 1.6 bouyer 484 1.6 bouyer void 485 1.19 christos badsb(int listerr, const char *s) 486 1.1 bouyer { 487 1.1 bouyer 488 1.1 bouyer if (!listerr) 489 1.1 bouyer return; 490 1.1 bouyer if (preen) 491 1.1 bouyer printf("%s: ", cdevname()); 492 1.1 bouyer pfatal("BAD SUPER BLOCK: %s\n", s); 493 1.1 bouyer } 494 1.1 bouyer 495 1.1 bouyer /* 496 1.1 bouyer * Calculate a prototype superblock based on information in the disk label. 497 1.1 bouyer * When done the cgsblock macro can be calculated and the fs_ncg field 498 1.1 bouyer * can be used. Do NOT attempt to use other macros without verifying that 499 1.1 bouyer * their needed information is available! 500 1.1 bouyer */ 501 1.1 bouyer 502 1.1 bouyer int 503 1.17 xtraeme calcsb(const char *dev, int devfd, struct m_ext2fs *fs) 504 1.1 bouyer { 505 1.38 mlelstv struct dkwedge_info dkw; 506 1.38 mlelstv struct disk_geom geo; 507 1.38 mlelstv 508 1.38 mlelstv if (getdiskinfo(dev, devfd, NULL, &geo, &dkw) == -1) 509 1.38 mlelstv pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 510 1.38 mlelstv if (dkw.dkw_parent[0] == '\0') { 511 1.1 bouyer pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); 512 1.23 tsutsui return 0; 513 1.1 bouyer } 514 1.38 mlelstv 515 1.38 mlelstv memset(fs, 0, sizeof(struct m_ext2fs)); 516 1.38 mlelstv 517 1.38 mlelstv if (dkw.dkw_size < (uint64_t)SMALL_FSSIZE) 518 1.38 mlelstv fs->e2fs_bsize = S_DFL_BSIZE; 519 1.38 mlelstv else if (dkw.dkw_size < (uint64_t)MEDIUM_FSSIZE) 520 1.38 mlelstv fs->e2fs_bsize = M_DFL_BSIZE; 521 1.1 bouyer else 522 1.38 mlelstv fs->e2fs_bsize = L_DFL_BSIZE; 523 1.38 mlelstv 524 1.38 mlelstv fs->e2fs.e2fs_log_bsize = ilog2(fs->e2fs_bsize / 1024); 525 1.38 mlelstv fs->e2fs.e2fs_bcount = (fs->e2fs_bsize * DEV_BSIZE) / fs->e2fs_bsize; 526 1.6 bouyer fs->e2fs.e2fs_first_dblock = (fs->e2fs.e2fs_log_bsize == 0) ? 1 : 0; 527 1.1 bouyer fs->e2fs.e2fs_bpg = fs->e2fs_bsize * NBBY; 528 1.1 bouyer fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; 529 1.1 bouyer fs->e2fs_qbmask = fs->e2fs_bsize - 1; 530 1.1 bouyer fs->e2fs_bmask = ~fs->e2fs_qbmask; 531 1.1 bouyer fs->e2fs_ncg = 532 1.23 tsutsui howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, 533 1.23 tsutsui fs->e2fs.e2fs_bpg); 534 1.1 bouyer fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; 535 1.1 bouyer fs->e2fs_ngdb = howmany(fs->e2fs_ncg, 536 1.23 tsutsui fs->e2fs_bsize / sizeof(struct ext2_gd)); 537 1.1 bouyer 538 1.23 tsutsui return 1; 539 1.1 bouyer } 540 1.1 bouyer 541 1.12 bouyer daddr_t 542 1.17 xtraeme cgoverhead(int c) 543 1.12 bouyer { 544 1.12 bouyer int overh; 545 1.23 tsutsui overh = 546 1.23 tsutsui 1 /* block bitmap */ + 547 1.23 tsutsui 1 /* inode bitmap */ + 548 1.23 tsutsui sblock.e2fs_itpg; 549 1.12 bouyer if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 550 1.12 bouyer sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { 551 1.12 bouyer if (cg_has_sb(c) == 0) 552 1.12 bouyer return overh; 553 1.12 bouyer } 554 1.23 tsutsui overh += 1 /* superblock */ + sblock.e2fs_ngdb; 555 1.12 bouyer return overh; 556 1.1 bouyer } 557