22 #include <winpr/config.h>
23 #include <winpr/debug.h>
24 #include <winpr/assert.h>
26 #include <winpr/wtypes.h>
27 #include <winpr/crt.h>
28 #include <winpr/file.h>
37 #define TAG WINPR_TAG("file")
39 #include <winpr/wlog.h>
40 #include <winpr/string.h>
52 #include <sys/statvfs.h>
56 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
59 static BOOL FileIsHandled(HANDLE handle)
61 return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_FILE, FALSE);
64 static int FileGetFd(HANDLE handle)
66 WINPR_FILE* file = (WINPR_FILE*)handle;
68 if (!FileIsHandled(handle))
71 return fileno(file->fp);
74 static BOOL FileCloseHandle(HANDLE handle)
76 WINPR_FILE* file = (WINPR_FILE*)handle;
78 if (!FileIsHandled(handle))
84 if (fileno(file->fp) > 2)
86 (void)fclose(file->fp);
91 free(file->lpFileName);
96 static BOOL FileSetEndOfFile(HANDLE hFile)
98 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
103 const INT64 size = _ftelli64(pFile->fp);
107 if (ftruncate(fileno(pFile->fp), (off_t)size) < 0)
109 char ebuffer[256] = { 0 };
110 WLog_ERR(TAG,
"ftruncate %s failed with %s [0x%08X]", pFile->lpFileName,
111 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
112 SetLastError(map_posix_err(errno));
120 static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove,
121 const PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
124 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
129 return INVALID_SET_FILE_POINTER;
133 if (lpDistanceToMoveHigh)
135 offset = (INT64)(((UINT64)*lpDistanceToMoveHigh << 32U) | (UINT64)lDistanceToMove);
138 offset = lDistanceToMove;
140 switch (dwMoveMethod)
152 return INVALID_SET_FILE_POINTER;
155 if (_fseeki64(pFile->fp, offset, whence))
157 char ebuffer[256] = { 0 };
158 WLog_ERR(TAG,
"_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName,
159 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
160 return INVALID_SET_FILE_POINTER;
163 return (DWORD)_ftelli64(pFile->fp);
166 static BOOL FileSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
167 PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
169 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
175 switch (dwMoveMethod)
190 if (_fseeki64(pFile->fp, liDistanceToMove.QuadPart, whence))
192 char ebuffer[256] = { 0 };
193 WLog_ERR(TAG,
"_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName,
194 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
198 if (lpNewFilePointer)
199 lpNewFilePointer->QuadPart = _ftelli64(pFile->fp);
204 static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
207 size_t io_status = 0;
208 WINPR_FILE* file = NULL;
213 WLog_ERR(TAG,
"WinPR does not support the lpOverlapped parameter");
214 SetLastError(ERROR_NOT_SUPPORTED);
221 file = (WINPR_FILE*)Object;
223 io_status = fread(lpBuffer, 1, nNumberOfBytesToRead, file->fp);
225 if (io_status == 0 && ferror(file->fp))
232 SetLastError(ERROR_NO_DATA);
235 SetLastError(map_posix_err(errno));
239 if (lpNumberOfBytesRead)
240 *lpNumberOfBytesRead = (DWORD)io_status;
245 static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
246 LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
248 size_t io_status = 0;
249 WINPR_FILE* file = NULL;
253 WLog_ERR(TAG,
"WinPR does not support the lpOverlapped parameter");
254 SetLastError(ERROR_NOT_SUPPORTED);
261 file = (WINPR_FILE*)Object;
264 io_status = fwrite(lpBuffer, 1, nNumberOfBytesToWrite, file->fp);
265 if (io_status == 0 && ferror(file->fp))
267 SetLastError(map_posix_err(errno));
271 *lpNumberOfBytesWritten = (DWORD)io_status;
275 static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh)
277 WINPR_FILE* file = NULL;
284 file = (WINPR_FILE*)Object;
286 cur = _ftelli64(file->fp);
290 char ebuffer[256] = { 0 };
291 WLog_ERR(TAG,
"_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName,
292 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
293 return INVALID_FILE_SIZE;
296 if (_fseeki64(file->fp, 0, SEEK_END) != 0)
298 char ebuffer[256] = { 0 };
299 WLog_ERR(TAG,
"_fseeki64(%s) failed with %s [0x%08X]", file->lpFileName,
300 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
301 return INVALID_FILE_SIZE;
304 size = _ftelli64(file->fp);
308 char ebuffer[256] = { 0 };
309 WLog_ERR(TAG,
"_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName,
310 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
311 return INVALID_FILE_SIZE;
314 if (_fseeki64(file->fp, cur, SEEK_SET) != 0)
316 char ebuffer[256] = { 0 };
317 WLog_ERR(TAG,
"_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName,
318 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
319 return INVALID_FILE_SIZE;
323 *lpFileSizeHigh = (UINT32)(size >> 32);
325 return (UINT32)(size & 0xFFFFFFFF);
328 static BOOL FileGetFileInformationByHandle(HANDLE hFile,
331 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
334 const char* lastSep = NULL;
338 if (!lpFileInformation)
341 if (fstat(fileno(pFile->fp), &st) == -1)
343 char ebuffer[256] = { 0 };
344 WLog_ERR(TAG,
"fstat failed with %s [%#08X]", errno,
345 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
349 lpFileInformation->dwFileAttributes = 0;
351 if (S_ISDIR(st.st_mode))
352 lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
354 if (lpFileInformation->dwFileAttributes == 0)
355 lpFileInformation->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
357 lastSep = strrchr(pFile->lpFileName,
'/');
361 const char* name = lastSep + 1;
362 const size_t namelen = strlen(name);
364 if ((namelen > 1) && (name[0] ==
'.') && (name[1] !=
'.'))
365 lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
368 if (!(st.st_mode & S_IWUSR))
369 lpFileInformation->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
371 #ifdef _DARWIN_FEATURE_64_BIT_INODE
372 ft = STAT_TIME_TO_FILETIME(st.st_birthtime);
374 ft = STAT_TIME_TO_FILETIME(st.st_ctime);
376 lpFileInformation->ftCreationTime.dwHighDateTime = (ft) >> 32ULL;
377 lpFileInformation->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
378 ft = STAT_TIME_TO_FILETIME(st.st_mtime);
379 lpFileInformation->ftLastWriteTime.dwHighDateTime = (ft) >> 32ULL;
380 lpFileInformation->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
381 ft = STAT_TIME_TO_FILETIME(st.st_atime);
382 lpFileInformation->ftLastAccessTime.dwHighDateTime = (ft) >> 32ULL;
383 lpFileInformation->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
384 lpFileInformation->nFileSizeHigh = ((UINT64)st.st_size) >> 32ULL;
385 lpFileInformation->nFileSizeLow = st.st_size & 0xFFFFFFFF;
386 lpFileInformation->dwVolumeSerialNumber = (UINT32)st.st_dev;
387 lpFileInformation->nNumberOfLinks = (UINT32)st.st_nlink;
388 lpFileInformation->nFileIndexHigh = (st.st_ino >> 4) & 0xFFFFFFFF;
389 lpFileInformation->nFileIndexLow = st.st_ino & 0xFFFFFFFF;
393 static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
394 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
403 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
407 WLog_ERR(TAG,
"WinPR does not support the lpOverlapped parameter");
408 SetLastError(ERROR_NOT_SUPPORTED);
417 WLog_ERR(TAG,
"File %s already locked!", pFile->lpFileName);
424 lock.l_whence = SEEK_SET;
426 if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
427 lock.l_type = F_WRLCK;
429 lock.l_type = F_WRLCK;
431 if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
436 if (fcntl(fileno(pFile->fp), lckcmd, &lock) == -1)
438 char ebuffer[256] = { 0 };
439 WLog_ERR(TAG,
"F_SETLK failed with %s [0x%08X]",
440 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
444 if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
449 if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
452 if (flock(fileno(pFile->fp), lock) < 0)
454 char ebuffer[256] = { 0 };
455 WLog_ERR(TAG,
"flock failed with %s [0x%08X]",
456 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
461 pFile->bLocked = TRUE;
466 static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
467 DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
469 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
479 WLog_ERR(TAG,
"File %s is not locked!", pFile->lpFileName);
486 lock.l_whence = SEEK_SET;
487 lock.l_type = F_UNLCK;
488 if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1)
490 char ebuffer[256] = { 0 };
491 WLog_ERR(TAG,
"F_UNLCK on %s failed with %s [0x%08X]", pFile->lpFileName,
492 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
497 if (flock(fileno(pFile->fp), LOCK_UN) < 0)
499 char ebuffer[256] = { 0 };
500 WLog_ERR(TAG,
"flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName,
501 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
509 static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
510 DWORD nNumberOfBytesToUnlockHigh,
LPOVERLAPPED lpOverlapped)
512 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
519 WLog_ERR(TAG,
"WinPR does not support the lpOverlapped parameter");
520 SetLastError(ERROR_NOT_SUPPORTED);
529 WLog_ERR(TAG,
"File %s is not locked!", pFile->lpFileName);
536 lock.l_whence = SEEK_SET;
537 lock.l_type = F_UNLCK;
538 if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1)
540 char ebuffer[256] = { 0 };
541 WLog_ERR(TAG,
"F_UNLCK on %s failed with %s [0x%08X]", pFile->lpFileName,
542 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
546 if (flock(fileno(pFile->fp), LOCK_UN) < 0)
548 char ebuffer[256] = { 0 };
549 WLog_ERR(TAG,
"flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName,
550 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
558 static INT64 FileTimeToUS(
const FILETIME* ft)
560 const INT64 EPOCH_DIFF_US = EPOCH_DIFF * 1000000LL;
561 INT64 tmp = ((INT64)ft->dwHighDateTime) << 32 | ft->dwLowDateTime;
563 tmp -= EPOCH_DIFF_US;
567 #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
568 static struct timespec filetimeToTimespec(const FILETIME* ftime)
571 INT64 tmp = FileTimeToUS(ftime);
572 struct timespec ts = { 0 };
573 ts.tv_sec = tmp / 1000000LL;
574 ts.tv_nsec = (tmp % 1000000LL) * 1000LL;
578 static BOOL FileSetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
579 const FILETIME* lpLastAccessTime,
const FILETIME* lpLastWriteTime)
581 struct timespec times[2] = { { UTIME_OMIT, UTIME_OMIT },
582 { UTIME_OMIT, UTIME_OMIT } };
583 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
588 if (lpLastAccessTime)
589 times[0] = filetimeToTimespec(lpLastAccessTime);
592 times[1] = filetimeToTimespec(lpLastWriteTime);
595 const int rc = futimens(fileno(pFile->fp), times);
601 #elif defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
602 static struct timeval filetimeToTimeval(const FILETIME* ftime)
605 UINT64 tmp = FileTimeToUS(ftime);
606 struct timeval tv = { 0 };
607 tv.tv_sec = tmp / 1000000ULL;
608 tv.tv_usec = tmp % 1000000ULL;
612 static struct timeval statToTimeval(const struct stat* sval)
615 struct timeval tv = { 0 };
616 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
617 tv.tv_sec = sval->st_atime;
619 TIMESPEC_TO_TIMEVAL(&tv, &sval->st_atim);
621 TIMESPEC_TO_TIMEVAL(&tv, &sval->st_atimespec);
623 #elif defined(ANDROID)
624 tv.tv_sec = sval->st_atime;
625 tv.tv_usec = sval->st_atimensec / 1000UL;
630 static BOOL FileSetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
631 const FILETIME* lpLastAccessTime,
const FILETIME* lpLastWriteTime)
633 struct stat buf = { 0 };
635 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
640 const int rc = fstat(fileno(pFile->fp), &buf);
644 struct timeval timevals[2] = { statToTimeval(&buf), statToTimeval(&buf) };
645 if (lpLastAccessTime)
646 timevals[0] = filetimeToTimeval(lpLastAccessTime);
649 timevals[1] = filetimeToTimeval(lpLastWriteTime);
653 const int res = utimes(pFile->lpFileName, timevals);
661 static BOOL FileSetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
662 const FILETIME* lpLastAccessTime,
const FILETIME* lpLastWriteTime)
664 WINPR_FILE* pFile = (WINPR_FILE*)hFile;
669 WLog_WARN(TAG,
"TODO: Creation, Access and Write time can not be handled!");
671 "TODO: Define _POSIX_C_SOURCE >= 200809L or implement a platform specific handler!");
691 FileSetFilePointerEx,
697 FileGetFileInformationByHandle,
721 FileGetFileInformationByHandle,
724 static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create)
726 BOOL writeable = (dwDesiredAccess & (GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
728 switch (dwCreationDisposition)
732 return (writeable) ?
"wb+" :
"rwb";
741 return (writeable) ?
"rb+" :
"rb";
742 case TRUNCATE_EXISTING:
751 UINT32 map_posix_err(
int fs_errno)
767 rc = ERROR_FILE_NOT_FOUND;
773 rc = ERROR_ACCESS_DENIED;
777 rc = ERROR_FILE_NOT_FOUND;
781 rc = ERROR_BUSY_DRIVE;
785 rc = ERROR_FILE_EXISTS;
789 rc = STATUS_FILE_IS_A_DIRECTORY;
793 rc = STATUS_DIRECTORY_NOT_EMPTY;
797 rc = STATUS_TOO_MANY_OPENED_FILES;
802 char ebuffer[256] = { 0 };
803 WLog_ERR(TAG,
"Missing ERRNO mapping %s [%d]",
804 winpr_strerror(fs_errno, ebuffer,
sizeof(ebuffer)), fs_errno);
805 rc = STATUS_UNSUCCESSFUL;
813 static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
814 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
815 DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
816 HANDLE hTemplateFile)
818 WINPR_FILE* pFile = NULL;
820 const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create);
829 if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
831 WLog_ERR(TAG,
"WinPR does not support the FILE_FLAG_OVERLAPPED flag");
832 SetLastError(ERROR_NOT_SUPPORTED);
833 return INVALID_HANDLE_VALUE;
836 pFile = (WINPR_FILE*)calloc(1,
sizeof(WINPR_FILE));
839 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
840 return INVALID_HANDLE_VALUE;
843 WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
844 pFile->common.ops = &fileOps;
846 pFile->lpFileName = _strdup(lpFileName);
847 if (!pFile->lpFileName)
849 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
851 return INVALID_HANDLE_VALUE;
854 pFile->dwOpenMode = dwDesiredAccess;
855 pFile->dwShareMode = dwShareMode;
856 pFile->dwFlagsAndAttributes = dwFlagsAndAttributes;
857 pFile->lpSecurityAttributes = lpSecurityAttributes;
858 pFile->dwCreationDisposition = dwCreationDisposition;
859 pFile->hTemplateFile = hTemplateFile;
863 if (dwCreationDisposition == CREATE_NEW)
865 if (stat(pFile->lpFileName, &st) == 0)
867 SetLastError(ERROR_FILE_EXISTS);
868 free(pFile->lpFileName);
870 return INVALID_HANDLE_VALUE;
874 fp = winpr_fopen(pFile->lpFileName,
"ab");
877 SetLastError(map_posix_err(errno));
878 free(pFile->lpFileName);
880 return INVALID_HANDLE_VALUE;
883 fp = freopen(pFile->lpFileName, mode, fp);
887 if (stat(pFile->lpFileName, &st) != 0)
889 SetLastError(map_posix_err(errno));
890 free(pFile->lpFileName);
892 return INVALID_HANDLE_VALUE;
898 if (S_ISFIFO(st.st_mode))
900 SetLastError(ERROR_FILE_NOT_FOUND);
901 free(pFile->lpFileName);
903 return INVALID_HANDLE_VALUE;
908 fp = winpr_fopen(pFile->lpFileName, mode);
915 SetLastError(map_posix_err(errno));
916 free(pFile->lpFileName);
918 return INVALID_HANDLE_VALUE;
921 (void)setvbuf(fp, NULL, _IONBF, 0);
926 lock.l_whence = SEEK_SET;
928 if (dwShareMode & FILE_SHARE_READ)
929 lock.l_type = F_RDLCK;
930 if (dwShareMode & FILE_SHARE_WRITE)
931 lock.l_type = F_RDLCK;
933 if (dwShareMode & FILE_SHARE_READ)
935 if (dwShareMode & FILE_SHARE_WRITE)
939 if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE))
942 if (fcntl(fileno(pFile->fp), F_SETLKW, &lock) == -1)
944 if (flock(fileno(pFile->fp), lock) < 0)
947 char ebuffer[256] = { 0 };
949 WLog_ERR(TAG,
"F_SETLKW failed with %s [0x%08X]",
950 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
952 WLog_ERR(TAG,
"flock failed with %s [0x%08X]",
953 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)), errno);
956 SetLastError(map_posix_err(errno));
957 FileCloseHandle(pFile);
958 return INVALID_HANDLE_VALUE;
961 pFile->bLocked = TRUE;
964 if (fstat(fileno(pFile->fp), &st) == 0 && dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY)
966 st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
967 fchmod(fileno(pFile->fp), st.st_mode);
970 SetLastError(STATUS_SUCCESS);
974 static BOOL IsFileDevice(LPCTSTR lpDeviceName)
979 static const HANDLE_CREATOR FileHandleCreator = { IsFileDevice, FileCreateFileA };
983 return &FileHandleCreator;
986 static WINPR_FILE* FileHandle_New(FILE* fp)
988 WINPR_FILE* pFile = NULL;
989 char name[MAX_PATH] = { 0 };
991 (void)_snprintf(name,
sizeof(name),
"device_%d", fileno(fp));
992 pFile = (WINPR_FILE*)calloc(1,
sizeof(WINPR_FILE));
995 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
999 pFile->common.ops = &shmOps;
1000 pFile->lpFileName = _strdup(name);
1002 WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
1006 HANDLE GetStdHandle(DWORD nStdHandle)
1009 WINPR_FILE* pFile = NULL;
1013 case STD_INPUT_HANDLE:
1016 case STD_OUTPUT_HANDLE:
1019 case STD_ERROR_HANDLE:
1023 return INVALID_HANDLE_VALUE;
1025 pFile = FileHandle_New(fp);
1027 return INVALID_HANDLE_VALUE;
1029 return (HANDLE)pFile;
1032 BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
1037 BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
1042 BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
1043 LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
1045 #if defined(ANDROID)
1046 #define STATVFS statfs
1048 #define STATVFS statvfs
1051 struct STATVFS svfst = { 0 };
1052 STATVFS(lpRootPathName, &svfst);
1053 *lpSectorsPerCluster = (UINT32)MIN(svfst.f_frsize, UINT32_MAX);
1054 *lpBytesPerSector = 1;
1055 *lpNumberOfFreeClusters = (UINT32)MIN(svfst.f_bavail, UINT32_MAX);
1056 *lpTotalNumberOfClusters = (UINT32)MIN(svfst.f_blocks, UINT32_MAX);
1060 BOOL GetDiskFreeSpaceW(LPCWSTR lpwRootPathName, LPDWORD lpSectorsPerCluster,
1061 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
1062 LPDWORD lpTotalNumberOfClusters)
1064 LPSTR lpRootPathName = NULL;
1066 if (!lpwRootPathName)
1069 lpRootPathName = ConvertWCharToUtf8Alloc(lpwRootPathName, NULL);
1070 if (!lpRootPathName)
1072 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1075 ret = GetDiskFreeSpaceA(lpRootPathName, lpSectorsPerCluster, lpBytesPerSector,
1076 lpNumberOfFreeClusters, lpTotalNumberOfClusters);
1077 free(lpRootPathName);
1089 BOOL ValidFileNameComponent(LPCWSTR lpFileName)
1095 if ((lpFileName[0] != L
'\0' && (lpFileName[0] == L
'C' || lpFileName[0] == L
'c')) &&
1096 (lpFileName[1] != L
'\0' && (lpFileName[1] == L
'O' || lpFileName[1] == L
'o')) &&
1097 (lpFileName[2] != L
'\0' && (lpFileName[2] == L
'N' || lpFileName[2] == L
'n')) &&
1098 (lpFileName[3] == L
'\0'))
1104 if ((lpFileName[0] != L
'\0' && (lpFileName[0] == L
'P' || lpFileName[0] == L
'p')) &&
1105 (lpFileName[1] != L
'\0' && (lpFileName[1] == L
'R' || lpFileName[1] == L
'r')) &&
1106 (lpFileName[2] != L
'\0' && (lpFileName[2] == L
'N' || lpFileName[2] == L
'n')) &&
1107 (lpFileName[3] == L
'\0'))
1113 if ((lpFileName[0] != L
'\0' && (lpFileName[0] == L
'A' || lpFileName[0] == L
'a')) &&
1114 (lpFileName[1] != L
'\0' && (lpFileName[1] == L
'U' || lpFileName[1] == L
'u')) &&
1115 (lpFileName[2] != L
'\0' && (lpFileName[2] == L
'X' || lpFileName[2] == L
'x')) &&
1116 (lpFileName[3] == L
'\0'))
1122 if ((lpFileName[0] != L
'\0' && (lpFileName[0] == L
'N' || lpFileName[0] == L
'n')) &&
1123 (lpFileName[1] != L
'\0' && (lpFileName[1] == L
'U' || lpFileName[1] == L
'u')) &&
1124 (lpFileName[2] != L
'\0' && (lpFileName[2] == L
'L' || lpFileName[2] == L
'l')) &&
1125 (lpFileName[3] == L
'\0'))
1131 if ((lpFileName[0] != L
'\0' && (lpFileName[0] == L
'L' || lpFileName[0] == L
'l')) &&
1132 (lpFileName[1] != L
'\0' && (lpFileName[1] == L
'P' || lpFileName[1] == L
'p')) &&
1133 (lpFileName[2] != L
'\0' && (lpFileName[2] == L
'T' || lpFileName[2] == L
't')) &&
1134 (lpFileName[3] != L
'\0' && (L
'0' <= lpFileName[3] && lpFileName[3] <= L
'9')) &&
1135 (lpFileName[4] == L
'\0'))
1141 if ((lpFileName[0] != L
'\0' && (lpFileName[0] == L
'C' || lpFileName[0] == L
'c')) &&
1142 (lpFileName[1] != L
'\0' && (lpFileName[1] == L
'O' || lpFileName[1] == L
'o')) &&
1143 (lpFileName[2] != L
'\0' && (lpFileName[2] == L
'M' || lpFileName[2] == L
'm')) &&
1144 (lpFileName[3] != L
'\0' && (L
'0' <= lpFileName[3] && lpFileName[3] <= L
'9')) &&
1145 (lpFileName[4] == L
'\0'))
1151 for (LPCWSTR c = lpFileName; *c; c++)
1153 if ((*c == L
'<') || (*c == L
'>') || (*c == L
':') || (*c == L
'"') || (*c == L
'/') ||
1154 (*c == L
'\\') || (*c == L
'|') || (*c == L
'?') || (*c == L
'*'))
1165 HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
1166 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
1167 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
1170 CREATEFILE2_EXTENDED_PARAMETERS params = { 0 };
1172 params.dwSize =
sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
1174 if (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
1175 params.dwFileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
1176 if (dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
1177 params.dwFileFlags |= FILE_FLAG_DELETE_ON_CLOSE;
1178 if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
1179 params.dwFileFlags |= FILE_FLAG_NO_BUFFERING;
1180 if (dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
1181 params.dwFileFlags |= FILE_FLAG_OPEN_NO_RECALL;
1182 if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
1183 params.dwFileFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
1184 if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REQUIRING_OPLOCK)
1185 params.dwFileFlags |= FILE_FLAG_OPEN_REQUIRING_OPLOCK;
1186 if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
1187 params.dwFileFlags |= FILE_FLAG_OVERLAPPED;
1188 if (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS)
1189 params.dwFileFlags |= FILE_FLAG_POSIX_SEMANTICS;
1190 if (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
1191 params.dwFileFlags |= FILE_FLAG_RANDOM_ACCESS;
1192 if (dwFlagsAndAttributes & FILE_FLAG_SESSION_AWARE)
1193 params.dwFileFlags |= FILE_FLAG_SESSION_AWARE;
1194 if (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
1195 params.dwFileFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
1196 if (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
1197 params.dwFileFlags |= FILE_FLAG_WRITE_THROUGH;
1199 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ARCHIVE)
1200 params.dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
1201 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_COMPRESSED)
1202 params.dwFileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
1203 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DEVICE)
1204 params.dwFileAttributes |= FILE_ATTRIBUTE_DEVICE;
1205 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY)
1206 params.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
1207 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ENCRYPTED)
1208 params.dwFileAttributes |= FILE_ATTRIBUTE_ENCRYPTED;
1209 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_HIDDEN)
1210 params.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
1211 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM)
1212 params.dwFileAttributes |= FILE_ATTRIBUTE_INTEGRITY_STREAM;
1213 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NORMAL)
1214 params.dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
1215 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
1216 params.dwFileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
1217 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA)
1218 params.dwFileAttributes |= FILE_ATTRIBUTE_NO_SCRUB_DATA;
1219 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_OFFLINE)
1220 params.dwFileAttributes |= FILE_ATTRIBUTE_OFFLINE;
1221 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY)
1222 params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
1223 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1224 params.dwFileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1225 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SPARSE_FILE)
1226 params.dwFileAttributes |= FILE_ATTRIBUTE_SPARSE_FILE;
1227 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SYSTEM)
1228 params.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
1229 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_TEMPORARY)
1230 params.dwFileAttributes |= FILE_ATTRIBUTE_TEMPORARY;
1231 if (dwFlagsAndAttributes & FILE_ATTRIBUTE_VIRTUAL)
1232 params.dwFileAttributes |= FILE_ATTRIBUTE_VIRTUAL;
1234 if (dwFlagsAndAttributes & SECURITY_ANONYMOUS)
1235 params.dwSecurityQosFlags |= SECURITY_ANONYMOUS;
1236 if (dwFlagsAndAttributes & SECURITY_CONTEXT_TRACKING)
1237 params.dwSecurityQosFlags |= SECURITY_CONTEXT_TRACKING;
1238 if (dwFlagsAndAttributes & SECURITY_DELEGATION)
1239 params.dwSecurityQosFlags |= SECURITY_DELEGATION;
1240 if (dwFlagsAndAttributes & SECURITY_EFFECTIVE_ONLY)
1241 params.dwSecurityQosFlags |= SECURITY_EFFECTIVE_ONLY;
1242 if (dwFlagsAndAttributes & SECURITY_IDENTIFICATION)
1243 params.dwSecurityQosFlags |= SECURITY_IDENTIFICATION;
1244 if (dwFlagsAndAttributes & SECURITY_IMPERSONATION)
1245 params.dwSecurityQosFlags |= SECURITY_IMPERSONATION;
1247 params.lpSecurityAttributes = lpSecurityAttributes;
1248 params.hTemplateFile = hTemplateFile;
1250 hFile = CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, ¶ms);
1255 HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
1256 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
1257 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
1263 WCHAR* lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
1268 hFile = CreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
1269 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
1276 DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
1279 LARGE_INTEGER fileSize = { 0, 0 };
1281 if (!lpFileSizeHigh)
1282 return INVALID_FILE_SIZE;
1284 status = GetFileSizeEx(hFile, &fileSize);
1287 return INVALID_FILE_SIZE;
1289 *lpFileSizeHigh = fileSize.HighPart;
1291 return fileSize.LowPart;
1294 DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
1298 LARGE_INTEGER liDistanceToMove = { 0, 0 };
1299 LARGE_INTEGER liNewFilePointer = { 0, 0 };
1301 liDistanceToMove.LowPart = lDistanceToMove;
1303 status = SetFilePointerEx(hFile, liDistanceToMove, &liNewFilePointer, dwMoveMethod);
1306 return INVALID_SET_FILE_POINTER;
1308 if (lpDistanceToMoveHigh)
1309 *lpDistanceToMoveHigh = liNewFilePointer.HighPart;
1311 return liNewFilePointer.LowPart;
1316 return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch,
1322 return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch,
1326 DWORD GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
1329 WCHAR* lpFileNameW = NULL;
1330 WCHAR* lpBufferW = NULL;
1331 WCHAR* lpFilePartW = NULL;
1332 DWORD nBufferLengthW = nBufferLength *
sizeof(WCHAR);
1334 if (!lpFileName || (nBufferLength < 1))
1337 lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
1341 lpBufferW = (WCHAR*)malloc(nBufferLengthW);
1346 dwStatus = GetFullPathNameW(lpFileNameW, nBufferLengthW, lpBufferW, &lpFilePartW);
1348 (void)ConvertWCharNToUtf8(lpBufferW, nBufferLengthW /
sizeof(WCHAR), lpBuffer, nBufferLength);
1351 lpFilePart = lpBuffer + (lpFilePartW - lpBufferW);
1356 return dwStatus * 2;
1359 BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
1360 LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
1363 ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
1364 ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
1365 ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
1367 status = GetDiskFreeSpaceExA(lpRootPathName, &FreeBytesAvailableToCaller, &TotalNumberOfBytes,
1368 &TotalNumberOfFreeBytes);
1373 *lpBytesPerSector = 1;
1374 *lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
1375 *lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
1376 *lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
1381 BOOL GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
1382 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
1383 LPDWORD lpTotalNumberOfClusters)
1386 ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
1387 ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
1388 ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
1390 status = GetDiskFreeSpaceExW(lpRootPathName, &FreeBytesAvailableToCaller, &TotalNumberOfBytes,
1391 &TotalNumberOfFreeBytes);
1396 *lpBytesPerSector = 1;
1397 *lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
1398 *lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
1399 *lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
1404 DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
1406 SetLastError(ERROR_INVALID_FUNCTION);
1410 DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer)
1412 SetLastError(ERROR_INVALID_FUNCTION);
1416 BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
1434 HANDLE GetFileHandleForFileDescriptor(
int fd)
1437 return (HANDLE)_get_osfhandle(fd);
1439 WINPR_FILE* pFile = NULL;
1444 if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
1445 return INVALID_HANDLE_VALUE;
1447 flags = fcntl(fd, F_GETFL);
1449 return INVALID_HANDLE_VALUE;
1451 if (flags & O_WRONLY)
1452 fp = fdopen(fd,
"wb");
1454 fp = fdopen(fd,
"rb");
1457 return INVALID_HANDLE_VALUE;
1459 (void)setvbuf(fp, NULL, _IONBF, 0);
1461 pFile = FileHandle_New(fp);
1463 return INVALID_HANDLE_VALUE;
1465 return (HANDLE)pFile;
1469 FILE* winpr_fopen(
const char* path,
const char* mode)
1472 return fopen(path, mode);
1474 LPWSTR lpPathW = NULL;
1475 LPWSTR lpModeW = NULL;
1476 FILE* result = NULL;
1481 lpPathW = ConvertUtf8ToWCharAlloc(path, NULL);
1485 lpModeW = ConvertUtf8ToWCharAlloc(mode, NULL);
1489 result = _wfopen(lpPathW, lpModeW);