Provide futimens(), utimensat() missing on FreeBSD

This commit is contained in:
Ingo Weinhold 2011-11-28 04:32:04 +01:00
parent b328f5b034
commit 62f5df5852
2 changed files with 152 additions and 1 deletions

View File

@ -0,0 +1,25 @@
#ifndef _HAIKU_BUILD_COMPATIBILITY_FREEBSD_SYS_STAT
#define _HAIKU_BUILD_COMPATIBILITY_FREEBSD_SYS_STAT
#include_next <sys/stat.h>
#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 */

View File

@ -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 <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
@ -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<typename File>
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