From 23510b930ea31f7de8005e2f0ff6cab7062b4e26 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Thu, 19 Aug 2010 15:23:06 +0200 Subject: [PATCH 2/2] use futimens() if available, instead of utime() --- configure.ac | 2 +- src/files.c | 48 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 66f8ee3..f4975d3 100644 --- a/configure.ac +++ b/configure.ac @@ -415,7 +415,7 @@ fi]) dnl Checks for functions. -AC_CHECK_FUNCS(getdelim getline isblank strcasecmp strcasestr strncasecmp strnlen vsnprintf) +AC_CHECK_FUNCS(futimens getdelim getline isblank strcasecmp strcasestr strncasecmp strnlen 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 @@ -1455,6 +1455,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 @@ -1694,6 +1717,18 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type fprintf(stderr, "Backing up %s to %s\n", realname, backupname); #endif + /* Set backup's file metadata. */ + if (utime_wrap(backup_fd, backupname, &filetime) == -1 + && !ISSET(INSECURE_BACKUP)) { + statusbar(_("Error writing backup file %s: %s"), backupname, + strerror(errno)); + /* If we can't write to the backup, DONT go on, since + whatever caused the backup file to fail (e.g. disk + full may well cause the real file write to fail, which + means we could lose both the backup and the original! */ + goto cleanup_and_exit; + } + /* Copy the file. */ copy_status = copy_file(f, backup_file); @@ -1704,19 +1739,6 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type goto cleanup_and_exit; } - /* And set its metadata. */ - if (utime(backupname, &filetime) == -1 && !ISSET(INSECURE_BACKUP)) { - if (prompt_failed_backupwrite(backupname)) - goto skip_backup; - statusbar(_("Error writing backup file %s: %s"), backupname, - strerror(errno)); - /* If we can't write to the backup, DONT go on, since - whatever caused the backup file to fail (e.g. disk - full may well cause the real file write to fail, which - means we could lose both the backup and the original! */ - goto cleanup_and_exit; - } - free(backupname); } -- 1.7.4