/* pass2.c */
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
ext2_ino_t ino, char *buf);
+extern int get_filename_hash(ext2_filsys fs, int encrypted, int version,
+ const char *name, int len,
+ ext2_dirhash_t *ret_hash,
+ ext2_dirhash_t *ret_minor_hash);
/* pass3.c */
extern int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
ext2_extent_handle_t handle;
struct ext2_extent_info info;
struct ext2fs_extent extent;
+ int encrypted = 0;
if ((inode->i_size_high || inode->i_size == 0) ||
(inode->i_flags & EXT2_INDEX_FL))
if (io_channel_read_blk64(fs->io, inode->i_block[0], 1, buf))
return 0;
- len = strnlen(buf, fs->blocksize);
+ if (inode->i_flags & EXT4_ENCRYPT_FL) {
+ len = ext2fs_le32_to_cpu(*((__u32 *)buf)) + 4;
+ } else {
+ len = strnlen(buf, fs->blocksize);
+ }
if (len == fs->blocksize)
return 0;
} else if (inode->i_flags & EXT4_INLINE_DATA_FL) {
return 0;
}
if (len != inode->i_size)
- return 0;
+ if ((inode->i_flags & EXT4_ENCRYPT_FL) == 0)
+ return 0;
return 1;
}
static int check_name(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
ext2_ino_t dir_ino,
- int *encrypted,
struct problem_context *pctx)
{
int i;
int fixup = -1;
int ret = 0;
- if (*encrypted > 0)
- return 0;
for ( i = 0; i < ext2fs_dirent_name_len(dirent); i++) {
if (dirent->name[i] != '/' && dirent->name[i] != '\0')
continue;
- if (*encrypted < 0 && ctx->encrypted_dirs)
- *encrypted = ext2fs_u32_list_test(ctx->encrypted_dirs,
- dir_ino);
- if (*encrypted > 0)
- return 0;
if (fixup < 0)
fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
if (fixup == 0)
return retval;
}
+int get_filename_hash(ext2_filsys fs, int encrypted, int version,
+ const char *name, int len, ext2_dirhash_t *ret_hash,
+ ext2_dirhash_t *ret_minor_hash)
+{
+ char buf[2*EXT2FS_DIGEST_SIZE];
+ int buf_len;
+
+ if (!encrypted)
+ return ext2fs_dirhash(version, name, len,
+ fs->super->s_hash_seed,
+ ret_hash, ret_minor_hash);
+
+ if (len <= EXT2FS_DIGEST_SIZE)
+ buf_len = ext2fs_digest_encode(name, len, buf);
+ else {
+ ext2fs_sha256(name, len, buf + EXT2FS_DIGEST_SIZE);
+ buf[0] = 'I';
+ buf_len = ext2fs_digest_encode(buf + EXT2FS_DIGEST_SIZE,
+ EXT2FS_DIGEST_SIZE, buf + 1);
+ buf_len++;
+ }
+ return ext2fs_dirhash(version, buf, buf_len,
+ fs->super->s_hash_seed,
+ ret_hash, ret_minor_hash);
+}
+
static int check_dir_block(ext2_filsys fs,
struct ext2_db_entry2 *db,
void *priv_data)
int is_leaf = 1;
size_t inline_data_size = 0;
int filetype = 0;
- int encrypted = -1;
+ int encrypted = 0;
size_t max_block_size;
cd = (struct check_dir_struct *) priv_data;
} else
max_block_size = fs->blocksize - de_csum_size;
+ if (ctx->encrypted_dirs)
+ encrypted = ext2fs_u32_list_test(ctx->encrypted_dirs, ino);
+
dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
prev = 0;
do {
}
}
- if (check_name(ctx, dirent, ino, &encrypted, &cd->pctx))
+ if (!encrypted && check_name(ctx, dirent, ino, &cd->pctx))
dir_modified++;
if (check_filetype(ctx, dirent, ino, &cd->pctx))
#ifdef ENABLE_HTREE
if (dx_db) {
- ext2fs_dirhash(dx_dir->hashversion, dirent->name,
- ext2fs_dirent_name_len(dirent),
- fs->super->s_hash_seed, &hash, 0);
+ get_filename_hash(fs, encrypted, dx_dir->hashversion,
+ dirent->name,
+ ext2fs_dirent_name_len(dirent),
+ &hash, 0);
if (hash < dx_db->min_hash)
dx_db->min_hash = hash;
if (hash > dx_db->max_hash)
struct fill_dir_struct {
char *buf;
struct ext2_inode *inode;
+ ext2_ino_t ino;
errcode_t err;
e2fsck_t ctx;
struct hash_entry *harray;
char *dir;
unsigned int offset, dir_offset, rec_len, name_len;
int hash_alg;
+ int encrypted = 0;
+ char processed_filename[2*EXT2FS_DIGEST_SIZE];
+ int processed_filename_len;
if (blockcnt < 0)
return 0;
fd->err = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
+
+ /* Determine if the directory is encrypted */
+ if (fd->ctx->encrypted_dirs)
+ encrypted = ext2fs_u32_list_test(fd->ctx->encrypted_dirs,
+ fd->ino);
+
dir = (fd->buf+offset);
if (HOLE_BLKADDR(*block_nr)) {
memset(dir, 0, fs->blocksize);
if (fd->compress)
ent->hash = ent->minor_hash = 0;
else {
- fd->err = ext2fs_dirhash(hash_alg, dirent->name,
- name_len,
- fs->super->s_hash_seed,
- &ent->hash, &ent->minor_hash);
+ fd->err = get_filename_hash(fs, encrypted,
+ hash_alg, dirent->name,
+ ext2fs_dirent_name_len(dirent),
+ &ent->hash, &ent->minor_hash);
if (fd->err)
return BLOCK_ABORT;
}
char new_name[256];
unsigned int new_len;
int hash_alg;
+ int encrypted = 0;
+ char processed_filename[2*EXT2FS_DIGEST_SIZE];
+ int processed_filename_len;
clear_problem_context(&pctx);
pctx.ino = ino;
(fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
hash_alg += 3;
+ /* Determine if the directory is encrypted */
+ if (fd->ctx->encrypted_dirs)
+ encrypted = ext2fs_u32_list_test(fd->ctx->encrypted_dirs,
+ fd->ino);
for (i=1; i < fd->num_array; i++) {
ent = fd->harray + i;
prev = ent - 1;
if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
memcpy(ent->dir->name, new_name, new_len);
ext2fs_dirent_set_name_len(ent->dir, new_len);
- ext2fs_dirhash(hash_alg, ent->dir->name, new_len,
- fs->super->s_hash_seed,
- &ent->hash, &ent->minor_hash);
+ get_filename_hash(fs, encrypted,
+ hash_alg, new_name, new_len,
+ &ent->hash, &ent->minor_hash);
fixed++;
}
}
fd.ctx = ctx;
fd.buf = dir_buf;
fd.inode = &inode;
+ fd.ino = ino;
fd.err = 0;
fd.dir_size = 0;
fd.compress = 0;