This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=272a5232b24a1ffc1363ec7119fd38e3f855b024 commit 272a5232b24a1ffc1363ec7119fd38e3f855b024 Author: Guillem Jover <guil...@debian.org> AuthorDate: Mon Feb 7 00:29:35 2022 +0100 u-a: Use the target timestamp when the symlink does not exist Some programs track the symlink timestamps in their databases (such as man-db). To be able to create reproducible installations we have to use timestamps that are reproducible, at least on the first installation. We also need to take into account that not using the current timestamp when updating symlinks might cause backup systems to not work properly. To cover these two cases, we will copy the timestamp from the target, if the symlink did not exist. Closes: #1004557 --- utils/update-alternatives.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c index 53364d3ba..da2d4119e 100644 --- a/utils/update-alternatives.c +++ b/utils/update-alternatives.c @@ -25,6 +25,7 @@ #include <compat.h> #include <sys/types.h> +#include <sys/time.h> #include <sys/stat.h> #include <sys/wait.h> @@ -631,6 +632,37 @@ fsys_xreadlink(const char *linkname) return buf; } +static void +fsys_set_ref_time(const char *linkname, const char *target) +{ +#ifdef HAVE_LUTIMES + /* If the symlink did not exist, then copy the timestamps + * from the target. This is needed so we can get reproducible + * installations, for programs that track these timestamps on + * their databases. */ + struct stat st; + struct timeval tv[2]; + char *root_linkname; + + if (fsys_lstat(target, &st) < 0) { + if (errno != ENOENT) + syserr(_("unable to get file '%s%s' metadata"), + instdir, target); + return; + } + + tv[0].tv_sec = st.st_mtime; + tv[0].tv_usec = 0; + tv[1].tv_sec = st.st_mtime; + tv[1].tv_usec = 0; + + root_linkname = fsys_get_path(linkname); + if (lutimes(root_linkname, tv) < 0 && errno != ENOSYS) + syserr(_("cannot set symlink '%s' timestamp"), root_linkname); + free(root_linkname); +#endif +} + static void fsys_symlink(const char *filename, const char *linkname) { @@ -813,6 +845,7 @@ struct commit_operation { OPCODE_NOP, OPCODE_RM, OPCODE_MV, + OPCODE_REF_TIME, } opcode; char *arg_a; @@ -1894,6 +1927,9 @@ alternative_commit(struct alternative *a) case OPCODE_MV: fsys_mv(op->arg_a, op->arg_b); break; + case OPCODE_REF_TIME: + fsys_set_ref_time(op->arg_a, op->arg_b); + break; } } @@ -1984,6 +2020,8 @@ alternative_prepare_install_single(struct alternative *a, const char *name, fn = xasprintf("%s/%s", altdir, name); fsys_symlink(file, fntmp); alternative_add_commit_op(a, OPCODE_MV, fntmp, fn); + if (fsys_pathname_is_missing(fn)) + alternative_add_commit_op(a, OPCODE_REF_TIME, fn, file); free(fntmp); if (alternative_path_needs_update(linkname, fn)) { @@ -1991,6 +2029,8 @@ alternative_prepare_install_single(struct alternative *a, const char *name, fntmp = xasprintf("%s" ALT_TMP_EXT, linkname); fsys_symlink(fn, fntmp); alternative_add_commit_op(a, OPCODE_MV, fntmp, linkname); + if (fsys_pathname_is_missing(linkname)) + alternative_add_commit_op(a, OPCODE_REF_TIME, linkname, fn); free(fntmp); } free(fn); -- Dpkg.Org's dpkg