[winpr,path] implement normalize and IsRootOf functions

This commit is contained in:
akallabeth 2024-11-07 12:21:18 +01:00
parent 789ba52ea5
commit 0d02c8607b
No known key found for this signature in database
GPG Key ID: A49454A3FC909FD5
3 changed files with 128 additions and 45 deletions

View File

@ -342,6 +342,48 @@ extern "C"
WINPR_ATTR_MALLOC(free, 1)
WINPR_API char* GetCombinedPath(const char* basePath, const char* subPath);
/** @brief creates a normalized version of \b path
* Duplicate path delimiters and '.' in path are removed, '..' is resolved. The normalized
* path does not contain any of these.
*
* @param path The path to normalize
* @return A normalized version of \b path or \b NULL in case of an error
* @since version 3.10.0
*/
WINPR_ATTR_MALLOC(free, 1)
WINPR_API WCHAR* winpr_NormalizePathW(const WCHAR* path);
/** @brief creates a normalized version of \b path
* Duplicate path delimiters and '.' in path are removed, '..' is resolved. The normalized
* path does not contain any of these.
*
* @param path The path to normalize
* @return A normalized version of \b path or \b NULL in case of an error
* @since version 3.10.0
*/
WINPR_ATTR_MALLOC(free, 1)
WINPR_API char* winpr_NormalizePathA(const char* path);
/** @brief Checks if path \b root is the root of \b path
* Both paths are normalized first and then checked if \b root is a prefix of \b path.
*
* @param root The root path, must be an absolute path.
* @param path The path to check
* @return \b TRUE if \b path has \b root as parent
* @since version 3.10.0
*/
WINPR_API BOOL winpr_PathIsRootOfA(const char* root, const char* path);
/** @brief Checks if path \b root is the root of \b path
* Both paths are normalized first and then checked if \b root is a prefix of \b path
*
* @param root The root path, must be an absolute path.
* @param path The path to check
* @return \b TRUE if \b path has \b root as parent
* @since version 3.10.0
*/
WINPR_API BOOL winpr_PathIsRootOfW(const WCHAR* root, const WCHAR* path);
WINPR_API BOOL PathMakePathA(LPCSTR path, LPSECURITY_ATTRIBUTES lpAttributes);
WINPR_API BOOL PathMakePathW(LPCWSTR path, LPSECURITY_ATTRIBUTES lpAttributes);

View File

@ -21,12 +21,15 @@
#include <winpr/version.h>
#include <winpr/build-config.h>
#include <winpr/assert.h>
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/path.h>
#include <winpr/file.h>
#include <cwalk.h>
#define STR(x) #x
#define PATH_SLASH_CHR '/'
@ -1214,3 +1217,70 @@ char* winpr_GetConfigFilePath(BOOL system, const char* filename)
return path;
}
char* winpr_NormalizePathA(const char* path)
{
const size_t rc = cwk_path_normalize(path, NULL, 0);
if (rc == 0)
return NULL;
char* npath = calloc(rc + 2, sizeof(char));
if (!npath)
return NULL;
const size_t chk = cwk_path_normalize(path, npath, rc + 1);
WINPR_ASSERT(chk == rc);
if (chk != rc)
{
free(npath);
return NULL;
}
return npath;
}
WCHAR* winpr_NormalizePathW(const WCHAR* path)
{
char* utf = ConvertWCharToUtf8Alloc(path, NULL);
if (!utf)
return NULL;
char* nutf = winpr_NormalizePathA(utf);
free(utf);
if (!nutf)
return NULL;
WCHAR* wstr = ConvertUtf8ToWCharAlloc(nutf, NULL);
free(nutf);
return wstr;
}
BOOL winpr_PathIsRootOfA(const char* root, const char* path)
{
BOOL rc = FALSE;
if (!cwk_path_is_absolute(root))
return FALSE;
char* nroot = winpr_NormalizePathA(root);
char* npath = winpr_NormalizePathA(path);
if (npath && nroot)
{
const size_t len = strlen(root);
const size_t ilen = cwk_path_get_intersection(nroot, npath);
rc = len == ilen;
}
free(npath);
free(nroot);
return rc;
}
BOOL winpr_PathIsRootOfW(const WCHAR* root, const WCHAR* path)
{
if (!root || !path)
return FALSE;
char* utfroot = ConvertWCharToUtf8Alloc(root, NULL);
char* utfpath = ConvertWCharToUtf8Alloc(path, NULL);
BOOL rc = FALSE;
if (utfroot && utfpath)
rc = winpr_PathIsRootOfA(utfroot, utfpath);
free(utfroot);
free(utfpath);
return rc;
}

View File

@ -19,6 +19,7 @@
*/
#include <winpr/config.h>
#include <winpr/assert.h>
#include <winpr/build-config.h>
#include <stdio.h>
@ -26,6 +27,8 @@
#include <string.h>
#include <sys/stat.h>
#include <cwalk.h>
#include <winpr/crt.h>
#include <winpr/platform.h>
#include <winpr/file.h>
@ -447,53 +450,22 @@ char* GetEnvironmentSubPath(char* name, const char* path)
char* GetCombinedPath(const char* basePath, const char* subPath)
{
size_t length = 0;
HRESULT status = 0;
char* path = NULL;
char* subPathCpy = NULL;
size_t basePathLength = 0;
size_t subPathLength = 0;
if (basePath)
basePathLength = strlen(basePath);
if (subPath)
subPathLength = strlen(subPath);
length = basePathLength + subPathLength + 1;
path = (char*)calloc(1, length + 1);
const size_t len = cwk_path_join(basePath, subPath, NULL, 0);
if (len == 0)
return NULL;
char* path = calloc(len + 2, sizeof(char));
if (!path)
goto fail;
return NULL;
if (basePath)
CopyMemory(path, basePath, basePathLength);
if (FAILED(PathCchConvertStyleA(path, basePathLength, PATH_STYLE_NATIVE)))
goto fail;
if (!subPath)
return path;
subPathCpy = _strdup(subPath);
if (!subPathCpy)
goto fail;
if (FAILED(PathCchConvertStyleA(subPathCpy, subPathLength, PATH_STYLE_NATIVE)))
goto fail;
status = NativePathCchAppendA(path, length + 1, subPathCpy);
if (FAILED(status))
goto fail;
free(subPathCpy);
const size_t chk = cwk_path_join(basePath, subPath, path, len + 1);
WINPR_ASSERT(len == chk);
if (len != chk)
{
free(path);
return NULL;
}
return path;
fail:
free(path);
free(subPathCpy);
return NULL;
}
BOOL PathMakePathA(LPCSTR path, LPSECURITY_ATTRIBUTES lpAttributes)
@ -610,8 +582,7 @@ BOOL PathIsRelativeA(LPCSTR pszPath)
{
if (!pszPath)
return FALSE;
return pszPath[0] != '/';
return cwk_path_is_relative(pszPath);
}
BOOL PathIsRelativeW(LPCWSTR pszPath)