Esempio n. 1
0
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
				    ext2_ino_t ino, char *buf)
{
	ext2_filsys fs = ctx->fs;
	struct ext2_inode	inode;
	int			inode_modified = 0;
	int			not_fixed = 0;
	unsigned char		*frag, *fsize;
	struct problem_context	pctx;
	int	problem = 0;

	e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");

	clear_problem_context(&pctx);
	pctx.ino = ino;
	pctx.dir = dir;
	pctx.inode = &inode;

	if (ext2fs_file_acl_block(fs, &inode) &&
	    !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
		if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
			ext2fs_file_acl_block_set(fs, &inode, 0);
			inode_modified++;
		} else
			not_fixed++;
	}

	if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
	    !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
	    !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
	    !(LINUX_S_ISSOCK(inode.i_mode)))
		problem = PR_2_BAD_MODE;
	else if (LINUX_S_ISCHR(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_CHAR_DEV;
	else if (LINUX_S_ISBLK(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_BLOCK_DEV;
	else if (LINUX_S_ISFIFO(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_FIFO;
	else if (LINUX_S_ISSOCK(inode.i_mode)
		 && !e2fsck_pass1_check_device_inode(fs, &inode))
		problem = PR_2_BAD_SOCKET;
	else if (LINUX_S_ISLNK(inode.i_mode)
		 && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) {
		problem = PR_2_INVALID_SYMLINK;
	}

	if (problem) {
		if (fix_problem(ctx, problem, &pctx)) {
			deallocate_inode(ctx, ino, 0);
			if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
				return 0;
			return 1;
		} else
			not_fixed++;
		problem = 0;
	}

	if (inode.i_faddr) {
		if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
			inode.i_faddr = 0;
			inode_modified++;
		} else
			not_fixed++;
	}

	switch (fs->super->s_creator_os) {
	    case EXT2_OS_HURD:
		frag = &inode.osd2.hurd2.h_i_frag;
		fsize = &inode.osd2.hurd2.h_i_fsize;
		break;
	    default:
		frag = fsize = 0;
	}
	if (frag && *frag) {
		pctx.num = *frag;
		if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
			*frag = 0;
			inode_modified++;
		} else
			not_fixed++;
		pctx.num = 0;
	}
	if (fsize && *fsize) {
		pctx.num = *fsize;
		if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
			*fsize = 0;
			inode_modified++;
		} else
			not_fixed++;
		pctx.num = 0;
	}

	if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
	    !(fs->super->s_feature_ro_compat &
	      EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
	    (inode.osd2.linux2.l_i_blocks_hi != 0)) {
		pctx.num = inode.osd2.linux2.l_i_blocks_hi;
		if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
			inode.osd2.linux2.l_i_blocks_hi = 0;
			inode_modified++;
		}
	}

	if (!(fs->super->s_feature_incompat & 
	     EXT4_FEATURE_INCOMPAT_64BIT) &&
	    inode.osd2.linux2.l_i_file_acl_high != 0) {
		pctx.num = inode.osd2.linux2.l_i_file_acl_high;
		if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) {
			inode.osd2.linux2.l_i_file_acl_high = 0;
			inode_modified++;
		} else
			not_fixed++;
	}

	if (ext2fs_file_acl_block(fs, &inode) &&
	    ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) ||
	     (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) {
		if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
			ext2fs_file_acl_block_set(fs, &inode, 0);
			inode_modified++;
		} else
			not_fixed++;
	}
	if (inode.i_dir_acl &&
	    LINUX_S_ISDIR(inode.i_mode)) {
		if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
			inode.i_dir_acl = 0;
			inode_modified++;
		} else
			not_fixed++;
	}

	if (inode_modified)
		e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
	if (!not_fixed && ctx->inode_bad_map)
		ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
	return 0;
}
Esempio n. 2
0
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                                    ext2_ino_t ino)
{
    ext2_filsys fs = ctx->fs;
    struct ext2_inode	inode;
    int			inode_modified = 0;
    unsigned char		*frag, *fsize;
    struct problem_context	pctx;
    int	problem = 0;

    e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");

    clear_problem_context(&pctx);
    pctx.ino = ino;
    pctx.dir = dir;
    pctx.inode = &inode;

    if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
            !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
            !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
            !(LINUX_S_ISSOCK(inode.i_mode)))
        problem = PR_2_BAD_MODE;
    else if (LINUX_S_ISCHR(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_CHAR_DEV;
    else if (LINUX_S_ISBLK(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_BLOCK_DEV;
    else if (LINUX_S_ISFIFO(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_FIFO;
    else if (LINUX_S_ISSOCK(inode.i_mode)
             && !e2fsck_pass1_check_device_inode(&inode))
        problem = PR_2_BAD_SOCKET;
    else if (LINUX_S_ISLNK(inode.i_mode)
             && !e2fsck_pass1_check_symlink(fs, &inode)) {
        problem = PR_2_SYMLINK_SIZE;
    }

    if (problem) {
        if (fix_problem(ctx, problem, &pctx)) {
            deallocate_inode(ctx, ino, 0);
            if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
                return 0;
            return 1;
        }
        problem = 0;
    }

    if (inode.i_faddr &&
            fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
        inode.i_faddr = 0;
        inode_modified++;
    }

    switch (fs->super->s_creator_os) {
    case EXT2_OS_LINUX:
        frag = &inode.osd2.linux2.l_i_frag;
        fsize = &inode.osd2.linux2.l_i_fsize;
        break;
    case EXT2_OS_HURD:
        frag = &inode.osd2.hurd2.h_i_frag;
        fsize = &inode.osd2.hurd2.h_i_fsize;
        break;
    case EXT2_OS_MASIX:
        frag = &inode.osd2.masix2.m_i_frag;
        fsize = &inode.osd2.masix2.m_i_fsize;
        break;
    default:
        frag = fsize = 0;
    }
    if (frag && *frag) {
        pctx.num = *frag;
        if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
            *frag = 0;
            inode_modified++;
        }
        pctx.num = 0;
    }
    if (fsize && *fsize) {
        pctx.num = *fsize;
        if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
            *fsize = 0;
            inode_modified++;
        }
        pctx.num = 0;
    }

    if (inode.i_file_acl &&
            !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
            fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
        inode.i_file_acl = 0;
        inode_modified++;
    }
    if (inode.i_file_acl &&
            ((inode.i_file_acl < fs->super->s_first_data_block) ||
             (inode.i_file_acl >= fs->super->s_blocks_count)) &&
            fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
        inode.i_file_acl = 0;
        inode_modified++;
    }
    if (inode.i_dir_acl &&
            LINUX_S_ISDIR(inode.i_mode) &&
            fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
        inode.i_dir_acl = 0;
        inode_modified++;
    }
    if (inode_modified)
        e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
    return 0;
}