From 62f5df5852a32dc9d58b7aa4bdafa3d3c773f708 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 28 Nov 2011 04:32:04 +0100 Subject: [PATCH] Provide futimens(), utimensat() missing on FreeBSD --- headers/build/host/freebsd/sys/stat.h | 25 +++++ src/build/libroot/fs_freebsd.cpp | 128 +++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 headers/build/host/freebsd/sys/stat.h diff --git a/headers/build/host/freebsd/sys/stat.h b/headers/build/host/freebsd/sys/stat.h new file mode 100644 index 0000000000..bc8cd2751f --- /dev/null +++ b/headers/build/host/freebsd/sys/stat.h @@ -0,0 +1,25 @@ +#ifndef _HAIKU_BUILD_COMPATIBILITY_FREEBSD_SYS_STAT +#define _HAIKU_BUILD_COMPATIBILITY_FREEBSD_SYS_STAT + +#include_next + + +#ifndef UTIME_NOW +# define UTIME_NOW (-1) +# define UTIME_OMIT (-2) + + /* assume that futimens() and utimensat() aren't available */ + int futimens(int fd, const struct timespec times[2]); + int utimensat(int fd, const char* path, const struct timespec times[2], + int flag); + +# ifndef _HAIKU_BUILD_NO_FUTIMENS +# define _HAIKU_BUILD_NO_FUTIMENS 1 +# endif +# ifndef _HAIKU_BUILD_NO_UTIMENSAT +# define _HAIKU_BUILD_NO_UTIMENSAT 1 +# endif +#endif + + +#endif /* _HAIKU_BUILD_COMPATIBILITY_FREEBSD_SYS_STAT */ diff --git a/src/build/libroot/fs_freebsd.cpp b/src/build/libroot/fs_freebsd.cpp index e6fc60ff21..339d8a5dc9 100644 --- a/src/build/libroot/fs_freebsd.cpp +++ b/src/build/libroot/fs_freebsd.cpp @@ -1,5 +1,6 @@ /* * Copyright 2008, Samuel Rodriguez Perez, samuelgaliza@gmail.com. + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -7,12 +8,13 @@ #include #include -#include #include +#include #include #include #include #include +#include #include @@ -252,3 +254,127 @@ haiku_freebsd_writev(int fd, const struct iovec *vecs, size_t count) return bytesWritten; } + + +#if defined(_HAIKU_BUILD_NO_FUTIMENS) || defined(_HAIKU_BUILD_NO_FUTIMENS) + +template +static int +utimes_helper(File& file, const struct timespec times[2]) +{ + if (times == NULL) + return file.SetTimes(NULL); + + timeval timeBuffer[2]; + timeBuffer[0].tv_sec = times[0].tv_sec; + timeBuffer[0].tv_usec = times[0].tv_nsec / 1000; + timeBuffer[1].tv_sec = times[1].tv_sec; + timeBuffer[1].tv_usec = times[1].tv_nsec / 1000; + + if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) { + struct stat st; + if (file.GetStat(st) != 0) + return -1; + + if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) + return 0; + + if (times[0].tv_nsec == UTIME_OMIT) { + timeBuffer[0].tv_sec = st.st_atimespec.tv_sec; + timeBuffer[0].tv_usec = st.st_atimespec.tv_nsec / 1000; + } + + if (times[1].tv_nsec == UTIME_OMIT) { + timeBuffer[1].tv_sec = st.st_mtimespec.tv_sec; + timeBuffer[1].tv_usec = st.st_mtimespec.tv_nsec / 1000; + } + } + + if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) { + timeval now; + gettimeofday(&now, NULL); + + if (times[0].tv_nsec == UTIME_NOW) + timeBuffer[0] = now; + + if (times[1].tv_nsec == UTIME_NOW) + timeBuffer[1] = now; + } + + return file.SetTimes(timeBuffer); +} + +#endif // _HAIKU_BUILD_NO_FUTIMENS || _HAIKU_BUILD_NO_FUTIMENS + + +#ifdef _HAIKU_BUILD_NO_FUTIMENS + +struct FDFile { + FDFile(int fd) + : + fFD(fd) + { + } + + int GetStat(struct stat& _st) + { + return fstat(fFD, &_st); + } + + int SetTimes(const timeval times[2]) + { + return futimes(fFD, times); + } + +private: + int fFD; +}; + + +int +futimens(int fd, const struct timespec times[2]) +{ + FDFile file(fd); + return utimes_helper(file, times); +} + +#endif // _HAIKU_BUILD_NO_FUTIMENS + + +#ifdef _HAIKU_BUILD_NO_UTIMENSAT + +struct FDPathFile { + FDPathFile(int fd, const char* path, int flag) + : + fFD(fd), + fPath(path), + fFlag(flag) + { + } + + int GetStat(struct stat& _st) + { + return fstatat(fFD, fPath, &_st, fFlag); + } + + int SetTimes(const timeval times[2]) + { + // TODO: fFlag (AT_SYMLINK_NOFOLLOW) is not supported here! + return futimesat(fFD, fPath, times); + } + +private: + int fFD; + const char* fPath; + int fFlag; +}; + + +int +utimensat(int fd, const char* path, const struct timespec times[2], int flag) +{ + FDPathFile file(fd, path, flag); + return utimes_helper(file, times); +} + +#endif // _HAIKU_BUILD_NO_UTIMENSAT