0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-19 19:42:24 +02:00

misc/path_utils: normalize win32 paths

This commit is contained in:
Kacper Michajłow 2024-05-05 18:50:38 +02:00
parent 1d640c9887
commit 053d971507
4 changed files with 63 additions and 2 deletions

View File

@ -495,6 +495,11 @@ endif
features += {'win32-desktop': win32 and not uwp.found()}
if features['win32-desktop']
pathcch = cc.find_library('pathcch', required: false)
features += {'pathcch': pathcch.found()}
if features['pathcch']
dependencies += pathcch
endif
win32_desktop_libs = [cc.find_library('avrt'),
cc.find_library('dwmapi'),
cc.find_library('gdi32'),

View File

@ -34,6 +34,11 @@
#include "misc/ctype.h"
#include "misc/path_utils.h"
#if defined(HAVE_PATHCCH) && HAVE_PATHCCH
#include <windows.h>
#include <pathcch.h>
#endif
char *mp_basename(const char *path)
{
char *s;
@ -164,7 +169,34 @@ char *mp_normalize_path(void *talloc_ctx, const char *path)
path = mp_path_join(talloc_ctx, cwd, path);
}
#if HAVE_DOS_PATHS
#if defined(HAVE_PATHCCH) && HAVE_PATHCCH
wchar_t *pathw = mp_from_utf8(NULL, path);
wchar_t *read = pathw, *write = pathw;
wchar_t prev = '\0';
// preserve leading double backslashes
if (read[0] == '\\' && read[1] == '\\') {
prev = '\\';
write += 2;
read += 2;
}
wchar_t curr;
while ((curr = *read)) {
if (curr == '/')
curr = '\\';
if (curr != '\\' || prev != '\\')
*write++ = curr;
prev = curr;
read++;
}
*write = '\0';
size_t max_size = wcslen(pathw) + 1;
wchar_t *pathc = talloc_array(NULL, wchar_t, max_size);
HRESULT hr = PathCchCanonicalizeEx(pathc, max_size, pathw, PATHCCH_ALLOW_LONG_PATHS);
char *ret = SUCCEEDED(hr) ? mp_to_utf8(talloc_ctx, pathc) : talloc_strdup(talloc_ctx, path);
talloc_free(pathw);
talloc_free(pathc);
return ret;
#elif HAVE_DOS_PATHS
return talloc_strdup(talloc_ctx, path);
#else
char *result = talloc_strdup(talloc_ctx, "");

View File

@ -53,6 +53,9 @@ endif
if features['win32-desktop']
test_utils_deps += cc.find_library('imm32')
test_utils_deps += cc.find_library('ntdll')
if features['pathcch']
test_utils_deps += cc.find_library('pathcch')
endif
endif
test_utils_objects = libmpv.extract_objects(test_utils_files)
test_utils = static_library('test-utils', 'test_utils.c', include_directories: incdir,

View File

@ -81,15 +81,36 @@ int main(void)
#endif
TEST_NORMALIZE("https://foo", "https://foo");
#if !HAVE_DOS_PATHS
TEST_NORMALIZE("/foo", "/foo");
#endif
void *ctx = talloc_new(NULL);
bstr dst = bstr0(mp_getcwd(ctx));
bstr_xappend(ctx, &dst, bstr0("/foo"));
#if HAVE_DOS_PATHS
char *p = dst.start;
while (*p) {
*p = *p == '/' ? '\\' : *p;
p++;
}
#endif
TEST_NORMALIZE(dst.start, "foo");
talloc_free(ctx);
#if (!HAVE_DOS_PATHS)
#if HAVE_DOS_PATHS
TEST_NORMALIZE("C:\\foo\\baz", "C:/foo/bar/../baz");
TEST_NORMALIZE("C:\\", "C:/foo/../..");
TEST_NORMALIZE("C:\\foo\\baz", "C:/foo/bar/./../baz");
TEST_NORMALIZE("C:\\foo\\bar\\baz", "C:/foo//bar/./baz");
TEST_NORMALIZE("C:\\foo\\bar\\baz", "C:/foo\\./bar\\/baz");
TEST_NORMALIZE("C:\\file.mkv", "\\\\?\\C:\\folder\\..\\file.mkv");
TEST_NORMALIZE("C:\\dir", "\\\\?\\C:\\dir\\subdir\\..\\.");
TEST_NORMALIZE("D:\\newfile.txt", "\\\\?\\D:\\\\new\\subdir\\..\\..\\newfile.txt");
TEST_NORMALIZE("\\\\server\\share\\path", "\\\\?\\UNC/server/share/path/.");
TEST_NORMALIZE("C:\\", "C:/.");
TEST_NORMALIZE("C:\\", "C:/../");
#else
TEST_NORMALIZE("/foo/bar", "/foo//bar");
TEST_NORMALIZE("/foo/bar", "/foo///bar");
TEST_NORMALIZE("/foo/bar", "/foo/bar/");