From 649a3a5626febae61196d51b205a73d4c7f204bf Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 9 Jun 2016 21:59:35 +0000 Subject: [PATCH] install: When preserving timestamps, also copy the nanoseconds part. Now that we have utimensat in -legacy, install(1) can use it. This is a revert of r299942 which is itself a revert of r299850. --- usr.bin/xinstall/tests/install_test.sh | 7 ++++++ usr.bin/xinstall/xinstall.c | 30 +++++++++++--------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/usr.bin/xinstall/tests/install_test.sh b/usr.bin/xinstall/tests/install_test.sh index 24a8a4d45521..9a9c69fd6992 100755 --- a/usr.bin/xinstall/tests/install_test.sh +++ b/usr.bin/xinstall/tests/install_test.sh @@ -64,6 +64,12 @@ copy_to_nonexistent_backup_safe_body() { copy_to_nonexistent_with_opts -b -B.bak -S } +atf_test_case copy_to_nonexistent_preserving +copy_to_nonexistent_preserving_body() { + copy_to_nonexistent_with_opts -p + [ ! testf -ot copyf ] || atf_fail "bad timestamp 2" +} + copy_self_with_opts() { printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0z' >testf2 @@ -307,6 +313,7 @@ atf_init_test_cases() { atf_add_test_case copy_to_nonexistent_safe_comparing atf_add_test_case copy_to_nonexistent_backup atf_add_test_case copy_to_nonexistent_backup_safe + atf_add_test_case copy_to_nonexistent_preserving atf_add_test_case copy_self atf_add_test_case copy_self_safe atf_add_test_case copy_self_comparing diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 1121cffe78ac..5e05ba841163 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -131,7 +131,7 @@ static void do_symlink(const char *, const char *, const struct stat *); static void makelink(const char *, const char *, const struct stat *); static void install(const char *, const char *, u_long, u_int); static void install_dir(char *); -static void metadata_log(const char *, const char *, struct timeval *, +static void metadata_log(const char *, const char *, struct timespec *, const char *, const char *, off_t); static int parseid(const char *, id_t *); static void strip(const char *); @@ -722,7 +722,7 @@ static void install(const char *from_name, const char *to_name, u_long fset, u_int flags) { struct stat from_sb, temp_sb, to_sb; - struct timeval tvb[2]; + struct timespec tsb[2]; int devnull, files_match, from_fd, serrno, target; int tempcopy, temp_fd, to_fd; char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN]; @@ -857,11 +857,9 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) * Need to preserve target file times, though. */ if (to_sb.st_nlink != 1) { - tvb[0].tv_sec = to_sb.st_atime; - tvb[0].tv_usec = 0; - tvb[1].tv_sec = to_sb.st_mtime; - tvb[1].tv_usec = 0; - (void)utimes(tempfile, tvb); + tsb[0] = to_sb.st_atim; + tsb[1] = to_sb.st_mtim; + (void)utimensat(AT_FDCWD, tempfile, tsb, 0); } else { files_match = 1; (void)unlink(tempfile); @@ -916,11 +914,9 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) * Preserve the timestamp of the source file if necessary. */ if (dopreserve && !files_match && !devnull) { - tvb[0].tv_sec = from_sb.st_atime; - tvb[0].tv_usec = 0; - tvb[1].tv_sec = from_sb.st_mtime; - tvb[1].tv_usec = 0; - (void)utimes(to_name, tvb); + tsb[0] = from_sb.st_atim; + tsb[1] = from_sb.st_mtim; + (void)utimensat(AT_FDCWD, to_name, tsb, 0); } if (fstat(to_fd, &to_sb) == -1) { @@ -989,7 +985,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) if (!devnull) (void)close(from_fd); - metadata_log(to_name, "file", tvb, NULL, digestresult, to_sb.st_size); + metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size); free(digestresult); } @@ -1301,7 +1297,7 @@ install_dir(char *path) * or to allow integrity checks to be performed. */ static void -metadata_log(const char *path, const char *type, struct timeval *tv, +metadata_log(const char *path, const char *type, struct timespec *ts, const char *slink, const char *digestresult, off_t size) { static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; @@ -1355,9 +1351,9 @@ metadata_log(const char *path, const char *type, struct timeval *tv, } if (*type == 'f') /* type=file */ fprintf(metafp, " size=%lld", (long long)size); - if (tv != NULL && dopreserve) - fprintf(metafp, " time=%lld.%ld", - (long long)tv[1].tv_sec, (long)tv[1].tv_usec); + if (ts != NULL && dopreserve) + fprintf(metafp, " time=%lld.%09ld", + (long long)ts[1].tv_sec, ts[1].tv_nsec); if (digestresult && digest) fprintf(metafp, " %s=%s", digest, digestresult); if (fflags)