From 534bb77ce223f7f41beb69e740fe1801d6343965 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 8 Oct 2021 10:26:02 -0600 Subject: [PATCH 1/9] argv0_path -> argv0_dir. --- Modules/getpath.c | 100 +++++++++++++++++++++++----------------------- PC/getpathp.c | 48 +++++++++++----------- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index 22e5ef24b5d578..ea024420fa56db 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -39,16 +39,16 @@ * link. If so, the link is chased (correctly interpreting a relative * pathname if one is found) and the directory of the link target is used. * - * Finally, argv0_path is set to the directory containing the executable + * Finally, argv0_dir is set to the directory containing the executable * (i.e. the last component is stripped). * - * With argv0_path in hand, we perform a number of steps. The same steps + * With argv0_dir in hand, we perform a number of steps. The same steps * are performed for prefix and for exec_prefix, but with a different * landmark. * * Step 1. Are we running python out of the build directory? This is * checked by looking for a different kind of landmark relative to - * argv0_path. For prefix, the landmark's path is derived from the VPATH + * argv0_dir. For prefix, the landmark's path is derived from the VPATH * preprocessor variable (taking into account that its value is almost, but * not quite, what we need). For exec_prefix, the landmark is * pybuilddir.txt. If the landmark is found, we're done. @@ -67,7 +67,7 @@ * directory, which is used for both, or the prefix and exec_prefix * directories separated by a colon. * - * Step 3. Try to find prefix and exec_prefix relative to argv0_path, + * Step 3. Try to find prefix and exec_prefix relative to argv0_dir, * backtracking up the path until it is exhausted. This is the most common * step to succeed. Note that if prefix and exec_prefix are different, * exec_prefix is more likely to be found; however if exec_prefix is a @@ -134,7 +134,7 @@ typedef struct { const wchar_t *pythonpath_env; const wchar_t *platlibdir; - wchar_t *argv0_path; + wchar_t *argv0_dir; wchar_t *zip_path; wchar_t *prefix; wchar_t *exec_prefix; @@ -395,7 +395,7 @@ add_exe_suffix(wchar_t **progpath_p) #endif -/* search_for_prefix requires that argv0_path be no more than MAXPATHLEN +/* search_for_prefix requires that argv0_dir be no more than MAXPATHLEN bytes long. */ static PyStatus @@ -422,10 +422,10 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, return _PyStatus_OK(); } - /* Check to see if argv0_path is in the build directory + /* Check to see if argv0_dir is in the build directory - Path: / */ - wchar_t *path = joinpath2(calculate->argv0_path, BUILD_LANDMARK); + Path: / */ + wchar_t *path = joinpath2(calculate->argv0_dir, BUILD_LANDMARK); if (path == NULL) { return _PyStatus_NO_MEMORY(); } @@ -434,12 +434,12 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, PyMem_RawFree(path); if (is_build_dir) { - /* argv0_path is the build directory (BUILD_LANDMARK exists), + /* argv0_dir is the build directory (BUILD_LANDMARK exists), now also check LANDMARK using ismodule(). */ - /* Path: / / Lib */ - /* or if VPATH is empty: / Lib */ - if (safe_wcscpy(prefix, calculate->argv0_path, prefix_len) < 0) { + /* Path: / / Lib */ + /* or if VPATH is empty: / Lib */ + if (safe_wcscpy(prefix, calculate->argv0_dir, prefix_len) < 0) { return PATHLEN_ERR(); } @@ -465,14 +465,14 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, } } - /* Search from argv0_path, until root is found */ - status = copy_absolute(prefix, calculate->argv0_path, prefix_len); + /* Search from argv0_dir, until root is found */ + status = copy_absolute(prefix, calculate->argv0_dir, prefix_len); if (_PyStatus_EXCEPTION(status)) { return status; } do { - /* Path: / / LANDMARK */ + /* Path: / / LANDMARK */ size_t n = wcslen(prefix); status = joinpath(prefix, calculate->lib_python, prefix_len); if (_PyStatus_EXCEPTION(status)) { @@ -594,7 +594,7 @@ calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) static PyStatus -calculate_pybuilddir(const wchar_t *argv0_path, +calculate_pybuilddir(const wchar_t *argv0_dir, wchar_t *exec_prefix, size_t exec_prefix_len, int *found) { @@ -604,8 +604,8 @@ calculate_pybuilddir(const wchar_t *argv0_path, is written by setup.py and contains the relative path to the location of shared library modules. - Filename: / "pybuilddir.txt" */ - wchar_t *filename = joinpath2(argv0_path, L"pybuilddir.txt"); + Filename: / "pybuilddir.txt" */ + wchar_t *filename = joinpath2(argv0_dir, L"pybuilddir.txt"); if (filename == NULL) { return _PyStatus_NO_MEMORY(); } @@ -628,8 +628,8 @@ calculate_pybuilddir(const wchar_t *argv0_path, return DECODE_LOCALE_ERR("pybuilddir.txt", dec_len); } - /* Path: / */ - if (safe_wcscpy(exec_prefix, argv0_path, exec_prefix_len) < 0) { + /* Path: / */ + if (safe_wcscpy(exec_prefix, argv0_dir, exec_prefix_len) < 0) { PyMem_RawFree(pybuilddir); return PATHLEN_ERR(); } @@ -644,7 +644,7 @@ calculate_pybuilddir(const wchar_t *argv0_path, } -/* search_for_exec_prefix requires that argv0_path be no more than +/* search_for_exec_prefix requires that argv0_dir be no more than MAXPATHLEN bytes long. */ static PyStatus @@ -682,7 +682,7 @@ search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, /* Check for pybuilddir.txt */ assert(*found == 0); - status = calculate_pybuilddir(calculate->argv0_path, + status = calculate_pybuilddir(calculate->argv0_dir, exec_prefix, exec_prefix_len, found); if (_PyStatus_EXCEPTION(status)) { return status; @@ -691,14 +691,14 @@ search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, return _PyStatus_OK(); } - /* Search from argv0_path, until root is found */ - status = copy_absolute(exec_prefix, calculate->argv0_path, exec_prefix_len); + /* Search from argv0_dir, until root is found */ + status = copy_absolute(exec_prefix, calculate->argv0_dir, exec_prefix_len); if (_PyStatus_EXCEPTION(status)) { return status; } do { - /* Path: / / "lib-dynload" */ + /* Path: / / "lib-dynload" */ size_t n = wcslen(exec_prefix); status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); if (_PyStatus_EXCEPTION(status)) { @@ -1044,7 +1044,7 @@ resolve_symlinks(wchar_t **path_p) #ifdef WITH_NEXT_FRAMEWORK static PyStatus -calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +calculate_argv0_dir_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { NSModule pythonModule; @@ -1102,9 +1102,9 @@ calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathco if (!module) { /* We are in the build directory so use the name of the executable - we know that the absolute path is passed */ - PyMem_RawFree(calculate->argv0_path); - calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path); - if (calculate->argv0_path == NULL) { + PyMem_RawFree(calculate->argv0_dir); + calculate->argv0_dir = _PyMem_RawWcsdup(pathconfig->program_full_path); + if (calculate->argv0_dir == NULL) { status = _PyStatus_NO_MEMORY(); goto done; } @@ -1113,9 +1113,9 @@ calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathco goto done; } - /* Use the location of the library as argv0_path */ - PyMem_RawFree(calculate->argv0_path); - calculate->argv0_path = wbuf; + /* Use the location of the library as argv0_dir */ + PyMem_RawFree(calculate->argv0_dir); + calculate->argv0_dir = wbuf; return _PyStatus_OK(); done: @@ -1126,29 +1126,29 @@ calculate_argv0_path_framework(PyCalculatePath *calculate, _PyPathConfig *pathco static PyStatus -calculate_argv0_path(PyCalculatePath *calculate, +calculate_argv0_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { PyStatus status; - calculate->argv0_path = _PyMem_RawWcsdup(pathconfig->program_full_path); - if (calculate->argv0_path == NULL) { + calculate->argv0_dir = _PyMem_RawWcsdup(pathconfig->program_full_path); + if (calculate->argv0_dir == NULL) { return _PyStatus_NO_MEMORY(); } #ifdef WITH_NEXT_FRAMEWORK - status = calculate_argv0_path_framework(calculate, pathconfig); + status = calculate_argv0_dir_framework(calculate, pathconfig); if (_PyStatus_EXCEPTION(status)) { return status; } #endif - status = resolve_symlinks(&calculate->argv0_path); + status = resolve_symlinks(&calculate->argv0_dir); if (_PyStatus_EXCEPTION(status)) { return status; } - reduce(calculate->argv0_path); + reduce(calculate->argv0_dir); return _PyStatus_OK(); } @@ -1161,8 +1161,8 @@ calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p) const wchar_t *env_cfg = L"pyvenv.cfg"; - /* Filename: / "pyvenv.cfg" */ - wchar_t *filename = joinpath2(calculate->argv0_path, env_cfg); + /* Filename: / "pyvenv.cfg" */ + wchar_t *filename = joinpath2(calculate->argv0_dir, env_cfg); if (filename == NULL) { return _PyStatus_NO_MEMORY(); } @@ -1178,8 +1178,8 @@ calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p) /* fopen() failed: reset errno */ errno = 0; - /* Path: / "pyvenv.cfg" */ - wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_path); + /* Path: / "pyvenv.cfg" */ + wchar_t *parent = _PyMem_RawWcsdup(calculate->argv0_dir); if (parent == NULL) { return _PyStatus_NO_MEMORY(); } @@ -1206,7 +1206,7 @@ calculate_open_pyenv(PyCalculatePath *calculate, FILE **env_file_p) executable's directory and then in the parent directory. If found, open it for use when searching for prefixes. - Write the 'home' variable of pyvenv.cfg into calculate->argv0_path. */ + Write the 'home' variable of pyvenv.cfg into calculate->argv0_dir. */ static PyStatus calculate_read_pyenv(PyCalculatePath *calculate) { @@ -1223,7 +1223,7 @@ calculate_read_pyenv(PyCalculatePath *calculate) return _PyStatus_OK(); } - /* Look for a 'home' variable and set argv0_path to it, if found */ + /* Look for a 'home' variable and set argv0_dir to it, if found */ wchar_t *home = NULL; status = _Py_FindEnvConfigValue(env_file, L"home", &home); if (_PyStatus_EXCEPTION(status)) { @@ -1232,8 +1232,8 @@ calculate_read_pyenv(PyCalculatePath *calculate) } if (home) { - PyMem_RawFree(calculate->argv0_path); - calculate->argv0_path = home; + PyMem_RawFree(calculate->argv0_dir); + calculate->argv0_dir = home; } fclose(env_file); return _PyStatus_OK(); @@ -1433,7 +1433,7 @@ calculate_free(PyCalculatePath *calculate) PyMem_RawFree(calculate->lib_python); PyMem_RawFree(calculate->path_env); PyMem_RawFree(calculate->zip_path); - PyMem_RawFree(calculate->argv0_path); + PyMem_RawFree(calculate->argv0_dir); PyMem_RawFree(calculate->prefix); PyMem_RawFree(calculate->exec_prefix); } @@ -1451,13 +1451,13 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } } - status = calculate_argv0_path(calculate, pathconfig); + status = calculate_argv0_dir(calculate, pathconfig); if (_PyStatus_EXCEPTION(status)) { return status; } /* If a pyvenv.cfg configure file is found, - argv0_path is overridden with its 'home' variable. */ + argv0_dir is overridden with its 'home' variable. */ status = calculate_read_pyenv(calculate); if (_PyStatus_EXCEPTION(status)) { return status; diff --git a/PC/getpathp.c b/PC/getpathp.c index 79569bb554457c..f910ebba471822 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -297,14 +297,14 @@ is_stdlibdir(wchar_t *stdlibdir) return ismodule(filename); } -/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. +/* assumes argv0_dir is MAXPATHLEN+1 bytes long, already \0 term'd. assumption provided by only caller, calculate_path() */ static int -search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path) +search_for_prefix(wchar_t *prefix, const wchar_t *argv0_dir) { - /* Search from argv0_path, until LANDMARK is found. + /* Search from argv0_dir, until LANDMARK is found. We guarantee 'prefix' is null terminated in bounds. */ - wcscpy_s(prefix, MAXPATHLEN+1, argv0_path); + wcscpy_s(prefix, MAXPATHLEN+1, argv0_dir); if (!prefix[0]) { return 0; } @@ -727,20 +727,20 @@ calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig, */ static PyStatus calculate_pyvenv_file(PyCalculatePath *calculate, - wchar_t *argv0_path, size_t argv0_path_len) + wchar_t *argv0_dir, size_t argv0_dir_len) { wchar_t filename[MAXPATHLEN+1]; const wchar_t *env_cfg = L"pyvenv.cfg"; - /* Filename: / "pyvenv.cfg" */ - wcscpy_s(filename, MAXPATHLEN+1, argv0_path); + /* Filename: / "pyvenv.cfg" */ + wcscpy_s(filename, MAXPATHLEN+1, argv0_dir); join(filename, env_cfg); FILE *env_file = _Py_wfopen(filename, L"r"); if (env_file == NULL) { errno = 0; - /* Filename: / "pyvenv.cfg" */ + /* Filename: / "pyvenv.cfg" */ reduce(filename); reduce(filename); join(filename, env_cfg); @@ -752,7 +752,7 @@ calculate_pyvenv_file(PyCalculatePath *calculate, } } - /* Look for a 'home' variable and set argv0_path to it, if found */ + /* Look for a 'home' variable and set argv0_dir to it, if found */ wchar_t *home = NULL; PyStatus status = _Py_FindEnvConfigValue(env_file, L"home", &home); if (_PyStatus_EXCEPTION(status)) { @@ -760,7 +760,7 @@ calculate_pyvenv_file(PyCalculatePath *calculate, return status; } if (home) { - wcscpy_s(argv0_path, argv0_path_len, home); + wcscpy_s(argv0_dir, argv0_dir_len, home); PyMem_RawFree(home); } fclose(env_file); @@ -770,7 +770,7 @@ calculate_pyvenv_file(PyCalculatePath *calculate, static void calculate_home_prefix(PyCalculatePath *calculate, - const wchar_t *argv0_path, + const wchar_t *argv0_dir, const wchar_t *zip_path, wchar_t *prefix) { @@ -780,7 +780,7 @@ calculate_home_prefix(PyCalculatePath *calculate, reduce(prefix); calculate->home = prefix; } - else if (search_for_prefix(prefix, argv0_path)) { + else if (search_for_prefix(prefix, argv0_dir)) { calculate->home = prefix; } else { @@ -796,7 +796,7 @@ calculate_home_prefix(PyCalculatePath *calculate, static PyStatus calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - const wchar_t *argv0_path, + const wchar_t *argv0_dir, wchar_t *prefix, const wchar_t *zip_path) { @@ -821,7 +821,7 @@ calculate_module_search_path(PyCalculatePath *calculate, (3) for Win32, the machine_path and user_path, if set; (4) the PYTHONPATH config macro, with the leading "." of each component replaced with home, if set; - (5) the directory containing the executable (argv0_path). + (5) the directory containing the executable (argv0_dir). The length calculation calculates #4 first. Extra rules: - If PYTHONHOME is set (in any way) item (3) is ignored. @@ -841,7 +841,7 @@ calculate_module_search_path(PyCalculatePath *calculate, bufsz *= wcslen(calculate->home); } bufsz += wcslen(PYTHONPATH) + 1; - bufsz += wcslen(argv0_path) + 1; + bufsz += wcslen(argv0_dir) + 1; if (calculate->user_path) { bufsz += wcslen(calculate->user_path) + 1; } @@ -926,8 +926,8 @@ calculate_module_search_path(PyCalculatePath *calculate, p = q+1; } } - if (argv0_path) { - wcscpy(buf, argv0_path); + if (argv0_dir) { + wcscpy(buf, argv0_dir); buf = wcschr(buf, L'\0'); *buf++ = DELIM; } @@ -990,11 +990,11 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */ - wchar_t argv0_path[MAXPATHLEN+1]; - memset(argv0_path, 0, sizeof(argv0_path)); + wchar_t argv0_dir[MAXPATHLEN+1]; + memset(argv0_dir, 0, sizeof(argv0_dir)); - wcscpy_s(argv0_path, MAXPATHLEN+1, pathconfig->program_full_path); - reduce(argv0_path); + wcscpy_s(argv0_dir, MAXPATHLEN+1, pathconfig->program_full_path); + reduce(argv0_dir); wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); @@ -1010,7 +1010,7 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } status = calculate_pyvenv_file(calculate, - argv0_path, Py_ARRAY_LENGTH(argv0_path)); + argv0_dir, Py_ARRAY_LENGTH(argv0_dir)); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -1026,11 +1026,11 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } } - calculate_home_prefix(calculate, argv0_path, zip_path, prefix); + calculate_home_prefix(calculate, argv0_dir, zip_path, prefix); if (pathconfig->module_search_path == NULL) { status = calculate_module_search_path(calculate, pathconfig, - argv0_path, prefix, zip_path); + argv0_dir, prefix, zip_path); if (_PyStatus_EXCEPTION(status)) { return status; } From 633ce3dbc9871004db7b7302baf48c6ab1d44bf5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 8 Oct 2021 11:22:23 -0600 Subject: [PATCH 2/9] Add PyCalculatePath.stdlib_dir. --- Modules/getpath.c | 173 ++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 75 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index ea024420fa56db..a871f3459933c2 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -127,17 +127,22 @@ typedef struct { wchar_t *lib_python; /* / "pythonX.Y" */ - int prefix_found; /* found platform independent libraries? */ - int exec_prefix_found; /* found the platform dependent libraries? */ - int warnings; const wchar_t *pythonpath_env; const wchar_t *platlibdir; wchar_t *argv0_dir; - wchar_t *zip_path; + + wchar_t *stdlib_dir; + int stdlib_dir_found; /* found stdlib dir? */ + wchar_t *prefix; + int prefix_found; /* found platform independent libraries? */ + wchar_t *exec_prefix; + int exec_prefix_found; /* found the platform dependent libraries? */ + + wchar_t *zip_path; } PyCalculatePath; static const wchar_t delimiter[2] = {DELIM, '\0'}; @@ -399,22 +404,22 @@ add_exe_suffix(wchar_t **progpath_p) bytes long. */ static PyStatus -search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - wchar_t *prefix, size_t prefix_len, int *found) +search_for_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig, + wchar_t *stdlib, size_t stdlib_len, int *found) { PyStatus status; /* If PYTHONHOME is set, we believe it unconditionally */ if (pathconfig->home) { /* Path: / */ - if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) { + if (safe_wcscpy(stdlib, pathconfig->home, stdlib_len) < 0) { return PATHLEN_ERR(); } - wchar_t *delim = wcschr(prefix, DELIM); + wchar_t *delim = wcschr(stdlib, DELIM); if (delim) { *delim = L'\0'; } - status = joinpath(prefix, calculate->lib_python, prefix_len); + status = joinpath(stdlib, calculate->lib_python, stdlib_len); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -439,22 +444,22 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, /* Path: / / Lib */ /* or if VPATH is empty: / Lib */ - if (safe_wcscpy(prefix, calculate->argv0_dir, prefix_len) < 0) { + if (safe_wcscpy(stdlib, calculate->argv0_dir, stdlib_len) < 0) { return PATHLEN_ERR(); } - status = joinpath(prefix, calculate->vpath_macro, prefix_len); + status = joinpath(stdlib, calculate->vpath_macro, stdlib_len); if (_PyStatus_EXCEPTION(status)) { return status; } - status = joinpath(prefix, L"Lib", prefix_len); + status = joinpath(stdlib, L"Lib", stdlib_len); if (_PyStatus_EXCEPTION(status)) { return status; } int module; - status = ismodule(prefix, &module); + status = ismodule(stdlib, &module); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -466,21 +471,21 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, } /* Search from argv0_dir, until root is found */ - status = copy_absolute(prefix, calculate->argv0_dir, prefix_len); + status = copy_absolute(stdlib, calculate->argv0_dir, stdlib_len); if (_PyStatus_EXCEPTION(status)) { return status; } do { /* Path: / / LANDMARK */ - size_t n = wcslen(prefix); - status = joinpath(prefix, calculate->lib_python, prefix_len); + size_t n = wcslen(stdlib); + status = joinpath(stdlib, calculate->lib_python, stdlib_len); if (_PyStatus_EXCEPTION(status)) { return status; } int module; - status = ismodule(prefix, &module); + status = ismodule(stdlib, &module); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -488,22 +493,22 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, *found = 1; return _PyStatus_OK(); } - prefix[n] = L'\0'; - reduce(prefix); - } while (prefix[0]); + stdlib[n] = L'\0'; + reduce(stdlib); + } while (stdlib[0]); /* Look at configure's PREFIX. Path: / / LANDMARK */ - if (safe_wcscpy(prefix, calculate->prefix_macro, prefix_len) < 0) { + if (safe_wcscpy(stdlib, calculate->prefix_macro, stdlib_len) < 0) { return PATHLEN_ERR(); } - status = joinpath(prefix, calculate->lib_python, prefix_len); + status = joinpath(stdlib, calculate->lib_python, stdlib_len); if (_PyStatus_EXCEPTION(status)) { return status; } int module; - status = ismodule(prefix, &module); + status = ismodule(stdlib, &module); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -519,71 +524,86 @@ search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, static PyStatus -calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - wchar_t prefix[MAXPATHLEN+1]; - memset(prefix, 0, sizeof(prefix)); - size_t prefix_len = Py_ARRAY_LENGTH(prefix); - PyStatus status; - status = search_for_prefix(calculate, pathconfig, - prefix, prefix_len, - &calculate->prefix_found); + wchar_t stdlib[MAXPATHLEN+1]; + memset(stdlib, 0, sizeof(stdlib)); + size_t stdlib_len = Py_ARRAY_LENGTH(stdlib); + + status = search_for_stdlib_dir(calculate, pathconfig, + stdlib, stdlib_len, + &calculate->stdlib_dir_found); if (_PyStatus_EXCEPTION(status)) { return status; } - if (!calculate->prefix_found) { - if (calculate->warnings) { - fprintf(stderr, - "Could not find platform independent libraries \n"); + if (!calculate->stdlib_dir_found) { + calculate->stdlib_dir = joinpath2(calculate->prefix_macro, + calculate->lib_python); + if (calculate->stdlib_dir == NULL) { + return _PyStatus_NO_MEMORY(); } - - calculate->prefix = joinpath2(calculate->prefix_macro, - calculate->lib_python); } else { - calculate->prefix = _PyMem_RawWcsdup(prefix); + calculate->stdlib_dir = _PyMem_RawWcsdup(stdlib); + if (calculate->stdlib_dir == NULL) { + return _PyStatus_NO_MEMORY(); + } } + return _PyStatus_OK(); +} + +static PyStatus +calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +{ + wchar_t prefix[MAXPATHLEN+1]; + memset(prefix, 0, sizeof(prefix)); + size_t prefix_len = Py_ARRAY_LENGTH(prefix); + if (safe_wcscpy(prefix, calculate->stdlib_dir, prefix_len) < 0) { + return PATHLEN_ERR(); + } + /* Reduce stdlib_dir to the essense of the prefix, + * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. + */ + reduce(prefix); + reduce(prefix); + if (*prefix == L'\0') { + /* The prefix is the root directory, but reduce() chopped + off the "/". */ + wcscpy(prefix, separator); + } + calculate->prefix = _PyMem_RawWcsdup(prefix); if (calculate->prefix == NULL) { return _PyStatus_NO_MEMORY(); } + + calculate->prefix_found = calculate->stdlib_dir_found; + if (!calculate->prefix_found) { + if (calculate->warnings) { + fprintf(stderr, + "Could not find platform independent libraries \n"); + } + } + return _PyStatus_OK(); } - static PyStatus calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - /* Reduce prefix and exec_prefix to their essence, - * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. - * If we're loading relative to the build directory, - * return the compiled-in defaults instead. - */ + // XXX Handle 0 here too. if (calculate->prefix_found > 0) { - wchar_t *prefix = _PyMem_RawWcsdup(calculate->prefix); - if (prefix == NULL) { + pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix); + if (pathconfig->prefix == NULL) { return _PyStatus_NO_MEMORY(); } - - reduce(prefix); - reduce(prefix); - if (prefix[0]) { - pathconfig->prefix = prefix; - } - else { - PyMem_RawFree(prefix); - - /* The prefix is the root directory, but reduce() chopped - off the "/". */ - pathconfig->prefix = _PyMem_RawWcsdup(separator); - if (pathconfig->prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - } } else { + /* We're loading relative to the build directory, + * so return the compiled-in defaults instead. + */ pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro); if (pathconfig->prefix == NULL) { return _PyStatus_NO_MEMORY(); @@ -1256,14 +1276,12 @@ calculate_zip_path(PyCalculatePath *calculate) if (calculate->prefix_found > 0) { /* Use the reduced prefix returned by Py_GetPrefix() - Path: / / "pythonXY.zip" */ + Path: / / "pythonXY.zip" */ wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix); if (parent == NULL) { res = _PyStatus_NO_MEMORY(); goto done; } - reduce(parent); - reduce(parent); calculate->zip_path = joinpath2(parent, path); PyMem_RawFree(parent); } @@ -1295,13 +1313,13 @@ calculate_module_search_path(PyCalculatePath *calculate, } wchar_t *defpath = calculate->pythonpath_macro; - size_t prefixsz = wcslen(calculate->prefix) + 1; + size_t stdlibsz = wcslen(calculate->stdlib_dir) + 1; while (1) { wchar_t *delim = wcschr(defpath, DELIM); if (!_Py_isabs(defpath)) { /* Paths are relative to prefix */ - bufsz += prefixsz; + bufsz += stdlibsz; } if (delim) { @@ -1335,15 +1353,15 @@ calculate_module_search_path(PyCalculatePath *calculate, wcscat(buf, delimiter); /* Next goes merge of compile-time $PYTHONPATH with - * dynamically located prefix. + * dynamically located stdlib. */ defpath = calculate->pythonpath_macro; while (1) { wchar_t *delim = wcschr(defpath, DELIM); if (!_Py_isabs(defpath)) { - wcscat(buf, calculate->prefix); - if (prefixsz >= 2 && calculate->prefix[prefixsz - 2] != SEP && + wcscat(buf, calculate->stdlib_dir); + if (stdlibsz >= 2 && calculate->stdlib_dir[stdlibsz - 2] != SEP && defpath[0] != (delim ? DELIM : L'\0')) { /* not empty */ @@ -1434,6 +1452,7 @@ calculate_free(PyCalculatePath *calculate) PyMem_RawFree(calculate->path_env); PyMem_RawFree(calculate->zip_path); PyMem_RawFree(calculate->argv0_dir); + PyMem_RawFree(calculate->stdlib_dir); PyMem_RawFree(calculate->prefix); PyMem_RawFree(calculate->exec_prefix); } @@ -1463,6 +1482,11 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) return status; } + status = calculate_stdlib_dir(calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + status = calculate_prefix(calculate, pathconfig); if (_PyStatus_EXCEPTION(status)) { return status; @@ -1482,7 +1506,7 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) && calculate->warnings) { fprintf(stderr, - "Consider setting $PYTHONHOME to [:]\n"); + "Consider setting $PYTHONHOME to [:]\n"); } if (pathconfig->module_search_path == NULL) { @@ -1493,9 +1517,8 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } if (pathconfig->stdlib_dir == NULL) { - if (calculate->prefix_found) { - /* This must be done *before* calculate_set_prefix() is called. */ - pathconfig->stdlib_dir = _PyMem_RawWcsdup(calculate->prefix); + if (calculate->stdlib_dir != NULL) { + pathconfig->stdlib_dir = _PyMem_RawWcsdup(calculate->stdlib_dir); if (pathconfig->stdlib_dir == NULL) { return _PyStatus_NO_MEMORY(); } From 418b59025c17474e4d9356e630c11ff977150320 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 8 Oct 2021 13:57:39 -0600 Subject: [PATCH 3/9] Break up prefix_found. --- Modules/getpath.c | 177 +++++++++++++++++++++++----------------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index a871f3459933c2..5e6c0fd2b4d4e9 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -8,6 +8,7 @@ #include #include +#include #ifdef __APPLE__ # include @@ -117,6 +118,13 @@ extern "C" { #define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long") +#define LOCATION_UNKNOWN 0 +#define LOCATION_EXISTS 1 +#define LOCATION_FORCED 2 +#define LOCATION_IN_SOURCE_TREE 4 + +#define LOCATION_FOUND (LOCATION_EXISTS | LOCATION_FORCED) + typedef struct { wchar_t *path_env; /* PATH environment variable */ @@ -134,10 +142,11 @@ typedef struct { wchar_t *argv0_dir; wchar_t *stdlib_dir; - int stdlib_dir_found; /* found stdlib dir? */ + int stdlib_dir_verified; /* bit vector of verified LOCATION_* flags */ wchar_t *prefix; - int prefix_found; /* found platform independent libraries? */ + int prefix_verified; /* bit vector of verified LOCATION_* flags */ + bool prefix_found; /* found platform independent libraries? */ wchar_t *exec_prefix; int exec_prefix_found; /* found the platform dependent libraries? */ @@ -404,29 +413,11 @@ add_exe_suffix(wchar_t **progpath_p) bytes long. */ static PyStatus -search_for_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - wchar_t *stdlib, size_t stdlib_len, int *found) +search_for_stdlib_dir(PyCalculatePath *calculate, + wchar_t *stdlib, size_t stdlib_len, int *verified) { PyStatus status; - /* If PYTHONHOME is set, we believe it unconditionally */ - if (pathconfig->home) { - /* Path: / */ - if (safe_wcscpy(stdlib, pathconfig->home, stdlib_len) < 0) { - return PATHLEN_ERR(); - } - wchar_t *delim = wcschr(stdlib, DELIM); - if (delim) { - *delim = L'\0'; - } - status = joinpath(stdlib, calculate->lib_python, stdlib_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - *found = 1; - return _PyStatus_OK(); - } - /* Check to see if argv0_dir is in the build directory Path: / */ @@ -465,7 +456,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig, } if (module) { /* BUILD_LANDMARK and LANDMARK found */ - *found = -1; + *verified |= LOCATION_EXISTS | LOCATION_IN_SOURCE_TREE; return _PyStatus_OK(); } } @@ -490,7 +481,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig, return status; } if (module) { - *found = 1; + *verified |= LOCATION_EXISTS; return _PyStatus_OK(); } stdlib[n] = L'\0'; @@ -513,44 +504,68 @@ search_for_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig, return status; } if (module) { - *found = 1; + *verified |= LOCATION_EXISTS; return _PyStatus_OK(); } /* Fail */ - *found = 0; return _PyStatus_OK(); } - static PyStatus calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { + assert(calculate->stdlib_dir == NULL); + assert(calculate->stdlib_dir_verified == LOCATION_UNKNOWN); + PyStatus status; wchar_t stdlib[MAXPATHLEN+1]; memset(stdlib, 0, sizeof(stdlib)); size_t stdlib_len = Py_ARRAY_LENGTH(stdlib); + const wchar_t *prefix = NULL; + int verified = LOCATION_UNKNOWN; - status = search_for_stdlib_dir(calculate, pathconfig, - stdlib, stdlib_len, - &calculate->stdlib_dir_found); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - - if (!calculate->stdlib_dir_found) { - calculate->stdlib_dir = joinpath2(calculate->prefix_macro, - calculate->lib_python); - if (calculate->stdlib_dir == NULL) { - return _PyStatus_NO_MEMORY(); + /* If PYTHONHOME is set, we believe it unconditionally. */ + if (pathconfig->home != NULL) { + /* Path: / */ + prefix = pathconfig->home; + if (safe_wcscpy(stdlib, prefix, stdlib_len) < 0) { + return PATHLEN_ERR(); } + wchar_t *delim = wcschr(stdlib, DELIM); + if (delim) { + *delim = L'\0'; + } + verified |= LOCATION_FORCED; } else { - calculate->stdlib_dir = _PyMem_RawWcsdup(stdlib); - if (calculate->stdlib_dir == NULL) { - return _PyStatus_NO_MEMORY(); + status = search_for_stdlib_dir(calculate, + stdlib, stdlib_len, &verified); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + if (*stdlib == L'\0') { + /* Fall back to PREFIX / . */ + prefix = calculate->prefix_macro; + if (safe_wcscpy(stdlib, prefix, stdlib_len) < 0) { + return PATHLEN_ERR(); + } } } + + if (prefix != NULL) { + status = joinpath(stdlib, calculate->lib_python, stdlib_len); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + calculate->stdlib_dir = _PyMem_RawWcsdup(stdlib); + if (calculate->stdlib_dir == NULL) { + return _PyStatus_NO_MEMORY(); + } + calculate->stdlib_dir_verified = verified; + return _PyStatus_OK(); } @@ -558,15 +573,20 @@ calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) static PyStatus calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { + assert(calculate->stdlib_dir != NULL); + assert(calculate->prefix == NULL); + assert(calculate->prefix_verified == LOCATION_UNKNOWN); + wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); size_t prefix_len = Py_ARRAY_LENGTH(prefix); - if (safe_wcscpy(prefix, calculate->stdlib_dir, prefix_len) < 0) { - return PATHLEN_ERR(); - } + /* Reduce stdlib_dir to the essense of the prefix, * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. */ + if (safe_wcscpy(prefix, calculate->stdlib_dir, prefix_len) < 0) { + return PATHLEN_ERR(); + } reduce(prefix); reduce(prefix); if (*prefix == L'\0') { @@ -574,12 +594,14 @@ calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) off the "/". */ wcscpy(prefix, separator); } + calculate->prefix = _PyMem_RawWcsdup(prefix); if (calculate->prefix == NULL) { return _PyStatus_NO_MEMORY(); } + calculate->prefix_verified = calculate->stdlib_dir_verified; + calculate->prefix_found = calculate->prefix_verified & LOCATION_FOUND; - calculate->prefix_found = calculate->stdlib_dir_found; if (!calculate->prefix_found) { if (calculate->warnings) { fprintf(stderr, @@ -593,21 +615,17 @@ calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) static PyStatus calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - // XXX Handle 0 here too. - if (calculate->prefix_found > 0) { - pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix); - if (pathconfig->prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } - } - else { + assert(pathconfig->prefix == NULL); + const wchar_t *prefix = calculate->prefix; + if (calculate->prefix_verified & LOCATION_IN_SOURCE_TREE) { /* We're loading relative to the build directory, * so return the compiled-in defaults instead. */ - pathconfig->prefix = _PyMem_RawWcsdup(calculate->prefix_macro); - if (pathconfig->prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } + prefix = calculate->prefix_macro; + } + pathconfig->prefix = _PyMem_RawWcsdup(prefix); + if (pathconfig->prefix == NULL) { + return _PyStatus_NO_MEMORY(); } return _PyStatus_OK(); } @@ -1263,42 +1281,25 @@ calculate_read_pyenv(PyCalculatePath *calculate) static PyStatus calculate_zip_path(PyCalculatePath *calculate) { - PyStatus res; + /* Use the reduced prefix returned by Py_GetPrefix(). + Note that we're using PREFIX if we couldn't find the prefix already. - /* Path: / "pythonXY.zip" */ - wchar_t *path = joinpath2(calculate->platlibdir, - L"python" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) - L".zip"); - if (path == NULL) { - return _PyStatus_NO_MEMORY(); - } - - if (calculate->prefix_found > 0) { - /* Use the reduced prefix returned by Py_GetPrefix() + Path: / / "pythonXY.zip" */ - Path: / / "pythonXY.zip" */ - wchar_t *parent = _PyMem_RawWcsdup(calculate->prefix); - if (parent == NULL) { - res = _PyStatus_NO_MEMORY(); - goto done; - } - calculate->zip_path = joinpath2(parent, path); - PyMem_RawFree(parent); - } - else { - calculate->zip_path = joinpath2(calculate->prefix_macro, path); + wchar_t *relpath = joinpath2( + calculate->platlibdir, + L"python" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) L".zip"); + if (relpath == NULL) { + return _PyStatus_NO_MEMORY(); } + calculate->zip_path = joinpath2(calculate->prefix, relpath); + PyMem_RawFree(relpath); if (calculate->zip_path == NULL) { - res = _PyStatus_NO_MEMORY(); - goto done; + return _PyStatus_NO_MEMORY(); } - res = _PyStatus_OK(); - -done: - PyMem_RawFree(path); - return res; + return _PyStatus_OK(); } @@ -1306,6 +1307,8 @@ static PyStatus calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { + assert(calculate->stdlib_dir != NULL); + /* Calculate size of return buffer */ size_t bufsz = 0; if (calculate->pythonpath_env != NULL) { From 53f75e056c66d9de336da8b7a95d9ee0f5d5beb0 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 8 Oct 2021 15:07:37 -0600 Subject: [PATCH 4/9] Add more location flags. --- Modules/getpath.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index 5e6c0fd2b4d4e9..78c0c2764b5874 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -120,8 +120,13 @@ extern "C" { #define LOCATION_UNKNOWN 0 #define LOCATION_EXISTS 1 -#define LOCATION_FORCED 2 -#define LOCATION_IN_SOURCE_TREE 4 +#define LOCATION_FORCED 2 /* trusted to exist */ +#define LOCATION_DEFAULT 4 /* the default value */ +#define LOCATION_CUSTOM 8 /* from a file or env var */ +#define LOCATION_IN_BUILD_DIR 16 +#define LOCATION_IN_SOURCE_TREE 32 +#define LOCATION_PREFIX 64 +#define LOCATION_NEAR_ARGV0 128 #define LOCATION_FOUND (LOCATION_EXISTS | LOCATION_FORCED) @@ -456,7 +461,8 @@ search_for_stdlib_dir(PyCalculatePath *calculate, } if (module) { /* BUILD_LANDMARK and LANDMARK found */ - *verified |= LOCATION_EXISTS | LOCATION_IN_SOURCE_TREE; + *verified |= LOCATION_EXISTS | LOCATION_NEAR_ARGV0; + *verified |= LOCATION_IN_SOURCE_TREE | LOCATION_IN_BUILD_DIR; return _PyStatus_OK(); } } @@ -481,7 +487,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, return status; } if (module) { - *verified |= LOCATION_EXISTS; + *verified |= LOCATION_EXISTS | LOCATION_NEAR_ARGV0; return _PyStatus_OK(); } stdlib[n] = L'\0'; @@ -504,7 +510,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, return status; } if (module) { - *verified |= LOCATION_EXISTS; + *verified |= LOCATION_EXISTS | LOCATION_PREFIX; return _PyStatus_OK(); } @@ -536,7 +542,7 @@ calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) if (delim) { *delim = L'\0'; } - verified |= LOCATION_FORCED; + verified |= LOCATION_FORCED | LOCATION_CUSTOM; } else { status = search_for_stdlib_dir(calculate, @@ -550,6 +556,7 @@ calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) if (safe_wcscpy(stdlib, prefix, stdlib_len) < 0) { return PATHLEN_ERR(); } + verified |= LOCATION_DEFAULT | LOCATION_PREFIX; } } From 26da17a93bda53efa68ded6fb92dda90916bfb69 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 8 Oct 2021 16:56:36 -0600 Subject: [PATCH 5/9] Add PyCalculatePath.argv0_dir_verified. --- Modules/getpath.c | 132 ++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index 78c0c2764b5874..2c8859219ce31e 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -126,7 +126,8 @@ extern "C" { #define LOCATION_IN_BUILD_DIR 16 #define LOCATION_IN_SOURCE_TREE 32 #define LOCATION_PREFIX 64 -#define LOCATION_NEAR_ARGV0 128 +#define LOCATION_WITH_ARGV0 128 /* in the tree under dirname(argv[0]) */ +#define LOCATION_NEAR_ARGV0 256 /* based on a parent of argv[0] */ #define LOCATION_FOUND (LOCATION_EXISTS | LOCATION_FORCED) @@ -145,6 +146,7 @@ typedef struct { const wchar_t *platlibdir; wchar_t *argv0_dir; + int argv0_dir_verified; /* bit vector of verified LOCATION_* flags */ wchar_t *stdlib_dir; int stdlib_dir_verified; /* bit vector of verified LOCATION_* flags */ @@ -461,7 +463,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, } if (module) { /* BUILD_LANDMARK and LANDMARK found */ - *verified |= LOCATION_EXISTS | LOCATION_NEAR_ARGV0; + *verified |= LOCATION_EXISTS | LOCATION_WITH_ARGV0; *verified |= LOCATION_IN_SOURCE_TREE | LOCATION_IN_BUILD_DIR; return _PyStatus_OK(); } @@ -473,6 +475,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, return status; } + int flag = LOCATION_WITH_ARGV0; do { /* Path: / / LANDMARK */ size_t n = wcslen(stdlib); @@ -487,11 +490,12 @@ search_for_stdlib_dir(PyCalculatePath *calculate, return status; } if (module) { - *verified |= LOCATION_EXISTS | LOCATION_NEAR_ARGV0; + *verified |= LOCATION_EXISTS | flag; return _PyStatus_OK(); } stdlib[n] = L'\0'; reduce(stdlib); + flag = LOCATION_NEAR_ARGV0; } while (stdlib[0]); /* Look at configure's PREFIX. @@ -558,6 +562,14 @@ calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } verified |= LOCATION_DEFAULT | LOCATION_PREFIX; } + else if (verified & LOCATION_WITH_ARGV0) { + calculate->argv0_dir_verified |= verified & LOCATION_EXISTS; + calculate->argv0_dir_verified |= verified & LOCATION_IN_BUILD_DIR; + calculate->argv0_dir_verified |= verified & LOCATION_IN_SOURCE_TREE; + } + if (verified & LOCATION_WITH_ARGV0) { + verified |= LOCATION_NEAR_ARGV0; + } } if (prefix != NULL) { @@ -1043,37 +1055,32 @@ calculate_program(PyCalculatePath *calculate, _PyPathConfig *pathconfig) #if HAVE_READLINK static PyStatus -resolve_symlinks(wchar_t **path_p) +resolve_symlinks(wchar_t *buf, size_t bufsize) { wchar_t new_path[MAXPATHLEN + 1]; const size_t new_path_len = Py_ARRAY_LENGTH(new_path); unsigned int nlink = 0; while (1) { - int linklen = _Py_wreadlink(*path_p, new_path, new_path_len); + int linklen = _Py_wreadlink(buf, new_path, new_path_len); if (linklen == -1) { - /* not a symbolic link: we are done */ + /* We could not read a symbolic link: we are done. + * Note that we are silencing errors here. */ break; } if (_Py_isabs(new_path)) { - PyMem_RawFree(*path_p); - *path_p = _PyMem_RawWcsdup(new_path); - if (*path_p == NULL) { - return _PyStatus_NO_MEMORY(); + if (safe_wcscpy(buf, new_path, bufsize) < 0) { + return PATHLEN_ERR(); } } else { - /* new_path is relative to path */ - reduce(*path_p); - - wchar_t *abs_path = joinpath2(*path_p, new_path); - if (abs_path == NULL) { - return _PyStatus_NO_MEMORY(); + /* new_path is relative to the current one. */ + reduce(buf); + PyStatus status = joinpath(buf, new_path, bufsize); + if (_PyStatus_EXCEPTION(status)) { + return status; } - - PyMem_RawFree(*path_p); - *path_p = abs_path; } nlink++; @@ -1089,7 +1096,8 @@ resolve_symlinks(wchar_t **path_p) #ifdef WITH_NEXT_FRAMEWORK static PyStatus -calculate_argv0_dir_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +calculate_argv0_dir_framework(PyCalculatePath *calculate, _PyPathConfig *pathconfig, + wchar_t *argv0, size_t argv0_len, int *verified) { NSModule pythonModule; @@ -1114,58 +1122,44 @@ calculate_argv0_dir_framework(PyCalculatePath *calculate, _PyPathConfig *pathcon be running the interpreter in the build directory, so we use the build-directory-specific logic to find Lib and such. */ size_t len; - wchar_t* wbuf = Py_DecodeLocale(modPath, &len); - if (wbuf == NULL) { + wchar_t* framework_exe = Py_DecodeLocale(modPath, &len); + if (framework_exe == NULL) { return DECODE_LOCALE_ERR("framework location", len); } /* Path: reduce(modPath) / lib_python / LANDMARK */ - PyStatus status; - - wchar_t *parent = _PyMem_RawWcsdup(wbuf); - if (parent == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; + wchar_t stdlib[MAXPATHLEN+1]; + size_t stdlib_len = Py_ARRAY_LENGTH(stdlib); + if (safe_wcscpy(stdlib, framework_exe, stdlib_len) < 0) { + return PATHLEN_ERR(); } + reduce(stdlib); - reduce(parent); - wchar_t *lib_python = joinpath2(parent, calculate->lib_python); - PyMem_RawFree(parent); - - if (lib_python == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; + PyStatus status = joinpath(stdlib, calculate->lib_python, stdlib_len); + if (_PyStatus_EXCEPTION(status)) { + return status; } int module; - status = ismodule(lib_python, &module); - PyMem_RawFree(lib_python); - + status = ismodule(stdlib, &module); if (_PyStatus_EXCEPTION(status)) { - goto done; + return status; } - if (!module) { - /* We are in the build directory so use the name of the - executable - we know that the absolute path is passed */ - PyMem_RawFree(calculate->argv0_dir); - calculate->argv0_dir = _PyMem_RawWcsdup(pathconfig->program_full_path); - if (calculate->argv0_dir == NULL) { - status = _PyStatus_NO_MEMORY(); - goto done; + if (module) { + /* Use the location of the library as argv0_dir */ + if (safe_wcscpy(argv0, framework_exe, argv0_len) < 0) { + return PATHLEN_ERR(); } - - status = _PyStatus_OK(); - goto done; + *verified |= LOCATION_EXISTS; + // XXX Set calculate->stdlib_dir, etc.? + return _PyStatus_OK(); } - /* Use the location of the library as argv0_dir */ - PyMem_RawFree(calculate->argv0_dir); - calculate->argv0_dir = wbuf; + /* We are in the build directory so use the name of the + executable - we know that the absolute path is passed */ + assert(wcscmp(argv0, pathconfig->program_full_path) == 0); + *verified |= LOCATION_IN_BUILD_DIR; return _PyStatus_OK(); - -done: - PyMem_RawFree(wbuf); - return status; } #endif @@ -1174,26 +1168,38 @@ static PyStatus calculate_argv0_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { + assert(calculate->argv0_dir == NULL); + assert(calculate->argv0_dir_verified == LOCATION_UNKNOWN); + PyStatus status; + wchar_t argv0[MAXPATHLEN+1]; + size_t argv0_len = Py_ARRAY_LENGTH(argv0); + int verified = LOCATION_UNKNOWN; - calculate->argv0_dir = _PyMem_RawWcsdup(pathconfig->program_full_path); - if (calculate->argv0_dir == NULL) { - return _PyStatus_NO_MEMORY(); + if (safe_wcscpy(argv0, pathconfig->program_full_path, argv0_len) < 0) { + return PATHLEN_ERR(); } #ifdef WITH_NEXT_FRAMEWORK - status = calculate_argv0_dir_framework(calculate, pathconfig); + status = calculate_argv0_dir_framework(calculate, pathconfig, + argv0, argv0_len, &verified); if (_PyStatus_EXCEPTION(status)) { return status; } #endif - status = resolve_symlinks(&calculate->argv0_dir); + // XXX Don't we need to wrap this in "#if HAVE_READLINK"? + status = resolve_symlinks(argv0, argv0_len); if (_PyStatus_EXCEPTION(status)) { return status; } - reduce(calculate->argv0_dir); + reduce(argv0); + calculate->argv0_dir = _PyMem_RawWcsdup(argv0); + if (calculate->argv0_dir == NULL) { + return _PyStatus_NO_MEMORY(); + } + calculate->argv0_dir_verified = verified | LOCATION_WITH_ARGV0; return _PyStatus_OK(); } From 957c37585c2b7ae6c9fb602ddb0e98ae8585d465 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 8 Oct 2021 20:25:18 -0600 Subject: [PATCH 6/9] Add PyCalculatePath.extensions. --- Modules/getpath.c | 284 ++++++++++++++++++++++++++-------------------- 1 file changed, 161 insertions(+), 123 deletions(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index 2c8859219ce31e..7315849e1330fc 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -125,9 +125,10 @@ extern "C" { #define LOCATION_CUSTOM 8 /* from a file or env var */ #define LOCATION_IN_BUILD_DIR 16 #define LOCATION_IN_SOURCE_TREE 32 -#define LOCATION_PREFIX 64 -#define LOCATION_WITH_ARGV0 128 /* in the tree under dirname(argv[0]) */ -#define LOCATION_NEAR_ARGV0 256 /* based on a parent of argv[0] */ +#define LOCATION_WITH_ARGV0 64 /* in the tree under dirname(argv[0]) */ +#define LOCATION_NEAR_ARGV0 128 /* based on a parent of argv[0] */ +#define LOCATION_PREFIX 256 +#define LOCATION_EXEC_PREFIX 512 #define LOCATION_FOUND (LOCATION_EXISTS | LOCATION_FORCED) @@ -146,17 +147,21 @@ typedef struct { const wchar_t *platlibdir; wchar_t *argv0_dir; - int argv0_dir_verified; /* bit vector of verified LOCATION_* flags */ + int argv0_dir_verified; /* bit vector of verified LOCATION_* flags */ wchar_t *stdlib_dir; - int stdlib_dir_verified; /* bit vector of verified LOCATION_* flags */ + int stdlib_dir_verified; /* bit vector of verified LOCATION_* flags */ wchar_t *prefix; - int prefix_verified; /* bit vector of verified LOCATION_* flags */ - bool prefix_found; /* found platform independent libraries? */ + int prefix_verified; /* bit vector of verified LOCATION_* flags */ + bool prefix_found; /* found platform independent libraries? */ + + wchar_t *extensions; /* path under exec_prefix where stdlib ext modules are found */ + int extensions_verified; /* bit vector of verified LOCATION_* flags */ wchar_t *exec_prefix; - int exec_prefix_found; /* found the platform dependent libraries? */ + int exec_prefix_verified; /* bit vector of verified LOCATION_* flags */ + bool exec_prefix_found; /* found the platform dependent libraries? */ wchar_t *zip_path; } PyCalculatePath; @@ -567,9 +572,9 @@ calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) calculate->argv0_dir_verified |= verified & LOCATION_IN_BUILD_DIR; calculate->argv0_dir_verified |= verified & LOCATION_IN_SOURCE_TREE; } - if (verified & LOCATION_WITH_ARGV0) { - verified |= LOCATION_NEAR_ARGV0; - } + if (verified & LOCATION_WITH_ARGV0) { + verified |= LOCATION_NEAR_ARGV0; + } } if (prefix != NULL) { @@ -600,7 +605,7 @@ calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) memset(prefix, 0, sizeof(prefix)); size_t prefix_len = Py_ARRAY_LENGTH(prefix); - /* Reduce stdlib_dir to the essense of the prefix, + /* Reduce stdlib_dir to the essence of the prefix, * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. */ if (safe_wcscpy(prefix, calculate->stdlib_dir, prefix_len) < 0) { @@ -652,8 +657,7 @@ calculate_set_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) static PyStatus calculate_pybuilddir(const wchar_t *argv0_dir, - wchar_t *exec_prefix, size_t exec_prefix_len, - int *found) + wchar_t *ext_dir, size_t ext_dir_len, int *verified) { PyStatus status; @@ -686,17 +690,17 @@ calculate_pybuilddir(const wchar_t *argv0_dir, } /* Path: / */ - if (safe_wcscpy(exec_prefix, argv0_dir, exec_prefix_len) < 0) { + if (safe_wcscpy(ext_dir, argv0_dir, ext_dir_len) < 0) { PyMem_RawFree(pybuilddir); return PATHLEN_ERR(); } - status = joinpath(exec_prefix, pybuilddir, exec_prefix_len); + status = joinpath(ext_dir, pybuilddir, ext_dir_len); PyMem_RawFree(pybuilddir); if (_PyStatus_EXCEPTION(status)) { return status; } - *found = -1; + *verified |= LOCATION_IN_BUILD_DIR | LOCATION_CUSTOM; return _PyStatus_OK(); } @@ -705,181 +709,209 @@ calculate_pybuilddir(const wchar_t *argv0_dir, MAXPATHLEN bytes long. */ static PyStatus -search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, - wchar_t *exec_prefix, size_t exec_prefix_len, - int *found) +search_for_extensions(PyCalculatePath *calculate, + wchar_t *ext_dir, size_t ext_dir_len, int *verified) { + assert(*verified == LOCATION_UNKNOWN); PyStatus status; - /* If PYTHONHOME is set, we believe it unconditionally */ - if (pathconfig->home) { - /* Path: / / "lib-dynload" */ - wchar_t *delim = wcschr(pathconfig->home, DELIM); - if (delim) { - if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) { - return PATHLEN_ERR(); - } - } - else { - if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) { - return PATHLEN_ERR(); - } - } - status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - *found = 1; - return _PyStatus_OK(); - } - /* Check for pybuilddir.txt */ - assert(*found == 0); status = calculate_pybuilddir(calculate->argv0_dir, - exec_prefix, exec_prefix_len, found); + ext_dir, ext_dir_len, verified); if (_PyStatus_EXCEPTION(status)) { return status; } - if (*found) { + if (*verified) { return _PyStatus_OK(); } + // XXX Try / "lib-dynload" here first? + /* Search from argv0_dir, until root is found */ - status = copy_absolute(exec_prefix, calculate->argv0_dir, exec_prefix_len); + status = copy_absolute(ext_dir, calculate->argv0_dir, ext_dir_len); if (_PyStatus_EXCEPTION(status)) { return status; } + int flag = LOCATION_WITH_ARGV0; do { /* Path: / / "lib-dynload" */ - size_t n = wcslen(exec_prefix); - status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); + size_t n = wcslen(ext_dir); + status = joinpath(ext_dir, calculate->lib_python, ext_dir_len); if (_PyStatus_EXCEPTION(status)) { return status; } - status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); + status = joinpath(ext_dir, L"lib-dynload", ext_dir_len); if (_PyStatus_EXCEPTION(status)) { return status; } - if (isdir(exec_prefix)) { - *found = 1; + if (isdir(ext_dir)) { + *verified |= LOCATION_EXISTS | flag; return _PyStatus_OK(); } - exec_prefix[n] = L'\0'; - reduce(exec_prefix); - } while (exec_prefix[0]); + ext_dir[n] = L'\0'; + reduce(ext_dir); + flag = LOCATION_NEAR_ARGV0; + } while (ext_dir[0]); /* Look at configure's EXEC_PREFIX. Path: / / "lib-dynload" */ - if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, exec_prefix_len) < 0) { + if (safe_wcscpy(ext_dir, calculate->exec_prefix_macro, ext_dir_len) < 0) { return PATHLEN_ERR(); } - status = joinpath(exec_prefix, calculate->lib_python, exec_prefix_len); + status = joinpath(ext_dir, calculate->lib_python, ext_dir_len); if (_PyStatus_EXCEPTION(status)) { return status; } - status = joinpath(exec_prefix, L"lib-dynload", exec_prefix_len); + status = joinpath(ext_dir, L"lib-dynload", ext_dir_len); if (_PyStatus_EXCEPTION(status)) { return status; } - if (isdir(exec_prefix)) { - *found = 1; + if (isdir(ext_dir)) { + *verified |= LOCATION_EXISTS | LOCATION_EXEC_PREFIX; return _PyStatus_OK(); } /* Fail */ - *found = 0; return _PyStatus_OK(); } static PyStatus -calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) +calculate_extensions_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { PyStatus status; - wchar_t exec_prefix[MAXPATHLEN+1]; - memset(exec_prefix, 0, sizeof(exec_prefix)); - size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix); - - status = search_for_exec_prefix(calculate, pathconfig, - exec_prefix, exec_prefix_len, - &calculate->exec_prefix_found); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + wchar_t extensions[MAXPATHLEN+1]; + memset(extensions, 0, sizeof(extensions)); + size_t extensions_len = Py_ARRAY_LENGTH(extensions); + const wchar_t *exec_prefix = NULL; + int verified = LOCATION_UNKNOWN; - if (!calculate->exec_prefix_found) { - if (calculate->warnings) { - fprintf(stderr, - "Could not find platform dependent libraries \n"); + /* If PYTHONHOME is set, we believe it unconditionally */ + if (pathconfig->home != NULL) { + /* Path: / */ + wchar_t *delim = wcschr(pathconfig->home, DELIM); + if (delim) { + exec_prefix = delim + 1; } - - /* / "lib-dynload" */ - wchar_t *lib_dynload = joinpath2(calculate->platlibdir, - L"lib-dynload"); - if (lib_dynload == NULL) { - return _PyStatus_NO_MEMORY(); + else { + exec_prefix = pathconfig->home; } - - calculate->exec_prefix = joinpath2(calculate->exec_prefix_macro, - lib_dynload); - PyMem_RawFree(lib_dynload); - - if (calculate->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); + if (safe_wcscpy(extensions, exec_prefix, extensions_len) < 0) { + return PATHLEN_ERR(); } + verified |= LOCATION_FORCED | LOCATION_CUSTOM; } else { - /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ - calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix); - if (calculate->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); + status = search_for_extensions(calculate, + extensions, extensions_len, &verified); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + if (*extensions == L'\0') { + /* Fall back to EXEC_PREFIX / / "lib-dynload". */ + exec_prefix = calculate->exec_prefix_macro; + if (safe_wcscpy(extensions, exec_prefix, extensions_len) < 0) { + return PATHLEN_ERR(); + } + verified |= LOCATION_DEFAULT | LOCATION_EXEC_PREFIX; + } + else if (verified & LOCATION_WITH_ARGV0) { + calculate->argv0_dir_verified |= verified & LOCATION_EXISTS; + } + if (verified & LOCATION_WITH_ARGV0) { + verified |= LOCATION_NEAR_ARGV0; } } + + if (exec_prefix != NULL) { + status = joinpath(extensions, calculate->lib_python, extensions_len); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + status = joinpath(extensions, L"lib-dynload", extensions_len); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + } + + calculate->extensions= _PyMem_RawWcsdup(extensions); + if (calculate->extensions== NULL) { + return _PyStatus_NO_MEMORY(); + } + calculate->extensions_verified = verified; + return _PyStatus_OK(); } - static PyStatus -calculate_set_exec_prefix(PyCalculatePath *calculate, - _PyPathConfig *pathconfig) +calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig) { - if (calculate->exec_prefix_found > 0) { - wchar_t *exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix); - if (exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } + assert(calculate->extensions != NULL); + assert(calculate->exec_prefix == NULL); + assert(calculate->exec_prefix_verified == LOCATION_UNKNOWN); + + wchar_t exec_prefix[MAXPATHLEN+1]; + memset(exec_prefix, 0, sizeof(exec_prefix)); + size_t exec_prefix_len = Py_ARRAY_LENGTH(exec_prefix); + int verified = calculate->extensions_verified; + bool found = verified & LOCATION_FOUND; + if (verified & LOCATION_IN_BUILD_DIR) { + /* Fall back to EXEC_PREFIX. */ + if (safe_wcscpy(exec_prefix, calculate->exec_prefix_macro, + exec_prefix_len) < 0) { + return PATHLEN_ERR(); + } + verified = LOCATION_DEFAULT | LOCATION_EXEC_PREFIX; + found = true; + } + else { + /* Reduce extensions to the essence of the exc prefix, + * e.g. /usr/local/lib/python1.5/lib-dynload is reduced to /usr/local. + */ + if (safe_wcscpy(exec_prefix, calculate->extensions, exec_prefix_len) < 0) { + return PATHLEN_ERR(); + } reduce(exec_prefix); reduce(exec_prefix); reduce(exec_prefix); - - if (exec_prefix[0]) { - pathconfig->exec_prefix = exec_prefix; - } - else { - /* empty string: use SEP instead */ - PyMem_RawFree(exec_prefix); - - /* The exec_prefix is the root directory, but reduce() chopped + if (*exec_prefix == L'\0') { + /* exec_prefix is the root directory, but reduce() chopped off the "/". */ - pathconfig->exec_prefix = _PyMem_RawWcsdup(separator); - if (pathconfig->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); - } + wcscpy(exec_prefix, separator); } } - else { - pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix_macro); - if (pathconfig->exec_prefix == NULL) { - return _PyStatus_NO_MEMORY(); + + calculate->exec_prefix = _PyMem_RawWcsdup(exec_prefix); + if (calculate->exec_prefix == NULL) { + return _PyStatus_NO_MEMORY(); + } + calculate->exec_prefix_verified = verified; + calculate->exec_prefix_found = found; + + if (!calculate->exec_prefix_found) { + if (calculate->warnings) { + fprintf(stderr, + "Could not find platform dependent libraries \n"); } } + + return _PyStatus_OK(); +} + + +static PyStatus +calculate_set_exec_prefix(PyCalculatePath *calculate, + _PyPathConfig *pathconfig) +{ + assert(calculate->exec_prefix != NULL); + assert(pathconfig->exec_prefix == NULL); + pathconfig->exec_prefix = _PyMem_RawWcsdup(calculate->exec_prefix); + if (pathconfig->exec_prefix == NULL) { + return _PyStatus_NO_MEMORY(); + } return _PyStatus_OK(); } @@ -1349,7 +1381,7 @@ calculate_module_search_path(PyCalculatePath *calculate, } bufsz += wcslen(calculate->zip_path) + 1; - bufsz += wcslen(calculate->exec_prefix) + 1; + bufsz += wcslen(calculate->extensions) + 1; /* Allocate the buffer */ wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); @@ -1400,7 +1432,7 @@ calculate_module_search_path(PyCalculatePath *calculate, wcscat(buf, delimiter); /* Finally, on goes the directory for dynamic-load modules */ - wcscat(buf, calculate->exec_prefix); + wcscat(buf, calculate->extensions); pathconfig->module_search_path = buf; return _PyStatus_OK(); @@ -1469,6 +1501,7 @@ calculate_free(PyCalculatePath *calculate) PyMem_RawFree(calculate->zip_path); PyMem_RawFree(calculate->argv0_dir); PyMem_RawFree(calculate->stdlib_dir); + PyMem_RawFree(calculate->extensions); PyMem_RawFree(calculate->prefix); PyMem_RawFree(calculate->exec_prefix); } @@ -1513,6 +1546,11 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) return status; } + status = calculate_extensions_dir(calculate, pathconfig); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + status = calculate_exec_prefix(calculate, pathconfig); if (_PyStatus_EXCEPTION(status)) { return status; From 027d88b8e075011859587dbca053fd4454e86458 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 11 Oct 2021 12:24:02 -0600 Subject: [PATCH 7/9] Add LOCATION_NEAR_LIB. --- Include/internal/pycore_pathconfig.h | 17 ++++++++++++++ Modules/getpath.c | 34 ++++++++-------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index a258aab2397660..991dcb3d2aa1cd 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -8,6 +8,23 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#define LOCATION_UNKNOWN 0 +#define LOCATION_EXISTS 2<<0 +#define LOCATION_FORCED 2<<1 /* trusted to exist */ +#define LOCATION_DEFAULT 2<<2 /* the default value */ +#define LOCATION_CUSTOM 2<<3 /* from a file or env var */ +/* build-defined */ +#define LOCATION_PREFIX 2<<10 +#define LOCATION_EXEC_PREFIX 2<<11 +/* build-related */ +#define LOCATION_IN_BUILD_DIR 2<<15 +#define LOCATION_IN_SOURCE_TREE 2<<16 +/* relative */ +#define LOCATION_WITH_FILE 2<<20 /* in the tree under dirname() + (combined with LOCATION_NEAR_*) */ +#define LOCATION_NEAR_ARGV0 2<<21 /* based on a parent of argv[0] */ +#define LOCATION_NEAR_LIB 2<<22 /* based on a parent of DLL/SO file */ + typedef struct _PyPathConfig { /* Full path to the Python program */ wchar_t *program_full_path; diff --git a/Modules/getpath.c b/Modules/getpath.c index 7315849e1330fc..94ccfd5852f7df 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -118,18 +118,6 @@ extern "C" { #define PATHLEN_ERR() _PyStatus_ERR("path configuration: path too long") -#define LOCATION_UNKNOWN 0 -#define LOCATION_EXISTS 1 -#define LOCATION_FORCED 2 /* trusted to exist */ -#define LOCATION_DEFAULT 4 /* the default value */ -#define LOCATION_CUSTOM 8 /* from a file or env var */ -#define LOCATION_IN_BUILD_DIR 16 -#define LOCATION_IN_SOURCE_TREE 32 -#define LOCATION_WITH_ARGV0 64 /* in the tree under dirname(argv[0]) */ -#define LOCATION_NEAR_ARGV0 128 /* based on a parent of argv[0] */ -#define LOCATION_PREFIX 256 -#define LOCATION_EXEC_PREFIX 512 - #define LOCATION_FOUND (LOCATION_EXISTS | LOCATION_FORCED) typedef struct { @@ -468,8 +456,9 @@ search_for_stdlib_dir(PyCalculatePath *calculate, } if (module) { /* BUILD_LANDMARK and LANDMARK found */ - *verified |= LOCATION_EXISTS | LOCATION_WITH_ARGV0; - *verified |= LOCATION_IN_SOURCE_TREE | LOCATION_IN_BUILD_DIR; + *verified |= LOCATION_EXISTS | + LOCATION_NEAR_ARGV0 | LOCATION_WITH_FILE | + LOCATION_IN_SOURCE_TREE | LOCATION_IN_BUILD_DIR; return _PyStatus_OK(); } } @@ -480,7 +469,7 @@ search_for_stdlib_dir(PyCalculatePath *calculate, return status; } - int flag = LOCATION_WITH_ARGV0; + int flag = LOCATION_NEAR_ARGV0 | LOCATION_WITH_FILE; do { /* Path: / / LANDMARK */ size_t n = wcslen(stdlib); @@ -567,14 +556,11 @@ calculate_stdlib_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } verified |= LOCATION_DEFAULT | LOCATION_PREFIX; } - else if (verified & LOCATION_WITH_ARGV0) { + else if (verified & LOCATION_WITH_FILE) { calculate->argv0_dir_verified |= verified & LOCATION_EXISTS; calculate->argv0_dir_verified |= verified & LOCATION_IN_BUILD_DIR; calculate->argv0_dir_verified |= verified & LOCATION_IN_SOURCE_TREE; } - if (verified & LOCATION_WITH_ARGV0) { - verified |= LOCATION_NEAR_ARGV0; - } } if (prefix != NULL) { @@ -733,7 +719,7 @@ search_for_extensions(PyCalculatePath *calculate, return status; } - int flag = LOCATION_WITH_ARGV0; + int flag = LOCATION_NEAR_ARGV0 | LOCATION_WITH_FILE; do { /* Path: / / "lib-dynload" */ size_t n = wcslen(ext_dir); @@ -817,12 +803,9 @@ calculate_extensions_dir(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } verified |= LOCATION_DEFAULT | LOCATION_EXEC_PREFIX; } - else if (verified & LOCATION_WITH_ARGV0) { + else if (verified & LOCATION_WITH_FILE) { calculate->argv0_dir_verified |= verified & LOCATION_EXISTS; } - if (verified & LOCATION_WITH_ARGV0) { - verified |= LOCATION_NEAR_ARGV0; - } } if (exec_prefix != NULL) { @@ -1231,7 +1214,8 @@ calculate_argv0_dir(PyCalculatePath *calculate, if (calculate->argv0_dir == NULL) { return _PyStatus_NO_MEMORY(); } - calculate->argv0_dir_verified = verified | LOCATION_WITH_ARGV0; + calculate->argv0_dir_verified = verified | + LOCATION_NEAR_ARGV0 | LOCATION_WITH_FILE; return _PyStatus_OK(); } From 83171d133d437b6549464e1f2df8ee0f0c0c23c5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 12 Oct 2021 14:21:39 -0600 Subject: [PATCH 8/9] Fix the LOCATION_* values. --- Include/internal/pycore_pathconfig.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index 991dcb3d2aa1cd..c66903abd404c7 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -8,22 +8,22 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#define LOCATION_UNKNOWN 0 -#define LOCATION_EXISTS 2<<0 -#define LOCATION_FORCED 2<<1 /* trusted to exist */ -#define LOCATION_DEFAULT 2<<2 /* the default value */ -#define LOCATION_CUSTOM 2<<3 /* from a file or env var */ +#define LOCATION_UNKNOWN (0) +#define LOCATION_EXISTS (1<<0) +#define LOCATION_FORCED (1<<1) /* trusted to exist */ +#define LOCATION_DEFAULT (1<<2) /* the default value */ +#define LOCATION_CUSTOM (1<<3) /* from a file or env var */ /* build-defined */ -#define LOCATION_PREFIX 2<<10 -#define LOCATION_EXEC_PREFIX 2<<11 +#define LOCATION_PREFIX (1<<10) +#define LOCATION_EXEC_PREFIX (1<<11) /* build-related */ -#define LOCATION_IN_BUILD_DIR 2<<15 -#define LOCATION_IN_SOURCE_TREE 2<<16 +#define LOCATION_IN_BUILD_DIR (1<<15) +#define LOCATION_IN_SOURCE_TREE (1<<16) /* relative */ -#define LOCATION_WITH_FILE 2<<20 /* in the tree under dirname() +#define LOCATION_WITH_FILE (1<<20) /* in the tree under dirname() (combined with LOCATION_NEAR_*) */ -#define LOCATION_NEAR_ARGV0 2<<21 /* based on a parent of argv[0] */ -#define LOCATION_NEAR_LIB 2<<22 /* based on a parent of DLL/SO file */ +#define LOCATION_NEAR_ARGV0 (1<<21) /* based on a parent of argv[0] */ +#define LOCATION_NEAR_LIB (1<<22) /* based on a parent of DLL/SO file */ typedef struct _PyPathConfig { /* Full path to the Python program */ From 8566bd36ae03511cf43029ae2022b45722820b7d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 12 Oct 2021 16:21:55 -0600 Subject: [PATCH 9/9] Preserve existing behavior. --- Modules/getpath.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/getpath.c b/Modules/getpath.c index 94ccfd5852f7df..55514a7544e89d 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1555,7 +1555,9 @@ calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) } if (pathconfig->stdlib_dir == NULL) { - if (calculate->stdlib_dir != NULL) { + // XXX Drop the prefix_found check. stdlib_dir_verified can be + // used where the distinction is needed. + if (calculate->stdlib_dir != NULL && calculate->prefix_found) { pathconfig->stdlib_dir = _PyMem_RawWcsdup(calculate->stdlib_dir); if (pathconfig->stdlib_dir == NULL) { return _PyStatus_NO_MEMORY();