@@ -734,11 +734,14 @@ int mingw_chmod(const char *filename, int mode)
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
*/
+
+#define UNIX_EPOCH_FILETIME 116444736000000000LL
+
static inline long long filetime_to_hnsec(const FILETIME *ft)
{
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
/* Windows to Unix Epoch conversion */
- return winTime - 116444736000000000LL;
+ return winTime - UNIX_EPOCH_FILETIME;
}
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
@@ -748,6 +751,13 @@ static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
ts->tv_nsec = (hnsec % 10000000) * 100;
}
+static inline void timespec_to_filetime(const struct timespec *t, FILETIME *ft)
+{
+ long long winTime = t->tv_sec * 10000000LL + t->tv_nsec / 100 + UNIX_EPOCH_FILETIME;
+ ft->dwLowDateTime = winTime;
+ ft->dwHighDateTime = winTime >> 32;
+}
+
/**
* Verifies that safe_create_leading_directories() would succeed.
*/
@@ -949,19 +959,33 @@ int mingw_fstat(int fd, struct stat *buf)
}
}
-static inline void time_t_to_filetime(time_t t, FILETIME *ft)
+int mingw_futimens(int fd, const struct timespec times[2])
{
- long long winTime = t * 10000000LL + 116444736000000000LL;
- ft->dwLowDateTime = winTime;
- ft->dwHighDateTime = winTime >> 32;
+ FILETIME mft, aft;
+
+ if (times) {
+ timespec_to_filetime(×[0], &aft);
+ timespec_to_filetime(×[1], &mft);
+ } else {
+ GetSystemTimeAsFileTime(&mft);
+ aft = mft;
+ }
+
+ if (!SetFileTime((HANDLE)_get_osfhandle(fd), NULL, &aft, &mft)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
}
-int mingw_utime (const char *file_name, const struct utimbuf *times)
+int mingw_utime(const char *file_name, const struct utimbuf *times)
{
- FILETIME mft, aft;
int fh, rc;
DWORD attrs;
wchar_t wfilename[MAX_PATH];
+ struct timespec ts[2];
+
if (xutftowcs_path(wfilename, file_name) < 0)
return -1;
@@ -979,17 +1003,12 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
}
if (times) {
- time_t_to_filetime(times->modtime, &mft);
- time_t_to_filetime(times->actime, &aft);
- } else {
- GetSystemTimeAsFileTime(&mft);
- aft = mft;
+ memset(ts, 0, sizeof(ts));
+ ts[0].tv_sec = times->actime;
+ ts[1].tv_sec = times->modtime;
}
- if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
- errno = EINVAL;
- rc = -1;
- } else
- rc = 0;
+
+ rc = mingw_futimens(fh, times ? ts : NULL);
close(fh);
revert_attrs:
@@ -398,6 +398,8 @@ int mingw_fstat(int fd, struct stat *buf);
int mingw_utime(const char *file_name, const struct utimbuf *times);
#define utime mingw_utime
+int mingw_futimens(int fd, const struct timespec times[2]);
+#define futimens mingw_futimens
size_t mingw_strftime(char *s, size_t max,
const char *format, const struct tm *tm);
#define strftime mingw_strftime
@@ -1860,12 +1860,13 @@ int hash_object_file(const struct git_hash_algo *algo, const void *buf,
}
/* Finalize a file on disk, and close it. */
-static void close_loose_object(int fd)
+static int close_loose_object(int fd, const char *tmpfile, const char *filename)
{
if (fsync_object_files)
fsync_or_die(fd, "loose object file");
if (close(fd) != 0)
die_errno(_("error when closing loose object file"));
+ return finalize_object_file(tmpfile, filename);
}
/* Size of directory component, including the ending '/' */
@@ -1973,17 +1974,15 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
die(_("confused by unstable object source data for %s"),
oid_to_hex(oid));
- close_loose_object(fd);
-
if (mtime) {
- struct utimbuf utb;
- utb.actime = mtime;
- utb.modtime = mtime;
- if (utime(tmp_file.buf, &utb) < 0)
- warning_errno(_("failed utime() on %s"), tmp_file.buf);
+ struct timespec ts[2] = {0};
+ ts[0].tv_sec = mtime;
+ ts[1].tv_sec = mtime;
+ if (futimens(fd, ts) < 0)
+ warning_errno(_("failed futimes() on %s"), tmp_file.buf);
}
- return finalize_object_file(tmp_file.buf, filename.buf);
+ return close_loose_object(fd, tmp_file.buf, filename.buf);
}
static int freshen_loose_object(const struct object_id *oid)