pass2.c revision 6d96b00d57d236e2746f8245df6c8ea64abc64c1
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass2.c --- check directory structure 33839e65723771b85975f4263102dd3ceec4523cTheodore 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% 103839e65723771b85975f4263102dd3ceec4523cTheodore 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) 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * should be less than (rec_len - 8). 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode number in the directory entry should be within 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * legal bounds. 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode number should refer to a in-use inode. 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The first entry should be '.', and its inode should be 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * the inode of the directory. 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The second entry should be '..'. 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * To minimize disk seek time, the directory blocks are processed in 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * sorted order of block numbers. 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 also collects the following information: 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode numbers of the subdirectories for each directory. 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 relies on the following information from previous passes: 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The directory information collected in pass 1. 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_used_map bitmap 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_bad_map bitmap 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_dir_map bitmap 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 2 frees the following data structures 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The inode_bad_map bitmap 41aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * - The inode_reg_map bitmap 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 44b969b1b8a5c13992cadb026114731958644540d8Matthias Andree#define _GNU_SOURCE 1 /* get strnlen() */ 4548e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#include <string.h> 4648e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 4821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 490926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o#include "dict.h" 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 51aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#ifdef NO_INLINE_FUNCS 52aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ 53aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#else 54aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#define _INLINE_ inline 55aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o#endif 56aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 57ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o/* #define DX_DEBUG */ 588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Keeps track of how many times an inode is referenced. 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 624035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 6421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct ext2_db_entry *dir_blocks_info, 6554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data); 661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 6721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct ext2_db_entry *dir_blocks_info, 6821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf, struct problem_context *pctx); 6950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'ostatic int update_dir_block(ext2_filsys fs, 7050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o blk_t *block_nr, 71133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o e2_blkcnt_t blockcnt, 724035f40bc4550ce7520724cc837992a700794e00Theodore Ts'o blk_t ref_block, 734035f40bc4550ce7520724cc837992a700794e00Theodore Ts'o int ref_offset, 744035f40bc4550ce7520724cc837992a700794e00Theodore Ts'o void *priv_data); 758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino); 76ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 77ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db); 78ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b); 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostruct check_dir_struct { 8121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o char *buf; 8221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 83f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o int count, max; 841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 8521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o}; 8621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 8708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass2(e2fsck_t ctx) 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 89a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct ext2_super_block *sb = ctx->fs->super; 90a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o struct problem_context pctx; 91a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2_filsys fs = ctx->fs; 92a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o char *buf; 938bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 958bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 9621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct check_dir_struct cd; 978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db, *dx_parent; 99544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int b; 100ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, depth; 1018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o problem_t code; 1028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o int bad_dir; 1038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1048bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 1056d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o init_resource_track(&rtrack, ctx->fs->io); 1068bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&cd.pctx); 1091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 2"); 1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1141b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 1151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); 1161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 11734b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT, 11834b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o &ctx->inode_count); 11934b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o if (ctx->inode_count) 12034b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o cd.pctx.errcode = 0; 12134b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o else 12234b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o cd.pctx.errcode = ext2fs_create_icount2(fs, 12334b9f7963933daeb1c3fb3f21a70a1673d098154Theodore Ts'o EXT2_ICOUNT_OPT_INCREMENT, 1241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 0, ctx->inode_link_info, 1251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &ctx->inode_count); 1261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); 12808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 12908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 13021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 131bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, 13254dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o "directory scan buffer"); 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 13421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 13521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Set up the parent pointer for the root directory, if 13621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * present. (If the root directory is not present, we will 13721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * create it in pass 3.) 13821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o */ 13928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 14021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 14121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd.buf = buf; 1421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd.ctx = ctx; 143f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o cd.count = 1; 144f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o cd.max = ext2fs_dblist_count(fs->dblist); 145f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o 146f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o if (ctx->progress) 147f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o (void) (ctx->progress)(ctx, 2, 0, cd.max); 148ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 149ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) 150ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp); 15121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 1521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block, 1531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &cd); 154a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 15508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd.pctx.errcode) { 1571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); 15808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 15908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1607ac02a5ebddcc6187c893eedc80d92777b399575Theodore Ts'o } 1618fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1628fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 1638fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { 1644cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1654cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return; 16662acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir->numblocks == 0) 1678fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_problem_context(&pctx); 1698fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir = 0; 1708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.dir = dx_dir->ino; 1718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = dx_dir->dx_block; 1728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) 1738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 1748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else 1758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 1768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * Find all of the first and last leaf blocks, and 1788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * update their parent's min and max hash values 1798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 1818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 1828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 1838fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type != DX_DIRBLOCK_LEAF) || 1848fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) 1858fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 1868fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent = &dx_dir->dx_block[dx_db->parent]; 1878fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1888fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->min_hash > dx_db->min_hash 1898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_FIRST) 1918fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->min_hash = dx_db->min_hash; 1928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 1938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * XXX Make sure dx_parent->max_hash < dx_db->max_hash 1948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 1958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_LAST) 1968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_parent->max_hash = dx_db->max_hash; 1978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 1988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 1998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o for (b=0, dx_db = dx_dir->dx_block; 2008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b < dx_dir->numblocks; 2018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o b++, dx_db++) { 2028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blkcount = b; 2038fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.group = dx_db->parent; 2048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = 0; 2058fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_FIRST) && 2068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->min_hash < dx_db->node_min_hash)) { 2078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->min_hash; 2088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_min_hash; 2098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MIN_HASH; 2108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 213ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (dx_db->type == DX_DIRBLOCK_LEAF) { 214ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth = htree_depth(dx_dir, dx_db); 215ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (depth != dx_dir->depth) { 216ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o code = PR_2_HTREE_BAD_DEPTH; 217ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(ctx, code, &pctx); 218ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o bad_dir++; 219ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 220ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 2218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* 2228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This test doesn't apply for the root block 2238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * at block #0 2248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 2258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (b && 2268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->max_hash > dx_db->node_max_hash)) { 2278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk = dx_db->max_hash; 2288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o pctx.blk2 = dx_db->node_max_hash; 2298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_MAX_HASH; 2308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 231503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o bad_dir++; 2328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (!(dx_db->flags & DX_FLAG_REFERENCED)) { 2348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_NOTREF; 2358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if (dx_db->flags & DX_FLAG_DUP_REF) { 2388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o code = PR_2_HTREE_DUPREF; 2398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o fix_problem(ctx, code, &pctx); 2408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o bad_dir++; 2418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (code == 0) 2438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o continue; 2448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { 2468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o clear_htree(ctx, dx_dir->ino); 24762acaa1de132a808949d71264731bba7fe095705Theodore Ts'o dx_dir->numblocks = 0; 2488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 2508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 251c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 25221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ext2fs_free_dblist(fs->dblist); 25321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 2541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map) { 2551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_bad_map); 2561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_bad_map = 0; 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 258aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (ctx->inode_reg_map) { 259aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ext2fs_free_inode_bitmap(ctx->inode_reg_map); 260aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ctx->inode_reg_map = 0; 261aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 262a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 263a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o clear_problem_context(&pctx); 264a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (ctx->large_files) { 265a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (!(sb->s_feature_ro_compat & 266a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && 267a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { 268a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o sb->s_feature_ro_compat |= 269a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 270a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 271a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 272a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (sb->s_rev_level == EXT2_GOOD_OLD_REV && 273a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { 274a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_update_dynamic_rev(fs); 275a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 276a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 277a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } else if (!ctx->large_files && 278a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o (sb->s_feature_ro_compat & 279a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { 280a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o if (fs->flags & EXT2_FLAG_RW) { 281a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o sb->s_feature_ro_compat &= 282a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 283a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ext2fs_mark_super_dirty(fs); 284a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 285a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o } 286a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 2878bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 2885596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o if (ctx->options & E2F_OPT_TIME2) { 2895596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o e2fsck_clear_progbar(ctx); 2906d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o print_resource_track(_("Pass 2"), &rtrack, fs->io); 2915596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o } 2928bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 295ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o#define MAX_DEPTH 32000 296ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic int htree_depth(struct dx_dir_info *dx_dir, 297ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o struct dx_dirblock_info *dx_db) 298ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o{ 299ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int depth = 0; 300ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 301ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) { 302ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_db = &dx_dir->dx_block[dx_db->parent]; 303ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o depth++; 304ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 305ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return depth; 306ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o} 307ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 3080926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'ostatic int dict_de_cmp(const void *a, const void *b) 3090926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o{ 310520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o const struct ext2_dir_entry *de_a, *de_b; 3110926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int a_len, b_len; 3120926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 313520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_a = (const struct ext2_dir_entry *) a; 3140926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o a_len = de_a->name_len & 0xFF; 315520ead378ec5ddef828a8d206434cc3a444b2e9eTheodore Ts'o de_b = (const struct ext2_dir_entry *) b; 3160926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o b_len = de_b->name_len & 0xFF; 3170926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3180926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (a_len != b_len) 3190926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return (a_len - b_len); 3200926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 3210926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return strncmp(de_a->name, de_b->name, a_len); 3220926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o} 323ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 325ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This is special sort function that makes sure that directory blocks 326ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * with a dirblock of zero are sorted to the beginning of the list. 327ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * This guarantees that the root node of the htree directories are 328ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o * processed first, so we know what hash version to use. 329ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o */ 330ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'ostatic EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b) 331ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o{ 332ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o const struct ext2_db_entry *db_a = 333ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o (const struct ext2_db_entry *) a; 334ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o const struct ext2_db_entry *db_b = 335ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o (const struct ext2_db_entry *) b; 336ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 337ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blockcnt && !db_b->blockcnt) 338ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return 1; 339ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 340ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (!db_a->blockcnt && db_b->blockcnt) 341ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return -1; 342ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 343ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->blk != db_b->blk) 344ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blk - db_b->blk); 345ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 346ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if (db_a->ino != db_b->ino) 347ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->ino - db_b->ino); 348ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 349ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o return (int) (db_a->blockcnt - db_b->blockcnt); 350ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o} 351ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 352ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o 353ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o/* 3543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the first entry in the directory is '.', and that the 3553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. 3563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dot(e2fsck_t ctx, 3583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 35986c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 3603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *nextdir; 3623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int status = 0; 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int created = 0; 3643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int new_len; 36521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int problem = 0; 3663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 36721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 36821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT; 369b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o else if (((dirent->name_len & 0xFF) != 1) || 37021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.')) 37121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_1ST_NOT_DOT; 37221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[1] != '\0') 37321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_NULL_TERM; 37421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 37521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 3761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 37721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (dirent->rec_len < 12) 37821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->rec_len = 12; 3793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 3803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name_len = 1; 3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 38221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[1] = '\0'; 3833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o created = 1; 3853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->inode != ino) { 3881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = ino; 3903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 39121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->rec_len > 12) { 3943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o new_len = dirent->rec_len - 12; 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (new_len > 12) { 3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (created || 397f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { 3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir = (struct ext2_dir_entry *) 3993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ((char *) dirent + 12); 4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->rec_len = 12; 4013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->rec_len = new_len; 4023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->inode = 0; 4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o nextdir->name_len = 0; 4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o status = 1; 4053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return status; 4093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the second entry in the directory is '..', and that the 4133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory entry is sane. We do not check the inode number of '..' 4143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * here; this gets done in pass 3. 4153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_dotdot(e2fsck_t ctx, 4173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 41828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t ino, struct problem_context *pctx) 4193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 42028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o int problem = 0; 4213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 42221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!dirent->inode) 42321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_MISSING_DOT_DOT; 424b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o else if (((dirent->name_len & 0xFF) != 2) || 42521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[0] != '.') || 42621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o (dirent->name[1] != '.')) 42721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_2ND_NOT_DOT_DOT; 42821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o else if (dirent->name[2] != '\0') 42921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o problem = PR_2_DOT_DOT_NULL_TERM; 43021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 43121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (problem) { 4321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, pctx)) { 43321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (dirent->rec_len < 12) 43421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->rec_len = 12; 4353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Note: we don't have the parent inode just 4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * yet, so we will fill it in with the root 4383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * inode. This will get fixed in pass 3. 4393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = EXT2_ROOT_INO; 4413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name_len = 2; 4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[0] = '.'; 4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[1] = '.'; 44421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->name[2] = '\0'; 4453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 44621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 4473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 44928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) { 45028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, pctx); 45128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o return -1; 45228db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Check to make sure a directory entry doesn't contain any illegal 4583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * characters. 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int check_name(e2fsck_t ctx, 4613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_dir_entry *dirent, 462544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 463544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 4643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 4663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int fixup = -1; 4673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int ret = 0; 4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 469b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o for ( i = 0; i < (dirent->name_len & 0xFF); i++) { 4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dirent->name[i] == '/' || dirent->name[i] == '\0') { 4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fixup < 0) { 4721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); 4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fixup) { 4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->name[i] = '.'; 4763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ret = 1; 47721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 4783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ret; 4813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 483aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o/* 484aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o * Check the directory filetype (if present) 485aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o */ 486aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'ostatic _INLINE_ int check_filetype(e2fsck_t ctx, 487544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct ext2_dir_entry *dirent, 488544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_ino_t dir_ino EXT2FS_ATTR((unused)), 489544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 490aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o{ 491aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int filetype = dirent->name_len >> 8; 492aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o int should_be = EXT2_FT_UNKNOWN; 493aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o struct ext2_inode inode; 494aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 495aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (!(ctx->fs->super->s_feature_incompat & 4967847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o EXT2_FEATURE_INCOMPAT_FILETYPE)) { 4977847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o if (filetype == 0 || 4987847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) 4997847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 0; 5007847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o dirent->name_len = dirent->name_len & 0xFF; 5017847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o return 1; 5027847c1d4fff9195c16b6d74194d104200b3f6c67Theodore Ts'o } 503aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 504aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) { 505aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_DIR; 506aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map, 507aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) { 508aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = EXT2_FT_REG_FILE; 509aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } else if (ctx->inode_bad_map && 510aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o ext2fs_test_inode_bitmap(ctx->inode_bad_map, 511aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->inode)) 512aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o should_be = 0; 513aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o else { 514aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o e2fsck_read_inode(ctx, dirent->inode, &inode, 515aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o "check_filetype"); 5166fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o should_be = ext2_file_type(inode.i_mode); 517aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o } 518aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (filetype == should_be) 519aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 520aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx->num = should_be; 521aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 522aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, 523aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o pctx) == 0) 524aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 0; 525aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 526aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; 527aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o return 1; 528aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o} 529aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 5308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 5318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void parse_int_node(ext2_filsys fs, 5328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_db_entry *db, 5338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct check_dir_struct *cd, 5348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir, 5358fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o char *block_buf) 5368fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 5378fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_root_info *root; 5388fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_entry *ent; 5398fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_dx_countlimit *limit; 5408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db; 541ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int i, expect_limit, count; 5428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o blk_t blk; 5438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t min_hash = 0xffffffff; 5448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t max_hash = 0; 545ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o ext2_dirhash_t hash = 0, prev_hash; 5468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 5488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o root = (struct ext2_dx_root_info *) (block_buf + 24); 5498fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Root node dump:\n"); 5528deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("\t Reserved zero: %u\n", root->reserved_zero); 5538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Hash Version: %d\n", root->hash_version); 5548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Info length: %d\n", root->info_length); 5558fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Indirect levels: %d\n", root->indirect_levels); 5568fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("\t Flags: %d\n", root->unused_flags); 5578fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5588fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5598fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); 5608fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 5618fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ent = (struct ext2_dx_entry *) (block_buf+8); 5628fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 5638fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o limit = (struct ext2_dx_countlimit *) ent; 5648fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5658fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5668132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o printf("Number of entries (count): %d\n", 5678132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->count)); 5688132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o printf("Number of entries (limit): %d\n", 5698132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le16_to_cpu(limit->limit)); 5708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 5728132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o count = ext2fs_le16_to_cpu(limit->count); 573ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o expect_limit = (fs->blocksize - ((char *) ent - block_buf)) / 574ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o sizeof(struct ext2_dx_entry); 5758132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { 5768132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); 577ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) 578ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 579ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 5808132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if (count > expect_limit) { 5818132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o cd->pctx.num = count; 582ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) 583ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 584ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o count = expect_limit; 585ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 586ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 587ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o for (i=0; i < count; i++) { 588ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o prev_hash = hash; 5898132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; 5908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 5918deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato printf("Entry #%d: Hash 0x%08x, block %u\n", i, 5928132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o hash, ext2fs_le32_to_cpu(ent[i].block)); 5938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 5948132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; 5958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o /* Check to make sure the block is valid */ 596977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o if (blk >= (blk_t) dx_dir->numblocks) { 597b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.blk = blk; 5988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, 599ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o &cd->pctx)) 600ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 601977ac8731bf3bd934421dd8107e77325ec7e6de7Theodore Ts'o continue; 6028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 603ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if (hash < prev_hash && 604ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx)) 605ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o goto clear_and_exit; 6068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[blk]; 6078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db->flags & DX_FLAG_REFERENCED) { 6088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_DUP_REF; 6098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else { 6108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_REFERENCED; 6118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->parent = db->blockcnt; 6128fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < min_hash) 6148fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o min_hash = hash; 6158fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > max_hash) 6168fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o max_hash = hash; 6178fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_min_hash = hash; 6188132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o if ((i+1) < count) 6198132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o dx_db->node_max_hash = 6208132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; 6218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o else { 6228fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->node_max_hash = 0xfffffffe; 6238fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_LAST; 6248fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6258fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (i == 0) 6268fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST; 6278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 6288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 6298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n", 6308fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, min_hash, max_hash); 6318fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 6328fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 6338fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = min_hash; 6348fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = max_hash; 635ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 636ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o 637ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'oclear_and_exit: 638ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o clear_htree(cd->ctx, cd->pctx.ino); 639ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->numblocks = 0; 6408fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 6418fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 642aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 643e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o/* 644e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Given a busted directory, try to salvage it somehow. 645e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * 646e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 647ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'ostatic void salvage_directory(ext2_filsys fs, 648e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, 649e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *prev, 650544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int *offset) 651e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o{ 652e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o char *cp = (char *) dirent; 653ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o int left = fs->blocksize - *offset - dirent->rec_len; 654642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o unsigned int name_len = dirent->name_len & 0xFF; 655e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 656e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 657e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Special case of directory entry of size 8: copy what's left 658e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * of the directory block up to cover up the invalid hole. 659e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 660e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if ((left >= 12) && (dirent->rec_len == 8)) { 661e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o memmove(cp, cp+8, left); 662e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o memset(cp + left, 0, 8); 663ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 664ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o } 665ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o /* 666ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * If the directory entry overruns the end of the directory 667ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * block, and the name is small enough to fit, then adjust the 668ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o * record length. 669ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o */ 670ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o if ((left < 0) && 671642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o (name_len + 8 <= dirent->rec_len + (unsigned) left) && 672ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dirent->inode <= fs->super->s_inodes_count && 673ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o strnlen(dirent->name, name_len) == name_len) { 674ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dirent->rec_len += left; 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 */ 682575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0 && 683575307cc63d24766ff789262a5cea7b4faf2fa13Kalpak Shah (*offset + dirent->rec_len <= fs->blocksize)) { 684e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev->rec_len += dirent->rec_len; 685ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o *offset += dirent->rec_len; 686ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o return; 687e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 688e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o /* 689e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * Default salvage method --- kill all of the directory 690e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * entries for the rest of the block. We will either try to 691e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * absorb it into the previous directory entry, or create a 692e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o * new empty directory entry the rest of the directory block. 693e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o */ 694e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (prev) { 695ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o prev->rec_len += fs->blocksize - *offset; 696ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o *offset = fs->blocksize; 697e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else { 698ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dirent->rec_len = fs->blocksize - *offset; 699e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->name_len = 0; 700e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dirent->inode = 0; 701e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } 702e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o} 703e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o 7043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int check_dir_block(ext2_filsys fs, 70521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct ext2_db_entry *db, 70654dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 7073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 7088fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dir_info *dx_dir; 7098fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 7108fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct dx_dirblock_info *dx_db = 0; 7118fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 712e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o struct ext2_dir_entry *dirent, *prev; 7138fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2_dirhash_t hash; 714544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int offset = 0; 715e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o const char * old_op; 7163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dir_modified = 0; 71721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o int dot_state; 7183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t block_nr = db->blk; 71986c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o ext2_ino_t ino = db->ino; 72028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ext2_ino_t subdir_parent; 72121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o __u16 links; 72254dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct check_dir_struct *cd; 7231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o char *buf; 7241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 7251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o int problem; 726ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o struct ext2_dx_root_info *root; 727e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o struct ext2_dx_countlimit *limit; 7280926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o static dict_t de_dict; 7290926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o struct problem_context pctx; 7300926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o int dups_found = 0; 73128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o int ret; 7321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 73354dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o cd = (struct check_dir_struct *) priv_data; 7341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o buf = cd->buf; 7351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx = cd->ctx; 736f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 7374cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 7384cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 7394cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o 7404cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) 7414cae04529eda0e482ceaa86b48e532f9c8d35f24Theodore Ts'o return DIRENT_ABORT; 74221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 7433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 7443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the inode is still in use (could have been 7453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * deleted in the duplicate/bad blocks pass. 7463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 7471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))) 7483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 74950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 75021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino = ino; 75121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blk = block_nr; 75221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.blkcount = db->blockcnt; 75321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 75421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = 0; 75521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = 0; 75621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 75750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blk == 0) { 7581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (allocate_dir_block(ctx, db, buf, &cd->pctx)) 75950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 76050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o block_nr = db->blk; 76150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 7623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (db->blockcnt) 7643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 2; 7653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 7663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dot_state = 0; 7673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7680926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (ctx->dirs_to_hash && 7690926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_test(ctx->dirs_to_hash, ino)) 7700926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 7710926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 7723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 773f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr, 7743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o db->blockcnt, ino); 7753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 7763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 777e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o old_op = ehandler_operation(_("reading directory block")); 7781b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf); 779e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o ehandler_operation(0); 780b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) 781b9852cd87b42f79d569db68c3fdefe4a8f48ede1Theodore Ts'o cd->pctx.errcode = 0; /* We'll handle this ourselves */ 7821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 78308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { 78408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 78508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 78608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o } 7871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o memset(buf, 0, fs->blocksize); 7883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7898fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 7908fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_dir = e2fsck_get_dx_dir_info(ctx, ino); 79162acaa1de132a808949d71264731bba7fe095705Theodore Ts'o if (dx_dir && dx_dir->numblocks) { 7928fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt >= dx_dir->numblocks) { 7938fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("XXX should never happen!!!\n"); 7948fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o abort(); 7958fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 7968fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db = &dx_dir->dx_block[db->blockcnt]; 7978fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_LEAF; 7988fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->phys = block_nr; 7998fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = ~0; 8008fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = 0; 8018fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 8028fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dirent = (struct ext2_dir_entry *) buf; 803e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o limit = (struct ext2_dx_countlimit *) (buf+8); 8048fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (db->blockcnt == 0) { 805ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root = (struct ext2_dx_root_info *) (buf + 24); 8068fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_ROOT; 8078fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; 808ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o if ((root->reserved_zero || 809ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->info_length < 8 || 810ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o root->indirect_levels > 1) && 811ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { 812ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o clear_htree(ctx, ino); 813ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->numblocks = 0; 814ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_db = 0; 815f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o } 816ea1959f01523ffc105747d660ccc5b7f02805928Theodore Ts'o dx_dir->hashversion = root->hash_version; 817f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o if ((dx_dir->hashversion <= EXT2_HASH_TEA) && 818f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) 819f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o dx_dir->hashversion += 3; 820ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o dx_dir->depth = root->indirect_levels + 1; 8218fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } else if ((dirent->inode == 0) && 822e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o (dirent->rec_len == fs->blocksize) && 823e8254bfd3b49cb325a1ff6b21ca86570a1008744Theodore Ts'o (dirent->name_len == 0) && 8248132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o (ext2fs_le16_to_cpu(limit->limit) == 8258132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o ((fs->blocksize-8) / 8268132d840c8f6b0d90ab5048d6f8529f74e1aa0b3Theodore Ts'o sizeof(struct ext2_dx_entry)))) 8278fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->type = DX_DIRBLOCK_NODE; 8288fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 8298fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 8303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8310926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp); 832e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = 0; 8333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o do { 8341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = 0; 8353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent = (struct ext2_dir_entry *) (buf + offset); 83621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.dirent = dirent; 83721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.num = offset; 8383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (((offset + dirent->rec_len) > fs->blocksize) || 839c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o (dirent->rec_len < 12) || 84021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o ((dirent->rec_len % 4) != 0) || 841b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { 8421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { 843ad4fa4660404ed88a3231fee338397af11e041b4Theodore Ts'o salvage_directory(fs, dirent, prev, &offset); 8443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 845e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o continue; 84621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } else 8470926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 8483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 849b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) { 8501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) { 85150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o dirent->name_len = EXT2_NAME_LEN; 85250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o dir_modified++; 85350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 85450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 85550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 856e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if (dot_state == 0) { 8571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (check_dot(ctx, dirent, ino, &cd->pctx)) 8583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 859e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if (dot_state == 1) { 86028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o ret = check_dotdot(ctx, dirent, ino, &cd->pctx); 86128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ret < 0) 8620926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 86328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (ret) 8643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 8653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else if (dirent->inode == ino) { 8661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_LINK_DOT; 8671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) { 8683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 8693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 87021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 8713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!dirent->inode) 8743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 8753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 8773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure the inode listed is a legal one. 8783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 8793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (((dirent->inode != EXT2_ROOT_INO) && 8807f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o (dirent->inode < EXT2_FIRST_INODE(fs->super))) || 8813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o (dirent->inode > fs->super->s_inodes_count)) { 8821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_BAD_INO; 8831b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, 8843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode))) { 8851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 8861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If the inode is unused, offer to clear it. 8871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 8881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_UNUSED_INODE; 8891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else if (ctx->inode_bb_map && 8901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (ext2fs_test_inode_bitmap(ctx->inode_bb_map, 8911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dirent->inode))) { 8921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 8931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If the inode is in a bad block, offer to 8941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * clear it. 8951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 8961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_BB_INODE; 897e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 898b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o ((dirent->name_len & 0xFF) == 1) && 8991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[0] == '.')) { 9001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 9011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If there's a '.' entry in anything other 9021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * than the first directory entry, it's a 9031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * duplicate entry that should be removed. 9041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_DUP_DOT; 906e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 907b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o ((dirent->name_len & 0xFF) == 2) && 9081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[0] == '.') && 9091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->name[1] == '.')) { 9101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 9111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * If there's a '..' entry in anything other 9121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * than the second directory entry, it's a 9131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * duplicate entry that should be removed. 9141b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_DUP_DOT_DOT; 916e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 9171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (dirent->inode == EXT2_ROOT_INO)) { 9181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o /* 9191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * Don't allow links to the root directory. 9201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * We check this specially to make sure we 9211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * catch this error case even if the root 9221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * directory hasn't been created yet. 9231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */ 9241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o problem = PR_2_LINK_ROOT; 925e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o } else if ((dot_state > 1) && 926c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o (dirent->name_len & 0xFF) == 0) { 927c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o /* 928c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o * Don't allow zero-length directory names. 929c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o */ 930c40db6d5717023bdd6bb4935161e7ce9678d6234Theodore Ts'o problem = PR_2_NULL_NAME; 93121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 93221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 9331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (problem) { 9341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, problem, &cd->pctx)) { 93521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dirent->inode = 0; 93621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o dir_modified++; 93721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o goto next; 9381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } else { 9391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_valid(fs); 9401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (problem == PR_2_BAD_INO) 9411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o goto next; 94221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 9433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 9443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 9463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If the inode was marked as having bad fields in 9473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass1, process it and offer to fix/clear it. 9483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * (We wait until now so that we can display the 9493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pathname to the user.) 9503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 9511b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map && 9521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_test_inode_bitmap(ctx->inode_bad_map, 9533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode)) { 954e72a9ba39471364ad2f9397f645ca547090e3485Theodore Ts'o if (e2fsck_process_bad_inode(ctx, ino, 955bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o dirent->inode, 956bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o buf + fs->blocksize)) { 9573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 9583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 9593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 9603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 961a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 96208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return DIRENT_ABORT; 9633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 9643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 9651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (check_name(ctx, dirent, ino, &cd->pctx)) 9661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dir_modified++; 9671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 968aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o if (check_filetype(ctx, dirent, ino, &cd->pctx)) 969aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o dir_modified++; 970aa4115a47c554a936fdf5e6679e72a9329fecf45Theodore Ts'o 9718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 9728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db) { 9738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o ext2fs_dirhash(dx_dir->hashversion, dirent->name, 974503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o (dirent->name_len & 0xFF), 975503f9e7f6eb331c5b75d7f1ad126f71bcdcfb4e3Theodore Ts'o fs->super->s_hash_seed, &hash, 0); 9768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash < dx_db->min_hash) 9778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash = hash; 9788fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (hash > dx_db->max_hash) 9798fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->max_hash = hash; 9808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 9818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 9828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 98321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o /* 9843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If this is a directory, then mark its parent in its 9853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * dir_info structure. If the parent field is already 9863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filled in, then this directory has more than one 9873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * hard link. We assume the first link is correct, 9883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * and ask the user if he/she wants to clear this one. 9893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 990e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o if ((dot_state > 1) && 9911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (ext2fs_test_inode_bitmap(ctx->inode_dir_map, 9923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode))) { 99328db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (e2fsck_dir_info_get_parent(ctx, dirent->inode, 99428db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o &subdir_parent)) { 9951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.ino = dirent->inode; 9961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); 9970926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 9983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 99928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o if (subdir_parent) { 100028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o cd->pctx.ino2 = subdir_parent; 10011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_LINK_DIR, 100221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o &cd->pctx)) { 10033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = 0; 10043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir_modified++; 10053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto next; 100621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 100721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o cd->pctx.ino2 = 0; 100828db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } else { 100928db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o (void) e2fsck_dir_info_set_parent(ctx, 101028db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o dirent->inode, ino); 101128db82a84a33fab19f22da12bb2a8a3c558ae97bTheodore Ts'o } 10123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10130926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o 10140926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (dups_found) { 10150926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ; 10160926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o } else if (dict_lookup(&de_dict, dirent)) { 10170926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o clear_problem_context(&pctx); 10180926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o pctx.ino = ino; 10190926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o pctx.dirent = dirent; 10200926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx); 10210926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (!ctx->dirs_to_hash) 10220926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_create(&ctx->dirs_to_hash, 50); 10230926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o if (ctx->dirs_to_hash) 10240926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 10250926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dups_found++; 10260926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o } else 10270926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_alloc_insert(&de_dict, dirent, dirent); 10283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 10291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_count, dirent->inode, 10301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &links); 103121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (links > 1) 10321b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->fs_links_count++; 10331b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->fs_total_count++; 10343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o next: 1035e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o prev = dirent; 10363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o offset += dirent->rec_len; 1037e70ae99e077f5085c15a4526028e2aac0e91d7c1Theodore Ts'o dot_state++; 10383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } while (offset < fs->blocksize); 10393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 10403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o printf("\n"); 10413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 10428fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef ENABLE_HTREE 10438fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if (dx_db) { 10448fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#ifdef DX_DEBUG 10458fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n", 10468fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o db->blockcnt, dx_db->type, 10478fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o dx_db->min_hash, dx_db->max_hash); 10488fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif 1049b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o cd->pctx.dir = cd->pctx.ino; 10508fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o if ((dx_db->type == DX_DIRBLOCK_ROOT) || 10518fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o (dx_db->type == DX_DIRBLOCK_NODE)) 10528fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o parse_int_node(fs, db, cd, dx_dir, buf); 10538fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o } 10548fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o#endif /* ENABLE_HTREE */ 10553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (offset != fs->blocksize) { 10561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.num = dirent->rec_len - fs->blocksize + offset; 10571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) { 10581b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dirent->rec_len = cd->pctx.num; 10591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o dir_modified++; 10601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 10613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dir_modified) { 10631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf); 10641b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (cd->pctx.errcode) { 106508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, 10660926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o &cd->pctx)) 10670926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o goto abort_free_dict; 10683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_changed(fs); 10703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 10710926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_free_nodes(&de_dict); 10723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 10730926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'oabort_free_dict: 10740926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o dict_free_nodes(&de_dict); 10750926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 10760926668d3af802b4d385d0fc3525a5a4e679574aTheodore Ts'o return DIRENT_ABORT; 10773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 10783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 10793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 10803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This function is called to deallocate a block, and is an interator 10813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * functioned called by deallocate inode via ext2fs_iterate_block(). 10823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 10833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int deallocate_inode_block(ext2_filsys fs, 1084133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o blk_t *block_nr, 1085544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 1086544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o blk_t ref_block EXT2FS_ATTR((unused)), 1087544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 1088133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o void *priv_data) 10893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 109054dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o e2fsck_t ctx = (e2fsck_t) priv_data; 10911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 10921917875fcd16428d14eb5a86acf414472bc216f1Theodore Ts'o if (HOLE_BLKADDR(*block_nr)) 10933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 10941ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o if ((*block_nr < fs->super->s_first_data_block) || 10951ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o (*block_nr >= fs->super->s_blocks_count)) 10961ba7a2f2b6a9b152828a06443955a7fb1d139930Theodore Ts'o return 0; 10971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); 10980684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_block_alloc_stats(fs, *block_nr, -1); 10993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 11003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 11013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 11023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 11033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This fuction deallocates an inode 11043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 11054035f40bc4550ce7520724cc837992a700794e00Theodore Ts'ostatic void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) 11063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 11071b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 11083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 11091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 11100684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o __u32 count; 11111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 11121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_link_info, ino, 0); 111308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 11143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 0; 11151f3ad14a5ad5df3ac4012d41ef5d76411cd8fff3Theodore Ts'o inode.i_dtime = ctx->now; 111608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode"); 11171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 11181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.ino = ino; 1119f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 11203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 11213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Fix up the bitmaps... 11223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1123f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 11241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); 11251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); 11261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ctx->inode_bad_map) 11271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); 11280684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); 11290684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o 11300684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (inode.i_file_acl && 11310684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 11320684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl, 11330684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o block_buf, -1, &count); 11340684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { 11350684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o pctx.errcode = 0; 11360684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o count = 1; 11370684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 11380684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (pctx.errcode) { 11390684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o pctx.blk = inode.i_file_acl; 11400684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); 11410684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 11420684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o return; 11430684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 11440684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o if (count == 0) { 11450684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_unmark_block_bitmap(ctx->block_found_map, 11460684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o inode.i_file_acl); 11470684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1); 11480684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 11490684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o inode.i_file_acl = 0; 11500684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o } 11513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 115221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (!ext2fs_inode_has_valid_blocks(&inode)) 11533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 1154a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 1155b94a052a25d0c524209782e408c31d8ff25a6fe1Andreas Dilger if (LINUX_S_ISREG(inode.i_mode) && 1156a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o (inode.i_size_high || inode.i_size & 0x80000000UL)) 1157a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o ctx->large_files--; 1158a47426914745b7d50bb58a3d44b3509c647c637eTheodore Ts'o 1159133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, 11601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o deallocate_inode_block, ctx); 11611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 11621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); 116308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 116408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 11651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 11663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 11673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 11688fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o/* 11698fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o * This fuction clears the htree flag on an inode 11708fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o */ 11718fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'ostatic void clear_htree(e2fsck_t ctx, ext2_ino_t ino) 11728fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o{ 11738fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o struct ext2_inode inode; 11748fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 11758fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); 11768fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; 11778fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); 1178b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o if (ctx->dirs_to_hash) 1179b7a00563b22b0ea47ddc7117508c0b8e0d65df43Theodore Ts'o ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 11808fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o} 11818fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 11828fdc9985c1e2a4467630b33719b7feb281b7b33bTheodore Ts'o 118386c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'oextern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, 1184bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o ext2_ino_t ino, char *buf) 11853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 11861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 11873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 11883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int inode_modified = 0; 11896c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o int not_fixed = 0; 11901e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o unsigned char *frag, *fsize; 119121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 119208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o int problem = 0; 11933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 119408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); 119521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 119621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o clear_problem_context(&pctx); 119721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.ino = ino; 119821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.dir = dir; 119921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.inode = &inode; 120021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 12016c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (inode.i_file_acl && 1202f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 1203f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { 1204f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o inode.i_file_acl = 0; 1205f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o inode_modified++; 1206f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } else 1207f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o not_fixed++; 1208f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o } 12096c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 121050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && 121150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && 121250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && 121308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o !(LINUX_S_ISSOCK(inode.i_mode))) 121408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_MODE; 1215fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISCHR(inode.i_mode) 12160684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 121708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_CHAR_DEV; 1218fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISBLK(inode.i_mode) 12190684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 122008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = PR_2_BAD_BLOCK_DEV; 1221fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISFIFO(inode.i_mode) 12220684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 12231dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_FIFO; 1224fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISSOCK(inode.i_mode) 12250684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o && !e2fsck_pass1_check_device_inode(fs, &inode)) 12261dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o problem = PR_2_BAD_SOCKET; 1227fdbdea09b87dbd8e39c23286f22653e7641599aeTheodore Ts'o else if (LINUX_S_ISLNK(inode.i_mode) 1228bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o && !e2fsck_pass1_check_symlink(fs, &inode, buf)) { 1229bcf9c5d4016975c3c2afdb4a4b358569bd3c8681Theodore Ts'o problem = PR_2_INVALID_SYMLINK; 123067052a8aeeca8cd80d1dd33c2792f917573accc8Andreas Dilger } 12311dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o 123208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (problem) { 123308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (fix_problem(ctx, problem, &pctx)) { 12341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o deallocate_inode(ctx, ino, 0); 1235a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 123608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return 0; 12377cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o return 1; 12386c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 12396c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 124008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o problem = 0; 12417cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o } 12427cf73dcd3d173d88ceab26d381f4abac362d8518Theodore Ts'o 12436c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (inode.i_faddr) { 12446c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { 12456c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_faddr = 0; 12466c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 12476c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 12486c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 12493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 12501e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o 12511e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o switch (fs->super->s_creator_os) { 12521e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o case EXT2_OS_HURD: 12531e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = &inode.osd2.hurd2.h_i_frag; 12541e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o fsize = &inode.osd2.hurd2.h_i_fsize; 12551e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o break; 12561e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o case EXT2_OS_MASIX: 12571e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = &inode.osd2.masix2.m_i_frag; 12581e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o fsize = &inode.osd2.masix2.m_i_fsize; 12591e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o break; 12601e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o default: 12611e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o frag = fsize = 0; 12621e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o } 126321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (frag && *frag) { 126421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *frag; 12651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { 126621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *frag = 0; 126721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 12687e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o } else 12697e0282c5f21add344b306876ca999aecd4d5fd0cTheodore Ts'o not_fixed++; 127021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 127121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 127221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (fsize && *fsize) { 127321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = *fsize; 12741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { 127521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *fsize = 0; 127621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o inode_modified++; 12776c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 12786c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 127921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx.num = 0; 128021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 128121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 12825d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if ((fs->super->s_creator_os == EXT2_OS_LINUX) && 12835d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o !(fs->super->s_feature_ro_compat & 12845d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && 12855d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o (inode.osd2.linux2.l_i_blocks_hi != 0)) { 12865d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o pctx.num = inode.osd2.linux2.l_i_blocks_hi; 12875d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { 12885d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode.osd2.linux2.l_i_blocks_hi = 0; 12895d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o inode_modified++; 12905d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 12915d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o } 12925d17119d14fe1276936c85d7986695a4543b1aa1Theodore Ts'o 129321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (inode.i_file_acl && 1294342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o ((inode.i_file_acl < fs->super->s_first_data_block) || 12956c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o (inode.i_file_acl >= fs->super->s_blocks_count))) { 12966c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { 12976c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_file_acl = 0; 12986c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 12996c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13006c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 1301342d847db355d81299218e07a1e58ece82080a04Theodore Ts'o } 130221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (inode.i_dir_acl && 13036c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o LINUX_S_ISDIR(inode.i_mode)) { 13046c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { 13056c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode.i_dir_acl = 0; 13066c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o inode_modified++; 13076c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o } else 13086c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o not_fixed++; 130921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 13106c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o 1311f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (inode_modified) 131208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); 1313f76344fb6f9439ecd5060943930e73cd3b3dd9feTheodore Ts'o if (!not_fixed && ctx->inode_bad_map) 13146c313fd4732adbb83d6f9c402300487b6a7e84bbTheodore Ts'o ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); 13153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 13163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 13173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 131850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 131950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/* 132050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * allocate_dir_block --- this function allocates a new directory 132150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * block for a particular inode; this is done if a directory has 132250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * a "hole" in it, or if a directory has a illegal block number 132350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * that was zeroed out and now needs to be replaced. 132450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 13251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic int allocate_dir_block(e2fsck_t ctx, 132621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct ext2_db_entry *db, 1327544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o char *buf EXT2FS_ATTR((unused)), 1328544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o struct problem_context *pctx) 132950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{ 13301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 133150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o blk_t blk; 133250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o char *block; 133350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o struct ext2_inode inode; 133450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 13351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) 133650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 133750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 133850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 133950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 134050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * them. 134150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1342f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 134350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 134450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 134550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * First, find a free block 134650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 13471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 13481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 13491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_new_block"; 13501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 135150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 135250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 13531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 135450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 135550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o ext2fs_mark_bb_dirty(fs); 135650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 135750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 135850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Now let's create the actual data block for the inode 135950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 136050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (db->blockcnt) 13611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); 136250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o else 13631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_new_dir_block(fs, db->ino, 13641b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o EXT2_ROOT_INO, &block); 136550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 13661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 13671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_new_dir_block"; 13681b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 136950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 137050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 137150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 13721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->errcode = ext2fs_write_dir_block(fs, blk, block); 1373c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block); 13741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 13751b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_write_dir_block"; 13761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 137750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 137850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 137950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 138050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 138150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Update the inode block count 138250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 138308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); 138450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o inode.i_blocks += fs->blocksize / 512; 138550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o if (inode.i_size < (db->blockcnt+1) * fs->blocksize) 138650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o inode.i_size = (db->blockcnt+1) * fs->blocksize; 138708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); 138850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 138950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o /* 139050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Finally, update the block pointers for the inode 139150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 139250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o db->blk = blk; 1393133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE, 139450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 0, update_dir_block, db); 13951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx->errcode) { 13961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx->str = "ext2fs_block_iterate"; 13971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 139850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 1; 139950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 140050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 140150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 140250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o} 140350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 140450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/* 140550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * This is a helper function for allocate_dir_block(). 140650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */ 1407544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int update_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)), 140850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o blk_t *block_nr, 1409133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o e2_blkcnt_t blockcnt, 1410544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o blk_t ref_block EXT2FS_ATTR((unused)), 1411544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 141254dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 141350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{ 141454dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct ext2_db_entry *db; 141550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 141654dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o db = (struct ext2_db_entry *) priv_data; 1417133a56dc9da52054bc27b4c1a23f03e3405003dbTheodore Ts'o if (db->blockcnt == (int) blockcnt) { 141850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o *block_nr = db->blk; 141950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return BLOCK_CHANGED; 142050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 142150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o return 0; 142250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o} 1423