Support --crtimes on Cygwin.
authorWayne Davison <wayne@opencoder.net>
Fri, 9 Jul 2021 01:47:21 +0000 (18:47 -0700)
committerWayne Davison <wayne@opencoder.net>
Fri, 9 Jul 2021 01:59:26 +0000 (18:59 -0700)
Makefile.in
flist.c
generator.c
rsync.c
rsync.h
syscall.c
tls.c

index 67190489ff14bf8f0ed0b20c6cf4f55a61ca8f93..0313e6ff5334f708161a9f3f783bbdfe42fc6af6 100644 (file)
@@ -50,7 +50,7 @@ popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
        popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) @SIMD@ $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -155,7 +155,7 @@ getgroups$(EXEEXT): getgroups.o
 getfsdev$(EXEEXT): getfsdev.o
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o t_stub.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
diff --git a/flist.c b/flist.c
index 5a1e4245c2a4a8eab7b7e036990b6171cf2e2e9f..3442d868f63ff239d7a5bb6921c9a160142f1df2 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -1438,7 +1438,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                F_ATIME(file) = st.st_atime;
 #ifdef SUPPORT_CRTIMES
        if (crtimes_ndx)
-               F_CRTIME(file) = get_create_time(fname);
+               F_CRTIME(file) = get_create_time(fname, &st);
 #endif
 
        if (basename != thisname)
index a890bdc3c5b7e9577289d9837deffe1055f1f7d4..dc4570931002e2d630c4cac51e8db01d77492a25 100644 (file)
@@ -399,7 +399,7 @@ static inline int any_time_differs(stat_x *sxp, struct file_struct *file, UNUSED
 #ifdef SUPPORT_CRTIMES
        if (!differs && crtimes_ndx) {
                if (sxp->crtime == 0)
-                       sxp->crtime = get_create_time(fname);
+                       sxp->crtime = get_create_time(fname, &sxp->st);
                differs = !same_time(sxp->crtime, 0, F_CRTIME(file), 0);
        }
 #endif
@@ -525,7 +525,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
 #ifdef SUPPORT_CRTIMES
                if (crtimes_ndx) {
                        if (sxp->crtime == 0)
-                               sxp->crtime = get_create_time(fnamecmp);
+                               sxp->crtime = get_create_time(fnamecmp, &sxp->st);
                        if (!same_time(sxp->crtime, 0, F_CRTIME(file), 0))
                                iflags |= ITEM_REPORT_CRTIME;
                }
diff --git a/rsync.c b/rsync.c
index e7f1f96a8f814c0494bd5935bce9eb5615b4c9ec..bcecac63fce196570c3705c28e99d8d4d253ada6 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -620,7 +620,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        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->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;
diff --git a/rsync.h b/rsync.h
index 9d5c80080175f7216e93b2c165c5bf08d4d7ad4c..2f674bc532d3b420965d649bde3bd1cf8f50eec4 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -587,7 +587,7 @@ typedef unsigned int size_t;
 #define SUPPORT_ATIMES 1
 #endif
 
-#ifdef HAVE_GETATTRLIST
+#if defined HAVE_GETATTRLIST || defined __CYGWIN__
 #define SUPPORT_CRTIMES 1
 #endif
 
index 11d10e4a6b7dd58b1a1cbc1f5eb632f8f702f041..181be11dba495b8678c001cfd64f8c5d35cb9393 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -55,12 +55,16 @@ extern int open_noatime;
 #endif
 
 #ifdef SUPPORT_CRTIMES
+#ifdef HAVE_GETATTRLIST
 #pragma pack(push, 4)
 struct create_time {
        uint32 length;
        struct timespec crtime;
 };
 #pragma pack(pop)
+#elif defined __CYGWIN__
+#include <windows.h>
+#endif
 #endif
 
 #define RETURN_ERROR_IF(x,e) \
@@ -407,23 +411,30 @@ int do_setattrlist_times(const char *fname, STRUCT_STAT *stp)
 #endif
 
 #ifdef SUPPORT_CRTIMES
-time_t get_create_time(const char *path)
+time_t get_create_time(const char *path, STRUCT_STAT *stp)
 {
+#ifdef HAVE_GETATTRLIST
        static struct create_time attrBuf;
        struct attrlist attrList;
 
+       (void)stp;
        memset(&attrList, 0, sizeof attrList);
        attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
        attrList.commonattr = ATTR_CMN_CRTIME;
        if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
                return 0;
        return attrBuf.crtime.tv_sec;
-}
+#elif defined __CYGWIN__
+       (void)path;
+       return stp->st_birthtime;
+#else
+#error Unknown crtimes implementation
 #endif
+}
 
-#ifdef SUPPORT_CRTIMES
 int set_create_time(const char *path, time_t crtime)
 {
+#ifdef HAVE_GETATTRLIST
        struct attrlist attrList;
        struct timespec ts;
 
@@ -437,6 +448,27 @@ int set_create_time(const char *path, time_t crtime)
        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;
+       WCHAR *pathw = new_array(WCHAR, cnt);
+       if (!pathw)
+           return -1;
+       MultiByteToWideChar(CP_UTF8, 0, path, -1, pathw, cnt);
+       HANDLE handle = CreateFileW(pathw, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                   NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+       free(pathw);
+       if (handle == INVALID_HANDLE_VALUE)
+           return -1;
+       int64 temp_time = Int32x32To64(crtime, 10000000) + 116444736000000000LL;
+       FILETIME birth_time;
+       birth_time.dwLowDateTime = (DWORD)temp_time;
+       birth_time.dwHighDateTime = (DWORD)(temp_time >> 32);
+       int ok = SetFileTime(handle, &birth_time, NULL, NULL);
+       CloseHandle(handle);
+       return ok ? 0 : -1;
+#endif
 }
 #endif
 
diff --git a/tls.c b/tls.c
index cb497360e88b5aa16a78d166bbe94b335e55921d..966986745168d4cd31d89cf35df892891358d1c4 100644 (file)
--- a/tls.c
+++ b/tls.c
@@ -160,7 +160,7 @@ static void list_file(const char *fname)
        if (do_lstat(fname, &buf) < 0)
                failed("stat", fname);
 #ifdef SUPPORT_CRTIMES
-       if (display_crtimes && (crtime = get_create_time(fname)) == 0)
+       if (display_crtimes && (crtime = get_create_time(fname, &buf)) == 0)
                failed("get_create_time", fname);
 #endif
 #ifdef SUPPORT_XATTRS