diff options
author | Edward Thomson <ethomson@microsoft.com> | 2015-06-16 15:18:04 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-06-16 15:32:02 -0400 |
commit | 121c3171e5b4918337910250487691efa8dbbd49 (patch) | |
tree | 7b3e78726836b9ff0163d1291c7aabb7c2b136f2 | |
parent | e44abe16bd20512c76331e6889f390e35993153a (diff) | |
download | libgit2-121c3171e5b4918337910250487691efa8dbbd49.tar.gz |
Introduce p_utimes and p_futimes
Provide functionality to set the time on a filesystem entry,
using utimes or futimes on POSIX type systems or SetFileTime
on Win32.
-rw-r--r-- | src/unix/posix.h | 4 | ||||
-rw-r--r-- | src/win32/posix.h | 3 | ||||
-rw-r--r-- | src/win32/posix_w32.c | 38 | ||||
-rw-r--r-- | src/win32/w32_util.h | 10 | ||||
-rw-r--r-- | tests/checkout/checkout_helpers.c | 12 | ||||
-rw-r--r-- | tests/core/posix.c | 49 |
6 files changed, 110 insertions, 6 deletions
diff --git a/src/unix/posix.h b/src/unix/posix.h index 35bd431b8..425e6bb1b 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -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) diff --git a/src/win32/posix.h b/src/win32/posix.h index bf35c8125..ac98fd864 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -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); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 332ea233c..504562b0e 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -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; diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h index 8cb0f5b94..377d651a8 100644 --- a/src/win32/w32_util.h +++ b/src/win32/w32_util.h @@ -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, diff --git a/tests/checkout/checkout_helpers.c b/tests/checkout/checkout_helpers.c index c2e65b885..f6e36d39b 100644 --- a/tests/checkout/checkout_helpers.c +++ b/tests/checkout/checkout_helpers.c @@ -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)); } diff --git a/tests/core/posix.c b/tests/core/posix.c index 1cef937cd..5a9e24899 100644 --- a/tests/core/posix.c +++ b/tests/core/posix.c @@ -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"); +} |