21#include <winpr/config.h>
22#include <winpr/build-config.h>
30#include <winpr/platform.h>
31#include <winpr/file.h>
32#include <winpr/tchar.h>
33#include <winpr/environment.h>
35#include <winpr/path.h>
36#include <winpr/wlog.h>
38#include "../file/file.h"
41#define TAG WINPR_TAG("path.shell")
55static char* GetPath_XDG_CONFIG_HOME(
void);
56static char* GetPath_XDG_RUNTIME_DIR(
void);
63#if defined(WIN32) && !defined(_UWP)
65static char* win_get_known_folder(REFKNOWNFOLDERID
id, BOOL currentUser)
68 HANDLE handle = currentUser ? NULL : (HANDLE)-1;
69 if (FAILED(SHGetKnownFolderPath(
id, 0, handle, &wpath)))
75 char* path = ConvertWCharToUtf8Alloc(wpath, NULL);
86char* GetEnvAlloc(LPCSTR lpName)
92 nSize = GetEnvironmentVariableX(lpName, NULL, 0);
101 nStatus = GetEnvironmentVariableX(lpName, env, nSize);
103 if (nStatus != (nSize - 1))
113static char* GetPath_HOME(
void)
117 path = GetEnvAlloc(
"UserProfile");
118#elif defined(__IOS__)
119 path = ios_get_home();
121 path = GetEnvAlloc(
"HOME");
126static char* GetPath_TEMP(
void)
130 path = GetEnvAlloc(
"TEMP");
131#elif defined(__IOS__)
132 path = ios_get_temp();
134 path = GetEnvAlloc(
"TMPDIR");
137 path = _strdup(
"/tmp");
143static char* GetPath_XDG_DATA_HOME(
void)
146#if defined(WIN32) || defined(__IOS__)
147 path = GetPath_XDG_CONFIG_HOME();
159 path = GetEnvAlloc(
"XDG_DATA_HOME");
164 home = GetPath_HOME();
169 size = strlen(home) + strlen(
"/.local/share") + 1;
170 path = (
char*)malloc(size);
178 (void)sprintf_s(path, size,
"%s%s", home,
"/.local/share");
184static char* GetPath_XDG_CONFIG_HOME(
void)
187#if defined(WIN32) && !defined(_UWP)
189 path = win_get_known_folder(&FOLDERID_RoamingAppData, TRUE);
191#elif defined(__IOS__)
192 path = ios_get_data();
204 path = GetEnvAlloc(
"XDG_CONFIG_HOME");
209 home = GetPath_HOME();
212 home = GetPath_TEMP();
217 size = strlen(home) + strlen(
"/.config") + 1;
218 path = (
char*)malloc(size);
226 (void)sprintf_s(path, size,
"%s%s", home,
"/.config");
232static char* GetPath_SYSTEM_CONFIG_HOME(
void)
235#if defined(WIN32) && !defined(_UWP)
237 path = win_get_known_folder(&FOLDERID_ProgramData, FALSE);
239#elif defined(__IOS__)
240 path = ios_get_data();
242 path = _strdup(WINPR_INSTALL_SYSCONFDIR);
247static char* GetPath_XDG_CACHE_HOME(
void)
252 char* home = GetPath_XDG_RUNTIME_DIR();
256 path = GetCombinedPath(home,
"cache");
258 if (!winpr_PathFileExists(path))
259 if (!winpr_PathMakePath(path, NULL))
265#elif defined(__IOS__)
266 path = ios_get_cache();
277 path = GetEnvAlloc(
"XDG_CACHE_HOME");
282 char* home = GetPath_HOME();
287 size = strlen(home) + strlen(
"/.cache") + 1;
288 path = (
char*)malloc(size);
296 (void)sprintf_s(path, size,
"%s%s", home,
"/.cache");
302char* GetPath_XDG_RUNTIME_DIR(
void)
305#if defined(WIN32) && !defined(_UWP)
307 path = win_get_known_folder(&FOLDERID_LocalAppData, TRUE);
341 path = GetEnvAlloc(
"XDG_RUNTIME_DIR");
347 path = GetPath_TEMP();
351char* GetKnownPath(eKnownPathTypes
id)
357 case KNOWN_PATH_HOME:
358 path = GetPath_HOME();
361 case KNOWN_PATH_TEMP:
362 path = GetPath_TEMP();
365 case KNOWN_PATH_XDG_DATA_HOME:
366 path = GetPath_XDG_DATA_HOME();
369 case KNOWN_PATH_XDG_CONFIG_HOME:
370 path = GetPath_XDG_CONFIG_HOME();
373 case KNOWN_PATH_XDG_CACHE_HOME:
374 path = GetPath_XDG_CACHE_HOME();
377 case KNOWN_PATH_XDG_RUNTIME_DIR:
378 path = GetPath_XDG_RUNTIME_DIR();
381 case KNOWN_PATH_SYSTEM_CONFIG_HOME:
382 path = GetPath_SYSTEM_CONFIG_HOME();
391 WLog_WARN(TAG,
"Path %s is %p", GetKnownPathIdString(WINPR_ASSERTING_INT_CAST(
int,
id)),
396char* GetKnownSubPath(eKnownPathTypes
id,
const char* path)
398 char* knownPath = GetKnownPath(
id);
402 char* subPath = GetCombinedPath(knownPath, path);
407char* GetEnvironmentPath(
char* name)
412 nSize = GetEnvironmentVariableX(name, NULL, 0);
416 env = (LPSTR)malloc(nSize);
421 nStatus = GetEnvironmentVariableX(name, env, nSize);
423 if (nStatus != (nSize - 1))
433char* GetEnvironmentSubPath(
char* name,
const char* path)
436 char* subpath = NULL;
437 env = GetEnvironmentPath(name);
442 subpath = GetCombinedPath(env, path);
447char* GetCombinedPath(
const char* basePath,
const char* subPath)
452 char* subPathCpy = NULL;
453 size_t basePathLength = 0;
454 size_t subPathLength = 0;
457 basePathLength = strlen(basePath);
460 subPathLength = strlen(subPath);
462 length = basePathLength + subPathLength + 1;
463 path = (
char*)calloc(1, length + 1);
469 CopyMemory(path, basePath, basePathLength);
471 if (FAILED(PathCchConvertStyleA(path, basePathLength, PATH_STYLE_NATIVE)))
477 subPathCpy = _strdup(subPath);
482 if (FAILED(PathCchConvertStyleA(subPathCpy, subPathLength, PATH_STYLE_NATIVE)))
485 status = NativePathCchAppendA(path, length + 1, subPathCpy);
498BOOL PathMakePathA(LPCSTR path, WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpAttributes)
503 return (SHCreateDirectoryExA(NULL, path, lpAttributes) == ERROR_SUCCESS);
505 const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
516 if (!path || *path != delim)
521 if (!(dup = _strdup(path)))
525 p = (strlen(dup) > 3) && (dup[1] ==
':') && (dup[2] == delim)) ? &dup[3] : dup;
529 for (
char* p = dup; p;)
532 if ((p = strchr(p + 1, delim)))
535 if (mkdir(dup, 0777) != 0)
551BOOL PathMakePathW(LPCWSTR path, WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpAttributes)
556 return (SHCreateDirectoryExW(NULL, path, lpAttributes) == ERROR_SUCCESS);
558 const WCHAR wdelim = PathGetSeparatorW(PATH_STYLE_NATIVE);
559 const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
570 if (!path || *path != wdelim)
575 dup = ConvertWCharToUtf8Alloc(path, NULL);
580 p = (strlen(dup) > 3) && (dup[1] ==
':') && (dup[2] == delim)) ? &dup[3] : dup;
584 for (
char* p = dup; p;)
587 if ((p = strchr(p + 1, delim)))
590 if (mkdir(dup, 0777) != 0)
606#if !defined(_WIN32) || defined(_UWP)
608BOOL PathIsRelativeA(LPCSTR pszPath)
613 return pszPath[0] !=
'/';
616BOOL PathIsRelativeW(LPCWSTR pszPath)
618 LPSTR lpFileNameA = NULL;
624 lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
627 ret = PathIsRelativeA(lpFileNameA);
633BOOL PathFileExistsA(LPCSTR pszPath)
635 struct stat stat_info;
637 if (stat(pszPath, &stat_info) != 0)
643BOOL PathFileExistsW(LPCWSTR pszPath)
645 LPSTR lpFileNameA = NULL;
650 lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
654 ret = winpr_PathFileExists(lpFileNameA);
660BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
662 struct dirent* dp = NULL;
664 DIR* dir = opendir(pszPath);
670 while ((dp = readdir(dir)) != NULL)
672 if (strcmp(dp->d_name,
".") == 0 || strcmp(dp->d_name,
"..") == 0)
683BOOL PathIsDirectoryEmptyW(LPCWSTR pszPath)
685 LPSTR lpFileNameA = NULL;
689 lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
692 ret = PathIsDirectoryEmptyA(lpFileNameA);
700BOOL winpr_MoveFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
702 return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0);
705BOOL winpr_MoveFileEx(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
710 ret = stat(lpNewFileName, &st);
712 if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
716 SetLastError(ERROR_ALREADY_EXISTS);
722 if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
724 SetLastError(ERROR_ACCESS_DENIED);
729 ret = rename(lpExistingFileName, lpNewFileName);
732 SetLastError(map_posix_err(errno));
737 LPWSTR lpExistingFileNameW = NULL;
738 LPWSTR lpNewFileNameW = NULL;
740 if (!lpExistingFileName || !lpNewFileName)
743 lpExistingFileNameW = ConvertUtf8ToWCharAlloc(lpExistingFileName, NULL);
744 if (!lpExistingFileNameW)
746 lpNewFileNameW = ConvertUtf8ToWCharAlloc(lpNewFileName, NULL);
750 result = MoveFileExW(lpExistingFileNameW, lpNewFileNameW, dwFlags);
753 free(lpExistingFileNameW);
754 free(lpNewFileNameW);
759BOOL winpr_DeleteFile(
const char* lpFileName)
765 const int status = unlink(lpFileName);
766 return (status != -1) ? TRUE : FALSE;
768 LPWSTR lpFileNameW = NULL;
772 lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
777 result = DeleteFileW(lpFileNameW);
785BOOL winpr_RemoveDirectory(LPCSTR lpPathName)
788 int ret = rmdir(lpPathName);
791 SetLastError(map_posix_err(errno));
793 SetLastError(STATUS_SUCCESS);
797 LPWSTR lpPathNameW = NULL;
801 lpPathNameW = ConvertUtf8ToWCharAlloc(lpPathName, NULL);
806 result = RemoveDirectoryW(lpPathNameW);
814BOOL winpr_PathFileExists(
const char* pszPath)
819 return PathFileExistsA(pszPath);
821 WCHAR* pathW = ConvertUtf8ToWCharAlloc(pszPath, NULL);
827 result = PathFileExistsW(pathW);
834BOOL winpr_PathMakePath(
const char* path, LPSECURITY_ATTRIBUTES lpAttributes)
839 return PathMakePathA(path, lpAttributes);
841 WCHAR* pathW = ConvertUtf8ToWCharAlloc(path, NULL);
847 result = SHCreateDirectoryExW(NULL, pathW, lpAttributes) == ERROR_SUCCESS;