mirror of https://github.com/vitalif/e2fsprogs
e2fsck: Recover a special file which looks an awful lot like a directory
This is probably only useful in artificial test cases, but it will be useful if we ever do the "inodes in directory" idea for ext4. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>bitmap-optimize
parent
ccfbb266d6
commit
fbc3f90194
|
@ -1,5 +1,15 @@
|
|||
2007-03-31 Theodore Tso <tytso@mit.edu>
|
||||
|
||||
* pass1.c (e2fsck_pass1, check_is_really_dir): Check for an edge
|
||||
condition where the mode of a directory is incorrect, and
|
||||
looks like a special device, but it is really a directory.
|
||||
We can't do this for regular files because of the
|
||||
performance hit, but this will catch directories which
|
||||
have their i_mode bits mutated so they looks like a
|
||||
special device.
|
||||
|
||||
* problem.c, problem.h (PR_1_TREAT_AS_DIRECTORY): New problem code
|
||||
|
||||
* message.c (expand_percent_expression): Add support for %It, which
|
||||
will print the type of the inode.
|
||||
|
||||
|
|
|
@ -372,6 +372,74 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the inode might really be a directory, despite i_mode
|
||||
*
|
||||
* This is a lot of complexity for something for which I'm not really
|
||||
* convinced happens frequently in the wild. If for any reason this
|
||||
* causes any problems, take this code out.
|
||||
* [tytso:20070331.0827EDT]
|
||||
*/
|
||||
static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
|
||||
char *buf)
|
||||
{
|
||||
struct ext2_inode *inode = pctx->inode;
|
||||
int i, not_device = 0;
|
||||
blk_t blk;
|
||||
struct ext2_dir_entry *dirent;
|
||||
|
||||
if (LINUX_S_ISDIR(inode->i_mode) || LINUX_S_ISREG(inode->i_mode) ||
|
||||
inode->i_block[0] == 0)
|
||||
return;
|
||||
|
||||
for (i=1; i < EXT2_N_BLOCKS; i++) {
|
||||
blk = inode->i_block[i];
|
||||
if (!blk)
|
||||
continue;
|
||||
if (i >= 4)
|
||||
not_device++;
|
||||
|
||||
if (blk < ctx->fs->super->s_first_data_block ||
|
||||
blk >= ctx->fs->super->s_blocks_count ||
|
||||
ext2fs_fast_test_block_bitmap(ctx->block_found_map, blk))
|
||||
return; /* Invalid block, can't be dir */
|
||||
}
|
||||
|
||||
if ((LINUX_S_ISCHR(inode->i_mode) || LINUX_S_ISBLK(inode->i_mode)) &&
|
||||
(inode->i_links_count == 1) && !not_device)
|
||||
return;
|
||||
|
||||
if (LINUX_S_ISLNK(inode->i_mode) && inode->i_links_count == 1)
|
||||
return;
|
||||
|
||||
if (ext2fs_read_dir_block(ctx->fs, inode->i_block[0], buf))
|
||||
return;
|
||||
|
||||
dirent = (struct ext2_dir_entry *) buf;
|
||||
if (((dirent->name_len & 0xFF) != 1) ||
|
||||
(dirent->name[0] != '.') ||
|
||||
(dirent->inode != pctx->ino) ||
|
||||
(dirent->rec_len < 12) ||
|
||||
(dirent->rec_len % 4) ||
|
||||
(dirent->rec_len >= ctx->fs->blocksize - 12))
|
||||
return;
|
||||
|
||||
dirent = (struct ext2_dir_entry *) (buf + dirent->rec_len);
|
||||
if (((dirent->name_len & 0xFF) != 2) ||
|
||||
(dirent->name[0] != '.') ||
|
||||
(dirent->name[1] != '.') ||
|
||||
(dirent->rec_len < 12) ||
|
||||
(dirent->rec_len % 4))
|
||||
return;
|
||||
|
||||
if (fix_problem(ctx, PR_1_TREAT_AS_DIRECTORY, pctx)) {
|
||||
inode->i_mode = (inode->i_mode & 07777) | LINUX_S_IFDIR;
|
||||
e2fsck_write_inode_full(ctx, pctx->ino, inode,
|
||||
EXT2_INODE_SIZE(ctx->fs->super),
|
||||
"check_is_really_dir");
|
||||
}
|
||||
}
|
||||
|
||||
void e2fsck_pass1(e2fsck_t ctx)
|
||||
{
|
||||
int i;
|
||||
|
@ -769,6 +837,7 @@ void e2fsck_pass1(e2fsck_t ctx)
|
|||
}
|
||||
|
||||
check_inode_extra_space(ctx, &pctx);
|
||||
check_is_really_dir(ctx, &pctx, block_buf);
|
||||
|
||||
if (LINUX_S_ISDIR(inode->i_mode)) {
|
||||
ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
|
||||
|
|
|
@ -779,6 +779,11 @@ static struct e2fsck_problem problem_table[] = {
|
|||
N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
|
||||
PROMPT_CLEAR, PR_PREEN_OK },
|
||||
|
||||
/* inode appears to be a directory */
|
||||
{ PR_1_TREAT_AS_DIRECTORY,
|
||||
N_("@i %i is a %It but it looks like it is really a directory.\n"),
|
||||
PROMPT_FIX, 0 },
|
||||
|
||||
/* Pass 1b errors */
|
||||
|
||||
/* Pass 1B: Rescan for duplicate/bad blocks */
|
||||
|
|
|
@ -452,6 +452,9 @@ struct problem_context {
|
|||
/* wrong EA hash value */
|
||||
#define PR_1_ATTR_HASH 0x010054
|
||||
|
||||
/* inode appears to be a directory */
|
||||
#define PR_1_TREAT_AS_DIRECTORY 0x010055
|
||||
|
||||
/*
|
||||
* Pass 1b errors
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2007-04-01 Theodore Tso <tytso@mit.edu>
|
||||
|
||||
* f_dir_bad_mode: New test case.
|
||||
|
||||
2007-03-31 Theodore Tso <tytso@mit.edu>
|
||||
|
||||
* f_orphan_dotdot_ft: New test case which checks to see what
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
Pass 1: Checking inodes, blocks, and sizes
|
||||
Inode 12 is a socket but it looks like it is really a directory.
|
||||
Fix? yes
|
||||
|
||||
Pass 2: Checking directory structure
|
||||
Pass 3: Checking directory connectivity
|
||||
Pass 4: Checking reference counts
|
||||
Pass 5: Checking group summary information
|
||||
|
||||
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||
test_filesys: 15/16 files (0.0% non-contiguous), 25/100 blocks
|
||||
Exit status is 1
|
|
@ -0,0 +1,7 @@
|
|||
Pass 1: Checking inodes, blocks, and sizes
|
||||
Pass 2: Checking directory structure
|
||||
Pass 3: Checking directory connectivity
|
||||
Pass 4: Checking reference counts
|
||||
Pass 5: Checking group summary information
|
||||
test_filesys: 15/16 files (0.0% non-contiguous), 25/100 blocks
|
||||
Exit status is 0
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
directory with corrupted i_mode
|
Loading…
Reference in New Issue