pass2.c revision 36769c606c270094df0431cbcab9932905adcedc
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() */ 45d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 4648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#include <string.h> 4748e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 4921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 500926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o#include "dict.h" 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 52aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#ifdef NO_INLINE_FUNCS 53aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ 54aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#else 55aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ inline 56aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#endif 57aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 58ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o/* #define DX_DEBUG */ 598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Keeps track of how many times an inode is referenced. 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 634035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 656dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *dir_blocks_info, 6654dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data); 671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 686dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *dir_blocks_info, 6921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf, struct problem_context *pctx); 708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino); 71ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 72ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db); 73ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b); 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostruct check_dir_struct { 7621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf; 7721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 78f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o int count, max; 791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 80efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o}; 8121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 8208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass2(e2fsck_t ctx) 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 84a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct ext2_super_block *sb = ctx->fs->super; 85a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct problem_context pctx; 86a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2_filsys fs = ctx->fs; 87a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o char *buf; 888bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 908bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 9121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct check_dir_struct cd; 928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db, *dx_parent; 94830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o unsigned int save_type; 95544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int b; 96ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, depth; 978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o problem_t code; 988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o int bad_dir; 998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1006d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o init_resource_track(&rtrack, ctx->fs->io); 1011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&cd.pctx); 1021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 2"); 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 1081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); 1091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 110efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT, 11134b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o &ctx->inode_count); 11234b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o if (ctx->inode_count) 11334b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o cd.pctx.errcode = 0; 114830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o else { 115830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, 116830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o "inode_count", &save_type); 117efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o cd.pctx.errcode = ext2fs_create_icount2(fs, 11834b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o EXT2_ICOUNT_OPT_INCREMENT, 1191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 0, ctx->inode_link_info, 1201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &ctx->inode_count); 121830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o fs->default_bitmap_type = save_type; 122830b44f4385eb255d08fe0c8b200f8d8e3e97a8dTheodore Ts'o } 1231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); 12508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 12608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 12721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 128bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, 12954dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o "directory scan buffer"); 1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 13121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 13221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Set up the parent pointer for the root directory, if 13321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * present. (If the root directory is not present, we will 13421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * create it in pass 3.) 13521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 13628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 13721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 13821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd.buf = buf; 1391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd.ctx = ctx; 140f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o cd.count = 1; 1416dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd.max = ext2fs_dblist_count2(fs->dblist); 142f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o 143f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o if (ctx->progress) 144f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o (void) (ctx->progress)(ctx, 2, 0, cd.max); 145ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 146ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) 1476dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp); 148efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1496dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block, 1506dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson &cd); 15149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) 15208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1536267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger 1546267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger if (ctx->flags & E2F_FLAG_RESTART_LATER) { 1556267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger ctx->flags |= E2F_FLAG_RESTART; 1566267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger return; 1576267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger } 1586267ee49be64035d8a9772c3bafed18a09874fa5Andreas Dilger 1591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); 16108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 16208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1637ac02a5ebddcc6187c893eedc80d92777b399575Theodore Ts'o } 1648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 1668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { 1674cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1684cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return; 16962acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir->numblocks == 0) 1708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_problem_context(&pctx); 1728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir = 0; 1738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.dir = dx_dir->ino; 1748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = dx_dir->dx_block; 1758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) 1768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 1778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else 1788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 1798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * Find all of the first and last leaf blocks, and 1818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * update their parent's min and max hash values 1828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 1848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 1858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 1868fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type != DX_DIRBLOCK_LEAF) || 1878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) 1888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent = &dx_dir->dx_block[dx_db->parent]; 1908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->min_hash > dx_db->min_hash 1928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_FIRST) 1948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->min_hash = dx_db->min_hash; 1958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->max_hash < dx_db->max_hash 1978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_LAST) 1998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->max_hash = dx_db->max_hash; 2008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 201efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 2038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 2048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 2058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blkcount = b; 2068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.group = dx_db->parent; 2078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = 0; 2088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_FIRST) && 2098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->min_hash < dx_db->node_min_hash)) { 2108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->min_hash; 2118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_min_hash; 2128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MIN_HASH; 2138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 216ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (dx_db->type == DX_DIRBLOCK_LEAF) { 217ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth = htree_depth(dx_dir, dx_db); 218ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (depth != dx_dir->depth) { 219e5e12db959d3c18f6cf4ac938a14f68be0a89accAndreas Dilger pctx.num = dx_dir->depth; 220ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o code = PR_2_HTREE_BAD_DEPTH; 221ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(ctx, code, &pctx); 222ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o bad_dir++; 223ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 224ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 2258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 226efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * This test doesn't apply for the root block 2278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * at block #0 2288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 2298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (b && 2308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->max_hash > dx_db->node_max_hash)) { 2318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->max_hash; 2328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_max_hash; 2338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MAX_HASH; 2348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 235503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o bad_dir++; 2368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_REFERENCED)) { 2388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_NOTREF; 2398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if (dx_db->flags & DX_FLAG_DUP_REF) { 2428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_DUPREF; 2438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { 2488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_htree(ctx, dx_dir->ino); 24962acaa1de132a808949d71264731bba7fe095705Theodore Ts'o dx_dir->numblocks = 0; 2508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 25223f75f6efaac6b756e0f3e4e1d33b6798347f66aTheodore Ts'o e2fsck_free_dx_dir_info(ctx); 2538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 254c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 25521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2fs_free_dblist(fs->dblist); 25621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 2571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map) { 2581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_bad_map); 2591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_bad_map = 0; 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 261aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (ctx->inode_reg_map) { 262aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_reg_map); 263aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ctx->inode_reg_map = 0; 264aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 265a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 266a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o clear_problem_context(&pctx); 267a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (ctx->large_files) { 268a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (!(sb->s_feature_ro_compat & 269a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && 270a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { 271a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o sb->s_feature_ro_compat |= 272a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 2730cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 274a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 275a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 276a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (sb->s_rev_level == EXT2_GOOD_OLD_REV && 277a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { 278a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_update_dynamic_rev(fs); 279a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 280a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 281a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 282efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2839facd076ae8af6e908e228392cea866ce0faf1bcKen Chen print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io); 2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 286ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o#define MAX_DEPTH 32000 287ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 288ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db) 289ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o{ 290ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int depth = 0; 291ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 292ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) { 293ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_db = &dx_dir->dx_block[dx_db->parent]; 294ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth++; 295ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 296ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return depth; 297ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o} 298ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 2990926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'ostatic int dict_de_cmp(const void *a, const void *b) 3000926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o{ 301520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o const struct ext2_dir_entry *de_a, *de_b; 3020926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int a_len, b_len; 3030926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 304520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_a = (const struct ext2_dir_entry *) a; 3050926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o a_len = de_a->name_len & 0xFF; 306520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_b = (const struct ext2_dir_entry *) b; 3070926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o b_len = de_b->name_len & 0xFF; 3080926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3090926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (a_len != b_len) 3100926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return (a_len - b_len); 3110926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3120926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return strncmp(de_a->name, de_b->name, a_len); 3130926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o} 314ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 3153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 316ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This is special sort function that makes sure that directory blocks 317ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * with a dirblock of zero are sorted to the beginning of the list. 318ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This guarantees that the root node of the htree directories are 319ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * processed first, so we know what hash version to use. 320ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o */ 321ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b) 322ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{ 3236dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson const struct ext2_db_entry2 *db_a = 3246dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson (const struct ext2_db_entry2 *) a; 3256dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson const struct ext2_db_entry2 *db_b = 3266dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson (const struct ext2_db_entry2 *) b; 327ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 328ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blockcnt && !db_b->blockcnt) 329ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return 1; 330ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 331ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (!db_a->blockcnt && db_b->blockcnt) 332ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return -1; 333efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 334ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blk != db_b->blk) 335ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blk - db_b->blk); 336efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 337ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->ino != db_b->ino) 338ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->ino - db_b->ino); 339ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 340ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blockcnt - db_b->blockcnt); 341ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o} 342ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 343ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 344ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o/* 3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the first entry in the directory is '.', and that the 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. 3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dot(e2fsck_t ctx, 3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 35086c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 3513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *nextdir; 3538a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len, new_len; 3543c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o int status = 0; 3553c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o int created = 0; 3563c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem = 0; 357efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 35821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 35921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT; 360b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o else if (((dirent->name_len & 0xFF) != 1) || 36121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.')) 36221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_1ST_NOT_DOT; 36321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[1] != '\0') 36421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_NULL_TERM; 3655dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o 3668a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); 36721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 3681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 3695dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len < 12) 3705dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o rec_len = dirent->rec_len = 12; 3713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name_len = 1; 3733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 37421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[1] = '\0'; 3753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o created = 1; 3773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->inode != ino) { 3801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { 3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 38321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3855dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len > 12) { 3865dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o new_len = rec_len - 12; 3873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (new_len > 12) { 3883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (created || 389f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { 3903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir = (struct ext2_dir_entry *) 3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ((char *) dirent + 12); 3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->rec_len = 12; 3938a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(ctx->fs, new_len, 3948a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o nextdir); 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->inode = 0; 3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->name_len = 0; 3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return status; 4023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the second entry in the directory is '..', and that the 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. We do not check the inode number of '..' 4073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * here; this gets done in pass 3. 4083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dotdot(e2fsck_t ctx, 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 41128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 4123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4133c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem = 0; 414cf5301d7f2c3bbed3d26600335102414cbf0c4baAndreas Dilger unsigned int rec_len; 415efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 41621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 41721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT_DOT; 418b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o else if (((dirent->name_len & 0xFF) != 2) || 41921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.') || 42021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[1] != '.')) 42121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_2ND_NOT_DOT_DOT; 42221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[2] != '\0') 42321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_DOT_NULL_TERM; 42421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 4258a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); 42621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 4271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 4285dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (rec_len < 12) 42921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->rec_len = 12; 4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Note: we don't have the parent inode just 4323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * yet, so we will fill it in with the root 4333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * inode. This will get fixed in pass 3. 4343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = EXT2_ROOT_INO; 4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name_len = 2; 4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 4383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[1] = '.'; 43921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[2] = '\0'; 4403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 441efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } 4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 44428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) { 44528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, pctx); 44628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o return -1; 44728db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Check to make sure a directory entry doesn't contain any illegal 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * characters. 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_name(e2fsck_t ctx, 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 457efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 458544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 4613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int fixup = -1; 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int ret = 0; 463efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 464b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o for ( i = 0; i < (dirent->name_len & 0xFF); i++) { 4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->name[i] == '/' || dirent->name[i] == '\0') { 4663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fixup < 0) { 4671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); 4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fixup) { 4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[i] = '.'; 4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ret = 1; 47221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ret; 4763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 478aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o/* 479aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * Check the directory filetype (if present) 480aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o */ 481aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'ostatic _INLINE_ int check_filetype(e2fsck_t ctx, 482544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct ext2_dir_entry *dirent, 483544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 484544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 485aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o{ 486aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int filetype = dirent->name_len >> 8; 487aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int should_be = EXT2_FT_UNKNOWN; 488aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o struct ext2_inode inode; 489aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 490aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (!(ctx->fs->super->s_feature_incompat & 4917847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o EXT2_FEATURE_INCOMPAT_FILETYPE)) { 4927847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o if (filetype == 0 || 4937847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) 4947847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 0; 4957847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o dirent->name_len = dirent->name_len & 0xFF; 4967847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 1; 4977847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o } 498aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 499c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) { 500aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_DIR; 501c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, 502aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) { 503aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_REG_FILE; 504aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } else if (ctx->inode_bad_map && 505c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_test_inode_bitmap2(ctx->inode_bad_map, 506aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) 507aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = 0; 508aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o else { 509aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o e2fsck_read_inode(ctx, dirent->inode, &inode, 510aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o "check_filetype"); 5116fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o should_be = ext2_file_type(inode.i_mode); 512aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 513aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (filetype == should_be) 514aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 515aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx->num = should_be; 516aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 517aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, 518aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx) == 0) 519aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 520efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 521aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; 522aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 1; 523aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o} 524aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 5258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 5268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void parse_int_node(ext2_filsys fs, 5276dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 5288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct check_dir_struct *cd, 5298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir, 5308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o char *block_buf) 5318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 5328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_root_info *root; 5338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_entry *ent; 5348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_countlimit *limit; 5358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db; 536ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, expect_limit, count; 5378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o blk_t blk; 5388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t min_hash = 0xffffffff; 5398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t max_hash = 0; 540ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o ext2_dirhash_t hash = 0, prev_hash; 5418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 5438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o root = (struct ext2_dx_root_info *) (block_buf + 24); 544efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Root node dump:\n"); 5478deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("\t Reserved zero: %u\n", root->reserved_zero); 5488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Hash Version: %d\n", root->hash_version); 5498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Info length: %d\n", root->info_length); 5508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Indirect levels: %d\n", root->indirect_levels); 5518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Flags: %d\n", root->unused_flags); 5528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); 5558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 5568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf+8); 5578fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 5588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 5598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 561efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o printf("Number of entries (count): %d\n", 5628132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->count)); 563efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o printf("Number of entries (limit): %d\n", 5648132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->limit)); 5658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5668fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5678132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o count = ext2fs_le16_to_cpu(limit->count); 568ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o expect_limit = (fs->blocksize - ((char *) ent - block_buf)) / 569ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o sizeof(struct ext2_dx_entry); 5708132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { 5718132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); 572ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) 573ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 574ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 5758132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (count > expect_limit) { 5768132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = count; 577ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) 578ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 579ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o count = expect_limit; 580ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 581efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 582ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o for (i=0; i < count; i++) { 583ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o prev_hash = hash; 5848132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; 5858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5868deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("Entry #%d: Hash 0x%08x, block %u\n", i, 5878132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash, ext2fs_le32_to_cpu(ent[i].block)); 5888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5898132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; 5908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* Check to make sure the block is valid */ 591977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o if (blk >= (blk_t) dx_dir->numblocks) { 592b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.blk = blk; 5938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, 594ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o &cd->pctx)) 595ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 596977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o continue; 5978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 598ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (hash < prev_hash && 599ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx)) 600ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 6018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[blk]; 6028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) { 6038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 6048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 6058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 6068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->parent = db->blockcnt; 6078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < min_hash) 6098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o min_hash = hash; 6108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > max_hash) 6118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o max_hash = hash; 6128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_min_hash = hash; 6138132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if ((i+1) < count) 614efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o dx_db->node_max_hash = 6158132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; 6168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else { 6178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_max_hash = 0xfffffffe; 6188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_LAST; 6198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (i == 0) 6218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST; 6228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 6248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n", 6258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, min_hash, max_hash); 6268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 6278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 6288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = min_hash; 6298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = max_hash; 630ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 631ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 632ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'oclear_and_exit: 633ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o clear_htree(cd->ctx, cd->pctx.ino); 634ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->numblocks = 0; 6358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 6368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 637aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 638e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o/* 639e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Given a busted directory, try to salvage it somehow. 640efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 641e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 642ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic void salvage_directory(ext2_filsys fs, 643e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, 644e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *prev, 645544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int *offset) 646e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o{ 647e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o char *cp = (char *) dirent; 6488a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o int left; 6498a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o unsigned int rec_len, prev_rec_len; 650642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o unsigned int name_len = dirent->name_len & 0xFF; 651e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 6528a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 6535dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o left = fs->blocksize - *offset - rec_len; 6545dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o 655e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 656e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Special case of directory entry of size 8: copy what's left 657e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * of the directory block up to cover up the invalid hole. 658e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 6595dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if ((left >= 12) && (rec_len == 8)) { 660e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o memmove(cp, cp+8, left); 661e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o memset(cp + left, 0, 8); 662ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 663ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 664ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o /* 665ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * If the directory entry overruns the end of the directory 666ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * block, and the name is small enough to fit, then adjust the 667ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * record length. 668ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o */ 669ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if ((left < 0) && 6708a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o ((int) rec_len + left > 8) && 67168477355a9f3b4ca46dfa6c34d05105dcc6682adTheodore Ts'o ((int) name_len + 8 <= (int) rec_len + left) && 672ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dirent->inode <= fs->super->s_inodes_count && 673ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o strnlen(dirent->name, name_len) == name_len) { 6748a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent); 675ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 676e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 677e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 678575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * If the record length of the directory entry is a multiple 679575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * of four, and not too big, such that it is valid, let the 680575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah * previous directory entry absorb the invalid one. 681e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 6825dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (prev && rec_len && (rec_len % 4) == 0 && 6835dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (*offset + rec_len <= fs->blocksize)) { 6848a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); 6858a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o prev_rec_len += rec_len; 6868a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); 6875dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o *offset += rec_len; 688ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 689e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 690e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 691e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Default salvage method --- kill all of the directory 692e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * entries for the rest of the block. We will either try to 693e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * absorb it into the previous directory entry, or create a 694e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * new empty directory entry the rest of the directory block. 695e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 696e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (prev) { 6978a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); 6988a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o prev_rec_len += fs->blocksize - *offset; 6998a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); 700ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o *offset = fs->blocksize; 701e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else { 7028a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o rec_len = fs->blocksize - *offset; 7038a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_set_rec_len(fs, rec_len, dirent); 704e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->name_len = 0; 705e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->inode = 0; 706e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 707e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o} 708e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 7093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 7106dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 71154dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 7123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 7138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 7148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 7158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db = 0; 7168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 717e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, *prev; 7188fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t hash; 719544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 7203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dir_modified = 0; 72121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int dot_state; 72203fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o unsigned int rec_len; 7236dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t block_nr = db->blk; 72486c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino = db->ino; 72528db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t subdir_parent; 72621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o __u16 links; 72754dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct check_dir_struct *cd; 7281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o char *buf; 7291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 7303c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem; 731ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o struct ext2_dx_root_info *root; 732e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o struct ext2_dx_countlimit *limit; 7330926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o static dict_t de_dict; 7340926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o struct problem_context pctx; 7350926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int dups_found = 0; 73628db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o int ret; 7371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 73854dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o cd = (struct check_dir_struct *) priv_data; 7391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o buf = cd->buf; 7401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx = cd->ctx; 741f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 74249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) 7434cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 744efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7454cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) 7464cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 747efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 749efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Make sure the inode is still in use (could have been 7503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * deleted in the duplicate/bad blocks pass. 7513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 752c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino))) 7533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 75450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 75521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino = ino; 75621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blk = block_nr; 75721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blkcount = db->blockcnt; 75821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 75921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = 0; 76021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = 0; 76121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 76250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blk == 0) { 7631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (allocate_dir_block(ctx, db, buf, &cd->pctx)) 76450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 76550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o block_nr = db->blk; 76650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 767efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 7683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (db->blockcnt) 7693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 2; 7703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 7713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 0; 7723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7730926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (ctx->dirs_to_hash && 7740926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_test(ctx->dirs_to_hash, ino)) 7750926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 7760926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 7773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 778f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr, 7793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o db->blockcnt, ino); 7803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 781efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 782f85a9ae6397ff074193322a12ed721dbf5751e41Eric Sandeen ehandler_operation(_("reading directory block")); 7836dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson cd->pctx.errcode = ext2fs_read_dir_block3(fs, block_nr, buf, 0); 784e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o ehandler_operation(0); 785b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) 786b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o cd->pctx.errcode = 0; /* We'll handle this ourselves */ 7871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 78808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { 78908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 79008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 79108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o } 7921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o memset(buf, 0, fs->blocksize); 7933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 7958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_dir = e2fsck_get_dx_dir_info(ctx, ino); 79662acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir && dx_dir->numblocks) { 7978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt >= dx_dir->numblocks) { 798ea9085c711e92c3727538a0637bc805141333d83Darrick J. Wong pctx.dir = ino; 799efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK, 800d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o &pctx)) { 801d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o clear_htree(ctx, ino); 802d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o dx_dir->numblocks = 0; 803d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o dx_db = 0; 804d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o goto out_htree; 805d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o } 806d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'o fatal_error(ctx, _("Can not continue.")); 8078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 8088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 8098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_LEAF; 8108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->phys = block_nr; 8118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = ~0; 8128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = 0; 813efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 8148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dirent = (struct ext2_dir_entry *) buf; 8158a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 816e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o limit = (struct ext2_dx_countlimit *) (buf+8); 8178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 818ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root = (struct ext2_dx_root_info *) (buf + 24); 8198fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_ROOT; 8208fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; 821ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if ((root->reserved_zero || 822ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->info_length < 8 || 823ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->indirect_levels > 1) && 824ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { 825ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o clear_htree(ctx, ino); 826ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->numblocks = 0; 827ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_db = 0; 828f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o } 829ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->hashversion = root->hash_version; 830f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((dx_dir->hashversion <= EXT2_HASH_TEA) && 831f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 832f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o dx_dir->hashversion += 3; 833ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->depth = root->indirect_levels + 1; 8348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if ((dirent->inode == 0) && 8355dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len == fs->blocksize) && 836e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o (dirent->name_len == 0) && 837efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (ext2fs_le16_to_cpu(limit->limit) == 838efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o ((fs->blocksize-8) / 8398132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o sizeof(struct ext2_dx_entry)))) 8408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_NODE; 8418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 842d45edec0fb2e5d100d122fdda0914560c64def44Theodore Ts'oout_htree: 8438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 8443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8450926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp); 846e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = 0; 8473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o do { 8483971bfe878d6c30f9b5be3a2c0310943982a4775Theodore Ts'o dgrp_t group; 84949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos ext2_ino_t first_unused_inode; 85049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos 8511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = 0; 8523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 8538a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o (void) ext2fs_get_rec_len(fs, dirent, &rec_len); 85421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = dirent; 85521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = offset; 8565dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o if (((offset + rec_len) > fs->blocksize) || 8575dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o (rec_len < 12) || 8585dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o ((rec_len % 4) != 0) || 85903fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) { 8601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { 861ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o salvage_directory(fs, dirent, prev, &offset); 8623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 863e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o continue; 86421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } else 8650926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 8663839e65723771b85975f4263102dd3ceec4523cTheodore 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) { 11367bef6d52125ef3f1ef07d9da71a13546f6843c56Kit Westneat cd->pctx.errcode = ext2fs_write_dir_block3(fs, block_nr, buf, 0); 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 1152624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kalistruct del_block { 1153624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali e2fsck_t ctx; 1154624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali e2_blkcnt_t num; 1155624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali}; 1156624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali 11573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 11583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This function is called to deallocate a block, and is an interator 11593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * functioned called by deallocate inode via ext2fs_iterate_block(). 11603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 11613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int deallocate_inode_block(ext2_filsys fs, 11626dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t *block_nr, 1163544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 11646dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson blk64_t ref_block EXT2FS_ATTR((unused)), 1165544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 1166133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o void *priv_data) 11673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1168624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali struct del_block *p = priv_data; 1169efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11701917875fcd16428d14eb5a86acf414472bc216f1Theodore Ts'o if (HOLE_BLKADDR(*block_nr)) 11713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 11721ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o if ((*block_nr < fs->super->s_first_data_block) || 11734efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson (*block_nr >= ext2fs_blocks_count(fs->super))) 11741ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o return 0; 11758dd650ab9ac394c6d6d19b02e8bb22d5a1e5da0dDarrick J. Wong if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0) 11768dd650ab9ac394c6d6d19b02e8bb22d5a1e5da0dDarrick J. Wong ext2fs_block_alloc_stats2(fs, *block_nr, -1); 1177624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali p->num++; 11783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 11793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1180efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 11823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This fuction deallocates an inode 11833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 11844035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) 11853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 11861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 11873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 11881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 11890684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o __u32 count; 1190624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali struct del_block del_block; 1191efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 119208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 11931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 11941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.ino = ino; 1195f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 11963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 11973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Fix up the bitmaps... 11983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1199f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 12000684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); 12010684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o 12020c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (ext2fs_file_acl_block(fs, &inode) && 12030684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 12040c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o pctx.errcode = ext2fs_adjust_ea_refcount2(fs, 12050c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block(fs, &inode), 12060c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o block_buf, -1, &count); 12070684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { 12080684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o pctx.errcode = 0; 12090684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o count = 1; 12100684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12110684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode) { 12120c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o pctx.blk = ext2fs_file_acl_block(fs, &inode); 12130684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); 12140684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 12150684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o return; 12160684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12170684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (count == 0) { 121848f23054bb8ad0506c0baa9f06ba182acc2aa88bValerie Aurora Henson ext2fs_block_alloc_stats2(fs, 12190c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block(fs, &inode), -1); 12200684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12210c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block_set(fs, &inode, 0); 12220684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 12233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 12240c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) 1225c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o goto clear_inode; 1226a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 12273b6c0938ec5aa401c7ae6c95e94e5ad30a7b8562Darrick J. Wong if (LINUX_S_ISREG(inode.i_mode) && 12283b6c0938ec5aa401c7ae6c95e94e5ad30a7b8562Darrick J. Wong ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode))) 1229a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ctx->large_files--; 1230a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 1231624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali del_block.ctx = ctx; 1232624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali del_block.num = 0; 12336dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, 1234624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali deallocate_inode_block, 1235624e4a6466dba9889f5f80dc168f2bb7c2a3f5d0Aditya Kali &del_block); 12361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 12371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); 123808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 123908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 12401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 1241c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'oclear_inode: 1242c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o /* Inode may have changed by block_iterate, so reread it */ 1243c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 1244c8ec2bad18fdaa842f786f3b37c9320a3411aea3Theodore Ts'o e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); 12453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 12463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 12478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o/* 12488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This fuction clears the htree flag on an inode 12498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 12508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino) 12518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 12528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_inode inode; 1253efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 12548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); 12558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; 12568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); 1257b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (ctx->dirs_to_hash) 1258b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 12598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 12608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 12618fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1262f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'oint e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, 1263f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'o ext2_ino_t ino, char *buf) 12643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 12651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 12663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 12673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int inode_modified = 0; 12686c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o int not_fixed = 0; 12691e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o unsigned char *frag, *fsize; 127021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 12713c7c6d73f1a0bd45835966f1179fc3e8236a7d9cTheodore Ts'o problem_t problem = 0; 12723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 127308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); 127421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 127521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o clear_problem_context(&pctx); 127621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.ino = ino; 127721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.dir = dir; 127821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.inode = &inode; 127921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 12800c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (ext2fs_file_acl_block(fs, &inode) && 1281f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 1282f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { 12830c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block_set(fs, &inode, 0); 1284f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o inode_modified++; 1285f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } else 1286f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o not_fixed++; 1287f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } 12886c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 128950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && 129050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && 129150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && 129208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o !(LINUX_S_ISSOCK(inode.i_mode))) 129308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_MODE; 1294fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISCHR(inode.i_mode) 12950684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 129608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_CHAR_DEV; 1297fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISBLK(inode.i_mode) 12980684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 129908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_BLOCK_DEV; 1300fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISFIFO(inode.i_mode) 13010684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 13021dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_FIFO; 1303fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISSOCK(inode.i_mode) 13040684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 13051dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_SOCKET; 1306fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISLNK(inode.i_mode) 13077cadc57780f3e3e8e644e8976e11a336902d4a25Theodore Ts'o && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) { 1308bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o problem = PR_2_INVALID_SYMLINK; 130967052a8aeeca8cd80d1dd33c2792f917573accc8Andreas Dilger } 13101dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o 131108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (problem) { 131208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (fix_problem(ctx, problem, &pctx)) { 13131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o deallocate_inode(ctx, ino, 0); 1314a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 131508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return 0; 13167cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o return 1; 13176c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13186c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 131908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = 0; 13207cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o } 1321efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 13226c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (inode.i_faddr) { 13236c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { 13246c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_faddr = 0; 13256c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13266c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13276c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 13283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 13291e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 13301e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o switch (fs->super->s_creator_os) { 13311e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o case EXT2_OS_HURD: 13321e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = &inode.osd2.hurd2.h_i_frag; 13331e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o fsize = &inode.osd2.hurd2.h_i_fsize; 13341e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o break; 13351e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o default: 13361e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = fsize = 0; 13371e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o } 133821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (frag && *frag) { 133921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *frag; 13401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { 134121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *frag = 0; 134221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 13437e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o } else 13447e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o not_fixed++; 134521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 134621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 134721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (fsize && *fsize) { 134821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *fsize; 13491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { 135021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *fsize = 0; 135121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 13526c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13536c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 135421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 135521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 135621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 13575d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if ((fs->super->s_creator_os == EXT2_OS_LINUX) && 1358efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o !(fs->super->s_feature_ro_compat & 13595d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && 13605d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o (inode.osd2.linux2.l_i_blocks_hi != 0)) { 13615d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_blocks_hi; 13625d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { 13635d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode.osd2.linux2.l_i_blocks_hi = 0; 13645d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode_modified++; 13655d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 13665d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 13675d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o 136836769c606c270094df0431cbcab9932905adcedcJustus Winter if ((fs->super->s_creator_os == EXT2_OS_LINUX) && 136936769c606c270094df0431cbcab9932905adcedcJustus Winter !(fs->super->s_feature_incompat & 1370911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o EXT4_FEATURE_INCOMPAT_64BIT) && 1371911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode.osd2.linux2.l_i_file_acl_high != 0) { 1372911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_file_acl_high; 1373911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) { 1374911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode.osd2.linux2.l_i_file_acl_high = 0; 1375911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o inode_modified++; 1376911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o } else 1377911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o not_fixed++; 1378911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o } 1379911ec6261568ca56d2d7b9a15f00578c4d127cf4Theodore Ts'o 13800c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o if (ext2fs_file_acl_block(fs, &inode) && 13810c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) || 13820c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) { 13836c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { 13840c80c44bd08c60f3cd0ad87f12a71a75cac3bcaaTheodore Ts'o ext2fs_file_acl_block_set(fs, &inode, 0); 13856c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13866c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13876c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 1388342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o } 138921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (inode.i_dir_acl && 13906c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o LINUX_S_ISDIR(inode.i_mode)) { 13916c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { 13926c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_dir_acl = 0; 13936c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13946c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13956c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 139621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 13976c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 1398f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (inode_modified) 139908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); 1400f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (!not_fixed && ctx->inode_bad_map) 1401c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); 14023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 14033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 14043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 140550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 140650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/* 140750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * allocate_dir_block --- this function allocates a new directory 140850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * block for a particular inode; this is done if a directory has 140950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * a "hole" in it, or if a directory has a illegal block number 141050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * that was zeroed out and now needs to be replaced. 141150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 14121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 14136dc64392c052839f373b7bbbb58efa3048bfb355Valerie Aurora Henson struct ext2_db_entry2 *db, 1414efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o char *buf EXT2FS_ATTR((unused)), 1415544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 141650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{ 14171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 1418ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong blk64_t blk = 0; 141950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o char *block; 142050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o struct ext2_inode inode; 142150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 14221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) 142350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 142450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 142550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 142650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 142750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * them. 142850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1429f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 1430efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 143150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 143250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * First, find a free block 143350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1434ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); 1435ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong pctx->errcode = ext2fs_map_cluster_block(fs, db->ino, &inode, 1436ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong db->blockcnt, &blk); 1437ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong if (pctx->errcode || blk == 0) { 1438ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong pctx->errcode = ext2fs_new_block2(fs, 0, 1439ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong ctx->block_found_map, &blk); 1440ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong if (pctx->errcode) { 1441ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong pctx->str = "ext2fs_new_block"; 1442ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 1443ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong return 1; 1444ff11309ecc24fae663a4d65947b24c371a04a5c7Darrick J. Wong } 144550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 1446c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); 1447c5d2f50dee996e48e96066155f85d7c925fcba0dValerie Aurora Henson ext2fs_mark_block_bitmap2(fs->block_map, blk); 144850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o ext2fs_mark_bb_dirty(fs); 144950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 145050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 145150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Now let's create the actual data block for the inode 145250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 145350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blockcnt) 14541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); 145550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o else 14561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, db->ino, 14571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o EXT2_ROOT_INO, &block); 145850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 14591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_new_dir_block"; 14611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 146250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 146350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 146450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 14657bef6d52125ef3f1ef07d9da71a13546f6843c56Kit Westneat pctx->errcode = ext2fs_write_dir_block3(fs, blk, block, 0); 1466c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 14671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_write_dir_block"; 14691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 147050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 147150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 147250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 147350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 147450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Update the inode block count 147550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 14761ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, &inode, 1); 147797c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong if (EXT2_I_SIZE(&inode) < (db->blockcnt+1) * fs->blocksize) { 147897c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong pctx->errcode = ext2fs_inode_size_set(fs, &inode, 147997c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong (db->blockcnt+1) * fs->blocksize); 148097c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong if (pctx->errcode) { 148197c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong pctx->str = "ext2fs_inode_size_set"; 148297c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 148397c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong return 1; 148497c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong } 148597c607b1a25e1f4e83bf246c76b679d91470f5dcDarrick J. Wong } 148608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); 148750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 148850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 148950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Finally, update the block pointers for the inode 149050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 149150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o db->blk = blk; 14922d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET, 14932d07b3ad98bfe1db5fb1071f53a5338ab6c35522Theodore Ts'o db->blockcnt, 0, &blk); 14941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 14951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_block_iterate"; 14961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 149750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 149850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 149950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 150050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 150150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o} 1502