Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ include shared.mak
#
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
#
# Define NO_UTIMENSAT if you don't have utimensat.
#
# Define MKDIR_WO_TRAILING_SLASH if your mkdir() can't deal with trailing slash.
#
# Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
Expand Down Expand Up @@ -2049,6 +2051,10 @@ ifdef NO_WRITEV
COMPAT_CFLAGS += -DNO_WRITEV
COMPAT_OBJS += compat/writev.o
endif
ifdef NO_UTIMENSAT
COMPAT_CFLAGS += -DNO_UTIMENSAT
COMPAT_OBJS += compat/utimensat.o
endif
ifdef NO_FAST_WORKING_DIRECTORY
BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
endif
Expand Down
12 changes: 7 additions & 5 deletions builtin/pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -1438,11 +1438,13 @@ static void write_pack_file(void)
} else if (!last_mtime) {
last_mtime = st.st_mtime;
} else {
struct utimbuf utb;
utb.actime = st.st_atime;
utb.modtime = --last_mtime;
if (utime(pack_tmp_name, &utb) < 0)
warning_errno(_("failed utime() on %s"), pack_tmp_name);
struct timespec times[2];
times[0].tv_sec = st.st_atime;
times[0].tv_nsec = ST_ATIME_NSEC(st);
times[1].tv_sec = --last_mtime;
times[1].tv_nsec = 0;
if (utimensat(AT_FDCWD, pack_tmp_name, times, 0) < 0)
warning_errno(_("failed utimensat() on %s"), pack_tmp_name);
}

strbuf_addf(&tmpname, "%s-%s.", base_name,
Expand Down
17 changes: 6 additions & 11 deletions commit-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -2484,18 +2484,13 @@ static void mark_commit_graphs(struct write_commit_graph_context *ctx)
{
uint32_t i;
time_t now = time(NULL);
struct timespec times[2] = {
{ .tv_nsec = UTIME_OMIT },
{ .tv_sec = now, .tv_nsec = 0 },
};

for (i = ctx->num_commit_graphs_after - 1; i < ctx->num_commit_graphs_before; i++) {
struct stat st;
struct utimbuf updated_time;

if (stat(ctx->commit_graph_filenames_before[i], &st) < 0)
continue;

updated_time.actime = st.st_atime;
updated_time.modtime = now;
utime(ctx->commit_graph_filenames_before[i], &updated_time);
}
for (i = ctx->num_commit_graphs_after - 1; i < ctx->num_commit_graphs_before; i++)
utimensat(AT_FDCWD, ctx->commit_graph_filenames_before[i], times, 0);
}

static void expire_commit_graphs(struct write_commit_graph_context *ctx)
Expand Down
4 changes: 2 additions & 2 deletions compat/mingw-posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ int mingw_fstat(int fd, struct stat *buf);
#define lstat mingw_lstat


int mingw_utime(const char *file_name, const struct utimbuf *times);
#define utime mingw_utime
int mingw_utimensat(int fd, const char *path, const struct timespec times[2], int flag);
#define utimensat mingw_utimensat
size_t mingw_strftime(char *s, size_t max,
const char *format, const struct tm *tm);
#define strftime mingw_strftime
Expand Down
36 changes: 29 additions & 7 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1391,22 +1391,33 @@ int mingw_fstat(int fd, struct stat *buf)
}
}

static inline void time_t_to_filetime(time_t t, FILETIME *ft)
static inline void timespec_to_filetime(const struct timespec *ts, FILETIME *ft)
{
long long winTime = t * 10000000LL + 116444736000000000LL;
long long winTime = (long long)ts->tv_sec * 10000000LL + (ts->tv_nsec / 100) + 116444736000000000LL;
ft->dwLowDateTime = winTime;
ft->dwHighDateTime = winTime >> 32;
}

int mingw_utime (const char *file_name, const struct utimbuf *times)
int mingw_utimensat(int fd, const char *path, const struct timespec times[2], int flag)
{
FILETIME mft, aft;
FILETIME *paft = &aft, *pmft = &mft;
int rc;
DWORD attrs;
wchar_t wfilename[MAX_PATH];
HANDLE osfilehandle;

if (xutftowcs_path(wfilename, file_name) < 0)
if (fd != AT_FDCWD) {
errno = ENOSYS;
return -1;
}

if (flag) {
errno = ENOSYS;
return -1;
}

if (xutftowcs_path(wfilename, path) < 0)
return -1;

/* must have write permission */
Expand All @@ -1433,14 +1444,25 @@ 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);
if (times[0].tv_nsec == UTIME_NOW)
GetSystemTimeAsFileTime(&aft);
else if (times[0].tv_nsec == UTIME_OMIT)
paft = NULL;
else
timespec_to_filetime(&times[0], &aft);

if (times[1].tv_nsec == UTIME_NOW)
GetSystemTimeAsFileTime(&mft);
else if (times[1].tv_nsec == UTIME_OMIT)
pmft = NULL;
else
timespec_to_filetime(&times[1], &mft);
} else {
GetSystemTimeAsFileTime(&mft);
aft = mft;
}

if (!SetFileTime(osfilehandle, NULL, &aft, &mft)) {
if (!SetFileTime(osfilehandle, NULL, paft, pmft)) {
errno = EINVAL;
rc = -1;
} else
Expand Down
22 changes: 21 additions & 1 deletion compat/posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@
#include <signal.h>
#include <assert.h>
#include <regex.h>
#include <utime.h>
#include <syslog.h>
#if !defined(NO_POLL_H)
#include <poll.h>
Expand Down Expand Up @@ -348,6 +347,24 @@ struct git_iovec {
ssize_t git_writev(int fd, const struct iovec *iov, int iovcnt);
#endif

#ifndef AT_FDCWD
#define AT_FDCWD (-100)
#endif
#ifndef UTIME_NOW
#define UTIME_NOW ((1L << 30) - 1L)
#endif
#ifndef UTIME_OMIT
#define UTIME_OMIT ((1L << 30) - 2L)
#endif

#ifdef NO_UTIMENSAT
#ifdef utimensat
#undef utimensat
#endif
#define utimensat git_utimensat
int git_utimensat(int fd, const char *path, const struct timespec times[2], int flag);
#endif

#ifdef NO_SETENV
#define setenv gitsetenv
int gitsetenv(const char *, const char *, int);
Expand Down Expand Up @@ -502,13 +519,16 @@ int git_qsort_s(void *base, size_t nmemb, size_t size,

#ifdef NO_NSEC
#undef USE_NSEC
#define ST_ATIME_NSEC(st) 0
#define ST_CTIME_NSEC(st) 0
#define ST_MTIME_NSEC(st) 0
#else
#ifdef USE_ST_TIMESPEC
#define ST_ATIME_NSEC(st) ((unsigned int)((st).st_atimespec.tv_nsec))
#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
#else
#define ST_ATIME_NSEC(st) ((unsigned int)((st).st_atim.tv_nsec))
#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
#endif
Expand Down
39 changes: 39 additions & 0 deletions compat/utimensat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "../git-compat-util.h"

int git_utimensat(int fd, const char *path, const struct timespec times[2], int flag)
{
struct timeval tv[2];
struct timeval *tvp = NULL;

if (fd != AT_FDCWD) {
errno = ENOSYS;
return -1;
}

if (flag) {
errno = ENOSYS;
return -1;
}

if (times) {
for (int i = 0; i < 2; i++) {
if (times[i].tv_nsec == UTIME_NOW) {
struct timeval now;
gettimeofday(&now, NULL);
tv[i] = now;
} else if (times[i].tv_nsec == UTIME_OMIT) {
struct stat st;
if (stat(path, &st) < 0)
return -1;
tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
tv[i].tv_usec = (i == 0) ? ST_ATIME_NSEC(st) / 1000 : ST_MTIME_NSEC(st) / 1000;
} else {
tv[i].tv_sec = times[i].tv_sec;
tv[i].tv_usec = times[i].tv_nsec / 1000;
}
}
tvp = tv;
}

return utimes(path, tvp);
}
34 changes: 0 additions & 34 deletions compat/vcbuild/include/sys/utime.h

This file was deleted.

1 change: 0 additions & 1 deletion compat/vcbuild/include/utime.h

This file was deleted.

6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,12 @@ GIT_CHECK_FUNC(mkdtemp,
[NO_MKDTEMP=YesPlease])
GIT_CONF_SUBST([NO_MKDTEMP])
#
# Define NO_UTIMENSAT if you don't have utimensat in the C library.
GIT_CHECK_FUNC(utimensat,
[NO_UTIMENSAT=],
[NO_UTIMENSAT=YesPlease])
GIT_CONF_SUBST([NO_UTIMENSAT])
#
# Define NO_INITGROUPS if you don't have initgroups in the C library.
GIT_CHECK_FUNC(initgroups,
[NO_INITGROUPS=],
Expand Down
8 changes: 6 additions & 2 deletions contrib/buildsystems/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@ set(function_checks
strcasestr memmem strlcpy strtoimax strtoumax strtoull
setenv mkdtemp poll pread memmem writev)

#unsetenv,hstrerror are incompatible with windows build
#unsetenv,hstrerror,utimensat are incompatible with windows build (provided by compat/mingw.c)
if(NOT WIN32)
list(APPEND function_checks unsetenv hstrerror)
list(APPEND function_checks unsetenv hstrerror utimensat)
endif()

foreach(f ${function_checks})
Expand Down Expand Up @@ -428,6 +428,10 @@ if(NOT HAVE_WRITEV)
endif()

if(NOT WIN32)
if(NOT HAVE_UTIMENSAT)
list(APPEND compat_SOURCES compat/utimensat.c)
endif()

if(NOT HAVE_UNSETENV)
list(APPEND compat_SOURCES compat/unsetenv.c)
endif()
Expand Down
10 changes: 6 additions & 4 deletions copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ int copy_fd(int ifd, int ofd)
static int copy_times(const char *dst, const char *src)
{
struct stat st;
struct utimbuf times;
struct timespec times[2];
if (stat(src, &st) < 0)
return -1;
times.actime = st.st_atime;
times.modtime = st.st_mtime;
if (utime(dst, &times) < 0)
times[0].tv_sec = st.st_atime;
times[0].tv_nsec = ST_ATIME_NSEC(st);
times[1].tv_sec = st.st_mtime;
times[1].tv_nsec = ST_MTIME_NSEC(st);
if (utimensat(AT_FDCWD, dst, times, 0) < 0)
return -1;
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,8 @@ else
'unsetenv' : ['unsetenv.c'],
# provided by compat/mingw.c.
'getpagesize' : [],
# provided by compat/mingw.c.
'utimensat' : ['utimensat.c'],
}

if get_option('b_sanitize').contains('address') or get_option('b_sanitize').contains('leak')
Expand Down
12 changes: 7 additions & 5 deletions object-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,17 @@ const char *odb_loose_path(struct odb_source_loose *loose,
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
static int freshen_file(const char *fn, const time_t *mtime)
{
struct utimbuf times, *timesp = NULL;
struct timespec times[2], *timesp = NULL;

if (mtime) {
times.actime = *mtime;
times.modtime = *mtime;
timesp = &times;
times[0].tv_sec = *mtime;
times[0].tv_nsec = 0;
times[1].tv_sec = *mtime;
times[1].tv_nsec = 0;
timesp = times;
}

return !utime(fn, timesp);
return !utimensat(AT_FDCWD, fn, timesp, 0);
}

/*
Expand Down
10 changes: 5 additions & 5 deletions odb/source-loose.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,14 +807,14 @@ static int write_loose_object(struct odb_source_loose *loose,
close_loose_object(loose, fd, tmp_file.buf);

if (mtime) {
struct utimbuf utb = {
.actime = *mtime,
.modtime = *mtime,
struct timespec times[2] = {
{ .tv_sec = *mtime },
{ .tv_sec = *mtime },
};

if (utime(tmp_file.buf, &utb) < 0 &&
if (utimensat(AT_FDCWD, tmp_file.buf, times, 0) < 0 &&
!(flags & ODB_WRITE_OBJECT_SILENT))
warning_errno(_("failed utime() on %s"), tmp_file.buf);
warning_errno(_("failed utimensat() on %s"), tmp_file.buf);
}

return finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf,
Expand Down
Loading
Loading