Description: Handle FS with more than 2^32 blocks
 Original patch provided by Greg Oster in https://sourceforge.net/p/dump/bugs/174/
 Extended patch to correctly handle extended attributes stored
 in blocks >2^32
Author: Tim Woodall <debianbugs@woodall.me.uk>

--- a/compat/include/bsdcompat.h
+++ b/compat/include/bsdcompat.h
@@ -115,32 +115,58 @@ typedef unsigned char u_char;
 #endif /* sunos */
 
 struct dinode {
-	__u16	di_mode;
+/*00*/	__u16	di_mode;
 	__u16	di_uid;
 	__u32	di_size;
 	__u32	di_atime;
 	__u32	di_ctime;
-	__u32	di_mtime;
+/*10*/	__u32	di_mtime;
 	__u32	di_dtime;
 	__u16	di_gid;
 	__u16	di_nlink;
 	__u32	di_blocks;
-	__u32	di_flags;
-	__u32	di_reserved1;
-	__u32	di_db[NDADDR];
+/*20*/	__u32	di_flags;
+	union {
+		struct {
+			__u32	l_di_version;		/* linux was di_reserved1 */
+		} linux1;
+		struct {
+			__u32	h_di_translator;	/* hurd */
+		} hurd1;
+	} osd1; /* was di_reserved1 */
+/*28*/	__u32	di_db[NDADDR];
 	__u32	di_ib[NIADDR];
-	__u32	di_gen;
+/*64*/	__u32	di_gen;
 	__u32	di_file_acl;
 	__u32	di_dir_acl;
-	__u32	di_faddr;
-	__u8	di_frag;
-	__u8	di_fsize;
-	__u16	di_pad1;
-	__u16	di_uidhigh;
-	__u16	di_gidhigh;
-	__u32	di_spare;
-	__u16	di_extraisize;
-	__u16	di_pad2;
+/*70*/	__u32	di_faddr;
+	union {
+		struct {
+			__u16	l_i_blocks_hi;
+			__u16	l_i_file_acl_high;
+			__u16	l_i_uid_high;
+			__u16	l_i_gid_high;
+			__u16	l_i_checksum_lo;
+			__u16	l_i_reserved;
+		} linux2;
+		struct {
+			__u8	di_frag;
+			__u8	di_fsize;
+			__u16	di_mode_high; /* was di_pad1 */
+			__u16	di_uidhigh;
+			__u16	di_gidhigh;
+			__u32	di_spare;
+		} hurd2;
+	} osd2;
+/*80*/	__u16	di_extraisize;
+	__u16	i_checksum_hi;	/* crc32c(uuid+inum+inode) */ /* was di_pad2 */
+	__u32	i_ctime_extra;	/* extra Change time (nsec << 2 | epoch) */
+	__u32	i_mtime_extra;	/* extra Modification time (nsec << 2 | epoch) */
+	__u32	i_atime_extra;	/* extra Access time (nsec << 2 | epoch) */
+/*90*/	__u32	i_crtime;	/* File creation time */
+	__u32	i_crtime_extra;	/* extra File creation time (nsec << 2 | epoch)*/
+	__u32	i_version_hi;	/* high 32 bits for 64-bit version */
+/*9c*/	__u32	i_projid;       /* Project ID */
 };
 
 #define di_rdev		di_db[0]
--- a/dump/dump.h
+++ b/dump/dump.h
@@ -140,7 +140,7 @@ int	maponefile (dump_ino_t maxino, long
 int	mapdirs (dump_ino_t maxino, long long *tapesize);
 
 /* file dumping routines */
-void	bread (ext2_loff_t blkno, char *buf, int size);
+void	bread (ext2_loff_t blkno, char *buf, size_t size);
 void	dumpino (struct dinode *dp, dump_ino_t ino, int metaonly);
 #ifdef	__linux__
 void	dumpdirino (struct dinode *dp, dump_ino_t ino);
--- a/dump/traverse.c
+++ b/dump/traverse.c
@@ -757,7 +757,7 @@ struct block_context {
 	struct block_info	*buf;
 	int	cnt;
 	int	max;
-	int	next_block;
+	e2_blkcnt_t	next_block;
 	int	uninit;
 };
 
@@ -767,8 +767,8 @@ static void blksout (struct block_info *
  * Dump a block to the tape
  */
 static int
-dumponeblock(UNUSED(ext2_filsys fs), blk_t *blocknr, e2_blkcnt_t blockcnt,
-	     UNUSED(blk_t ref_block), UNUSED(int ref_offset), void * private)
+dumponeblock(UNUSED(ext2_filsys fs), blk64_t *blocknr, e2_blkcnt_t blockcnt,
+	     UNUSED(blk64_t ref_block), UNUSED(int ref_offset), void * private)
 {
 	struct block_context *p;
 	e2_blkcnt_t i;
@@ -842,7 +842,7 @@ dump_xattr(dump_ino_t ino, struct dinode
 #endif
 	}
 
-	if (dp->di_file_acl) {
+	if (dp->di_file_acl || dp->osd2.linux2.l_i_file_acl_high) {
 
 		if (vflag)
 			msg("dumping EA (block) in inode #%ld\n", (long)ino);
@@ -851,8 +851,9 @@ dump_xattr(dump_ino_t ino, struct dinode
 		spcl.c_dinode.di_size = sblock->fs_bsize;
 		spcl.c_flags |= DR_EXTATTRIBUTES;
 		spcl.c_extattributes = EXT_XATTR;
+    // debugfs.c does something special for HURD that this might break?
     struct block_info acl;
-		acl.blocknr = dp->di_file_acl | ((long long)dp->osd2.linux2.l_i_file_acl_high<<32);
+    acl.blocknr = dp->di_file_acl | ((long long)dp->osd2.linux2.l_i_file_acl_high<<32);
 		acl.uninit = 0;
 		blksout(&acl, EXT2_FRAGS_PER_BLOCK(fs->super), ino);
 		spcl.c_flags &= ~DR_EXTATTRIBUTES;
@@ -950,8 +951,8 @@ dumpino(struct dinode *dp, dump_ino_t in
 	nbi.di_flags = dp->di_flags;
 	nbi.di_blocks = dp->di_blocks;
 	nbi.di_gen = dp->di_gen;
-	nbi.di_uid = (((int32_t)dp->di_uidhigh) << 16) | dp->di_uid;
-	nbi.di_gid = (((int32_t)dp->di_gidhigh) << 16) | dp->di_gid;
+	nbi.di_uid = (((int32_t)dp->osd2.hurd2.di_uidhigh) << 16) | dp->di_uid;
+	nbi.di_gid = (((int32_t)dp->osd2.hurd2.di_gidhigh) << 16) | dp->di_gid;
 	memmove(&spcl.c_dinode, &nbi, sizeof(nbi));
 #else	/* __linux__ */
 	spcl.c_dinode = *dp;
@@ -1228,8 +1229,8 @@ dumpdirino(struct dinode *dp, dump_ino_t
 	nbi.di_flags = dp->di_flags;
 	nbi.di_blocks = dp->di_blocks;
 	nbi.di_gen = dp->di_gen;
-	nbi.di_uid = (((int32_t)dp->di_uidhigh) << 16) | dp->di_uid;
-	nbi.di_gid = (((int32_t)dp->di_gidhigh) << 16) | dp->di_gid;
+	nbi.di_uid = (((int32_t)dp->osd2.hurd2.di_uidhigh) << 16) | dp->di_uid;
+	nbi.di_gid = (((int32_t)dp->osd2.hurd2.di_gidhigh) << 16) | dp->di_gid;
 	memmove(&spcl.c_dinode, &nbi, sizeof(nbi));
 #else	/* __linux__ */
 	spcl.c_dinode = *dp;
@@ -1468,7 +1469,7 @@ getino(dump_ino_t inum)
 int	breaderrors = 0;
 
 void
-bread(ext2_loff_t blkno, char *buf, int size)
+bread(ext2_loff_t blkno, char *buf, size_t size)
 {
 	int cnt, i;
 
