pass2.c revision cf5301d7f2c3bbed3d26600335102414cbf0c4ba
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass2.c --- check directory structure 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o 521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 10efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 of e2fsck iterates through all active directory inodes, and 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * applies to following tests to each directory entry in the directory 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * blocks in the inodes: 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The length of the directory entry (rec_len) should be at 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * least 8 bytes, and no more than the remaining space 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * left in the directory block. 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The length of the name in the directory entry (name_len) 19efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * should be less than (rec_len - 8). 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode number in the directory entry should be within 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * legal bounds. 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode number should refer to a in-use inode. 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The first entry should be '.', and its inode should be 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * the inode of the directory. 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The second entry should be '..'. 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * To minimize disk seek time, the directory blocks are processed in 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * sorted order of block numbers. 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 also collects the following information: 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode numbers of the subdirectories for each directory. 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 relies on the following information from previous passes: 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The directory information collected in pass 1. 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_used_map bitmap 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_bad_map bitmap 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_dir_map bitmap 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 frees the following data structures 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_bad_map bitmap 41aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * - The inode_reg_map bitmap 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 44b969b1b8a5c13992cadb026114731958644540d8Matthias Andree#define _GNU_SOURCE 1 /* get strnlen() */ 4548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#include <string.h> 4648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 4821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 490926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o#include "dict.h" 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 51aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#ifdef NO_INLINE_FUNCS 52aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ 53aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#else 54aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ inline 55aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#endif 56aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 57ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o/* #define DX_DEBUG */ 588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Keeps track of how many times an inode is referenced. 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 624035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 646dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *dir_blocks_info, 6554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data); 661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 676dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *dir_blocks_info, 6821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf, struct problem_context *pctx); 698fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino); 70ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 71ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db); 72ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b); 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostruct check_dir_struct { 7521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf; 7621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 77f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o int count, max; 781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 79efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o}; 8021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 8108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass2(e2fsck_t ctx) 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 83a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct ext2_super_block *sb = ctx->fs->super; 84a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct problem_context pctx; 85a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2_filsys fs = ctx->fs; 86a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o char *buf; 878bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 898bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 9021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct check_dir_struct cd; 918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db, *dx_parent; 93544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int b; 94ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, depth; 958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o problem_t code; 968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o int bad_dir; 978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 986d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o init_resource_track(&rtrack, ctx->fs->io); 991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&cd.pctx); 1001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 2"); 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 1061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); 1071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 108efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT, 10934b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o &ctx->inode_count); 11034b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o if (ctx->inode_count) 11134b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o cd.pctx.errcode = 0; 112efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o else 113efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o cd.pctx.errcode = ext2fs_create_icount2(fs, 11434b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o EXT2_ICOUNT_OPT_INCREMENT, 1151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 0, ctx->inode_link_info, 1161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &ctx->inode_count); 1171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); 11908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 12008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 12121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 122bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, 12354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o "directory scan buffer"); 1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 12521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 12621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Set up the parent pointer for the root directory, if 12721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * present. (If the root directory is not present, we will 12821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * create it in pass 3.) 12921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 13028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 13121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 13221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd.buf = buf; 1331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd.ctx = ctx; 134f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o cd.count = 1; 1356dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd.max = ext2fs_dblist_count2(fs->dblist); 136f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o 137f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o if (ctx->progress) 138f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o (void) (ctx->progress)(ctx, 2, 0, cd.max); 139ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 140ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) 1416dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp); 142efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1436dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block, 1446dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson &cd); 14549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) 14608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1476267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger 1486267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger if (ctx->flags & E2F_FLAG_RESTART_LATER) { 1496267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART; 1506267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger return; 1516267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger } 1526267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger 1531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); 15508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 15608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1577ac02a5ebddcc6187c893eedc80d92777b399575Theodore Ts'o } 1588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 1608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { 1614cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1624cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return; 16362acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir->numblocks == 0) 1648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_problem_context(&pctx); 1668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir = 0; 1678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.dir = dx_dir->ino; 1688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = dx_dir->dx_block; 1698fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) 1708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 1718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else 1728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 1738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * Find all of the first and last leaf blocks, and 1758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * update their parent's min and max hash values 1768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 1788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 1798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 1808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type != DX_DIRBLOCK_LEAF) || 1818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) 1828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent = &dx_dir->dx_block[dx_db->parent]; 1848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->min_hash > dx_db->min_hash 1868fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_FIRST) 1888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->min_hash = dx_db->min_hash; 1898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->max_hash < dx_db->max_hash 1918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_LAST) 1938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->max_hash = dx_db->max_hash; 1948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 195efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 1978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 1988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 1998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blkcount = b; 2008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.group = dx_db->parent; 2018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = 0; 2028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_FIRST) && 2038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->min_hash < dx_db->node_min_hash)) { 2048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->min_hash; 2058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_min_hash; 2068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MIN_HASH; 2078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 210ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (dx_db->type == DX_DIRBLOCK_LEAF) { 211ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth = htree_depth(dx_dir, dx_db); 212ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (depth != dx_dir->depth) { 213e5e12db959d3c18f6cf4ac938a14f68be0a89accAndreas Dilger pctx.num = dx_dir->depth; 214ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o code = PR_2_HTREE_BAD_DEPTH; 215ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(ctx, code, &pctx); 216ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o bad_dir++; 217ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 218ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 2198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 220efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * This test doesn't apply for the root block 2218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * at block #0 2228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 2238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (b && 2248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->max_hash > dx_db->node_max_hash)) { 2258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->max_hash; 2268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_max_hash; 2278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MAX_HASH; 2288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 229503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o bad_dir++; 2308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_REFERENCED)) { 2328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_NOTREF; 2338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if (dx_db->flags & DX_FLAG_DUP_REF) { 2368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_DUPREF; 2378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { 2428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_htree(ctx, dx_dir->ino); 24362acaa1de132a808949d71264731bba7fe095705Theodore Ts'o dx_dir->numblocks = 0; 2448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 24623f75f6efaac6b756e0f3e4e1d33b6798347f66aTheodore Ts'o e2fsck_free_dx_dir_info(ctx); 2478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 248c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 24921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2fs_free_dblist(fs->dblist); 25021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 2511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map) { 2521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_bad_map); 2531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_bad_map = 0; 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 255aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (ctx->inode_reg_map) { 256aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_reg_map); 257aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ctx->inode_reg_map = 0; 258aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 259a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 260a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o clear_problem_context(&pctx); 261a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (ctx->large_files) { 262a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (!(sb->s_feature_ro_compat & 263a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && 264a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { 265a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o sb->s_feature_ro_compat |= 266a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 2670cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 268a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 269a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 270a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (sb->s_rev_level == EXT2_GOOD_OLD_REV && 271a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { 272a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_update_dynamic_rev(fs); 273a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 274a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 275a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 276efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2779facd076ae8af6e908e228392cea866ce0faf1bcKen Chen print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io); 2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 280ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o#define MAX_DEPTH 32000 281ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 282ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db) 283ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o{ 284ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int depth = 0; 285ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 286ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) { 287ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_db = &dx_dir->dx_block[dx_db->parent]; 288ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth++; 289ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 290ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return depth; 291ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o} 292ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 2930926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'ostatic int dict_de_cmp(const void *a, const void *b) 2940926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o{ 295520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o const struct ext2_dir_entry *de_a, *de_b; 2960926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int a_len, b_len; 2970926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 298520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_a = (const struct ext2_dir_entry *) a; 2990926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o a_len = de_a->name_len & 0xFF; 300520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_b = (const struct ext2_dir_entry *) b; 3010926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o b_len = de_b->name_len & 0xFF; 3020926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3030926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (a_len != b_len) 3040926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return (a_len - b_len); 3050926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3060926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return strncmp(de_a->name, de_b->name, a_len); 3070926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o} 308ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 3093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 310ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This is special sort function that makes sure that directory blocks 311ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * with a dirblock of zero are sorted to the beginning of the list. 312ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This guarantees that the root node of the htree directories are 313ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * processed first, so we know what hash version to use. 314ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o */ 315ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b) 316ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{ 3176dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson const struct ext2_db_entry2 *db_a = 3186dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson (const struct ext2_db_entry2 *) a; 3196dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson const struct ext2_db_entry2 *db_b = 3206dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson (const struct ext2_db_entry2 *) b; 321ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 322ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blockcnt && !db_b->blockcnt) 323ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return 1; 324ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 325ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (!db_a->blockcnt && db_b->blockcnt) 326ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return -1; 327efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 328ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blk != db_b->blk) 329ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blk - db_b->blk); 330efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 331ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->ino != db_b->ino) 332ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->ino - db_b->ino); 333ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 334ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blockcnt - db_b->blockcnt); 335ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o} 336ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 337ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 338ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o/* 3393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the first entry in the directory is '.', and that the 3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. 3413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dot(e2fsck_t ctx, 3433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 34486c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *nextdir; 3478a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len, new_len; 3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int status = 0; 3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int created = 0; 35021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int problem = 0; 351efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 35221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 35321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT; 354b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o else if (((dirent->name_len & 0xFF) != 1) || 35521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.')) 35621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_1ST_NOT_DOT; 35721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[1] != '\0') 35821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_NULL_TERM; 3595dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o 3608a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); 36121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 3621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 3635dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len < 12) 3645dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o rec_len = dirent->rec_len = 12; 3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 3663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name_len = 1; 3673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 36821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[1] = '\0'; 3693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 3703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o created = 1; 3713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->inode != ino) { 3741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { 3753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 37721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3795dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len > 12) { 3805dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o new_len = rec_len - 12; 3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (new_len > 12) { 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (created || 383f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { 3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir = (struct ext2_dir_entry *) 3853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ((char *) dirent + 12); 3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->rec_len = 12; 3878a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(ctx->fs, new_len, 3888a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o nextdir); 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->inode = 0; 3903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->name_len = 0; 3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return status; 3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 3993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the second entry in the directory is '..', and that the 4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. We do not check the inode number of '..' 4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * here; this gets done in pass 3. 4023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dotdot(e2fsck_t ctx, 4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 40528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 407cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger int problem = 0; 408cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger unsigned int rec_len; 409efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 41021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 41121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT_DOT; 412b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o else if (((dirent->name_len & 0xFF) != 2) || 41321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.') || 41421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[1] != '.')) 41521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_2ND_NOT_DOT_DOT; 41621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[2] != '\0') 41721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_DOT_NULL_TERM; 41821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 4198a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); 42021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 4211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 4225dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len < 12) 42321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->rec_len = 12; 4243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Note: we don't have the parent inode just 4263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * yet, so we will fill it in with the root 4273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * inode. This will get fixed in pass 3. 4283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = EXT2_ROOT_INO; 4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name_len = 2; 4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 4323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[1] = '.'; 43321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[2] = '\0'; 4343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 435efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } 4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 43828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) { 43928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, pctx); 44028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o return -1; 44128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Check to make sure a directory entry doesn't contain any illegal 4473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * characters. 4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_name(e2fsck_t ctx, 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 451efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 452544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 4553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int fixup = -1; 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int ret = 0; 457efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 458b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o for ( i = 0; i < (dirent->name_len & 0xFF); i++) { 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->name[i] == '/' || dirent->name[i] == '\0') { 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fixup < 0) { 4611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fixup) { 4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[i] = '.'; 4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ret = 1; 46621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 4673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ret; 4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 472aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o/* 473aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * Check the directory filetype (if present) 474aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o */ 475aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'ostatic _INLINE_ int check_filetype(e2fsck_t ctx, 476544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct ext2_dir_entry *dirent, 477544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 478544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 479aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o{ 480aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int filetype = dirent->name_len >> 8; 481aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int should_be = EXT2_FT_UNKNOWN; 482aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o struct ext2_inode inode; 483aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 484aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (!(ctx->fs->super->s_feature_incompat & 4857847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o EXT2_FEATURE_INCOMPAT_FILETYPE)) { 4867847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o if (filetype == 0 || 4877847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) 4887847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 0; 4897847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o dirent->name_len = dirent->name_len & 0xFF; 4907847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 1; 4917847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o } 492aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 493c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) { 494aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_DIR; 495c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, 496aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) { 497aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_REG_FILE; 498aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } else if (ctx->inode_bad_map && 499c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_test_inode_bitmap2(ctx->inode_bad_map, 500aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) 501aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = 0; 502aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o else { 503aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o e2fsck_read_inode(ctx, dirent->inode, &inode, 504aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o "check_filetype"); 5056fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o should_be = ext2_file_type(inode.i_mode); 506aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 507aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (filetype == should_be) 508aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 509aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx->num = should_be; 510aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 511aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, 512aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx) == 0) 513aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 514efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 515aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; 516aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 1; 517aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o} 518aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 5198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 5208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void parse_int_node(ext2_filsys fs, 5216dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 5228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct check_dir_struct *cd, 5238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir, 5248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o char *block_buf) 5258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 5268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_root_info *root; 5278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_entry *ent; 5288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_countlimit *limit; 5298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db; 530ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, expect_limit, count; 5318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o blk_t blk; 5328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t min_hash = 0xffffffff; 5338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t max_hash = 0; 534ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o ext2_dirhash_t hash = 0, prev_hash; 5358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 5378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o root = (struct ext2_dx_root_info *) (block_buf + 24); 538efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Root node dump:\n"); 5418deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("\t Reserved zero: %u\n", root->reserved_zero); 5428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Hash Version: %d\n", root->hash_version); 5438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Info length: %d\n", root->info_length); 5448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Indirect levels: %d\n", root->indirect_levels); 5458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Flags: %d\n", root->unused_flags); 5468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); 5498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 5508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf+8); 5518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 5528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 5538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 555efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o printf("Number of entries (count): %d\n", 5568132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->count)); 557efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o printf("Number of entries (limit): %d\n", 5588132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->limit)); 5598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5618132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o count = ext2fs_le16_to_cpu(limit->count); 562ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o expect_limit = (fs->blocksize - ((char *) ent - block_buf)) / 563ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o sizeof(struct ext2_dx_entry); 5648132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { 5658132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); 566ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) 567ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 568ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 5698132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (count > expect_limit) { 5708132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = count; 571ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) 572ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 573ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o count = expect_limit; 574ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 575efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 576ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o for (i=0; i < count; i++) { 577ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o prev_hash = hash; 5788132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; 5798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5808deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("Entry #%d: Hash 0x%08x, block %u\n", i, 5818132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash, ext2fs_le32_to_cpu(ent[i].block)); 5828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5838132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; 5848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* Check to make sure the block is valid */ 585977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o if (blk >= (blk_t) dx_dir->numblocks) { 586b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.blk = blk; 5878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, 588ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o &cd->pctx)) 589ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 590977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o continue; 5918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 592ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (hash < prev_hash && 593ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx)) 594ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 5958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[blk]; 5968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) { 5978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 5988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 5998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 6008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->parent = db->blockcnt; 6018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < min_hash) 6038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o min_hash = hash; 6048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > max_hash) 6058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o max_hash = hash; 6068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_min_hash = hash; 6078132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if ((i+1) < count) 608efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o dx_db->node_max_hash = 6098132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; 6108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else { 6118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_max_hash = 0xfffffffe; 6128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_LAST; 6138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (i == 0) 6158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST; 6168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 6188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n", 6198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, min_hash, max_hash); 6208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 6218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 6228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = min_hash; 6238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = max_hash; 624ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 625ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 626ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'oclear_and_exit: 627ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o clear_htree(cd->ctx, cd->pctx.ino); 628ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->numblocks = 0; 6298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 6308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 631aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 632e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o/* 633e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Given a busted directory, try to salvage it somehow. 634efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 635e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 636ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic void salvage_directory(ext2_filsys fs, 637e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, 638e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *prev, 639544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int *offset) 640e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o{ 641e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o char *cp = (char *) dirent; 6428a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o int left; 6438a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len, prev_rec_len; 644642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o unsigned int name_len = dirent->name_len & 0xFF; 645e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 6468a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 6475dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o left = fs->blocksize - *offset - rec_len; 6485dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o 649e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 650e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Special case of directory entry of size 8: copy what's left 651e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * of the directory block up to cover up the invalid hole. 652e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 6535dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if ((left >= 12) && (rec_len == 8)) { 654e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o memmove(cp, cp+8, left); 655e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o memset(cp + left, 0, 8); 656ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 657ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 658ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o /* 659ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * If the directory entry overruns the end of the directory 660ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * block, and the name is small enough to fit, then adjust the 661ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * record length. 662ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o */ 663ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if ((left < 0) && 6648a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o ((int) rec_len + left > 8) && 6658a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (name_len + 8 <= (int) rec_len + left) && 666ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dirent->inode <= fs->super->s_inodes_count && 667ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o strnlen(dirent->name, name_len) == name_len) { 6688a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent); 669ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 670e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 671e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 672575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * If the record length of the directory entry is a multiple 673575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * of four, and not too big, such that it is valid, let the 674575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * previous directory entry absorb the invalid one. 675e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 6765dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (prev && rec_len && (rec_len % 4) == 0 && 6775dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (*offset + rec_len <= fs->blocksize)) { 6788a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); 6798a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o prev_rec_len += rec_len; 6808a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); 6815dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o *offset += rec_len; 682ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 683e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 684e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 685e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Default salvage method --- kill all of the directory 686e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * entries for the rest of the block. We will either try to 687e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * absorb it into the previous directory entry, or create a 688e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * new empty directory entry the rest of the directory block. 689e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 690e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (prev) { 6918a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); 6928a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o prev_rec_len += fs->blocksize - *offset; 6938a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); 694ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o *offset = fs->blocksize; 695e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else { 6968a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o rec_len = fs->blocksize - *offset; 6978a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, rec_len, dirent); 698e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->name_len = 0; 699e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->inode = 0; 700e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 701e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o} 702e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 7033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 7046dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 70554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 7063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 7078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 7088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 7098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db = 0; 7108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 711e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, *prev; 7128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t hash; 713544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 714e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o const char * old_op; 7153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dir_modified = 0; 71621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int dot_state; 71703fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o unsigned int rec_len; 7186dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t block_nr = db->blk; 71986c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino = db->ino; 72028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t subdir_parent; 72121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o __u16 links; 72254dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct check_dir_struct *cd; 7231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o char *buf; 7241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 7251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o int problem; 726ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o struct ext2_dx_root_info *root; 727e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o struct ext2_dx_countlimit *limit; 7280926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o static dict_t de_dict; 7290926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o struct problem_context pctx; 7300926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int dups_found = 0; 73128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o int ret; 7321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 73354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o cd = (struct check_dir_struct *) priv_data; 7341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o buf = cd->buf; 7351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx = cd->ctx; 736f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 73749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) 7384cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 739efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7404cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) 7414cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 742efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 744efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Make sure the inode is still in use (could have been 7453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * deleted in the duplicate/bad blocks pass. 7463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 747c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino))) 7483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 74950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 75021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino = ino; 75121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blk = block_nr; 75221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blkcount = db->blockcnt; 75321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 75421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = 0; 75521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = 0; 75621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 75750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blk == 0) { 7581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (allocate_dir_block(ctx, db, buf, &cd->pctx)) 75950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 76050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o block_nr = db->blk; 76150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 762efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (db->blockcnt) 7643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 2; 7653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 7663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 0; 7673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7680926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (ctx->dirs_to_hash && 7690926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_test(ctx->dirs_to_hash, ino)) 7700926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 7710926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 7723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 773f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr, 7743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o db->blockcnt, ino); 7753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 776efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 777e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o old_op = ehandler_operation(_("reading directory block")); 7786dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd->pctx.errcode = ext2fs_read_dir_block3(fs, block_nr, buf, 0); 779e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o ehandler_operation(0); 780b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) 781b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o cd->pctx.errcode = 0; /* We'll handle this ourselves */ 7821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 78308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { 78408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 78508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 78608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o } 7871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o memset(buf, 0, fs->blocksize); 7883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 7908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_dir = e2fsck_get_dx_dir_info(ctx, ino); 79162acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir && dx_dir->numblocks) { 7928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt >= dx_dir->numblocks) { 793efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK, 794d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o &pctx)) { 795d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o clear_htree(ctx, ino); 796d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o dx_dir->numblocks = 0; 797d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o dx_db = 0; 798d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o goto out_htree; 799d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o } 800d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o fatal_error(ctx, _("Can not continue.")); 8018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 8028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 8038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_LEAF; 8048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->phys = block_nr; 8058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = ~0; 8068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = 0; 807efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 8088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dirent = (struct ext2_dir_entry *) buf; 8098a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 810e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o limit = (struct ext2_dx_countlimit *) (buf+8); 8118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 812ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root = (struct ext2_dx_root_info *) (buf + 24); 8138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_ROOT; 8148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; 815ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if ((root->reserved_zero || 816ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->info_length < 8 || 817ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->indirect_levels > 1) && 818ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { 819ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o clear_htree(ctx, ino); 820ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->numblocks = 0; 821ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_db = 0; 822f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o } 823ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->hashversion = root->hash_version; 824f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((dx_dir->hashversion <= EXT2_HASH_TEA) && 825f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 826f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o dx_dir->hashversion += 3; 827ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->depth = root->indirect_levels + 1; 8288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if ((dirent->inode == 0) && 8295dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len == fs->blocksize) && 830e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o (dirent->name_len == 0) && 831efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (ext2fs_le16_to_cpu(limit->limit) == 832efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o ((fs->blocksize-8) / 8338132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o sizeof(struct ext2_dx_entry)))) 8348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_NODE; 8358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 836d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'oout_htree: 8378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 8383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8390926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp); 840e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = 0; 8413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o do { 84249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos int group; 84349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2_ino_t first_unused_inode; 84449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 8451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = 0; 8463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 8478a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 84821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = dirent; 84921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = offset; 8505dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (((offset + rec_len) > fs->blocksize) || 8515dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len < 12) || 8525dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o ((rec_len % 4) != 0) || 85303fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) { 8541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { 855ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o salvage_directory(fs, dirent, prev, &offset); 8563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 857e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o continue; 85821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } else 8590926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 8603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 861b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) { 8621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) { 86350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o dirent->name_len = EXT2_NAME_LEN; 86450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o dir_modified++; 86550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 86650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 86750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 868e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (dot_state == 0) { 8691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (check_dot(ctx, dirent, ino, &cd->pctx)) 8703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 871e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if (dot_state == 1) { 87228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ret = check_dotdot(ctx, dirent, ino, &cd->pctx); 87328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ret < 0) 8740926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 87528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ret) 8763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 8773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else if (dirent->inode == ino) { 8781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_LINK_DOT; 8791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) { 8803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 8813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 88221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 8833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 885efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (!dirent->inode) 8863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 887efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 8883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 8893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the inode listed is a legal one. 890efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o */ 8913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (((dirent->inode != EXT2_ROOT_INO) && 8927f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o (dirent->inode < EXT2_FIRST_INODE(fs->super))) || 8933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o (dirent->inode > fs->super->s_inodes_count)) { 8941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_BAD_INO; 8951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else if (ctx->inode_bb_map && 896c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson (ext2fs_test_inode_bitmap2(ctx->inode_bb_map, 8971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dirent->inode))) { 8981b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 8991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If the inode is in a bad block, offer to 9001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * clear it. 9011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_BB_INODE; 903e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 904b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o ((dirent->name_len & 0xFF) == 1) && 9051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[0] == '.')) { 9061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 9071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If there's a '.' entry in anything other 9081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * than the first directory entry, it's a 9091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * duplicate entry that should be removed. 9101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_DUP_DOT; 912e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 913b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o ((dirent->name_len & 0xFF) == 2) && 914efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (dirent->name[0] == '.') && 9151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[1] == '.')) { 9161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 9171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If there's a '..' entry in anything other 9181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * than the second directory entry, it's a 9191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * duplicate entry that should be removed. 9201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_DUP_DOT_DOT; 922e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 9231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->inode == EXT2_ROOT_INO)) { 9241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 9251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * Don't allow links to the root directory. 9261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * We check this specially to make sure we 9271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * catch this error case even if the root 9281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * directory hasn't been created yet. 9291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_LINK_ROOT; 931e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 932c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o (dirent->name_len & 0xFF) == 0) { 933c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o /* 934c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o * Don't allow zero-length directory names. 935c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o */ 936c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o problem = PR_2_NULL_NAME; 93721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 93821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 9391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (problem) { 9401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, &cd->pctx)) { 94121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->inode = 0; 94221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dir_modified++; 94321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 9441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else { 9451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_valid(fs); 9461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (problem == PR_2_BAD_INO) 9471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o goto next; 94821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 9493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 9503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 9523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If the inode was marked as having bad fields in 9533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass1, process it and offer to fix/clear it. 9543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * (We wait until now so that we can display the 9553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pathname to the user.) 9563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 9571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map && 958c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_test_inode_bitmap2(ctx->inode_bad_map, 9593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode)) { 960e72a9ba39471364ad2f9397f645ca547090e3485Theodore Ts'o if (e2fsck_process_bad_inode(ctx, ino, 961bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o dirent->inode, 962bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf + fs->blocksize)) { 9633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 9643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 9653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 9663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 967a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 96808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 9693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 9703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 97149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos group = ext2fs_group_of_ino(fs, dirent->inode); 97249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos first_unused_inode = group * fs->super->s_inodes_per_group + 97349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 1 + fs->super->s_inodes_per_group - 974d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused(fs, group); 97549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos cd->pctx.group = group; 97649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 97749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos /* 97842e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * Check if the inode was missed out because 97942e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * _INODE_UNINIT flag was set or bg_itable_unused was 98042e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * incorrect. If so, clear the _INODE_UNINIT flag and 98142e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * restart e2fsck. In the future it would be nice if 98242e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * we could call a function in pass1.c that checks the 98342e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o * newly visible inodes. 98449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos */ 985cd65a24e756b8f6770a5961fd94c67eb00dd7baaTheodore Ts'o if (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)) { 9866267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger pctx.num = dirent->inode; 98749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT, 98849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos &cd->pctx)){ 989e633b58ac75f2f544b7d6572e37d4b63da31e59cEric Sandeen ext2fs_bg_flags_clear(fs, group, 990732c8cd58ff30ffae0d3276c411a08920717a46cTheodore Ts'o EXT2_BG_INODE_UNINIT); 99142e89ce7f8823ad14099b03469c2f4e4f6530d05Theodore Ts'o ext2fs_mark_super_dirty(fs); 9926267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART_LATER; 99349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else { 99449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_unmark_valid(fs); 99549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem == PR_2_BAD_INO) 99649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 99749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 99849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else if (dirent->inode >= first_unused_inode) { 9996267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger pctx.num = dirent->inode; 100049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){ 1001d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused_set(fs, group, 0); 100249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_mark_super_dirty(fs); 10036267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART_LATER; 100449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else { 100549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_unmark_valid(fs); 100649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem == PR_2_BAD_INO) 100749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 100849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 100949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 101049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 10110433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o /* 10120433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * Offer to clear unused inodes; if we are going to be 10130433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * restarting the scan due to bg_itable_unused being 10140433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * wrong, then don't clear any inodes to avoid zapping 10150433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * inodes that were skipped during pass1 due to an 10160433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * incorrect bg_itable_unused; we'll get any real 10170433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o * problems after we restart. 10180433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o */ 10190433c1f1b72bb85d9ea11e7716a415a878a655c8Theodore Ts'o if (!(ctx->flags & E2F_FLAG_RESTART_LATER) && 102097d26ce9e3589e9f5fa17014467a9730a884d158Theodore Ts'o !(ext2fs_test_inode_bitmap2(ctx->inode_used_map, 102197d26ce9e3589e9f5fa17014467a9730a884d158Theodore Ts'o dirent->inode))) 102249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos problem = PR_2_UNUSED_INODE; 102349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 102449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem) { 102549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (fix_problem(ctx, problem, &cd->pctx)) { 102649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos dirent->inode = 0; 102749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos dir_modified++; 102849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 102949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } else { 103049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2fs_unmark_valid(fs); 103149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (problem == PR_2_BAD_INO) 103249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos goto next; 103349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 103449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos } 103549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 10361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (check_name(ctx, dirent, ino, &cd->pctx)) 10371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dir_modified++; 10381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1039aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (check_filetype(ctx, dirent, ino, &cd->pctx)) 1040aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dir_modified++; 1041aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 10428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 10438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db) { 10448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2fs_dirhash(dx_dir->hashversion, dirent->name, 1045503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o (dirent->name_len & 0xFF), 1046503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o fs->super->s_hash_seed, &hash, 0); 10478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < dx_db->min_hash) 10488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = hash; 10498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > dx_db->max_hash) 10508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = hash; 10518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 10528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 10538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 105421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 10553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If this is a directory, then mark its parent in its 10563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * dir_info structure. If the parent field is already 10573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filled in, then this directory has more than one 10583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * hard link. We assume the first link is correct, 10593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * and ask the user if he/she wants to clear this one. 10603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1061e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if ((dot_state > 1) && 1062c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, 10633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode))) { 106428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_get_parent(ctx, dirent->inode, 106528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o &subdir_parent)) { 10661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.ino = dirent->inode; 10671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); 10680926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 10693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 107028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (subdir_parent) { 107128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o cd->pctx.ino2 = subdir_parent; 10721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_LINK_DIR, 107321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o &cd->pctx)) { 10743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 10753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 10763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 107721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 107821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 107928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } else { 1080efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, 108128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o dirent->inode, ino); 108228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 10833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10840926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 10850926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (dups_found) { 10860926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ; 10870926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o } else if (dict_lookup(&de_dict, dirent)) { 10880926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o clear_problem_context(&pctx); 10890926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o pctx.ino = ino; 10900926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o pctx.dirent = dirent; 10910926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx); 10920926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (!ctx->dirs_to_hash) 10930926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_create(&ctx->dirs_to_hash, 50); 10940926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (ctx->dirs_to_hash) 10950926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 10960926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 10970926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o } else 10980926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_alloc_insert(&de_dict, dirent, dirent); 1099efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_count, dirent->inode, 11011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &links); 110221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (links > 1) 11031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->fs_links_count++; 11041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->fs_total_count++; 11053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o next: 1106e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = dirent; 11075dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (dir_modified) 11088a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 11095dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o offset += rec_len; 1110e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dot_state++; 11113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } while (offset < fs->blocksize); 11123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 11133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o printf("\n"); 11143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 11158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 11168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db) { 11178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 11188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n", 11198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, dx_db->type, 11208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash, dx_db->max_hash); 11218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 1122b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.dir = cd->pctx.ino; 11238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type == DX_DIRBLOCK_ROOT) || 11248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->type == DX_DIRBLOCK_NODE)) 11258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o parse_int_node(fs, db, cd, dx_dir, buf); 11268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 11278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 11283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (offset != fs->blocksize) { 11295dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o cd->pctx.num = rec_len - fs->blocksize + offset; 11301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) { 11311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dirent->rec_len = cd->pctx.num; 11321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dir_modified++; 11331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 11343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 11353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dir_modified) { 11361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf); 11371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 113808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, 11390926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o &cd->pctx)) 11400926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 11413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 11423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_changed(fs); 11433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 11440926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_free_nodes(&de_dict); 11453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 11460926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'oabort_free_dict: 11470926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 114849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos dict_free_nodes(&de_dict); 11490926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return DIRENT_ABORT; 11503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 11513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 11523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 11533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This function is called to deallocate a block, and is an interator 11543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * functioned called by deallocate inode via ext2fs_iterate_block(). 11553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 11563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int deallocate_inode_block(ext2_filsys fs, 11576dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t *block_nr, 1158544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 11596dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t ref_block EXT2FS_ATTR((unused)), 1160544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 1161133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o void *priv_data) 11623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 116354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o e2fsck_t ctx = (e2fsck_t) priv_data; 1164efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11651917875fcd16428d14eb5a86acf414472bc216f1Theodore Ts'o if (HOLE_BLKADDR(*block_nr)) 11663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 11671ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o if ((*block_nr < fs->super->s_first_data_block) || 11684efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson (*block_nr >= ext2fs_blocks_count(fs->super))) 11691ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o return 0; 1170c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_unmark_block_bitmap2(ctx->block_found_map, *block_nr); 117148f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_block_alloc_stats2(fs, *block_nr, -1); 11723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 11733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1174efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 11763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This fuction deallocates an inode 11773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 11784035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) 11793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 11801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 11813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 11821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 11830684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o __u32 count; 1184efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 118508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 1186e3df15abdb288c3519000c639ed40429a82b63cdTheodore Ts'o e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); 11871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 11881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.ino = ino; 1189f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 11903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 11913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Fix up the bitmaps... 11923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1193f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 11940684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); 11950684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o 1196a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson if (ext2fs_file_acl_block(&inode) && 11970684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 11986dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson pctx.errcode = ext2fs_adjust_ea_refcount2(fs, ext2fs_file_acl_block(&inode), 11990684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o block_buf, -1, &count); 12000684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { 12010684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o pctx.errcode = 0; 12020684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o count = 1; 12030684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12040684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode) { 1205a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson pctx.blk = ext2fs_file_acl_block(&inode); 12060684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); 12070684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 12080684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o return; 12090684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12100684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (count == 0) { 1211c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_unmark_block_bitmap2(ctx->block_found_map, 121248f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_file_acl_block(&inode)); 121348f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_block_alloc_stats2(fs, 121448f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_file_acl_block(&inode), 121548f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson -1); 12160684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 1217a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson ext2fs_file_acl_block_set(&inode, 0); 12180684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 122021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!ext2fs_inode_has_valid_blocks(&inode)) 12213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 1222a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 1223b94a052a25d0c524209782e408c31d8ff25a6fe1Andreas Dilger if (LINUX_S_ISREG(inode.i_mode) && 1224a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o (inode.i_size_high || inode.i_size & 0x80000000UL)) 1225a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ctx->large_files--; 1226a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 12276dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, 12286dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson deallocate_inode_block, ctx); 12291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 12301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); 123108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 123208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 12331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 12343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 12353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 12368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o/* 12378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This fuction clears the htree flag on an inode 12388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 12398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino) 12408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 12418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_inode inode; 1242efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 12438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); 12448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; 12458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); 1246b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (ctx->dirs_to_hash) 1247b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 12488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 12498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 12508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 125186c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'oextern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, 1252bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o ext2_ino_t ino, char *buf) 12533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 12541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 12553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 12563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int inode_modified = 0; 12576c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o int not_fixed = 0; 12581e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o unsigned char *frag, *fsize; 125921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 126008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o int problem = 0; 12613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 126208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); 126321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 126421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o clear_problem_context(&pctx); 126521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.ino = ino; 126621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.dir = dir; 126721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.inode = &inode; 126821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 1269a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson if (ext2fs_file_acl_block(&inode) && 1270f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 1271f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { 1272a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson ext2fs_file_acl_block_set(&inode, 0); 1273f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o inode_modified++; 1274f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } else 1275f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o not_fixed++; 1276f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } 12776c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 127850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && 127950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && 128050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && 128108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o !(LINUX_S_ISSOCK(inode.i_mode))) 128208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_MODE; 1283fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISCHR(inode.i_mode) 12840684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 128508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_CHAR_DEV; 1286fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISBLK(inode.i_mode) 12870684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 128808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_BLOCK_DEV; 1289fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISFIFO(inode.i_mode) 12900684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 12911dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_FIFO; 1292fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISSOCK(inode.i_mode) 12930684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 12941dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_SOCKET; 1295fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISLNK(inode.i_mode) 12967cadc57780f3e3e8e644e8976e11a336902d4a25Theodore Ts'o && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) { 1297bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o problem = PR_2_INVALID_SYMLINK; 129867052a8aeeca8cd80d1dd33c2792f917573accc8Andreas Dilger } 12991dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o 130008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (problem) { 130108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (fix_problem(ctx, problem, &pctx)) { 13021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o deallocate_inode(ctx, ino, 0); 1303a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 130408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return 0; 13057cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o return 1; 13066c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13076c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 130808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = 0; 13097cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o } 1310efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 13116c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (inode.i_faddr) { 13126c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { 13136c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_faddr = 0; 13146c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13156c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13166c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 13173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 13181e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 13191e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o switch (fs->super->s_creator_os) { 13201e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o case EXT2_OS_HURD: 13211e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = &inode.osd2.hurd2.h_i_frag; 13221e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o fsize = &inode.osd2.hurd2.h_i_fsize; 13231e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o break; 13241e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o default: 13251e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = fsize = 0; 13261e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o } 132721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (frag && *frag) { 132821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *frag; 13291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { 133021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *frag = 0; 133121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 13327e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o } else 13337e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o not_fixed++; 133421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 133521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 133621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (fsize && *fsize) { 133721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *fsize; 13381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { 133921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *fsize = 0; 134021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 13416c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13426c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 134321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 134421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 134521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 13465d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if ((fs->super->s_creator_os == EXT2_OS_LINUX) && 1347efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o !(fs->super->s_feature_ro_compat & 13485d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && 13495d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o (inode.osd2.linux2.l_i_blocks_hi != 0)) { 13505d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_blocks_hi; 13515d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { 13525d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode.osd2.linux2.l_i_blocks_hi = 0; 13535d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode_modified++; 13545d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 13555d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 13565d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o 1357911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o if (!(fs->super->s_feature_incompat & 1358911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o EXT4_FEATURE_INCOMPAT_64BIT) && 1359911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode.osd2.linux2.l_i_file_acl_high != 0) { 1360911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_file_acl_high; 1361911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) { 1362911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode.osd2.linux2.l_i_file_acl_high = 0; 1363911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode_modified++; 1364911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o } else 1365911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o not_fixed++; 1366911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o } 1367911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o 1368a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson if (ext2fs_file_acl_block(&inode) && 1369a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson ((ext2fs_file_acl_block(&inode) < fs->super->s_first_data_block) || 13704efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson (ext2fs_file_acl_block(&inode) >= ext2fs_blocks_count(fs->super)))) { 13716c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { 1372a63745e81cbb476b90c75ca3ca60b9ba4be95caeValerie Aurora Henson ext2fs_file_acl_block_set(&inode, 0); 13736c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13746c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13756c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 1376342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o } 137721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (inode.i_dir_acl && 13786c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o LINUX_S_ISDIR(inode.i_mode)) { 13796c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { 13806c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_dir_acl = 0; 13816c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13826c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13836c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 138421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 13856c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 1386f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (inode_modified) 138708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); 1388f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (!not_fixed && ctx->inode_bad_map) 1389c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); 13903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 13913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 13923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 139350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 139450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/* 139550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * allocate_dir_block --- this function allocates a new directory 139650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * block for a particular inode; this is done if a directory has 139750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * a "hole" in it, or if a directory has a illegal block number 139850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * that was zeroed out and now needs to be replaced. 139950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 14001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 14016dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 1402efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o char *buf EXT2FS_ATTR((unused)), 1403544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 140450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{ 14051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 1406c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson blk64_t blk; 140750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o char *block; 140850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o struct ext2_inode inode; 140950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 14101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) 141150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 141250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 141350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 141450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 141550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * them. 141650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1417f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 1418efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 141950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 142050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * First, find a free block 142150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1422c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson pctx->errcode = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk); 14231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_new_block"; 14251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 142650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 142750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 1428c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); 1429c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_mark_block_bitmap2(fs->block_map, blk); 143050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o ext2fs_mark_bb_dirty(fs); 143150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 143250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 143350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Now let's create the actual data block for the inode 143450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 143550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blockcnt) 14361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); 143750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o else 14381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, db->ino, 14391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o EXT2_ROOT_INO, &block); 144050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 14411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_new_dir_block"; 14431b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 144450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 144550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 144650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 14471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_write_dir_block(fs, blk, block); 1448c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 14491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_write_dir_block"; 14511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 145250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 145350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 145450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 145550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 145650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Update the inode block count 145750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 145808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); 14591ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, &inode, 1); 146050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (inode.i_size < (db->blockcnt+1) * fs->blocksize) 146150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o inode.i_size = (db->blockcnt+1) * fs->blocksize; 146208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); 146350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 146450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 146550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Finally, update the block pointers for the inode 146650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 146750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o db->blk = blk; 14682d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET, 14692d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o db->blockcnt, 0, &blk); 14701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_block_iterate"; 14721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 147350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 147450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 147550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 147650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 147750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o} 1478