Blob Blame History Raw
From 23510b930ea31f7de8005e2f0ff6cab7062b4e26 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Thu, 19 Aug 2010 15:23:06 +0200
Subject: [PATCH 2/2] use futimens() if available, instead of utime()

---
 config.h.in  |    3 +++
 configure    |    2 +-
 configure.ac |    2 +-
 src/files.c  |   46 +++++++++++++++++++++++++++++++++++-----------
 4 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/config.h.in b/config.h.in
index 52e13f1..cb17b29 100644
--- a/config.h.in
+++ b/config.h.in
@@ -72,6 +72,9 @@
 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
 #undef HAVE_DOPRNT
 
+/* Define to 1 if you have the `futimens' function. */
+#undef HAVE_FUTIMENS
+
 /* Define to 1 if you have the `getdelim' function. */
 #undef HAVE_GETDELIM
 
diff --git a/configure b/configure
index 02733c7..1805e53 100755
--- a/configure
+++ b/configure
@@ -7776,7 +7776,7 @@ fi
 
 
 
-for ac_func in getdelim getline isblank strcasecmp strcasestr strncasecmp strnlen snprintf vsnprintf
+for ac_func in futimens getdelim getline isblank strcasecmp strcasestr strncasecmp strnlen snprintf vsnprintf
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index 66f8ee3..f4975d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -442,7 +442,7 @@ int main(void)
 
 dnl Checks for functions.
 
-AC_CHECK_FUNCS(getdelim getline isblank strcasecmp strcasestr strncasecmp strnlen snprintf vsnprintf)
+AC_CHECK_FUNCS(futimens getdelim getline isblank strcasecmp strcasestr strncasecmp strnlen snprintf vsnprintf)
 
 if test "x$enable_utf8" != xno; then
     AC_CHECK_FUNCS(iswalnum iswblank iswpunct iswspace nl_langinfo mblen mbstowcs mbtowc wctomb wcwidth)
diff --git a/src/files.c b/src/files.c
index 99cc1b8..9a1bdcc 100644
--- a/src/files.c
+++ b/src/files.c
@@ -1696,6 +1696,29 @@ int copy_file(FILE *inn, FILE *out)
     return retval;
 }
 
+#ifdef HAVE_FUTIMENS
+/* set atime/mtime by file descriptor */
+int utime_wrap(int fd, const char *filename, struct utimbuf *ut)
+{
+    struct timespec times[2];
+    (void) filename;
+
+    times[0].tv_sec = ut->actime;
+    times[1].tv_sec = ut->modtime;
+    times[0].tv_nsec = 0L;
+    times[1].tv_nsec = 0L;
+
+    return futimens(fd, times);
+}
+#else
+/* set atime/mtime by file name */
+int utime_wrap(int fd, const char *filename, struct utimbuf *ut)
+{
+    (void) fd;
+    return utime(filename, ut);
+}
+#endif
+
 /* Write a file out to disk.  If f_open isn't NULL, we assume that it is
  * a stream associated with the file, and we don't try to open it
  * ourselves.  If tmp is TRUE, we set the umask to disallow anyone else
@@ -1917,17 +1940,9 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
 	fprintf(stderr, "Backing up %s to %s\n", realname, backupname);
 #endif
 
-	/* Copy the file. */
-	copy_status = copy_file(f, backup_file);
-
-	if (copy_status != 0) {
-	    statusline(ALERT, _("Error reading %s: %s"), realname,
-			strerror(errno));
-	    goto cleanup_and_exit;
-	}
-
-	/* And set its metadata. */
-	if (utime(backupname, &filetime) == -1 && !ISSET(INSECURE_BACKUP)) {
+	/* Set backup's file metadata. */
+	if (utime_wrap(backup_fd, backupname, &filetime) == -1
+		&& !ISSET(INSECURE_BACKUP)) {
 	    if (prompt_failed_backupwrite(backupname))
 		goto skip_backup;
 	    statusline(HUSH, _("Error writing backup file %s: %s"),
@@ -1939,6 +1954,15 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
 	    goto cleanup_and_exit;
 	}
 
+	/* Copy the file. */
+	copy_status = copy_file(f, backup_file);
+
+	if (copy_status != 0) {
+	    statusline(ALERT, _("Error reading %s: %s"), realname,
+			strerror(errno));
+	    goto cleanup_and_exit;
+	}
+
 	free(backupname);
     }
 
-- 
1.7.4