Blame winpr/libwinpr/file/generic.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * File Functions
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2014 Hewlett-Packard Development Company, L.P.
Packit 1fb8d4
 * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/path.h>
Packit 1fb8d4
#include <winpr/file.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_UNISTD_H
Packit 1fb8d4
#include <unistd.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_FCNTL_H
Packit 1fb8d4
#include <fcntl.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("file")
Packit 1fb8d4
Packit 1fb8d4
#ifdef _WIN32
Packit 1fb8d4
#include <io.h>
Packit 1fb8d4
#include <sys/stat.h>
Packit 1fb8d4
#else
Packit 1fb8d4
#include <assert.h>
Packit 1fb8d4
#include <pthread.h>
Packit 1fb8d4
#include <dirent.h>
Packit 1fb8d4
#include <libgen.h>
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
Packit 1fb8d4
#include <sys/un.h>
Packit 1fb8d4
#include <sys/stat.h>
Packit 1fb8d4
#include <sys/socket.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_AIO_H
Packit 1fb8d4
#undef HAVE_AIO_H /* disable for now, incomplete */
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_AIO_H
Packit 1fb8d4
#include <aio.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifdef ANDROID
Packit 1fb8d4
#include <sys/vfs.h>
Packit 1fb8d4
#else
Packit 1fb8d4
#include <sys/statvfs.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "../handle/handle.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../pipe/pipe.h"
Packit 1fb8d4
Packit 1fb8d4
#include "file.h"
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * api-ms-win-core-file-l1-2-0.dll:
Packit 1fb8d4
 *
Packit 1fb8d4
 * CreateFileA
Packit 1fb8d4
 * CreateFileW
Packit 1fb8d4
 * CreateFile2
Packit 1fb8d4
 * DeleteFileA
Packit 1fb8d4
 * DeleteFileW
Packit 1fb8d4
 * CreateDirectoryA
Packit 1fb8d4
 * CreateDirectoryW
Packit 1fb8d4
 * RemoveDirectoryA
Packit 1fb8d4
 * RemoveDirectoryW
Packit 1fb8d4
 * CompareFileTime
Packit 1fb8d4
 * DefineDosDeviceW
Packit 1fb8d4
 * DeleteVolumeMountPointW
Packit 1fb8d4
 * FileTimeToLocalFileTime
Packit 1fb8d4
 * LocalFileTimeToFileTime
Packit 1fb8d4
 * FindClose
Packit 1fb8d4
 * FindCloseChangeNotification
Packit 1fb8d4
 * FindFirstChangeNotificationA
Packit 1fb8d4
 * FindFirstChangeNotificationW
Packit 1fb8d4
 * FindFirstFileA
Packit 1fb8d4
 * FindFirstFileExA
Packit 1fb8d4
 * FindFirstFileExW
Packit 1fb8d4
 * FindFirstFileW
Packit 1fb8d4
 * FindFirstVolumeW
Packit 1fb8d4
 * FindNextChangeNotification
Packit 1fb8d4
 * FindNextFileA
Packit 1fb8d4
 * FindNextFileW
Packit 1fb8d4
 * FindNextVolumeW
Packit 1fb8d4
 * FindVolumeClose
Packit 1fb8d4
 * GetDiskFreeSpaceA
Packit 1fb8d4
 * GetDiskFreeSpaceExA
Packit 1fb8d4
 * GetDiskFreeSpaceExW
Packit 1fb8d4
 * GetDiskFreeSpaceW
Packit 1fb8d4
 * GetDriveTypeA
Packit 1fb8d4
 * GetDriveTypeW
Packit 1fb8d4
 * GetFileAttributesA
Packit 1fb8d4
 * GetFileAttributesExA
Packit 1fb8d4
 * GetFileAttributesExW
Packit 1fb8d4
 * GetFileAttributesW
Packit 1fb8d4
 * GetFileInformationByHandle
Packit 1fb8d4
 * GetFileSize
Packit 1fb8d4
 * GetFileSizeEx
Packit 1fb8d4
 * GetFileTime
Packit 1fb8d4
 * GetFileType
Packit 1fb8d4
 * GetFinalPathNameByHandleA
Packit 1fb8d4
 * GetFinalPathNameByHandleW
Packit 1fb8d4
 * GetFullPathNameA
Packit 1fb8d4
 * GetFullPathNameW
Packit 1fb8d4
 * GetLogicalDrives
Packit 1fb8d4
 * GetLogicalDriveStringsW
Packit 1fb8d4
 * GetLongPathNameA
Packit 1fb8d4
 * GetLongPathNameW
Packit 1fb8d4
 * GetShortPathNameW
Packit 1fb8d4
 * GetTempFileNameW
Packit 1fb8d4
 * GetTempPathW
Packit 1fb8d4
 * GetVolumeInformationByHandleW
Packit 1fb8d4
 * GetVolumeInformationW
Packit 1fb8d4
 * GetVolumeNameForVolumeMountPointW
Packit 1fb8d4
 * GetVolumePathNamesForVolumeNameW
Packit 1fb8d4
 * GetVolumePathNameW
Packit 1fb8d4
 * QueryDosDeviceW
Packit 1fb8d4
 * SetFileAttributesA
Packit 1fb8d4
 * SetFileAttributesW
Packit 1fb8d4
 * SetFileTime
Packit 1fb8d4
 * SetFileValidData
Packit 1fb8d4
 * SetFileInformationByHandle
Packit 1fb8d4
 * ReadFile
Packit 1fb8d4
 * ReadFileEx
Packit 1fb8d4
 * ReadFileScatter
Packit 1fb8d4
 * WriteFile
Packit 1fb8d4
 * WriteFileEx
Packit 1fb8d4
 * WriteFileGather
Packit 1fb8d4
 * FlushFileBuffers
Packit 1fb8d4
 * SetEndOfFile
Packit 1fb8d4
 * SetFilePointer
Packit 1fb8d4
 * SetFilePointerEx
Packit 1fb8d4
 * LockFile
Packit 1fb8d4
 * LockFileEx
Packit 1fb8d4
 * UnlockFile
Packit 1fb8d4
 * UnlockFileEx
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * File System Behavior in the Microsoft Windows Environment:
Packit 1fb8d4
 * http://download.microsoft.com/download/4/3/8/43889780-8d45-4b2e-9d3a-c696a890309f/File%20System%20Behavior%20Overview.pdf
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Asynchronous I/O - The GNU C Library:
Packit 1fb8d4
 * http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * aio.h - asynchronous input and output:
Packit 1fb8d4
 * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Asynchronous I/O User Guide:
Packit 1fb8d4
 * http://code.google.com/p/kernel/wiki/AIOUserGuide
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#define EPOCH_DIFF 11644473600LL
Packit 1fb8d4
#define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
Packit 1fb8d4
Packit 1fb8d4
static wArrayList* _HandleCreators;
Packit 1fb8d4
Packit 1fb8d4
static pthread_once_t _HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
Packit 1fb8d4
Packit Service 5a9772
extern HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void);
Packit 1fb8d4
Packit 1fb8d4
#if defined __linux__ && !defined ANDROID
Packit Service 5a9772
extern HANDLE_CREATOR* GetCommHandleCreator(void);
Packit 1fb8d4
#endif /* __linux__ && !defined ANDROID */
Packit 1fb8d4
Packit 1fb8d4
static void _HandleCreatorsInit()
Packit 1fb8d4
{
Packit 1fb8d4
	assert(_HandleCreators == NULL);
Packit 1fb8d4
	_HandleCreators = ArrayList_New(TRUE);
Packit 1fb8d4
Packit 1fb8d4
	if (!_HandleCreators)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	/*
Packit 1fb8d4
	 * Register all file handle creators.
Packit 1fb8d4
	 */
Packit 1fb8d4
	ArrayList_Add(_HandleCreators, GetNamedPipeClientHandleCreator());
Packit 1fb8d4
#if defined __linux__ && !defined ANDROID
Packit 1fb8d4
	ArrayList_Add(_HandleCreators, GetCommHandleCreator());
Packit 1fb8d4
#endif /* __linux__ && !defined ANDROID */
Packit 1fb8d4
	ArrayList_Add(_HandleCreators, GetFileHandleCreator());
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_AIO_H
Packit 1fb8d4
Packit 1fb8d4
static BOOL g_AioSignalHandlerInstalled = FALSE;
Packit 1fb8d4
Packit 1fb8d4
void AioSignalHandler(int signum, siginfo_t* siginfo, void* arg)
Packit 1fb8d4
{
Packit 1fb8d4
	WLog_INFO("%d", signum);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int InstallAioSignalHandler()
Packit 1fb8d4
{
Packit 1fb8d4
	if (!g_AioSignalHandlerInstalled)
Packit 1fb8d4
	{
Packit 1fb8d4
		struct sigaction action;
Packit 1fb8d4
		sigemptyset(&action.sa_mask);
Packit 1fb8d4
		sigaddset(&action.sa_mask, SIGIO);
Packit 1fb8d4
		action.sa_flags = SA_SIGINFO;
Packit Service 5a9772
		action.sa_sigaction = (void*)&AioSignalHandler;
Packit 1fb8d4
		sigaction(SIGIO, &action, NULL);
Packit 1fb8d4
		g_AioSignalHandlerInstalled = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif /* HAVE_AIO_H */
Packit 1fb8d4
Packit 1fb8d4
HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
Packit Service 5a9772
                   LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
Packit Service 5a9772
                   DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
Packit 1fb8d4
{
Packit 1fb8d4
	int i;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileName)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	if (pthread_once(&_HandleCreatorsInitialized, _HandleCreatorsInit) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_DLL_INIT_FAILED);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (_HandleCreators == NULL)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_DLL_INIT_FAILED);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ArrayList_Lock(_HandleCreators);
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i <= ArrayList_Count(_HandleCreators); i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		HANDLE_CREATOR* creator = ArrayList_GetItem(_HandleCreators, i);
Packit 1fb8d4
Packit 1fb8d4
		if (creator && creator->IsHandled(lpFileName))
Packit 1fb8d4
		{
Packit Service 5a9772
			HANDLE newHandle =
Packit Service 5a9772
			    creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
Packit Service 5a9772
			                         dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
Packit 1fb8d4
			ArrayList_Unlock(_HandleCreators);
Packit 1fb8d4
			return newHandle;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ArrayList_Unlock(_HandleCreators);
Packit 1fb8d4
	return INVALID_HANDLE_VALUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
Packit Service 5a9772
                   LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
Packit Service 5a9772
                   DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR lpFileNameA = NULL;
Packit 1fb8d4
	HANDLE hdl;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL) < 1)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	hdl = CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
Packit 1fb8d4
	                  dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
Packit 1fb8d4
	free(lpFileNameA);
Packit 1fb8d4
	return hdl;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL DeleteFileA(LPCSTR lpFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	status = unlink(lpFileName);
Packit 1fb8d4
	return (status != -1) ? TRUE : FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL DeleteFileW(LPCWSTR lpFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR lpFileNameA = NULL;
Packit 1fb8d4
	BOOL rc = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL) < 1)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	rc = DeleteFileA(lpFileNameA);
Packit 1fb8d4
	free(lpFileNameA);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
Packit 1fb8d4
              LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	/*
Packit 1fb8d4
	 * from http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx
Packit 1fb8d4
	 * lpNumberOfBytesRead can be NULL only when the lpOverlapped parameter is not NULL.
Packit 1fb8d4
	 */
Packit 1fb8d4
Packit 1fb8d4
	if (!lpNumberOfBytesRead && !lpOverlapped)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->ReadFile)
Packit Service 5a9772
		return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
Packit Service 5a9772
		                             lpOverlapped);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "ReadFile operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
Packit 1fb8d4
                LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->ReadFileEx)
Packit Service 5a9772
		return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, lpOverlapped,
Packit Service 5a9772
		                               lpCompletionRoutine);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "ReadFileEx operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL ReadFileScatter(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
Packit Service 5a9772
                     LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->ReadFileScatter)
Packit Service 5a9772
		return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, lpReserved,
Packit Service 5a9772
		                                    lpOverlapped);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "ReadFileScatter operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
Packit 1fb8d4
               LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->WriteFile)
Packit 1fb8d4
		return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
Packit 1fb8d4
		                              lpNumberOfBytesWritten, lpOverlapped);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "WriteFile operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
Packit 1fb8d4
                 LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->WriteFileEx)
Packit Service 5a9772
		return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, lpOverlapped,
Packit Service 5a9772
		                                lpCompletionRoutine);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "WriteFileEx operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WriteFileGather(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[],
Packit 1fb8d4
                     DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->WriteFileGather)
Packit 1fb8d4
		return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
Packit 1fb8d4
		                                    lpReserved, lpOverlapped);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "WriteFileGather operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL FlushFileBuffers(HANDLE hFile)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->FlushFileBuffers)
Packit 1fb8d4
		return handle->ops->FlushFileBuffers(handle);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "FlushFileBuffers operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
Packit 1fb8d4
                                 LPVOID lpFileInformation)
Packit 1fb8d4
{
Packit 1fb8d4
	LPWIN32_FILE_ATTRIBUTE_DATA fd = lpFileInformation;
Packit 1fb8d4
	WIN32_FIND_DATAA findFileData;
Packit 1fb8d4
	HANDLE hFind;
Packit 1fb8d4
Packit 1fb8d4
	if (!fd)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	FindClose(hFind);
Packit 1fb8d4
	fd->dwFileAttributes = findFileData.dwFileAttributes;
Packit 1fb8d4
	fd->ftCreationTime = findFileData.ftCreationTime;
Packit 1fb8d4
	fd->ftLastAccessTime = findFileData.ftLastAccessTime;
Packit 1fb8d4
	fd->ftLastWriteTime = findFileData.ftLastWriteTime;
Packit 1fb8d4
	fd->nFileSizeHigh = findFileData.nFileSizeHigh;
Packit 1fb8d4
	fd->nFileSizeLow = findFileData.nFileSizeLow;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
Packit 1fb8d4
                                 LPVOID lpFileInformation)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
	LPSTR lpCFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
Packit 1fb8d4
	free(lpCFileName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	WIN32_FIND_DATAA findFileData;
Packit 1fb8d4
	HANDLE hFind;
Packit 1fb8d4
Packit 1fb8d4
	if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return INVALID_FILE_ATTRIBUTES;
Packit 1fb8d4
Packit 1fb8d4
	FindClose(hFind);
Packit 1fb8d4
	return findFileData.dwFileAttributes;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD ret;
Packit 1fb8d4
	LPSTR lpCFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = GetFileAttributesA(lpCFileName);
Packit 1fb8d4
	free(lpCFileName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
Packit 1fb8d4
{
Packit 1fb8d4
	struct stat st;
Packit 1fb8d4
Packit 1fb8d4
	if (stat(lpFileName, &st) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
Packit 1fb8d4
	{
Packit 1fb8d4
		st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		st.st_mode |= S_IWUSR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (chmod(lpFileName, st.st_mode) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
	LPSTR lpCFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = SetFileAttributesA(lpCFileName, dwFileAttributes);
Packit 1fb8d4
	free(lpCFileName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetEndOfFile(HANDLE hFile)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->SetEndOfFile)
Packit 1fb8d4
		return handle->ops->SetEndOfFile(handle);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "SetEndOfFile operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->GetFileSize)
Packit 1fb8d4
		return handle->ops->GetFileSize(handle, lpFileSizeHigh);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "GetFileSize operation not implemented");
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
Packit Service 5a9772
                     DWORD dwMoveMethod)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->SetFilePointer)
Packit Service 5a9772
		return handle->ops->SetFilePointer(handle, lDistanceToMove, lpDistanceToMoveHigh,
Packit Service 5a9772
		                                   dwMoveMethod);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "SetFilePointer operation not implemented");
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
Packit Service 5a9772
                      DWORD dwMoveMethod)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->SetFilePointerEx)
Packit Service 5a9772
		return handle->ops->SetFilePointerEx(handle, liDistanceToMove, lpNewFilePointer,
Packit Service 5a9772
		                                     dwMoveMethod);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "SetFilePointerEx operation not implemented");
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
Packit 1fb8d4
              DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->LockFile)
Packit 1fb8d4
		return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
Packit 1fb8d4
		                             nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "LockFile operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow,
Packit Service 5a9772
                DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->LockFileEx)
Packit Service 5a9772
		return handle->ops->LockFileEx(handle, dwFlags, dwReserved, nNumberOfBytesToLockLow,
Packit Service 5a9772
		                               nNumberOfBytesToLockHigh, lpOverlapped);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "LockFileEx operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
Packit 1fb8d4
                DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->UnlockFile)
Packit 1fb8d4
		return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
Packit 1fb8d4
		                               nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "UnLockFile operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
Packit 1fb8d4
                  DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->UnlockFileEx)
Packit Service 5a9772
		return handle->ops->UnlockFileEx(handle, dwReserved, nNumberOfBytesToUnlockLow,
Packit Service 5a9772
		                                 nNumberOfBytesToUnlockHigh, lpOverlapped);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "UnLockFileEx operation not implemented");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
Packit 1fb8d4
                        const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
Packit 1fb8d4
{
Packit 1fb8d4
	ULONG Type;
Packit 1fb8d4
	WINPR_HANDLE* handle;
Packit 1fb8d4
Packit 1fb8d4
	if (hFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	handle = (WINPR_HANDLE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (handle->ops->SetFileTime)
Packit Service 5a9772
		return handle->ops->SetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
struct _WIN32_FILE_SEARCH
Packit 1fb8d4
{
Packit 1fb8d4
	DIR* pDir;
Packit 1fb8d4
	LPSTR lpPath;
Packit 1fb8d4
	LPSTR lpPattern;
Packit 1fb8d4
	struct dirent* pDirent;
Packit 1fb8d4
};
Packit 1fb8d4
typedef struct _WIN32_FILE_SEARCH WIN32_FILE_SEARCH;
Packit 1fb8d4
Packit 1fb8d4
static BOOL FindDataFromStat(const char* path, const struct stat* fileStat,
Packit 1fb8d4
                             LPWIN32_FIND_DATAA lpFindFileData)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT64 ft;
Packit 1fb8d4
	char* lastSep;
Packit 1fb8d4
	lpFindFileData->dwFileAttributes = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (S_ISDIR(fileStat->st_mode))
Packit 1fb8d4
		lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
Packit 1fb8d4
Packit 1fb8d4
	if (lpFindFileData->dwFileAttributes == 0)
Packit 1fb8d4
		lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
Packit 1fb8d4
Packit 1fb8d4
	lastSep = strrchr(path, '/');
Packit 1fb8d4
Packit 1fb8d4
	if (lastSep)
Packit 1fb8d4
	{
Packit 1fb8d4
		const char* name = lastSep + 1;
Packit 1fb8d4
		const size_t namelen = strlen(name);
Packit 1fb8d4
Packit 1fb8d4
		if ((namelen > 1) && (name[0] == '.') && (name[1] != '.'))
Packit 1fb8d4
			lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!(fileStat->st_mode & S_IWUSR))
Packit 1fb8d4
		lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
Packit 1fb8d4
Packit 1fb8d4
#ifdef _DARWIN_FEATURE_64_BIT_INODE
Packit 1fb8d4
	ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
Packit 1fb8d4
#else
Packit 1fb8d4
	ft = STAT_TIME_TO_FILETIME(fileStat->st_ctime);
Packit 1fb8d4
#endif
Packit 1fb8d4
	lpFindFileData->ftCreationTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
Packit 1fb8d4
	lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
Packit 1fb8d4
	ft = STAT_TIME_TO_FILETIME(fileStat->st_mtime);
Packit 1fb8d4
	lpFindFileData->ftLastWriteTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
Packit 1fb8d4
	lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
Packit 1fb8d4
	ft = STAT_TIME_TO_FILETIME(fileStat->st_atime);
Packit 1fb8d4
	lpFindFileData->ftLastAccessTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
Packit 1fb8d4
	lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
Packit 1fb8d4
	lpFindFileData->nFileSizeHigh = ((UINT64)fileStat->st_size) >> 32ULL;
Packit 1fb8d4
	lpFindFileData->nFileSizeLow = fileStat->st_size & 0xFFFFFFFF;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL isDir = FALSE;
Packit 1fb8d4
	struct stat fileStat;
Packit 1fb8d4
	WIN32_FILE_SEARCH* pFileSearch;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFindFileData || !lpFileName)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_BAD_ARGUMENTS);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
Packit Service 5a9772
	pFileSearch = (WIN32_FILE_SEARCH*)calloc(1, sizeof(WIN32_FILE_SEARCH));
Packit 1fb8d4
Packit 1fb8d4
	if (!pFileSearch)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (stat(lpFileName, &fileStat) >= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		isDir = (S_ISDIR(fileStat.st_mode) != 0);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
		errno = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (isDir)
Packit 1fb8d4
	{
Packit 1fb8d4
		pFileSearch->lpPath = _strdup(lpFileName);
Packit 1fb8d4
		pFileSearch->lpPattern = _strdup(".");
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		LPSTR p;
Packit 1fb8d4
		size_t index;
Packit 1fb8d4
		size_t length;
Packit 1fb8d4
		/* Separate lpFileName into path and pattern components */
Packit 1fb8d4
		p = strrchr(lpFileName, '/');
Packit 1fb8d4
Packit 1fb8d4
		if (!p)
Packit 1fb8d4
			p = strrchr(lpFileName, '\\');
Packit 1fb8d4
Packit 1fb8d4
		index = (p - lpFileName);
Packit 1fb8d4
		length = (p - lpFileName) + 1;
Packit Service 5a9772
		pFileSearch->lpPath = (LPSTR)malloc(length + 1);
Packit 1fb8d4
Packit 1fb8d4
		if (!pFileSearch->lpPath)
Packit 1fb8d4
		{
Packit 1fb8d4
			free(pFileSearch);
Packit 1fb8d4
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(pFileSearch->lpPath, lpFileName, length);
Packit 1fb8d4
		pFileSearch->lpPath[length] = '\0';
Packit 1fb8d4
		length = strlen(lpFileName) - index;
Packit Service 5a9772
		pFileSearch->lpPattern = (LPSTR)malloc(length + 1);
Packit 1fb8d4
Packit 1fb8d4
		if (!pFileSearch->lpPattern)
Packit 1fb8d4
		{
Packit 1fb8d4
			free(pFileSearch->lpPath);
Packit 1fb8d4
			free(pFileSearch);
Packit 1fb8d4
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(pFileSearch->lpPattern, &lpFileName[index + 1], length);
Packit 1fb8d4
		pFileSearch->lpPattern[length] = '\0';
Packit 1fb8d4
Packit 1fb8d4
		/* Check if the path is a directory */
Packit 1fb8d4
Packit 1fb8d4
		if (stat(pFileSearch->lpPath, &fileStat) < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			FindClose(pFileSearch);
Packit 1fb8d4
			SetLastError(map_posix_err(errno));
Packit 1fb8d4
			errno = 0;
Packit 1fb8d4
			return INVALID_HANDLE_VALUE; /* stat error */
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (S_ISDIR(fileStat.st_mode) == 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			FindClose(pFileSearch);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE; /* not a directory */
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Open directory for reading */
Packit 1fb8d4
	pFileSearch->pDir = opendir(pFileSearch->lpPath);
Packit 1fb8d4
Packit 1fb8d4
	if (!pFileSearch->pDir)
Packit 1fb8d4
	{
Packit 1fb8d4
		FindClose(pFileSearch);
Packit 1fb8d4
		SetLastError(map_posix_err(errno));
Packit 1fb8d4
		errno = 0;
Packit 1fb8d4
		return INVALID_HANDLE_VALUE; /* failed to open directory */
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData))
Packit 1fb8d4
	{
Packit 1fb8d4
		if (isDir)
Packit 1fb8d4
		{
Packit Service 5a9772
			const char* name = strrchr(lpFileName, '/');
Packit 1fb8d4
Packit 1fb8d4
			if (!name)
Packit 1fb8d4
				name = lpFileName;
Packit 1fb8d4
			else
Packit 1fb8d4
				name++;
Packit 1fb8d4
Packit 1fb8d4
			pFileSearch->lpPattern[0] = '*';
Packit Service 5a9772
			sprintf_s(lpFindFileData->cFileName, ARRAYSIZE(lpFindFileData->cFileName), "%s", name);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		return (HANDLE)pFileSearch;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	FindClose(pFileSearch);
Packit 1fb8d4
	return INVALID_HANDLE_VALUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL ConvertFindDataAToW(LPWIN32_FIND_DATAA lpFindFileDataA,
Packit 1fb8d4
                                LPWIN32_FIND_DATAW lpFindFileDataW)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	WCHAR* unicodeFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFindFileDataA || !lpFindFileDataW)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	lpFindFileDataW->dwFileAttributes = lpFindFileDataA->dwFileAttributes;
Packit 1fb8d4
	lpFindFileDataW->ftCreationTime = lpFindFileDataA->ftCreationTime;
Packit 1fb8d4
	lpFindFileDataW->ftLastAccessTime = lpFindFileDataA->ftLastAccessTime;
Packit 1fb8d4
	lpFindFileDataW->ftLastWriteTime = lpFindFileDataA->ftLastWriteTime;
Packit 1fb8d4
	lpFindFileDataW->nFileSizeHigh = lpFindFileDataA->nFileSizeHigh;
Packit 1fb8d4
	lpFindFileDataW->nFileSizeLow = lpFindFileDataA->nFileSizeLow;
Packit 1fb8d4
	lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0;
Packit 1fb8d4
	lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1;
Packit 1fb8d4
	unicodeFileName = NULL;
Packit 1fb8d4
	length = ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cFileName, -1, &unicodeFileName, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (length == 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (length > MAX_PATH)
Packit 1fb8d4
		length = MAX_PATH;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(lpFindFileDataW->cFileName, unicodeFileName, length * sizeof(WCHAR));
Packit 1fb8d4
	free(unicodeFileName);
Packit Service 5a9772
	length =
Packit Service 5a9772
	    ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cAlternateFileName, -1, &unicodeFileName, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (length == 0)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (length > 14)
Packit 1fb8d4
		length = 14;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(lpFindFileDataW->cAlternateFileName, unicodeFileName, length * sizeof(WCHAR));
Packit 1fb8d4
	free(unicodeFileName);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR utfFileName = NULL;
Packit 1fb8d4
	HANDLE h;
Packit 1fb8d4
	LPWIN32_FIND_DATAA fd = (LPWIN32_FIND_DATAA)calloc(1, sizeof(WIN32_FIND_DATAA));
Packit 1fb8d4
Packit 1fb8d4
	if (!fd)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &utfFileName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		free(fd);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	h = FindFirstFileA(utfFileName, fd);
Packit 1fb8d4
	free(utfFileName);
Packit 1fb8d4
Packit 1fb8d4
	if (h != INVALID_HANDLE_VALUE)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!ConvertFindDataAToW(fd, lpFindFileData))
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
			FindClose(h);
Packit 1fb8d4
			h = INVALID_HANDLE_VALUE;
Packit 1fb8d4
			goto out;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
out:
Packit 1fb8d4
	free(fd);
Packit 1fb8d4
	return h;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData,
Packit 1fb8d4
                        FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)
Packit 1fb8d4
{
Packit 1fb8d4
	return INVALID_HANDLE_VALUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE FindFirstFileExW(LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData,
Packit 1fb8d4
                        FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)
Packit 1fb8d4
{
Packit 1fb8d4
	return INVALID_HANDLE_VALUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
Packit 1fb8d4
{
Packit 1fb8d4
	WIN32_FILE_SEARCH* pFileSearch;
Packit 1fb8d4
	struct stat fileStat;
Packit 1fb8d4
	char* fullpath;
Packit 1fb8d4
	size_t pathlen;
Packit 1fb8d4
	size_t namelen;
Packit 1fb8d4
Packit 1fb8d4
	if (!hFindFile || !lpFindFileData)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (hFindFile == INVALID_HANDLE_VALUE)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
Packit Service 5a9772
	pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
Packit 1fb8d4
Packit 1fb8d4
	while ((pFileSearch->pDirent = readdir(pFileSearch->pDir)) != NULL)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (FilePatternMatchA(pFileSearch->pDirent->d_name, pFileSearch->lpPattern))
Packit 1fb8d4
		{
Packit 1fb8d4
			BOOL success;
Packit 1fb8d4
			strncpy(lpFindFileData->cFileName, pFileSearch->pDirent->d_name, MAX_PATH);
Packit 1fb8d4
			namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
Packit 1fb8d4
			pathlen = strlen(pFileSearch->lpPath);
Packit 1fb8d4
			fullpath = (char*)malloc(pathlen + namelen + 2);
Packit 1fb8d4
Packit 1fb8d4
			if (fullpath == NULL)
Packit 1fb8d4
			{
Packit 1fb8d4
				SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			memcpy(fullpath, pFileSearch->lpPath, pathlen);
Packit Service 5a9772
			/* Ensure path is terminated with a separator, but prevent
Packit Service 5a9772
			 * duplicate separators */
Packit Service 5a9772
			if (fullpath[pathlen - 1] != '/')
Packit Service 5a9772
				fullpath[pathlen++] = '/';
Packit Service 5a9772
			memcpy(fullpath + pathlen, pFileSearch->pDirent->d_name, namelen);
Packit Service 5a9772
			fullpath[pathlen + namelen] = 0;
Packit 1fb8d4
Packit 1fb8d4
			if (stat(fullpath, &fileStat) != 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(fullpath);
Packit 1fb8d4
				SetLastError(map_posix_err(errno));
Packit 1fb8d4
				errno = 0;
Packit 1fb8d4
				continue;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			/* Skip FIFO entries. */
Packit 1fb8d4
			if (S_ISFIFO(fileStat.st_mode))
Packit 1fb8d4
			{
Packit 1fb8d4
				free(fullpath);
Packit 1fb8d4
				continue;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			success = FindDataFromStat(fullpath, &fileStat, lpFindFileData);
Packit 1fb8d4
			free(fullpath);
Packit 1fb8d4
			return success;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	SetLastError(ERROR_NO_MORE_FILES);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData)
Packit 1fb8d4
{
Packit 1fb8d4
	LPWIN32_FIND_DATAA fd = (LPWIN32_FIND_DATAA)calloc(1, sizeof(WIN32_FIND_DATAA));
Packit 1fb8d4
Packit 1fb8d4
	if (!fd)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (FindNextFileA(hFindFile, fd))
Packit 1fb8d4
	{
Packit 1fb8d4
		if (!ConvertFindDataAToW(fd, lpFindFileData))
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
			free(fd);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		free(fd);
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(fd);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL FindClose(HANDLE hFindFile)
Packit 1fb8d4
{
Packit Service 5a9772
	WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
Packit 1fb8d4
Packit Service 5a9772
	/* Since INVALID_HANDLE_VALUE != NULL the analyzer guesses that there
Packit Service 5a9772
	 * is a initialized HANDLE that is not freed properly.
Packit Service 5a9772
	 * Disable this return to stop confusing the analyzer. */
Packit Service 5a9772
#ifndef __clang_analyzer__
Packit 1fb8d4
	if (!pFileSearch || (pFileSearch == INVALID_HANDLE_VALUE))
Packit 1fb8d4
		return FALSE;
Packit Service 5a9772
#endif
Packit 1fb8d4
Packit 1fb8d4
	free(pFileSearch->lpPath);
Packit 1fb8d4
	free(pFileSearch->lpPattern);
Packit 1fb8d4
Packit 1fb8d4
	if (pFileSearch->pDir)
Packit 1fb8d4
		closedir(pFileSearch->pDir);
Packit 1fb8d4
Packit 1fb8d4
	free(pFileSearch);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!mkdir(lpPathName, S_IRUSR | S_IWUSR | S_IXUSR))
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Packit 1fb8d4
{
Packit 1fb8d4
	char* utfPathName = NULL;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpPathName, -1, &utfPathName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
Packit 1fb8d4
	free(utfPathName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL RemoveDirectoryA(LPCSTR lpPathName)
Packit 1fb8d4
{
Packit 1fb8d4
	int ret = rmdir(lpPathName);
Packit 1fb8d4
Packit 1fb8d4
	if (ret != 0)
Packit 1fb8d4
		SetLastError(map_posix_err(errno));
Packit 1fb8d4
	else
Packit 1fb8d4
		SetLastError(STATUS_SUCCESS);
Packit 1fb8d4
Packit 1fb8d4
	return ret == 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL RemoveDirectoryW(LPCWSTR lpPathName)
Packit 1fb8d4
{
Packit 1fb8d4
	char* utfPathName = NULL;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpPathName, -1, &utfPathName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = RemoveDirectoryA(utfPathName);
Packit 1fb8d4
	free(utfPathName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
Packit 1fb8d4
{
Packit 1fb8d4
	struct stat st;
Packit 1fb8d4
	int ret;
Packit 1fb8d4
	ret = stat(lpNewFileName, &st);
Packit 1fb8d4
Packit 1fb8d4
	if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ret == 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_ALREADY_EXISTS);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_ACCESS_DENIED);
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = rename(lpExistingFileName, lpNewFileName);
Packit 1fb8d4
Packit 1fb8d4
	if (ret != 0)
Packit 1fb8d4
		SetLastError(map_posix_err(errno));
Packit 1fb8d4
Packit 1fb8d4
	return ret == 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR lpCExistingFileName;
Packit 1fb8d4
	LPSTR lpCNewFileName;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpExistingFileName, -1, &lpCExistingFileName, 0, NULL,
Packit 1fb8d4
	                       NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpNewFileName, -1, &lpCNewFileName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(lpCExistingFileName);
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ret = MoveFileExA(lpCExistingFileName, lpCNewFileName, dwFlags);
Packit 1fb8d4
	free(lpCNewFileName);
Packit 1fb8d4
	free(lpCExistingFileName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	return MoveFileExA(lpExistingFileName, lpNewFileName, 0);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
/* Extended API */
Packit 1fb8d4
Packit 1fb8d4
int UnixChangeFileMode(const char* filename, int flags)
Packit 1fb8d4
{
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
	mode_t fl = 0;
Packit 1fb8d4
	fl |= (flags & 0x4000) ? S_ISUID : 0;
Packit 1fb8d4
	fl |= (flags & 0x2000) ? S_ISGID : 0;
Packit 1fb8d4
	fl |= (flags & 0x1000) ? S_ISVTX : 0;
Packit 1fb8d4
	fl |= (flags & 0x0400) ? S_IRUSR : 0;
Packit 1fb8d4
	fl |= (flags & 0x0200) ? S_IWUSR : 0;
Packit 1fb8d4
	fl |= (flags & 0x0100) ? S_IXUSR : 0;
Packit 1fb8d4
	fl |= (flags & 0x0040) ? S_IRGRP : 0;
Packit 1fb8d4
	fl |= (flags & 0x0020) ? S_IWGRP : 0;
Packit 1fb8d4
	fl |= (flags & 0x0010) ? S_IXGRP : 0;
Packit 1fb8d4
	fl |= (flags & 0x0004) ? S_IROTH : 0;
Packit 1fb8d4
	fl |= (flags & 0x0002) ? S_IWOTH : 0;
Packit 1fb8d4
	fl |= (flags & 0x0001) ? S_IXOTH : 0;
Packit 1fb8d4
	return chmod(filename, fl);
Packit 1fb8d4
#else
Packit 1fb8d4
	int rc;
Packit 1fb8d4
	WCHAR* wfl = NULL;
Packit 1fb8d4
	int fl = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertToUnicode(CP_UTF8, 0, filename, -1, &wfl, 0) <= 0)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	/* Check for unsupported flags. */
Packit 1fb8d4
	if (flags & ~(_S_IREAD | _S_IWRITE))
Packit 1fb8d4
		WLog_WARN(TAG, "Unsupported file mode %d for _wchmod", flags);
Packit 1fb8d4
Packit 1fb8d4
	rc = _wchmod(wfl, flags);
Packit 1fb8d4
	free(wfl);
Packit 1fb8d4
	return rc;
Packit 1fb8d4
#endif
Packit 1fb8d4
}