aboutsummaryrefslogtreecommitdiff
path: root/binutils/rename.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-04-15 00:36:42 +0930
committerAlan Modra <amodra@gmail.com>2021-04-15 17:51:17 +0930
commit985e026451640c880e13827454aa31b7a636d1bc (patch)
tree2a034beb448ef79b8b57e9d207f2e0722e38cda5 /binutils/rename.c
parentd0ecdcddc363ad7f05fc50cf1eee4028fa7f8964 (diff)
downloadgdb-985e026451640c880e13827454aa31b7a636d1bc.zip
gdb-985e026451640c880e13827454aa31b7a636d1bc.tar.gz
gdb-985e026451640c880e13827454aa31b7a636d1bc.tar.bz2
PR27725, better objcopy -p times
Nanosecond rather than second resolution. PR 27725 * configure.ac: Check for sys/time.h and utimensat. Use standard checks for mkstemp and mkdtemp. Whitespace. Check for nanosecond members of struct stat. * rename.c: Prefer sys/time.h for utimes over utime.h for utime. (STAT_TIMESPEC, STAT_TIMESPEC_NS): Define (get_stat_atime_ns, get_stat_mtime_ns): New inline functions. (get_stat_atime, get_stat_mtime): Likewise. (set_times): Choose first available of utimensat, utimes, utime. Use above inline functions to set timespec and timeval values. * configure: Regenerate. * config.in: Regenerate. * testsuite/binutils-all/objcopy.exp (objcopy_test): Add test of file timestamp when --preserve-dates is used.
Diffstat (limited to 'binutils/rename.c')
-rw-r--r--binutils/rename.c98
1 files changed, 87 insertions, 11 deletions
diff --git a/binutils/rename.c b/binutils/rename.c
index 969acc1..2cbe464 100644
--- a/binutils/rename.c
+++ b/binutils/rename.c
@@ -22,10 +22,10 @@
#include "bfd.h"
#include "bucomm.h"
-#ifdef HAVE_GOOD_UTIME_H
-#include <utime.h>
-#elif defined HAVE_UTIMES
+#if defined HAVE_UTIMES
#include <sys/time.h>
+#elif defined HAVE_GOOD_UTIME_H
+#include <utime.h>
#endif
/* The number of bytes to copy at once. */
@@ -86,6 +86,77 @@ simple_copy (int fromfd, const char *to,
return 0;
}
+/* The following defines and inline functions are copied from gnulib.
+ FIXME: Use a gnulib import and stat-time.h instead. */
+#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+# if defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
+# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
+# else
+# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
+# endif
+#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
+# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
+#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
+# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
+#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
+# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
+#endif
+
+/* Return the nanosecond component of *ST's access time. */
+inline long int
+get_stat_atime_ns (struct stat const *st)
+{
+# if defined STAT_TIMESPEC
+ return STAT_TIMESPEC (st, st_atim).tv_nsec;
+# elif defined STAT_TIMESPEC_NS
+ return STAT_TIMESPEC_NS (st, st_atim);
+# else
+ return 0;
+# endif
+}
+
+/* Return the nanosecond component of *ST's data modification time. */
+inline long int
+get_stat_mtime_ns (struct stat const *st)
+{
+# if defined STAT_TIMESPEC
+ return STAT_TIMESPEC (st, st_mtim).tv_nsec;
+# elif defined STAT_TIMESPEC_NS
+ return STAT_TIMESPEC_NS (st, st_mtim);
+# else
+ return 0;
+# endif
+}
+
+/* Return *ST's access time. */
+inline struct timespec
+get_stat_atime (struct stat const *st)
+{
+#ifdef STAT_TIMESPEC
+ return STAT_TIMESPEC (st, st_atim);
+#else
+ struct timespec t;
+ t.tv_sec = st->st_atime;
+ t.tv_nsec = get_stat_atime_ns (st);
+ return t;
+#endif
+}
+
+/* Return *ST's data modification time. */
+inline struct timespec
+get_stat_mtime (struct stat const *st)
+{
+#ifdef STAT_TIMESPEC
+ return STAT_TIMESPEC (st, st_mtim);
+#else
+ struct timespec t;
+ t.tv_sec = st->st_mtime;
+ t.tv_nsec = get_stat_mtime_ns (st);
+ return t;
+#endif
+}
+/* End FIXME. */
+
/* Set the times of the file DESTINATION to be the same as those in
STATBUF. */
@@ -93,20 +164,25 @@ void
set_times (const char *destination, const struct stat *statbuf)
{
int result;
-#ifdef HAVE_GOOD_UTIME_H
- struct utimbuf tb;
-
- tb.actime = statbuf->st_atime;
- tb.modtime = statbuf->st_mtime;
- result = utime (destination, &tb);
+#if defined HAVE_UTIMENSAT
+ struct timespec times[2];
+ times[0] = get_stat_atime (statbuf);
+ times[1] = get_stat_mtime (statbuf);
+ result = utimensat (AT_FDCWD, destination, times, 0);
#elif defined HAVE_UTIMES
struct timeval tv[2];
tv[0].tv_sec = statbuf->st_atime;
- tv[0].tv_usec = 0;
+ tv[0].tv_usec = get_stat_atime_ns (statbuf) / 1000;
tv[1].tv_sec = statbuf->st_mtime;
- tv[1].tv_usec = 0;
+ tv[1].tv_usec = get_stat_mtime_ns (statbuf) / 1000;
result = utimes (destination, tv);
+#elif defined HAVE_GOOD_UTIME_H
+ struct utimbuf tb;
+
+ tb.actime = statbuf->st_atime;
+ tb.modtime = statbuf->st_mtime;
+ result = utime (destination, &tb);
#else
long tb[2];