]> git.proxmox.com Git - libgit2.git/commitdiff
Introduce p_utimes and p_futimes
authorEdward Thomson <ethomson@microsoft.com>
Tue, 16 Jun 2015 19:18:04 +0000 (15:18 -0400)
committerEdward Thomson <ethomson@microsoft.com>
Tue, 16 Jun 2015 19:32:02 +0000 (15:32 -0400)
Provide functionality to set the time on a filesystem entry,
using utimes or futimes on POSIX type systems or SetFileTime
on Win32.

src/unix/posix.h
src/win32/posix.h
src/win32/posix_w32.c
src/win32/w32_util.h
tests/checkout/checkout_helpers.c
tests/core/posix.c

index 35bd431b844b6e9942ef6db4448f5e69a3e1f2de..425e6bb1b271c4f13baa0c4b4a2af816073a52ad 100644 (file)
@@ -19,6 +19,9 @@ typedef int GIT_SOCKET;
 #define p_lstat(p,b) lstat(p,b)
 #define p_stat(p,b) stat(p, b)
 
+#define p_utimes(f, t) utimes(f, t)
+#define p_futimes(f, t) futimes(f, t)
+
 #define p_readlink(a, b, c) readlink(a, b, c)
 #define p_symlink(o,n) symlink(o, n)
 #define p_link(o,n) link(o, n)
@@ -26,7 +29,6 @@ typedef int GIT_SOCKET;
 #define p_mkdir(p,m) mkdir(p, m)
 #define p_fsync(fd) fsync(fd)
 extern char *p_realpath(const char *, char *);
-#define p_utimensat(fd, path, times, flags) utimensat(fd, path, times, flags)
 
 #define p_recv(s,b,l,f) recv(s,b,l,f)
 #define p_send(s,b,l,f) send(s,b,l,f)
index bf35c812536b9a074f7d04e3286fd080655626e8..ac98fd864eda574f69e664c545d83d1e2a0b6283 100644 (file)
@@ -20,6 +20,9 @@ typedef SOCKET GIT_SOCKET;
 extern int p_lstat(const char *file_name, struct stat *buf);
 extern int p_stat(const char* path, struct stat* buf);
 
+extern int p_utimes(const char *filename, const struct timeval times[2]);
+extern int p_futimes(int fd, const struct timeval times[2]);
+
 extern int p_readlink(const char *path, char *buf, size_t bufsiz);
 extern int p_symlink(const char *old, const char *new);
 extern int p_link(const char *old, const char *new);
index 332ea233c6b65181c5cc7f1905f8726b363c9257..504562b0e3e572ea61d5e65df60458d3158e98a6 100644 (file)
@@ -201,6 +201,44 @@ int p_lstat_posixly(const char *filename, struct stat *buf)
        return do_lstat(filename, buf, true);
 }
 
+int p_utimes(const char *filename, const struct timeval times[2])
+{
+       int fd, error;
+
+       if ((fd = p_open(filename, O_RDWR)) < 0)
+               return fd;
+
+       error = p_futimes(fd, times);
+
+       close(fd);
+       return error;
+}
+
+int p_futimes(int fd, const struct timeval times[2])
+{
+       HANDLE handle;
+       FILETIME atime = {0}, mtime = {0};
+
+       if (times == NULL) {
+               SYSTEMTIME st;
+
+               GetSystemTime(&st);
+               SystemTimeToFileTime(&st, &atime);
+               SystemTimeToFileTime(&st, &mtime);
+       } else {
+               git_win32__timeval_to_filetime(&atime, times[0]);
+               git_win32__timeval_to_filetime(&mtime, times[1]);
+       }
+
+       if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
+               return -1;
+
+       if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
+               return -1;
+
+       return 0;
+}
+
 int p_readlink(const char *path, char *buf, size_t bufsiz)
 {
        git_win32_path path_w, target_w;
index 8cb0f5b9436a4bfd9e8456c78431f8536913ac6d..377d651a8d458ed2716f33ab159517af2f7692e9 100644 (file)
@@ -79,6 +79,16 @@ GIT_INLINE(time_t) git_win32__filetime_to_time_t(const FILETIME *ft)
        return (time_t)winTime;
 }
 
+GIT_INLINE(void) git_win32__timeval_to_filetime(
+       FILETIME *ft, const struct timeval tv)
+{
+       long long ticks = (tv.tv_sec * 10000000LL) +
+               (tv.tv_usec * 10LL) + 116444736000000000LL;
+
+       ft->dwHighDateTime = ((ticks >> 32) & 0xffffffffLL);
+       ft->dwLowDateTime = (ticks & 0xffffffffLL);
+}
+
 GIT_INLINE(int) git_win32__file_attribute_to_stat(
        struct stat *st,
        const WIN32_FILE_ATTRIBUTE_DATA *attrdata,
index c2e65b885214b10790f897a4d976b506975d9d34..f6e36d39b4503ed7321853eeccecd4a78e4d2c94 100644 (file)
@@ -132,8 +132,9 @@ int checkout_count_callback(
 
 void tick_index(git_index *index)
 {
+       int index_fd;
        git_time_t ts;
-       struct timespec times[2];
+       struct timeval times[2];
 
        cl_assert(index->on_disk);
        cl_assert(git_index_path(index));
@@ -141,10 +142,11 @@ void tick_index(git_index *index)
        cl_git_pass(git_index_read(index, true));
        ts = index->stamp.mtime;
 
-       times[0].tv_sec  = UTIME_OMIT; /* dont' change the atime */
-       times[0].tv_nsec = UTIME_OMIT; /* dont' change the atime */
+       times[0].tv_sec  = ts;
+       times[0].tv_usec = 0;
        times[1].tv_sec  = ts + 1;
-       times[1].tv_nsec = 0;
-       cl_git_pass(p_utimensat(AT_FDCWD, git_index_path(index), times, 0));
+       times[1].tv_usec = 0;
+
+       cl_git_pass(p_utimes(git_index_path(index), times));
        cl_git_pass(git_index_read(index, true));
 }
index 1cef937cdb0a81a9182e6ea4a2a675811b547a93..5a9e24899f9ad59c6d40585860e09667e1c4ffa6 100644 (file)
@@ -97,3 +97,52 @@ void test_core_posix__inet_pton(void)
        cl_git_fail(p_inet_pton(5, "315.124", NULL)); /* AF_CHAOS */
        cl_assert_equal_i(EAFNOSUPPORT, errno);
 }
+
+void test_core_posix__utimes(void)
+{
+       struct timeval times[2];
+       struct stat st;
+       time_t curtime;
+       int fd;
+
+       /* test p_utimes */
+       times[0].tv_sec = 1234567890;
+       times[0].tv_usec = 0;
+       times[1].tv_sec = 1234567890;
+       times[1].tv_usec = 0;
+
+       cl_git_mkfile("foo", "Dummy file.");
+       cl_must_pass(p_utimes("foo", times));
+
+       p_stat("foo", &st);
+       cl_assert_equal_i(1234567890, st.st_atime);
+       cl_assert_equal_i(1234567890, st.st_mtime);
+
+
+       /* test p_futimes */
+       times[0].tv_sec = 1414141414;
+       times[0].tv_usec = 0;
+       times[1].tv_sec = 1414141414;
+       times[1].tv_usec = 0;
+
+       cl_must_pass(fd = p_open("foo", O_RDWR));
+       cl_must_pass(p_futimes(fd, times));
+       p_close(fd);
+
+       p_stat("foo", &st);
+       cl_assert_equal_i(1414141414, st.st_atime);
+       cl_assert_equal_i(1414141414, st.st_mtime);
+
+
+       /* test p_utimes with current time, assume that
+        * it takes < 5 seconds to get the time...!
+        */
+       cl_must_pass(p_utimes("foo", NULL));
+
+       curtime = time(NULL);
+       p_stat("foo", &st);
+       cl_assert((st.st_atime - curtime) < 5);
+       cl_assert((st.st_mtime - curtime) < 5);
+
+       p_unlink("foo");
+}