- 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);
+ if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, ino) ||
+ ext2fs_test_inode_bitmap2(ctx->inode_dir_map, ino))
+ return 1;
+
+ e2fsck_read_inode(ctx, ino, &inode, "check_encryption_policy");
+ return LINUX_S_ISREG(inode.i_mode) ||
+ LINUX_S_ISDIR(inode.i_mode) ||
+ LINUX_S_ISLNK(inode.i_mode);
+}
+
+/*
+ * All regular files, directories, and symlinks in encrypted directories must be
+ * encrypted using the same encryption policy as their directory.
+ *
+ * Returns 1 if the dirent should be cleared, otherwise 0.
+ */
+static int check_encryption_policy(e2fsck_t ctx,
+ const struct ext2_dir_entry *dirent,
+ __u32 dir_encpolicy_id,
+ struct problem_context *pctx)
+{
+ __u32 file_encpolicy_id = find_encryption_policy(ctx, dirent->inode);
+
+ /* Same policy or both UNRECOGNIZED_ENCRYPTION_POLICY? */
+ if (file_encpolicy_id == dir_encpolicy_id)
+ return 0;
+
+ if (file_encpolicy_id == NO_ENCRYPTION_POLICY) {
+ if (!needs_encryption(ctx, dirent))
+ return 0;
+ return fix_problem(ctx, PR_2_UNENCRYPTED_FILE, pctx);
+ }
+
+ return fix_problem(ctx, PR_2_INCONSISTENT_ENCRYPTION_POLICY, pctx);
+}
+
+/*
+ * Check an encrypted directory entry.
+ *
+ * Returns 1 if the dirent should be cleared, otherwise 0.
+ */
+static int check_encrypted_dirent(e2fsck_t ctx,
+ const struct ext2_dir_entry *dirent,
+ __u32 dir_encpolicy_id,
+ struct problem_context *pctx)
+{
+ if (encrypted_check_name(ctx, dirent, pctx))
+ return 1;
+ if (check_encryption_policy(ctx, dirent, dir_encpolicy_id, pctx))
+ return 1;
+ return 0;
+}
+
+static int check_dir_block2(ext2_filsys fs,
+ struct ext2_db_entry2 *db,
+ void *priv_data)
+{
+ int err;
+ struct check_dir_struct *cd = priv_data;
+
+ if (cd->ra_entries && cd->list_offset >= cd->next_ra_off) {
+ err = e2fsck_readahead_dblist(fs,
+ E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT,
+ fs->dblist,
+ cd->list_offset + cd->ra_entries / 8,
+ cd->ra_entries);
+ if (err)
+ cd->ra_entries = 0;
+ cd->next_ra_off = cd->list_offset + (cd->ra_entries * 7 / 8);
+ }
+
+ err = check_dir_block(fs, db, priv_data);
+ cd->list_offset++;
+ return err;