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 ==
nullptr);
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,
nullptr);
226 g_AioSignalHandlerInstalled = TRUE;
234#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
235HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
236 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
237 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
239 return winpr_CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
240 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
244HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
245 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
246 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
249 return INVALID_HANDLE_VALUE;
251 if (pthread_once(&HandleCreatorsInitialized, HandleCreatorsInit) != 0)
253 SetLastError(ERROR_DLL_INIT_FAILED);
254 return INVALID_HANDLE_VALUE;
257 if (HandleCreators ==
nullptr)
259 SetLastError(ERROR_DLL_INIT_FAILED);
260 return INVALID_HANDLE_VALUE;
263 ArrayList_Lock(HandleCreators);
265 for (
size_t i = 0; i <= ArrayList_Count(HandleCreators); i++)
267 const HANDLE_CREATOR* creator = ArrayList_GetItem(HandleCreators, i);
269 if (creator && creator->IsHandled(lpFileName))
272 creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
273 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
274 ArrayList_Unlock(HandleCreators);
279 ArrayList_Unlock(HandleCreators);
280 return INVALID_HANDLE_VALUE;
283HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
284 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
285 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
287 HANDLE hdl =
nullptr;
290 char* lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName,
nullptr);
294 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
298 hdl = winpr_CreateFile(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
299 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
305#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
306BOOL DeleteFileA(LPCSTR lpFileName)
308 return winpr_DeleteFile(lpFileName);
312BOOL DeleteFileW(LPCWSTR lpFileName)
316 LPSTR lpFileNameA = ConvertWCharToUtf8Alloc(lpFileName,
nullptr);
317 BOOL rc = winpr_DeleteFile(lpFileNameA);
322BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
328 if (hFile == INVALID_HANDLE_VALUE)
336 if (!lpNumberOfBytesRead && !lpOverlapped)
339 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
344 if (handle->ops->ReadFile)
345 return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
348 WLog_ERR(TAG,
"ReadFile operation not implemented");
352BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
353 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
358 if (hFile == INVALID_HANDLE_VALUE)
361 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
366 if (handle->ops->ReadFileEx)
367 return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, lpOverlapped,
368 lpCompletionRoutine);
370 WLog_ERR(TAG,
"ReadFileEx operation not implemented");
374BOOL ReadFileScatter(HANDLE hFile,
FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
380 if (hFile == INVALID_HANDLE_VALUE)
383 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
388 if (handle->ops->ReadFileScatter)
389 return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, lpReserved,
392 WLog_ERR(TAG,
"ReadFileScatter operation not implemented");
396BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
397 LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped)
402 if (hFile == INVALID_HANDLE_VALUE)
405 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
410 if (handle->ops->WriteFile)
411 return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
412 lpNumberOfBytesWritten, lpOverlapped);
414 WLog_ERR(TAG,
"WriteFile operation not implemented");
418BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
419 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
424 if (hFile == INVALID_HANDLE_VALUE)
427 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
432 if (handle->ops->WriteFileEx)
433 return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, lpOverlapped,
434 lpCompletionRoutine);
436 WLog_ERR(TAG,
"WriteFileEx operation not implemented");
441 DWORD nNumberOfBytesToWrite, LPDWORD lpReserved,
LPOVERLAPPED lpOverlapped)
446 if (hFile == INVALID_HANDLE_VALUE)
449 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
454 if (handle->ops->WriteFileGather)
455 return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
456 lpReserved, lpOverlapped);
458 WLog_ERR(TAG,
"WriteFileGather operation not implemented");
462BOOL FlushFileBuffers(HANDLE hFile)
467 if (hFile == INVALID_HANDLE_VALUE)
470 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
475 if (handle->ops->FlushFileBuffers)
476 return handle->ops->FlushFileBuffers(handle);
478 WLog_ERR(TAG,
"FlushFileBuffers operation not implemented");
482BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName,
483 WINPR_ATTR_UNUSED GET_FILEEX_INFO_LEVELS fInfoLevelId,
484 LPVOID lpFileInformation)
490 struct stat fileStat = WINPR_C_ARRAY_INIT;
491 if (stat(lpFileName, &fileStat) != 0)
495 if (!FindDataFromStat(lpFileName, &fileStat, &findFileData))
498 fd->dwFileAttributes = findFileData.dwFileAttributes;
499 fd->ftCreationTime = findFileData.ftCreationTime;
500 fd->ftLastAccessTime = findFileData.ftLastAccessTime;
501 fd->ftLastWriteTime = findFileData.ftLastWriteTime;
502 fd->nFileSizeHigh = findFileData.nFileSizeHigh;
503 fd->nFileSizeLow = findFileData.nFileSizeLow;
507BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
508 LPVOID lpFileInformation)
513 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName,
nullptr);
517 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
521 ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
526DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
528 struct stat fileStat = WINPR_C_ARRAY_INIT;
529 if (stat(lpFileName, &fileStat) != 0)
530 return INVALID_FILE_ATTRIBUTES;
532 return FileAttributesFromStat(lpFileName, &fileStat);
535DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
540 LPSTR lpCFileName = ConvertWCharToUtf8Alloc(lpFileName,
nullptr);
543 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
547 ret = GetFileAttributesA(lpCFileName);
557 if (hFile == INVALID_HANDLE_VALUE)
560 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
565 if (handle->ops->GetFileInformationByHandle)
566 return handle->ops->GetFileInformationByHandle(handle, lpFileInformation);
568 WLog_ERR(TAG,
"GetFileInformationByHandle operation not implemented");
572static char* append(
char* buffer,
size_t size,
const char* append)
574 winpr_str_append(append, buffer, size,
"|");
578static const char* flagsToStr(
char* buffer,
size_t size, DWORD flags)
580 char strflags[32] = WINPR_C_ARRAY_INIT;
581 if (flags & FILE_ATTRIBUTE_READONLY)
582 append(buffer, size,
"FILE_ATTRIBUTE_READONLY");
583 if (flags & FILE_ATTRIBUTE_HIDDEN)
584 append(buffer, size,
"FILE_ATTRIBUTE_HIDDEN");
585 if (flags & FILE_ATTRIBUTE_SYSTEM)
586 append(buffer, size,
"FILE_ATTRIBUTE_SYSTEM");
587 if (flags & FILE_ATTRIBUTE_DIRECTORY)
588 append(buffer, size,
"FILE_ATTRIBUTE_DIRECTORY");
589 if (flags & FILE_ATTRIBUTE_ARCHIVE)
590 append(buffer, size,
"FILE_ATTRIBUTE_ARCHIVE");
591 if (flags & FILE_ATTRIBUTE_DEVICE)
592 append(buffer, size,
"FILE_ATTRIBUTE_DEVICE");
593 if (flags & FILE_ATTRIBUTE_NORMAL)
594 append(buffer, size,
"FILE_ATTRIBUTE_NORMAL");
595 if (flags & FILE_ATTRIBUTE_TEMPORARY)
596 append(buffer, size,
"FILE_ATTRIBUTE_TEMPORARY");
597 if (flags & FILE_ATTRIBUTE_SPARSE_FILE)
598 append(buffer, size,
"FILE_ATTRIBUTE_SPARSE_FILE");
599 if (flags & FILE_ATTRIBUTE_REPARSE_POINT)
600 append(buffer, size,
"FILE_ATTRIBUTE_REPARSE_POINT");
601 if (flags & FILE_ATTRIBUTE_COMPRESSED)
602 append(buffer, size,
"FILE_ATTRIBUTE_COMPRESSED");
603 if (flags & FILE_ATTRIBUTE_OFFLINE)
604 append(buffer, size,
"FILE_ATTRIBUTE_OFFLINE");
605 if (flags & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
606 append(buffer, size,
"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED");
607 if (flags & FILE_ATTRIBUTE_ENCRYPTED)
608 append(buffer, size,
"FILE_ATTRIBUTE_ENCRYPTED");
609 if (flags & FILE_ATTRIBUTE_VIRTUAL)
610 append(buffer, size,
"FILE_ATTRIBUTE_VIRTUAL");
612 (void)_snprintf(strflags,
sizeof(strflags),
" [0x%08" PRIx32
"]", flags);
613 winpr_str_append(strflags, buffer, size,
nullptr);
617BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
620#ifdef WINPR_HAVE_FCNTL_H
621 const uint32_t mask = ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_NORMAL);
622 if (dwFileAttributes & mask)
624 char buffer[8192] = WINPR_C_ARRAY_INIT;
625 const char* flags = flagsToStr(buffer,
sizeof(buffer), dwFileAttributes & mask);
626 WLog_WARN(TAG,
"Unsupported flags %s, ignoring!", flags);
629 int fd = open(lpFileName, O_RDONLY);
633 struct stat st = WINPR_C_ARRAY_INIT;
634 if (fstat(fd, &st) != 0)
637 if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
639 st.st_mode &= WINPR_ASSERTING_INT_CAST(mode_t, (mode_t)(~(S_IWUSR | S_IWGRP | S_IWOTH)));
643 st.st_mode |= S_IWUSR;
646 if (fchmod(fd, st.st_mode) != 0)
656BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
663 char* lpCFileName = ConvertWCharToUtf8Alloc(lpFileName,
nullptr);
666 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
670 ret = SetFileAttributesA(lpCFileName, dwFileAttributes);
675BOOL SetEndOfFile(HANDLE hFile)
680 if (hFile == INVALID_HANDLE_VALUE)
683 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
688 if (handle->ops->SetEndOfFile)
689 return handle->ops->SetEndOfFile(handle);
691 WLog_ERR(TAG,
"SetEndOfFile operation not implemented");
695DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
700 if (hFile == INVALID_HANDLE_VALUE)
703 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
708 if (handle->ops->GetFileSize)
709 return handle->ops->GetFileSize(handle, lpFileSizeHigh);
711 WLog_ERR(TAG,
"GetFileSize operation not implemented");
715DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
721 if (hFile == INVALID_HANDLE_VALUE)
724 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
729 if (handle->ops->SetFilePointer)
730 return handle->ops->SetFilePointer(handle, lDistanceToMove, lpDistanceToMoveHigh,
733 WLog_ERR(TAG,
"SetFilePointer operation not implemented");
737BOOL SetFilePointerEx(HANDLE hFile,
LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
743 if (hFile == INVALID_HANDLE_VALUE)
746 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
751 if (handle->ops->SetFilePointerEx)
752 return handle->ops->SetFilePointerEx(handle, liDistanceToMove, lpNewFilePointer,
755 WLog_ERR(TAG,
"SetFilePointerEx operation not implemented");
759BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
760 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
765 if (hFile == INVALID_HANDLE_VALUE)
768 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
773 if (handle->ops->LockFile)
774 return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
775 nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
777 WLog_ERR(TAG,
"LockFile operation not implemented");
781BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow,
782 DWORD nNumberOfBytesToLockHigh,
LPOVERLAPPED lpOverlapped)
787 if (hFile == INVALID_HANDLE_VALUE)
790 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
795 if (handle->ops->LockFileEx)
796 return handle->ops->LockFileEx(handle, dwFlags, dwReserved, nNumberOfBytesToLockLow,
797 nNumberOfBytesToLockHigh, lpOverlapped);
799 WLog_ERR(TAG,
"LockFileEx operation not implemented");
803BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
804 DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
809 if (hFile == INVALID_HANDLE_VALUE)
812 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
817 if (handle->ops->UnlockFile)
818 return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
819 nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
821 WLog_ERR(TAG,
"UnLockFile operation not implemented");
825BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
826 DWORD nNumberOfBytesToUnlockHigh,
LPOVERLAPPED lpOverlapped)
831 if (hFile == INVALID_HANDLE_VALUE)
834 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
839 if (handle->ops->UnlockFileEx)
840 return handle->ops->UnlockFileEx(handle, dwReserved, nNumberOfBytesToUnlockLow,
841 nNumberOfBytesToUnlockHigh, lpOverlapped);
843 WLog_ERR(TAG,
"UnLockFileEx operation not implemented");
847BOOL WINAPI SetFileTime(HANDLE hFile,
const FILETIME* lpCreationTime,
853 if (hFile == INVALID_HANDLE_VALUE)
856 if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
861 if (handle->ops->SetFileTime)
862 return handle->ops->SetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
864 WLog_ERR(TAG,
"operation not implemented");
876static const char file_search_magic[] =
"file_srch_magic";
878WINPR_ATTR_MALLOC(FindClose, 1)
879static WIN32_FILE_SEARCH* file_search_new(const
char* name,
size_t namelen, const
char* pattern,
882 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)calloc(1,
sizeof(WIN32_FILE_SEARCH));
885 WINPR_ASSERT(
sizeof(file_search_magic) ==
sizeof(pFileSearch->magic));
886 memcpy(pFileSearch->magic, file_search_magic,
sizeof(pFileSearch->magic));
888 pFileSearch->lpPath = strndup(name, namelen);
889 pFileSearch->lpPattern = strndup(pattern, patternlen);
890 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
893 pFileSearch->pDir = opendir(pFileSearch->lpPath);
894 if (!pFileSearch->pDir)
900 struct stat fileStat = WINPR_C_ARRAY_INIT;
901 if (stat(name, &fileStat) == 0)
903 if (S_ISDIR(fileStat.st_mode))
905 pFileSearch->pDir = opendir(name);
906 if (pFileSearch->pDir)
908 free(pFileSearch->lpPath);
909 free(pFileSearch->lpPattern);
910 pFileSearch->lpPath = _strdup(name);
911 pFileSearch->lpPattern = _strdup(
"*");
912 if (!pFileSearch->lpPath || !pFileSearch->lpPattern)
914 closedir(pFileSearch->pDir);
915 pFileSearch->pDir =
nullptr;
922 char buffer[128] = WINPR_C_ARRAY_INIT;
923 const DWORD err = map_posix_err(errno);
924 WLog_DBG(TAG,
"stat failed with %s [%d] -> %s",
925 winpr_strerror(errno, buffer,
sizeof(buffer)), errno,
926 Win32ErrorCode2Tag(err & 0xFFFF));
930 if (!pFileSearch->pDir)
935 WINPR_PRAGMA_DIAG_PUSH
936 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
937 FindClose(pFileSearch);
938 WINPR_PRAGMA_DIAG_POP
942static BOOL is_valid_file_search_handle(HANDLE handle)
944 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)handle;
947 if (pFileSearch == INVALID_HANDLE_VALUE)
949 if (strncmp(file_search_magic, pFileSearch->magic,
sizeof(file_search_magic)) != 0)
954static DWORD FileAttributesFromStat(
const char* path,
const struct stat* fileStat)
956 DWORD dwFileAttributes = 0;
958 if (S_ISDIR(fileStat->st_mode))
959 dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
961 if (dwFileAttributes == 0)
962 dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
964 const char* lastSep = strrchr(path,
'/');
967 const char* name = lastSep + 1;
968 const size_t namelen = strlen(name);
970 if ((namelen > 1) && (name[0] ==
'.') && (name[1] !=
'.'))
971 dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
974 if (!(fileStat->st_mode & S_IWUSR))
975 dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
977 return dwFileAttributes;
980static BOOL FindDataFromStat(
const char* path,
const struct stat* fileStat,
984 lpFindFileData->dwFileAttributes = FileAttributesFromStat(path, fileStat);
986#ifdef _DARWIN_FEATURE_64_BIT_INODE
987 ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
989 ft = STAT_TIME_TO_FILETIME(fileStat->st_ctime);
991 lpFindFileData->ftCreationTime.dwHighDateTime = (ft) >> 32ULL;
992 lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
993 ft = STAT_TIME_TO_FILETIME(fileStat->st_mtime);
994 lpFindFileData->ftLastWriteTime.dwHighDateTime = (ft) >> 32ULL;
995 lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
996 ft = STAT_TIME_TO_FILETIME(fileStat->st_atime);
997 lpFindFileData->ftLastAccessTime.dwHighDateTime = (ft) >> 32ULL;
998 lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
999 lpFindFileData->nFileSizeHigh = ((UINT64)fileStat->st_size) >> 32ULL;
1000 lpFindFileData->nFileSizeLow = fileStat->st_size & 0xFFFFFFFF;
1006 if (!lpFindFileData || !lpFileName)
1008 SetLastError(ERROR_BAD_ARGUMENTS);
1009 return INVALID_HANDLE_VALUE;
1013 *lpFindFileData = empty;
1015 WIN32_FILE_SEARCH* pFileSearch =
nullptr;
1016 size_t patternlen = 0;
1017 const size_t flen = strlen(lpFileName);
1018 const char sep = PathGetSeparatorA(PATH_STYLE_NATIVE);
1019 const char* ptr = strrchr(lpFileName, sep);
1022 patternlen = strlen(ptr + 1);
1023 if (patternlen == 0)
1026 pFileSearch = file_search_new(lpFileName, flen - patternlen, ptr + 1, patternlen);
1029 return INVALID_HANDLE_VALUE;
1031 if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData))
1032 return (HANDLE)pFileSearch;
1035 FindClose(pFileSearch);
1036 return INVALID_HANDLE_VALUE;
1042 if (!lpFindFileDataA || !lpFindFileDataW)
1045 lpFindFileDataW->dwFileAttributes = lpFindFileDataA->dwFileAttributes;
1046 lpFindFileDataW->ftCreationTime = lpFindFileDataA->ftCreationTime;
1047 lpFindFileDataW->ftLastAccessTime = lpFindFileDataA->ftLastAccessTime;
1048 lpFindFileDataW->ftLastWriteTime = lpFindFileDataA->ftLastWriteTime;
1049 lpFindFileDataW->nFileSizeHigh = lpFindFileDataA->nFileSizeHigh;
1050 lpFindFileDataW->nFileSizeLow = lpFindFileDataA->nFileSizeLow;
1051 lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0;
1052 lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1;
1054 if (ConvertUtf8NToWChar(lpFindFileDataA->cFileName, ARRAYSIZE(lpFindFileDataA->cFileName),
1055 lpFindFileDataW->cFileName, ARRAYSIZE(lpFindFileDataW->cFileName)) < 0)
1058 return ConvertUtf8NToWChar(lpFindFileDataA->cAlternateFileName,
1059 ARRAYSIZE(lpFindFileDataA->cAlternateFileName),
1060 lpFindFileDataW->cAlternateFileName,
1061 ARRAYSIZE(lpFindFileDataW->cAlternateFileName)) >= 0;
1066 LPSTR utfFileName =
nullptr;
1069 return INVALID_HANDLE_VALUE;
1075 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1076 return INVALID_HANDLE_VALUE;
1079 utfFileName = ConvertWCharToUtf8Alloc(lpFileName,
nullptr);
1082 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1084 return INVALID_HANDLE_VALUE;
1087 h = FindFirstFileA(utfFileName, fd);
1090 if (h != INVALID_HANDLE_VALUE)
1092 if (!ConvertFindDataAToW(fd, lpFindFileData))
1094 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1096 h = INVALID_HANDLE_VALUE;
1106HANDLE FindFirstFileExA(WINPR_ATTR_UNUSED LPCSTR lpFileName,
1107 WINPR_ATTR_UNUSED FINDEX_INFO_LEVELS fInfoLevelId,
1108 WINPR_ATTR_UNUSED LPVOID lpFindFileData,
1109 WINPR_ATTR_UNUSED FINDEX_SEARCH_OPS fSearchOp,
1110 WINPR_ATTR_UNUSED LPVOID lpSearchFilter,
1111 WINPR_ATTR_UNUSED DWORD dwAdditionalFlags)
1113 WLog_ERR(
"TODO",
"TODO: Implement");
1114 return INVALID_HANDLE_VALUE;
1117HANDLE FindFirstFileExW(WINPR_ATTR_UNUSED LPCWSTR lpFileName,
1118 WINPR_ATTR_UNUSED FINDEX_INFO_LEVELS fInfoLevelId,
1119 WINPR_ATTR_UNUSED LPVOID lpFindFileData,
1120 WINPR_ATTR_UNUSED FINDEX_SEARCH_OPS fSearchOp,
1121 WINPR_ATTR_UNUSED LPVOID lpSearchFilter,
1122 WINPR_ATTR_UNUSED DWORD dwAdditionalFlags)
1124 WLog_ERR(
"TODO",
"TODO: Implement");
1125 return INVALID_HANDLE_VALUE;
1130 if (!lpFindFileData)
1134 *lpFindFileData = empty;
1136 if (!is_valid_file_search_handle(hFindFile))
1139 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1140 struct dirent* pDirent =
nullptr;
1142 while ((pDirent = readdir(pFileSearch->pDir)) !=
nullptr)
1144 if (FilePatternMatchA(pDirent->d_name, pFileSearch->lpPattern))
1146 BOOL success = FALSE;
1148 strncpy(lpFindFileData->cFileName, pDirent->d_name, MAX_PATH);
1149 const size_t namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
1150 size_t pathlen = strlen(pFileSearch->lpPath);
1151 char* fullpath = (
char*)malloc(pathlen + namelen + 2);
1153 if (fullpath ==
nullptr)
1155 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1159 memcpy(fullpath, pFileSearch->lpPath, pathlen);
1162 if (fullpath[pathlen - 1] !=
'/')
1163 fullpath[pathlen++] =
'/';
1164 memcpy(fullpath + pathlen, pDirent->d_name, namelen);
1165 fullpath[pathlen + namelen] = 0;
1167 struct stat fileStat = WINPR_C_ARRAY_INIT;
1168 if (stat(fullpath, &fileStat) != 0)
1171 SetLastError(map_posix_err(errno));
1177 if (S_ISFIFO(fileStat.st_mode))
1183 success = FindDataFromStat(fullpath, &fileStat, lpFindFileData);
1189 SetLastError(ERROR_NO_MORE_FILES);
1199 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1203 if (FindNextFileA(hFindFile, fd))
1205 if (!ConvertFindDataAToW(fd, lpFindFileData))
1207 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1220BOOL FindClose(HANDLE hFindFile)
1222 WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
1229#ifndef __clang_analyzer__
1230 if (!is_valid_file_search_handle(hFindFile))
1234 free(pFileSearch->lpPath);
1235 free(pFileSearch->lpPattern);
1237 if (pFileSearch->pDir)
1238 closedir(pFileSearch->pDir);
1245BOOL CreateDirectoryA(LPCSTR lpPathName,
1246 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1248 return mkdir(lpPathName, S_IRUSR | S_IWUSR | S_IXUSR) == 0;
1251BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1255 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName,
nullptr);
1260 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1264 ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
1270#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
1271BOOL RemoveDirectoryA(LPCSTR lpPathName)
1273 return winpr_RemoveDirectory(lpPathName);
1277BOOL RemoveDirectoryW(LPCWSTR lpPathName)
1281 char* utfPathName = ConvertWCharToUtf8Alloc(lpPathName,
nullptr);
1286 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1290 ret = winpr_RemoveDirectory(utfPathName);
1296#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
1297BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
1299 return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags);
1303BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
1305 if (!lpExistingFileName || !lpNewFileName)
1308 LPSTR lpCExistingFileName = ConvertWCharToUtf8Alloc(lpExistingFileName,
nullptr);
1309 LPSTR lpCNewFileName = ConvertWCharToUtf8Alloc(lpNewFileName,
nullptr);
1312 if (!lpCExistingFileName || !lpCNewFileName)
1314 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1318 ret = winpr_MoveFileEx(lpCExistingFileName, lpCNewFileName, dwFlags);
1320 free(lpCNewFileName);
1321 free(lpCExistingFileName);
1325#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
1326BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
1328 return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0);
1332BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
1334 return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
1341int UnixChangeFileMode(
const char* filename,
int flags)
1347 fl |= (flags & 0x4000) ? S_ISUID : 0;
1348 fl |= (flags & 0x2000) ? S_ISGID : 0;
1349 fl |= (flags & 0x1000) ? S_ISVTX : 0;
1350 fl |= (flags & 0x0400) ? S_IRUSR : 0;
1351 fl |= (flags & 0x0200) ? S_IWUSR : 0;
1352 fl |= (flags & 0x0100) ? S_IXUSR : 0;
1353 fl |= (flags & 0x0040) ? S_IRGRP : 0;
1354 fl |= (flags & 0x0020) ? S_IWGRP : 0;
1355 fl |= (flags & 0x0010) ? S_IXGRP : 0;
1356 fl |= (flags & 0x0004) ? S_IROTH : 0;
1357 fl |= (flags & 0x0002) ? S_IWOTH : 0;
1358 fl |= (flags & 0x0001) ? S_IXOTH : 0;
1359 return chmod(filename, fl);
1362 WCHAR* wfl = ConvertUtf8ToWCharAlloc(filename,
nullptr);
1368 if (flags & ~(_S_IREAD | _S_IWRITE))
1369 WLog_WARN(TAG,
"Unsupported file mode %d for _wchmod", flags);
1371 rc = _wchmod(wfl, flags);
1377#if defined(_WIN32) || defined(_UWP)
1378HANDLE winpr_CreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
1379 LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
1380 DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
1382 WCHAR* filename = ConvertUtf8ToWCharAlloc(lpFileName,
nullptr);
1386 HANDLE hdl = CreateFileW(filename, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
1387 dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);