1 /* $NetBSD: mke2fs.c,v 1.7 2007/12/14 13:19:35 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Izumi Tsutsui. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Copyright (c) 1980, 1989, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58 /* 59 * Copyright (c) 1997 Manuel Bouyer. 60 * 61 * Redistribution and use in source and binary forms, with or without 62 * modification, are permitted provided that the following conditions 63 * are met: 64 * 1. Redistributions of source code must retain the above copyright 65 * notice, this list of conditions and the following disclaimer. 66 * 2. Redistributions in binary form must reproduce the above copyright 67 * notice, this list of conditions and the following disclaimer in the 68 * documentation and/or other materials provided with the distribution. 69 * 3. All advertising materials mentioning features or use of this software 70 * must display the following acknowledgement: 71 * This product includes software developed by Manuel Bouyer. 72 * 4. The name of the author may not be used to endorse or promote products 73 * derived from this software without specific prior written permission. 74 * 75 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 76 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 77 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 78 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 79 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 80 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 81 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 82 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 83 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 84 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 85 */ 86 87 /* 88 * mke2fs.c: "re-invent (dumb but non-GPLed) wheel as a fun project" 89 * 90 * In spite of this name, there is no piece of code 91 * derived from GPLed e2fsprogs written for Linux. 92 * I referred them only to see how each structure 93 * member should be initialized. 94 * 95 * Reference: 96 * - All NetBSD sources under src/sys/ufs/ext2fs and src/sbin/fsck_ext2fs 97 * - Ext2fs Home Page 98 * http://e2fsprogs.sourceforge.net/ext2.html 99 * - Design and Implementation of the Second Extended Filesystem 100 * http://e2fsprogs.sourceforge.net/ext2intro.html 101 * - Linux Documentation "The Second Extended Filesystem" 102 * src/linux/Documentation/filesystems/ext2.txt 103 * in the Linux kernel distribution 104 */ 105 106 #include <sys/cdefs.h> 107 #ifndef lint 108 #if 0 109 static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 110 #else 111 __RCSID("$NetBSD: mke2fs.c,v 1.7 2007/12/14 13:19:35 tsutsui Exp $"); 112 #endif 113 #endif /* not lint */ 114 115 #include <sys/param.h> 116 #include <sys/mman.h> 117 #include <sys/time.h> 118 #include <ufs/ext2fs/ext2fs_dinode.h> 119 #include <ufs/ext2fs/ext2fs_dir.h> 120 #include <ufs/ext2fs/ext2fs.h> 121 #include <sys/ioctl.h> 122 123 #include <err.h> 124 #include <errno.h> 125 #include <string.h> 126 #include <unistd.h> 127 #include <stdlib.h> 128 #include <stddef.h> 129 #include <stdio.h> 130 #include <uuid.h> 131 132 #include "extern.h" 133 134 static void initcg(uint); 135 static void zap_old_sblock(daddr_t); 136 static uint cgoverhead(uint); 137 static int fsinit(const struct timeval *); 138 static int makedir(struct ext2fs_direct *, int); 139 static void copy_dir(struct ext2fs_direct *, struct ext2fs_direct *); 140 static void init_resizeino(const struct timeval *); 141 static uint32_t alloc(uint32_t, uint16_t); 142 static void iput(struct ext2fs_dinode *, ino_t); 143 static void rdfs(daddr_t, int, void *); 144 static void wtfs(daddr_t, int, void *); 145 static int ilog2(uint); 146 static int skpc(int, size_t, uint8_t *); 147 148 /* XXX: some of these macro should be into <ufs/ext2fs/ext2fs.h>? */ 149 #define EXT2_DEF_MAX_MNT_COUNT 20 150 #define EXT2_DEF_FSCKINTV (180 * 24 * 60 * 60) /* 180 days */ 151 #define EXT2_RESERVED_INODES (EXT2_FIRSTINO - 1) 152 #define EXT2_UMASK 0755 153 154 #define EXT2_INO_INDEX(ino) ((ino) - 1) /* no inode zero */ 155 156 #define EXT2_LOSTFOUNDSIZE 16384 157 #define EXT2_LOSTFOUNDINO EXT2_FIRSTINO /* XXX: not quite */ 158 #define EXT2_LOSTFOUNDUMASK 0700 159 160 #define EXT2_RESIZEINOUMASK 0600 161 162 #define NBLOCK_SUPERBLOCK 1 163 #define NBLOCK_BLOCK_BITMAP 1 164 #define NBLOCK_INODE_BITMAP 1 165 166 #define cgbase(fs, c) \ 167 ((fs)->e2fs.e2fs_first_dblock + (fs)->e2fs.e2fs_bpg * (c)) 168 169 170 /* 171 * ext2fs super block and group descriptor structures 172 * 173 * We don't have to use or setup whole in-memory m_ext2fs structure, 174 * but prepare it to use several macro defined in kernel headers. 175 */ 176 union { 177 struct m_ext2fs m_ext2fs; 178 char pad[SBSIZE]; 179 } ext2fsun; 180 #define sblock ext2fsun.m_ext2fs 181 #define gd ext2fsun.m_ext2fs.e2fs_gd 182 183 static uint8_t *iobuf; /* for superblock and group descriptors */ 184 static int iobufsize; 185 186 static uint8_t buf[MAXBSIZE]; /* for initcg() and makedir() ops */ 187 188 static int fsi, fso; 189 190 void 191 mke2fs(const char *fsys, int fi, int fo) 192 { 193 struct timeval tv; 194 int64_t minfssize; 195 uint bcount, fbcount, ficount; 196 uint blocks_gd, blocks_per_cg, inodes_per_cg, iblocks_per_cg; 197 uint minblocks_per_cg, blocks_lastcg; 198 uint ncg, cylno, sboff; 199 uuid_t uuid; 200 uint32_t uustat; 201 int i, len, col, delta, fld_width, max_cols; 202 struct winsize winsize; 203 204 gettimeofday(&tv, NULL); 205 fsi = fi; 206 fso = fo; 207 208 /* 209 * collect and verify the block and fragment sizes 210 */ 211 if (!powerof2(bsize)) { 212 errx(EXIT_FAILURE, 213 "block size must be a power of 2, not %u\n", 214 bsize); 215 } 216 if (!powerof2(fsize)) { 217 errx(EXIT_FAILURE, 218 "fragment size must be a power of 2, not %u\n", 219 fsize); 220 } 221 if (fsize < sectorsize) { 222 errx(EXIT_FAILURE, 223 "fragment size %u is too small, minimum is %u\n", 224 fsize, sectorsize); 225 } 226 if (bsize < MINBSIZE) { 227 errx(EXIT_FAILURE, 228 "block size %u is too small, minimum is %u\n", 229 bsize, MINBSIZE); 230 } 231 if (bsize > EXT2_MAXBSIZE) { 232 errx(EXIT_FAILURE, 233 "block size %u is too large, maximum is %u\n", 234 bsize, MAXBSIZE); 235 } 236 if (bsize != fsize) { 237 /* 238 * There is no fragment support on current ext2fs (yet?), 239 * but some kernel code refers fsize or fpg as bsize or bpg 240 * and Linux seems to set the same values to them. 241 */ 242 errx(EXIT_FAILURE, 243 "block size (%u) can't be diffrent from " 244 "fragment size (%u)\n", 245 bsize, fsize); 246 } 247 248 sblock.e2fs.e2fs_log_bsize = ilog2(bsize) - LOG_MINBSIZE; 249 /* Umm, why not e2fs_log_fsize? */ 250 sblock.e2fs.e2fs_fsize = ilog2(fsize) - LOG_MINBSIZE; 251 252 sblock.e2fs_bsize = bsize; 253 sblock.e2fs_bshift = sblock.e2fs.e2fs_log_bsize + LOG_MINBSIZE; 254 sblock.e2fs_qbmask = sblock.e2fs_bsize - 1; 255 sblock.e2fs_bmask = ~sblock.e2fs_qbmask; 256 sblock.e2fs_fsbtodb = ilog2(sblock.e2fs_bsize) - ilog2(sectorsize); 257 sblock.e2fs_ipb = sblock.e2fs_bsize / EXT2_DINODE_SIZE; 258 259 /* 260 * Ext2fs preseves BBSIZE (1024 bytes) space at the top for 261 * bootloader (though it is not enough at all for our bootloader). 262 * If bsize == BBSIZE we have to preserve one block. 263 * If bsize > BBSIZE, the first block already contains BBSIZE space 264 * before superblock because superblock is allocated at SBOFF and 265 * bsize is a power of two (i.e. 2048 bytes or more). 266 */ 267 sblock.e2fs.e2fs_first_dblock = (sblock.e2fs_bsize > BBSIZE) ? 0 : 1; 268 minfssize = fsbtodb(&sblock, 269 sblock.e2fs.e2fs_first_dblock + 270 NBLOCK_SUPERBLOCK + 271 1 /* at least one group descriptor */ + 272 NBLOCK_BLOCK_BITMAP + 273 NBLOCK_INODE_BITMAP + 274 1 /* at least one inode table block */ + 275 1 /* at least one data block for rootdir */ + 276 1 /* at least one data block for data */ 277 ); /* XXX and more? */ 278 279 if (fssize < minfssize) 280 errx(EXIT_FAILURE, "Filesystem size %" PRId64 281 " < minimum size of %" PRId64 "\n", fssize, minfssize); 282 283 bcount = dbtofsb(&sblock, fssize); 284 285 /* 286 * While many people claim that ext2fs is a (bad) clone of ufs/ffs, 287 * it isn't actual ffs so maybe we should call it "block group" 288 * as their native name rather than ffs delived "cylinder group." 289 * But we'll use the latter here since other kernel sources use it. 290 * (I also agree "cylinder" based allocation is obsolete though) 291 */ 292 293 /* maybe "simple is the best" */ 294 blocks_per_cg = sblock.e2fs_bsize * NBBY; 295 296 ncg = howmany(bcount - sblock.e2fs.e2fs_first_dblock, blocks_per_cg); 297 blocks_gd = howmany(sizeof(struct ext2_gd) * ncg, bsize); 298 299 /* check range of inode number */ 300 if (num_inodes < EXT2_FIRSTINO) 301 num_inodes = EXT2_FIRSTINO; /* needs reserved inodes + 1 */ 302 if (num_inodes > UINT16_MAX * ncg) 303 num_inodes = UINT16_MAX * ncg; /* ext2bgd_nifree is uint16_t */ 304 305 inodes_per_cg = num_inodes / ncg; 306 iblocks_per_cg = howmany(EXT2_DINODE_SIZE * inodes_per_cg, bsize); 307 308 /* Check that the last cylinder group has enough space for inodes */ 309 minblocks_per_cg = 310 NBLOCK_BLOCK_BITMAP + 311 NBLOCK_INODE_BITMAP + 312 iblocks_per_cg + 313 1; /* at least one data block */ 314 if (Oflag == 0 || cg_has_sb(ncg - 1) != 0) 315 minblocks_per_cg += NBLOCK_SUPERBLOCK + blocks_gd; 316 317 blocks_lastcg = bcount - sblock.e2fs.e2fs_first_dblock - 318 blocks_per_cg * (ncg - 1); 319 if (blocks_lastcg < minblocks_per_cg) { 320 /* 321 * Since we make all the cylinder groups the same size, the 322 * last will only be small if there are more than one 323 * cylinder groups. If the last one is too small to store 324 * filesystem data, just kill it. 325 * 326 * XXX: Does fsck_ext2fs(8) properly handle this case? 327 */ 328 bcount -= blocks_lastcg; 329 ncg--; 330 blocks_lastcg = blocks_per_cg; 331 blocks_gd = howmany(sizeof(struct ext2_gd) * ncg, bsize); 332 inodes_per_cg = num_inodes / ncg; 333 } 334 /* roundup inodes_per_cg to make it use whole inode table blocks */ 335 inodes_per_cg = roundup(inodes_per_cg, sblock.e2fs_ipb); 336 num_inodes = inodes_per_cg * ncg; 337 iblocks_per_cg = inodes_per_cg / sblock.e2fs_ipb; 338 339 /* XXX: probably we should check these adjusted values again */ 340 341 sblock.e2fs.e2fs_bcount = bcount; 342 sblock.e2fs.e2fs_icount = num_inodes; 343 344 sblock.e2fs_ncg = ncg; 345 sblock.e2fs_ngdb = blocks_gd; 346 sblock.e2fs_itpg = iblocks_per_cg; 347 348 sblock.e2fs.e2fs_rbcount = sblock.e2fs.e2fs_bcount * minfree / 100; 349 /* e2fs_fbcount will be accounted later */ 350 /* e2fs_ficount will be accounted later */ 351 352 sblock.e2fs.e2fs_bpg = blocks_per_cg; 353 sblock.e2fs.e2fs_fpg = blocks_per_cg; 354 355 sblock.e2fs.e2fs_ipg = inodes_per_cg; 356 357 sblock.e2fs.e2fs_mtime = 0; 358 sblock.e2fs.e2fs_wtime = tv.tv_sec; 359 sblock.e2fs.e2fs_mnt_count = 0; 360 /* XXX: should add some entropy to avoid checking all fs at once? */ 361 sblock.e2fs.e2fs_max_mnt_count = EXT2_DEF_MAX_MNT_COUNT; 362 363 sblock.e2fs.e2fs_magic = E2FS_MAGIC; 364 sblock.e2fs.e2fs_state = E2FS_ISCLEAN; 365 sblock.e2fs.e2fs_beh = E2FS_BEH_DEFAULT; 366 sblock.e2fs.e2fs_minrev = 0; 367 sblock.e2fs.e2fs_lastfsck = tv.tv_sec; 368 sblock.e2fs.e2fs_fsckintv = EXT2_DEF_FSCKINTV; 369 370 /* 371 * Maybe we can use E2FS_OS_FREEBSD here and it would be more proper, 372 * but the purpose of this newfs_ext2fs(8) command is to provide 373 * a filesystem which can be recognized by firmwares on some 374 * Linux based appliances that can load bootstrap files only from 375 * (their native) ext2fs, and anyway we will (and should) try to 376 * act like them as much as possible. 377 * 378 * Anyway, I hope that all newer such boxes will keep their support 379 * for the "GOOD_OLD_REV" ext2fs. 380 */ 381 sblock.e2fs.e2fs_creator = E2FS_OS_LINUX; 382 383 if (Oflag == 0) { 384 sblock.e2fs.e2fs_rev = E2FS_REV0; 385 sblock.e2fs.e2fs_features_compat = 0; 386 sblock.e2fs.e2fs_features_incompat = 0; 387 sblock.e2fs.e2fs_features_rocompat = 0; 388 } else { 389 sblock.e2fs.e2fs_rev = E2FS_REV1; 390 /* 391 * e2fsprogs say "REV1" is "dynamic" so 392 * it isn't quite a version and maybe it means 393 * "extended from REV0 so check compat features." 394 * 395 * XXX: We don't have any native tool to activate 396 * the EXT2F_COMPAT_RESIZE feature and 397 * fsck_ext2fs(8) might not fix structures for it. 398 */ 399 sblock.e2fs.e2fs_features_compat = EXT2F_COMPAT_RESIZE; 400 sblock.e2fs.e2fs_features_incompat = EXT2F_INCOMPAT_FTYPE; 401 sblock.e2fs.e2fs_features_rocompat = 402 EXT2F_ROCOMPAT_SPARSESUPER | EXT2F_ROCOMPAT_LARGEFILE; 403 } 404 405 sblock.e2fs.e2fs_ruid = geteuid(); 406 sblock.e2fs.e2fs_rgid = getegid(); 407 408 sblock.e2fs.e2fs_first_ino = EXT2_FIRSTINO; 409 sblock.e2fs.e2fs_inode_size = EXT2_DINODE_SIZE; 410 411 /* e2fs_block_group_nr is set on writing superblock to each group */ 412 413 uuid_create(&uuid, &uustat); 414 if (uustat != uuid_s_ok) 415 errx(EXIT_FAILURE, "Failed to generate uuid\n"); 416 uuid_enc_le(sblock.e2fs.e2fs_uuid, &uuid); 417 if (volname != NULL) { 418 if (strlen(volname) > sizeof(sblock.e2fs.e2fs_vname)) 419 errx(EXIT_FAILURE, "Volume name is too long"); 420 strlcpy(sblock.e2fs.e2fs_vname, volname, 421 sizeof(sblock.e2fs.e2fs_vname)); 422 } 423 424 sblock.e2fs.e2fs_fsmnt[0] = '\0'; 425 sblock.e2fs_fsmnt[0] = '\0'; 426 427 sblock.e2fs.e2fs_algo = 0; /* XXX unsupported? */ 428 sblock.e2fs.e2fs_prealloc = 0; /* XXX unsupported? */ 429 sblock.e2fs.e2fs_dir_prealloc = 0; /* XXX unsupported? */ 430 431 /* calculate blocks for reserved group descriptors for resize */ 432 sblock.e2fs.e2fs_reserved_ngdb = 0; 433 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 434 (sblock.e2fs.e2fs_features_compat & EXT2F_COMPAT_RESIZE) != 0) { 435 uint64_t target_blocks; 436 uint target_ncg, target_ngdb, reserved_ngdb; 437 438 /* reserve descriptors for size as 1024 times as current */ 439 target_blocks = 440 (sblock.e2fs.e2fs_bcount - sblock.e2fs.e2fs_first_dblock) 441 * 1024ULL; 442 /* number of blocks must be in uint32_t */ 443 if (target_blocks > UINT32_MAX) 444 target_blocks = UINT32_MAX; 445 target_ncg = howmany(target_blocks, sblock.e2fs.e2fs_bpg); 446 target_ngdb = howmany(sizeof(struct ext2_gd) * target_ncg, 447 sblock.e2fs_bsize); 448 /* 449 * Reserved group descriptor blocks are preserved as 450 * the second level double indirect reference blocks in 451 * the EXT2_RESIZEINO inode, so the maximum number of 452 * the blocks is NINDIR(fs). 453 * (see also descriptions in init_resizeino() function) 454 * 455 * We check a number including current e2fs_ngdb here 456 * because they will be moved into reserved gdb on 457 * possible future size shrink, though e2fsprogs don't 458 * seem to care about it. 459 */ 460 if (target_ngdb > NINDIR(&sblock)) 461 target_ngdb = NINDIR(&sblock); 462 463 reserved_ngdb = target_ngdb - sblock.e2fs_ngdb; 464 465 /* make sure reserved_ngdb fits in the last cg */ 466 if (reserved_ngdb >= blocks_lastcg - cgoverhead(ncg - 1)) 467 reserved_ngdb = blocks_lastcg - cgoverhead(ncg - 1); 468 if (reserved_ngdb == 0) { 469 /* if no space for reserved gdb, disable the feature */ 470 sblock.e2fs.e2fs_features_compat &= 471 ~EXT2F_COMPAT_RESIZE; 472 } 473 sblock.e2fs.e2fs_reserved_ngdb = reserved_ngdb; 474 } 475 476 /* 477 * Initialize group descriptors 478 */ 479 gd = malloc(sblock.e2fs_ngdb * bsize); 480 if (gd == NULL) 481 errx(EXIT_FAILURE, "Can't allocate descriptors buffer"); 482 memset(gd, 0, sblock.e2fs_ngdb * bsize); 483 484 fbcount = 0; 485 ficount = 0; 486 for (cylno = 0; cylno < ncg; cylno++) { 487 uint boffset; 488 489 boffset = cgbase(&sblock, cylno); 490 if (sblock.e2fs.e2fs_rev == E2FS_REV0 || 491 (sblock.e2fs.e2fs_features_rocompat & 492 EXT2F_ROCOMPAT_SPARSESUPER) == 0 || 493 cg_has_sb(cylno)) { 494 boffset += NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb; 495 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 496 (sblock.e2fs.e2fs_features_compat & 497 EXT2F_COMPAT_RESIZE) != 0) 498 boffset += sblock.e2fs.e2fs_reserved_ngdb; 499 } 500 gd[cylno].ext2bgd_b_bitmap = boffset; 501 boffset += NBLOCK_BLOCK_BITMAP; 502 gd[cylno].ext2bgd_i_bitmap = boffset; 503 boffset += NBLOCK_INODE_BITMAP; 504 gd[cylno].ext2bgd_i_tables = boffset; 505 if (cylno == (ncg - 1)) 506 gd[cylno].ext2bgd_nbfree = 507 blocks_lastcg - cgoverhead(cylno); 508 else 509 gd[cylno].ext2bgd_nbfree = 510 sblock.e2fs.e2fs_bpg - cgoverhead(cylno); 511 fbcount += gd[cylno].ext2bgd_nbfree; 512 gd[cylno].ext2bgd_nifree = sblock.e2fs.e2fs_ipg; 513 if (cylno == 0) { 514 /* take reserved inodes off nifree */ 515 gd[cylno].ext2bgd_nifree -= EXT2_RESERVED_INODES; 516 } 517 ficount += gd[cylno].ext2bgd_nifree; 518 gd[cylno].ext2bgd_ndirs = 0; 519 } 520 sblock.e2fs.e2fs_fbcount = fbcount; 521 sblock.e2fs.e2fs_ficount = ficount; 522 523 /* 524 * Dump out summary information about file system. 525 */ 526 if (verbosity > 0) { 527 printf("%s: %u.%1uMB (%" PRId64 " sectors) " 528 "block size %u, fragment size %u\n", 529 fsys, 530 (uint)(((uint64_t)bcount * bsize) / (1024 * 1024)), 531 (uint)((uint64_t)bcount * bsize - 532 rounddown((uint64_t)bcount * bsize, 1024 * 1024)) 533 / 1024 / 100, 534 fssize, bsize, fsize); 535 printf("\tusing %u block groups of %u.0MB, %u blks, " 536 "%u inodes.\n", 537 ncg, bsize * sblock.e2fs.e2fs_bpg / (1024 * 1024), 538 sblock.e2fs.e2fs_bpg, sblock.e2fs.e2fs_ipg); 539 } 540 541 /* 542 * allocate space for superblock and group descriptors 543 */ 544 iobufsize = (NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb) * sblock.e2fs_bsize; 545 iobuf = mmap(0, iobufsize, PROT_READ|PROT_WRITE, 546 MAP_ANON|MAP_PRIVATE, -1, 0); 547 if (iobuf == NULL) 548 errx(EXIT_FAILURE, "Cannot allocate I/O buffer\n"); 549 memset(iobuf, 0, iobufsize); 550 551 /* 552 * We now start writing to the filesystem 553 */ 554 555 if (!Nflag) { 556 static const uint pbsize[] = { 1024, 2048, 4096, 0 }; 557 uint pblock, epblock; 558 /* 559 * Validate the given file system size. 560 * Verify that its last block can actually be accessed. 561 * Convert to file system fragment sized units. 562 */ 563 if (fssize <= 0) 564 errx(EXIT_FAILURE, "Preposterous size %" PRId64 "\n", 565 fssize); 566 wtfs(fssize - 1, sectorsize, iobuf); 567 568 /* 569 * Ensure there is nothing that looks like a filesystem 570 * superbock anywhere other than where ours will be. 571 * If fsck_ext2fs finds the wrong one all hell breaks loose! 572 * 573 * XXX: needs to check how fsck_ext2fs programs even 574 * on other OSes determine alternate superblocks 575 */ 576 for (i = 0; pbsize[i] != 0; i++) { 577 epblock = (uint64_t)bcount * bsize / pbsize[i]; 578 for (pblock = ((pbsize[i] == SBSIZE) ? 1 : 0); 579 pblock < epblock; 580 pblock += pbsize[i] * NBBY /* bpg */) 581 zap_old_sblock((daddr_t)pblock * 582 pbsize[i] / sectorsize); 583 } 584 } 585 586 if (verbosity >= 3) 587 printf("super-block backups (for fsck_ext2fs -b #) at:\n"); 588 /* If we are printing more than one line of numbers, line up columns */ 589 fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, 590 (uint64_t)cgbase(&sblock, ncg - 1)); 591 /* Get terminal width */ 592 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0) 593 max_cols = winsize.ws_col; 594 else 595 max_cols = 80; 596 if (Nflag && verbosity == 3) 597 /* Leave space to add " ..." after one row of numbers */ 598 max_cols -= 4; 599 #define BASE 0x10000 /* For some fixed-point maths */ 600 col = 0; 601 delta = verbosity > 2 ? 0 : max_cols * BASE / ncg; 602 for (cylno = 0; cylno < ncg; cylno++) { 603 fflush(stdout); 604 initcg(cylno); 605 if (verbosity < 2) 606 continue; 607 /* the first one is a master, not backup */ 608 if (cylno == 0) 609 continue; 610 /* skip if this cylinder doesn't have a backup */ 611 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 612 (sblock.e2fs.e2fs_features_rocompat & 613 EXT2F_ROCOMPAT_SPARSESUPER) != 0 && 614 cg_has_sb(cylno) == 0) 615 continue; 616 617 if (delta > 0) { 618 if (Nflag) 619 /* No point doing dots for -N */ 620 break; 621 /* Print dots scaled to end near RH margin */ 622 for (col += delta; col > BASE; col -= BASE) 623 printf("."); 624 continue; 625 } 626 /* Print superblock numbers */ 627 len = printf(" %*" PRIu64 "," + !col, fld_width, 628 (uint64_t)cgbase(&sblock, cylno)); 629 col += len; 630 if (col + len < max_cols) 631 /* Next number fits */ 632 continue; 633 /* Next number won't fit, need a newline */ 634 if (verbosity <= 3) { 635 /* Print dots for subsequent cylinder groups */ 636 delta = sblock.e2fs_ncg - cylno - 1; 637 if (delta != 0) { 638 if (Nflag) { 639 printf(" ..."); 640 break; 641 } 642 delta = max_cols * BASE / delta; 643 } 644 } 645 col = 0; 646 printf("\n"); 647 } 648 #undef BASE 649 if (col > 0) 650 printf("\n"); 651 if (Nflag) 652 return; 653 654 /* 655 * Now construct the initial file system, 656 */ 657 if (fsinit(&tv) == 0) 658 errx(EXIT_FAILURE, "Error making filesystem"); 659 /* 660 * Write out the superblock and group descriptors 661 */ 662 sblock.e2fs.e2fs_block_group_nr = 0; 663 sboff = 0; 664 if (cgbase(&sblock, 0) == 0) { 665 /* 666 * If the first block contains the boot block sectors, 667 * (i.e. in case of sblock.e2fs.e2fs_bsize > BBSIZE) 668 * we have to preserve data in it. 669 */ 670 sboff = SBOFF; 671 } 672 e2fs_sbsave(&sblock.e2fs, (struct ext2fs *)(iobuf + sboff)); 673 e2fs_cgsave(gd, (struct ext2_gd *)(iobuf + sblock.e2fs_bsize), 674 sizeof(struct ext2_gd) * sblock.e2fs_ncg); 675 wtfs(fsbtodb(&sblock, cgbase(&sblock, 0)) + sboff / sectorsize, 676 iobufsize - sboff, iobuf + sboff); 677 678 munmap(iobuf, iobufsize); 679 } 680 681 /* 682 * Initialize a cylinder (block) group. 683 */ 684 void 685 initcg(uint cylno) 686 { 687 uint nblcg, i, j, sboff; 688 struct ext2fs_dinode *dp; 689 690 /* 691 * Make a copy of the superblock and group descriptors. 692 */ 693 if (sblock.e2fs.e2fs_rev == E2FS_REV0 || 694 (sblock.e2fs.e2fs_features_rocompat & 695 EXT2F_ROCOMPAT_SPARSESUPER) == 0 || 696 cg_has_sb(cylno)) { 697 sblock.e2fs.e2fs_block_group_nr = cylno; 698 sboff = 0; 699 if (cgbase(&sblock, cylno) == 0) { 700 /* preserve data in bootblock in cg0 */ 701 sboff = SBOFF; 702 } 703 e2fs_sbsave(&sblock.e2fs, (struct ext2fs *)(iobuf + sboff)); 704 e2fs_cgsave(gd, (struct ext2_gd *)(iobuf + 705 sblock.e2fs_bsize * NBLOCK_SUPERBLOCK), 706 sizeof(struct ext2_gd) * sblock.e2fs_ncg); 707 /* write superblock and group descriptor backups */ 708 wtfs(fsbtodb(&sblock, cgbase(&sblock, cylno)) + 709 sboff / sectorsize, iobufsize - sboff, iobuf + sboff); 710 } 711 712 /* 713 * Initialize block bitmap. 714 */ 715 memset(buf, 0, sblock.e2fs_bsize); 716 if (cylno == (sblock.e2fs_ncg - 1)) { 717 /* The last group could have less blocks than e2fs_bpg. */ 718 nblcg = sblock.e2fs.e2fs_bcount - 719 cgbase(&sblock, sblock.e2fs_ncg - 1); 720 for (i = nblcg; i < roundup(nblcg, NBBY); i++) 721 setbit(buf, i); 722 memset(&buf[i / NBBY], ~0U, sblock.e2fs.e2fs_bpg - i); 723 } 724 /* set overhead (superblock, group descriptor etc.) blocks used */ 725 for (i = 0; i < cgoverhead(cylno) / NBBY; i++) 726 buf[i] = ~0; 727 i = i * NBBY; 728 for (; i < cgoverhead(cylno); i++) 729 setbit(buf, i); 730 wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_b_bitmap), sblock.e2fs_bsize, 731 buf); 732 733 /* 734 * Initialize inode bitmap. 735 * 736 * Assume e2fs_ipg is a multiple of NBBY since 737 * it's a multible of e2fs_ipb (as we did above). 738 * Note even (possibly smaller) the last group has the same e2fs_ipg. 739 */ 740 i = sblock.e2fs.e2fs_ipg / NBBY; 741 memset(buf, 0, i); 742 memset(buf + i, ~0U, sblock.e2fs_bsize - i); 743 if (cylno == 0) { 744 /* mark reserved inodes */ 745 for (i = 1; i < EXT2_FIRSTINO; i++) 746 setbit(buf, EXT2_INO_INDEX(i)); 747 } 748 wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_i_bitmap), sblock.e2fs_bsize, 749 buf); 750 751 /* 752 * Initialize inode tables. 753 * 754 * Just initialize generation numbers for NFS security. 755 * XXX: sys/ufs/ext2fs/ext2fs_alloc.c:ext2fs_valloc() seems 756 * to override these generated numbers. 757 */ 758 memset(buf, 0, sblock.e2fs_bsize); 759 dp = (struct ext2fs_dinode *)buf; 760 for (i = 0; i < sblock.e2fs_itpg; i++) { 761 for (j = 0; j < sblock.e2fs_ipb; j++) { 762 /* h2fs32() just for consistency */ 763 dp[j].e2di_gen = h2fs32(arc4random()); 764 } 765 wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_i_tables + i), 766 sblock.e2fs_bsize, buf); 767 } 768 } 769 770 /* 771 * Zap possible lingering old superblock data 772 */ 773 static void 774 zap_old_sblock(daddr_t sec) 775 { 776 static daddr_t cg0_data; 777 uint32_t oldfs[SBSIZE / sizeof(uint32_t)]; 778 static const struct fsm { 779 uint32_t offset; 780 uint32_t magic; 781 uint32_t mask; 782 } fs_magics[] = { 783 {offsetof(struct ext2fs, e2fs_magic) / 4, E2FS_MAGIC, 0xffff}, 784 {offsetof(struct ext2fs, e2fs_magic) / 4, 785 E2FS_MAGIC << 16, 0xffff0000}, 786 {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ 787 {0x55c / 4, 0x00011954, ~0U}, /* FS_UFS1_MAGIC */ 788 {0x55c / 4, 0x19540119, ~0U}, /* FS_UFS2_MAGIC */ 789 {0, 0x70162, ~0U}, /* LFS_MAGIC */ 790 {.offset = ~0U}, 791 }; 792 const struct fsm *fsm; 793 794 if (Nflag) 795 return; 796 797 /* don't override data before superblock */ 798 if (sec < SBOFF / sectorsize) 799 return; 800 801 if (cg0_data == 0) { 802 cg0_data = 803 ((daddr_t)sblock.e2fs.e2fs_first_dblock + cgoverhead(0)) * 804 sblock.e2fs_bsize / sectorsize; 805 } 806 807 /* Ignore anything that is beyond our filesystem */ 808 if (sec >= fssize) 809 return; 810 /* Zero anything inside our filesystem... */ 811 if (sec >= sblock.e2fs.e2fs_first_dblock * bsize / sectorsize) { 812 /* ...unless we will write that area anyway */ 813 if (sec >= cg0_data) 814 /* assume iobuf is zero'ed here */ 815 wtfs(sec, roundup(SBSIZE, sectorsize), iobuf); 816 return; 817 } 818 819 /* 820 * The sector might contain boot code, so we must validate it 821 * 822 * XXX: ext2fs won't preserve data after SBOFF, 823 * but first_dblock could have a differnt value. 824 */ 825 rdfs(sec, sizeof(oldfs), &oldfs); 826 for (fsm = fs_magics;; fsm++) { 827 uint32_t v; 828 if (fsm->mask == 0) 829 return; 830 v = oldfs[fsm->offset]; 831 if ((v & fsm->mask) == fsm->magic || 832 (bswap32(v) & fsm->mask) == fsm->magic) 833 break; 834 } 835 836 /* Just zap the magic number */ 837 oldfs[fsm->offset] = 0; 838 wtfs(sec, sizeof(oldfs), &oldfs); 839 } 840 841 /* 842 * uint cgoverhead(uint c) 843 * 844 * Return a number of reserved blocks on the specified group. 845 * XXX: should be shared with src/sbin/fsck_ext2fs/setup.c 846 */ 847 uint 848 cgoverhead(uint c) 849 { 850 uint overh; 851 852 overh = NBLOCK_BLOCK_BITMAP + NBLOCK_INODE_BITMAP + sblock.e2fs_itpg; 853 854 if (sblock.e2fs.e2fs_rev == E2FS_REV0 || 855 (sblock.e2fs.e2fs_features_rocompat & 856 EXT2F_ROCOMPAT_SPARSESUPER) == 0 || 857 cg_has_sb(c) != 0) { 858 overh += NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb; 859 860 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 861 (sblock.e2fs.e2fs_features_compat & 862 EXT2F_COMPAT_RESIZE) != 0) 863 overh += sblock.e2fs.e2fs_reserved_ngdb; 864 } 865 866 return overh; 867 } 868 869 /* 870 * Initialize the file system 871 */ 872 873 #define LOSTDIR /* e2fsck complains if there is no lost+found */ 874 875 #define PREDEFDIR 2 876 877 #ifdef LOSTDIR 878 #define PREDEFROOTDIR (PREDEFDIR + 1) 879 #else 880 #define PREDEFROOTDIR PREDEFDIR 881 #endif 882 883 struct ext2fs_direct root_dir[] = { 884 { EXT2_ROOTINO, 0, 1, 0, "." }, 885 { EXT2_ROOTINO, 0, 2, 0, ".." }, 886 #ifdef LOSTDIR 887 { EXT2_LOSTFOUNDINO, 0, 10, 0, "lost+found" }, 888 #endif 889 }; 890 891 #ifdef LOSTDIR 892 struct ext2fs_direct lost_found_dir[] = { 893 { EXT2_LOSTFOUNDINO, 0, 1, 0, "." }, 894 { EXT2_ROOTINO, 0, 2, 0, ".." }, 895 }; 896 struct ext2fs_direct pad_dir = { 0, sizeof(struct ext2fs_direct), 0, 0, "" }; 897 #endif 898 899 int 900 fsinit(const struct timeval *tv) 901 { 902 struct ext2fs_dinode node; 903 #ifdef LOSTDIR 904 uint i, nblks_lostfound, blk; 905 #endif 906 907 /* 908 * Initialize the inode for the resizefs feature 909 */ 910 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 911 (sblock.e2fs.e2fs_features_compat & EXT2F_COMPAT_RESIZE) != 0) 912 init_resizeino(tv); 913 914 /* 915 * Initialize the node 916 */ 917 918 #ifdef LOSTDIR 919 /* 920 * Create the lost+found directory 921 */ 922 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 923 sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) { 924 lost_found_dir[0].e2d_type = EXT2_FT_DIR; 925 lost_found_dir[1].e2d_type = EXT2_FT_DIR; 926 } 927 (void)makedir(lost_found_dir, __arraycount(lost_found_dir)); 928 929 /* prepare a bit large directory for preserved files */ 930 nblks_lostfound = EXT2_LOSTFOUNDSIZE / sblock.e2fs_bsize; 931 /* ...but only with direct blocks */ 932 if (nblks_lostfound > NDADDR) 933 nblks_lostfound = NDADDR; 934 935 memset(&node, 0, sizeof(node)); 936 node.e2di_mode = EXT2_IFDIR | EXT2_LOSTFOUNDUMASK; 937 node.e2di_uid = geteuid(); 938 node.e2di_size = sblock.e2fs_bsize * nblks_lostfound; 939 node.e2di_atime = tv->tv_sec; 940 node.e2di_ctime = tv->tv_sec; 941 node.e2di_mtime = tv->tv_sec; 942 node.e2di_gid = getegid(); 943 node.e2di_nlink = PREDEFDIR; 944 /* e2di_nblock is a number of disk block, not ext2fs block */ 945 node.e2di_nblock = fsbtodb(&sblock, nblks_lostfound); 946 node.e2di_blocks[0] = alloc(sblock.e2fs_bsize, node.e2di_mode); 947 if (node.e2di_blocks[0] == 0) { 948 printf("%s: can't allocate block for lost+found\n", __func__); 949 return 0; 950 } 951 for (i = 1; i < nblks_lostfound; i++) { 952 blk = alloc(sblock.e2fs_bsize, 0); 953 if (blk == 0) { 954 printf("%s: can't allocate blocks for lost+found\n", 955 __func__); 956 return 0; 957 } 958 node.e2di_blocks[i] = blk; 959 } 960 wtfs(fsbtodb(&sblock, node.e2di_blocks[0]), sblock.e2fs_bsize, buf); 961 pad_dir.e2d_reclen = sblock.e2fs_bsize; 962 for (i = 1; i < nblks_lostfound; i++) { 963 memset(buf, 0, sblock.e2fs_bsize); 964 copy_dir(&pad_dir, (struct ext2fs_direct *)buf); 965 wtfs(fsbtodb(&sblock, node.e2di_blocks[i]), sblock.e2fs_bsize, 966 buf); 967 } 968 iput(&node, EXT2_LOSTFOUNDINO); 969 #endif 970 /* 971 * create the root directory 972 */ 973 memset(&node, 0, sizeof(node)); 974 if (sblock.e2fs.e2fs_rev > E2FS_REV0 && 975 sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) { 976 root_dir[0].e2d_type = EXT2_FT_DIR; 977 root_dir[1].e2d_type = EXT2_FT_DIR; 978 #ifdef LOSTDIR 979 root_dir[2].e2d_type = EXT2_FT_DIR; 980 #endif 981 } 982 node.e2di_mode = EXT2_IFDIR | EXT2_UMASK; 983 node.e2di_uid = geteuid(); 984 node.e2di_size = makedir(root_dir, __arraycount(root_dir)); 985 node.e2di_atime = tv->tv_sec; 986 node.e2di_ctime = tv->tv_sec; 987 node.e2di_mtime = tv->tv_sec; 988 node.e2di_gid = getegid(); 989 node.e2di_nlink = PREDEFROOTDIR; 990 /* e2di_nblock is a number of disk block, not ext2fs block */ 991 node.e2di_nblock = fsbtodb(&sblock, 1); 992 node.e2di_blocks[0] = alloc(node.e2di_size, node.e2di_mode); 993 if (node.e2di_blocks[0] == 0) { 994 printf("%s: can't allocate block for root dir\n", __func__); 995 return 0; 996 } 997 wtfs(fsbtodb(&sblock, node.e2di_blocks[0]), sblock.e2fs_bsize, buf); 998 iput(&node, EXT2_ROOTINO); 999 return 1; 1000 } 1001 1002 /* 1003 * Construct a set of directory entries in "buf". 1004 * return size of directory. 1005 */ 1006 int 1007 makedir(struct ext2fs_direct *protodir, int entries) 1008 { 1009 uint8_t *cp; 1010 uint i, spcleft; 1011 uint dirblksiz; 1012 1013 dirblksiz = sblock.e2fs_bsize; 1014 memset(buf, 0, dirblksiz); 1015 spcleft = dirblksiz; 1016 for (cp = buf, i = 0; i < entries - 1; i++) { 1017 protodir[i].e2d_reclen = EXT2FS_DIRSIZ(protodir[i].e2d_namlen); 1018 copy_dir(&protodir[i], (struct ext2fs_direct *)cp); 1019 cp += protodir[i].e2d_reclen; 1020 spcleft -= protodir[i].e2d_reclen; 1021 } 1022 protodir[i].e2d_reclen = spcleft; 1023 copy_dir(&protodir[i], (struct ext2fs_direct *)cp); 1024 return dirblksiz; 1025 } 1026 1027 /* 1028 * Copy a direntry to a buffer, in fs byte order 1029 */ 1030 static void 1031 copy_dir(struct ext2fs_direct *dir, struct ext2fs_direct *dbuf) 1032 { 1033 1034 memcpy(dbuf, dir, EXT2FS_DIRSIZ(dir->e2d_namlen)); 1035 dbuf->e2d_ino = h2fs32(dir->e2d_ino); 1036 dbuf->e2d_reclen = h2fs16(dir->e2d_reclen); 1037 } 1038 1039 /* 1040 * void init_resizeino(const struct timeval *tv); 1041 * 1042 * Initialize the EXT2_RESEIZE_INO inode to prereserve 1043 * reserved group descriptor blocks for future growth of this ext2fs. 1044 */ 1045 void 1046 init_resizeino(const struct timeval *tv) 1047 { 1048 struct ext2fs_dinode node; 1049 uint64_t isize; 1050 uint32_t *dindir_block, *reserved_gdb; 1051 uint nblock, i, cylno, n; 1052 1053 memset(&node, 0, sizeof(node)); 1054 1055 /* 1056 * Note this function only prepares required structures for 1057 * future resize. It's a quite different work to implement 1058 * a utility like resize_ext2fs(8) which handles actual 1059 * resize ops even on offline. 1060 * 1061 * Anyway, I'm not sure if there is any documentation about 1062 * this resize ext2fs feature and related data structures, 1063 * and I've written this function based on things what I see 1064 * on some existing implementation and real file system data 1065 * created by existing tools. To be honest, they are not 1066 * so easy to read, so I will try to implement it here without 1067 * any dumb optimization for people who would eventually 1068 * work on "yet another wheel" like resize_ext2fs(8). 1069 */ 1070 1071 /* 1072 * I'm not sure what type is appropriate for this inode. 1073 * The release notes of e2fsprogs says they changed e2fsck to allow 1074 * IFREG for RESIZEINO since a certain resize tool used it. Hmm. 1075 */ 1076 node.e2di_mode = EXT2_IFREG | EXT2_RESIZEINOUMASK; 1077 node.e2di_uid = geteuid(); 1078 node.e2di_atime = tv->tv_sec; 1079 node.e2di_ctime = tv->tv_sec; 1080 node.e2di_mtime = tv->tv_sec; 1081 node.e2di_gid = getegid(); 1082 node.e2di_nlink = 1; 1083 1084 /* 1085 * To preserve the reserved group descriptor blocks, 1086 * EXT2_RESIZEINO uses only double indirect reference 1087 * blocks in its inode entries. 1088 * 1089 * All entries for direct, single indirect and triple 1090 * indirect references are left zero'ed. Maybe it's safe 1091 * because no write operation will happen with this inode. 1092 * 1093 * We have to allocate a block for the first level double 1094 * indirect reference block. Indexes of inode entries in 1095 * this first level dindirect block are corresponding to 1096 * indexes of group descriptors including both used (e2fs_ngdb) 1097 * and reserved (e2fs_reserved_ngdb) group descriptor blocks. 1098 * 1099 * Inode entries of indexes for used (e2fs_ngdb) descriptors are 1100 * left zero'ed. Entries for reserved (e2fs_reserved_ngdb) ones 1101 * have block numbers of actual reserved group descriptors 1102 * allocated at block group zero. This means e2fs_reserved_ngdb 1103 * blocks are reserved as the second level dindirect reference 1104 * blocks, and they acutually contain block numbers of indirect 1105 * references. It may be safe since they don't have to keep any 1106 * data yet. 1107 * 1108 * Each these second dindirect blocks (i.e. reserved group 1109 * descriptor blocks in the first block group) should have 1110 * block numbers of its backups in all other block groups. 1111 * I.e. reserved_ngdb[0] block in block group 0 contains block 1112 * numbers of resreved_ngdb[0] from group 1 through (e2fs_ncg - 1). 1113 * The number of backups can be determined by the 1114 * EXT2_ROCOMPAT_SPARSESUPER feature and cg_has_sb() macro 1115 * as done in the above initcg() function. 1116 */ 1117 1118 /* set e2di_size which occupies whole blocks through DINDIR blocks */ 1119 isize = (uint64_t)sblock.e2fs_bsize * NDADDR + 1120 (uint64_t)sblock.e2fs_bsize * NINDIR(&sblock) + 1121 (uint64_t)sblock.e2fs_bsize * NINDIR(&sblock) * NINDIR(&sblock); 1122 if (isize > UINT32_MAX && 1123 (sblock.e2fs.e2fs_features_rocompat & 1124 EXT2F_ROCOMPAT_LARGEFILE) == 0) { 1125 /* XXX should enable it here and update all backups? */ 1126 errx(EXIT_FAILURE, "%s: large_file rocompat feature is " 1127 "required to enable resize feature for this filesystem\n", 1128 __func__); 1129 } 1130 /* upper 32bit is stored into e2di_dacl on REV1 feature */ 1131 node.e2di_size = isize & UINT32_MAX; 1132 node.e2di_dacl = isize >> 32; 1133 1134 #define SINGLE 0 /* index of single indirect block */ 1135 #define DOUBLE 1 /* index of double indirect block */ 1136 #define TRIPLE 2 /* index of triple indirect block */ 1137 1138 /* zero out entries for direct references */ 1139 for (i = 0; i < NDADDR; i++) 1140 node.e2di_blocks[i] = 0; 1141 /* also zero out entries for single and triple indirect references */ 1142 node.e2di_blocks[NDADDR + SINGLE] = 0; 1143 node.e2di_blocks[NDADDR + TRIPLE] = 0; 1144 1145 /* allocate a block for the first level double indirect reference */ 1146 node.e2di_blocks[NDADDR + DOUBLE] = 1147 alloc(sblock.e2fs_bsize, node.e2di_mode); 1148 if (node.e2di_blocks[NDADDR + DOUBLE] == 0) 1149 errx(EXIT_FAILURE, "%s: Can't allocate a dindirect block", 1150 __func__); 1151 1152 /* account this first block */ 1153 nblock = fsbtodb(&sblock, 1); 1154 1155 /* allocate buffer to set data in the dindirect block */ 1156 dindir_block = malloc(sblock.e2fs_bsize); 1157 if (dindir_block == NULL) 1158 errx(EXIT_FAILURE, 1159 "%s: Can't allocate buffer for a dindirect block", 1160 __func__); 1161 1162 /* allocate buffer to set data in the group descriptor blocks */ 1163 reserved_gdb = malloc(sblock.e2fs_bsize); 1164 if (reserved_gdb == NULL) 1165 errx(EXIT_FAILURE, 1166 "%s: Can't allocate buffer for group descriptor blocks", 1167 __func__); 1168 1169 /* 1170 * Setup block entries in the first level dindirect blocks 1171 */ 1172 for (i = 0; i < sblock.e2fs_ngdb; i++) { 1173 /* no need to handle used group descriptor blocks */ 1174 dindir_block[i] = 0; 1175 } 1176 for (; i < sblock.e2fs_ngdb + sblock.e2fs.e2fs_reserved_ngdb; i++) { 1177 /* 1178 * point reserved group descriptor block in the first 1179 * (i.e. master) block group 1180 * 1181 * XXX: e2fsprogs seem to use "(i % NINDIR(&sblock))" here 1182 * to store maximum NINDIR(&sblock) reserved gdbs. 1183 * I'm not sure what will be done on future filesystem 1184 * shrink in that case on their way. 1185 */ 1186 if (i >= NINDIR(&sblock)) 1187 errx(EXIT_FAILURE, "%s: too many reserved " 1188 "group descriptors (%u) for resize inode", 1189 __func__, sblock.e2fs.e2fs_reserved_ngdb); 1190 dindir_block[i] = 1191 h2fs32(cgbase(&sblock, 0) + NBLOCK_SUPERBLOCK + i); 1192 1193 /* 1194 * Setup block entries in the second dindirect blocks 1195 * (which are primary reserved group descriptor blocks) 1196 * to point their backups. 1197 */ 1198 for (n = 0, cylno = 1; cylno < sblock.e2fs_ncg; cylno++) { 1199 /* skip block groups without backup */ 1200 if ((sblock.e2fs.e2fs_features_rocompat & 1201 EXT2F_ROCOMPAT_SPARSESUPER) != 0 && 1202 cg_has_sb(cylno) == 0) 1203 continue; 1204 1205 if (n >= NINDIR(&sblock)) 1206 errx(EXIT_FAILURE, "%s: too many block groups " 1207 "for the resize feature", __func__); 1208 /* 1209 * These blocks are already reserved in 1210 * initcg() so no need to use alloc() here. 1211 */ 1212 reserved_gdb[n++] = h2fs32(cgbase(&sblock, cylno) + 1213 NBLOCK_SUPERBLOCK + i); 1214 nblock += fsbtodb(&sblock, 1); 1215 } 1216 for (; n < NINDIR(&sblock); n++) 1217 reserved_gdb[n] = 0; 1218 1219 /* write group descriptor block as the second dindirect refs */ 1220 wtfs(fsbtodb(&sblock, fs2h32(dindir_block[i])), 1221 sblock.e2fs_bsize, reserved_gdb); 1222 nblock += fsbtodb(&sblock, 1); 1223 } 1224 for (; i < NINDIR(&sblock); i++) { 1225 /* leave trailing entries unallocated */ 1226 dindir_block[i] = 0; 1227 } 1228 free(reserved_gdb); 1229 1230 /* finally write the first level dindirect block */ 1231 wtfs(fsbtodb(&sblock, node.e2di_blocks[NDADDR + DOUBLE]), 1232 sblock.e2fs_bsize, dindir_block); 1233 free(dindir_block); 1234 1235 node.e2di_nblock = nblock; 1236 iput(&node, EXT2_RESIZEINO); 1237 } 1238 1239 /* 1240 * uint32_t alloc(uint32_t size, uint16_t mode) 1241 * 1242 * Allocate a block (from cylinder group 0) 1243 * Reference: src/sys/ufs/ext2fs/ext2fs_alloc.c:ext2fs_alloccg() 1244 */ 1245 uint32_t 1246 alloc(uint32_t size, uint16_t mode) 1247 { 1248 uint32_t loc, bno; 1249 uint8_t *bbp; 1250 uint len, map, i; 1251 1252 if (gd[0].ext2bgd_nbfree == 0) 1253 return 0; 1254 1255 if (size > sblock.e2fs_bsize) 1256 return 0; 1257 1258 bbp = malloc(sblock.e2fs_bsize); 1259 if (bbp == NULL) 1260 return 0; 1261 rdfs(fsbtodb(&sblock, gd[0].ext2bgd_b_bitmap), sblock.e2fs_bsize, bbp); 1262 1263 /* XXX: kernel uses e2fs_fpg here */ 1264 len = sblock.e2fs.e2fs_bpg / NBBY; 1265 1266 #if 0 /* no need block allocation for root or lost+found dir */ 1267 for (loc = 0; loc < len; loc++) { 1268 if (bbp[loc] == 0) { 1269 bno = loc * NBBY; 1270 goto gotit; 1271 } 1272 } 1273 #endif 1274 1275 loc = skpc(~0U, len, bbp); 1276 if (loc == 0) 1277 return 0; 1278 loc = len - loc; 1279 map = bbp[loc]; 1280 bno = loc * NBBY; 1281 for (i = 0; i < NBBY; i++, bno++) { 1282 if ((map & (1 << i)) == 0) 1283 goto gotit; 1284 } 1285 return 0; 1286 1287 gotit: 1288 if (isset(bbp, bno)) 1289 errx(EXIT_FAILURE, "%s: inconsistent bitmap\n", __func__); 1290 1291 setbit(bbp, bno); 1292 wtfs(fsbtodb(&sblock, gd[0].ext2bgd_b_bitmap), sblock.e2fs_bsize, bbp); 1293 free(bbp); 1294 /* XXX: modified group descriptors won't be written into backups */ 1295 gd[0].ext2bgd_nbfree--; 1296 if ((mode & EXT2_IFDIR) != 0) 1297 gd[0].ext2bgd_ndirs++; 1298 sblock.e2fs.e2fs_fbcount--; 1299 1300 return sblock.e2fs.e2fs_first_dblock + bno; 1301 } 1302 1303 /* 1304 * void iput(struct ext2fs_dinode *ip, ino_t ino) 1305 * 1306 * Put an inode entry into the corresponding table. 1307 */ 1308 static void 1309 iput(struct ext2fs_dinode *ip, ino_t ino) 1310 { 1311 daddr_t d; 1312 uint c, i; 1313 struct ext2fs_dinode *dp; 1314 uint8_t *bp; 1315 1316 bp = malloc(sblock.e2fs_bsize); 1317 if (bp == NULL) 1318 errx(EXIT_FAILURE, "%s: can't allocate buffer for inode\n", 1319 __func__); 1320 1321 /* 1322 * Reserved inodes are allocated and accounted in initcg() 1323 * so skip checks of the bitmap and allocation for them. 1324 */ 1325 if (ino >= EXT2_FIRSTINO) { 1326 c = ino_to_cg(&sblock, ino); 1327 1328 /* sanity check */ 1329 if (gd[c].ext2bgd_nifree == 0) 1330 errx(EXIT_FAILURE, 1331 "%s: no free inode %" PRIu64 " in block group %u\n", 1332 __func__, (uint64_t)ino, c); 1333 1334 /* update inode bitmap */ 1335 rdfs(fsbtodb(&sblock, gd[0].ext2bgd_i_bitmap), 1336 sblock.e2fs_bsize, bp); 1337 1338 /* more sanity */ 1339 if (isset(bp, EXT2_INO_INDEX(ino))) 1340 errx(EXIT_FAILURE, "%s: inode %" PRIu64 1341 " already in use\n", __func__, (uint64_t)ino); 1342 setbit(bp, EXT2_INO_INDEX(ino)); 1343 wtfs(fsbtodb(&sblock, gd[0].ext2bgd_i_bitmap), 1344 sblock.e2fs_bsize, bp); 1345 gd[c].ext2bgd_nifree--; 1346 sblock.e2fs.e2fs_ficount--; 1347 } 1348 1349 if (ino >= sblock.e2fs.e2fs_ipg * sblock.e2fs_ncg) 1350 errx(EXIT_FAILURE, "%s: inode value out of range (%" PRIu64 1351 ").\n", __func__, (uint64_t)ino); 1352 1353 /* update an inode entry in the table */ 1354 d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 1355 rdfs(d, sblock.e2fs_bsize, bp); 1356 1357 dp = (struct ext2fs_dinode *)bp; 1358 dp += ino_to_fsbo(&sblock, ino); 1359 e2fs_isave(ip, dp); 1360 /* e2fs_i_bswap() doesn't swap e2di_blocks addrs */ 1361 if ((ip->e2di_mode & EXT2_IFMT) != EXT2_IFLNK) { 1362 for (i = 0; i < NDADDR + NIADDR; i++) 1363 dp->e2di_blocks[i] = h2fs32(ip->e2di_blocks[i]); 1364 } 1365 /* h2fs32() just for consistency */ 1366 dp->e2di_gen = h2fs32(arc4random()); 1367 1368 wtfs(d, sblock.e2fs_bsize, bp); 1369 free(bp); 1370 } 1371 1372 /* 1373 * Read a block from the file system 1374 */ 1375 void 1376 rdfs(daddr_t bno, int size, void *bf) 1377 { 1378 int n; 1379 off_t offset; 1380 1381 offset = bno; 1382 n = pread(fsi, bf, size, offset * sectorsize); 1383 if (n != size) 1384 err(EXIT_FAILURE, "%s: read error for sector %" PRId64, 1385 __func__, (int64_t)bno); 1386 } 1387 1388 /* 1389 * Write a block to the file system 1390 */ 1391 void 1392 wtfs(daddr_t bno, int size, void *bf) 1393 { 1394 int n; 1395 off_t offset; 1396 1397 if (Nflag) 1398 return; 1399 offset = bno; 1400 n = pwrite(fso, bf, size, offset * sectorsize); 1401 if (n != size) 1402 err(EXIT_FAILURE, "%s: write error for sector %" PRId64, 1403 __func__, (int64_t)bno); 1404 } 1405 1406 int 1407 ilog2(uint val) 1408 { 1409 1410 if (val == 0 || !powerof2(val)) 1411 errx(EXIT_FAILURE, "%s: %u is not a power of 2\n", 1412 __func__, val); 1413 1414 return ffs(val) - 1; 1415 } 1416 1417 /* 1418 * int skpc(int mask, size_t size, uint8_t *cp) 1419 * 1420 * Locate an unsigned character of value mask inside cp[]. 1421 * (from src/sys/lib/libkern/skpc.c) 1422 */ 1423 int 1424 skpc(int mask, size_t size, uint8_t *cp) 1425 { 1426 uint8_t *end; 1427 1428 end = &cp[size]; 1429 while (cp < end && *cp == (uint8_t)mask) 1430 cp++; 1431 1432 return end - cp; 1433 } 1434