Add missing functions to WinPR
authorDavid PHAM-VAN <d.phamvan@inuvika.com>
Wed, 30 Nov 2016 21:47:06 +0000 (13:47 -0800)
committerDavid PHAM-VAN <d.phamvan@inuvika.com>
Mon, 13 Mar 2017 21:18:37 +0000 (14:18 -0700)
winpr/include/winpr/file.h
winpr/include/winpr/shell.h
winpr/libwinpr/file/file.c
winpr/libwinpr/file/file.h
winpr/libwinpr/file/generic.c
winpr/libwinpr/path/shell.c

index 7b050ab..f2610e7 100644 (file)
@@ -3,6 +3,7 @@
  * File Functions
  *
  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #define LOCKFILE_FAIL_IMMEDIATELY 1
 #define LOCKFILE_EXCLUSIVE_LOCK   2
 
+#define MOVEFILE_REPLACE_EXISTING 0x1
+#define MOVEFILE_COPY_ALLOWED 0x2
+#define MOVEFILE_DELAY_UNTIL_REBOOT 0x4
+#define MOVEFILE_WRITE_THROUGH 0x8
+#define MOVEFILE_CREATE_HARDLINK 0x10
+#define MOVEFILE_FAIL_IF_NOT_TRACKABLE 0x20
+
 typedef union _FILE_SEGMENT_ELEMENT
 {
        PVOID64 Buffer;
@@ -266,6 +274,34 @@ WINPR_API BOOL WriteFileGather(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[
 
 WINPR_API BOOL FlushFileBuffers(HANDLE hFile);
 
+typedef struct _WIN32_FILE_ATTRIBUTE_DATA
+{
+       DWORD    dwFileAttributes;
+       FILETIME ftCreationTime;
+       FILETIME ftLastAccessTime;
+       FILETIME ftLastWriteTime;
+       DWORD    nFileSizeHigh;
+       DWORD    nFileSizeLow;
+} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;
+
+typedef enum _GET_FILEEX_INFO_LEVELS
+{
+       GetFileExInfoStandard,
+       GetFileExMaxInfoLevel
+} GET_FILEEX_INFO_LEVELS;
+
+WINPR_API BOOL GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation);
+
+WINPR_API DWORD GetFileAttributesA(LPCSTR lpFileName);
+
+WINPR_API BOOL GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation);
+       
+WINPR_API DWORD GetFileAttributesW(LPCWSTR lpFileName);
+
+WINPR_API BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes);
+
+WINPR_API BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes);
+
 WINPR_API BOOL SetEndOfFile(HANDLE hFile);
 
 WINPR_API DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
@@ -314,6 +350,20 @@ WINPR_API HANDLE GetStdHandle(DWORD nStdHandle);
 WINPR_API BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle);
 WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle);
 
+WINPR_API BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
+       LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters);
+
+WINPR_API BOOL GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
+       LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters);
+
+WINPR_API BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags);
+
+WINPR_API BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags);
+
+WINPR_API BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName);
+
+WINPR_API BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName);
+
 #ifdef __cplusplus
 }
 #endif
@@ -326,6 +376,12 @@ WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOl
 #define FindNextFile           FindNextFileW
 #define CreateDirectory                CreateDirectoryW
 #define RemoveDirectory                RemoveDirectoryW
+#define GetFileAttributesEx    GetFileAttributesExW
+#define GetFileAttributes      GetFileAttributesW
+#define SetFileAttributes      SetFileAttributesW
+#define GetDiskFreeSpace       GetDiskFreeSpaceW
+#define MoveFileEx             MoveFileExW
+#define MoveFile               MoveFileW
 #else
 #define CreateFile             CreateFileA
 #define DeleteFile             DeleteFileA
@@ -334,6 +390,12 @@ WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOl
 #define FindNextFile           FindNextFileA
 #define CreateDirectory                CreateDirectoryA
 #define RemoveDirectory                RemoveDirectoryA
+#define GetFileAttributesEx    GetFileAttributesExA
+#define GetFileAttributes      GetFileAttributesA
+#define SetFileAttributes      SetFileAttributesA
+#define GetDiskFreeSpace       GetDiskFreeSpaceA
+#define MoveFileEx             MoveFileExA
+#define MoveFile               MoveFileA
 #endif
 
 /* Extra Functions */
index 5093925..ceb22e8 100644 (file)
@@ -3,6 +3,7 @@
  * Shell Functions
  *
  * Copyright 2015 Dell Software <Mike.McDonald@software.dell.com>
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -36,14 +37,20 @@ WINPR_API BOOL GetUserProfileDirectoryA(HANDLE hToken, LPSTR lpProfileDir, LPDWO
 
 WINPR_API BOOL GetUserProfileDirectoryW(HANDLE hToken, LPWSTR lpProfileDir, LPDWORD lpcchSize);
 
+WINPR_API BOOL PathIsDirectoryEmptyA(LPCSTR pszPath);
+
+WINPR_API BOOL PathIsDirectoryEmptyW(LPCWSTR pszPath);
+
 #ifdef __cplusplus
 }
 #endif
 
 #ifdef UNICODE
 #define GetUserProfileDirectory GetUserProfileDirectoryW
+#define PathIsDirectoryEmpty   PathIsDirectoryEmptyW
 #else
 #define GetUserProfileDirectory GetUserProfileDirectoryA
+#define PathIsDirectoryEmpty   PathIsDirectoryEmptyA
 #endif
 
 #endif
index d42e3e6..1846c8e 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright 2015 Thincast Technologies GmbH
  * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#ifdef ANDROID
+#include <sys/vfs.h>
+#else
+#include <sys/statvfs.h>
+#endif
+
+
 static BOOL FileIsHandled(HANDLE handle)
 {
        WINPR_FILE* pFile = (WINPR_FILE*) handle;
@@ -532,6 +540,51 @@ static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDispositio
        }
 }
 
+UINT32 map_posix_err(int fs_errno)
+{
+       UINT32 rc;
+
+       /* try to return NTSTATUS version of error code */
+
+       switch (fs_errno)
+       {
+               case 0:
+                       rc = STATUS_SUCCESS;
+                       break;
+
+               case EPERM:
+               case EACCES:
+                       rc = ERROR_ACCESS_DENIED;
+                       break;
+
+               case ENOENT:
+                       rc = ERROR_FILE_NOT_FOUND;
+                       break;
+
+               case EBUSY:
+                       rc = ERROR_BUSY_DRIVE;
+                       break;
+
+               case EEXIST:
+                       rc  = ERROR_FILE_EXISTS;
+                       break;
+
+               case EISDIR:
+                       rc = STATUS_FILE_IS_A_DIRECTORY;
+                       break;
+
+               case ENOTEMPTY:
+                       rc = STATUS_DIRECTORY_NOT_EMPTY;
+                       break;
+
+               default:
+                       rc = STATUS_UNSUCCESSFUL;
+                       break;
+       }
+       
+       return rc;
+}
+
 static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                                  DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
 {
@@ -695,6 +748,39 @@ BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
        return FALSE;
 }
 
+BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
+                                                                                        LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
+{
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#define STATVFS statvfs
+#elif defined(ANDROID)
+#define STATVFS statfs
+#else
+#define STATVFS statvfs
+#endif
+
+       struct STATVFS svfst;
+       STATVFS(lpRootPathName, &svfst);
+       *lpSectorsPerCluster = svfst.f_frsize;
+       *lpBytesPerSector = 1;
+       *lpNumberOfFreeClusters = svfst.f_bavail;
+       *lpTotalNumberOfClusters = svfst.f_blocks;
+       return TRUE;
+}
+
+BOOL GetDiskFreeSpaceW(LPCWSTR lpwRootPathName, LPDWORD lpSectorsPerCluster,
+                                                                                        LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
+{
+       LPSTR lpRootPathName;
+       BOOL ret;
+
+       ConvertFromUnicode(CP_UTF8, 0, lpwRootPathName, -1, &lpRootPathName, 0, NULL, NULL);
+       ret = GetDiskFreeSpaceA(lpRootPathName, lpSectorsPerCluster, lpBytesPerSector,
+                                                                                                        lpNumberOfFreeClusters, lpTotalNumberOfClusters);
+       free(lpRootPathName);
+       return ret;
+}
+
 #endif /* _WIN32 */
 
 #ifdef _UWP
index af09167..d7dfe1d 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright 2015 Armin Novak <armin.novak@thincast.com>
  * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -55,6 +56,8 @@ typedef struct winpr_file WINPR_FILE;
 
 HANDLE_CREATOR *GetFileHandleCreator(void);
 
+UINT32 map_posix_err(int fs_errno);
+
 #endif /* _WIN32 */
 
 #endif /* WINPR_FILE_PRIV_H */
index 1f2dc05..77a9a81 100644 (file)
@@ -4,6 +4,7 @@
  *
  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  * Copyright 2014 Hewlett-Packard Development Company, L.P.
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,6 +45,8 @@
 #include <assert.h>
 #include <pthread.h>
 #include <dirent.h>
+#include <libgen.h>
+#include <errno.h>
 
 #include <sys/un.h>
 #include <sys/stat.h>
  * http://code.google.com/p/kernel/wiki/AIOUserGuide
  */
 
+#define EPOCH_DIFF 11644473600LL
+#define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
+
+
 static wArrayList *_HandleCreators;
 
 static pthread_once_t _HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
@@ -461,6 +468,94 @@ BOOL FlushFileBuffers(HANDLE hFile)
        return FALSE;
 }
 
+BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+                                                                                                                                LPVOID lpFileInformation)
+{
+       LPWIN32_FILE_ATTRIBUTE_DATA fd = lpFileInformation;
+       WIN32_FIND_DATAA findFileData;
+       HANDLE hFind;
+
+       if (!(hFind = FindFirstFileA(lpFileName, &findFileData) == INVALID_HANDLE_VALUE))
+               FindClose(hFind);
+
+       fd->dwFileAttributes = findFileData.dwFileAttributes;
+       fd->ftCreationTime = findFileData.ftCreationTime;
+       fd->ftLastAccessTime = findFileData.ftLastAccessTime;
+       fd->ftLastWriteTime = findFileData.ftLastWriteTime;
+       fd->nFileSizeHigh = findFileData.nFileSizeHigh;
+       fd->nFileSizeLow = findFileData.nFileSizeLow;
+       return TRUE;
+}
+
+BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+                                                                                                                                LPVOID lpFileInformation)
+{
+       BOOL ret;
+       LPSTR lpCFileName;
+       ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL);
+       ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
+       free(lpCFileName);
+       return ret;
+}
+
+DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
+{
+       WIN32_FIND_DATAA findFileData;
+       HANDLE hFind;
+
+       if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
+               return INVALID_FILE_ATTRIBUTES;
+
+       FindClose(hFind);
+       return findFileData.dwFileAttributes;
+}
+
+DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
+{
+       DWORD ret;
+       LPSTR lpCFileName;
+       ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL);
+       ret = GetFileAttributesA(lpCFileName);
+       free(lpCFileName);
+       return ret;
+}
+
+BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
+{
+       struct stat st;
+
+       if (stat(lpFileName, &st) != 0)
+       {
+               return FALSE;
+       }
+
+       if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+       {
+               st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+       }
+       else
+       {
+               st.st_mode |= S_IWUSR;
+       }
+
+       if (chmod(lpFileName, st.st_mode) != 0)
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
+{
+       BOOL ret;
+       LPSTR lpCFileName;
+       ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL);
+       ret = SetFileAttributesA(lpCFileName,dwFileAttributes);
+       free(lpCFileName);
+       return ret;
+}
+
 BOOL SetEndOfFile(HANDLE hFile)
 {
        ULONG Type;
@@ -816,17 +911,88 @@ BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttribu
 
 BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
 {
-       return FALSE;
+       char* utfPathName = NULL;
+       BOOL ret;
+
+       ConvertFromUnicode(CP_UTF8, 0, lpPathName, -1, &utfPathName, 0, NULL, NULL);
+       ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
+       free(utfPathName);
+       return ret;
 }
 
 BOOL RemoveDirectoryA(LPCSTR lpPathName)
 {
-       return (rmdir(lpPathName) == 0);
+       int ret = rmdir(lpPathName);
+       if (ret != 0)
+               SetLastError(map_posix_err(errno));
+       else
+               SetLastError(STATUS_SUCCESS);
+       return ret == 0;
 }
 
 BOOL RemoveDirectoryW(LPCWSTR lpPathName)
 {
-       return FALSE;
+       char* utfPathName = NULL;
+       BOOL ret;
+
+       ConvertFromUnicode(CP_UTF8, 0, lpPathName, -1, &utfPathName, 0, NULL, NULL);
+       ret = RemoveDirectoryA(utfPathName);
+       free(utfPathName);
+       return ret;
+}
+
+BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
+{
+       struct stat st;
+       int ret;
+       ret = stat(lpNewFileName, &st);
+
+       if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
+       {
+               if (ret == 0)
+               {
+                       SetLastError(ERROR_ALREADY_EXISTS);
+                       return FALSE;
+               }
+       }
+       else
+       {
+               if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
+               {
+                       SetLastError(ERROR_ACCESS_DENIED);
+                       return FALSE;
+               }
+       }
+
+       ret = rename(lpExistingFileName, lpNewFileName);
+
+       if (ret != 0)
+               SetLastError(map_posix_err(errno));
+
+       return ret == 0;
+}
+
+BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
+{
+       LPSTR lpCExistingFileName;
+       LPSTR lpCNewFileName;
+       BOOL ret;
+       ConvertFromUnicode(CP_UTF8, 0, lpExistingFileName, -1, &lpCExistingFileName, 0, NULL, NULL);
+       ConvertFromUnicode(CP_UTF8, 0, lpNewFileName, -1, &lpCNewFileName, 0, NULL, NULL);
+       ret = MoveFileExA(lpCExistingFileName, lpCNewFileName, dwFlags);
+       free(lpCNewFileName);
+       free(lpCExistingFileName);
+       return ret;
+}
+
+BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
+{
+       return MoveFileExA(lpExistingFileName, lpNewFileName, 0);
+}
+
+BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
+{
+       return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
 }
 
 #endif
index 386cac3..785197f 100644 (file)
@@ -3,6 +3,7 @@
  * Path Functions
  *
  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -43,6 +44,7 @@
 #include <Shlobj.h>
 #else
 #include <errno.h>
+#include <dirent.h>
 #endif
 
 static char* GetPath_XDG_CONFIG_HOME(void);
@@ -505,9 +507,54 @@ BOOL PathFileExistsA(LPCSTR pszPath)
 
 BOOL PathFileExistsW(LPCWSTR pszPath)
 {
-       return FALSE;
+       LPSTR lpFileNameA = NULL;
+       BOOL ret;
+
+       if (ConvertFromUnicode(CP_UTF8, 0, pszPath, -1, &lpFileNameA, 0, NULL, NULL) < 1)
+               return FALSE;
+
+       ret = PathFileExistsA(lpFileNameA);
+       free (lpFileNameA);
+
+       return ret;
 }
 
+BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
+{
+       struct dirent *dp;
+       int empty = 1;
+
+       DIR *dir = opendir(pszPath);
+       if (dir == NULL) //Not a directory or doesn't exist
+               return 1;
+
+       while ((dp = readdir(dir)) != NULL) {
+               if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+                       continue;    /* Skip . and .. */
+
+               empty = 0;
+               break;
+       }
+       closedir(dir);
+       return empty;
+}
+
+
+BOOL PathIsDirectoryEmptyW(LPCWSTR pszPath)
+{
+       LPSTR lpFileNameA = NULL;
+       BOOL ret;
+
+       if (ConvertFromUnicode(CP_UTF8, 0, pszPath, -1, &lpFileNameA, 0, NULL, NULL) < 1)
+               return FALSE;
+
+       ret = PathIsDirectoryEmptyA(lpFileNameA);
+       free (lpFileNameA);
+
+       return ret;
+}
+
+
 #else
 
 #ifdef _WIN32