]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Use Gnulib’s same-inode module
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 9 Aug 2025 23:10:49 +0000 (16:10 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 14 Aug 2025 17:27:28 +0000 (10:27 -0700)
This is more portable to non-POSIX systems.
However, don’t bother trying to port to systems
where st_ino is not a scalar of type dev_t,
as these systems no longer seem to be active targets
and it’s not worth the maintenance hassle.
* gnulib.modules: Add same-inode, now that we use it
explicitly rather than indirectly.
* src/compare.c (diff_link):
* src/create.c (compare_links, restore_parent_fd):
* src/incremen.c (compare_directory_meta, procdir):
* src/extract.c (dl_compare, repair_delayed_set_stat)
(apply_nonancestor_delayed_set_stat, extract_link)
(apply_delayed_link):
* src/names.c (add_file_id):
* src/system.c (sys_file_is_archive, sys_detect_dev_null_output):
Include same-inode.h, and prefer its macros and functions
to doing things by hand.
* src/create.c (struct link):
* src/extract.c (struct delayed_set_stat, struct delayed_link):
* src/incremen.c (struct directory):
* src/names.c (struct file_id_list):
Rename members to st_dev and st_ino so that SAME_INODE and
PSAME_INODE can be used on the type.  All uses changed.
* src/system.c (sys_compare_links): Remove.
All uses replaced by psame_inode.

gnulib.modules
src/common.h
src/compare.c
src/create.c
src/extract.c
src/incremen.c
src/names.c
src/system.c

index 796c1dcdf22b1ddcbe7ecf9d0d0efa5d0ca0b62a..8819b03b63510b08bb0cd2a83ad38bd2b0e920d0 100644 (file)
@@ -94,6 +94,7 @@ root-uid
 rpmatch
 full-read
 safe-read
+same-inode
 savedir
 selinux-at
 setenv
index 9bc0652358050ebbe4204ed82431d2ca316e2917..24c53cc4f1570dd2e568724953d775abb879b4ab 100644 (file)
@@ -942,7 +942,6 @@ void sys_spawn_shell (void);
 bool sys_compare_uid (struct stat *a, struct stat *b);
 bool sys_compare_gid (struct stat *a, struct stat *b);
 bool sys_file_is_archive (struct tar_stat_info *p);
-bool sys_compare_links (struct stat *link_data, struct stat *stat_data);
 int sys_truncate (int fd);
 pid_t sys_child_open_for_compress (void);
 pid_t sys_child_open_for_uncompress (void);
index 95a9118132ff26b23fb73532e0b5cb5ecb29dccd..c2d0d157a3b96a3fc2015689518493868d72c593 100644 (file)
@@ -34,6 +34,7 @@
 #include <alignalloc.h>
 #include <quotearg.h>
 #include <rmt.h>
+#include <same-inode.h>
 #include <stdarg.h>
 
 /* Nonzero if we are verifying at the moment.  */
@@ -251,7 +252,7 @@ diff_link (void)
 
   if (get_stat_data (current_stat_info.file_name, &file_data)
       && get_stat_data (current_stat_info.link_name, &link_data)
-      && !sys_compare_links (&file_data, &link_data))
+      && !psame_inode (&file_data, &link_data))
     report_difference (&current_stat_info,
                       _("Not linked to %s"),
                       quote_n_colon (QUOTE_ARG,
index 7da4560d84694f0a117a16f9b1d728c1e706bb61..078c77e1ecaadbe4df3de747fc8c7bd54dc69dcc 100644 (file)
@@ -24,6 +24,7 @@
 #include <areadlink.h>
 #include <flexmember.h>
 #include <quotearg.h>
+#include <same-inode.h>
 
 #include "common.h"
 #include <hash.h>
@@ -34,8 +35,8 @@ enum { IMPOSTOR_ERRNO = ENOENT };
 
 struct link
   {
-    dev_t dev;
-    ino_t ino;
+    dev_t st_dev;
+    ino_t st_ino;
     nlink_t nlink;
     char name[FLEXIBLE_ARRAY_MEMBER];
   };
@@ -1387,7 +1388,7 @@ static size_t
 hash_link (void const *entry, size_t n_buckets)
 {
   struct link const *l = entry;
-  uintmax_t num = l->dev ^ l->ino;
+  uintmax_t num = l->st_dev ^ l->st_ino;
   return num % n_buckets;
 }
 
@@ -1397,7 +1398,7 @@ compare_links (void const *entry1, void const *entry2)
 {
   struct link const *link1 = entry1;
   struct link const *link2 = entry2;
-  return ((link1->dev ^ link2->dev) | (link1->ino ^ link2->ino)) == 0;
+  return PSAME_INODE (link1, link2);
 }
 
 static void
@@ -1430,8 +1431,8 @@ dump_hard_link (struct tar_stat_info *st)
       off_t block_ordinal;
       union block *blk;
 
-      lp.ino = st->stat.st_ino;
-      lp.dev = st->stat.st_dev;
+      lp.st_dev = st->stat.st_dev;
+      lp.st_ino = st->stat.st_ino;
 
       if ((duplicate = hash_lookup (link_table, &lp)))
        {
@@ -1485,8 +1486,8 @@ file_count_links (struct tar_stat_info *st)
        }
 
       lp = xmalloc (FLEXNSIZEOF (struct link, name, strlen (linkname) + 1));
-      lp->ino = st->stat.st_ino;
-      lp->dev = st->stat.st_dev;
+      lp->st_dev = st->stat.st_dev;
+      lp->st_ino = st->stat.st_ino;
       lp->nlink = st->stat.st_nlink;
       strcpy (lp->name, linkname);
       free (linkname);
@@ -1560,8 +1561,7 @@ restore_parent_fd (struct tar_stat_info const *st)
       if (parentfd < 0)
        parentfd = - errno;
       else if (fstat (parentfd, &parentstat) < 0
-              || parent->stat.st_ino != parentstat.st_ino
-              || parent->stat.st_dev != parentstat.st_dev)
+              || !psame_inode (&parent->stat, &parentstat))
        {
          close (parentfd);
          parentfd = IMPOSTOR_ERRNO;
@@ -1574,8 +1574,7 @@ restore_parent_fd (struct tar_stat_info const *st)
          if (0 <= origfd)
            {
              if (fstat (parentfd, &parentstat) < 0
-                 || parent->stat.st_ino != parentstat.st_ino
-                 || parent->stat.st_dev != parentstat.st_dev)
+                 || !psame_inode (&parent->stat, &parentstat))
                close (origfd);
              else
                parentfd = origfd;
index 3b913c54398fe6f31442a9ec125fb4dd197765d9..7bf41feff52d7ec793918a4bfcdcb9089b81afbb 100644 (file)
@@ -26,6 +26,7 @@
 #include <hash.h>
 #include <priv-set.h>
 #include <root-uid.h>
+#include <same-inode.h>
 #include <utimens.h>
 
 #include "common.h"
@@ -85,8 +86,8 @@ struct delayed_set_stat
     struct delayed_set_stat *next;
 
     /* Metadata for this directory.  */
-    dev_t dev;
-    ino_t ino;
+    dev_t st_dev;
+    ino_t st_ino;
     mode_t mode; /* The desired mode is MODE & ~ current_umask.  */
     uid_t uid;
     gid_t gid;
@@ -147,8 +148,8 @@ struct delayed_link
        other process removes the placeholder.  Don't use ctime as
        this would cause race conditions and other screwups, e.g.,
        when restoring hard-linked symlinks.  */
-    dev_t dev;
-    ino_t ino;
+    dev_t st_dev;
+    ino_t st_ino;
 #if HAVE_BIRTHTIME
     struct timespec birthtime;
 #endif
@@ -203,11 +204,11 @@ static size_t
 dl_hash (void const *entry, size_t table_size)
 {
   struct delayed_link const *dl = entry;
-  uintmax_t n = dl->dev;
-  int nshift = TYPE_WIDTH (n) - TYPE_WIDTH (dl->dev);
+  uintmax_t n = dl->st_dev;
+  int nshift = TYPE_WIDTH (n) - TYPE_WIDTH (dl->st_dev);
   if (0 < nshift)
     n <<= nshift;
-  n ^= dl->ino;
+  n ^= dl->st_ino;
   return n % table_size;
 }
 
@@ -215,7 +216,7 @@ static bool
 dl_compare (void const *a, void const *b)
 {
   struct delayed_link const *da = a, *db = b;
-  return (da->dev == db->dev) & (da->ino == db->ino);
+  return PSAME_INODE (da, db);
 }
 
 static size_t
@@ -496,8 +497,8 @@ mark_after_links (struct delayed_set_stat *head)
        stat_error (h->file_name);
       else
        {
-         h->dev = st.st_dev;
-         h->ino = st.st_ino;
+         h->st_dev = st.st_dev;
+         h->st_ino = st.st_ino;
        }
     }
   while ((h = h->next) && ! h->after_links);
@@ -551,8 +552,8 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
            }
          else
            {
-             data->dev = real_st.st_dev;
-             data->ino = real_st.st_ino;
+             data->st_dev = real_st.st_dev;
+             data->st_ino = real_st.st_ino;
            }
        }
     }
@@ -568,8 +569,8 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
       data->after_links = false;
       if (st)
        {
-         data->dev = st->stat.st_dev;
-         data->ino = st->stat.st_ino;
+         data->st_dev = st->stat.st_dev;
+         data->st_ino = st->stat.st_ino;
        }
       xattr_map_init (&data->xattr_map);
     }
@@ -631,8 +632,8 @@ update_interdir_set_stat (char const *dir)
       data = hash_lookup (delayed_set_stat_table, &key);
       if (data && data->interdir)
        {
-         data->dev = current_stat_info.stat.st_dev;
-         data->ino = current_stat_info.stat.st_ino;
+         data->st_dev = current_stat_info.stat.st_dev;
+         data->st_ino = current_stat_info.stat.st_ino;
          data->mode = current_stat_info.stat.st_mode;
          data->uid = current_stat_info.stat.st_uid;
          data->gid = current_stat_info.stat.st_gid;
@@ -663,11 +664,10 @@ repair_delayed_set_stat (char const *dir,
          return;
        }
 
-      if (st.st_dev == dir_stat_info->st_dev
-         && st.st_ino == dir_stat_info->st_ino)
+      if (psame_inode (&st, dir_stat_info))
        {
-         data->dev = current_stat_info.stat.st_dev;
-         data->ino = current_stat_info.stat.st_ino;
+         data->st_dev = current_stat_info.stat.st_dev;
+         data->st_ino = current_stat_info.stat.st_ino;
          data->mode = current_stat_info.stat.st_mode;
          data->uid = current_stat_info.stat.st_uid;
          data->gid = current_stat_info.stat.st_gid;
@@ -1022,7 +1022,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
            {
              current_mode = st.st_mode;
              current_mode_mask = all_mode_bits;
-             if (! (st.st_dev == data->dev && st.st_ino == data->ino))
+             if (!SAME_INODE (st, *data))
                {
                  paxerror (0,
                            _("%s: Directory renamed before its status"
@@ -1416,8 +1416,8 @@ find_delayed_link_source (char const *name)
     }
 
   struct delayed_link dl;
-  dl.dev = st.st_dev;
-  dl.ino = st.st_ino;
+  dl.st_dev = st.st_dev;
+  dl.st_ino = st.st_ino;
   return hash_lookup (delayed_link_table, &dl) != NULL;
 }
 
@@ -1473,8 +1473,8 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
        xmalloc (FLEXNSIZEOF (struct delayed_link, target,
                              strlen (current_stat_info.link_name) + 1));
       p->next = NULL;
-      p->dev = st.st_dev;
-      p->ino = st.st_ino;
+      p->st_dev = st.st_dev;
+      p->st_ino = st.st_ino;
 #if HAVE_BIRTHTIME
       p->birthtime = get_stat_birthtime (&st);
 #endif
@@ -1545,8 +1545,8 @@ extract_link (char *file_name, MAYBE_UNUSED char typeflag)
              && fstatat (chdir_fd, link_name, &st1, AT_SYMLINK_NOFOLLOW) == 0)
            {
              struct delayed_link dl1;
-             dl1.ino = st1.st_ino;
-             dl1.dev = st1.st_dev;
+             dl1.st_ino = st1.st_ino;
+             dl1.st_dev = st1.st_dev;
              struct delayed_link *ds = hash_lookup (delayed_link_table, &dl1);
              if (ds && ds->change_dir == chdir_current
                  && BIRTHTIME_EQ (ds->birthtime, get_stat_birthtime (&st1)))
@@ -1567,8 +1567,7 @@ extract_link (char *file_name, MAYBE_UNUSED char typeflag)
                    == 0)
                   && (fstatat (chdir_fd, file_name, &st2, AT_SYMLINK_NOFOLLOW)
                       == 0)
-                  && st1.st_dev == st2.st_dev
-                  && st1.st_ino == st2.st_ino))
+                  && psame_inode (&st1, &st2)))
        return true;
 
       errno = e;
@@ -1894,8 +1893,7 @@ apply_delayed_link (struct delayed_link *ds)
         don't create a link, as the placeholder was probably
         removed by a later extraction.  */
       if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
-         && st.st_dev == ds->dev
-         && st.st_ino == ds->ino
+         && SAME_INODE (st, *ds)
          && BIRTHTIME_EQ (get_stat_birthtime (&st), ds->birthtime))
        {
          /* Unlink the placeholder, then create a hard link if possible,
index 020fa1f0a668dd9cae812b1eb40b808a1acc5a18..76f982b45ea433c742e4b2757da389d32c1e7313 100644 (file)
@@ -22,6 +22,7 @@
 #include <flexmember.h>
 #include <hash.h>
 #include <quotearg.h>
+#include <same-inode.h>
 #include "common.h"
 
 /* Incremental dump specialities.  */
@@ -73,8 +74,8 @@ struct directory
   {
     struct directory *next;
     struct timespec mtime;      /* Modification time */
-    dev_t device_number;       /* device number for directory */
-    ino_t inode_number;                /* inode number for directory */
+    dev_t st_dev;              /* device number for directory */
+    ino_t st_ino;              /* inode number for directory */
     struct dumpdir *dump;       /* Directory contents */
     struct dumpdir *idump;      /* Initial contents if the directory was
                                   rescanned */
@@ -284,7 +285,7 @@ hash_directory_meta (void const *entry, size_t n_buckets)
 {
   struct directory const *directory = entry;
   /* FIXME: Work out a better algorytm */
-  return (directory->device_number + directory->inode_number) % n_buckets;
+  return (directory->st_dev + directory->st_ino) % n_buckets;
 }
 
 /* Compare two directories for equality of their device and inode numbers. */
@@ -293,8 +294,7 @@ compare_directory_meta (void const *entry1, void const *entry2)
 {
   struct directory const *directory1 = entry1;
   struct directory const *directory2 = entry2;
-  return directory1->device_number == directory2->device_number
-            && directory1->inode_number == directory2->inode_number;
+  return PSAME_INODE (directory1, directory2);
 }
 
 /* Make a directory entry for given relative NAME and canonical name CANAME.
@@ -375,8 +375,8 @@ note_directory (char const *name, struct timespec mtime,
   struct directory *directory = attach_directory (name);
 
   directory->mtime = mtime;
-  directory->device_number = dev;
-  directory->inode_number = ino;
+  directory->st_dev = dev;
+  directory->st_ino = ino;
   directory->children = CHANGED_CHILDREN;
   if (nfs)
     dir_set_flag (directory, DIRF_NFS);
@@ -457,8 +457,8 @@ find_directory_meta (dev_t dev, ino_t ino)
     {
       struct directory *dir = make_directory ("", NULL);
       struct directory *ret;
-      dir->device_number = dev;
-      dir->inode_number = ino;
+      dir->st_dev = dev;
+      dir->st_ino = ino;
       ret = hash_lookup (directory_meta_table, dir);
       free_directory (dir);
       return ret;
@@ -528,10 +528,9 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
         directories, consider all NFS devices as equal,
         relying on the i-node to establish differences.  */
 
-      if (! ((!check_device_option
-             || (dir_is_nfs (directory) && nfs)
-             || directory->device_number == stat_data->st_dev)
-            && directory->inode_number == stat_data->st_ino))
+      if (! (!check_device_option || (dir_is_nfs (directory) && nfs)
+            ? directory->st_ino == stat_data->st_ino
+            : PSAME_INODE (directory, stat_data)))
        {
          /* FIXME: find_directory_meta ignores nfs */
          struct directory *d = find_directory_meta (stat_data->st_dev,
@@ -555,8 +554,8 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
            {
              perhaps_renamed = true;
              directory->children = ALL_CHILDREN;
-             directory->device_number = stat_data->st_dev;
-             directory->inode_number = stat_data->st_ino;
+             directory->st_dev = stat_data->st_dev;
+             directory->st_ino = stat_data->st_ino;
            }
          if (nfs)
            dir_set_flag (directory, DIRF_NFS);
@@ -1439,10 +1438,10 @@ write_directory_file_entry (void *entry, void *data)
       fwrite (s, strlen (s) + 1, 1, fp);
       int ns = directory->mtime.tv_nsec;
       fprintf (fp, "%d%c", ns, 0);
-      s = sysinttostr (directory->device_number,
+      s = sysinttostr (directory->st_dev,
                       TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf);
       fwrite (s, strlen (s) + 1, 1, fp);
-      s = sysinttostr (directory->inode_number,
+      s = sysinttostr (directory->st_ino,
                       TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), buf);
       fwrite (s, strlen (s) + 1, 1, fp);
 
index ebdec2e0cf14562196c8d37c334d9fbb1aa7a0b1..e1927ba48c0445e94ded2d8c296750f0e169ae5a 100644 (file)
@@ -21,6 +21,7 @@
 #include <fnmatch.h>
 #include <hash.h>
 #include <quotearg.h>
+#include <same-inode.h>
 #include <wordsplit.h>
 #include <argp.h>
 
@@ -881,8 +882,8 @@ name_init (void)
 struct file_id_list
 {
   struct file_id_list *next;
-  ino_t ino;
-  dev_t dev;
+  dev_t st_dev;
+  ino_t st_ino;
   const char *from_file;
 };
 
@@ -913,7 +914,7 @@ add_file_id (const char *filename)
     stat_fatal (filename);
   reading_from = file_list_name ();
   for (p = file_id_list; p; p = p->next)
-    if (p->ino == st.st_ino && p->dev == st.st_dev)
+    if (SAME_INODE (*p, st))
       {
        int oldc = set_char_quoting (NULL, ':', 1);
        paxerror (0, _("%s: file list requested from %s already read from %s"),
@@ -924,8 +925,8 @@ add_file_id (const char *filename)
       }
   p = xmalloc (sizeof *p);
   p->next = file_id_list;
-  p->ino = st.st_ino;
-  p->dev = st.st_dev;
+  p->st_dev = st.st_dev;
+  p->st_ino = st.st_ino;
   p->from_file = reading_from;
   file_id_list = p;
   return true;
index a52b8af47414bb25a983aabcda5604e0e91ccddc..7538b6b2dfe326247f8467621d4f7ddec391b997 100644 (file)
@@ -25,6 +25,7 @@
 #include "common.h"
 #include <priv-set.h>
 #include <rmt.h>
+#include <same-inode.h>
 #include <signal.h>
 #include <wordsplit.h>
 #include <poll.h>
@@ -125,12 +126,6 @@ sys_compare_gid (struct stat *a, struct stat *b)
   return true;
 }
 
-void
-sys_compare_links (struct stat *link_data, struct stat *stat_data)
-{
-  return true;
-}
-
 int
 sys_truncate (int fd)
 {
@@ -194,8 +189,7 @@ bool
 sys_file_is_archive (struct tar_stat_info *p)
 {
   return (!dev_null_output && !_isrmt (archive)
-         && p->stat.st_dev == archive_stat.st_dev
-         && p->stat.st_ino == archive_stat.st_ino);
+         && psame_inode (&p->stat, &archive_stat));
 }
 
 static char const dev_null[] = "/dev/null";
@@ -211,8 +205,7 @@ sys_detect_dev_null_output (void)
                         && S_ISCHR (archive_stat.st_mode)
                         && (dev_null_stat.st_ino != 0
                             || stat (dev_null, &dev_null_stat) == 0)
-                        && archive_stat.st_ino == dev_null_stat.st_ino
-                        && archive_stat.st_dev == dev_null_stat.st_dev));
+                        && psame_inode (&archive_stat, &dev_null_stat)));
 }
 
 void
@@ -279,13 +272,6 @@ sys_compare_gid (struct stat *a, struct stat *b)
   return a->st_gid == b->st_gid;
 }
 
-bool
-sys_compare_links (struct stat *link_data, struct stat *stat_data)
-{
-  return stat_data->st_dev == link_data->st_dev
-         && stat_data->st_ino == link_data->st_ino;
-}
-
 int
 sys_truncate (int fd)
 {