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);
+}