Skip to content

Commit

Permalink
dpkg: Use utimensat() if available and in preference of lutimes/utimes
Browse files Browse the repository at this point in the history
This funcion is only specified in POSIX.1-2008, but if it is, it is
going to be more standard than lutimes() which is only available on
Linux and the BSDs.

XXX: On recent Linux (2.6.32, 2009-12) and Solaris (11.1, 2013-04)
systems utimensat() is pretty much broken on multiple conditions.
→ But these issues (taken from gnulib and man utimensat(), do not really
affect our usage, no UTIME_OMIT nor UTIME_NOW, etc.
  • Loading branch information
guillemj committed Dec 25, 2024
1 parent 5ffb20e commit 9dd7b9d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ AC_CHECK_FUNCS([\
getprogname \
getexecname \
lutimes \
utimensat \
fallocate \
posix_fallocate \
posix_fadvise \
Expand Down
22 changes: 22 additions & 0 deletions src/main/archives.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,28 @@ static void
tarobject_set_mtime(struct tar_entry *te, const char *path)
{
struct timeval tv[2];
#ifdef HAVE_UTIMENSAT
struct timespec ts[2];
int rc, flags;

ts[0].tv_sec = currenttime;
ts[0].tv_nsec = 0;
ts[1].tv_sec = te->mtime;
ts[1].tv_nsec = 0;

if (te->type == TAR_FILETYPE_SYMLINK)
flags = AT_SYMLINK_NOFOLLOW;
else
flags = 0;

/* Try to use the POSIX.1-2008 interface, and fallback to the old code in
* case it's not supported by the system at run-time. */
rc = utimensat(AT_FDCWD, path, ts, flags);
if (rc == 0)
return;
else if (rc < 0 && errno != ENOSYS)
ohshite(_("error setting timestamps of '%.255s'"), path);
#endif

tv[0].tv_sec = currenttime;
tv[0].tv_usec = 0;
Expand Down

0 comments on commit 9dd7b9d

Please sign in to comment.