22 #include <winpr/config.h>
24 #include <winpr/crt.h>
25 #include <winpr/string.h>
26 #include <winpr/path.h>
27 #include <winpr/file.h>
29 #ifdef WINPR_HAVE_UNISTD_H
33 #ifdef WINPR_HAVE_FCNTL_H
38 #define TAG WINPR_TAG("file")
44 #include <winpr/assert.h>
52 #include <sys/socket.h>
54 #ifdef WINPR_HAVE_AIO_H
55 #undef WINPR_HAVE_AIO_H
58 #ifdef WINPR_HAVE_AIO_H
65 #include <sys/statvfs.h>
68 #include "../handle/handle.h"
70 #include "../pipe/pipe.h"
177 static wArrayList* HandleCreators;
179 static pthread_once_t HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
181 #include "../comm/comm.h"
182 #include "namedPipeClient.h"
184 static void HandleCreatorsInit(
void)
186 WINPR_ASSERT(HandleCreators == NULL);
187 HandleCreators = ArrayList_New(TRUE);
195 ArrayList_Append(HandleCreators, GetNamedPipeClientHandleCreator());
198 ArrayList_Append(HandleCreators, serial);
199 ArrayList_Append(HandleCreators, GetFileHandleCreator());
202 #ifdef WINPR_HAVE_AIO_H
204 static BOOL g_AioSignalHandlerInstalled = FALSE;
206 void AioSignalHandler(
int signum, siginfo_t* siginfo,
void* arg)
208 WLog_INFO(
"%d", signum);
211 int InstallAioSignalHandler()
213 if (!g_AioSignalHandlerInstalled)
215 struct sigaction action;
216 sigemptyset(&action.sa_mask);
217 sigaddset(&action.sa_mask, SIGIO);
218 action.sa_flags = SA_SIGINFO;
219 action.sa_sigaction = (
void*)&AioSignalHandler;
220 sigaction(SIGIO, &action, NULL);
221 g_AioSignalHandlerInstalled = TRUE;
229 HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
230 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
231 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
234 return INVALID_HANDLE_VALUE;
236 if (pthread_once(&HandleCreatorsInitialized, HandleCreatorsInit) != 0)
238 SetLastError(ERROR_DLL_INIT_FAILED);
239 return INVALID_HANDLE_VALUE;
242 if (HandleCreators == NULL)
244 SetLastError(ERROR_DLL_INIT_FAILED);
245 return INVALID_HANDLE_VALUE;
248 ArrayList_Lock(HandleCreators);
250 for (
size_t i = 0; i <= ArrayList_Count(HandleCreators); i++)
252 const HANDLE_CREATOR* creator = ArrayList_GetItem(HandleCreators, i);
254 if (creator && creator->IsHandled(lpFileName))
257 creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
258 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
259 ArrayList_Unlock(HandleCreators);
264 ArrayList_Unlock(HandleCreators);
265 return INVALID_HANDLE_VALUE;
268 HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
269 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
270 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
275 char* lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL);
279 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
283 hdl = CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
284 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
290 BOOL DeleteFileA(LPCSTR lpFileName)
293 status = unlink(lpFileName);
294 return (status != -1) ? TRUE : FALSE;
297 BOOL DeleteFileW(LPCWSTR lpFileName)
301 LPSTR lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL);
307 rc = DeleteFileA(lpFileNameA);
313 BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
319 if (hFile == INVALID_HANDLE_VALUE)
327 if (!lpNumberOfBytesRead && !lpOverlapped)
330 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
335 if (handle->ops->ReadFile)
336 return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
339 WLog_ERR(TAG,
"ReadFile operation not implemented");
343 BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
344 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
349 if (hFile == INVALID_HANDLE_VALUE)
352 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
357 if (handle->ops->ReadFileEx)
358 return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, lpOverlapped,
359 lpCompletionRoutine);
361 WLog_ERR(TAG,
"ReadFileEx operation not implemented");
365 BOOL ReadFileScatter(HANDLE hFile,
FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
371 if (hFile == INVALID_HANDLE_VALUE)
374 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
379 if (handle->ops->ReadFileScatter)
380 return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, lpReserved,
383 WLog_ERR(TAG,
"ReadFileScatter operation not implemented");
387 BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
388 LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
393 if (hFile == INVALID_HANDLE_VALUE)
396 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
401 if (handle->ops->WriteFile)
402 return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
403 lpNumberOfBytesWritten, lpOverlapped);
405 WLog_ERR(TAG,
"WriteFile operation not implemented");
409 BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
410 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
415 if (hFile == INVALID_HANDLE_VALUE)
418 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
423 if (handle->ops->WriteFileEx)
424 return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, lpOverlapped,
425 lpCompletionRoutine);
427 WLog_ERR(TAG,
"WriteFileEx operation not implemented");
432 DWORD nNumberOfBytesToWrite, LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped)
437 if (hFile == INVALID_HANDLE_VALUE)
440 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
445 if (handle->ops->WriteFileGather)
446 return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
447 lpReserved, lpOverlapped);
449 WLog_ERR(TAG,
"WriteFileGather operation not implemented");
453 BOOL FlushFileBuffers(HANDLE hFile)
458 if (hFile == INVALID_HANDLE_VALUE)
461 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
466 if (handle->ops->FlushFileBuffers)
467 return handle->ops->FlushFileBuffers(handle);
469 WLog_ERR(TAG,
"FlushFileBuffers operation not implemented");
473 BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
474 LPVOID lpFileInformation)
483 if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
487 fd->dwFileAttributes = findFileData.dwFileAttributes;
488 fd->ftCreationTime = findFileData.ftCreationTime;
489 fd->ftLastAccessTime = findFileData.ftLastAccessTime;
490 fd->ftLastWriteTime = findFileData.ftLastWriteTime;
491 fd->nFileSizeHigh = findFileData.nFileSizeHigh;
492 fd->nFileSizeLow = findFileData.nFileSizeLow;
496 BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
497 LPVOID lpFileInformation)
502 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
506 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
510 ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
515 DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
520 if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
521 return INVALID_FILE_ATTRIBUTES;
524 return findFileData.dwFileAttributes;
527 DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
532 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
535 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
539 ret = GetFileAttributesA(lpCFileName);
549 if (hFile == INVALID_HANDLE_VALUE)
552 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
557 if (handle->ops->GetFileInformationByHandle)
558 return handle->ops->GetFileInformationByHandle(handle, lpFileInformation);
560 WLog_ERR(TAG,
"GetFileInformationByHandle operation not implemented");
564 static char* append(
char* buffer,
size_t size,
const char* append)
566 winpr_str_append(append, buffer, size,
"|");
570 static const char* flagsToStr(
char* buffer,
size_t size, DWORD flags)
572 char strflags[32] = { 0 };
573 if (flags & FILE_ATTRIBUTE_READONLY)
574 append(buffer, size,
"FILE_ATTRIBUTE_READONLY");
575 if (flags & FILE_ATTRIBUTE_HIDDEN)
576 append(buffer, size,
"FILE_ATTRIBUTE_HIDDEN");
577 if (flags & FILE_ATTRIBUTE_SYSTEM)
578 append(buffer, size,
"FILE_ATTRIBUTE_SYSTEM");
579 if (flags & FILE_ATTRIBUTE_DIRECTORY)
580 append(buffer, size,
"FILE_ATTRIBUTE_DIRECTORY");
581 if (flags & FILE_ATTRIBUTE_ARCHIVE)
582 append(buffer, size,
"FILE_ATTRIBUTE_ARCHIVE");
583 if (flags & FILE_ATTRIBUTE_DEVICE)
584 append(buffer, size,
"FILE_ATTRIBUTE_DEVICE");
585 if (flags & FILE_ATTRIBUTE_NORMAL)
586 append(buffer, size,
"FILE_ATTRIBUTE_NORMAL");
587 if (flags & FILE_ATTRIBUTE_TEMPORARY)
588 append(buffer, size,
"FILE_ATTRIBUTE_TEMPORARY");
589 if (flags & FILE_ATTRIBUTE_SPARSE_FILE)
590 append(buffer, size,
"FILE_ATTRIBUTE_SPARSE_FILE");
591 if (flags & FILE_ATTRIBUTE_REPARSE_POINT)
592 append(buffer, size,
"FILE_ATTRIBUTE_REPARSE_POINT");
593 if (flags & FILE_ATTRIBUTE_COMPRESSED)
594 append(buffer, size,
"FILE_ATTRIBUTE_COMPRESSED");
595 if (flags & FILE_ATTRIBUTE_OFFLINE)
596 append(buffer, size,
"FILE_ATTRIBUTE_OFFLINE");
597 if (flags & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
598 append(buffer, size,
"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED");
599 if (flags & FILE_ATTRIBUTE_ENCRYPTED)
600 append(buffer, size,
"FILE_ATTRIBUTE_ENCRYPTED");
601 if (flags & FILE_ATTRIBUTE_VIRTUAL)
602 append(buffer, size,
"FILE_ATTRIBUTE_VIRTUAL");
604 (void)_snprintf(strflags,
sizeof(strflags),
" [0x%08" PRIx32
"]", flags);
605 winpr_str_append(strflags, buffer, size, NULL);
609 BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
612 #ifdef WINPR_HAVE_FCNTL_H
613 struct stat st = { 0 };
616 if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
618 char buffer[8192] = { 0 };
620 flagsToStr(buffer,
sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
621 WLog_WARN(TAG,
"Unsupported flags %s, ignoring!", flags);
624 fd = open(lpFileName, O_RDONLY);
628 if (fstat(fd, &st) != 0)
631 if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
633 st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
637 st.st_mode |= S_IWUSR;
640 if (fchmod(fd, st.st_mode) != 0)
650 BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
653 LPSTR lpCFileName = NULL;
658 if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
660 char buffer[8192] = { 0 };
662 flagsToStr(buffer,
sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
663 WLog_WARN(TAG,
"Unsupported flags %s, ignoring!", flags);
666 lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
669 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
673 ret = SetFileAttributesA(lpCFileName, dwFileAttributes);
678 BOOL SetEndOfFile(HANDLE hFile)
683 if (hFile == INVALID_HANDLE_VALUE)
686 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
691 if (handle->ops->SetEndOfFile)
692 return handle->ops->SetEndOfFile(handle);
694 WLog_ERR(TAG,
"SetEndOfFile operation not implemented");
698 DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
703 if (hFile == INVALID_HANDLE_VALUE)
706 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
711 if (handle->ops->GetFileSize)
712 return handle->ops->GetFileSize(handle, lpFileSizeHigh);
714 WLog_ERR(TAG,
"GetFileSize operation not implemented");
718 DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
724 if (hFile == INVALID_HANDLE_VALUE)
727 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
732 if (handle->ops->SetFilePointer)
733 return handle->ops->SetFilePointer(handle, lDistanceToMove, lpDistanceToMoveHigh,
736 WLog_ERR(TAG,
"SetFilePointer operation not implemented");
740 BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
746 if (hFile == INVALID_HANDLE_VALUE)
749 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
754 if (handle->ops->SetFilePointerEx)
755 return handle->ops->SetFilePointerEx(handle, liDistanceToMove, lpNewFilePointer,
758 WLog_ERR(TAG,
"SetFilePointerEx operation not implemented");
762 BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
763 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
768 if (hFile == INVALID_HANDLE_VALUE)
771 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
776 if (handle->ops->LockFile)
777 return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
778 nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
780 WLog_ERR(TAG,
"LockFile operation not implemented");
784 BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow,
785 DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped)
790 if (hFile == INVALID_HANDLE_VALUE)
793 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
798 if (handle->ops->LockFileEx)
799 return handle->ops->LockFileEx(handle, dwFlags, dwReserved, nNumberOfBytesToLockLow,
800 nNumberOfBytesToLockHigh, lpOverlapped);
802 WLog_ERR(TAG,
"LockFileEx operation not implemented");
806 BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
807 DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
812 if (hFile == INVALID_HANDLE_VALUE)
815 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
820 if (handle->ops->UnlockFile)
821 return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
822 nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
824 WLog_ERR(TAG,
"UnLockFile operation not implemented");
828 BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
829 DWORD nNumberOfBytesToUnlockHigh,
LPOVERLAPPED lpOverlapped)
834 if (hFile == INVALID_HANDLE_VALUE)
837 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
842 if (handle->ops->UnlockFileEx)
843 return handle->ops->UnlockFileEx(handle, dwReserved, nNumberOfBytesToUnlockLow,
844 nNumberOfBytesToUnlockHigh, lpOverlapped);
846 WLog_ERR(TAG,
"UnLockFileEx operation not implemented");
850 BOOL WINAPI SetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
851 const FILETIME* lpLastAccessTime,
const FILETIME* lpLastWriteTime)
856 if (hFile == INVALID_HANDLE_VALUE)
859 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
864 if (handle->ops->SetFileTime)
865 return handle->ops->SetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
867 WLog_ERR(TAG,
"operation not implemented");
879 static const char file_search_magic[] =
"file_srch_magic";
881 WINPR_ATTR_MALLOC(FindClose, 1)
882 static WIN32_FILE_SEARCH* file_search_new(const
char* name,
size_t namelen, const
char* pattern,
885 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)calloc(1,
sizeof(WIN32_FILE_SEARCH));
888 WINPR_ASSERT(
sizeof(file_search_magic) ==
sizeof(pFileSearch->magic));
889 memcpy(pFileSearch->magic, file_search_magic,
sizeof(pFileSearch->magic));
891 pFileSearch->lpPath = strndup(name, namelen);
892 pFileSearch->lpPattern = strndup(pattern, patternlen);
893 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
896 pFileSearch->pDir = opendir(pFileSearch->lpPath);
897 if (!pFileSearch->pDir)
903 struct stat fileStat = { 0 };
904 if (stat(name, &fileStat) == 0)
906 if (S_ISDIR(fileStat.st_mode))
908 pFileSearch->pDir = opendir(name);
909 if (pFileSearch->pDir)
911 free(pFileSearch->lpPath);
912 free(pFileSearch->lpPattern);
913 pFileSearch->lpPath = _strdup(name);
914 pFileSearch->lpPattern = _strdup(
"*");
915 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
917 closedir(pFileSearch->pDir);
918 pFileSearch->pDir = NULL;
924 if (!pFileSearch->pDir)
929 WINPR_PRAGMA_DIAG_PUSH
930 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
931 FindClose(pFileSearch);
932 WINPR_PRAGMA_DIAG_POP
936 static BOOL is_valid_file_search_handle(HANDLE handle)
938 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)handle;
941 if (pFileSearch == INVALID_HANDLE_VALUE)
943 if (strncmp(file_search_magic, pFileSearch->magic,
sizeof(file_search_magic)) != 0)
947 static BOOL FindDataFromStat(
const char* path,
const struct stat* fileStat,
951 char* lastSep = NULL;
952 lpFindFileData->dwFileAttributes = 0;
954 if (S_ISDIR(fileStat->st_mode))
955 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
957 if (lpFindFileData->dwFileAttributes == 0)
958 lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
960 lastSep = strrchr(path,
'/');
964 const char* name = lastSep + 1;
965 const size_t namelen = strlen(name);
967 if ((namelen > 1) && (name[0] ==
'.') && (name[1] !=
'.'))
968 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
971 if (!(fileStat->st_mode & S_IWUSR))
972 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
974 #ifdef _DARWIN_FEATURE_64_BIT_INODE
975 ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
977 ft = STAT_TIME_TO_FILETIME(fileStat->st_ctime);
979 lpFindFileData->ftCreationTime.dwHighDateTime = (ft) >> 32ULL;
980 lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
981 ft = STAT_TIME_TO_FILETIME(fileStat->st_mtime);
982 lpFindFileData->ftLastWriteTime.dwHighDateTime = (ft) >> 32ULL;
983 lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
984 ft = STAT_TIME_TO_FILETIME(fileStat->st_atime);
985 lpFindFileData->ftLastAccessTime.dwHighDateTime = (ft) >> 32ULL;
986 lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
987 lpFindFileData->nFileSizeHigh = ((UINT64)fileStat->st_size) >> 32ULL;
988 lpFindFileData->nFileSizeLow = fileStat->st_size & 0xFFFFFFFF;
994 if (!lpFindFileData || !lpFileName)
996 SetLastError(ERROR_BAD_ARGUMENTS);
997 return INVALID_HANDLE_VALUE;
1001 *lpFindFileData = empty;
1003 WIN32_FILE_SEARCH* pFileSearch = NULL;
1004 size_t patternlen = 0;
1005 const size_t flen = strlen(lpFileName);
1006 const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
1007 const char* ptr = strrchr(lpFileName, sep);
1010 patternlen = strlen(ptr + 1);
1011 if (patternlen == 0)
1014 pFileSearch = file_search_new(lpFileName, flen - patternlen, ptr + 1, patternlen);
1018 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1019 return INVALID_HANDLE_VALUE;
1022 if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData))
1023 return (HANDLE)pFileSearch;
1026 FindClose(pFileSearch);
1027 return INVALID_HANDLE_VALUE;
1033 if (!lpFindFileDataA || !lpFindFileDataW)
1036 lpFindFileDataW->dwFileAttributes = lpFindFileDataA->dwFileAttributes;
1037 lpFindFileDataW->ftCreationTime = lpFindFileDataA->ftCreationTime;
1038 lpFindFileDataW->ftLastAccessTime = lpFindFileDataA->ftLastAccessTime;
1039 lpFindFileDataW->ftLastWriteTime = lpFindFileDataA->ftLastWriteTime;
1040 lpFindFileDataW->nFileSizeHigh = lpFindFileDataA->nFileSizeHigh;
1041 lpFindFileDataW->nFileSizeLow = lpFindFileDataA->nFileSizeLow;
1042 lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0;
1043 lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1;
1045 if (ConvertUtf8NToWChar(lpFindFileDataA->cFileName, ARRAYSIZE(lpFindFileDataA->cFileName),
1046 lpFindFileDataW->cFileName, ARRAYSIZE(lpFindFileDataW->cFileName)) < 0)
1049 return ConvertUtf8NToWChar(lpFindFileDataA->cAlternateFileName,
1050 ARRAYSIZE(lpFindFileDataA->cAlternateFileName),
1051 lpFindFileDataW->cAlternateFileName,
1052 ARRAYSIZE(lpFindFileDataW->cAlternateFileName)) >= 0;
1057 LPSTR utfFileName = NULL;
1065 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1066 return INVALID_HANDLE_VALUE;
1069 utfFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
1072 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1074 return INVALID_HANDLE_VALUE;
1077 h = FindFirstFileA(utfFileName, fd);
1080 if (h != INVALID_HANDLE_VALUE)
1082 if (!ConvertFindDataAToW(fd, lpFindFileData))
1084 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1086 h = INVALID_HANDLE_VALUE;
1096 HANDLE FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData,
1097 FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)
1099 return INVALID_HANDLE_VALUE;
1102 HANDLE FindFirstFileExW(LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData,
1103 FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)
1105 return INVALID_HANDLE_VALUE;
1110 if (!lpFindFileData)
1114 *lpFindFileData = empty;
1116 if (!is_valid_file_search_handle(hFindFile))
1119 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1120 struct dirent* pDirent = NULL;
1121 while ((pDirent = readdir(pFileSearch->pDir)) != NULL)
1123 if (FilePatternMatchA(pDirent->d_name, pFileSearch->lpPattern))
1125 BOOL success = FALSE;
1127 strncpy(lpFindFileData->cFileName, pDirent->d_name, MAX_PATH);
1128 const size_t namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
1129 size_t pathlen = strlen(pFileSearch->lpPath);
1130 char* fullpath = (
char*)malloc(pathlen + namelen + 2);
1132 if (fullpath == NULL)
1134 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1138 memcpy(fullpath, pFileSearch->lpPath, pathlen);
1141 if (fullpath[pathlen - 1] !=
'/')
1142 fullpath[pathlen++] =
'/';
1143 memcpy(fullpath + pathlen, pDirent->d_name, namelen);
1144 fullpath[pathlen + namelen] = 0;
1146 struct stat fileStat = { 0 };
1147 if (stat(fullpath, &fileStat) != 0)
1150 SetLastError(map_posix_err(errno));
1156 if (S_ISFIFO(fileStat.st_mode))
1162 success = FindDataFromStat(fullpath, &fileStat, lpFindFileData);
1168 SetLastError(ERROR_NO_MORE_FILES);
1178 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1182 if (FindNextFileA(hFindFile, fd))
1184 if (!ConvertFindDataAToW(fd, lpFindFileData))
1186 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1199 BOOL FindClose(HANDLE hFindFile)
1201 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1208 #ifndef __clang_analyzer__
1209 if (!is_valid_file_search_handle(hFindFile))
1213 free(pFileSearch->lpPath);
1214 free(pFileSearch->lpPattern);
1216 if (pFileSearch->pDir)
1217 closedir(pFileSearch->pDir);
1223 BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1225 if (!mkdir(lpPathName, S_IRUSR | S_IWUSR | S_IXUSR))
1231 BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1235 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1240 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1244 ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
1250 BOOL RemoveDirectoryA(LPCSTR lpPathName)
1252 int ret = rmdir(lpPathName);
1255 SetLastError(map_posix_err(errno));
1257 SetLastError(STATUS_SUCCESS);
1262 BOOL RemoveDirectoryW(LPCWSTR lpPathName)
1266 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1271 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1275 ret = RemoveDirectoryA(utfPathName);
1281 BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
1285 ret = stat(lpNewFileName, &st);
1287 if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
1291 SetLastError(ERROR_ALREADY_EXISTS);
1297 if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
1299 SetLastError(ERROR_ACCESS_DENIED);
1304 ret = rename(lpExistingFileName, lpNewFileName);
1307 SetLastError(map_posix_err(errno));
1312 BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
1314 if (!lpExistingFileName || !lpNewFileName)
1317 LPSTR lpCExistingFileName = ConvertWCharToUtf8Alloc(lpExistingFileName, NULL);
1318 LPSTR lpCNewFileName = ConvertWCharToUtf8Alloc(lpNewFileName, NULL);
1321 if (!lpCExistingFileName || !lpCNewFileName)
1323 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1327 ret = MoveFileExA(lpCExistingFileName, lpCNewFileName, dwFlags);
1329 free(lpCNewFileName);
1330 free(lpCExistingFileName);
1334 BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
1336 return MoveFileExA(lpExistingFileName, lpNewFileName, 0);
1339 BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
1341 return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
1348 int UnixChangeFileMode(
const char* filename,
int flags)
1354 fl |= (flags & 0x4000) ? S_ISUID : 0;
1355 fl |= (flags & 0x2000) ? S_ISGID : 0;
1356 fl |= (flags & 0x1000) ? S_ISVTX : 0;
1357 fl |= (flags & 0x0400) ? S_IRUSR : 0;
1358 fl |= (flags & 0x0200) ? S_IWUSR : 0;
1359 fl |= (flags & 0x0100) ? S_IXUSR : 0;
1360 fl |= (flags & 0x0040) ? S_IRGRP : 0;
1361 fl |= (flags & 0x0020) ? S_IWGRP : 0;
1362 fl |= (flags & 0x0010) ? S_IXGRP : 0;
1363 fl |= (flags & 0x0004) ? S_IROTH : 0;
1364 fl |= (flags & 0x0002) ? S_IWOTH : 0;
1365 fl |= (flags & 0x0001) ? S_IXOTH : 0;
1366 return chmod(filename, fl);
1369 WCHAR* wfl = ConvertUtf8ToWCharAlloc(filename, NULL);
1375 if (flags & ~(_S_IREAD | _S_IWRITE))
1376 WLog_WARN(TAG,
"Unsupported file mode %d for _wchmod", flags);
1378 rc = _wchmod(wfl, flags);