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