} else if (protocol_version >= 30) {
if (am_server) {
compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
compat_flags |= CF_SYMLINK_TIMES;
#endif
#ifdef ICONV_OPTION
? strchr(client_info, 'L') != NULL
: !!(compat_flags & CF_SYMLINK_TIMES);
}
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
else
receiver_symlink_times = 1;
#endif
}
use_safe_inc_flist = !!(compat_flags & CF_SAFE_FLIST);
need_messages_from_generator = 1;
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
} else if (!am_sender) {
receiver_symlink_times = 1;
#endif
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
- extattr_get_link sigaction sigprocmask setattrlist)
+ extattr_get_link sigaction sigprocmask setattrlist \
+ utimensat)
dnl cygwin iconv.h defines iconv_open as libiconv_open
if test x"$ac_cv_func_iconv_open" != x"yes"; then
int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
{
-#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
- if (S_ISLNK(file->mode)) {
+ if (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(file->mode)) {
;
- } else
-#endif
- if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
+ } else if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
return 0;
if (preserve_perms) {
{
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
int keep_time = !preserve_times ? 0
- : S_ISDIR(file->mode) ? preserve_times > 1 :
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
- 1;
-#else
- !S_ISLNK(file->mode);
-#endif
+ : S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
+ : S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
+ : 1;
if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
iflags |= ITEM_REPORT_SIZE;
}
solo_file = local_name;
dir_tweaking = !(list_only || solo_file || dry_run);
- need_retouch_dir_times = preserve_times > 1;
+ need_retouch_dir_times = preserve_times & PRESERVE_DIR_TIMES;
loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
symlink_timeset_failed_flags = ITEM_REPORT_TIME
| (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
#ifdef ICONV_OPTION
iconv = "";
#endif
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
symtimes = "";
#endif
{"xattrs", 'X', POPT_ARG_NONE, 0, 'X', 0, 0 },
{"no-xattrs", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
{"no-X", 0, POPT_ARG_VAL, &preserve_xattrs, 0, 0, 0 },
- {"times", 't', POPT_ARG_VAL, &preserve_times, 2, 0, 0 },
+ {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
{"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
{"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
{"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 1, 0, 0 },
preserve_links = 1;
#endif
preserve_perms = 1;
- preserve_times = 2;
+ preserve_times = 1;
preserve_gid = 1;
preserve_uid = 1;
preserve_devices = 1;
parse_rule(&filter_list, backup_dir_buf, 0, 0);
}
+ if (preserve_times) {
+ preserve_times = PRESERVE_FILE_TIMES;
+ if (!omit_dir_times)
+ preserve_times |= PRESERVE_DIR_TIMES;
+#ifdef CAN_SET_SYMLINK_TIMES
+ preserve_times |= PRESERVE_LINK_TIMES;
+#endif
+ }
+
if (make_backups && !backup_dir) {
omit_dir_times = 0; /* Implied, so avoid -O to sender. */
- if (preserve_times > 1)
- preserve_times = 1;
- } else if (omit_dir_times) {
- if (preserve_times > 1)
- preserve_times = 1;
+ preserve_times &= ~PRESERVE_DIR_TIMES;
}
if (stdout_format) {
argstr[x++] = '.';
if (allow_inc_recurse)
argstr[x++] = 'i';
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
argstr[x++] = 'L';
#endif
#ifdef ICONV_OPTION
set_xattr(fname, file, fnamecmp, sxp);
#endif
- if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
+ if (!preserve_times
+ || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
+ || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
#include <utime.h>
#endif
+#if defined HAVE_LUTIMES || defined HAVE_UTIMENSAT
+#define CAN_SET_SYMLINK_TIMES 1
+#endif
+
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
+#define PRESERVE_FILE_TIMES (1<<0)
+#define PRESERVE_DIR_TIMES (1<<1)
+#define PRESERVE_LINK_TIMES (1<<2)
+
/* Initial mask on permissions given to temporary files. Mask off setuid
bits and group access because of potential race-condition security
holes, and mask other access because mode 707 is bizarre */
return lseek(fd, offset, whence);
#endif
}
+
+#ifdef HAVE_UTIMENSAT
+int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
+{
+ struct timespec t[2];
+
+ if (dry_run) return 0;
+ RETURN_ERROR_IF_RO_OR_LO;
+
+ t[0].tv_sec = 0;
+ t[0].tv_nsec = UTIME_NOW;
+ t[1].tv_sec = modtime;
+ t[1].tv_nsec = mod_nsec;
+ return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
+}
+#endif
+
+#ifdef HAVE_LUTIMES
+int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
+{
+ struct timeval t[2];
+
+ if (dry_run) return 0;
+ RETURN_ERROR_IF_RO_OR_LO;
+
+ t[0].tv_sec = time(NULL);
+ t[0].tv_usec = 0;
+ t[1].tv_sec = modtime;
+ t[1].tv_usec = mod_nsec / 1000;
+ return lutimes(fname, t);
+}
+#endif
+
+#ifdef HAVE_UTIMES
+int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
+{
+ struct timeval t[2];
+
+ if (dry_run) return 0;
+ RETURN_ERROR_IF_RO_OR_LO;
+
+ t[0].tv_sec = time(NULL);
+ t[0].tv_usec = 0;
+ t[1].tv_sec = modtime;
+ t[1].tv_usec = mod_nsec / 1000;
+ return utimes(fname, t);
+}
+
+#elif defined HAVE_UTIME
+int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
+{
+#ifdef HAVE_STRUCT_UTIMBUF
+ struct utimbuf tbuf;
+#else
+ time_t t[2];
+#endif
+
+ if (dry_run) return 0;
+ RETURN_ERROR_IF_RO_OR_LO;
+
+# ifdef HAVE_STRUCT_UTIMBUF
+ tbuf.actime = time(NULL);
+ tbuf.modtime = modtime;
+ return utime(fname, &tbuf);
+# else
+ t[0] = time(NULL);
+ t[1] = modtime;
+ return utime(fname, t);
+# endif
+}
+
+#else
+#error Need utimes or utime function.
+#endif
int relative_paths = 0;
int human_readable = 0;
int module_dirlen = 0;
+int preserve_times = 0;
int preserve_xattrs = 0;
mode_t orig_umask = 002;
char *partial_dir;
extern int module_id;
extern int modify_window;
extern int relative_paths;
+extern int preserve_times;
extern int human_readable;
extern int preserve_xattrs;
extern char *module_dir;
exit_cleanup(RERR_MALLOC);
}
+/* This returns 0 for success, 1 for a symlink if symlink time-setting
+ * is not possible, or -1 for any other error. */
int set_modtime(const char *fname, time_t modtime, mode_t mode)
{
-#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
- if (S_ISLNK(mode))
- return 1;
-#endif
+ static int switch_step = 0;
if (verbose > 2) {
rprintf(FINFO, "set modtime of %s to (%ld) %s",
asctime(localtime(&modtime)));
}
- if (dry_run)
- return 0;
+ switch (switch_step) {
+#ifdef HAVE_UTIMENSAT
+#include "case_N.h"
+ if (do_utimensat(fname, modtime, 0) == 0)
+ break;
+ if (errno != ENOSYS)
+ return -1;
+ switch_step++;
+ /* FALLTHROUGH */
+#endif
- {
-#ifdef HAVE_UTIMES
- struct timeval t[2];
- t[0].tv_sec = time(NULL);
- t[0].tv_usec = 0;
- t[1].tv_sec = modtime;
- t[1].tv_usec = 0;
-# ifdef HAVE_LUTIMES
- if (S_ISLNK(mode)) {
- if (lutimes(fname, t) < 0)
- return errno == ENOSYS ? 1 : -1;
- return 0;
+#ifdef HAVE_LUTIMES
+#include "case_N.h"
+ if (do_lutimes(fname, modtime, 0) == 0)
+ break;
+ if (errno != ENOSYS)
+ return -1;
+ switch_step++;
+ /* FALLTHROUGH */
+#endif
+
+#include "case_N.h"
+ switch_step++;
+ if (preserve_times & PRESERVE_LINK_TIMES) {
+ preserve_times &= ~PRESERVE_LINK_TIMES;
+ if (S_ISLNK(mode))
+ return 1;
}
-# endif
- return utimes(fname, t);
-#elif defined HAVE_STRUCT_UTIMBUF
- struct utimbuf tbuf;
- tbuf.actime = time(NULL);
- tbuf.modtime = modtime;
- return utime(fname,&tbuf);
-#elif defined HAVE_UTIME
- time_t t[2];
- t[0] = time(NULL);
- t[1] = modtime;
- return utime(fname,t);
+ /* FALLTHROUGH */
+
+#include "case_N.h"
+#ifdef HAVE_UTIMES
+ if (do_utimes(fname, modtime, 0) == 0)
+ break;
#else
-#error No file-time-modification routine found!
+ if (do_utime(fname, modtime, 0) == 0)
+ break;
#endif
+
+ return -1;
}
+
+ return 0;
}
/* This creates a new directory with default permissions. Since there