From: Paul Eggert Date: Sat, 9 Aug 2025 23:10:49 +0000 (-0700) Subject: Use Gnulib’s same-inode module X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bdc442bd5c2cb573c57a46b36f2cdfd0daf52c55;p=thirdparty%2Ftar.git Use Gnulib’s same-inode module 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. --- diff --git a/gnulib.modules b/gnulib.modules index 796c1dcd..8819b03b 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -94,6 +94,7 @@ root-uid rpmatch full-read safe-read +same-inode savedir selinux-at setenv diff --git a/src/common.h b/src/common.h index 9bc06523..24c53cc4 100644 --- a/src/common.h +++ b/src/common.h @@ -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); diff --git a/src/compare.c b/src/compare.c index 95a91181..c2d0d157 100644 --- a/src/compare.c +++ b/src/compare.c @@ -34,6 +34,7 @@ #include #include #include +#include #include /* 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 (¤t_stat_info, _("Not linked to %s"), quote_n_colon (QUOTE_ARG, diff --git a/src/create.c b/src/create.c index 7da4560d..078c77e1 100644 --- a/src/create.c +++ b/src/create.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "common.h" #include @@ -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; diff --git a/src/extract.c b/src/extract.c index 3b913c54..7bf41fef 100644 --- a/src/extract.c +++ b/src/extract.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #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, diff --git a/src/incremen.c b/src/incremen.c index 020fa1f0..76f982b4 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -22,6 +22,7 @@ #include #include #include +#include #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); diff --git a/src/names.c b/src/names.c index ebdec2e0..e1927ba4 100644 --- a/src/names.c +++ b/src/names.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -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; diff --git a/src/system.c b/src/system.c index a52b8af4..7538b6b2 100644 --- a/src/system.c +++ b/src/system.c @@ -25,6 +25,7 @@ #include "common.h" #include #include +#include #include #include #include @@ -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) {