bpo-32030: Add _PyPathConfig_Init() (#4551)
* Add _PyPathConfig_Init() and _PyPathConfig_Fini() * Remove _Py_GetPathWithConfig() * _PyPathConfig_Init() returns _PyInitError to allow to handle errors properly * Add pathconfig_clear() * Windows calculate_path_impl(): replace Py_FatalError() with _PyInitError * Py_FinalizeEx() now calls _PyPathConfig_Fini() to release memory * Fix _Py_InitializeMainInterpreter() regression: don't initialize path config if _disable_importlib is false * PyPathConfig now uses dynamically allocated memory
This commit is contained in:
parent
706cb3162e
commit
9316ee4da2
|
@ -103,8 +103,9 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
|
|||
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
|
||||
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
|
||||
#ifdef Py_BUILD_CORE
|
||||
PyAPI_FUNC(wchar_t *) _Py_GetPathWithConfig(
|
||||
const _PyMainInterpreterConfig *config);
|
||||
PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(
|
||||
const _PyMainInterpreterConfig *main_config);
|
||||
PyAPI_FUNC(void) _PyPathConfig_Fini(void);
|
||||
#endif
|
||||
PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
|
||||
#ifdef MS_WINDOWS
|
||||
|
|
|
@ -109,10 +109,16 @@ extern "C" {
|
|||
#define LANDMARK L"os.py"
|
||||
#endif
|
||||
|
||||
#define DECODE_LOCALE_ERR(NAME, LEN) \
|
||||
((LEN) == (size_t)-2) \
|
||||
? _Py_INIT_USER_ERR("cannot decode " #NAME) \
|
||||
: _Py_INIT_NO_MEMORY()
|
||||
|
||||
|
||||
typedef struct {
|
||||
wchar_t prefix[MAXPATHLEN+1];
|
||||
wchar_t exec_prefix[MAXPATHLEN+1];
|
||||
wchar_t program_name[MAXPATHLEN+1];
|
||||
wchar_t *prefix;
|
||||
wchar_t *exec_prefix;
|
||||
wchar_t *program_name;
|
||||
wchar_t *module_search_path;
|
||||
} PyPathConfig;
|
||||
|
||||
|
@ -361,63 +367,63 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value)
|
|||
bytes long.
|
||||
*/
|
||||
static int
|
||||
search_for_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix)
|
||||
{
|
||||
size_t n;
|
||||
wchar_t *vpath;
|
||||
|
||||
/* If PYTHONHOME is set, we believe it unconditionally */
|
||||
if (calculate->home) {
|
||||
wcsncpy(config->prefix, calculate->home, MAXPATHLEN);
|
||||
config->prefix[MAXPATHLEN] = L'\0';
|
||||
wchar_t *delim = wcschr(config->prefix, DELIM);
|
||||
wcsncpy(prefix, calculate->home, MAXPATHLEN);
|
||||
prefix[MAXPATHLEN] = L'\0';
|
||||
wchar_t *delim = wcschr(prefix, DELIM);
|
||||
if (delim) {
|
||||
*delim = L'\0';
|
||||
}
|
||||
joinpath(config->prefix, calculate->lib_python);
|
||||
joinpath(config->prefix, LANDMARK);
|
||||
joinpath(prefix, calculate->lib_python);
|
||||
joinpath(prefix, LANDMARK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check to see if argv[0] is in the build directory */
|
||||
wcsncpy(config->prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
config->prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->prefix, L"Modules/Setup");
|
||||
if (isfile(config->prefix)) {
|
||||
wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(prefix, L"Modules/Setup");
|
||||
if (isfile(prefix)) {
|
||||
/* Check VPATH to see if argv0_path is in the build directory. */
|
||||
vpath = Py_DecodeLocale(VPATH, NULL);
|
||||
if (vpath != NULL) {
|
||||
wcsncpy(config->prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
config->prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->prefix, vpath);
|
||||
wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(prefix, vpath);
|
||||
PyMem_RawFree(vpath);
|
||||
joinpath(config->prefix, L"Lib");
|
||||
joinpath(config->prefix, LANDMARK);
|
||||
if (ismodule(config->prefix)) {
|
||||
joinpath(prefix, L"Lib");
|
||||
joinpath(prefix, LANDMARK);
|
||||
if (ismodule(prefix)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Search from argv0_path, until root is found */
|
||||
copy_absolute(config->prefix, calculate->argv0_path, MAXPATHLEN+1);
|
||||
copy_absolute(prefix, calculate->argv0_path, MAXPATHLEN+1);
|
||||
do {
|
||||
n = wcslen(config->prefix);
|
||||
joinpath(config->prefix, calculate->lib_python);
|
||||
joinpath(config->prefix, LANDMARK);
|
||||
if (ismodule(config->prefix)) {
|
||||
n = wcslen(prefix);
|
||||
joinpath(prefix, calculate->lib_python);
|
||||
joinpath(prefix, LANDMARK);
|
||||
if (ismodule(prefix)) {
|
||||
return 1;
|
||||
}
|
||||
config->prefix[n] = L'\0';
|
||||
reduce(config->prefix);
|
||||
} while (config->prefix[0]);
|
||||
prefix[n] = L'\0';
|
||||
reduce(prefix);
|
||||
} while (prefix[0]);
|
||||
|
||||
/* Look at configure's PREFIX */
|
||||
wcsncpy(config->prefix, calculate->prefix, MAXPATHLEN);
|
||||
config->prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->prefix, calculate->lib_python);
|
||||
joinpath(config->prefix, LANDMARK);
|
||||
if (ismodule(config->prefix)) {
|
||||
wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
|
||||
prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(prefix, calculate->lib_python);
|
||||
joinpath(prefix, LANDMARK);
|
||||
if (ismodule(prefix)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -427,25 +433,25 @@ search_for_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
|
||||
|
||||
static void
|
||||
calculate_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix)
|
||||
{
|
||||
calculate->prefix_found = search_for_prefix(calculate, config);
|
||||
calculate->prefix_found = search_for_prefix(calculate, prefix);
|
||||
if (!calculate->prefix_found) {
|
||||
if (!Py_FrozenFlag) {
|
||||
fprintf(stderr,
|
||||
"Could not find platform independent libraries <prefix>\n");
|
||||
}
|
||||
wcsncpy(config->prefix, calculate->prefix, MAXPATHLEN);
|
||||
joinpath(config->prefix, calculate->lib_python);
|
||||
wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
|
||||
joinpath(prefix, calculate->lib_python);
|
||||
}
|
||||
else {
|
||||
reduce(config->prefix);
|
||||
reduce(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_reduce_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
|
||||
{
|
||||
/* Reduce prefix and exec_prefix to their essence,
|
||||
* e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
|
||||
|
@ -453,16 +459,16 @@ calculate_reduce_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
* return the compiled-in defaults instead.
|
||||
*/
|
||||
if (calculate->prefix_found > 0) {
|
||||
reduce(config->prefix);
|
||||
reduce(config->prefix);
|
||||
reduce(prefix);
|
||||
reduce(prefix);
|
||||
/* The prefix is the root directory, but reduce() chopped
|
||||
* off the "/". */
|
||||
if (!config->prefix[0]) {
|
||||
wcscpy(config->prefix, separator);
|
||||
if (!prefix[0]) {
|
||||
wcscpy(prefix, separator);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wcsncpy(config->prefix, calculate->prefix, MAXPATHLEN);
|
||||
wcsncpy(prefix, calculate->prefix, MAXPATHLEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,7 +477,7 @@ calculate_reduce_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
MAXPATHLEN bytes long.
|
||||
*/
|
||||
static int
|
||||
search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
|
@ -479,25 +485,25 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
if (calculate->home) {
|
||||
wchar_t *delim = wcschr(calculate->home, DELIM);
|
||||
if (delim) {
|
||||
wcsncpy(config->exec_prefix, delim+1, MAXPATHLEN);
|
||||
wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
|
||||
}
|
||||
else {
|
||||
wcsncpy(config->exec_prefix, calculate->home, MAXPATHLEN);
|
||||
wcsncpy(exec_prefix, calculate->home, MAXPATHLEN);
|
||||
}
|
||||
config->exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->exec_prefix, calculate->lib_python);
|
||||
joinpath(config->exec_prefix, L"lib-dynload");
|
||||
exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(exec_prefix, calculate->lib_python);
|
||||
joinpath(exec_prefix, L"lib-dynload");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
|
||||
is written by setup.py and contains the relative path to the location
|
||||
of shared library modules. */
|
||||
wcsncpy(config->exec_prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
config->exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->exec_prefix, L"pybuilddir.txt");
|
||||
if (isfile(config->exec_prefix)) {
|
||||
FILE *f = _Py_wfopen(config->exec_prefix, L"rb");
|
||||
wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(exec_prefix, L"pybuilddir.txt");
|
||||
if (isfile(exec_prefix)) {
|
||||
FILE *f = _Py_wfopen(exec_prefix, L"rb");
|
||||
if (f == NULL) {
|
||||
errno = 0;
|
||||
}
|
||||
|
@ -516,9 +522,9 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
Py_DECREF(decoded);
|
||||
if (k >= 0) {
|
||||
rel_builddir_path[k] = L'\0';
|
||||
wcsncpy(config->exec_prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
config->exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->exec_prefix, rel_builddir_path);
|
||||
wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN);
|
||||
exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(exec_prefix, rel_builddir_path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -526,24 +532,24 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
}
|
||||
|
||||
/* Search from argv0_path, until root is found */
|
||||
copy_absolute(config->exec_prefix, calculate->argv0_path, MAXPATHLEN+1);
|
||||
copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1);
|
||||
do {
|
||||
n = wcslen(config->exec_prefix);
|
||||
joinpath(config->exec_prefix, calculate->lib_python);
|
||||
joinpath(config->exec_prefix, L"lib-dynload");
|
||||
if (isdir(config->exec_prefix)) {
|
||||
n = wcslen(exec_prefix);
|
||||
joinpath(exec_prefix, calculate->lib_python);
|
||||
joinpath(exec_prefix, L"lib-dynload");
|
||||
if (isdir(exec_prefix)) {
|
||||
return 1;
|
||||
}
|
||||
config->exec_prefix[n] = L'\0';
|
||||
reduce(config->exec_prefix);
|
||||
} while (config->exec_prefix[0]);
|
||||
exec_prefix[n] = L'\0';
|
||||
reduce(exec_prefix);
|
||||
} while (exec_prefix[0]);
|
||||
|
||||
/* Look at configure's EXEC_PREFIX */
|
||||
wcsncpy(config->exec_prefix, calculate->exec_prefix, MAXPATHLEN);
|
||||
config->exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(config->exec_prefix, calculate->lib_python);
|
||||
joinpath(config->exec_prefix, L"lib-dynload");
|
||||
if (isdir(config->exec_prefix)) {
|
||||
wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
|
||||
exec_prefix[MAXPATHLEN] = L'\0';
|
||||
joinpath(exec_prefix, calculate->lib_python);
|
||||
joinpath(exec_prefix, L"lib-dynload");
|
||||
if (isdir(exec_prefix)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -553,41 +559,44 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
|
||||
|
||||
static void
|
||||
calculate_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
|
||||
{
|
||||
calculate->exec_prefix_found = search_for_exec_prefix(calculate, config);
|
||||
calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix);
|
||||
if (!calculate->exec_prefix_found) {
|
||||
if (!Py_FrozenFlag) {
|
||||
fprintf(stderr,
|
||||
"Could not find platform dependent libraries <exec_prefix>\n");
|
||||
}
|
||||
wcsncpy(config->exec_prefix, calculate->exec_prefix, MAXPATHLEN);
|
||||
joinpath(config->exec_prefix, L"lib/lib-dynload");
|
||||
wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
|
||||
joinpath(exec_prefix, L"lib/lib-dynload");
|
||||
}
|
||||
/* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_reduce_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
|
||||
{
|
||||
if (calculate->exec_prefix_found > 0) {
|
||||
reduce(config->exec_prefix);
|
||||
reduce(config->exec_prefix);
|
||||
reduce(config->exec_prefix);
|
||||
if (!config->exec_prefix[0]) {
|
||||
wcscpy(config->exec_prefix, separator);
|
||||
reduce(exec_prefix);
|
||||
reduce(exec_prefix);
|
||||
reduce(exec_prefix);
|
||||
if (!exec_prefix[0]) {
|
||||
wcscpy(exec_prefix, separator);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wcsncpy(config->exec_prefix, calculate->exec_prefix, MAXPATHLEN);
|
||||
wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
static _PyInitError
|
||||
calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
{
|
||||
wchar_t program_name[MAXPATHLEN+1];
|
||||
memset(program_name, 0, sizeof(program_name));
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
||||
uint32_t nsexeclength = MAXPATHLEN;
|
||||
|
@ -603,7 +612,7 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
* $PATH isn't exported, you lose.
|
||||
*/
|
||||
if (wcschr(calculate->program_name, SEP)) {
|
||||
wcsncpy(config->program_name, calculate->program_name, MAXPATHLEN);
|
||||
wcsncpy(program_name, calculate->program_name, MAXPATHLEN);
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
/* On Mac OS X, if a script uses an interpreter of the form
|
||||
|
@ -619,10 +628,10 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
|
||||
execpath[0] == SEP)
|
||||
{
|
||||
size_t r = mbstowcs(config->program_name, execpath, MAXPATHLEN+1);
|
||||
size_t r = mbstowcs(program_name, execpath, MAXPATHLEN+1);
|
||||
if (r == (size_t)-1 || r > MAXPATHLEN) {
|
||||
/* Could not convert execpath, or it's too long. */
|
||||
config->program_name[0] = '\0';
|
||||
program_name[0] = '\0';
|
||||
}
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
|
@ -636,38 +645,44 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
if (len > MAXPATHLEN) {
|
||||
len = MAXPATHLEN;
|
||||
}
|
||||
wcsncpy(config->program_name, path, len);
|
||||
*(config->program_name + len) = '\0';
|
||||
wcsncpy(program_name, path, len);
|
||||
program_name[len] = '\0';
|
||||
}
|
||||
else {
|
||||
wcsncpy(config->program_name, path, MAXPATHLEN);
|
||||
wcsncpy(program_name, path, MAXPATHLEN);
|
||||
}
|
||||
|
||||
joinpath(config->program_name, calculate->program_name);
|
||||
if (isxfile(config->program_name)) {
|
||||
joinpath(program_name, calculate->program_name);
|
||||
if (isxfile(program_name)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!delim) {
|
||||
config->program_name[0] = L'\0';
|
||||
program_name[0] = L'\0';
|
||||
break;
|
||||
}
|
||||
path = delim + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
config->program_name[0] = '\0';
|
||||
program_name[0] = '\0';
|
||||
}
|
||||
if (config->program_name[0] != SEP && config->program_name[0] != '\0') {
|
||||
absolutize(config->program_name);
|
||||
if (program_name[0] != SEP && program_name[0] != '\0') {
|
||||
absolutize(program_name);
|
||||
}
|
||||
|
||||
config->program_name = _PyMem_RawWcsdup(program_name);
|
||||
if (config->program_name == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
static _PyInitError
|
||||
calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name)
|
||||
{
|
||||
wcsncpy(calculate->argv0_path, config->program_name, MAXPATHLEN);
|
||||
wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN);
|
||||
calculate->argv0_path[MAXPATHLEN] = '\0';
|
||||
|
||||
#ifdef WITH_NEXT_FRAMEWORK
|
||||
|
@ -690,9 +705,10 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
** be running the interpreter in the build directory, so we use the
|
||||
** build-directory-specific logic to find Lib and such.
|
||||
*/
|
||||
wchar_t* wbuf = Py_DecodeLocale(modPath, NULL);
|
||||
size_t len;
|
||||
wchar_t* wbuf = Py_DecodeLocale(modPath, &len);
|
||||
if (wbuf == NULL) {
|
||||
Py_FatalError("Cannot decode framework location");
|
||||
return DECODE_LOCALE_ERR("framework location", len);
|
||||
}
|
||||
|
||||
wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
|
||||
|
@ -702,7 +718,7 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
if (!ismodule(calculate->argv0_path)) {
|
||||
/* We are in the build directory so use the name of the
|
||||
executable - we know that the absolute path is passed */
|
||||
wcsncpy(calculate->argv0_path, config->program_name, MAXPATHLEN);
|
||||
wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN);
|
||||
}
|
||||
else {
|
||||
/* Use the location of the library as the program_name */
|
||||
|
@ -714,7 +730,7 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
|
||||
#if HAVE_READLINK
|
||||
wchar_t tmpbuffer[MAXPATHLEN+1];
|
||||
int linklen = _Py_wreadlink(config->program_name, tmpbuffer, MAXPATHLEN);
|
||||
int linklen = _Py_wreadlink(program_name, tmpbuffer, MAXPATHLEN);
|
||||
while (linklen != -1) {
|
||||
if (tmpbuffer[0] == SEP) {
|
||||
/* tmpbuffer should never be longer than MAXPATHLEN,
|
||||
|
@ -733,6 +749,7 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
reduce(calculate->argv0_path);
|
||||
/* At this point, argv0_path is guaranteed to be less than
|
||||
MAXPATHLEN bytes long. */
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
|
@ -777,9 +794,9 @@ calculate_read_pyenv(PyCalculatePath *calculate)
|
|||
|
||||
|
||||
static void
|
||||
calculate_zip_path(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
|
||||
{
|
||||
wcsncpy(calculate->zip_path, config->prefix, MAXPATHLEN);
|
||||
wcsncpy(calculate->zip_path, prefix, MAXPATHLEN);
|
||||
calculate->zip_path[MAXPATHLEN] = L'\0';
|
||||
|
||||
if (calculate->prefix_found > 0) {
|
||||
|
@ -799,8 +816,10 @@ calculate_zip_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
}
|
||||
|
||||
|
||||
static wchar_t *
|
||||
calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
static _PyInitError
|
||||
calculate_module_search_path(PyCalculatePath *calculate,
|
||||
const wchar_t *prefix, const wchar_t *exec_prefix,
|
||||
PyPathConfig *config)
|
||||
{
|
||||
/* Calculate size of return buffer */
|
||||
size_t bufsz = 0;
|
||||
|
@ -809,7 +828,7 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
}
|
||||
|
||||
wchar_t *defpath = calculate->pythonpath;
|
||||
size_t prefixsz = wcslen(config->prefix) + 1;
|
||||
size_t prefixsz = wcslen(prefix) + 1;
|
||||
while (1) {
|
||||
wchar_t *delim = wcschr(defpath, DELIM);
|
||||
|
||||
|
@ -829,13 +848,12 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
}
|
||||
|
||||
bufsz += wcslen(calculate->zip_path) + 1;
|
||||
bufsz += wcslen(config->exec_prefix) + 1;
|
||||
bufsz += wcslen(exec_prefix) + 1;
|
||||
|
||||
/* Allocate the buffer */
|
||||
wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t));
|
||||
if (buf == NULL) {
|
||||
Py_FatalError(
|
||||
"Not enough memory for dynamic PYTHONPATH");
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
buf[0] = '\0';
|
||||
|
||||
|
@ -857,8 +875,8 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
wchar_t *delim = wcschr(defpath, DELIM);
|
||||
|
||||
if (defpath[0] != SEP) {
|
||||
wcscat(buf, config->prefix);
|
||||
if (prefixsz >= 2 && config->prefix[prefixsz - 2] != SEP &&
|
||||
wcscat(buf, prefix);
|
||||
if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP &&
|
||||
defpath[0] != (delim ? DELIM : L'\0'))
|
||||
{
|
||||
/* not empty */
|
||||
|
@ -870,7 +888,7 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
size_t len = delim - defpath + 1;
|
||||
size_t end = wcslen(buf) + len;
|
||||
wcsncat(buf, defpath, len);
|
||||
*(buf + end) = '\0';
|
||||
buf[end] = '\0';
|
||||
}
|
||||
else {
|
||||
wcscat(buf, defpath);
|
||||
|
@ -881,18 +899,13 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
wcscat(buf, delimiter);
|
||||
|
||||
/* Finally, on goes the directory for dynamic-load modules */
|
||||
wcscat(buf, config->exec_prefix);
|
||||
wcscat(buf, exec_prefix);
|
||||
|
||||
return buf;
|
||||
config->module_search_path = buf;
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
#define DECODE_LOCALE_ERR(NAME, LEN) \
|
||||
((LEN) == (size_t)-2) \
|
||||
? _Py_INIT_USER_ERR("failed to decode " #NAME) \
|
||||
: _Py_INIT_NO_MEMORY()
|
||||
|
||||
|
||||
static _PyInitError
|
||||
calculate_init(PyCalculatePath *calculate,
|
||||
const _PyMainInterpreterConfig *main_config)
|
||||
|
@ -941,15 +954,30 @@ calculate_free(PyCalculatePath *calculate)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
static _PyInitError
|
||||
calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
{
|
||||
calculate_progpath(calculate, config);
|
||||
calculate_argv0_path(calculate, config);
|
||||
_PyInitError err = calculate_program_name(calculate, config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = calculate_argv0_path(calculate, config->program_name);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
calculate_read_pyenv(calculate);
|
||||
calculate_prefix(calculate, config);
|
||||
calculate_zip_path(calculate, config);
|
||||
calculate_exec_prefix(calculate, config);
|
||||
|
||||
wchar_t prefix[MAXPATHLEN+1];
|
||||
memset(prefix, 0, sizeof(prefix));
|
||||
calculate_prefix(calculate, prefix);
|
||||
|
||||
calculate_zip_path(calculate, prefix);
|
||||
|
||||
wchar_t exec_prefix[MAXPATHLEN+1];
|
||||
memset(exec_prefix, 0, sizeof(exec_prefix));
|
||||
calculate_exec_prefix(calculate, exec_prefix);
|
||||
|
||||
if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
|
||||
!Py_FrozenFlag)
|
||||
|
@ -958,53 +986,105 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
"Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
|
||||
}
|
||||
|
||||
config->module_search_path = calculate_module_search_path(calculate, config);
|
||||
calculate_reduce_prefix(calculate, config);
|
||||
calculate_reduce_exec_prefix(calculate, config);
|
||||
err = calculate_module_search_path(calculate, prefix, exec_prefix,
|
||||
config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
calculate_reduce_prefix(calculate, prefix);
|
||||
|
||||
config->prefix = _PyMem_RawWcsdup(prefix);
|
||||
if (config->prefix == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
|
||||
calculate_reduce_exec_prefix(calculate, exec_prefix);
|
||||
|
||||
config->exec_prefix = _PyMem_RawWcsdup(exec_prefix);
|
||||
if (config->exec_prefix == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_path(const _PyMainInterpreterConfig *main_config)
|
||||
pathconfig_clear(PyPathConfig *config)
|
||||
{
|
||||
_PyInitError err;
|
||||
#define CLEAR(ATTR) \
|
||||
do { \
|
||||
PyMem_RawFree(ATTR); \
|
||||
ATTR = NULL; \
|
||||
} while (0)
|
||||
|
||||
CLEAR(config->prefix);
|
||||
CLEAR(config->exec_prefix);
|
||||
CLEAR(config->program_name);
|
||||
CLEAR(config->module_search_path);
|
||||
#undef CLEAR
|
||||
}
|
||||
|
||||
|
||||
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
|
||||
and Py_GetProgramFullPath() */
|
||||
_PyInitError
|
||||
_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
|
||||
{
|
||||
if (path_config.module_search_path) {
|
||||
/* Already initialized */
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
PyCalculatePath calculate;
|
||||
memset(&calculate, 0, sizeof(calculate));
|
||||
|
||||
_PyMainInterpreterConfig tmp_config;
|
||||
int use_tmp = (main_config == NULL);
|
||||
if (use_tmp) {
|
||||
tmp_config = _PyMainInterpreterConfig_INIT;
|
||||
err = _PyMainInterpreterConfig_ReadEnv(&tmp_config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto fatal_error;
|
||||
}
|
||||
main_config = &tmp_config;
|
||||
}
|
||||
|
||||
err = calculate_init(&calculate, main_config);
|
||||
_PyInitError err = calculate_init(&calculate, main_config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto fatal_error;
|
||||
goto done;
|
||||
}
|
||||
|
||||
PyPathConfig new_path_config;
|
||||
memset(&new_path_config, 0, sizeof(new_path_config));
|
||||
|
||||
calculate_path_impl(&calculate, &new_path_config);
|
||||
err = calculate_path_impl(&calculate, &new_path_config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
pathconfig_clear(&new_path_config);
|
||||
goto done;
|
||||
}
|
||||
|
||||
path_config = new_path_config;
|
||||
err = _Py_INIT_OK();
|
||||
|
||||
if (use_tmp) {
|
||||
_PyMainInterpreterConfig_Clear(&tmp_config);
|
||||
}
|
||||
done:
|
||||
calculate_free(&calculate);
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
|
||||
fatal_error:
|
||||
if (use_tmp) {
|
||||
_PyMainInterpreterConfig_Clear(&tmp_config);
|
||||
|
||||
static void
|
||||
calculate_path(void)
|
||||
{
|
||||
_PyInitError err;
|
||||
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
|
||||
|
||||
err = _PyMainInterpreterConfig_ReadEnv(&config);
|
||||
if (!_Py_INIT_FAILED(err)) {
|
||||
err = _PyPathConfig_Init(&config);
|
||||
}
|
||||
calculate_free(&calculate);
|
||||
_Py_FatalInitError(err);
|
||||
_PyMainInterpreterConfig_Clear(&config);
|
||||
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
_Py_FatalInitError(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_PyPathConfig_Fini(void)
|
||||
{
|
||||
pathconfig_clear(&path_config);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1012,33 +1092,19 @@ fatal_error:
|
|||
void
|
||||
Py_SetPath(const wchar_t *path)
|
||||
{
|
||||
if (path_config.module_search_path != NULL) {
|
||||
PyMem_RawFree(path_config.module_search_path);
|
||||
path_config.module_search_path = NULL;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
pathconfig_clear(&path_config);
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t *program_name = Py_GetProgramName();
|
||||
wcsncpy(path_config.program_name, program_name, MAXPATHLEN);
|
||||
path_config.exec_prefix[0] = path_config.prefix[0] = L'\0';
|
||||
size_t size = (wcslen(path) + 1) * sizeof(wchar_t);
|
||||
path_config.module_search_path = PyMem_RawMalloc(size);
|
||||
if (path_config.module_search_path != NULL) {
|
||||
wcscpy(path_config.module_search_path, path);
|
||||
}
|
||||
}
|
||||
PyPathConfig new_config;
|
||||
new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName());
|
||||
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
|
||||
new_config.prefix = _PyMem_RawWcsdup(L"");
|
||||
new_config.module_search_path = _PyMem_RawWcsdup(path);
|
||||
|
||||
|
||||
wchar_t *
|
||||
_Py_GetPathWithConfig(const _PyMainInterpreterConfig *main_config)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(main_config);
|
||||
}
|
||||
return path_config.module_search_path;
|
||||
pathconfig_clear(&path_config);
|
||||
path_config = new_config;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1046,7 +1112,7 @@ wchar_t *
|
|||
Py_GetPath(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.module_search_path;
|
||||
}
|
||||
|
@ -1056,7 +1122,7 @@ wchar_t *
|
|||
Py_GetPrefix(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.prefix;
|
||||
}
|
||||
|
@ -1066,7 +1132,7 @@ wchar_t *
|
|||
Py_GetExecPrefix(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.exec_prefix;
|
||||
}
|
||||
|
@ -1076,7 +1142,7 @@ wchar_t *
|
|||
Py_GetProgramFullPath(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.program_name;
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ extern "C" {
|
|||
|
||||
#define DECODE_LOCALE_ERR(NAME, LEN) \
|
||||
(((LEN) == -2) \
|
||||
? _Py_INIT_USER_ERR("failed to decode " #NAME) \
|
||||
? _Py_INIT_USER_ERR("cannot decode " #NAME) \
|
||||
: _Py_INIT_NO_MEMORY())
|
||||
|
||||
|
||||
#define SET_DECODE_ERROR(NAME, LEN) \
|
||||
do { \
|
||||
if ((LEN) == (size_t)-2) { \
|
||||
pymain->err = _Py_INIT_USER_ERR("failed to decode " #NAME); \
|
||||
pymain->err = _Py_INIT_USER_ERR("cannot decode " #NAME); \
|
||||
} \
|
||||
else { \
|
||||
pymain->err = _Py_INIT_NO_MEMORY(); \
|
||||
|
|
322
PC/getpathp.c
322
PC/getpathp.c
|
@ -117,9 +117,9 @@
|
|||
#endif
|
||||
|
||||
typedef struct {
|
||||
wchar_t prefix[MAXPATHLEN+1];
|
||||
wchar_t program_name[MAXPATHLEN+1];
|
||||
wchar_t dllpath[MAXPATHLEN+1];
|
||||
wchar_t *prefix;
|
||||
wchar_t *program_name;
|
||||
wchar_t *dll_path;
|
||||
wchar_t *module_search_path;
|
||||
} PyPathConfig;
|
||||
|
||||
|
@ -483,24 +483,39 @@ done:
|
|||
#endif /* Py_ENABLE_SHARED */
|
||||
|
||||
|
||||
static void
|
||||
get_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
static _PyInitError
|
||||
get_dll_path(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
{
|
||||
wchar_t *path = calculate->path_env;
|
||||
wchar_t dll_path[MAXPATHLEN+1];
|
||||
memset(dll_path, 0, sizeof(dll_path));
|
||||
|
||||
#ifdef Py_ENABLE_SHARED
|
||||
extern HANDLE PyWin_DLLhModule;
|
||||
/* static init of program_name ensures final char remains \0 */
|
||||
if (PyWin_DLLhModule) {
|
||||
if (!GetModuleFileNameW(PyWin_DLLhModule, config->dllpath, MAXPATHLEN)) {
|
||||
config->dllpath[0] = 0;
|
||||
if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) {
|
||||
dll_path[0] = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
config->dllpath[0] = 0;
|
||||
dll_path[0] = 0;
|
||||
#endif
|
||||
if (GetModuleFileNameW(NULL, config->program_name, MAXPATHLEN)) {
|
||||
return;
|
||||
|
||||
config->dll_path = _PyMem_RawWcsdup(dll_path);
|
||||
if (config->dll_path == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
static _PyInitError
|
||||
get_program_name(PyCalculatePath *calculate, PyPathConfig *config)
|
||||
{
|
||||
wchar_t program_name[MAXPATHLEN+1];
|
||||
memset(program_name, 0, sizeof(program_name));
|
||||
|
||||
if (GetModuleFileNameW(NULL, program_name, MAXPATHLEN)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If there is no slash in the argv0 path, then we have to
|
||||
|
@ -514,9 +529,10 @@ get_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
if (wcschr(calculate->program_name, SEP))
|
||||
#endif
|
||||
{
|
||||
wcsncpy(config->program_name, calculate->program_name, MAXPATHLEN);
|
||||
wcsncpy(program_name, calculate->program_name, MAXPATHLEN);
|
||||
}
|
||||
else if (path) {
|
||||
else if (calculate->path_env) {
|
||||
wchar_t *path = calculate->path_env;
|
||||
while (1) {
|
||||
wchar_t *delim = wcschr(path, DELIM);
|
||||
|
||||
|
@ -524,29 +540,36 @@ get_progpath(PyCalculatePath *calculate, PyPathConfig *config)
|
|||
size_t len = delim - path;
|
||||
/* ensure we can't overwrite buffer */
|
||||
len = min(MAXPATHLEN,len);
|
||||
wcsncpy(config->program_name, path, len);
|
||||
*(config->program_name + len) = '\0';
|
||||
wcsncpy(program_name, path, len);
|
||||
program_name[len] = '\0';
|
||||
}
|
||||
else {
|
||||
wcsncpy(config->program_name, path, MAXPATHLEN);
|
||||
wcsncpy(program_name, path, MAXPATHLEN);
|
||||
}
|
||||
|
||||
/* join() is safe for MAXPATHLEN+1 size buffer */
|
||||
join(config->program_name, calculate->program_name);
|
||||
if (exists(config->program_name)) {
|
||||
join(program_name, calculate->program_name);
|
||||
if (exists(program_name)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!delim) {
|
||||
config->program_name[0] = '\0';
|
||||
program_name[0] = '\0';
|
||||
break;
|
||||
}
|
||||
path = delim + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
config->program_name[0] = '\0';
|
||||
program_name[0] = '\0';
|
||||
}
|
||||
|
||||
done:
|
||||
config->program_name = _PyMem_RawWcsdup(program_name);
|
||||
if (config->program_name == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
|
@ -602,12 +625,13 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value)
|
|||
}
|
||||
|
||||
|
||||
static wchar_t*
|
||||
read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite)
|
||||
static int
|
||||
read_pth_file(PyPathConfig *config, wchar_t *prefix, const wchar_t *path,
|
||||
int *isolated, int *nosite)
|
||||
{
|
||||
FILE *sp_file = _Py_wfopen(path, L"r");
|
||||
if (sp_file == NULL) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wcscpy_s(prefix, MAXPATHLEN+1, path);
|
||||
|
@ -680,12 +704,13 @@ read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite)
|
|||
}
|
||||
|
||||
fclose(sp_file);
|
||||
return buf;
|
||||
config->module_search_path = buf;
|
||||
return 1;
|
||||
|
||||
error:
|
||||
PyMem_RawFree(buf);
|
||||
fclose(sp_file);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -704,8 +729,8 @@ calculate_init(PyCalculatePath *calculate,
|
|||
static int
|
||||
get_pth_filename(wchar_t *spbuffer, PyPathConfig *config)
|
||||
{
|
||||
if (config->dllpath[0]) {
|
||||
if (!change_ext(spbuffer, config->dllpath, L"._pth") && exists(spbuffer)) {
|
||||
if (config->dll_path[0]) {
|
||||
if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -719,7 +744,7 @@ get_pth_filename(wchar_t *spbuffer, PyPathConfig *config)
|
|||
|
||||
|
||||
static int
|
||||
calculate_pth_file(PyPathConfig *config)
|
||||
calculate_pth_file(PyPathConfig *config, wchar_t *prefix)
|
||||
{
|
||||
wchar_t spbuffer[MAXPATHLEN+1];
|
||||
|
||||
|
@ -727,13 +752,8 @@ calculate_pth_file(PyPathConfig *config)
|
|||
return 0;
|
||||
}
|
||||
|
||||
config->module_search_path = read_pth_file(spbuffer, config->prefix,
|
||||
&Py_IsolatedFlag,
|
||||
&Py_NoSiteFlag);
|
||||
if (!config->module_search_path) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return read_pth_file(config, prefix, spbuffer,
|
||||
&Py_IsolatedFlag, &Py_NoSiteFlag);
|
||||
}
|
||||
|
||||
|
||||
|
@ -775,43 +795,34 @@ calculate_pyvenv_file(PyCalculatePath *calculate)
|
|||
}
|
||||
|
||||
|
||||
#define INIT_ERR_BUFFER_OVERFLOW() _Py_INIT_ERR("buffer overflow")
|
||||
|
||||
|
||||
static void
|
||||
calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
||||
const _PyMainInterpreterConfig *main_config)
|
||||
calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix)
|
||||
{
|
||||
get_progpath(calculate, config);
|
||||
/* program_name guaranteed \0 terminated in MAXPATH+1 bytes. */
|
||||
wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_name);
|
||||
reduce(calculate->argv0_path);
|
||||
|
||||
/* Search for a sys.path file */
|
||||
if (calculate_pth_file(config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
calculate_pyvenv_file(calculate);
|
||||
|
||||
/* Calculate zip archive path from DLL or exe path */
|
||||
change_ext(calculate->zip_path,
|
||||
config->dllpath[0] ? config->dllpath : config->program_name,
|
||||
L".zip");
|
||||
|
||||
if (calculate->home == NULL || *calculate->home == '\0') {
|
||||
if (calculate->zip_path[0] && exists(calculate->zip_path)) {
|
||||
wcscpy_s(config->prefix, MAXPATHLEN+1, calculate->zip_path);
|
||||
reduce(config->prefix);
|
||||
calculate->home = config->prefix;
|
||||
} else if (search_for_prefix(config->prefix, calculate->argv0_path, LANDMARK)) {
|
||||
calculate->home = config->prefix;
|
||||
wcscpy_s(prefix, MAXPATHLEN+1, calculate->zip_path);
|
||||
reduce(prefix);
|
||||
calculate->home = prefix;
|
||||
}
|
||||
else if (search_for_prefix(prefix, calculate->argv0_path, LANDMARK)) {
|
||||
calculate->home = prefix;
|
||||
}
|
||||
else {
|
||||
calculate->home = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wcscpy_s(config->prefix, MAXPATHLEN+1, calculate->home);
|
||||
wcscpy_s(prefix, MAXPATHLEN+1, calculate->home);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static _PyInitError
|
||||
calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config, wchar_t *prefix)
|
||||
{
|
||||
int skiphome = calculate->home==NULL ? 0 : 1;
|
||||
#ifdef Py_ENABLE_SHARED
|
||||
calculate->machine_path = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
|
||||
|
@ -873,34 +884,34 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
|||
fprintf(stderr, "Using default static path.\n");
|
||||
config->module_search_path = PYTHONPATH;
|
||||
}
|
||||
return;
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
start_buf = buf;
|
||||
|
||||
if (calculate->module_search_path_env) {
|
||||
if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->module_search_path_env)) {
|
||||
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
|
||||
return INIT_ERR_BUFFER_OVERFLOW();
|
||||
}
|
||||
buf = wcschr(buf, L'\0');
|
||||
*buf++ = DELIM;
|
||||
}
|
||||
if (calculate->zip_path[0]) {
|
||||
if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->zip_path)) {
|
||||
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
|
||||
return INIT_ERR_BUFFER_OVERFLOW();
|
||||
}
|
||||
buf = wcschr(buf, L'\0');
|
||||
*buf++ = DELIM;
|
||||
}
|
||||
if (calculate->user_path) {
|
||||
if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->user_path)) {
|
||||
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
|
||||
return INIT_ERR_BUFFER_OVERFLOW();
|
||||
}
|
||||
buf = wcschr(buf, L'\0');
|
||||
*buf++ = DELIM;
|
||||
}
|
||||
if (calculate->machine_path) {
|
||||
if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->machine_path)) {
|
||||
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
|
||||
return INIT_ERR_BUFFER_OVERFLOW();
|
||||
}
|
||||
buf = wcschr(buf, L'\0');
|
||||
*buf++ = DELIM;
|
||||
|
@ -908,7 +919,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
|||
if (calculate->home == NULL) {
|
||||
if (!skipdefault) {
|
||||
if (wcscpy_s(buf, bufsz - (buf - start_buf), PYTHONPATH)) {
|
||||
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
|
||||
return INIT_ERR_BUFFER_OVERFLOW();
|
||||
}
|
||||
buf = wcschr(buf, L'\0');
|
||||
*buf++ = DELIM;
|
||||
|
@ -927,7 +938,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
|||
}
|
||||
if (p[0] == '.' && is_sep(p[1])) {
|
||||
if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->home)) {
|
||||
Py_FatalError("buffer overflow in getpathp.c's calculate_path()");
|
||||
return INIT_ERR_BUFFER_OVERFLOW();
|
||||
}
|
||||
buf = wcschr(buf, L'\0');
|
||||
p++;
|
||||
|
@ -957,7 +968,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
|||
on the path, and that our 'prefix' directory is
|
||||
the parent of that.
|
||||
*/
|
||||
if (config->prefix[0] == L'\0') {
|
||||
if (prefix[0] == L'\0') {
|
||||
wchar_t lookBuf[MAXPATHLEN+1];
|
||||
wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */
|
||||
while (1) {
|
||||
|
@ -974,7 +985,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
|||
lookBuf[nchars] = L'\0';
|
||||
/* Up one level to the parent */
|
||||
reduce(lookBuf);
|
||||
if (search_for_prefix(config->prefix, lookBuf, LANDMARK)) {
|
||||
if (search_for_prefix(prefix, lookBuf, LANDMARK)) {
|
||||
break;
|
||||
}
|
||||
/* If we are out of paths to search - give up */
|
||||
|
@ -986,6 +997,59 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
|||
}
|
||||
|
||||
config->module_search_path = start_buf;
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
static _PyInitError
|
||||
calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config,
|
||||
const _PyMainInterpreterConfig *main_config)
|
||||
{
|
||||
_PyInitError err;
|
||||
|
||||
err = get_dll_path(calculate, config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = get_program_name(calculate, config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* program_name guaranteed \0 terminated in MAXPATH+1 bytes. */
|
||||
wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_name);
|
||||
reduce(calculate->argv0_path);
|
||||
|
||||
wchar_t prefix[MAXPATHLEN+1];
|
||||
memset(prefix, 0, sizeof(prefix));
|
||||
|
||||
/* Search for a sys.path file */
|
||||
if (calculate_pth_file(config, prefix)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
calculate_pyvenv_file(calculate);
|
||||
|
||||
/* Calculate zip archive path from DLL or exe path */
|
||||
change_ext(calculate->zip_path,
|
||||
config->dll_path[0] ? config->dll_path : config->program_name,
|
||||
L".zip");
|
||||
|
||||
calculate_home_prefix(calculate, prefix);
|
||||
|
||||
err = calculate_module_search_path(calculate, config, prefix);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
done:
|
||||
config->prefix = _PyMem_RawWcsdup(prefix);
|
||||
if (config->prefix == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
||||
|
@ -996,47 +1060,85 @@ calculate_free(PyCalculatePath *calculate)
|
|||
PyMem_RawFree(calculate->user_path);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_path(const _PyMainInterpreterConfig *main_config)
|
||||
pathconfig_clear(PyPathConfig *config)
|
||||
{
|
||||
#define CLEAR(ATTR) \
|
||||
do { \
|
||||
PyMem_RawFree(ATTR); \
|
||||
ATTR = NULL; \
|
||||
} while (0)
|
||||
|
||||
CLEAR(config->prefix);
|
||||
CLEAR(config->program_name);
|
||||
CLEAR(config->dll_path);
|
||||
CLEAR(config->module_search_path);
|
||||
#undef CLEAR
|
||||
}
|
||||
|
||||
|
||||
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
|
||||
and Py_GetProgramFullPath() */
|
||||
_PyInitError
|
||||
_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
|
||||
{
|
||||
if (path_config.module_search_path) {
|
||||
/* Already initialized */
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
_PyInitError err;
|
||||
|
||||
PyCalculatePath calculate;
|
||||
memset(&calculate, 0, sizeof(calculate));
|
||||
|
||||
_PyMainInterpreterConfig tmp_config;
|
||||
int use_tmp = (main_config == NULL);
|
||||
if (use_tmp) {
|
||||
tmp_config = _PyMainInterpreterConfig_INIT;
|
||||
err = _PyMainInterpreterConfig_ReadEnv(&tmp_config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto fatal_error;
|
||||
}
|
||||
main_config = &tmp_config;
|
||||
}
|
||||
|
||||
calculate_init(&calculate, main_config);
|
||||
|
||||
PyPathConfig new_path_config;
|
||||
memset(&new_path_config, 0, sizeof(new_path_config));
|
||||
|
||||
calculate_path_impl(&calculate, &new_path_config, main_config);
|
||||
err = calculate_path_impl(&calculate, &new_path_config, main_config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
path_config = new_path_config;
|
||||
err = _Py_INIT_OK();
|
||||
|
||||
if (use_tmp) {
|
||||
_PyMainInterpreterConfig_Clear(&tmp_config);
|
||||
done:
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
pathconfig_clear(&new_path_config);
|
||||
}
|
||||
calculate_free(&calculate);
|
||||
return;
|
||||
|
||||
fatal_error:
|
||||
if (use_tmp) {
|
||||
_PyMainInterpreterConfig_Clear(&tmp_config);
|
||||
}
|
||||
calculate_free(&calculate);
|
||||
_Py_FatalInitError(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_path(void)
|
||||
{
|
||||
_PyInitError err;
|
||||
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
|
||||
|
||||
err = _PyMainInterpreterConfig_ReadEnv(&config);
|
||||
if (!_Py_INIT_FAILED(err)) {
|
||||
err = _PyPathConfig_Init(&config);
|
||||
}
|
||||
_PyMainInterpreterConfig_Clear(&config);
|
||||
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
_Py_FatalInitError(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_PyPathConfig_Fini(void)
|
||||
{
|
||||
pathconfig_clear(&path_config);
|
||||
}
|
||||
|
||||
|
||||
/* External interface */
|
||||
|
||||
|
@ -1044,31 +1146,21 @@ void
|
|||
Py_SetPath(const wchar_t *path)
|
||||
{
|
||||
if (path_config.module_search_path != NULL) {
|
||||
PyMem_RawFree(path_config.module_search_path);
|
||||
path_config.module_search_path = NULL;
|
||||
pathconfig_clear(&path_config);
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t *program_name = Py_GetProgramName();
|
||||
wcsncpy(path_config.program_name, program_name, MAXPATHLEN);
|
||||
path_config.prefix[0] = L'\0';
|
||||
path_config.module_search_path = PyMem_RawMalloc((wcslen(path) + 1) * sizeof(wchar_t));
|
||||
if (path_config.module_search_path != NULL) {
|
||||
wcscpy(path_config.module_search_path, path);
|
||||
}
|
||||
}
|
||||
PyPathConfig new_config;
|
||||
new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName());
|
||||
new_config.prefix = _PyMem_RawWcsdup(L"");
|
||||
new_config.dll_path = _PyMem_RawWcsdup(L"");
|
||||
new_config.module_search_path = _PyMem_RawWcsdup(path);
|
||||
|
||||
|
||||
wchar_t *
|
||||
_Py_GetPathWithConfig(const _PyMainInterpreterConfig *main_config)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(main_config);
|
||||
}
|
||||
return path_config.module_search_path;
|
||||
pathconfig_clear(&path_config);
|
||||
path_config = new_config;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1076,7 +1168,7 @@ wchar_t *
|
|||
Py_GetPath(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.module_search_path;
|
||||
}
|
||||
|
@ -1086,7 +1178,7 @@ wchar_t *
|
|||
Py_GetPrefix(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.prefix;
|
||||
}
|
||||
|
@ -1103,7 +1195,7 @@ wchar_t *
|
|||
Py_GetProgramFullPath(void)
|
||||
{
|
||||
if (!path_config.module_search_path) {
|
||||
calculate_path(NULL);
|
||||
calculate_path();
|
||||
}
|
||||
return path_config.program_name;
|
||||
}
|
||||
|
@ -1129,7 +1221,7 @@ _Py_CheckPython3()
|
|||
|
||||
/* If there is a python3.dll next to the python3y.dll,
|
||||
assume this is a build tree; use that DLL */
|
||||
wcscpy(py3path, path_config.dllpath);
|
||||
wcscpy(py3path, path_config.dll_path);
|
||||
s = wcsrchr(py3path, L'\\');
|
||||
if (!s) {
|
||||
s = py3path;
|
||||
|
|
|
@ -866,11 +866,6 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
|||
/* Now finish configuring the main interpreter */
|
||||
interp->config = *config;
|
||||
|
||||
/* GetPath may initialize state that _PySys_EndInit locks
|
||||
in, and so has to be called first. */
|
||||
/* TODO: Call Py_GetPath() in Py_ReadConfig, rather than here */
|
||||
wchar_t *sys_path = _Py_GetPathWithConfig(&interp->config);
|
||||
|
||||
if (interp->core_config._disable_importlib) {
|
||||
/* Special mode for freeze_importlib: run with no import system
|
||||
*
|
||||
|
@ -880,11 +875,20 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
|||
_PyRuntime.initialized = 1;
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
/* TODO: Report exceptions rather than fatal errors below here */
|
||||
|
||||
if (_PyTime_Init() < 0)
|
||||
return _Py_INIT_ERR("can't initialize time");
|
||||
|
||||
/* GetPath may initialize state that _PySys_EndInit locks
|
||||
in, and so has to be called first. */
|
||||
err = _PyPathConfig_Init(&interp->config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
wchar_t *sys_path = Py_GetPath();
|
||||
|
||||
/* Finish setting up the sys module and import system */
|
||||
PySys_SetPath(sys_path);
|
||||
if (_PySys_EndInit(interp->sysdict) < 0)
|
||||
|
@ -1261,6 +1265,9 @@ Py_FinalizeEx(void)
|
|||
#endif
|
||||
|
||||
call_ll_exitfuncs();
|
||||
|
||||
_PyPathConfig_Fini();
|
||||
|
||||
_PyRuntime_Finalize();
|
||||
return status;
|
||||
}
|
||||
|
@ -1290,6 +1297,7 @@ new_interpreter(PyThreadState **tstate_p)
|
|||
PyInterpreterState *interp;
|
||||
PyThreadState *tstate, *save_tstate;
|
||||
PyObject *bimod, *sysmod;
|
||||
_PyInitError err;
|
||||
|
||||
if (!_PyRuntime.initialized) {
|
||||
return _Py_INIT_ERR("Py_Initialize must be called first");
|
||||
|
@ -1325,10 +1333,13 @@ new_interpreter(PyThreadState **tstate_p)
|
|||
interp->config = main_interp->config;
|
||||
}
|
||||
|
||||
err = _PyPathConfig_Init(&interp->config);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
wchar_t *sys_path = Py_GetPath();
|
||||
|
||||
/* XXX The following is lax in error checking */
|
||||
|
||||
wchar_t *sys_path = _Py_GetPathWithConfig(&interp->config);
|
||||
|
||||
PyObject *modules = PyDict_New();
|
||||
if (modules == NULL) {
|
||||
return _Py_INIT_ERR("can't make modules dictionary");
|
||||
|
@ -1359,7 +1370,6 @@ new_interpreter(PyThreadState **tstate_p)
|
|||
|
||||
if (bimod != NULL && sysmod != NULL) {
|
||||
PyObject *pstderr;
|
||||
_PyInitError err;
|
||||
|
||||
/* Set up a preliminary stderr printer until we have enough
|
||||
infrastructure for the io module in place. */
|
||||
|
|
Loading…
Reference in New Issue