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 void HandleCreatorsInit(
void)
187 WINPR_ASSERT(HandleCreators == NULL);
188 HandleCreators = ArrayList_New(TRUE);
196 ArrayList_Append(HandleCreators, GetNamedPipeClientHandleCreator());
199 ArrayList_Append(HandleCreators, serial);
200 ArrayList_Append(HandleCreators, GetFileHandleCreator());
203#ifdef WINPR_HAVE_AIO_H
205static BOOL g_AioSignalHandlerInstalled = FALSE;
207void AioSignalHandler(
int signum, siginfo_t* siginfo,
void* arg)
209 WLog_INFO(
"%d", signum);
212int InstallAioSignalHandler()
214 if (!g_AioSignalHandlerInstalled)
216 struct sigaction action;
217 sigemptyset(&action.sa_mask);
218 sigaddset(&action.sa_mask, SIGIO);
219 action.sa_flags = SA_SIGINFO;
220 action.sa_sigaction = (
void*)&AioSignalHandler;
221 sigaction(SIGIO, &action, NULL);
222 g_AioSignalHandlerInstalled = TRUE;
230HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
231 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
232 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
235 return INVALID_HANDLE_VALUE;
237 if (pthread_once(&HandleCreatorsInitialized, HandleCreatorsInit) != 0)
239 SetLastError(ERROR_DLL_INIT_FAILED);
240 return INVALID_HANDLE_VALUE;
243 if (HandleCreators == NULL)
245 SetLastError(ERROR_DLL_INIT_FAILED);
246 return INVALID_HANDLE_VALUE;
249 ArrayList_Lock(HandleCreators);
251 for (
size_t i = 0; i <= ArrayList_Count(HandleCreators); i++)
253 const HANDLE_CREATOR* creator = ArrayList_GetItem(HandleCreators, i);
255 if (creator && creator->IsHandled(lpFileName))
258 creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
259 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
260 ArrayList_Unlock(HandleCreators);
265 ArrayList_Unlock(HandleCreators);
266 return INVALID_HANDLE_VALUE;
269HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
270 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
271 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
276 char* lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL);
280 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
284 hdl = CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
285 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
291BOOL DeleteFileA(LPCSTR lpFileName)
294 status = unlink(lpFileName);
295 return (status != -1) ? TRUE : FALSE;
298BOOL DeleteFileW(LPCWSTR lpFileName)
302 LPSTR lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName, NULL);
308 rc = DeleteFileA(lpFileNameA);
314BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
320 if (hFile == INVALID_HANDLE_VALUE)
328 if (!lpNumberOfBytesRead && !lpOverlapped)
331 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
336 if (handle->ops->ReadFile)
337 return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
340 WLog_ERR(TAG,
"ReadFile operation not implemented");
344BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
345 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
350 if (hFile == INVALID_HANDLE_VALUE)
353 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
358 if (handle->ops->ReadFileEx)
359 return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, lpOverlapped,
360 lpCompletionRoutine);
362 WLog_ERR(TAG,
"ReadFileEx operation not implemented");
366BOOL ReadFileScatter(HANDLE hFile,
FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
372 if (hFile == INVALID_HANDLE_VALUE)
375 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
380 if (handle->ops->ReadFileScatter)
381 return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, lpReserved,
384 WLog_ERR(TAG,
"ReadFileScatter operation not implemented");
388BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
389 LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
394 if (hFile == INVALID_HANDLE_VALUE)
397 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
402 if (handle->ops->WriteFile)
403 return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
404 lpNumberOfBytesWritten, lpOverlapped);
406 WLog_ERR(TAG,
"WriteFile operation not implemented");
410BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
411 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
416 if (hFile == INVALID_HANDLE_VALUE)
419 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
424 if (handle->ops->WriteFileEx)
425 return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, lpOverlapped,
426 lpCompletionRoutine);
428 WLog_ERR(TAG,
"WriteFileEx operation not implemented");
433 DWORD nNumberOfBytesToWrite, LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped)
438 if (hFile == INVALID_HANDLE_VALUE)
441 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
446 if (handle->ops->WriteFileGather)
447 return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
448 lpReserved, lpOverlapped);
450 WLog_ERR(TAG,
"WriteFileGather operation not implemented");
454BOOL FlushFileBuffers(HANDLE hFile)
459 if (hFile == INVALID_HANDLE_VALUE)
462 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
467 if (handle->ops->FlushFileBuffers)
468 return handle->ops->FlushFileBuffers(handle);
470 WLog_ERR(TAG,
"FlushFileBuffers operation not implemented");
474BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName,
475 WINPR_ATTR_UNUSED GET_FILEEX_INFO_LEVELS fInfoLevelId,
476 LPVOID lpFileInformation)
484 HANDLE hFind = FindFirstFileA(lpFileName, &findFileData);
485 if (hFind == INVALID_HANDLE_VALUE)
489 fd->dwFileAttributes = findFileData.dwFileAttributes;
490 fd->ftCreationTime = findFileData.ftCreationTime;
491 fd->ftLastAccessTime = findFileData.ftLastAccessTime;
492 fd->ftLastWriteTime = findFileData.ftLastWriteTime;
493 fd->nFileSizeHigh = findFileData.nFileSizeHigh;
494 fd->nFileSizeLow = findFileData.nFileSizeLow;
498BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
499 LPVOID lpFileInformation)
504 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
508 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
512 ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
517DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
520 HANDLE hFind = FindFirstFileA(lpFileName, &findFileData);
522 if (hFind == INVALID_HANDLE_VALUE)
523 return INVALID_FILE_ATTRIBUTES;
526 return findFileData.dwFileAttributes;
529DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
534 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
537 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
541 ret = GetFileAttributesA(lpCFileName);
551 if (hFile == INVALID_HANDLE_VALUE)
554 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
559 if (handle->ops->GetFileInformationByHandle)
560 return handle->ops->GetFileInformationByHandle(handle, lpFileInformation);
562 WLog_ERR(TAG,
"GetFileInformationByHandle operation not implemented");
566static char* append(
char* buffer,
size_t size,
const char* append)
568 winpr_str_append(append, buffer, size,
"|");
572static const char* flagsToStr(
char* buffer,
size_t size, DWORD flags)
574 char strflags[32] = { 0 };
575 if (flags & FILE_ATTRIBUTE_READONLY)
576 append(buffer, size,
"FILE_ATTRIBUTE_READONLY");
577 if (flags & FILE_ATTRIBUTE_HIDDEN)
578 append(buffer, size,
"FILE_ATTRIBUTE_HIDDEN");
579 if (flags & FILE_ATTRIBUTE_SYSTEM)
580 append(buffer, size,
"FILE_ATTRIBUTE_SYSTEM");
581 if (flags & FILE_ATTRIBUTE_DIRECTORY)
582 append(buffer, size,
"FILE_ATTRIBUTE_DIRECTORY");
583 if (flags & FILE_ATTRIBUTE_ARCHIVE)
584 append(buffer, size,
"FILE_ATTRIBUTE_ARCHIVE");
585 if (flags & FILE_ATTRIBUTE_DEVICE)
586 append(buffer, size,
"FILE_ATTRIBUTE_DEVICE");
587 if (flags & FILE_ATTRIBUTE_NORMAL)
588 append(buffer, size,
"FILE_ATTRIBUTE_NORMAL");
589 if (flags & FILE_ATTRIBUTE_TEMPORARY)
590 append(buffer, size,
"FILE_ATTRIBUTE_TEMPORARY");
591 if (flags & FILE_ATTRIBUTE_SPARSE_FILE)
592 append(buffer, size,
"FILE_ATTRIBUTE_SPARSE_FILE");
593 if (flags & FILE_ATTRIBUTE_REPARSE_POINT)
594 append(buffer, size,
"FILE_ATTRIBUTE_REPARSE_POINT");
595 if (flags & FILE_ATTRIBUTE_COMPRESSED)
596 append(buffer, size,
"FILE_ATTRIBUTE_COMPRESSED");
597 if (flags & FILE_ATTRIBUTE_OFFLINE)
598 append(buffer, size,
"FILE_ATTRIBUTE_OFFLINE");
599 if (flags & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
600 append(buffer, size,
"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED");
601 if (flags & FILE_ATTRIBUTE_ENCRYPTED)
602 append(buffer, size,
"FILE_ATTRIBUTE_ENCRYPTED");
603 if (flags & FILE_ATTRIBUTE_VIRTUAL)
604 append(buffer, size,
"FILE_ATTRIBUTE_VIRTUAL");
606 (void)_snprintf(strflags,
sizeof(strflags),
" [0x%08" PRIx32
"]", flags);
607 winpr_str_append(strflags, buffer, size, NULL);
611BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
614#ifdef WINPR_HAVE_FCNTL_H
615 struct stat st = { 0 };
618 if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
620 char buffer[8192] = { 0 };
622 flagsToStr(buffer,
sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
623 WLog_WARN(TAG,
"Unsupported flags %s, ignoring!", flags);
626 fd = open(lpFileName, O_RDONLY);
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)
655 LPSTR lpCFileName = NULL;
660 if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
662 char buffer[8192] = { 0 };
664 flagsToStr(buffer,
sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
665 WLog_WARN(TAG,
"Unsupported flags %s, ignoring!", flags);
668 lpCFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
671 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
675 ret = SetFileAttributesA(lpCFileName, dwFileAttributes);
680BOOL SetEndOfFile(HANDLE hFile)
685 if (hFile == INVALID_HANDLE_VALUE)
688 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
693 if (handle->ops->SetEndOfFile)
694 return handle->ops->SetEndOfFile(handle);
696 WLog_ERR(TAG,
"SetEndOfFile operation not implemented");
700DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
705 if (hFile == INVALID_HANDLE_VALUE)
708 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
713 if (handle->ops->GetFileSize)
714 return handle->ops->GetFileSize(handle, lpFileSizeHigh);
716 WLog_ERR(TAG,
"GetFileSize operation not implemented");
720DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
726 if (hFile == INVALID_HANDLE_VALUE)
729 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
734 if (handle->ops->SetFilePointer)
735 return handle->ops->SetFilePointer(handle, lDistanceToMove, lpDistanceToMoveHigh,
738 WLog_ERR(TAG,
"SetFilePointer operation not implemented");
742BOOL SetFilePointerEx(HANDLE hFile,
LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
748 if (hFile == INVALID_HANDLE_VALUE)
751 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
756 if (handle->ops->SetFilePointerEx)
757 return handle->ops->SetFilePointerEx(handle, liDistanceToMove, lpNewFilePointer,
760 WLog_ERR(TAG,
"SetFilePointerEx operation not implemented");
764BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
765 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
770 if (hFile == INVALID_HANDLE_VALUE)
773 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
778 if (handle->ops->LockFile)
779 return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
780 nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
782 WLog_ERR(TAG,
"LockFile operation not implemented");
786BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow,
787 DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped)
792 if (hFile == INVALID_HANDLE_VALUE)
795 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
800 if (handle->ops->LockFileEx)
801 return handle->ops->LockFileEx(handle, dwFlags, dwReserved, nNumberOfBytesToLockLow,
802 nNumberOfBytesToLockHigh, lpOverlapped);
804 WLog_ERR(TAG,
"LockFileEx operation not implemented");
808BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
809 DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
814 if (hFile == INVALID_HANDLE_VALUE)
817 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
822 if (handle->ops->UnlockFile)
823 return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
824 nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
826 WLog_ERR(TAG,
"UnLockFile operation not implemented");
830BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
831 DWORD nNumberOfBytesToUnlockHigh,
LPOVERLAPPED lpOverlapped)
836 if (hFile == INVALID_HANDLE_VALUE)
839 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
844 if (handle->ops->UnlockFileEx)
845 return handle->ops->UnlockFileEx(handle, dwReserved, nNumberOfBytesToUnlockLow,
846 nNumberOfBytesToUnlockHigh, lpOverlapped);
848 WLog_ERR(TAG,
"UnLockFileEx operation not implemented");
852BOOL WINAPI SetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
858 if (hFile == INVALID_HANDLE_VALUE)
861 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
866 if (handle->ops->SetFileTime)
867 return handle->ops->SetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
869 WLog_ERR(TAG,
"operation not implemented");
881static const char file_search_magic[] =
"file_srch_magic";
883WINPR_ATTR_MALLOC(FindClose, 1)
884static WIN32_FILE_SEARCH* file_search_new(const
char* name,
size_t namelen, const
char* pattern,
887 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)calloc(1,
sizeof(WIN32_FILE_SEARCH));
890 WINPR_ASSERT(
sizeof(file_search_magic) ==
sizeof(pFileSearch->magic));
891 memcpy(pFileSearch->magic, file_search_magic,
sizeof(pFileSearch->magic));
893 pFileSearch->lpPath = strndup(name, namelen);
894 pFileSearch->lpPattern = strndup(pattern, patternlen);
895 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
898 pFileSearch->pDir = opendir(pFileSearch->lpPath);
899 if (!pFileSearch->pDir)
905 struct stat fileStat = { 0 };
906 if (stat(name, &fileStat) == 0)
908 if (S_ISDIR(fileStat.st_mode))
910 pFileSearch->pDir = opendir(name);
911 if (pFileSearch->pDir)
913 free(pFileSearch->lpPath);
914 free(pFileSearch->lpPattern);
915 pFileSearch->lpPath = _strdup(name);
916 pFileSearch->lpPattern = _strdup(
"*");
917 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
919 closedir(pFileSearch->pDir);
920 pFileSearch->pDir = NULL;
926 if (!pFileSearch->pDir)
931 WINPR_PRAGMA_DIAG_PUSH
932 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
933 FindClose(pFileSearch);
934 WINPR_PRAGMA_DIAG_POP
938static BOOL is_valid_file_search_handle(HANDLE handle)
940 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)handle;
943 if (pFileSearch == INVALID_HANDLE_VALUE)
945 if (strncmp(file_search_magic, pFileSearch->magic,
sizeof(file_search_magic)) != 0)
949static BOOL FindDataFromStat(
const char* path,
const struct stat* fileStat,
953 char* lastSep = NULL;
954 lpFindFileData->dwFileAttributes = 0;
956 if (S_ISDIR(fileStat->st_mode))
957 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
959 if (lpFindFileData->dwFileAttributes == 0)
960 lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
962 lastSep = strrchr(path,
'/');
966 const char* name = lastSep + 1;
967 const size_t namelen = strlen(name);
969 if ((namelen > 1) && (name[0] ==
'.') && (name[1] !=
'.'))
970 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
973 if (!(fileStat->st_mode & S_IWUSR))
974 lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
976#ifdef _DARWIN_FEATURE_64_BIT_INODE
977 ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
979 ft = STAT_TIME_TO_FILETIME(fileStat->st_ctime);
981 lpFindFileData->ftCreationTime.dwHighDateTime = (ft) >> 32ULL;
982 lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
983 ft = STAT_TIME_TO_FILETIME(fileStat->st_mtime);
984 lpFindFileData->ftLastWriteTime.dwHighDateTime = (ft) >> 32ULL;
985 lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
986 ft = STAT_TIME_TO_FILETIME(fileStat->st_atime);
987 lpFindFileData->ftLastAccessTime.dwHighDateTime = (ft) >> 32ULL;
988 lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
989 lpFindFileData->nFileSizeHigh = ((UINT64)fileStat->st_size) >> 32ULL;
990 lpFindFileData->nFileSizeLow = fileStat->st_size & 0xFFFFFFFF;
996 if (!lpFindFileData || !lpFileName)
998 SetLastError(ERROR_BAD_ARGUMENTS);
999 return INVALID_HANDLE_VALUE;
1003 *lpFindFileData = empty;
1005 WIN32_FILE_SEARCH* pFileSearch = NULL;
1006 size_t patternlen = 0;
1007 const size_t flen = strlen(lpFileName);
1008 const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
1009 const char* ptr = strrchr(lpFileName, sep);
1012 patternlen = strlen(ptr + 1);
1013 if (patternlen == 0)
1016 pFileSearch = file_search_new(lpFileName, flen - patternlen, ptr + 1, patternlen);
1020 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1021 return INVALID_HANDLE_VALUE;
1024 if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData))
1025 return (HANDLE)pFileSearch;
1028 FindClose(pFileSearch);
1029 return INVALID_HANDLE_VALUE;
1035 if (!lpFindFileDataA || !lpFindFileDataW)
1038 lpFindFileDataW->dwFileAttributes = lpFindFileDataA->dwFileAttributes;
1039 lpFindFileDataW->ftCreationTime = lpFindFileDataA->ftCreationTime;
1040 lpFindFileDataW->ftLastAccessTime = lpFindFileDataA->ftLastAccessTime;
1041 lpFindFileDataW->ftLastWriteTime = lpFindFileDataA->ftLastWriteTime;
1042 lpFindFileDataW->nFileSizeHigh = lpFindFileDataA->nFileSizeHigh;
1043 lpFindFileDataW->nFileSizeLow = lpFindFileDataA->nFileSizeLow;
1044 lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0;
1045 lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1;
1047 if (ConvertUtf8NToWChar(lpFindFileDataA->cFileName, ARRAYSIZE(lpFindFileDataA->cFileName),
1048 lpFindFileDataW->cFileName, ARRAYSIZE(lpFindFileDataW->cFileName)) < 0)
1051 return ConvertUtf8NToWChar(lpFindFileDataA->cAlternateFileName,
1052 ARRAYSIZE(lpFindFileDataA->cAlternateFileName),
1053 lpFindFileDataW->cAlternateFileName,
1054 ARRAYSIZE(lpFindFileDataW->cAlternateFileName)) >= 0;
1059 LPSTR utfFileName = NULL;
1062 return INVALID_HANDLE_VALUE;
1068 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1069 return INVALID_HANDLE_VALUE;
1072 utfFileName = ConvertWCharToUtf8Alloc(lpFileName, NULL);
1075 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1077 return INVALID_HANDLE_VALUE;
1080 h = FindFirstFileA(utfFileName, fd);
1083 if (h != INVALID_HANDLE_VALUE)
1085 if (!ConvertFindDataAToW(fd, lpFindFileData))
1087 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1089 h = INVALID_HANDLE_VALUE;
1099HANDLE FindFirstFileExA(WINPR_ATTR_UNUSED LPCSTR lpFileName,
1100 WINPR_ATTR_UNUSED FINDEX_INFO_LEVELS fInfoLevelId,
1101 WINPR_ATTR_UNUSED LPVOID lpFindFileData,
1102 WINPR_ATTR_UNUSED FINDEX_SEARCH_OPS fSearchOp,
1103 WINPR_ATTR_UNUSED LPVOID lpSearchFilter,
1104 WINPR_ATTR_UNUSED DWORD dwAdditionalFlags)
1106 WLog_ERR(
"TODO",
"TODO: Implement");
1107 return INVALID_HANDLE_VALUE;
1110HANDLE FindFirstFileExW(WINPR_ATTR_UNUSED LPCWSTR lpFileName,
1111 WINPR_ATTR_UNUSED FINDEX_INFO_LEVELS fInfoLevelId,
1112 WINPR_ATTR_UNUSED LPVOID lpFindFileData,
1113 WINPR_ATTR_UNUSED FINDEX_SEARCH_OPS fSearchOp,
1114 WINPR_ATTR_UNUSED LPVOID lpSearchFilter,
1115 WINPR_ATTR_UNUSED DWORD dwAdditionalFlags)
1117 WLog_ERR(
"TODO",
"TODO: Implement");
1118 return INVALID_HANDLE_VALUE;
1123 if (!lpFindFileData)
1127 *lpFindFileData = empty;
1129 if (!is_valid_file_search_handle(hFindFile))
1132 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1133 struct dirent* pDirent = NULL;
1135 while ((pDirent = readdir(pFileSearch->pDir)) != NULL)
1137 if (FilePatternMatchA(pDirent->d_name, pFileSearch->lpPattern))
1139 BOOL success = FALSE;
1141 strncpy(lpFindFileData->cFileName, pDirent->d_name, MAX_PATH);
1142 const size_t namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
1143 size_t pathlen = strlen(pFileSearch->lpPath);
1144 char* fullpath = (
char*)malloc(pathlen + namelen + 2);
1146 if (fullpath == NULL)
1148 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1152 memcpy(fullpath, pFileSearch->lpPath, pathlen);
1155 if (fullpath[pathlen - 1] !=
'/')
1156 fullpath[pathlen++] =
'/';
1157 memcpy(fullpath + pathlen, pDirent->d_name, namelen);
1158 fullpath[pathlen + namelen] = 0;
1160 struct stat fileStat = { 0 };
1161 if (stat(fullpath, &fileStat) != 0)
1164 SetLastError(map_posix_err(errno));
1170 if (S_ISFIFO(fileStat.st_mode))
1176 success = FindDataFromStat(fullpath, &fileStat, lpFindFileData);
1182 SetLastError(ERROR_NO_MORE_FILES);
1192 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1196 if (FindNextFileA(hFindFile, fd))
1198 if (!ConvertFindDataAToW(fd, lpFindFileData))
1200 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1213BOOL FindClose(HANDLE hFindFile)
1215 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1222#ifndef __clang_analyzer__
1223 if (!is_valid_file_search_handle(hFindFile))
1227 free(pFileSearch->lpPath);
1228 free(pFileSearch->lpPattern);
1230 if (pFileSearch->pDir)
1231 closedir(pFileSearch->pDir);
1238BOOL CreateDirectoryA(LPCSTR lpPathName,
1239 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1241 if (!mkdir(lpPathName, S_IRUSR | S_IWUSR | S_IXUSR))
1247BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1251 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1256 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1260 ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
1266BOOL RemoveDirectoryA(LPCSTR lpPathName)
1268 int ret = rmdir(lpPathName);
1271 SetLastError(map_posix_err(errno));
1273 SetLastError(STATUS_SUCCESS);
1278BOOL RemoveDirectoryW(LPCWSTR lpPathName)
1282 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1287 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1291 ret = RemoveDirectoryA(utfPathName);
1297BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
1301 ret = stat(lpNewFileName, &st);
1303 if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
1307 SetLastError(ERROR_ALREADY_EXISTS);
1313 if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
1315 SetLastError(ERROR_ACCESS_DENIED);
1320 ret = rename(lpExistingFileName, lpNewFileName);
1323 SetLastError(map_posix_err(errno));
1328BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
1330 if (!lpExistingFileName || !lpNewFileName)
1333 LPSTR lpCExistingFileName = ConvertWCharToUtf8Alloc(lpExistingFileName, NULL);
1334 LPSTR lpCNewFileName = ConvertWCharToUtf8Alloc(lpNewFileName, NULL);
1337 if (!lpCExistingFileName || !lpCNewFileName)
1339 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1343 ret = MoveFileExA(lpCExistingFileName, lpCNewFileName, dwFlags);
1345 free(lpCNewFileName);
1346 free(lpCExistingFileName);
1350BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
1352 return MoveFileExA(lpExistingFileName, lpNewFileName, 0);
1355BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
1357 return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
1364int UnixChangeFileMode(
const char* filename,
int flags)
1370 fl |= (flags & 0x4000) ? S_ISUID : 0;
1371 fl |= (flags & 0x2000) ? S_ISGID : 0;
1372 fl |= (flags & 0x1000) ? S_ISVTX : 0;
1373 fl |= (flags & 0x0400) ? S_IRUSR : 0;
1374 fl |= (flags & 0x0200) ? S_IWUSR : 0;
1375 fl |= (flags & 0x0100) ? S_IXUSR : 0;
1376 fl |= (flags & 0x0040) ? S_IRGRP : 0;
1377 fl |= (flags & 0x0020) ? S_IWGRP : 0;
1378 fl |= (flags & 0x0010) ? S_IXGRP : 0;
1379 fl |= (flags & 0x0004) ? S_IROTH : 0;
1380 fl |= (flags & 0x0002) ? S_IWOTH : 0;
1381 fl |= (flags & 0x0001) ? S_IXOTH : 0;
1382 return chmod(filename, fl);
1385 WCHAR* wfl = ConvertUtf8ToWCharAlloc(filename, NULL);
1391 if (flags & ~(_S_IREAD | _S_IWRITE))
1392 WLog_WARN(TAG,
"Unsupported file mode %d for _wchmod", flags);
1394 rc = _wchmod(wfl, flags);