libext2fs: ext2fs_[set_]file_acl_block needs to check for 64-bit feature flag
The ext2fs_file_acl_block() and ext2fs_set_file_acl_block() needs to
only check i_file_acl_high if the 64-bit flag is set. This is needed
because otherwise we will run into problems on Hurd systems which
actually use that field for h_i_mode_high.
This involves an ABI change since we need to pass ext2_filsys to these
functions. Fortunately these functions were first included in the
1.42-WIP series, so it's OK for us to change them now. (This is why
we have 1.42-WIP releases. :-)
Addresses-Sourceforge-Bug: #3379227
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c
index fd203b4..33da7d6 100644
--- a/lib/ext2fs/blknum.c
+++ b/lib/ext2fs/blknum.c
@@ -475,23 +475,24 @@
/*
* Get the acl block of a file
- *
- * XXX Ignoring 64-bit file system flag - most places where this is
- * called don't have access to the fs struct, and the high bits should
- * be 0 in the non-64-bit case anyway.
*/
-blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode)
+blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
{
- return (inode->i_file_acl |
- (__u64) inode->osd2.linux2.l_i_file_acl_high << 32);
+ blk64_t blk = inode->i_file_acl;
+
+ if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
+ return blk;
}
/*
* Set the acl block of a file
*/
-void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk)
+void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
+ blk64_t blk)
{
inode->i_file_acl = blk;
- inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
+ if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
}
diff --git a/lib/ext2fs/bmove.c b/lib/ext2fs/bmove.c
index d057998..e2ea405 100644
--- a/lib/ext2fs/bmove.c
+++ b/lib/ext2fs/bmove.c
@@ -141,7 +141,7 @@
while (ino) {
if ((inode.i_links_count == 0) ||
- !ext2fs_inode_has_valid_blocks(&inode))
+ !ext2fs_inode_has_valid_blocks2(fs, &inode))
goto next;
pb.ino = ino;
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 411a383..57c5bfa 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -841,8 +841,10 @@
extern void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags);
extern __u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group);
extern void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum);
-extern blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode);
-extern void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk);
+extern blk64_t ext2fs_file_acl_block(ext2_filsys fs,
+ const struct ext2_inode *inode);
+extern void ext2fs_file_acl_block_set(ext2_filsys fs,
+ struct ext2_inode *inode, blk64_t blk);
/* block.c */
extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
@@ -1396,6 +1398,8 @@
/* valid_blk.c */
extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
+extern int ext2fs_inode_has_valid_blocks2(ext2_filsys fs,
+ struct ext2_inode *inode);
/* version.c */
extern int ext2fs_parse_version_string(const char *ver_string);
diff --git a/lib/ext2fs/valid_blk.c b/lib/ext2fs/valid_blk.c
index 9047f41..895e36e 100644
--- a/lib/ext2fs/valid_blk.c
+++ b/lib/ext2fs/valid_blk.c
@@ -24,7 +24,7 @@
* This function returns 1 if the inode's block entries actually
* contain block entries.
*/
-int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
+int ext2fs_inode_has_valid_blocks2(ext2_filsys fs, struct ext2_inode *inode)
{
/*
* Only directories, regular files, and some symbolic links
@@ -39,7 +39,7 @@
* target is stored in the block entries.
*/
if (LINUX_S_ISLNK (inode->i_mode)) {
- if (ext2fs_file_acl_block(inode) == 0) {
+ if (ext2fs_file_acl_block(fs, inode) == 0) {
/* With no EA block, we can rely on i_blocks */
if (inode->i_blocks == 0)
return 0;
@@ -54,3 +54,8 @@
}
return 1;
}
+
+int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
+{
+ return ext2fs_inode_has_valid_blocks2(NULL, inode);
+}