| 
									
										
										
										
											1996-05-28 22:30:17 +00:00
										 |  |  | /* Return the initial module search path. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-08-04 04:20:48 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2023-07-24 20:48:06 +02:00
										 |  |  | #include "pycore_fileutils.h"     // _Py_abspath()
 | 
					
						
							|  |  |  | #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
 | 
					
						
							|  |  |  | #include "pycore_pathconfig.h"    // _PyPathConfig_ReadGlobal()
 | 
					
						
							|  |  |  | #include "pycore_pymem.h"         // _PyMem_RawWcsdup()
 | 
					
						
							| 
									
										
										
										
											2023-10-03 18:53:51 +02:00
										 |  |  | #include "pycore_pystate.h"       // _PyThreadState_GET()
 | 
					
						
							| 
									
										
										
										
											2023-07-24 20:48:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #include "marshal.h"              // PyMarshal_ReadObjectFromString
 | 
					
						
							|  |  |  | #include "osdefs.h"               // DELIM
 | 
					
						
							|  |  |  | #include <wchar.h>
 | 
					
						
							| 
									
										
										
										
											1995-08-04 04:20:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  | #  include <windows.h>            // GetFullPathNameW(), MAX_PATH
 | 
					
						
							|  |  |  | #  include <pathcch.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1995-08-04 04:20:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-26 04:03:06 +00:00
										 |  |  | #ifdef __APPLE__
 | 
					
						
							| 
									
										
										
										
											2023-11-21 13:15:25 +08:00
										 |  |  | #  include <dlfcn.h>
 | 
					
						
							| 
									
										
										
										
											2023-11-22 01:20:57 -05:00
										 |  |  | #  include <mach-o/dyld.h>
 | 
					
						
							| 
									
										
										
										
											1999-01-27 17:53:11 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Reference the precompiled getpath.py */ | 
					
						
							| 
									
										
										
										
											2023-12-18 09:04:40 -08:00
										 |  |  | #include "Python/frozen_modules/getpath.h"
 | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 09:53:09 +01:00
										 |  |  | #if (!defined(PREFIX) || !defined(EXEC_PREFIX) \
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         || !defined(VERSION) || !defined(VPATH) \ | 
					
						
							|  |  |  |         || !defined(PLATLIBDIR)) | 
					
						
							|  |  |  | #error "PREFIX, EXEC_PREFIX, VERSION, VPATH and PLATLIBDIR macros must be defined"
 | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1995-08-04 04:20:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #if !defined(PYTHONPATH)
 | 
					
						
							|  |  |  | #define PYTHONPATH NULL
 | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-09-28 20:00:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #if !defined(PYDEBUGEXT)
 | 
					
						
							|  |  |  | #define PYDEBUGEXT NULL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #if !defined(PYWINVER)
 | 
					
						
							|  |  |  | #ifdef MS_DLL_ID
 | 
					
						
							|  |  |  | #define PYWINVER MS_DLL_ID
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define PYWINVER NULL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-01-19 22:06:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #if !defined(EXE_SUFFIX)
 | 
					
						
							|  |  |  | #if defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(__MINGW32__)
 | 
					
						
							|  |  |  | #define EXE_SUFFIX L".exe"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define EXE_SUFFIX NULL
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-01-19 22:06:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* HELPER FUNCTIONS for getpath.py */ | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_abspath(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							| 
									
										
										
										
											2022-01-14 08:35:42 +09:00
										 |  |  |     wchar_t *path; | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     Py_ssize_t len; | 
					
						
							|  |  |  |     path = PyUnicode_AsWideCharString(pathobj, &len); | 
					
						
							|  |  |  |     if (path) { | 
					
						
							|  |  |  |         wchar_t *abs; | 
					
						
							| 
									
										
										
										
											2022-01-14 08:35:42 +09:00
										 |  |  |         if (_Py_abspath((const wchar_t *)_Py_normpath(path, -1), &abs) == 0 && abs) { | 
					
						
							|  |  |  |             r = PyUnicode_FromWideChar(abs, -1); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             PyMem_RawFree((void *)abs); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_OSError, "failed to make path absolute"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     return r; | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_basename(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-30 14:58:30 +02:00
										 |  |  |     PyObject *path; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &path)) { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-30 14:58:30 +02:00
										 |  |  |     Py_ssize_t end = PyUnicode_GET_LENGTH(path); | 
					
						
							|  |  |  |     Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1); | 
					
						
							|  |  |  |     if (pos < 0) { | 
					
						
							|  |  |  |         return Py_NewRef(path); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyUnicode_Substring(path, pos + 1, end); | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-30 14:58:30 +02:00
										 |  |  |     PyObject *path; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &path)) { | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-30 14:58:30 +02:00
										 |  |  |     Py_ssize_t end = PyUnicode_GET_LENGTH(path); | 
					
						
							|  |  |  |     Py_ssize_t pos = PyUnicode_FindChar(path, SEP, 0, end, -1); | 
					
						
							|  |  |  |     if (pos < 0) { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return PyUnicode_FromStringAndSize(NULL, 0); | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-30 14:58:30 +02:00
										 |  |  |     return PyUnicode_Substring(path, 0, pos); | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_isabs(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     const wchar_t *path; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     path = PyUnicode_AsWideCharString(pathobj, NULL); | 
					
						
							|  |  |  |     if (path) { | 
					
						
							|  |  |  |         r = _Py_isabs(path) ? Py_True : Py_False; | 
					
						
							|  |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |     return Py_XNewRef(r); | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_hassuffix(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2000-09-25 17:00:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     PyObject *suffixobj; | 
					
						
							|  |  |  |     const wchar_t *path; | 
					
						
							|  |  |  |     const wchar_t *suffix; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "UU", &pathobj, &suffixobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     Py_ssize_t len, suffixLen; | 
					
						
							|  |  |  |     path = PyUnicode_AsWideCharString(pathobj, &len); | 
					
						
							|  |  |  |     if (path) { | 
					
						
							|  |  |  |         suffix = PyUnicode_AsWideCharString(suffixobj, &suffixLen); | 
					
						
							|  |  |  |         if (suffix) { | 
					
						
							| 
									
										
										
										
											2021-12-11 15:06:17 +00:00
										 |  |  |             if (suffixLen > len || | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |                 wcsicmp(&path[len - suffixLen], suffix) != 0 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |                 wcscmp(&path[len - suffixLen], suffix) != 0 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |             ) { | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |                 r = Py_NewRef(Py_False); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |                 r = Py_NewRef(Py_True); | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             PyMem_Free((void *)suffix); | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2000-09-25 17:00:24 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     return r; | 
					
						
							| 
									
										
										
										
											2001-09-28 20:00:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2019-10-04 03:53:26 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     const wchar_t *path; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 03:53:26 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     path = PyUnicode_AsWideCharString(pathobj, NULL); | 
					
						
							|  |  |  |     if (path) { | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							| 
									
										
										
										
											2021-12-04 07:04:11 +09:00
										 |  |  |         DWORD attr = GetFileAttributesW(path); | 
					
						
							|  |  |  |         r = (attr != INVALID_FILE_ATTRIBUTES) && | 
					
						
							|  |  |  |             (attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |         struct stat st; | 
					
						
							|  |  |  |         r = (_Py_wstat(path, &st) == 0) && S_ISDIR(st.st_mode) ? Py_True : Py_False; | 
					
						
							| 
									
										
										
										
											2018-10-05 13:38:50 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2018-10-05 13:38:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |     return Py_XNewRef(r); | 
					
						
							| 
									
										
										
										
											2018-10-05 13:38:50 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     const wchar_t *path; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     path = PyUnicode_AsWideCharString(pathobj, NULL); | 
					
						
							|  |  |  |     if (path) { | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							| 
									
										
										
										
											2021-12-04 07:04:11 +09:00
										 |  |  |         DWORD attr = GetFileAttributesW(path); | 
					
						
							|  |  |  |         r = (attr != INVALID_FILE_ATTRIBUTES) && | 
					
						
							|  |  |  |             !(attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False; | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |         struct stat st; | 
					
						
							|  |  |  |         r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : Py_False; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |     return Py_XNewRef(r); | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2021-10-22 17:20:03 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     const wchar_t *path; | 
					
						
							|  |  |  |     Py_ssize_t cchPath; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2021-10-22 17:20:03 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     path = PyUnicode_AsWideCharString(pathobj, &cchPath); | 
					
						
							|  |  |  |     if (path) { | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							| 
									
										
										
										
											2021-12-04 07:04:11 +09:00
										 |  |  |         DWORD attr = GetFileAttributesW(path); | 
					
						
							|  |  |  |         r = (attr != INVALID_FILE_ATTRIBUTES) && | 
					
						
							|  |  |  |             !(attr & FILE_ATTRIBUTE_DIRECTORY) && | 
					
						
							| 
									
										
										
										
											2023-03-01 01:31:21 +01:00
										 |  |  |             (cchPath >= 4) && | 
					
						
							|  |  |  |             (CompareStringOrdinal(path + cchPath - 4, -1, L".exe", -1, 1 /* ignore case */) == CSTR_EQUAL) | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             ? Py_True : Py_False; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         struct stat st; | 
					
						
							|  |  |  |         r = (_Py_wstat(path, &st) == 0) && | 
					
						
							|  |  |  |             S_ISREG(st.st_mode) && | 
					
						
							|  |  |  |             (st.st_mode & 0111) | 
					
						
							|  |  |  |             ? Py_True : Py_False; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2021-10-22 17:20:03 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |     return Py_XNewRef(r); | 
					
						
							| 
									
										
										
										
											2021-10-22 17:20:03 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (!PyTuple_Check(args)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, "requires tuple of arguments"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     Py_ssize_t n = PyTuple_GET_SIZE(args); | 
					
						
							|  |  |  |     if (n == 0) { | 
					
						
							| 
									
										
										
										
											2022-10-05 12:51:58 +03:00
										 |  |  |         return PyUnicode_FromStringAndSize(NULL, 0); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     /* Convert all parts to wchar and accumulate max final length */ | 
					
						
							|  |  |  |     wchar_t **parts = (wchar_t **)PyMem_Malloc(n * sizeof(wchar_t *)); | 
					
						
							| 
									
										
										
										
											2024-02-08 11:40:38 +03:00
										 |  |  |     if (parts == NULL) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     memset(parts, 0, n * sizeof(wchar_t *)); | 
					
						
							|  |  |  |     Py_ssize_t cchFinal = 0; | 
					
						
							|  |  |  |     Py_ssize_t first = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (Py_ssize_t i = 0; i < n; ++i) { | 
					
						
							|  |  |  |         PyObject *s = PyTuple_GET_ITEM(args, i); | 
					
						
							|  |  |  |         Py_ssize_t cch; | 
					
						
							|  |  |  |         if (s == Py_None) { | 
					
						
							|  |  |  |             cch = 0; | 
					
						
							|  |  |  |         } else if (PyUnicode_Check(s)) { | 
					
						
							|  |  |  |             parts[i] = PyUnicode_AsWideCharString(s, &cch); | 
					
						
							|  |  |  |             if (!parts[i]) { | 
					
						
							|  |  |  |                 cchFinal = -1; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             if (_Py_isabs(parts[i])) { | 
					
						
							|  |  |  |                 first = i; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_TypeError, "all arguments to joinpath() must be str or None"); | 
					
						
							|  |  |  |             cchFinal = -1; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         cchFinal += cch + 1; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-09-25 02:54:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     wchar_t *final = cchFinal > 0 ? (wchar_t *)PyMem_Malloc(cchFinal * sizeof(wchar_t)) : NULL; | 
					
						
							|  |  |  |     if (!final) { | 
					
						
							|  |  |  |         for (Py_ssize_t i = 0; i < n; ++i) { | 
					
						
							|  |  |  |             PyMem_Free(parts[i]); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         PyMem_Free(parts); | 
					
						
							|  |  |  |         if (cchFinal) { | 
					
						
							|  |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return PyUnicode_FromStringAndSize(NULL, 0); | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     final[0] = '\0'; | 
					
						
							|  |  |  |     /* Now join all the paths. The final result should be shorter than the buffer */ | 
					
						
							|  |  |  |     for (Py_ssize_t i = 0; i < n; ++i) { | 
					
						
							|  |  |  |         if (!parts[i]) { | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         if (i >= first && final) { | 
					
						
							|  |  |  |             if (!final[0]) { | 
					
						
							|  |  |  |                 /* final is definitely long enough to fit any individual part */ | 
					
						
							|  |  |  |                 wcscpy(final, parts[i]); | 
					
						
							|  |  |  |             } else if (_Py_add_relfile(final, parts[i], cchFinal) < 0) { | 
					
						
							|  |  |  |                 /* if we fail, keep iterating to free memory, but stop adding parts */ | 
					
						
							|  |  |  |                 PyMem_Free(final); | 
					
						
							|  |  |  |                 final = NULL; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         PyMem_Free(parts[i]); | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyMem_Free(parts); | 
					
						
							|  |  |  |     if (!final) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_SystemError, "failed to join paths"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = PyUnicode_FromWideChar(_Py_normpath(final, -1), -1); | 
					
						
							|  |  |  |     PyMem_Free(final); | 
					
						
							|  |  |  |     return r; | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											1995-08-04 04:20:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     const wchar_t *path; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     path = PyUnicode_AsWideCharString(pathobj, NULL); | 
					
						
							|  |  |  |     if (!path) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     FILE *fp = _Py_wfopen(path, L"rb"); | 
					
						
							|  |  |  |     if (!fp) { | 
					
						
							|  |  |  |         PyErr_SetFromErrno(PyExc_OSError); | 
					
						
							| 
									
										
										
										
											2023-08-27 00:35:06 +03:00
										 |  |  |         PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-27 00:35:06 +03:00
										 |  |  |     PyMem_Free((void *)path); | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     r = PyList_New(0); | 
					
						
							|  |  |  |     if (!r) { | 
					
						
							|  |  |  |         fclose(fp); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2010-11-08 23:49:47 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     const size_t MAX_FILE = 32 * 1024; | 
					
						
							|  |  |  |     char *buffer = (char *)PyMem_Malloc(MAX_FILE); | 
					
						
							|  |  |  |     if (!buffer) { | 
					
						
							|  |  |  |         Py_DECREF(r); | 
					
						
							|  |  |  |         fclose(fp); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-09-24 00:55:48 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     size_t cb = fread(buffer, 1, MAX_FILE, fp); | 
					
						
							|  |  |  |     fclose(fp); | 
					
						
							|  |  |  |     if (!cb) { | 
					
						
							|  |  |  |         return r; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (cb >= MAX_FILE) { | 
					
						
							|  |  |  |         Py_DECREF(r); | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_MemoryError, | 
					
						
							|  |  |  |             "cannot read file larger than 32KB during initialization"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     buffer[cb] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     size_t len; | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     wchar_t *wbuffer = _Py_DecodeUTF8_surrogateescape(buffer, cb, &len); | 
					
						
							|  |  |  |     PyMem_Free((void *)buffer); | 
					
						
							|  |  |  |     if (!wbuffer) { | 
					
						
							|  |  |  |         Py_DECREF(r); | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     wchar_t *p1 = wbuffer; | 
					
						
							|  |  |  |     wchar_t *p2 = p1; | 
					
						
							|  |  |  |     while ((p2 = wcschr(p1, L'\n')) != NULL) { | 
					
						
							| 
									
										
										
										
											2021-12-11 13:43:40 +00:00
										 |  |  |         Py_ssize_t cb = p2 - p1; | 
					
						
							|  |  |  |         while (cb >= 0 && (p1[cb] == L'\n' || p1[cb] == L'\r')) { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             --cb; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-11 13:43:40 +00:00
										 |  |  |         PyObject *u = PyUnicode_FromWideChar(p1, cb >= 0 ? cb + 1 : 0); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         if (!u || PyList_Append(r, u) < 0) { | 
					
						
							|  |  |  |             Py_XDECREF(u); | 
					
						
							|  |  |  |             Py_CLEAR(r); | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         Py_DECREF(u); | 
					
						
							|  |  |  |         p1 = p2 + 1; | 
					
						
							| 
									
										
										
										
											2010-08-14 12:34:41 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (r && p1 && *p1) { | 
					
						
							|  |  |  |         PyObject *u = PyUnicode_FromWideChar(p1, -1); | 
					
						
							|  |  |  |         if (!u || PyList_Append(r, u) < 0) { | 
					
						
							|  |  |  |             Py_CLEAR(r); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_XDECREF(u); | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyMem_RawFree(wbuffer); | 
					
						
							|  |  |  |     return r; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-14 12:34:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args) | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *pathobj; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &pathobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #if defined(HAVE_READLINK)
 | 
					
						
							|  |  |  |     /* This readlink calculation only resolves a symlinked file, and
 | 
					
						
							|  |  |  |        does not resolve any path segments. This is consistent with | 
					
						
							|  |  |  |        prior releases, however, the realpath implementation below is | 
					
						
							|  |  |  |        potentially correct in more cases. */ | 
					
						
							|  |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     int nlink = 0; | 
					
						
							|  |  |  |     wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL); | 
					
						
							|  |  |  |     if (!path) { | 
					
						
							|  |  |  |         goto done; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     wchar_t *path2 = _PyMem_RawWcsdup(path); | 
					
						
							|  |  |  |     PyMem_Free((void *)path); | 
					
						
							|  |  |  |     path = path2; | 
					
						
							|  |  |  |     while (path) { | 
					
						
							|  |  |  |         wchar_t resolved[MAXPATHLEN + 1]; | 
					
						
							|  |  |  |         int linklen = _Py_wreadlink(path, resolved, Py_ARRAY_LENGTH(resolved)); | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         if (linklen == -1) { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             r = PyUnicode_FromWideChar(path, -1); | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         if (_Py_isabs(resolved)) { | 
					
						
							|  |  |  |             PyMem_RawFree((void *)path); | 
					
						
							|  |  |  |             path = _PyMem_RawWcsdup(resolved); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             wchar_t *s = wcsrchr(path, SEP); | 
					
						
							|  |  |  |             if (s) { | 
					
						
							|  |  |  |                 *s = L'\0'; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-03-15 13:58:43 +01:00
										 |  |  |             path2 = _Py_join_relfile(path, resolved); | 
					
						
							|  |  |  |             if (path2) { | 
					
						
							|  |  |  |                 path2 = _Py_normpath(path2, -1); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             PyMem_RawFree((void *)path); | 
					
						
							|  |  |  |             path = path2; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |         nlink++; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         /* 40 is the Linux kernel 4.2 limit */ | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |         if (nlink >= 40) { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |             PyErr_SetString(PyExc_OSError, "maximum number of symbolic links reached"); | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (!path) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | done: | 
					
						
							|  |  |  |     PyMem_RawFree((void *)path); | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif defined(HAVE_REALPATH)
 | 
					
						
							|  |  |  |     PyObject *r = NULL; | 
					
						
							|  |  |  |     struct stat st; | 
					
						
							|  |  |  |     const char *narrow = NULL; | 
					
						
							|  |  |  |     wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL); | 
					
						
							|  |  |  |     if (!path) { | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     narrow = Py_EncodeLocale(path, NULL); | 
					
						
							|  |  |  |     if (!narrow) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (lstat(narrow, &st)) { | 
					
						
							|  |  |  |         PyErr_SetFromErrno(PyExc_OSError); | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (!S_ISLNK(st.st_mode)) { | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |         r = Py_NewRef(pathobj); | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |         goto done; | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     wchar_t resolved[MAXPATHLEN+1]; | 
					
						
							|  |  |  |     if (_Py_wrealpath(path, resolved, MAXPATHLEN) == NULL) { | 
					
						
							|  |  |  |         PyErr_SetFromErrno(PyExc_OSError); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         r = PyUnicode_FromWideChar(resolved, -1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  | done: | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyMem_Free((void *)path); | 
					
						
							|  |  |  |     PyMem_Free((void *)narrow); | 
					
						
							|  |  |  |     return r; | 
					
						
							| 
									
										
										
										
											2023-12-13 23:41:43 +00:00
										 |  |  | #elif defined(MS_WINDOWS)
 | 
					
						
							|  |  |  |     HANDLE hFile; | 
					
						
							|  |  |  |     wchar_t resolved[MAXPATHLEN+1]; | 
					
						
							|  |  |  |     int len = 0, err; | 
					
						
							| 
									
										
										
										
											2023-12-14 15:16:39 +00:00
										 |  |  |     Py_ssize_t pathlen; | 
					
						
							| 
									
										
										
										
											2023-12-13 23:41:43 +00:00
										 |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-14 15:16:39 +00:00
										 |  |  |     wchar_t *path = PyUnicode_AsWideCharString(pathobj, &pathlen); | 
					
						
							| 
									
										
										
										
											2023-12-13 23:41:43 +00:00
										 |  |  |     if (!path) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-14 15:16:39 +00:00
										 |  |  |     if (wcslen(path) != pathlen) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "path contains embedded nulls"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-13 23:41:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     hFile = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 
					
						
							|  |  |  |     if (hFile != INVALID_HANDLE_VALUE) { | 
					
						
							|  |  |  |         len = GetFinalPathNameByHandleW(hFile, resolved, MAXPATHLEN, VOLUME_NAME_DOS); | 
					
						
							|  |  |  |         err = len ? 0 : GetLastError(); | 
					
						
							|  |  |  |         CloseHandle(hFile); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         err = GetLastError(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         PyErr_SetFromWindowsErr(err); | 
					
						
							|  |  |  |         result = NULL; | 
					
						
							|  |  |  |     } else if (len <= MAXPATHLEN) { | 
					
						
							|  |  |  |         const wchar_t *p = resolved; | 
					
						
							|  |  |  |         if (0 == wcsncmp(p, L"\\\\?\\", 4)) { | 
					
						
							|  |  |  |             if (GetFileAttributesW(&p[4]) != INVALID_FILE_ATTRIBUTES) { | 
					
						
							|  |  |  |                 p += 4; | 
					
						
							|  |  |  |                 len -= 4; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-14 15:16:39 +00:00
										 |  |  |         if (CompareStringOrdinal(path, (int)pathlen, p, len, TRUE) == CSTR_EQUAL) { | 
					
						
							|  |  |  |             result = Py_NewRef(pathobj); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             result = PyUnicode_FromWideChar(p, len); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-13 23:41:43 +00:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         result = Py_NewRef(pathobj); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyMem_Free(path); | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											1999-01-27 17:53:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |     return Py_NewRef(pathobj); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-04 02:22:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-04-11 17:18:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyMethodDef getpath_methods[] = { | 
					
						
							|  |  |  |     {"abspath", getpath_abspath, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"basename", getpath_basename, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"dirname", getpath_dirname, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"hassuffix", getpath_hassuffix, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"isabs", getpath_isabs, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"isdir", getpath_isdir, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"isfile", getpath_isfile, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"isxfile", getpath_isxfile, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"joinpath", getpath_joinpath, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"readlines", getpath_readlines, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {"realpath", getpath_realpath, METH_VARARGS, NULL}, | 
					
						
							|  |  |  |     {NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Two implementations of warn() to use depending on whether warnings
 | 
					
						
							|  |  |  |    are enabled or not. */ | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_warn(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *msgobj; | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "U", &msgobj)) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     fprintf(stderr, "%s\n", PyUnicode_AsUTF8(msgobj)); | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | getpath_nowarn(PyObject *Py_UNUSED(self), PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | static PyMethodDef getpath_warn_method = {"warn", getpath_warn, METH_VARARGS, NULL}; | 
					
						
							|  |  |  | static PyMethodDef getpath_nowarn_method = {"warn", getpath_nowarn, METH_VARARGS, NULL}; | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add the helper functions to the dict */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | funcs_to_dict(PyObject *dict, int warnings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (PyMethodDef *m = getpath_methods; m->ml_name; ++m) { | 
					
						
							|  |  |  |         PyObject *f = PyCFunction_NewEx(m, NULL, NULL); | 
					
						
							|  |  |  |         if (!f) { | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (PyDict_SetItemString(dict, m->ml_name, f) < 0) { | 
					
						
							|  |  |  |             Py_DECREF(f); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(f); | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyMethodDef *m2 = warnings ? &getpath_warn_method : &getpath_nowarn_method; | 
					
						
							|  |  |  |     PyObject *f = PyCFunction_NewEx(m2, NULL, NULL); | 
					
						
							|  |  |  |     if (!f) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (PyDict_SetItemString(dict, m2->ml_name, f) < 0) { | 
					
						
							|  |  |  |         Py_DECREF(f); | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-10-04 19:53:43 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     Py_DECREF(f); | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add a wide-character string constant to the dict */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | wchar_to_dict(PyObject *dict, const char *key, const wchar_t *s) | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *u; | 
					
						
							|  |  |  |     int r; | 
					
						
							|  |  |  |     if (s && s[0]) { | 
					
						
							|  |  |  |         u = PyUnicode_FromWideChar(s, -1); | 
					
						
							|  |  |  |         if (!u) { | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |         u = Py_NewRef(Py_None); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     r = PyDict_SetItemString(dict, key, u) == 0; | 
					
						
							|  |  |  |     Py_DECREF(u); | 
					
						
							|  |  |  |     return r; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add a narrow string constant to the dict, using default locale decoding */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | decode_to_dict(PyObject *dict, const char *key, const char *s) | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *u = NULL; | 
					
						
							|  |  |  |     int r; | 
					
						
							|  |  |  |     if (s && s[0]) { | 
					
						
							|  |  |  |         size_t len; | 
					
						
							|  |  |  |         const wchar_t *w = Py_DecodeLocale(s, &len); | 
					
						
							|  |  |  |         if (w) { | 
					
						
							|  |  |  |             u = PyUnicode_FromWideChar(w, len); | 
					
						
							|  |  |  |             PyMem_RawFree((void *)w); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!u) { | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-11-14 16:21:23 +01:00
										 |  |  |         u = Py_NewRef(Py_None); | 
					
						
							| 
									
										
										
										
											2020-03-10 09:53:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     r = PyDict_SetItemString(dict, key, u) == 0; | 
					
						
							|  |  |  |     Py_DECREF(u); | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add an environment variable to the dict, optionally clearing it afterwards */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | env_to_dict(PyObject *dict, const char *key, int and_clear) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *u = NULL; | 
					
						
							|  |  |  |     int r = 0; | 
					
						
							|  |  |  |     assert(strncmp(key, "ENV_", 4) == 0); | 
					
						
							|  |  |  |     assert(strlen(key) < 64); | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |     wchar_t wkey[64]; | 
					
						
							|  |  |  |     // Quick convert to wchar_t, since we know key is ASCII
 | 
					
						
							|  |  |  |     wchar_t *wp = wkey; | 
					
						
							|  |  |  |     for (const char *p = &key[4]; *p; ++p) { | 
					
						
							|  |  |  |         assert(*p < 128); | 
					
						
							|  |  |  |         *wp++ = *p; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *wp = L'\0'; | 
					
						
							|  |  |  |     const wchar_t *v = _wgetenv(wkey); | 
					
						
							|  |  |  |     if (v) { | 
					
						
							|  |  |  |         u = PyUnicode_FromWideChar(v, -1); | 
					
						
							|  |  |  |         if (!u) { | 
					
						
							|  |  |  |             PyErr_Clear(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     const char *v = getenv(&key[4]); | 
					
						
							|  |  |  |     if (v) { | 
					
						
							|  |  |  |         size_t len; | 
					
						
							|  |  |  |         const wchar_t *w = Py_DecodeLocale(v, &len); | 
					
						
							|  |  |  |         if (w) { | 
					
						
							|  |  |  |             u = PyUnicode_FromWideChar(w, len); | 
					
						
							|  |  |  |             if (!u) { | 
					
						
							|  |  |  |                 PyErr_Clear(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             PyMem_RawFree((void *)w); | 
					
						
							| 
									
										
										
										
											2019-09-24 18:21:02 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-23 00:12:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     if (u) { | 
					
						
							|  |  |  |         r = PyDict_SetItemString(dict, key, u) == 0; | 
					
						
							|  |  |  |         Py_DECREF(u); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         r = PyDict_SetItemString(dict, key, Py_None) == 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (r && and_clear) { | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |         _wputenv_s(wkey, L""); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         unsetenv(&key[4]); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-10-04 15:25:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     return r; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add an integer constant to the dict */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | int_to_dict(PyObject *dict, const char *key, int v) | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *o; | 
					
						
							|  |  |  |     int r; | 
					
						
							|  |  |  |     o = PyLong_FromLong(v); | 
					
						
							|  |  |  |     if (!o) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     r = PyDict_SetItemString(dict, key, o) == 0; | 
					
						
							|  |  |  |     Py_DECREF(o); | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | winmodule_to_dict(PyObject *dict, const char *key, HMODULE mod) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     wchar_t *buffer = NULL; | 
					
						
							|  |  |  |     for (DWORD cch = 256; buffer == NULL && cch < (1024 * 1024); cch *= 2) { | 
					
						
							|  |  |  |         buffer = (wchar_t*)PyMem_RawMalloc(cch * sizeof(wchar_t)); | 
					
						
							|  |  |  |         if (buffer) { | 
					
						
							|  |  |  |             if (GetModuleFileNameW(mod, buffer, cch) == cch) { | 
					
						
							|  |  |  |                 PyMem_RawFree(buffer); | 
					
						
							|  |  |  |                 buffer = NULL; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     int r = wchar_to_dict(dict, key, buffer); | 
					
						
							|  |  |  |     PyMem_RawFree(buffer); | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add the current executable's path to the dict */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | progname_to_dict(PyObject *dict, const char *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |     return winmodule_to_dict(dict, key, NULL); | 
					
						
							|  |  |  | #elif defined(__APPLE__)
 | 
					
						
							|  |  |  |     char *path; | 
					
						
							|  |  |  |     uint32_t pathLen = 256; | 
					
						
							|  |  |  |     while (pathLen) { | 
					
						
							|  |  |  |         path = PyMem_RawMalloc((pathLen + 1) * sizeof(char)); | 
					
						
							|  |  |  |         if (!path) { | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (_NSGetExecutablePath(path, &pathLen) != 0) { | 
					
						
							|  |  |  |             PyMem_RawFree(path); | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2013-11-16 01:22:04 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         // Only keep if the path is absolute
 | 
					
						
							|  |  |  |         if (path[0] == SEP) { | 
					
						
							|  |  |  |             int r = decode_to_dict(dict, key, path); | 
					
						
							|  |  |  |             PyMem_RawFree(path); | 
					
						
							|  |  |  |             return r; | 
					
						
							| 
									
										
										
										
											2013-11-16 01:22:04 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         // Fall back and store None
 | 
					
						
							|  |  |  |         PyMem_RawFree(path); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     return PyDict_SetItemString(dict, key, Py_None) == 0; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Add the runtime library's path to the dict */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | library_to_dict(PyObject *dict, const char *key) | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #ifdef Py_ENABLE_SHARED
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     extern HMODULE PyWin_DLLhModule; | 
					
						
							|  |  |  |     if (PyWin_DLLhModule) { | 
					
						
							|  |  |  |         return winmodule_to_dict(dict, key, PyWin_DLLhModule); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-03-09 22:09:12 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-12-07 20:09:53 +02:00
										 |  |  | #elif defined(WITH_NEXT_FRAMEWORK)
 | 
					
						
							| 
									
										
										
										
											2021-12-06 20:13:12 +02:00
										 |  |  |     static char modPath[MAXPATHLEN + 1]; | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     static int modPathInitialized = -1; | 
					
						
							|  |  |  |     if (modPathInitialized < 0) { | 
					
						
							|  |  |  |         modPathInitialized = 0; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         /* On Mac OS X we have a special case if we're running from a framework.
 | 
					
						
							|  |  |  |            This is because the python home should be set relative to the library, | 
					
						
							|  |  |  |            which is in the framework, not relative to the executable, which may | 
					
						
							|  |  |  |            be outside of the framework. Except when we're in the build | 
					
						
							|  |  |  |            directory... */ | 
					
						
							| 
									
										
										
										
											2023-11-21 13:15:25 +08:00
										 |  |  |         Dl_info pythonInfo; | 
					
						
							|  |  |  |         if (dladdr(&Py_Initialize, &pythonInfo)) { | 
					
						
							|  |  |  |             if (pythonInfo.dli_fname) { | 
					
						
							|  |  |  |                 strncpy(modPath, pythonInfo.dli_fname, MAXPATHLEN); | 
					
						
							|  |  |  |                 modPathInitialized = 1; | 
					
						
							| 
									
										
										
										
											2021-12-07 20:09:53 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2000-07-08 06:16:37 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (modPathInitialized > 0) { | 
					
						
							|  |  |  |         return decode_to_dict(dict, key, modPath); | 
					
						
							| 
									
										
										
										
											2020-06-11 17:28:52 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     return PyDict_SetItemString(dict, key, Py_None) == 0; | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 23:49:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2021-12-05 19:41:46 +02:00
										 |  |  | _Py_Get_Getpath_CodeObject(void) | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     return PyMarshal_ReadObjectFromString( | 
					
						
							|  |  |  |         (const char*)_Py_M__getpath, sizeof(_Py_M__getpath)); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | /* Perform the actual path calculation.
 | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |    When compute_path_config is 0, this only reads any initialised path | 
					
						
							|  |  |  |    config values into the PyConfig struct. For example, Py_SetHome() or | 
					
						
							|  |  |  |    Py_SetPath(). The only error should be due to failed memory allocation. | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |    When compute_path_config is 1, full path calculation is performed. | 
					
						
							|  |  |  |    The GIL must be held, and there may be filesystem access, side | 
					
						
							|  |  |  |    effects, and potential unraisable errors that are reported directly | 
					
						
							|  |  |  |    to stderr. | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |    Calling this function multiple times on the same PyConfig is only | 
					
						
							|  |  |  |    safe because already-configured values are not recalculated. To | 
					
						
							|  |  |  |    actually recalculate paths, you need a clean PyConfig. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | PyStatus | 
					
						
							|  |  |  | _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyStatus status = _PyPathConfig_ReadGlobal(config); | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (_PyStatus_EXCEPTION(status) || !compute_path_config) { | 
					
						
							| 
									
										
										
										
											2019-05-27 16:39:22 +02:00
										 |  |  |         return status; | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-03 18:53:51 +02:00
										 |  |  |     if (!_PyThreadState_GET()) { | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return PyStatus_Error("cannot calculate path configuration without GIL"); | 
					
						
							| 
									
										
										
										
											2019-03-18 23:54:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *configDict = _PyConfig_AsDict(config); | 
					
						
							|  |  |  |     if (!configDict) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         return PyStatus_NoMemory(); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *dict = PyDict_New(); | 
					
						
							|  |  |  |     if (!dict) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         Py_DECREF(configDict); | 
					
						
							|  |  |  |         return PyStatus_NoMemory(); | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if (PyDict_SetItemString(dict, "config", configDict) < 0) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         Py_DECREF(configDict); | 
					
						
							|  |  |  |         Py_DECREF(dict); | 
					
						
							|  |  |  |         return PyStatus_NoMemory(); | 
					
						
							| 
									
										
										
										
											2021-09-28 12:18:28 -06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     /* reference now held by dict */ | 
					
						
							|  |  |  |     Py_DECREF(configDict); | 
					
						
							| 
									
										
										
										
											2021-09-28 12:18:28 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     PyObject *co = _Py_Get_Getpath_CodeObject(); | 
					
						
							|  |  |  |     if (!co || !PyCode_Check(co)) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         Py_XDECREF(co); | 
					
						
							|  |  |  |         Py_DECREF(dict); | 
					
						
							|  |  |  |         return PyStatus_Error("error reading frozen getpath.py"); | 
					
						
							| 
									
										
										
										
											2019-03-19 02:58:14 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |     PyObject *winreg = PyImport_ImportModule("winreg"); | 
					
						
							|  |  |  |     if (!winreg || PyDict_SetItemString(dict, "winreg", winreg) < 0) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         Py_XDECREF(winreg); | 
					
						
							|  |  |  |         if (PyDict_SetItemString(dict, "winreg", Py_None) < 0) { | 
					
						
							|  |  |  |             PyErr_Clear(); | 
					
						
							|  |  |  |             Py_DECREF(co); | 
					
						
							|  |  |  |             Py_DECREF(dict); | 
					
						
							|  |  |  |             return PyStatus_Error("error importing winreg module"); | 
					
						
							| 
									
										
										
										
											2019-09-23 18:47:29 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         Py_DECREF(winreg); | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     if ( | 
					
						
							|  |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |         !decode_to_dict(dict, "os_name", "nt") || | 
					
						
							|  |  |  | #elif defined(__APPLE__)
 | 
					
						
							|  |  |  |         !decode_to_dict(dict, "os_name", "darwin") || | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         !decode_to_dict(dict, "os_name", "posix") || | 
					
						
							| 
									
										
										
										
											2022-04-05 08:05:36 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef WITH_NEXT_FRAMEWORK
 | 
					
						
							|  |  |  |         !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 1) || | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 0) || | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |         !decode_to_dict(dict, "PREFIX", PREFIX) || | 
					
						
							|  |  |  |         !decode_to_dict(dict, "EXEC_PREFIX", EXEC_PREFIX) || | 
					
						
							|  |  |  |         !decode_to_dict(dict, "PYTHONPATH", PYTHONPATH) || | 
					
						
							|  |  |  |         !decode_to_dict(dict, "VPATH", VPATH) || | 
					
						
							|  |  |  |         !decode_to_dict(dict, "PLATLIBDIR", PLATLIBDIR) || | 
					
						
							|  |  |  |         !decode_to_dict(dict, "PYDEBUGEXT", PYDEBUGEXT) || | 
					
						
							|  |  |  |         !int_to_dict(dict, "VERSION_MAJOR", PY_MAJOR_VERSION) || | 
					
						
							|  |  |  |         !int_to_dict(dict, "VERSION_MINOR", PY_MINOR_VERSION) || | 
					
						
							|  |  |  |         !decode_to_dict(dict, "PYWINVER", PYWINVER) || | 
					
						
							|  |  |  |         !wchar_to_dict(dict, "EXE_SUFFIX", EXE_SUFFIX) || | 
					
						
							|  |  |  |         !env_to_dict(dict, "ENV_PATH", 0) || | 
					
						
							|  |  |  |         !env_to_dict(dict, "ENV_PYTHONHOME", 0) || | 
					
						
							|  |  |  |         !env_to_dict(dict, "ENV_PYTHONEXECUTABLE", 0) || | 
					
						
							|  |  |  |         !env_to_dict(dict, "ENV___PYVENV_LAUNCHER__", 1) || | 
					
						
							|  |  |  |         !progname_to_dict(dict, "real_executable") || | 
					
						
							|  |  |  |         !library_to_dict(dict, "library") || | 
					
						
							|  |  |  |         !wchar_to_dict(dict, "executable_dir", NULL) || | 
					
						
							|  |  |  |         !wchar_to_dict(dict, "py_setpath", _PyPathConfig_GetGlobalModuleSearchPath()) || | 
					
						
							|  |  |  |         !funcs_to_dict(dict, config->pathconfig_warnings) || | 
					
						
							| 
									
										
										
										
											2024-07-11 23:00:28 +02:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							|  |  |  |         !decode_to_dict(dict, "ABI_THREAD", "t") || | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         !decode_to_dict(dict, "ABI_THREAD", "") || | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  | #ifndef MS_WINDOWS
 | 
					
						
							|  |  |  |         PyDict_SetItemString(dict, "winreg", Py_None) < 0 || | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0 | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         Py_DECREF(co); | 
					
						
							|  |  |  |         Py_DECREF(dict); | 
					
						
							| 
									
										
										
										
											2023-11-02 11:16:34 +02:00
										 |  |  |         PyErr_FormatUnraisable("Exception ignored in preparing getpath"); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return PyStatus_Error("error evaluating initial values"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *r = PyEval_EvalCode(co, dict, dict); | 
					
						
							|  |  |  |     Py_DECREF(co); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!r) { | 
					
						
							|  |  |  |         Py_DECREF(dict); | 
					
						
							| 
									
										
										
										
											2023-11-02 11:16:34 +02:00
										 |  |  |         PyErr_FormatUnraisable("Exception ignored in running getpath"); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         return PyStatus_Error("error evaluating path"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(r); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_PyConfig_FromDict(config, configDict) < 0) { | 
					
						
							| 
									
										
										
										
											2023-11-02 11:16:34 +02:00
										 |  |  |         PyErr_FormatUnraisable("Exception ignored in reading getpath results"); | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |         Py_DECREF(dict); | 
					
						
							|  |  |  |         return PyStatus_Error("error getting getpath results"); | 
					
						
							| 
									
										
										
										
											2017-11-25 03:17:57 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     Py_DECREF(dict); | 
					
						
							| 
									
										
										
										
											2017-11-23 17:03:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-03 00:08:42 +00:00
										 |  |  |     return _PyStatus_OK(); | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | } |