summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2015-06-16 15:18:04 -0400
committerEdward Thomson <ethomson@microsoft.com>2015-06-16 15:32:02 -0400
commit121c3171e5b4918337910250487691efa8dbbd49 (patch)
tree7b3e78726836b9ff0163d1291c7aabb7c2b136f2
parente44abe16bd20512c76331e6889f390e35993153a (diff)
downloadlibgit2-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.h4
-rw-r--r--src/win32/posix.h3
-rw-r--r--src/win32/posix_w32.c38
-rw-r--r--src/win32/w32_util.h10
-rw-r--r--tests/checkout/checkout_helpers.c12
-rw-r--r--tests/core/posix.c49
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");
+}