I've found a bug in the original patches where it wasn't correctly dumping an EA block >2^32. The original patch also relied on a cast to a 64 bit value which only worked on little endian and only if the next four bytes were zero (which they appear to always be)
This patch now addresses both those problems. I changed compat/include/bsdcompat.h. I can't find where this file is originally from and so whether there's an official version that could be imported that has the relevant updates. This change isn't strictly necessary, di_pad1 could be used in place of osd2.linux2.l_i_file_acl_high but I thought this was preferable.
testcase.sh
Description: Bourne shell script
diff -urN dump-0.4b47.orig/compat/include/bsdcompat.h dump-0.4b47/compat/include/bsdcompat.h --- dump-0.4b47.orig/compat/include/bsdcompat.h 2021-01-01 16:28:57.000000000 +0000 +++ dump-0.4b47/compat/include/bsdcompat.h 2021-01-01 16:28:57.000000000 +0000 @@ -115,32 +115,58 @@ #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] diff -urN dump-0.4b47.orig/dump/dump.h dump-0.4b47/dump/dump.h --- dump-0.4b47.orig/dump/dump.h 2022-05-03 10:02:27.000000000 +0000 +++ dump-0.4b47/dump/dump.h 2022-05-03 10:02:27.000000000 +0000 @@ -140,8 +140,8 @@ int mapdirs (dump_ino_t maxino, long long *tapesize); /* file dumping routines */ -void blksout (blk_t *blkp, int frags, dump_ino_t ino); -void bread (ext2_loff_t blkno, char *buf, int size); +void blksout (blk64_t *blkp, int frags, dump_ino_t ino); +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); @@ -153,7 +153,7 @@ /* tape writing routines */ int alloctape (void); void close_rewind (void); -void dumpblock (blk_t blkno, int size); +void dumpblock (blk64_t blkno, int size); void startnewtape (int top); time_t trewind (void); void writerec (const void *dp, int isspcl); diff -urN dump-0.4b47.orig/dump/tape.c dump-0.4b47/dump/tape.c --- dump-0.4b47.orig/dump/tape.c 2022-05-03 10:02:27.000000000 +0000 +++ dump-0.4b47/dump/tape.c 2022-05-03 10:02:27.000000000 +0000 @@ -254,7 +254,7 @@ } void -dumpblock(blk_t blkno, int size) +dumpblock(blk64_t blkno, int size) { int avail, tpblks; ext2_loff_t dblkno; diff -urN dump-0.4b47.orig/dump/traverse.c dump-0.4b47/dump/traverse.c --- dump-0.4b47.orig/dump/traverse.c 2021-01-01 16:28:57.000000000 +0000 +++ dump-0.4b47/dump/traverse.c 2021-01-01 16:28:57.000000000 +0000 @@ -748,7 +748,7 @@ struct block_context { ext2_ino_t ino; - blk_t *buf; + blk64_t *buf; int cnt; int max; int next_block; @@ -758,8 +758,8 @@ * 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; @@ -831,7 +831,7 @@ #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); @@ -840,7 +840,9 @@ spcl.c_dinode.di_size = sblock->fs_bsize; spcl.c_flags |= DR_EXTATTRIBUTES; spcl.c_extattributes = EXT_XATTR; - blksout(&dp->di_file_acl, EXT2_FRAGS_PER_BLOCK(fs->super), ino); + // debugfs.c does something special for HURD that this might break? + blk64_t acl = dp->di_file_acl | ((long long)dp->osd2.linux2.l_i_file_acl_high<<32); + blksout(&acl, EXT2_FRAGS_PER_BLOCK(fs->super), ino); spcl.c_flags &= ~DR_EXTATTRIBUTES; spcl.c_extattributes = 0; } @@ -891,8 +893,8 @@ 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; @@ -978,12 +980,12 @@ } #ifdef __linux__ bc.max = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super); - bc.buf = malloc (bc.max * sizeof (int)); + bc.buf = malloc (bc.max * sizeof (blk64_t)); bc.cnt = 0; bc.ino = ino; bc.next_block = 0; - ext2fs_block_iterate2(fs, (ext2_ino_t)ino, BLOCK_FLAG_DATA_ONLY, NULL, dumponeblock, (void *)&bc); + ext2fs_block_iterate3(fs, (ext2_ino_t)ino, BLOCK_FLAG_DATA_ONLY, NULL, dumponeblock, (void *)&bc); /* deal with holes at the end of the inode */ if (i_size > ((uint64_t)bc.next_block) * sblock->fs_fsize) { remaining = i_size - ((uint64_t)bc.next_block) * sblock->fs_fsize; @@ -1157,8 +1159,8 @@ 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; @@ -1261,9 +1263,9 @@ * Collect up the data into tape record sized buffers and output them. */ void -blksout(blk_t *blkp, int frags, dump_ino_t ino) +blksout(blk64_t *blkp, int frags, dump_ino_t ino) { - blk_t *bp; + blk64_t *bp; int i, j, count, blks, tbperdb; blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); @@ -1394,7 +1396,7 @@ 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;