Your message dated Sun, 06 Oct 2024 06:34:23 +0000
with message-id <[email protected]>
and subject line Bug#1081011: fixed in dump 0.4b47-6
has caused the Debian Bug report #1081011,
regarding dump: Restore of directory attributes fails if they're split across 
two blocks.
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1081011: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1081011
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: dump
Version: 0.4b47-4+~tjw12r5
Severity: important

Dear Maintainer,

Many years ago I reported a bug with verifying attributes on files where
the count was sometimes wrong. You fixed this (Thanks!)

However, it turns out the same bug is present for directories too.

Unfortunately, the fix for files meant that directories *verified*
correctly but did not restore correctly.

The attached patch *replaces* the xattr_verify patch currently in the
package and includes fix for the directory attributes which now both
restore and verify successfully.

(I haven't actually tested failure cases for the verify yet - i.e.
adding, removing or modifying an attribute between backup and verify)

-- System Information:
Debian Release: 12.7
  APT prefers stable-security
  APT policy: (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 6.1.0-25-amd64 (SMP w/4 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: sysvinit (via /sbin/init)

Versions of packages dump depends on:
ii  libblkid1     2.38.1-5+deb12u1
ii  libbz2-1.0    1.0.8-5+b1
ii  libc6         2.36-9+deb12u8
ii  libcom-err2   1.47.0-2
ii  libext2fs2    1.47.0-2
ii  liblzo2-2     2.10-2
ii  libreadline8  8.2-1.3
ii  libselinux1   3.4-1+b6
ii  tar           1.34+dfsg-1.2+deb12u1
ii  zlib1g        1:1.2.13.dfsg-1

dump recommends no packages.

dump suggests no packages.

-- no debconf information
diff -urN dump-0.4b47.orig/restore/dirs.c dump-0.4b47/restore/dirs.c
--- dump-0.4b47.orig/restore/dirs.c     2022-05-03 10:02:27.000000000 +0000
+++ dump-0.4b47/restore/dirs.c  2022-05-03 10:02:27.000000000 +0000
@@ -181,7 +181,7 @@
        struct inotab *itp;
        struct direct nulldir;
        int fd;
-       char xattr[XATTR_MAXSIZE];
+       char xattr[XATTR_MAXSIZE*2] = {0};
        int xattr_found = 0;
        _Bool is_tmp = command != 'r' && command != 'R';
        dump_ino_t ino;
@@ -248,7 +248,7 @@
                                skipfile();
                                break;
                        case EXT_XATTR:
-                               if (readxattr(xattr) == GOOD)
+                               if (readxattr(xattr+xattr_found*XATTR_MAXSIZE) 
== GOOD)
                                        xattr_found = 1;
                                break;
                        }
@@ -667,14 +667,14 @@
        }
        clearerr(mf);
        for (;;) {
-               char xattr[XATTR_MAXSIZE];
+               char xattr[XATTR_MAXSIZE*2];
                if (fread((char *)&node, sizeof(struct modeinfo), 1, mf) != 1) {
                        if (feof(mf))
                                break;
                        err(1, "fread");
                }
                if (node.xattr) {
-                       if (fread(xattr, XATTR_MAXSIZE, 1, mf) != 1) {
+                       if (fread(xattr, XATTR_MAXSIZE*2, 1, mf) != 1) {
                                if (feof(mf))
                                        break;
                                err(1, "fread");
@@ -701,8 +701,13 @@
                                warn("chown");
                        (void) chmod(cp, node.mode);
                        utimes(cp, node.timep);
-                       if (node.xattr)
+                       if (node.xattr) {
                                xattr_extract(cp, xattr);
+                               char* xattr2 = xattr + XATTR_MAXSIZE;
+                               if (*(uint32_t*)xattr2 != 0) {
+                                       xattr_extract(cp, xattr2);
+                               }
+                       }
                        ep->e_flags &= ~NEW;
                        if (node.flags)
 #ifdef __linux__
@@ -746,14 +751,14 @@
        }
        clearerr(mf);
        for (;;) {
-               char xattr[XATTR_MAXSIZE];
+               char xattr[XATTR_MAXSIZE*2];
                if (fread((char *)&node, sizeof(struct modeinfo), 1, mf) != 1) {
                        if (feof(mf))
                                break;
                        err(1, "fread");
                }
                if (node.xattr) {
-                       if (fread(xattr, XATTR_MAXSIZE, 1, mf) != 1) {
+                       if (fread(xattr, XATTR_MAXSIZE*2, 1, mf) != 1) {
                                if (feof(mf))
                                        break;
                                err(1, "fread");
@@ -805,14 +810,32 @@
                                }
                        }
 #endif
+                       int xattr_count_all = 0;
                        if (node.xattr) {
+                               int xattr_count_thisblock;
                                if (xattr_compare(cp, xattr) == FAIL)
                                        do_compare_error;
+                               xattr_count(xattr, &xattr_count_thisblock);
+                               xattr_count_all += xattr_count_thisblock;
+                               char* xattr2 = xattr + XATTR_MAXSIZE;
+                               if (*(uint32_t*)xattr2 != 0) {
+                                       xattr_extract(cp, xattr2);
+                                       xattr_count(xattr2, 
&xattr_count_thisblock);
+                                       xattr_count_all += 
xattr_count_thisblock;
+                               }
                        }
                        else {
                                if (xattr_compare(cp, NULL) == FAIL)
                                        do_compare_error;
                        }
+                       int count_file = xattr_count_file(cp);
+                       if (count_file < 0) {
+                               do_compare_error;
+                       } else if (count_file != xattr_count_all) {
+                               fprintf(stderr, "%s: directory does not have 
the same number of attributes (%d) as the tape (%d).\n",
+                                                               cp, count_file, 
xattr_count_all );
+                               do_compare_error;
+                       }
                        ep->e_flags &= ~NEW;
                }
        }
@@ -925,7 +948,7 @@
        if ( fwrite((char *)&node, sizeof(struct modeinfo), 1, mf) != 1 )
                err(1,"cannot write to file %s", modefile);
        if (xattr)
-               if ( fwrite(xattr, XATTR_MAXSIZE, 1, mf) != 1 )
+               if ( fwrite(xattr, XATTR_MAXSIZE*2, 1, mf) != 1 )
                        err(1,"cannot write to file %s", modefile);
 }
 
diff -urN dump-0.4b47.orig/restore/extern.h dump-0.4b47/restore/extern.h
--- dump-0.4b47.orig/restore/extern.h   2022-05-03 10:02:27.000000000 +0000
+++ dump-0.4b47/restore/extern.h        2022-05-03 10:02:27.000000000 +0000
@@ -154,3 +154,5 @@
 int    readxattr (char *);
 int    xattr_compare (char *, char *);
 int    xattr_extract (char *, char *);
+int xattr_count_file (char *);
+int xattr_count (char *, int *);
diff -urN dump-0.4b47.orig/restore/tape.c dump-0.4b47/restore/tape.c
--- dump-0.4b47.orig/restore/tape.c     2022-05-03 10:02:27.000000000 +0000
+++ dump-0.4b47/restore/tape.c  2022-05-03 10:02:27.000000000 +0000
@@ -1711,39 +1711,63 @@
 }
 #endif /* !COMPARE_ONTHEFLY */
 
+/* collect both extended attribute tape blocks, then
+       compare the attributes */
 static void
 compareattr(char *name)
 {
        int xattr_done = 0;
+       int xattr_count_all = 0;
 
        while (spcl.c_flags & DR_EXTATTRIBUTES) {
-               switch (spcl.c_extattributes) {
-               case EXT_MACOSFNDRINFO:
-                       msg("MacOSX not supported for comparision in this 
version, skipping\n");
-                       skipfile();
-                       break;
-               case EXT_MACOSRESFORK:
-                       msg("MacOSX not supported for comparision in this 
version, skipping\n");
-                       skipfile();
-                       break;
-               case EXT_XATTR: {
-                       char xattr[XATTR_MAXSIZE];
+                       switch (spcl.c_extattributes) {
+                               case EXT_MACOSFNDRINFO:
+                                               msg("MacOSX not supported for 
comparision in this version, skipping\n");
+                                               skipfile();
+                                               break;
+                               case EXT_MACOSRESFORK:
+                                               msg("MacOSX not supported for 
comparision in this version, skipping\n");
+                                               skipfile();
+                                               break;
+                               case EXT_XATTR: {
+                                               char xattr[XATTR_MAXSIZE];
+                                               int xattr_count_thisblock = 0;
 
-                       if (readxattr(xattr) == GOOD) {
-                               if (xattr_compare(name, xattr) == FAIL)
-                                       do_compare_error;
-                               xattr_done = 1;
-                       }
-                       else
-                               do_compare_error;
-                       break;
-               }
+                                               /* in-inode xattr record comes 
first, if present at all; then block xattr */
+                                               if (readxattr(xattr) == GOOD) {
+                                                       /* this returns fail if 
the buffer contains different attributes
+                                                                       than 
the file on disk; note that it mustn't return fail if the file on disk has more 
attributes! */
+                                                       if (xattr_compare(name, 
xattr) == FAIL)
+                                                                       
do_compare_error;
+
+                                                       xattr_count(xattr, 
&xattr_count_thisblock);
+                                                       xattr_count_all += 
xattr_count_thisblock;
+                                                       xattr_done = 1;
+                                               }
+                                               else
+                                                       do_compare_error;
+                                               break;
+                               }
                default:
                        msg("unexpected inode extension %ld, skipping\n", 
spcl.c_extattributes);
                        skipfile();
                        break;
                }
        }
+
+       /* cover the case of two xattr sources, the contents of which matched 
the file on disk:
+                       the only uncovered case left is if there re more 
attributes on disk than observed on tape */
+       if (xattr_done) {
+                       int count_file = xattr_count_file(name);
+                       if (count_file < 0) {
+                               do_compare_error;
+                       } else if (count_file != xattr_count_all) {
+                               fprintf(stderr, "%s: file does not have the 
same number of attributes (%d) as the tape (%d).\n",
+                                                               name, 
count_file, xattr_count_all );
+                               do_compare_error;
+                       }
+       }
+       /* no attrs whatsoever? file must have none then as well */
        if (!xattr_done && xattr_compare(name, NULL) == FAIL)
                do_compare_error;
 }
diff -urN dump-0.4b47.orig/restore/xattr.c dump-0.4b47/restore/xattr.c
--- dump-0.4b47.orig/restore/xattr.c    2022-05-03 10:02:27.000000000 +0000
+++ dump-0.4b47/restore/xattr.c 2022-05-03 10:02:27.000000000 +0000
@@ -123,7 +123,7 @@
 static int xattr_cb_set (char *, char *, int, int, void *);
 static int xattr_cb_compare (char *, char *, int, int, void *);
 static int xattr_verify (char *);
-static int xattr_count (char *, int *);
+int xattr_count (char *, int *);
 static int xattr_walk (char *, int (*)(char *, char *, int, int, void *), void 
*);
 
 #define POSIX_ACL_XATTR_VERSION 0x0002
@@ -373,7 +373,7 @@
 #endif
                valuesz = lgetxattr(path, name, valuef, XATTR_MAXSIZE);
                if (valuesz < 0) {
-                       warn("%s: EA compare lgetxattr failed\n", path);
+                       warn("%s: EA compare lgetxattr for %s failed\n", path, 
name);
                        return FAIL;
                }
 #ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
@@ -381,8 +381,9 @@
 #endif
 
        if (valuesz != valuelen || memcmp(value, valuef, valuelen)) {
+               valuef[valuesz] = '\0';
                /* GAN24May06: show name and new value for user to compare */
-               fprintf(stderr, "%s: EA %s:%s value changed to %s\n", path, 
name, value, valuef);
+               fprintf(stderr, "%s: EA %s value changed from %s on tape to %s 
on disk\n", path, name, value, valuef);
                return FAIL;
        }
 
@@ -429,7 +430,7 @@
        return GOOD;
 }
 
-static int
+int
 xattr_count(char *buffer, int *count)
 {
        struct ext2_xattr_entry *entry;
@@ -493,6 +494,7 @@
                size = entry->e_value_size;
 
                memcpy(value, buffer + VALUE_OFFSET(buffer, entry), size);
+               value[size]='\0';
 
                if (convertacl) {
                        struct posix_acl *acl;
@@ -540,43 +542,58 @@
        return GOOD;
 }
 
-int
-xattr_compare(char *path, char *buffer)
+/* return count of the xattrs on the given file or FAIL if failed */
+int xattr_count_file(char *path)
 {
-       int countf, countt;
+       int size, count = 0;
        char *names = NULL, *end_names, *name;
 
-       countf = llistxattr(path, NULL, 0);
-       if (countf < 0) {
-               warn("%s: llistxattr failed", path);
-               return FAIL;
+       /* return number of bytes a/v */
+       size = llistxattr(path, NULL, 0);
+       if (size < 0) {
+                       warn("%s: llistxattr failed", path);
+                       return FAIL;
        }
 
-       names = malloc(countf + 1);
-       if (!names) {
-               warn("%s: llistxattr failed", path);
-               return FAIL;
+       names = malloc(size + 1);
+       if (!names)
+       {
+                       warn("%s: malloc failed", path);
+                       return FAIL;
        }
 
-       countf = llistxattr(path, names, countf);
-       if (countf < 0) {
-               warn("%s: llistxattr failed", path);
-               free(names);
-               return FAIL;
+       /* return nr of bytes and park data in names array */
+       size = llistxattr(path, names, size);
+       if (size < 0)
+       {
+                       warn("%s: llistxattr failed", path);
+                       free(names);
+                       return FAIL;
        }
 
-       names[countf] = '\0';
-       end_names = names + countf;
+       names[size] = '\0';
+       end_names = names + size;
 
-       countf = 0;
-       for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
-               if (!*name)
-                       continue;
-               countf++;
+       for (name = names; name != end_names; name = strchr(name, '\0') + 1)
+       {
+                       if (!*name)
+                               continue;
+                       count++;
        }
-
        free(names);
 
+       return count;
+}
+
+int
+xattr_compare(char *path, char *buffer)
+{
+       int countf, countt;
+
+       countf = xattr_count_file(path); /* already warns on failure */
+       if (countf < 0)
+                       return FAIL;
+
        if (buffer) {
                if (xattr_verify(buffer) == FAIL)
                        return FAIL;
@@ -587,10 +604,20 @@
        else
                countt = 0;
 
-       if (countf != countt) {
-               fprintf(stderr, "%s: EA count changed from %d to %d\n", path, 
countt, countf);
+       /* with ext4 there may be two tape blocks for attrs: one from the 
actual inode, plus
+               one extra filesystem block. in this case countf must be at 
least >= countt;
+               verification of that aspect is delayed and left to compareattr
+               which loops over the different blocks */
+
+       /* nothing on tape but something on disk? sure fail. ditto for more on 
tape than on disk. */
+       if (countf > 0 && !countt)
+       {
+               fprintf(stderr, "%s: file does not have the same number of 
attributes (%d) as the tape (%d).\n",
+                                               path, countf, countt);
                return FAIL;
        }
+       if (countf < countt)
+               return FAIL;                                                    
        /* warning left to compareattr */
 
        if (!buffer)
                return GOOD;

--- End Message ---
--- Begin Message ---
Source: dump
Source-Version: 0.4b47-6
Done: Alexander Zangerl <[email protected]>

We believe that the bug you reported is fixed in the latest version of
dump, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Alexander Zangerl <[email protected]> (supplier of updated dump package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Sun, 06 Oct 2024 11:12:02 +1000
Source: dump
Architecture: source
Version: 0.4b47-6
Distribution: unstable
Urgency: high
Maintainer: Alexander Zangerl <[email protected]>
Changed-By: Alexander Zangerl <[email protected]>
Closes: 1081008 1081009 1081010 1081011
Changes:
 dump (0.4b47-6) unstable; urgency=high
 .
   * applied patches from tim woodall that repair a substantial
     number of compatibility issues
     (closes: #1081008, #1081009, #1081010, #1081011)
   * new -q option for restore
Checksums-Sha1:
 433c168cd2c590c39cc6924b9e946b365aa0c9f6 1907 dump_0.4b47-6.dsc
 7b2c610c084c2f1df365d20b2854b571709f98b7 57832 dump_0.4b47-6.debian.tar.xz
 1cf7e511cb8ddc6787cde7a0f1f834f84bb52ea5 8198 dump_0.4b47-6_amd64.buildinfo
Checksums-Sha256:
 724df1ef108de0c2e8a92bafa95e8e5a1b65b9d0362a5ac986c0757feea602a0 1907 
dump_0.4b47-6.dsc
 47bd200af219dc5e1909da94e0551fa43d85c063c7245b42b7c5c9628dc5b0b7 57832 
dump_0.4b47-6.debian.tar.xz
 262576c8f66c68415bbe5bf93fe1d0154928b2cdd19a252edc6dbf5ef45830a0 8198 
dump_0.4b47-6_amd64.buildinfo
Files:
 27255552bae4c88ed3180ad948d8776d 1907 utils optional dump_0.4b47-6.dsc
 3fab8c0c1e8f97328d3b3b8b53f72223 57832 utils optional 
dump_0.4b47-6.debian.tar.xz
 7094caec6e327f8a7f82629da7ae7e6d 8198 utils optional 
dump_0.4b47-6_amd64.buildinfo

-----BEGIN PGP SIGNATURE-----

iQIbBAEBCgAGBQJnAivQAAoJED06g4g30PqNxNoP9RHwi/OVonHkQoDkaxFVrcQr
JZm2T+sZZZQhhce1D+6rnvugKNpuCYQIdFrw4IMNOi0Kj5HQl6x3FM8t3oYkgSmc
uLWKPFI6uJ21sinZnaJCh1cvAh4qbzZu8qeF1M9AEs8D+P4hbbLDJW74E7VCrFCF
z02/gxose+JoDlFPgOOIhc9w/RewveutxD31bDfagjNZ9q5Prp/wHR+WipQqKsm5
ZeZz7+9WpKFEAIoG2xkF4PFKx+M6/HqkP0PjPjjltbkeR4N+P6N3hqjm5HQSTs2Y
o2Io8yXOHIcrXRGp4FYaFHhHJ1UpOtlEEUF5n5Qy5vXMXuTFcLd3kLXfKrBmu0Py
Fm7xtST5bajak2IfZBMMwzy3Z8TstFluYJ1AgWJJjDtACIEdRSWIFOXLrrS3rYTX
8NcmqhDXu9i+pjLUK96U7lGXT7O6RzF/oiilNvBU3LFnqw1BROVigCnSavallDxi
KXtKRT0didKr3tE38gSQJ8K5GrZo+pryIP7zxw7CWQMrWHgBSfwngEdMUFF7lZEw
Ie6LAorl2P2kVJm9cPvnCHDBurxDTpoKQfCkT0DKE9JBhZjz59cEAbqHoZktZIft
nmxl4O9hiWS4/n9Hu2ygeE8OWzc/NMx0uRCSsb23MT7mHcD6j43lYnfV1SSul5rL
RmINxbWAb83GY2utGaQ=
=rfWZ
-----END PGP SIGNATURE-----

Attachment: pgpv65isjN3ay.pgp
Description: PGP signature


--- End Message ---

Reply via email to