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;

