diff --git a/os.c b/os.c index f9e9bd40..11956bbb 100644 --- a/os.c +++ b/os.c @@ -230,7 +230,7 @@ int get_file_meta(const char *path, struct file_meta *metap) *metap = FILE_META_NONEXIST; } else { metap->size = st.st_size; - metap->mtime = st.st_mtim; + metap->mtime.tv_sec = st.st_mtime; // Truncate to whole seconds to ensure that this code will work on file systems that only have // whole-second time stamp resolution. metap->mtime.tv_nsec = 0; @@ -319,12 +319,14 @@ int alter_file_meta(const char *path, const struct file_meta *origp, struct file return 0; meta.mtime = origp->mtime; add_timespec(&meta.mtime, sec, nsec); - struct timespec times[2]; - times[0].tv_sec = 0; - times[0].tv_nsec = UTIME_OMIT; - times[1] = meta.mtime; - if (utimensat(AT_FDCWD, path, times, 0) == -1) - return WHYF_perror("utimensat(AT_FDCWD,%s,[UTIME_OMIT,%s],0)", alloca_str_toprint(path), alloca_timespec(×[1])); + struct timeval times[2]; + time_ms_t now = gettime_ms(); + times[0].tv_sec = now / 1000; + times[0].tv_usec = (now % 1000) * 1000; + times[1].tv_sec = meta.mtime.tv_sec; + times[1].tv_usec = meta.mtime.tv_nsec / 1000; + if (utimes(path, times) == -1) + return WHYF_perror("utimes(%s,[%s,%s])", alloca_str_toprint(path), alloca_timeval(×[0]), alloca_timeval(×[1])); nsec = 0; ++sec; } diff --git a/strbuf_helpers.c b/strbuf_helpers.c index 3ebbed36..0f5f4bc6 100644 --- a/strbuf_helpers.c +++ b/strbuf_helpers.c @@ -460,6 +460,31 @@ strbuf strbuf_append_time_t(strbuf sb, time_t time) return sb; } +strbuf strbuf_append_time_ms_t(strbuf sb, time_ms_t ms) +{ + struct tm tm; + time_t time = ms / 1000; + localtime_r(&time, &tm); + strbuf_append_strftime(sb, "%Y/%m/%d %H:%M:%S", &tm); + strbuf_sprintf(sb, ".%.03u", (unsigned)(ms % 1000)); + strbuf_append_strftime(sb, " %z", &tm); + return sb; +} + +strbuf strbuf_append_timeval(strbuf sb, const struct timeval *tv) +{ + if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec > 999999) { + strbuf_sprintf(sb, "INVALID{tv_sec=%ld,tv_usec=%ld}", (long)tv->tv_sec, (long)tv->tv_usec); + } else { + struct tm tm; + localtime_r(&tv->tv_sec, &tm); + strbuf_append_strftime(sb, "%Y/%m/%d %H:%M:%S", &tm); + strbuf_sprintf(sb, ".%.06lu", (long)tv->tv_usec); + strbuf_append_strftime(sb, " %z", &tm); + } + return sb; +} + strbuf strbuf_append_timespec(strbuf sb, const struct timespec *tv) { if (tv->tv_sec < 0 || tv->tv_nsec < 0 || tv->tv_nsec > 999999999) { diff --git a/strbuf_helpers.h b/strbuf_helpers.h index 92820a5f..94bed1bd 100644 --- a/strbuf_helpers.h +++ b/strbuf_helpers.h @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #endif #include "strbuf.h" +#include "os.h" /* Append a representation of the given chars in a given buffer (including nul * chars) in printable format, ie, with non-printable characters expanded to \n @@ -161,18 +162,31 @@ struct iovec; strbuf strbuf_append_iovec(strbuf sb, const struct iovec *iov, int iovcnt); #define alloca_iovec(iov,cnt) strbuf_str(strbuf_append_iovec(strbuf_alloca(200), (iov), (cnt))) -/* Append a representation of a time_t value. +/* Append a representation of a time_t value (second resolution). * @author Andrew Bettison */ strbuf strbuf_append_time_t(strbuf sb, time_t); #define alloca_time_t(t) strbuf_str(strbuf_append_time_t(strbuf_alloca(40), (t))) -/* Append a representation of a struct timespec. +/* Append a representation of a time_ms_t value (millisecond resolution). + * @author Andrew Bettison + */ +strbuf strbuf_append_time_ms_t(strbuf sb, time_ms_t); +#define alloca_time_ms_t(t) strbuf_str(strbuf_append_time_ms_t(strbuf_alloca(45), (t))) + +/* Append a representation of a struct timeval (microsecond resolution). + * @author Andrew Bettison + */ +struct timeval; +strbuf strbuf_append_timeval(strbuf sb, const struct timeval *tv); +#define alloca_timeval(tv) strbuf_str(strbuf_append_timeval(strbuf_alloca(50), (tv))) + +/* Append a representation of a struct timespec (nanosecond resolution). * @author Andrew Bettison */ struct timespec; strbuf strbuf_append_timespec(strbuf sb, const struct timespec *tv); -#define alloca_timespec(tv) strbuf_str(strbuf_append_timespec(strbuf_alloca(50), (tv))) +#define alloca_timespec(tv) strbuf_str(strbuf_append_timespec(strbuf_alloca(55), (tv))) /* Append a representation of a struct file_meta. * @author Andrew Bettison