122 lines
2.9 KiB
C
122 lines
2.9 KiB
C
/*
|
|
wpathconv: static functions for windows file path conversions
|
|
|
|
This file is intended to be included in libcompat sources for internal use.
|
|
It is separated out to be able to split off the dlopen functions into a
|
|
separate libcompat. It is just a code fragment.
|
|
|
|
copyright 2007-2019 by the mpg123 project - free software under the terms of the LGPL 2.1
|
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
|
initially written by JonY
|
|
*/
|
|
|
|
#ifndef WINDOWS_UWP
|
|
|
|
#ifdef WANT_WIN32_UNICODE
|
|
|
|
/* Convert unix UTF-8 (or ASCII) paths to Windows wide character paths. */
|
|
static wchar_t* u2wpath(const char *upath)
|
|
{
|
|
wchar_t* wpath, *p;
|
|
if(!upath || INT123_win32_utf8_wide(upath, &wpath, NULL) < 1)
|
|
return NULL;
|
|
for(p=wpath; *p; ++p)
|
|
if(*p == L'/')
|
|
*p = L'\\';
|
|
return wpath;
|
|
}
|
|
|
|
#ifndef HIDE_w2upath
|
|
/* Convert Windows wide character paths to unix UTF-8. */
|
|
static char* w2upath(const wchar_t *wpath)
|
|
{
|
|
char* upath, *p;
|
|
if(!wpath || INT123_win32_wide_utf8(wpath, &upath, NULL) < 1)
|
|
return NULL;
|
|
for(p=upath; *p; ++p)
|
|
if(*p == '\\')
|
|
*p = '/';
|
|
return upath;
|
|
}
|
|
#endif
|
|
|
|
/* An absolute path that is too long and not already marked with
|
|
\\?\ can be marked as a long one and still work. */
|
|
static int wpath_need_elongation(wchar_t *wpath)
|
|
{
|
|
if( wpath && !PathIsRelativeW(wpath)
|
|
&& wcslen(wpath) > MAX_PATH-1
|
|
&& wcsncmp(L"\\\\?\\", wpath, 4) )
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* Take any wide windows path and turn it into a path that is allowed
|
|
to be longer than MAX_PATH, if it is not already. */
|
|
static wchar_t* wlongpath(wchar_t *wpath)
|
|
{
|
|
size_t len, plen;
|
|
const wchar_t *prefix = L"";
|
|
wchar_t *wlpath = NULL;
|
|
if(!wpath)
|
|
return NULL;
|
|
|
|
/* Absolute paths that do not start with \\?\ get that prepended
|
|
to allow them being long. */
|
|
if(!PathIsRelativeW(wpath) && wcsncmp(L"\\\\?\\", wpath, 4))
|
|
{
|
|
if(wcslen(wpath) >= 2 && PathIsUNCW(wpath))
|
|
{
|
|
/* \\server\path -> \\?\UNC\server\path */
|
|
prefix = L"\\\\?\\UNC";
|
|
++wpath; /* Skip the first \. */
|
|
}
|
|
else /* c:\some/path -> \\?\c:\some\path */
|
|
prefix = L"\\\\?\\";
|
|
}
|
|
plen = wcslen(prefix);
|
|
len = plen + wcslen(wpath);
|
|
wlpath = malloc(len+1*sizeof(wchar_t));
|
|
if(wlpath)
|
|
{
|
|
/* Brute force memory copying, swprintf is too dandy. */
|
|
memcpy(wlpath, prefix, sizeof(wchar_t)*plen);
|
|
memcpy(wlpath+plen, wpath, sizeof(wchar_t)*(len-plen));
|
|
wlpath[len] = 0;
|
|
}
|
|
return wlpath;
|
|
}
|
|
|
|
/* Convert unix path to wide windows path, optionally marking
|
|
it as long path if necessary. */
|
|
static wchar_t* u2wlongpath(const char *upath)
|
|
{
|
|
wchar_t *wpath = NULL;
|
|
wchar_t *wlpath = NULL;
|
|
wpath = u2wpath(upath);
|
|
if(wpath_need_elongation(wpath))
|
|
{
|
|
wlpath = wlongpath(wpath);
|
|
free(wpath);
|
|
wpath = wlpath;
|
|
}
|
|
return wpath;
|
|
}
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
static wchar_t* u2wlongpath(const char *upath)
|
|
{
|
|
wchar_t* wpath, *p;
|
|
if (!upath || INT123_win32_utf8_wide(upath, &wpath, NULL) < 1)
|
|
return NULL;
|
|
for (p = wpath; *p; ++p)
|
|
if (*p == L'/')
|
|
*p = L'\\';
|
|
return wpath;
|
|
}
|
|
|
|
#endif
|