diff options
Diffstat (limited to 'winpr/libwinpr/file/file.c')
-rw-r--r-- | winpr/libwinpr/file/file.c | 159 |
1 files changed, 85 insertions, 74 deletions
diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 01328b8..a016beb 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -21,11 +21,7 @@ #include <winpr/config.h> #include <winpr/debug.h> - -#if defined(__FreeBSD_kernel__) && defined(__GLIBC__) -#define _GNU_SOURCE -#define KFREEBSD -#endif +#include <winpr/assert.h> #include <winpr/wtypes.h> #include <winpr/crt.h> @@ -100,14 +96,15 @@ static BOOL FileCloseHandle(HANDLE handle) static BOOL FileSetEndOfFile(HANDLE hFile) { WINPR_FILE* pFile = (WINPR_FILE*)hFile; - INT64 size = 0; if (!hFile) return FALSE; - size = _ftelli64(pFile->fp); + const INT64 size = _ftelli64(pFile->fp); + if (size < 0) + return FALSE; - if (ftruncate(fileno(pFile->fp), size) < 0) + if (ftruncate(fileno(pFile->fp), (off_t)size) < 0) { char ebuffer[256] = { 0 }; WLog_ERR(TAG, "ftruncate %s failed with %s [0x%08X]", pFile->lpFileName, @@ -565,100 +562,114 @@ static UINT64 FileTimeToUS(const FILETIME* ft) return tmp; } +#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) +static struct timespec filetimeToTimespec(const FILETIME* ftime) +{ + WINPR_ASSERT(ftime); + UINT64 tmp = FileTimeToUS(ftime); + struct timespec ts = { 0 }; + ts.tv_sec = tmp / 1000000ULL; + ts.tv_nsec = (tmp % 1000000ULL) * 1000ULL; + return ts; +} + static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime) { - int rc = 0; -#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD) - struct stat buf; - /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */ - struct timeval timevals[2]; -#else - struct timespec times[2]; /* last access, last modification */ -#endif + struct timespec times[2] = { { UTIME_OMIT, UTIME_OMIT }, + { UTIME_OMIT, UTIME_OMIT } }; /* last access, last modification */ WINPR_FILE* pFile = (WINPR_FILE*)hFile; if (!hFile) return FALSE; -#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD) - rc = fstat(fileno(pFile->fp), &buf); + if (lpLastAccessTime) + times[0] = filetimeToTimespec(lpLastAccessTime); - if (rc < 0) + if (lpLastWriteTime) + times[1] = filetimeToTimespec(lpLastWriteTime); + + // TODO: Creation time can not be handled! + const int rc = futimens(fileno(pFile->fp), times); + if (rc != 0) return FALSE; -#endif + return TRUE; +} +#elif defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD) +static struct timeval filetimeToTimeval(const FILETIME* ftime) +{ + WINPR_ASSERT(ftime); + UINT64 tmp = FileTimeToUS(ftime); + struct timeval tv = { 0 }; + tv.tv_sec = tmp / 1000000ULL; + tv.tv_usec = tmp % 1000000ULL; + return tv; +} - if (!lpLastAccessTime) - { +static struct timeval statToTimeval(const struct stat* sval) +{ + WINPR_ASSERT(sval); + struct timeval tv = { 0 }; #if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) - timevals[0].tv_sec = buf.st_atime; + tv.tv_sec = sval->st_atime; #ifdef _POSIX_SOURCE - TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim); + TIMESPEC_TO_TIMEVAL(&tv, &sval->st_atim); #else - TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atimespec); + TIMESPEC_TO_TIMEVAL(&tv, &sval->st_atimespec); #endif #elif defined(ANDROID) - timevals[0].tv_sec = buf.st_atime; - timevals[0].tv_usec = buf.st_atimensec / 1000UL; -#else - times[0].tv_sec = UTIME_OMIT; - times[0].tv_nsec = UTIME_OMIT; + tv.tv_sec = sval->st_atime; + tv.tv_usec = sval->st_atimensec / 1000UL; #endif - } - else - { - UINT64 tmp = FileTimeToUS(lpLastAccessTime); -#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) - timevals[0].tv_sec = tmp / 1000000ULL; - timevals[0].tv_usec = tmp % 1000000ULL; -#else - times[0].tv_sec = tmp / 1000000ULL; - times[0].tv_nsec = (tmp % 1000000ULL) * 1000ULL; -#endif - } + return tv; +} - if (!lpLastWriteTime) - { -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) - timevals[1].tv_sec = buf.st_mtime; -#ifdef _POSIX_SOURCE - TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim); -#else - TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtimespec); -#endif -#elif defined(ANDROID) - timevals[1].tv_sec = buf.st_mtime; - timevals[1].tv_usec = buf.st_mtimensec / 1000UL; -#else - times[1].tv_sec = UTIME_OMIT; - times[1].tv_nsec = UTIME_OMIT; -#endif - } - else +static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, + const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime) +{ + struct stat buf = { 0 }; + /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */ + WINPR_FILE* pFile = (WINPR_FILE*)hFile; + + if (!hFile) + return FALSE; + + const int rc = fstat(fileno(pFile->fp), &buf); + if (rc < 0) + return FALSE; + + struct timeval timevals[2] = { statToTimeval(&buf), statToTimeval(&buf) }; + if (lpLastAccessTime) + timevals[0] = filetimeToTimeval(lpLastAccessTime); + + if (lpLastWriteTime) + timevals[1] = filetimeToTimeval(lpLastWriteTime); + + // TODO: Creation time can not be handled! { - UINT64 tmp = FileTimeToUS(lpLastWriteTime); -#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) - timevals[1].tv_sec = tmp / 1000000ULL; - timevals[1].tv_usec = tmp % 1000000ULL; -#else - times[1].tv_sec = tmp / 1000000ULL; - times[1].tv_nsec = (tmp % 1000000ULL) * 1000ULL; -#endif + const int rc = utimes(pFile->lpFileName, timevals); + if (rc != 0) + return FALSE; } - // TODO: Creation time can not be handled! -#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD) - rc = utimes(pFile->lpFileName, timevals); + return TRUE; +} #else - rc = futimens(fileno(pFile->fp), times); -#endif +static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, + const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime) +{ + WINPR_FILE* pFile = (WINPR_FILE*)hFile; - if (rc != 0) + if (!hFile) return FALSE; + WLog_WARN(TAG, "TODO: Creation, Access and Write time can not be handled!"); + WLog_WARN(TAG, + "TODO: Define _POSIX_C_SOURCE >= 200809L or implement a platform specific handler!"); return TRUE; } +#endif static HANDLE_OPS fileOps = { FileIsHandled, |