unsigned int rec_len, min_rec_len, curr_rec_len;
int ret = 0;
int csum_size = 0;
+ struct ext2_dir_entry_tail *t;
+
+ if (ls->done)
+ return DIRENT_ABORT;
rec_len = EXT2_DIR_REC_LEN(ls->namelen);
if (ls->err)
return DIRENT_ABORT;
- if (EXT2_HAS_RO_COMPAT_FEATURE(ls->fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (ext2fs_has_feature_metadata_csum(ls->fs->super))
csum_size = sizeof(struct ext2_dir_entry_tail);
/*
* See if the following directory entry (if any) is unused;
}
/*
+ * Since ext2fs_link blows away htree data, we need to be
+ * careful -- if metadata_csum is enabled and we're passed in
+ * a dirent that contains htree data, we need to create the
+ * fake entry at the end of the block that hides the checksum.
+ */
+
+ /* De-convert a dx_node block */
+ if (csum_size &&
+ curr_rec_len == ls->fs->blocksize &&
+ !dirent->inode) {
+ curr_rec_len -= csum_size;
+ ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
+ if (ls->err)
+ return DIRENT_ABORT;
+ t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize);
+ ext2fs_initialize_dirent_tail(ls->fs, t);
+ ret = DIRENT_CHANGED;
+ }
+
+ /* De-convert a dx_root block */
+ if (csum_size &&
+ curr_rec_len == ls->fs->blocksize - EXT2_DIR_REC_LEN(1) &&
+ offset == EXT2_DIR_REC_LEN(1) &&
+ dirent->name[0] == '.' && dirent->name[1] == '.') {
+ curr_rec_len -= csum_size;
+ ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
+ if (ls->err)
+ return DIRENT_ABORT;
+ t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize);
+ ext2fs_initialize_dirent_tail(ls->fs, t);
+ ret = DIRENT_CHANGED;
+ }
+
+ /*
* If the directory entry is used, see if we can split the
* directory entry to make room for the new name. If so,
* truncate it and return.
dirent->inode = ls->inode;
ext2fs_dirent_set_name_len(dirent, ls->namelen);
strncpy(dirent->name, ls->name, ls->namelen);
- if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
+ if (ext2fs_has_feature_filetype(ls->sb))
ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7);
ls->done++;
if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
return retval;
+ /*
+ * If this function changes to preserve the htree, remove the
+ * two hunks in link_proc that shove checksum tails into the
+ * former dx_root/dx_node blocks.
+ */
if (inode.i_flags & EXT2_INDEX_FL) {
inode.i_flags &= ~EXT2_INDEX_FL;
if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)