22#include <winpr/config.h>
25#include <winpr/wlog.h>
26#include <winpr/string.h>
27#include <winpr/path.h>
28#include <winpr/file.h>
30#ifdef WINPR_HAVE_UNISTD_H
34#ifdef WINPR_HAVE_FCNTL_H
39#define TAG WINPR_TAG("file")
45#include <winpr/assert.h>
53#include <sys/socket.h>
55#ifdef WINPR_HAVE_AIO_H
56#undef WINPR_HAVE_AIO_H
59#ifdef WINPR_HAVE_AIO_H
66#include <sys/statvfs.h>
69#include "../handle/handle.h"
71#include "../pipe/pipe.h"
178static wArrayList* HandleCreators;
180static pthread_once_t HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
182#include "../comm/comm.h"
183#include "namedPipeClient.h"
185static DWORD FileAttributesFromStat(
const char* path,
const struct stat* fileStat);
186static BOOL FindDataFromStat(
const char* path,
const struct stat* fileStat,
189static void HandleCreatorsInit(
void)
191 WINPR_ASSERT(HandleCreators == NULL);
192 HandleCreators = ArrayList_New(TRUE);
200 ArrayList_Append(HandleCreators, GetNamedPipeClientHandleCreator());
203 ArrayList_Append(HandleCreators, serial);
204 ArrayList_Append(HandleCreators, GetFileHandleCreator());
207#ifdef WINPR_HAVE_AIO_H
209static BOOL g_AioSignalHandlerInstalled = FALSE;
211void AioSignalHandler(
int signum, siginfo_t* siginfo,
void* arg)
213 WLog_INFO(
"%d", signum);
216int InstallAioSignalHandler()
218 if (!g_AioSignalHandlerInstalled)
220 struct sigaction action;
221 sigemptyset(&action.sa_mask);
222 sigaddset(&action.sa_mask, SIGIO);
223 action.sa_flags = SA_SIGINFO;
224 action.sa_sigaction = (
void*)&AioSignalHandler;
225 sigaction(SIGIO, &action, NULL);
226 g_AioSignalHandlerInstalled = TRUE;
234HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
235 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
236 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
238 return winpr_CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
239 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
242HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
243 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
244 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
247 return INVALID_HANDLE_VALUE;
249 if (pthread_once(&HandleCreatorsInitialized, HandleCreatorsInit) != 0)
251 SetLastError(ERROR_DLL_INIT_FAILED);
252 return INVALID_HANDLE_VALUE;
255 if (HandleCreators == NULL)
257 SetLastError(ERROR_DLL_INIT_FAILED);
258 return INVALID_HANDLE_VALUE;
261 ArrayList_Lock(HandleCreators);
263 for (
size_t i = 0; i <= ArrayList_Count(HandleCreators); i++)
265 const HANDLE_CREATOR* creator = ArrayList_GetItem(HandleCreators, i);
267 if (creator && creator->IsHandled(lpFileName))
270 creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
271 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
272 ArrayList_Unlock(HandleCreators);
277 ArrayList_Unlock(HandleCreators);
278 return INVALID_HANDLE_VALUE;
281HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
282 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
283 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
288 char* lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL);
292 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
296 hdl = winpr_CreateFile(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
297 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
303BOOL DeleteFileA(LPCSTR lpFileName)
305 return winpr_DeleteFile(lpFileName);
308BOOL DeleteFileW(LPCWSTR lpFileName)
312 LPSTR lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL);
313 BOOL rc = winpr_DeleteFile(lpFileNameA);
318BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
324 if (hFile == INVALID_HANDLE_VALUE)
332 if (!lpNumberOfBytesRead && !lpOverlapped)
335 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
340 if (handle->ops->ReadFile)
341 return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
344 WLog_ERR(TAG,
"ReadFile operation not implemented");
348BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
349 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
354 if (hFile == INVALID_HANDLE_VALUE)
357 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
362 if (handle->ops->ReadFileEx)
363 return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, lpOverlapped,
364 lpCompletionRoutine);
366 WLog_ERR(TAG,
"ReadFileEx operation not implemented");
370BOOL ReadFileScatter(HANDLE hFile,
FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
376 if (hFile == INVALID_HANDLE_VALUE)
379 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
384 if (handle->ops->ReadFileScatter)
385 return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, lpReserved,
388 WLog_ERR(TAG,
"ReadFileScatter operation not implemented");
392BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
393 LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
398 if (hFile == INVALID_HANDLE_VALUE)
401 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
406 if (handle->ops->WriteFile)
407 return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
408 lpNumberOfBytesWritten, lpOverlapped);
410 WLog_ERR(TAG,
"WriteFile operation not implemented");
414BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
415 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
420 if (hFile == INVALID_HANDLE_VALUE)
423 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
428 if (handle->ops->WriteFileEx)
429 return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, lpOverlapped,
430 lpCompletionRoutine);
432 WLog_ERR(TAG,
"WriteFileEx operation not implemented");
437 DWORD nNumberOfBytesToWrite, LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped)
442 if (hFile == INVALID_HANDLE_VALUE)
445 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
450 if (handle->ops->WriteFileGather)
451 return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
452 lpReserved, lpOverlapped);
454 WLog_ERR(TAG,
"WriteFileGather operation not implemented");
458BOOL FlushFileBuffers(HANDLE hFile)
463 if (hFile == INVALID_HANDLE_VALUE)
466 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
471 if (handle->ops->FlushFileBuffers)
472 return handle->ops->FlushFileBuffers(handle);
474 WLog_ERR(TAG,
"FlushFileBuffers operation not implemented");
478BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName,
479 WINPR_ATTR_UNUSED GET_FILEEX_INFO_LEVELS fInfoLevelId,
480 LPVOID lpFileInformation)
486 struct stat fileStat = { 0 };
487 if (stat(lpFileName, &fileStat) != 0)
491 if (!FindDataFromStat(lpFileName, &fileStat, &findFileData))
494 fd->dwFileAttributes = findFileData.dwFileAttributes;
495 fd->ftCreationTime = findFileData.ftCreationTime;
496 fd->ftLastAccessTime = findFileData.ftLastAccessTime;
497 fd->ftLastWriteTime = findFileData.ftLastWriteTime;
498 fd->nFileSizeHigh = findFileData.nFileSizeHigh;
499 fd->nFileSizeLow = findFileData.nFileSizeLow;
503BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
504 LPVOID lpFileInformation)
509 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
513 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
517 ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
522DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
524 struct stat fileStat = { 0 };
525 if (stat(lpFileName, &fileStat) != 0)
526 return INVALID_FILE_ATTRIBUTES;
528 return FileAttributesFromStat(lpFileName, &fileStat);
531DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
536 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
539 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
543 ret = GetFileAttributesA(lpCFileName);
553 if (hFile == INVALID_HANDLE_VALUE)
556 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
561 if (handle->ops->GetFileInformationByHandle)
562 return handle->ops->GetFileInformationByHandle(handle, lpFileInformation);
564 WLog_ERR(TAG,
"GetFileInformationByHandle operation not implemented");
568static char* append(
char* buffer,
size_t size,
const char* append)
570 winpr_str_append(append, buffer, size,
"|");
574static const char* flagsToStr(
char* buffer,
size_t size, DWORD flags)
576 char strflags[32] = { 0 };
577 if (flags & FILE_ATTRIBUTE_READONLY)
578 append(buffer, size,
"FILE_ATTRIBUTE_READONLY");
579 if (flags & FILE_ATTRIBUTE_HIDDEN)
580 append(buffer, size,
"FILE_ATTRIBUTE_HIDDEN");
581 if (flags & FILE_ATTRIBUTE_SYSTEM)
582 append(buffer, size,
"FILE_ATTRIBUTE_SYSTEM");
583 if (flags & FILE_ATTRIBUTE_DIRECTORY)
584 append(buffer, size,
"FILE_ATTRIBUTE_DIRECTORY");
585 if (flags & FILE_ATTRIBUTE_ARCHIVE)
586 append(buffer, size,
"FILE_ATTRIBUTE_ARCHIVE");
587 if (flags & FILE_ATTRIBUTE_DEVICE)
588 append(buffer, size,
"FILE_ATTRIBUTE_DEVICE");
589 if (flags & FILE_ATTRIBUTE_NORMAL)
590 append(buffer, size,
"FILE_ATTRIBUTE_NORMAL");
591 if (flags & FILE_ATTRIBUTE_TEMPORARY)
592 append(buffer, size,
"FILE_ATTRIBUTE_TEMPORARY");
593 if (flags & FILE_ATTRIBUTE_SPARSE_FILE)
594 append(buffer, size,
"FILE_ATTRIBUTE_SPARSE_FILE");
595 if (flags & FILE_ATTRIBUTE_REPARSE_POINT)
596 append(buffer, size,
"FILE_ATTRIBUTE_REPARSE_POINT");
597 if (flags & FILE_ATTRIBUTE_COMPRESSED)
598 append(buffer, size,
"FILE_ATTRIBUTE_COMPRESSED");
599 if (flags & FILE_ATTRIBUTE_OFFLINE)
600 append(buffer, size,
"FILE_ATTRIBUTE_OFFLINE");
601 if (flags & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
602 append(buffer, size,
"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED");
603 if (flags & FILE_ATTRIBUTE_ENCRYPTED)
604 append(buffer, size,
"FILE_ATTRIBUTE_ENCRYPTED");
605 if (flags & FILE_ATTRIBUTE_VIRTUAL)
606 append(buffer, size,
"FILE_ATTRIBUTE_VIRTUAL");
608 (void)_snprintf(strflags,
sizeof(strflags),
" [0x%08" PRIx32
"]", flags);
609 winpr_str_append(strflags, buffer, size, NULL);
613BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
616#ifdef WINPR_HAVE_FCNTL_H
617 const uint32_t mask = ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_NORMAL);
618 if (dwFileAttributes & mask)
620 char buffer[8192] = { 0 };
621 const char* flags = flagsToStr(buffer,
sizeof(buffer), dwFileAttributes & mask);
622 WLog_WARN(TAG,
"Unsupported flags %s, ignoring!", flags);
625 int fd = open(lpFileName, O_RDONLY);
629 struct stat st = { 0 };
630 if (fstat(fd, &st) != 0)
633 if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
635 st.st_mode &= WINPR_ASSERTING_INT_CAST(mode_t, (mode_t)(~(S_IWUSR | S_IWGRP | S_IWOTH)));
639 st.st_mode |= S_IWUSR;
642 if (fchmod(fd, st.st_mode) != 0)
652BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
659 char* lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
662 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
666 ret = SetFileAttributesA(lpCFileName, dwFileAttributes);
671BOOL SetEndOfFile(HANDLE hFile)
676 if (hFile == INVALID_HANDLE_VALUE)
679 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
684 if (handle->ops->SetEndOfFile)
685 return handle->ops->SetEndOfFile(handle);
687 WLog_ERR(TAG,
"SetEndOfFile operation not implemented");
691DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
696 if (hFile == INVALID_HANDLE_VALUE)
699 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
704 if (handle->ops->GetFileSize)
705 return handle->ops->GetFileSize(handle, lpFileSizeHigh);
707 WLog_ERR(TAG,
"GetFileSize operation not implemented");
711DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
717 if (hFile == INVALID_HANDLE_VALUE)
720 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
725 if (handle->ops->SetFilePointer)
726 return handle->ops->SetFilePointer(handle, lDistanceToMove, lpDistanceToMoveHigh,
729 WLog_ERR(TAG,
"SetFilePointer operation not implemented");
733BOOL SetFilePointerEx(HANDLE hFile,
LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
739 if (hFile == INVALID_HANDLE_VALUE)
742 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
747 if (handle->ops->SetFilePointerEx)
748 return handle->ops->SetFilePointerEx(handle, liDistanceToMove, lpNewFilePointer,
751 WLog_ERR(TAG,
"SetFilePointerEx operation not implemented");
755BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
756 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
761 if (hFile == INVALID_HANDLE_VALUE)
764 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
769 if (handle->ops->LockFile)
770 return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
771 nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
773 WLog_ERR(TAG,
"LockFile operation not implemented");
777BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow,
778 DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped)
783 if (hFile == INVALID_HANDLE_VALUE)
786 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
791 if (handle->ops->LockFileEx)
792 return handle->ops->LockFileEx(handle, dwFlags, dwReserved, nNumberOfBytesToLockLow,
793 nNumberOfBytesToLockHigh, lpOverlapped);
795 WLog_ERR(TAG,
"LockFileEx operation not implemented");
799BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
800 DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
805 if (hFile == INVALID_HANDLE_VALUE)
808 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
813 if (handle->ops->UnlockFile)
814 return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
815 nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
817 WLog_ERR(TAG,
"UnLockFile operation not implemented");
821BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
822 DWORD nNumberOfBytesToUnlockHigh,
LPOVERLAPPED lpOverlapped)
827 if (hFile == INVALID_HANDLE_VALUE)
830 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
835 if (handle->ops->UnlockFileEx)
836 return handle->ops->UnlockFileEx(handle, dwReserved, nNumberOfBytesToUnlockLow,
837 nNumberOfBytesToUnlockHigh, lpOverlapped);
839 WLog_ERR(TAG,
"UnLockFileEx operation not implemented");
843BOOL WINAPI SetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
849 if (hFile == INVALID_HANDLE_VALUE)
852 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
857 if (handle->ops->SetFileTime)
858 return handle->ops->SetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
860 WLog_ERR(TAG,
"operation not implemented");
872static const char file_search_magic[] =
"file_srch_magic";
874WINPR_ATTR_MALLOC(FindClose, 1)
876static WIN32_FILE_SEARCH* file_search_new(const
char* name,
size_t namelen, const
char* pattern,
879 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)calloc(1,
sizeof(WIN32_FILE_SEARCH));
882 WINPR_ASSERT(
sizeof(file_search_magic) ==
sizeof(pFileSearch->magic));
883 memcpy(pFileSearch->magic, file_search_magic,
sizeof(pFileSearch->magic));
885 pFileSearch->lpPath = strndup(name, namelen);
886 pFileSearch->lpPattern = strndup(pattern, patternlen);
887 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
890 pFileSearch->pDir = opendir(pFileSearch->lpPath);
891 if (!pFileSearch->pDir)
897 struct stat fileStat = { 0 };
898 if (stat(name, &fileStat) == 0)
900 if (S_ISDIR(fileStat.st_mode))
902 pFileSearch->pDir = opendir(name);
903 if (pFileSearch->pDir)
905 free(pFileSearch->lpPath);
906 free(pFileSearch->lpPattern);
907 pFileSearch->lpPath = _strdup(name);
908 pFileSearch->lpPattern = _strdup(
"*");
909 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
911 closedir(pFileSearch->pDir);
912 pFileSearch->pDir = NULL;
918 if (!pFileSearch->pDir)
923 WINPR_PRAGMA_DIAG_PUSH
924 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
925 FindClose(pFileSearch);
926 WINPR_PRAGMA_DIAG_POP
930static BOOL is_valid_file_search_handle(HANDLE handle)
932 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)handle;
935 if (pFileSearch == INVALID_HANDLE_VALUE)
937 if (strncmp(file_search_magic, pFileSearch->magic,
sizeof(file_search_magic)) != 0)
942static DWORD FileAttributesFromStat(
const char* path,
const struct stat* fileStat)
944 char* lastSep = NULL;
945 DWORD dwFileAttributes = 0;
947 if (S_ISDIR(fileStat->st_mode))
948 dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
950 if (dwFileAttributes == 0)
951 dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
953 lastSep = strrchr(path,
'/');
956 const char* name = lastSep + 1;
957 const size_t namelen = strlen(name);
959 if ((namelen > 1) && (name[0] ==
'.') && (name[1] !=
'.'))
960 dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
963 if (!(fileStat->st_mode & S_IWUSR))
964 dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
966 return dwFileAttributes;
969static BOOL FindDataFromStat(
const char* path,
const struct stat* fileStat,
973 lpFindFileData->dwFileAttributes = FileAttributesFromStat(path, fileStat);
975#ifdef _DARWIN_FEATURE_64_BIT_INODE
976 ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
978 ft = STAT_TIME_TO_FILETIME(fileStat->st_ctime);
980 lpFindFileData->ftCreationTime.dwHighDateTime = (ft) >> 32ULL;
981 lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
982 ft = STAT_TIME_TO_FILETIME(fileStat->st_mtime);
983 lpFindFileData->ftLastWriteTime.dwHighDateTime = (ft) >> 32ULL;
984 lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
985 ft = STAT_TIME_TO_FILETIME(fileStat->st_atime);
986 lpFindFileData->ftLastAccessTime.dwHighDateTime = (ft) >> 32ULL;
987 lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
988 lpFindFileData->nFileSizeHigh = ((UINT64)fileStat->st_size) >> 32ULL;
989 lpFindFileData->nFileSizeLow = fileStat->st_size & 0xFFFFFFFF;
995 if (!lpFindFileData || !lpFileName)
997 SetLastError(ERROR_BAD_ARGUMENTS);
998 return INVALID_HANDLE_VALUE;
1002 *lpFindFileData = empty;
1004 WIN32_FILE_SEARCH* pFileSearch = NULL;
1005 size_t patternlen = 0;
1006 const size_t flen = strlen(lpFileName);
1007 const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
1008 const char* ptr = strrchr(lpFileName, sep);
1011 patternlen = strlen(ptr + 1);
1012 if (patternlen == 0)
1015 pFileSearch = file_search_new(lpFileName, flen - patternlen, ptr + 1, patternlen);
1019 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1020 return INVALID_HANDLE_VALUE;
1023 if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData))
1024 return (HANDLE)pFileSearch;
1027 FindClose(pFileSearch);
1028 return INVALID_HANDLE_VALUE;
1034 if (!lpFindFileDataA || !lpFindFileDataW)
1037 lpFindFileDataW->dwFileAttributes = lpFindFileDataA->dwFileAttributes;
1038 lpFindFileDataW->ftCreationTime = lpFindFileDataA->ftCreationTime;
1039 lpFindFileDataW->ftLastAccessTime = lpFindFileDataA->ftLastAccessTime;
1040 lpFindFileDataW->ftLastWriteTime = lpFindFileDataA->ftLastWriteTime;
1041 lpFindFileDataW->nFileSizeHigh = lpFindFileDataA->nFileSizeHigh;
1042 lpFindFileDataW->nFileSizeLow = lpFindFileDataA->nFileSizeLow;
1043 lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0;
1044 lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1;
1046 if (ConvertUtf8NToWChar(lpFindFileDataA->cFileName, ARRAYSIZE(lpFindFileDataA->cFileName),
1047 lpFindFileDataW->cFileName, ARRAYSIZE(lpFindFileDataW->cFileName)) < 0)
1050 return ConvertUtf8NToWChar(lpFindFileDataA->cAlternateFileName,
1051 ARRAYSIZE(lpFindFileDataA->cAlternateFileName),
1052 lpFindFileDataW->cAlternateFileName,
1053 ARRAYSIZE(lpFindFileDataW->cAlternateFileName)) >= 0;
1058 LPSTR utfFileName = NULL;
1061 return INVALID_HANDLE_VALUE;
1067 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1068 return INVALID_HANDLE_VALUE;
1071 utfFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
1074 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1076 return INVALID_HANDLE_VALUE;
1079 h = FindFirstFileA(utfFileName, fd);
1082 if (h != INVALID_HANDLE_VALUE)
1084 if (!ConvertFindDataAToW(fd, lpFindFileData))
1086 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1088 h = INVALID_HANDLE_VALUE;
1098HANDLE FindFirstFileExA(WINPR_ATTR_UNUSED LPCSTR lpFileName,
1099 WINPR_ATTR_UNUSED FINDEX_INFO_LEVELS fInfoLevelId,
1100 WINPR_ATTR_UNUSED LPVOID lpFindFileData,
1101 WINPR_ATTR_UNUSED FINDEX_SEARCH_OPS fSearchOp,
1102 WINPR_ATTR_UNUSED LPVOID lpSearchFilter,
1103 WINPR_ATTR_UNUSED DWORD dwAdditionalFlags)
1105 WLog_ERR(
"TODO",
"TODO: Implement");
1106 return INVALID_HANDLE_VALUE;
1109HANDLE FindFirstFileExW(WINPR_ATTR_UNUSED LPCWSTR lpFileName,
1110 WINPR_ATTR_UNUSED FINDEX_INFO_LEVELS fInfoLevelId,
1111 WINPR_ATTR_UNUSED LPVOID lpFindFileData,
1112 WINPR_ATTR_UNUSED FINDEX_SEARCH_OPS fSearchOp,
1113 WINPR_ATTR_UNUSED LPVOID lpSearchFilter,
1114 WINPR_ATTR_UNUSED DWORD dwAdditionalFlags)
1116 WLog_ERR(
"TODO",
"TODO: Implement");
1117 return INVALID_HANDLE_VALUE;
1122 if (!lpFindFileData)
1126 *lpFindFileData = empty;
1128 if (!is_valid_file_search_handle(hFindFile))
1131 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1132 struct dirent* pDirent = NULL;
1134 while ((pDirent = readdir(pFileSearch->pDir)) != NULL)
1136 if (FilePatternMatchA(pDirent->d_name, pFileSearch->lpPattern))
1138 BOOL success = FALSE;
1140 strncpy(lpFindFileData->cFileName, pDirent->d_name, MAX_PATH);
1141 const size_t namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
1142 size_t pathlen = strlen(pFileSearch->lpPath);
1143 char* fullpath = (
char*)malloc(pathlen + namelen + 2);
1145 if (fullpath == NULL)
1147 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1151 memcpy(fullpath, pFileSearch->lpPath, pathlen);
1154 if (fullpath[pathlen - 1] !=
'/')
1155 fullpath[pathlen++] =
'/';
1156 memcpy(fullpath + pathlen, pDirent->d_name, namelen);
1157 fullpath[pathlen + namelen] = 0;
1159 struct stat fileStat = { 0 };
1160 if (stat(fullpath, &fileStat) != 0)
1163 SetLastError(map_posix_err(errno));
1169 if (S_ISFIFO(fileStat.st_mode))
1175 success = FindDataFromStat(fullpath, &fileStat, lpFindFileData);
1181 SetLastError(ERROR_NO_MORE_FILES);
1191 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1195 if (FindNextFileA(hFindFile, fd))
1197 if (!ConvertFindDataAToW(fd, lpFindFileData))
1199 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1212BOOL FindClose(HANDLE hFindFile)
1214 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1221#ifndef __clang_analyzer__
1222 if (!is_valid_file_search_handle(hFindFile))
1226 free(pFileSearch->lpPath);
1227 free(pFileSearch->lpPattern);
1229 if (pFileSearch->pDir)
1230 closedir(pFileSearch->pDir);
1237BOOL CreateDirectoryA(LPCSTR lpPathName,
1238 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1240 if (!mkdir(lpPathName, S_IRUSR | S_IWUSR | S_IXUSR))
1246BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1250 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1255 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1259 ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
1265BOOL RemoveDirectoryA(LPCSTR lpPathName)
1267 return winpr_RemoveDirectory(lpPathName);
1270BOOL RemoveDirectoryW(LPCWSTR lpPathName)
1274 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1279 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1283 ret = winpr_RemoveDirectory(utfPathName);
1289BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
1291 return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags);
1294BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
1296 if (!lpExistingFileName || !lpNewFileName)
1299 LPSTR lpCExistingFileName = ConvertWCharToUtf8Alloc(lpExistingFileName, NULL);
1300 LPSTR lpCNewFileName = ConvertWCharToUtf8Alloc(lpNewFileName, NULL);
1303 if (!lpCExistingFileName || !lpCNewFileName)
1305 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1309 ret = winpr_MoveFileEx(lpCExistingFileName, lpCNewFileName, dwFlags);
1311 free(lpCNewFileName);
1312 free(lpCExistingFileName);
1316BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
1318 return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0);
1321BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
1323 return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
1330int UnixChangeFileMode(
const char* filename,
int flags)
1336 fl |= (flags & 0x4000) ? S_ISUID : 0;
1337 fl |= (flags & 0x2000) ? S_ISGID : 0;
1338 fl |= (flags & 0x1000) ? S_ISVTX : 0;
1339 fl |= (flags & 0x0400) ? S_IRUSR : 0;
1340 fl |= (flags & 0x0200) ? S_IWUSR : 0;
1341 fl |= (flags & 0x0100) ? S_IXUSR : 0;
1342 fl |= (flags & 0x0040) ? S_IRGRP : 0;
1343 fl |= (flags & 0x0020) ? S_IWGRP : 0;
1344 fl |= (flags & 0x0010) ? S_IXGRP : 0;
1345 fl |= (flags & 0x0004) ? S_IROTH : 0;
1346 fl |= (flags & 0x0002) ? S_IWOTH : 0;
1347 fl |= (flags & 0x0001) ? S_IXOTH : 0;
1348 return chmod(filename, fl);
1351 WCHAR* wfl = ConvertUtf8ToWCharAlloc(filename, NULL);
1357 if (flags & ~(_S_IREAD | _S_IWRITE))
1358 WLog_WARN(TAG,
"Unsupported file mode %d for _wchmod", flags);
1360 rc = _wchmod(wfl, flags);
1366#if defined(_WIN32) || defined(_UWP)
1367HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
1368 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
1369 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
1371 WCHAR* filename = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
1375 HANDLE hdl = CreateFileW(filename, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
1376 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);