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 NULL", GetKnownPathIdString(WINPR_ASSERTING_INT_CAST(
int,
id)));
395char* GetKnownSubPath(eKnownPathTypes
id,
const char* path)
397 char* knownPath = GetKnownPath(
id);
401 char* subPath = GetCombinedPath(knownPath, path);
406char* GetEnvironmentPath(
char* name)
411 nSize = GetEnvironmentVariableX(name, NULL, 0);
415 env = (LPSTR)malloc(nSize);
420 nStatus = GetEnvironmentVariableX(name, env, nSize);
422 if (nStatus != (nSize - 1))
432char* GetEnvironmentSubPath(
char* name,
const char* path)
435 char* subpath = NULL;
436 env = GetEnvironmentPath(name);
441 subpath = GetCombinedPath(env, path);
446char* GetCombinedPath(
const char* basePath,
const char* subPath)
449 char* subPathCpy = NULL;
450 size_t basePathLength = 0;
451 size_t subPathLength = 0;
454 basePathLength = strlen(basePath);
457 subPathLength = strlen(subPath);
459 const size_t length = basePathLength + subPathLength + 1;
460 char* path = (
char*)calloc(1, length + 1);
466 CopyMemory(path, basePath, basePathLength);
468 if (FAILED(PathCchConvertStyleA(path, basePathLength, PATH_STYLE_NATIVE)))
474 subPathCpy = _strdup(subPath);
479 if (FAILED(PathCchConvertStyleA(subPathCpy, subPathLength, PATH_STYLE_NATIVE)))
482 status = NativePathCchAppendA(path, length + 1, subPathCpy);
495BOOL PathMakePathA(LPCSTR path, WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpAttributes)
500 return (SHCreateDirectoryExA(NULL, path, lpAttributes) == ERROR_SUCCESS);
502 const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
513 if (!path || *path != delim)
518 if (!(dup = _strdup(path)))
522 p = (strlen(dup) > 3) && (dup[1] ==
':') && (dup[2] == delim)) ? &dup[3] : dup;
526 for (
char* p = dup; p;)
529 if ((p = strchr(p + 1, delim)))
532 if (mkdir(dup, 0777) != 0)
548BOOL PathMakePathW(LPCWSTR path, WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpAttributes)
553 return (SHCreateDirectoryExW(NULL, path, lpAttributes) == ERROR_SUCCESS);
555 const WCHAR wdelim = PathGetSeparatorW(PATH_STYLE_NATIVE);
556 const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
567 if (!path || *path != wdelim)
572 dup = ConvertWCharToUtf8Alloc(path, NULL);
577 p = (strlen(dup) > 3) && (dup[1] ==
':') && (dup[2] == delim)) ? &dup[3] : dup;
581 for (
char* p = dup; p;)
584 if ((p = strchr(p + 1, delim)))
587 if (mkdir(dup, 0777) != 0)
603#if !defined(_WIN32) || defined(_UWP)
605BOOL PathIsRelativeA(LPCSTR pszPath)
610 return pszPath[0] !=
'/';
613BOOL PathIsRelativeW(LPCWSTR pszPath)
615 LPSTR lpFileNameA = NULL;
621 lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
624 ret = PathIsRelativeA(lpFileNameA);
630BOOL PathFileExistsA(LPCSTR pszPath)
632 struct stat stat_info;
634 if (stat(pszPath, &stat_info) != 0)
640BOOL PathFileExistsW(LPCWSTR pszPath)
642 LPSTR lpFileNameA = NULL;
647 lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
651 ret = winpr_PathFileExists(lpFileNameA);
657BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
659 struct dirent* dp = NULL;
661 DIR* dir = opendir(pszPath);
667 while ((dp = readdir(dir)) != NULL)
669 if (strcmp(dp->d_name,
".") == 0 || strcmp(dp->d_name,
"..") == 0)
680BOOL PathIsDirectoryEmptyW(LPCWSTR pszPath)
682 LPSTR lpFileNameA = NULL;
686 lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
689 ret = PathIsDirectoryEmptyA(lpFileNameA);
697BOOL winpr_MoveFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
699 return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0);
702BOOL winpr_MoveFileEx(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
707 ret = stat(lpNewFileName, &st);
709 if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
713 SetLastError(ERROR_ALREADY_EXISTS);
719 if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
721 SetLastError(ERROR_ACCESS_DENIED);
726 ret = rename(lpExistingFileName, lpNewFileName);
729 SetLastError(map_posix_err(errno));
734 LPWSTR lpExistingFileNameW = NULL;
735 LPWSTR lpNewFileNameW = NULL;
737 if (!lpExistingFileName || !lpNewFileName)
740 lpExistingFileNameW = ConvertUtf8ToWCharAlloc(lpExistingFileName, NULL);
741 if (!lpExistingFileNameW)
743 lpNewFileNameW = ConvertUtf8ToWCharAlloc(lpNewFileName, NULL);
747 result = MoveFileExW(lpExistingFileNameW, lpNewFileNameW, dwFlags);
750 free(lpExistingFileNameW);
751 free(lpNewFileNameW);
756BOOL winpr_DeleteFile(
const char* lpFileName)
762 const int status = unlink(lpFileName);
763 return (status != -1) ? TRUE : FALSE;
765 LPWSTR lpFileNameW = NULL;
769 lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
774 result = DeleteFileW(lpFileNameW);
782BOOL winpr_RemoveDirectory(LPCSTR lpPathName)
785 int ret = rmdir(lpPathName);
788 SetLastError(map_posix_err(errno));
790 SetLastError(STATUS_SUCCESS);
794 LPWSTR lpPathNameW = NULL;
798 lpPathNameW = ConvertUtf8ToWCharAlloc(lpPathName, NULL);
803 result = RemoveDirectoryW(lpPathNameW);
811BOOL winpr_PathFileExists(
const char* pszPath)
816 return PathFileExistsA(pszPath);
818 WCHAR* pathW = ConvertUtf8ToWCharAlloc(pszPath, NULL);
824 result = PathFileExistsW(pathW);
831BOOL winpr_PathMakePath(
const char* path, LPSECURITY_ATTRIBUTES lpAttributes)
836 return PathMakePathA(path, lpAttributes);
838 WCHAR* pathW = ConvertUtf8ToWCharAlloc(path, NULL);
844 result = SHCreateDirectoryExW(NULL, pathW, lpAttributes) == ERROR_SUCCESS;