| From afe9fc7a1ffad8f5054050ecdc79203359c55d60 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= |
| <alexey.pawlow@gmail.com> |
| Date: Thu, 17 Jun 2021 18:51:47 +0530 |
| Subject: [PATCH 039/N] mingw use posix getpath |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| Co-authored-by: Алексей <alexey.pawlow@gmail.com> |
| Co-authored-by: Christoph Reiter <reiter.christoph@gmail.com> |
| --- |
| Include/cpython/fileutils.h | 3 +- |
| Include/pylifecycle.h | 2 +- |
| Modules/getpath.c | 131 +++++++++++++++++++++++++++++++++--- |
| Modules/posixmodule.c | 2 +- |
| Python/dynload_win.c | 2 + |
| Python/fileutils.c | 22 +++++- |
| 6 files changed, 146 insertions(+), 16 deletions(-) |
| |
| diff --git a/Include/cpython/fileutils.h b/Include/cpython/fileutils.h |
| index e79d03e..c222833 100644 |
| --- a/Include/cpython/fileutils.h |
| +++ b/Include/cpython/fileutils.h |
| @@ -136,9 +136,8 @@ PyAPI_FUNC(wchar_t*) _Py_wrealpath( |
| size_t resolved_path_len); |
| #endif |
| |
| -#ifndef MS_WINDOWS |
| PyAPI_FUNC(int) _Py_isabs(const wchar_t *path); |
| -#endif |
| +PyAPI_FUNC(int) _Py_issep(const wchar_t ch); |
| |
| PyAPI_FUNC(int) _Py_abspath(const wchar_t *path, wchar_t **abspath_p); |
| |
| diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h |
| index 4eec669..b34f110 100644 |
| --- a/Include/pylifecycle.h |
| +++ b/Include/pylifecycle.h |
| @@ -55,7 +55,7 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); |
| PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); |
| PyAPI_FUNC(wchar_t *) Py_GetPath(void); |
| PyAPI_FUNC(void) Py_SetPath(const wchar_t *); |
| -#ifdef MS_WINDOWS |
| +#ifdef _MSC_VER |
| int _Py_CheckPython3(void); |
| #endif |
| |
| diff --git a/Modules/getpath.c b/Modules/getpath.c |
| index 728ecad..3010182 100644 |
| --- a/Modules/getpath.c |
| +++ b/Modules/getpath.c |
| @@ -13,6 +13,11 @@ |
| # include <mach-o/dyld.h> |
| #endif |
| |
| +#ifdef MS_WINDOWS |
| +#include <windows.h> |
| +#include <shlwapi.h> |
| +#endif |
| + |
| /* Search in some common locations for the associated Python libraries. |
| * |
| * Two directories must be found, the platform independent directory |
| @@ -129,6 +134,7 @@ typedef struct { |
| wchar_t *prefix_macro; /* PREFIX macro */ |
| wchar_t *exec_prefix_macro; /* EXEC_PREFIX macro */ |
| wchar_t *vpath_macro; /* VPATH macro */ |
| + wchar_t *dll_path; /* DLL Path */ |
| |
| wchar_t *lib_python; /* <platlibdir> / "pythonX.Y" */ |
| |
| @@ -146,7 +152,7 @@ typedef struct { |
| } PyCalculatePath; |
| |
| static const wchar_t delimiter[2] = {DELIM, '\0'}; |
| -static const wchar_t separator[2] = {SEP, '\0'}; |
| +static wchar_t separator[2] = {SEP, '\0'}; |
| |
| |
| /* Get file status. Encode the path to the locale encoding. */ |
| @@ -170,7 +176,7 @@ static void |
| reduce(wchar_t *dir) |
| { |
| size_t i = wcslen(dir); |
| - while (i > 0 && dir[i] != SEP) { |
| + while (i > 0 && !_Py_issep(dir[i])) { |
| --i; |
| } |
| dir[i] = '\0'; |
| @@ -224,6 +230,9 @@ isdir(const wchar_t *filename) |
| return 1; |
| } |
| |
| +/* |
| +x86_64-w64-mingw32-gcc -c -Wno-unused-result -Wsign-compare -DNDEBUG -march=x86-64 -mtune=generic -O2 -pipe -fwrapv -D__USE_MINGW_ANSI_STDIO=1 -D_WIN32_WINNT=0x0601 -DNDEBUG -DMS_DLL_ID="\"3.9\"" -flto -fuse-linker-plugin -ffat-lto-objects -flto-partition=none -g -std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Wstrict-prototypes -Werror=implicit-function-declaration -fvisibility=hidden -fprofile-generate -I../Python-3.9.4/Include/internal -IObjects -IInclude -IPython -I. -I../Python-3.9.4/Include -I../Python-3.9.4/PC -D__USE_MINGW_ANSI_STDIO=1 -IC:/msys64/mingw64/include/ncurses -I. -DPy_BUILD_CORE -DPYTHONPATH='""' -DPREFIX='"/mingw64"' -DEXEC_PREFIX='"/mingw64"' -DVERSION='"3.9"' -DVPATH='"../Python-3.9.4"' -o Modules/getpath.o ../Python-3.9.4/Modules/getpath.c |
| +*/ |
| |
| /* Add a path component, by appending stuff to buffer. |
| buflen: 'buffer' length in characters including trailing NUL. |
| @@ -242,8 +251,8 @@ joinpath(wchar_t *path, const wchar_t *path2, size_t path_len) |
| return PATHLEN_ERR(); |
| } |
| |
| - if (n > 0 && path[n-1] != SEP) { |
| - path[n++] = SEP; |
| + if (n > 0 && !_Py_issep(path[n-1])) { |
| + path[n++] = Py_GetSepW(path); |
| } |
| } |
| else { |
| @@ -285,7 +294,7 @@ joinpath2(const wchar_t *path, const wchar_t *path2) |
| } |
| |
| size_t len = wcslen(path); |
| - int add_sep = (len > 0 && path[len - 1] != SEP); |
| + int add_sep = (len > 0 && !_Py_issep(path[len - 1])); |
| len += add_sep; |
| len += wcslen(path2); |
| |
| @@ -334,7 +343,7 @@ copy_absolute(wchar_t *abs_path, const wchar_t *path, size_t abs_path_len) |
| } |
| return _PyStatus_OK(); |
| } |
| - if (path[0] == '.' && path[1] == SEP) { |
| + if (path[0] == '.' && _Py_issep(path[1])) { |
| path += 2; |
| } |
| PyStatus status = joinpath(abs_path, path, abs_path_len); |
| @@ -478,6 +487,7 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, |
| return _PyStatus_NO_MEMORY(); |
| } |
| |
| + Py_NormalizeSepsW(path); |
| int is_build_dir = isfile(path); |
| PyMem_RawFree(path); |
| |
| @@ -502,6 +512,7 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, |
| } |
| |
| int module; |
| + Py_NormalizeSepsW(prefix); |
| status = ismodule(prefix, &module); |
| if (_PyStatus_EXCEPTION(status)) { |
| return status; |
| @@ -528,6 +539,7 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, |
| } |
| |
| int module; |
| + Py_NormalizeSepsW(prefix); |
| status = ismodule(prefix, &module); |
| if (_PyStatus_EXCEPTION(status)) { |
| return status; |
| @@ -551,6 +563,7 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, |
| } |
| |
| int module; |
| + Py_NormalizeSepsW(prefix); |
| status = ismodule(prefix, &module); |
| if (_PyStatus_EXCEPTION(status)) { |
| return status; |
| @@ -610,6 +623,11 @@ calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| * return the compiled-in defaults instead. |
| */ |
| if (calculate->prefix_found > 0) { |
| +#ifdef MS_WINDOWS |
| + wchar_t drive_root[3]; |
| + memset(drive_root, 0, sizeof(drive_root)); |
| + wcsncpy(drive_root, calculate->prefix, 3); |
| +#endif |
| wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix); |
| if (prefix == NULL) { |
| return _PyStatus_NO_MEMORY(); |
| @@ -625,7 +643,11 @@ calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| |
| /* The prefix is the root directory, but reduce() chopped |
| off the "/". */ |
| +#ifdef MS_WINDOWS |
| + pathconfig->prefix = _PyMem_RawWcsdup(drive_root); |
| +#else |
| pathconfig->prefix = _PyMem_RawWcsdup(separator); |
| +#endif |
| if (pathconfig->prefix == NULL) { |
| return _PyStatus_NO_MEMORY(); |
| } |
| @@ -682,6 +704,7 @@ calculate_pybuilddir(const wchar_t *argv0_path, |
| return PATHLEN_ERR(); |
| } |
| status = joinpath(exec_prefix, pybuilddir, exec_prefix_len); |
| + Py_NormalizeSepsW(exec_prefix); |
| PyMem_RawFree(pybuilddir); |
| if (_PyStatus_EXCEPTION(status)) { |
| return status; |
| @@ -730,6 +753,7 @@ search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, |
| |
| /* Check for pybuilddir.txt */ |
| assert(*found == 0); |
| + Py_NormalizeSepsW(exec_prefix); |
| status = calculate_pybuilddir(calculate->argv0_path, |
| exec_prefix, exec_prefix_len, found); |
| if (_PyStatus_EXCEPTION(status)) { |
| @@ -804,6 +828,7 @@ calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| return status; |
| } |
| |
| + Py_NormalizeSepsW(exec_prefix); |
| if (!calculate->exec_prefix_found) { |
| if (calculate->warnings) { |
| fprintf(stderr, |
| @@ -836,6 +861,47 @@ calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| } |
| |
| |
| +#ifdef MS_WINDOWS |
| +wchar_t * |
| +GetWindowsModulePaths(void) |
| +{ |
| + int result = 0; |
| + wchar_t program_full_path[MAXPATHLEN+1]; |
| + memset(program_full_path, 0, sizeof(program_full_path)); |
| + |
| + if (GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { |
| + result = 1; |
| + Py_NormalizeSepsW(program_full_path); |
| + } |
| + |
| + return _PyMem_RawWcsdup(program_full_path); |
| +} |
| + |
| + |
| +wchar_t* |
| +_Py_GetDLLPath(void) |
| +{ |
| + wchar_t dll_path[MAXPATHLEN+1]; |
| + memset(dll_path, 0, sizeof(dll_path)); |
| + |
| +#ifdef Py_ENABLE_SHARED |
| + extern HANDLE PyWin_DLLhModule; |
| + if (PyWin_DLLhModule) { |
| + if (GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) { |
| + Py_NormalizeSepsW(dll_path); |
| + } else { |
| + dll_path[0] = 0; |
| + } |
| + } |
| +#else |
| + dll_path[0] = 0; |
| +#endif |
| + |
| + return _PyMem_RawWcsdup(dll_path); |
| +} |
| +#endif /* MS_WINDOWS */ |
| + |
| + |
| static PyStatus |
| calculate_set_exec_prefix(PyCalculatePath *calculate, |
| _PyPathConfig *pathconfig) |
| @@ -846,6 +912,12 @@ calculate_set_exec_prefix(PyCalculatePath *calculate, |
| return _PyStatus_NO_MEMORY(); |
| } |
| |
| +#ifdef MS_WINDOWS |
| + wchar_t drive_root[3]; |
| + memset(drive_root, 0, sizeof(drive_root)); |
| + wcsncpy(drive_root, calculate->exec_prefix, 3); |
| +#endif |
| + |
| reduce(exec_prefix); |
| reduce(exec_prefix); |
| reduce(exec_prefix); |
| @@ -859,7 +931,11 @@ calculate_set_exec_prefix(PyCalculatePath *calculate, |
| |
| /* The exec_prefix is the root directory, but reduce() chopped |
| off the "/". */ |
| +#ifdef MS_WINDOWS |
| + pathconfig->exec_prefix = _PyMem_RawWcsdup(drive_root); |
| +#else |
| pathconfig->exec_prefix = _PyMem_RawWcsdup(separator); |
| +#endif |
| if (pathconfig->exec_prefix == NULL) { |
| return _PyStatus_NO_MEMORY(); |
| } |
| @@ -964,13 +1040,22 @@ calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| * other way to find a directory to start the search from. If |
| * $PATH isn't exported, you lose. |
| */ |
| - if (wcschr(pathconfig->program_name, SEP)) { |
| + if (wcschr(pathconfig->program_name, Py_GetSepW(pathconfig->program_name))) { |
| pathconfig->program_full_path = _PyMem_RawWcsdup(pathconfig->program_name); |
| if (pathconfig->program_full_path == NULL) { |
| return _PyStatus_NO_MEMORY(); |
| } |
| return _PyStatus_OK(); |
| } |
| +#ifdef MS_WINDOWS |
| + else if(pathconfig->program_full_path == NULL) { |
| + pathconfig->program_full_path = GetWindowsModulePaths(); |
| + if (pathconfig->program_full_path == NULL) { |
| + return _PyStatus_NO_MEMORY(); |
| + } |
| + return _PyStatus_OK(); |
| + } |
| +#endif /* MS_WINDOWS */ |
| |
| #ifdef __APPLE__ |
| wchar_t *abs_path = NULL; |
| @@ -1007,7 +1092,7 @@ calculate_program_impl(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| |
| |
| /* Calculate pathconfig->program_full_path */ |
| -static PyStatus |
| +PyStatus |
| calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| { |
| PyStatus status; |
| @@ -1173,7 +1258,7 @@ done: |
| #endif |
| |
| |
| -static PyStatus |
| +PyStatus |
| calculate_argv0_path(PyCalculatePath *calculate, |
| _PyPathConfig *pathconfig) |
| { |
| @@ -1191,10 +1276,12 @@ calculate_argv0_path(PyCalculatePath *calculate, |
| } |
| #endif |
| |
| +#if defined(HAVE_READLINK) |
| status = resolve_symlinks(&calculate->argv0_path); |
| if (_PyStatus_EXCEPTION(status)) { |
| return status; |
| } |
| +#endif |
| |
| reduce(calculate->argv0_path); |
| |
| @@ -1329,6 +1416,8 @@ calculate_zip_path(PyCalculatePath *calculate) |
| calculate->zip_path[len - 6] = VERSION[0]; |
| calculate->zip_path[len - 5] = VERSION[2]; |
| |
| + Py_NormalizeSepsW(calculate->zip_path); |
| + |
| res = _PyStatus_OK(); |
| |
| done: |
| @@ -1368,7 +1457,14 @@ calculate_module_search_path(PyCalculatePath *calculate, |
| } |
| |
| bufsz += wcslen(calculate->zip_path) + 1; |
| +/* TODO :: The MS_WINDOWS bit may be unnecessary. */ |
| +#ifdef MS_WINDOWS |
| + if (_Py_isabs(calculate->exec_prefix)) { |
| + bufsz += wcslen(calculate->exec_prefix) + 1; |
| + } |
| +#else |
| bufsz += wcslen(calculate->exec_prefix) + 1; |
| +#endif |
| |
| /* Allocate the buffer */ |
| wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); |
| @@ -1396,7 +1492,7 @@ calculate_module_search_path(PyCalculatePath *calculate, |
| |
| if (!_Py_isabs(defpath)) { |
| wcscat(buf, calculate->prefix); |
| - if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP && |
| + if (prefixsz >= 2 && !_Py_issep(calculate->prefix[prefixsz - 2]) && |
| defpath[0] != (delim ? DELIM : L'\0')) |
| { |
| /* not empty */ |
| @@ -1418,8 +1514,15 @@ calculate_module_search_path(PyCalculatePath *calculate, |
| } |
| wcscat(buf, delimiter); |
| |
| +#ifdef MS_WINDOWS |
| + if (_Py_isabs(calculate->exec_prefix)) { |
| + wcscat(buf, calculate->exec_prefix); |
| + wcscat(buf, delimiter); |
| + } |
| +#else |
| /* Finally, on goes the directory for dynamic-load modules */ |
| wcscat(buf, calculate->exec_prefix); |
| +#endif |
| |
| pathconfig->module_search_path = buf; |
| return _PyStatus_OK(); |
| @@ -1448,14 +1551,17 @@ calculate_init(PyCalculatePath *calculate, const PyConfig *config) |
| if (!calculate->pythonpath_macro) { |
| return DECODE_LOCALE_ERR("PYTHONPATH macro", len); |
| } |
| + Py_NormalizeSepsW(calculate->pythonpath_macro); |
| calculate->prefix_macro = Py_DecodeLocale(PREFIX, &len); |
| if (!calculate->prefix_macro) { |
| return DECODE_LOCALE_ERR("PREFIX macro", len); |
| } |
| + Py_NormalizeSepsW(calculate->prefix_macro); |
| calculate->exec_prefix_macro = Py_DecodeLocale(EXEC_PREFIX, &len); |
| if (!calculate->exec_prefix_macro) { |
| return DECODE_LOCALE_ERR("EXEC_PREFIX macro", len); |
| } |
| + Py_NormalizeSepsW(calculate->exec_prefix_macro); |
| calculate->vpath_macro = Py_DecodeLocale(VPATH, &len); |
| if (!calculate->vpath_macro) { |
| return DECODE_LOCALE_ERR("VPATH macro", len); |
| @@ -1466,6 +1572,7 @@ calculate_init(PyCalculatePath *calculate, const PyConfig *config) |
| if (!pyversion) { |
| return DECODE_LOCALE_ERR("VERSION macro", len); |
| } |
| + |
| calculate->lib_python = joinpath2(config->platlibdir, pyversion); |
| PyMem_RawFree(pyversion); |
| if (calculate->lib_python == NULL) { |
| @@ -1482,6 +1589,7 @@ calculate_free(PyCalculatePath *calculate) |
| PyMem_RawFree(calculate->pythonpath_macro); |
| PyMem_RawFree(calculate->prefix_macro); |
| PyMem_RawFree(calculate->exec_prefix_macro); |
| + PyMem_RawFree(calculate->dll_path); |
| PyMem_RawFree(calculate->vpath_macro); |
| PyMem_RawFree(calculate->lib_python); |
| PyMem_RawFree(calculate->path_env); |
| @@ -1497,6 +1605,8 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) |
| { |
| PyStatus status; |
| |
| + calculate->dll_path = _Py_GetDLLPath(); |
| + |
| if (pathconfig->program_full_path == NULL) { |
| status = calculate_program(calculate, pathconfig); |
| if (_PyStatus_EXCEPTION(status)) { |
| @@ -1597,6 +1707,7 @@ _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) |
| { |
| PyStatus status; |
| PyCalculatePath calculate; |
| + separator[0] = Py_GetSepW(NULL); |
| memset(&calculate, 0, sizeof(calculate)); |
| |
| status = calculate_init(&calculate, config); |
| diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c |
| index 1e61545..40fc270 100644 |
| --- a/Modules/posixmodule.c |
| +++ b/Modules/posixmodule.c |
| @@ -4049,7 +4049,7 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list) |
| Py_END_ALLOW_THREADS |
| /* FindNextFile sets error to ERROR_NO_MORE_FILES if |
| it got to the end of the directory. */ |
| - if (!result && GetLastError() != ERROR_NO_MORE_FILES) { |
| + if (!result && GetLastError() != 0 && GetLastError() != ERROR_NO_MORE_FILES) { |
| Py_DECREF(list); |
| list = path_error(path); |
| goto exit; |
| diff --git a/Python/dynload_win.c b/Python/dynload_win.c |
| index 9d7690e..bd34310 100644 |
| --- a/Python/dynload_win.c |
| +++ b/Python/dynload_win.c |
| @@ -174,7 +174,9 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, |
| char funcname[258], *import_python; |
| const wchar_t *wpathname; |
| |
| +#if defined(_MSC_VER) |
| _Py_CheckPython3(); |
| +#endif |
| |
| _Py_COMP_DIAG_PUSH |
| _Py_COMP_DIAG_IGNORE_DEPR_DECLS |
| diff --git a/Python/fileutils.c b/Python/fileutils.c |
| index 45ea204..d5f8b79 100644 |
| --- a/Python/fileutils.c |
| +++ b/Python/fileutils.c |
| @@ -1924,13 +1924,31 @@ _Py_wrealpath(const wchar_t *path, |
| #endif |
| |
| |
| -#ifndef MS_WINDOWS |
| int |
| _Py_isabs(const wchar_t *path) |
| { |
| - return (path[0] == SEP); |
| +#ifdef MS_WINDOWS |
| + size_t i = wcslen(path); |
| + if (i >= 3) { |
| + if (iswalpha(path[0]) && path[1] == L':' && _Py_issep(path[2])) { |
| + return 1; |
| + } |
| + } |
| + return 0; |
| +#else |
| + return _Py_issep(path[0]); |
| +#endif |
| } |
| + |
| +int |
| +_Py_issep(const wchar_t ch) |
| +{ |
| +#ifdef MS_WINDOWS |
| + return ch == SEP || ch == ALTSEP; |
| +#else |
| + return ch == SEP; |
| #endif |
| +} |
| |
| |
| /* Get an absolute path. |
| -- |
| 2.32.0 |
| |