Tweak atime/crtime code a bit more.
authorWayne Davison <wayne@opencoder.net>
Sun, 10 Oct 2021 18:45:14 +0000 (11:45 -0700)
committerWayne Davison <wayne@opencoder.net>
Sun, 10 Oct 2021 19:43:11 +0000 (12:43 -0700)
NEWS.md
generator.c
ifuncs.h
rsync.1.md
rsync.c
syscall.c

diff --git a/NEWS.md b/NEWS.md
index 74c3edfceefb6bfff677bb1c6821f4289279a592..a35d6ee592743318239a01641afa51570fb9147b 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -51,7 +51,7 @@
  - Reduced memory usage for an incremental transfer that has a bunch of small
    diretories.
 
- - Add support for `--atimes` on macOS.
+ - Added support for `--atimes` on macOS and fix using using it without -t.
 
  - Rsync can now update the xattrs on a read-only file when your user can
    temporarily add user-write permission to the file. (It always worked for a
index 3287ae311614b0371cd58bd70de2376cf01c3997..9c9751dc2f1e35c7bfa10ebc0ebf9925e07423de 100644 (file)
@@ -1269,7 +1269,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        return;
                }
        }
-       sx.crtime = 0;
 
        if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
                int i;
index 4037639b26a46495fdaaca05039b5c56c461eea8..491f0807e2f6c872fd1221751e0dae4ed3a2d28b 100644 (file)
--- a/ifuncs.h
+++ b/ifuncs.h
@@ -75,6 +75,7 @@ d_name(struct dirent *di)
 static inline void
 init_stat_x(stat_x *sx_p)
 {
+       sx_p->crtime = 0;
 #ifdef SUPPORT_ACLS
        sx_p->acc_acl = sx_p->def_acl = NULL;
 #endif
index 9bfda865a3dbbbc603065048bdd99ebfb24345bd..3de57b72a1fc431132ba23c9763ca331d1bbb6f4 100644 (file)
@@ -1391,8 +1391,8 @@ your home directory (remove the '=' for that).
 
 0.  `--omit-dir-times`, `-O`
 
-    This tells rsync to omit directories when it is preserving modification
-    times (see `--times`).  If NFS is sharing the directories on the receiving
+    This tells rsync to omit directories when it is preserving modification,
+    access, and create times.  If NFS is sharing the directories on the receiving
     side, it is a good idea to use `-O`.  This option is inferred if you use
     `--backup` without `--backup-dir`.
 
@@ -1409,8 +1409,8 @@ your home directory (remove the '=' for that).
 
 0.  `--omit-link-times`, `-J`
 
-    This tells rsync to omit symlinks when it is preserving modification times
-    (see `--times`).
+    This tells rsync to omit symlinks when it is preserving modification,
+    access, and create times.
 
 0.  `--super`
 
diff --git a/rsync.c b/rsync.c
index bcecac63fce196570c3705c28e99d8d4d253ada6..ff9489be871a665494c53bf438abdf2ee976a8ad 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -63,8 +63,7 @@ extern char *iconv_opt;
 #define UPDATED_ATIME (1<<3)
 #define UPDATED_ACLS  (1<<4)
 #define UPDATED_MODE  (1<<5)
-
-#define UPDATED_TIMES (UPDATED_MTIME|UPDATED_ATIME)
+#define UPDATED_CRTIME (1<<6)
 
 #ifdef ICONV_CONST
 iconv_t ic_chck = (iconv_t)-1;
@@ -576,10 +575,11 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                set_xattr(fname, file, fnamecmp, sxp);
 #endif
 
-       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 | ATTRS_SKIP_ATIME;
+       if (!preserve_times)
+               flags |= ATTRS_SKIP_MTIME | (atimes_ndx ? 0 : ATTRS_SKIP_ATIME) | (crtimes_ndx ? 0 : ATTRS_SKIP_CRTIME);
+       else if ((!(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 | ATTRS_SKIP_ATIME | ATTRS_SKIP_CRTIME;
        else if (sxp != &sx2)
                memcpy(&sx2.st, &sxp->st, sizeof (sx2.st));
        if (!atimes_ndx || S_ISDIR(sxp->st.st_mode))
@@ -604,28 +604,36 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                        updated |= UPDATED_ATIME;
                }
        }
-       if (updated & UPDATED_TIMES) {
+#ifdef SUPPORT_CRTIMES
+       if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
+               time_t file_crtime = F_CRTIME(file);
+               if (sxp->crtime == 0)
+                       sxp->crtime = get_create_time(fname, &sxp->st);
+               if (!same_time(sxp->crtime, 0L, file_crtime, 0L)) {
+                       if (
+#ifdef HAVE_GETATTRLIST
+                            do_setattrlist_crtime(fname, file_crtime) == 0
+#elif defined __CYGWIN__
+                            do_SetFileTime(fname, file_crtime) == 0
+#else
+#error Unknown crtimes implementation
+#endif
+                       )
+                               updated |= UPDATED_CRTIME;
+               }
+       }
+#endif
+       if (updated & (UPDATED_MTIME|UPDATED_ATIME)) {
                int ret = set_times(fname, &sx2.st);
                if (ret < 0) {
-                       rsyserr(FERROR_XFER, errno, "failed to set times on %s",
-                               full_fname(fname));
+                       rsyserr(FERROR_XFER, errno, "failed to set times on %s", full_fname(fname));
                        goto cleanup;
                }
                if (ret > 0) { /* ret == 1 if symlink could not be set */
-                       updated &= ~UPDATED_TIMES;
+                       updated &= ~(UPDATED_MTIME|UPDATED_ATIME);
                        file->flags |= FLAG_TIME_FAILED;
                }
        }
-#ifdef SUPPORT_CRTIMES
-       if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
-               time_t file_crtime = F_CRTIME(file);
-               if (sxp->crtime == 0)
-                       sxp->crtime = get_create_time(fname, &sxp->st);
-               if (!same_time(sxp->crtime, 0L, file_crtime, 0L)
-                && set_create_time(fname, file_crtime) == 0)
-                       updated = 1;
-       }
-#endif
 
 #ifdef SUPPORT_ACLS
        /* It's OK to call set_acl() now, even for a dir, as the generator
index 80a9a2f6e2e3b6bf6690b1c7511b5443cc67d804..56948a8327a4c576c41c79f1ade28fc7962ee9ff 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -233,8 +233,10 @@ int do_chmod(const char *path, mode_t mode)
 {
        static int switch_step = 0;
        int code;
+
        if (dry_run) return 0;
        RETURN_ERROR_IF_RO_OR_LO;
+
        switch (switch_step) {
 #ifdef HAVE_LCHMOD
        case 0:
@@ -415,7 +417,26 @@ int do_setattrlist_times(const char *path, STRUCT_STAT *stp)
        attrList.commonattr = ATTR_CMN_MODTIME | ATTR_CMN_ACCTIME;
        return setattrlist(path, &attrList, ts, sizeof ts, FSOPT_NOFOLLOW);
 }
+
+#ifdef SUPPORT_CRTIMES
+int do_setattrlist_crtime(const char *path, time_t crtime)
+{
+       struct attrlist attrList;
+       struct timespec ts;
+
+       if (dry_run) return 0;
+       RETURN_ERROR_IF_RO_OR_LO;
+
+       ts.tv_sec = crtime;
+       ts.tv_nsec = 0;
+
+       memset(&attrList, 0, sizeof attrList);
+       attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+       attrList.commonattr = ATTR_CMN_CRTIME;
+       return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
+}
 #endif
+#endif /* HAVE_SETATTRLIST */
 
 #ifdef SUPPORT_CRTIMES
 time_t get_create_time(const char *path, STRUCT_STAT *stp)
@@ -439,24 +460,12 @@ time_t get_create_time(const char *path, STRUCT_STAT *stp)
 #endif
 }
 
-int set_create_time(const char *path, time_t crtime)
+#if defined __CYGWIN__
+int do_SetFileTime(const char *path, time_t crtime)
 {
        if (dry_run) return 0;
        RETURN_ERROR_IF_RO_OR_LO;
 
-    {
-#ifdef HAVE_GETATTRLIST
-       struct attrlist attrList;
-       struct timespec ts;
-
-       ts.tv_sec = crtime;
-       ts.tv_nsec = 0;
-
-       memset(&attrList, 0, sizeof attrList);
-       attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
-       attrList.commonattr = ATTR_CMN_CRTIME;
-       return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
-#elif defined __CYGWIN__
        int cnt = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
        if (cnt == 0)
            return -1;
@@ -476,9 +485,8 @@ int set_create_time(const char *path, time_t crtime)
        int ok = SetFileTime(handle, &birth_time, NULL, NULL);
        CloseHandle(handle);
        return ok ? 0 : -1;
-#endif
-    }
 }
+#endif
 #endif /* SUPPORT_CRTIMES */
 
 #ifdef HAVE_UTIMENSAT