Line data Source code
1 : /* Return the initial module search path. */
2 :
3 : #include "Python.h"
4 : #include "marshal.h" // PyMarshal_ReadObjectFromString
5 : #include "osdefs.h" // DELIM
6 : #include "pycore_initconfig.h"
7 : #include "pycore_fileutils.h"
8 : #include "pycore_pathconfig.h"
9 : #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
10 : #include <wchar.h>
11 :
12 : #ifdef MS_WINDOWS
13 : # include <windows.h> // GetFullPathNameW(), MAX_PATH
14 : # include <pathcch.h>
15 : #endif
16 :
17 : #ifdef __APPLE__
18 : # include <mach-o/dyld.h>
19 : #endif
20 :
21 : /* Reference the precompiled getpath.py */
22 : #include "../Python/frozen_modules/getpath.h"
23 :
24 : #if (!defined(PREFIX) || !defined(EXEC_PREFIX) \
25 : || !defined(VERSION) || !defined(VPATH) \
26 : || !defined(PLATLIBDIR))
27 : #error "PREFIX, EXEC_PREFIX, VERSION, VPATH and PLATLIBDIR macros must be defined"
28 : #endif
29 :
30 : #if !defined(PYTHONPATH)
31 : #define PYTHONPATH NULL
32 : #endif
33 :
34 : #if !defined(PYDEBUGEXT)
35 : #define PYDEBUGEXT NULL
36 : #endif
37 :
38 : #if !defined(PYWINVER)
39 : #ifdef MS_DLL_ID
40 : #define PYWINVER MS_DLL_ID
41 : #else
42 : #define PYWINVER NULL
43 : #endif
44 : #endif
45 :
46 : #if !defined(EXE_SUFFIX)
47 : #if defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(__MINGW32__)
48 : #define EXE_SUFFIX L".exe"
49 : #else
50 : #define EXE_SUFFIX NULL
51 : #endif
52 : #endif
53 :
54 :
55 : /* HELPER FUNCTIONS for getpath.py */
56 :
57 : static PyObject *
58 2986 : getpath_abspath(PyObject *Py_UNUSED(self), PyObject *args)
59 : {
60 2986 : PyObject *r = NULL;
61 : PyObject *pathobj;
62 : wchar_t *path;
63 2986 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
64 0 : return NULL;
65 : }
66 : Py_ssize_t len;
67 2986 : path = PyUnicode_AsWideCharString(pathobj, &len);
68 2986 : if (path) {
69 : wchar_t *abs;
70 2986 : if (_Py_abspath((const wchar_t *)_Py_normpath(path, -1), &abs) == 0 && abs) {
71 2986 : r = PyUnicode_FromWideChar(abs, -1);
72 2986 : PyMem_RawFree((void *)abs);
73 : } else {
74 0 : PyErr_SetString(PyExc_OSError, "failed to make path absolute");
75 : }
76 2986 : PyMem_Free((void *)path);
77 : }
78 2986 : return r;
79 : }
80 :
81 :
82 : static PyObject *
83 25 : getpath_basename(PyObject *Py_UNUSED(self), PyObject *args)
84 : {
85 : const char *path;
86 25 : if (!PyArg_ParseTuple(args, "s", &path)) {
87 0 : return NULL;
88 : }
89 25 : const char *name = strrchr(path, SEP);
90 25 : return PyUnicode_FromString(name ? name + 1 : path);
91 : }
92 :
93 :
94 : static PyObject *
95 9476 : getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args)
96 : {
97 : const char *path;
98 9476 : if (!PyArg_ParseTuple(args, "s", &path)) {
99 0 : return NULL;
100 : }
101 9476 : const char *name = strrchr(path, SEP);
102 9476 : if (!name) {
103 10 : return PyUnicode_FromStringAndSize(NULL, 0);
104 : }
105 9466 : return PyUnicode_FromStringAndSize(path, (name - path));
106 : }
107 :
108 :
109 : static PyObject *
110 0 : getpath_isabs(PyObject *Py_UNUSED(self), PyObject *args)
111 : {
112 0 : PyObject *r = NULL;
113 : PyObject *pathobj;
114 : const wchar_t *path;
115 0 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
116 0 : return NULL;
117 : }
118 0 : path = PyUnicode_AsWideCharString(pathobj, NULL);
119 0 : if (path) {
120 0 : r = _Py_isabs(path) ? Py_True : Py_False;
121 0 : PyMem_Free((void *)path);
122 : }
123 0 : Py_XINCREF(r);
124 0 : return r;
125 : }
126 :
127 :
128 : static PyObject *
129 0 : getpath_hassuffix(PyObject *Py_UNUSED(self), PyObject *args)
130 : {
131 0 : PyObject *r = NULL;
132 : PyObject *pathobj;
133 : PyObject *suffixobj;
134 : const wchar_t *path;
135 : const wchar_t *suffix;
136 0 : if (!PyArg_ParseTuple(args, "UU", &pathobj, &suffixobj)) {
137 0 : return NULL;
138 : }
139 : Py_ssize_t len, suffixLen;
140 0 : path = PyUnicode_AsWideCharString(pathobj, &len);
141 0 : if (path) {
142 0 : suffix = PyUnicode_AsWideCharString(suffixobj, &suffixLen);
143 0 : if (suffix) {
144 0 : if (suffixLen > len ||
145 : #ifdef MS_WINDOWS
146 : wcsicmp(&path[len - suffixLen], suffix) != 0
147 : #else
148 0 : wcscmp(&path[len - suffixLen], suffix) != 0
149 : #endif
150 : ) {
151 0 : r = Py_False;
152 : } else {
153 0 : r = Py_True;
154 : }
155 0 : Py_INCREF(r);
156 0 : PyMem_Free((void *)suffix);
157 : }
158 0 : PyMem_Free((void *)path);
159 : }
160 0 : return r;
161 : }
162 :
163 :
164 : static PyObject *
165 1 : getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args)
166 : {
167 1 : PyObject *r = NULL;
168 : PyObject *pathobj;
169 : const wchar_t *path;
170 1 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
171 0 : return NULL;
172 : }
173 1 : path = PyUnicode_AsWideCharString(pathobj, NULL);
174 1 : if (path) {
175 : #ifdef MS_WINDOWS
176 : DWORD attr = GetFileAttributesW(path);
177 : r = (attr != INVALID_FILE_ATTRIBUTES) &&
178 : (attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False;
179 : #else
180 : struct stat st;
181 1 : r = (_Py_wstat(path, &st) == 0) && S_ISDIR(st.st_mode) ? Py_True : Py_False;
182 : #endif
183 1 : PyMem_Free((void *)path);
184 : }
185 1 : Py_XINCREF(r);
186 1 : return r;
187 : }
188 :
189 :
190 : static PyObject *
191 3212 : getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args)
192 : {
193 3212 : PyObject *r = NULL;
194 : PyObject *pathobj;
195 : const wchar_t *path;
196 3212 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
197 0 : return NULL;
198 : }
199 3212 : path = PyUnicode_AsWideCharString(pathobj, NULL);
200 3212 : if (path) {
201 : #ifdef MS_WINDOWS
202 : DWORD attr = GetFileAttributesW(path);
203 : r = (attr != INVALID_FILE_ATTRIBUTES) &&
204 : !(attr & FILE_ATTRIBUTE_DIRECTORY) ? Py_True : Py_False;
205 : #else
206 : struct stat st;
207 3212 : r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : Py_False;
208 : #endif
209 3212 : PyMem_Free((void *)path);
210 : }
211 3212 : Py_XINCREF(r);
212 3212 : return r;
213 : }
214 :
215 :
216 : static PyObject *
217 124 : getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args)
218 : {
219 124 : PyObject *r = NULL;
220 : PyObject *pathobj;
221 : const wchar_t *path;
222 : Py_ssize_t cchPath;
223 124 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
224 0 : return NULL;
225 : }
226 124 : path = PyUnicode_AsWideCharString(pathobj, &cchPath);
227 124 : if (path) {
228 : #ifdef MS_WINDOWS
229 : const wchar_t *ext;
230 : DWORD attr = GetFileAttributesW(path);
231 : r = (attr != INVALID_FILE_ATTRIBUTES) &&
232 : !(attr & FILE_ATTRIBUTE_DIRECTORY) &&
233 : SUCCEEDED(PathCchFindExtension(path, cchPath + 1, &ext)) &&
234 : (CompareStringOrdinal(ext, -1, L".exe", -1, 1 /* ignore case */) == CSTR_EQUAL)
235 : ? Py_True : Py_False;
236 : #else
237 : struct stat st;
238 124 : r = (_Py_wstat(path, &st) == 0) &&
239 3 : S_ISREG(st.st_mode) &&
240 3 : (st.st_mode & 0111)
241 127 : ? Py_True : Py_False;
242 : #endif
243 124 : PyMem_Free((void *)path);
244 : }
245 124 : Py_XINCREF(r);
246 124 : return r;
247 : }
248 :
249 :
250 : static PyObject *
251 25699 : getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args)
252 : {
253 25699 : if (!PyTuple_Check(args)) {
254 0 : PyErr_SetString(PyExc_TypeError, "requires tuple of arguments");
255 0 : return NULL;
256 : }
257 25699 : Py_ssize_t n = PyTuple_GET_SIZE(args);
258 25699 : if (n == 0) {
259 0 : return PyUnicode_FromString(NULL);
260 : }
261 : /* Convert all parts to wchar and accumulate max final length */
262 25699 : wchar_t **parts = (wchar_t **)PyMem_Malloc(n * sizeof(wchar_t *));
263 25699 : memset(parts, 0, n * sizeof(wchar_t *));
264 25699 : Py_ssize_t cchFinal = 0;
265 25699 : Py_ssize_t first = 0;
266 :
267 77097 : for (Py_ssize_t i = 0; i < n; ++i) {
268 51398 : PyObject *s = PyTuple_GET_ITEM(args, i);
269 : Py_ssize_t cch;
270 51398 : if (s == Py_None) {
271 3164 : cch = 0;
272 48234 : } else if (PyUnicode_Check(s)) {
273 48234 : parts[i] = PyUnicode_AsWideCharString(s, &cch);
274 48234 : if (!parts[i]) {
275 0 : cchFinal = -1;
276 0 : break;
277 : }
278 48234 : if (_Py_isabs(parts[i])) {
279 26094 : first = i;
280 : }
281 : } else {
282 0 : PyErr_SetString(PyExc_TypeError, "all arguments to joinpath() must be str or None");
283 0 : cchFinal = -1;
284 0 : break;
285 : }
286 51398 : cchFinal += cch + 1;
287 : }
288 :
289 25699 : wchar_t *final = cchFinal > 0 ? (wchar_t *)PyMem_Malloc(cchFinal * sizeof(wchar_t)) : NULL;
290 25699 : if (!final) {
291 0 : for (Py_ssize_t i = 0; i < n; ++i) {
292 0 : PyMem_Free(parts[i]);
293 : }
294 0 : PyMem_Free(parts);
295 0 : if (cchFinal) {
296 0 : PyErr_NoMemory();
297 0 : return NULL;
298 : }
299 0 : return PyUnicode_FromStringAndSize(NULL, 0);
300 : }
301 :
302 25699 : final[0] = '\0';
303 : /* Now join all the paths. The final result should be shorter than the buffer */
304 77097 : for (Py_ssize_t i = 0; i < n; ++i) {
305 51398 : if (!parts[i]) {
306 3164 : continue;
307 : }
308 48234 : if (i >= first && final) {
309 47829 : if (!final[0]) {
310 : /* final is definitely long enough to fit any individual part */
311 25707 : wcscpy(final, parts[i]);
312 22122 : } else if (_Py_add_relfile(final, parts[i], cchFinal) < 0) {
313 : /* if we fail, keep iterating to free memory, but stop adding parts */
314 0 : PyMem_Free(final);
315 0 : final = NULL;
316 : }
317 : }
318 48234 : PyMem_Free(parts[i]);
319 : }
320 25699 : PyMem_Free(parts);
321 25699 : if (!final) {
322 0 : PyErr_SetString(PyExc_SystemError, "failed to join paths");
323 0 : return NULL;
324 : }
325 25699 : PyObject *r = PyUnicode_FromWideChar(_Py_normpath(final, -1), -1);
326 25699 : PyMem_Free(final);
327 25699 : return r;
328 : }
329 :
330 :
331 : static PyObject *
332 15778 : getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args)
333 : {
334 15778 : PyObject *r = NULL;
335 : PyObject *pathobj;
336 : const wchar_t *path;
337 15778 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
338 0 : return NULL;
339 : }
340 15778 : path = PyUnicode_AsWideCharString(pathobj, NULL);
341 15778 : if (!path) {
342 0 : return NULL;
343 : }
344 15778 : FILE *fp = _Py_wfopen(path, L"rb");
345 15778 : PyMem_Free((void *)path);
346 15778 : if (!fp) {
347 12595 : PyErr_SetFromErrno(PyExc_OSError);
348 12595 : return NULL;
349 : }
350 :
351 3183 : r = PyList_New(0);
352 3183 : if (!r) {
353 0 : fclose(fp);
354 0 : return NULL;
355 : }
356 3183 : const size_t MAX_FILE = 32 * 1024;
357 3183 : char *buffer = (char *)PyMem_Malloc(MAX_FILE);
358 3183 : if (!buffer) {
359 0 : Py_DECREF(r);
360 0 : fclose(fp);
361 0 : return NULL;
362 : }
363 :
364 3183 : size_t cb = fread(buffer, 1, MAX_FILE, fp);
365 3183 : fclose(fp);
366 3183 : if (!cb) {
367 0 : return r;
368 : }
369 3183 : if (cb >= MAX_FILE) {
370 0 : Py_DECREF(r);
371 0 : PyErr_SetString(PyExc_MemoryError,
372 : "cannot read file larger than 32KB during initialization");
373 0 : return NULL;
374 : }
375 3183 : buffer[cb] = '\0';
376 :
377 : size_t len;
378 3183 : wchar_t *wbuffer = _Py_DecodeUTF8_surrogateescape(buffer, cb, &len);
379 3183 : PyMem_Free((void *)buffer);
380 3183 : if (!wbuffer) {
381 0 : Py_DECREF(r);
382 0 : PyErr_NoMemory();
383 0 : return NULL;
384 : }
385 :
386 3183 : wchar_t *p1 = wbuffer;
387 3183 : wchar_t *p2 = p1;
388 3782 : while ((p2 = wcschr(p1, L'\n')) != NULL) {
389 599 : Py_ssize_t cb = p2 - p1;
390 1198 : while (cb >= 0 && (p1[cb] == L'\n' || p1[cb] == L'\r')) {
391 599 : --cb;
392 : }
393 599 : PyObject *u = PyUnicode_FromWideChar(p1, cb >= 0 ? cb + 1 : 0);
394 599 : if (!u || PyList_Append(r, u) < 0) {
395 0 : Py_XDECREF(u);
396 0 : Py_CLEAR(r);
397 0 : break;
398 : }
399 599 : Py_DECREF(u);
400 599 : p1 = p2 + 1;
401 : }
402 3183 : if (r && p1 && *p1) {
403 3142 : PyObject *u = PyUnicode_FromWideChar(p1, -1);
404 3142 : if (!u || PyList_Append(r, u) < 0) {
405 0 : Py_CLEAR(r);
406 : }
407 3142 : Py_XDECREF(u);
408 : }
409 3183 : PyMem_RawFree(wbuffer);
410 3183 : return r;
411 : }
412 :
413 :
414 : static PyObject *
415 3209 : getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args)
416 : {
417 : PyObject *pathobj;
418 3209 : if (!PyArg_ParseTuple(args, "U", &pathobj)) {
419 0 : return NULL;
420 : }
421 : #if defined(HAVE_READLINK)
422 : /* This readlink calculation only resolves a symlinked file, and
423 : does not resolve any path segments. This is consistent with
424 : prior releases, however, the realpath implementation below is
425 : potentially correct in more cases. */
426 3209 : PyObject *r = NULL;
427 3209 : int nlink = 0;
428 3209 : wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL);
429 3209 : if (!path) {
430 0 : goto done;
431 : }
432 3209 : wchar_t *path2 = _PyMem_RawWcsdup(path);
433 3209 : PyMem_Free((void *)path);
434 3209 : path = path2;
435 3242 : while (path) {
436 : wchar_t resolved[MAXPATHLEN + 1];
437 3242 : int linklen = _Py_wreadlink(path, resolved, Py_ARRAY_LENGTH(resolved));
438 3242 : if (linklen == -1) {
439 3209 : r = PyUnicode_FromWideChar(path, -1);
440 3209 : break;
441 : }
442 33 : if (_Py_isabs(resolved)) {
443 31 : PyMem_RawFree((void *)path);
444 31 : path = _PyMem_RawWcsdup(resolved);
445 : } else {
446 2 : wchar_t *s = wcsrchr(path, SEP);
447 2 : if (s) {
448 2 : *s = L'\0';
449 : }
450 2 : path2 = _Py_normpath(_Py_join_relfile(path, resolved), -1);
451 2 : PyMem_RawFree((void *)path);
452 2 : path = path2;
453 : }
454 33 : nlink++;
455 : /* 40 is the Linux kernel 4.2 limit */
456 33 : if (nlink >= 40) {
457 0 : PyErr_SetString(PyExc_OSError, "maximum number of symbolic links reached");
458 0 : break;
459 : }
460 : }
461 3209 : if (!path) {
462 0 : PyErr_NoMemory();
463 : }
464 3209 : done:
465 3209 : PyMem_RawFree((void *)path);
466 3209 : return r;
467 :
468 : #elif defined(HAVE_REALPATH)
469 : PyObject *r = NULL;
470 : struct stat st;
471 : const char *narrow = NULL;
472 : wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL);
473 : if (!path) {
474 : goto done;
475 : }
476 : narrow = Py_EncodeLocale(path, NULL);
477 : if (!narrow) {
478 : PyErr_NoMemory();
479 : goto done;
480 : }
481 : if (lstat(narrow, &st)) {
482 : PyErr_SetFromErrno(PyExc_OSError);
483 : goto done;
484 : }
485 : if (!S_ISLNK(st.st_mode)) {
486 : Py_INCREF(pathobj);
487 : r = pathobj;
488 : goto done;
489 : }
490 : wchar_t resolved[MAXPATHLEN+1];
491 : if (_Py_wrealpath(path, resolved, MAXPATHLEN) == NULL) {
492 : PyErr_SetFromErrno(PyExc_OSError);
493 : } else {
494 : r = PyUnicode_FromWideChar(resolved, -1);
495 : }
496 : done:
497 : PyMem_Free((void *)path);
498 : PyMem_Free((void *)narrow);
499 : return r;
500 : #endif
501 :
502 : Py_INCREF(pathobj);
503 : return pathobj;
504 : }
505 :
506 :
507 : static PyMethodDef getpath_methods[] = {
508 : {"abspath", getpath_abspath, METH_VARARGS, NULL},
509 : {"basename", getpath_basename, METH_VARARGS, NULL},
510 : {"dirname", getpath_dirname, METH_VARARGS, NULL},
511 : {"hassuffix", getpath_hassuffix, METH_VARARGS, NULL},
512 : {"isabs", getpath_isabs, METH_VARARGS, NULL},
513 : {"isdir", getpath_isdir, METH_VARARGS, NULL},
514 : {"isfile", getpath_isfile, METH_VARARGS, NULL},
515 : {"isxfile", getpath_isxfile, METH_VARARGS, NULL},
516 : {"joinpath", getpath_joinpath, METH_VARARGS, NULL},
517 : {"readlines", getpath_readlines, METH_VARARGS, NULL},
518 : {"realpath", getpath_realpath, METH_VARARGS, NULL},
519 : {NULL, NULL, 0, NULL}
520 : };
521 :
522 :
523 : /* Two implementations of warn() to use depending on whether warnings
524 : are enabled or not. */
525 :
526 : static PyObject *
527 2 : getpath_warn(PyObject *Py_UNUSED(self), PyObject *args)
528 : {
529 : PyObject *msgobj;
530 2 : if (!PyArg_ParseTuple(args, "U", &msgobj)) {
531 0 : return NULL;
532 : }
533 2 : fprintf(stderr, "%s\n", PyUnicode_AsUTF8(msgobj));
534 2 : Py_RETURN_NONE;
535 : }
536 :
537 :
538 : static PyObject *
539 0 : getpath_nowarn(PyObject *Py_UNUSED(self), PyObject *args)
540 : {
541 0 : Py_RETURN_NONE;
542 : }
543 :
544 :
545 : static PyMethodDef getpath_warn_method = {"warn", getpath_warn, METH_VARARGS, NULL};
546 : static PyMethodDef getpath_nowarn_method = {"warn", getpath_nowarn, METH_VARARGS, NULL};
547 :
548 : /* Add the helper functions to the dict */
549 : static int
550 3172 : funcs_to_dict(PyObject *dict, int warnings)
551 : {
552 38064 : for (PyMethodDef *m = getpath_methods; m->ml_name; ++m) {
553 34892 : PyObject *f = PyCFunction_NewEx(m, NULL, NULL);
554 34892 : if (!f) {
555 0 : return 0;
556 : }
557 34892 : if (PyDict_SetItemString(dict, m->ml_name, f) < 0) {
558 0 : Py_DECREF(f);
559 0 : return 0;
560 : }
561 34892 : Py_DECREF(f);
562 : }
563 3172 : PyMethodDef *m2 = warnings ? &getpath_warn_method : &getpath_nowarn_method;
564 3172 : PyObject *f = PyCFunction_NewEx(m2, NULL, NULL);
565 3172 : if (!f) {
566 0 : return 0;
567 : }
568 3172 : if (PyDict_SetItemString(dict, m2->ml_name, f) < 0) {
569 0 : Py_DECREF(f);
570 0 : return 0;
571 : }
572 3172 : Py_DECREF(f);
573 3172 : return 1;
574 : }
575 :
576 :
577 : /* Add a wide-character string constant to the dict */
578 : static int
579 9516 : wchar_to_dict(PyObject *dict, const char *key, const wchar_t *s)
580 : {
581 : PyObject *u;
582 : int r;
583 9516 : if (s && s[0]) {
584 2 : u = PyUnicode_FromWideChar(s, -1);
585 2 : if (!u) {
586 0 : return 0;
587 : }
588 : } else {
589 9514 : u = Py_None;
590 9514 : Py_INCREF(u);
591 : }
592 9516 : r = PyDict_SetItemString(dict, key, u) == 0;
593 9516 : Py_DECREF(u);
594 9516 : return r;
595 : }
596 :
597 :
598 : /* Add a narrow string constant to the dict, using default locale decoding */
599 : static int
600 25376 : decode_to_dict(PyObject *dict, const char *key, const char *s)
601 : {
602 25376 : PyObject *u = NULL;
603 : int r;
604 38064 : if (s && s[0]) {
605 : size_t len;
606 12688 : const wchar_t *w = Py_DecodeLocale(s, &len);
607 12688 : if (w) {
608 12688 : u = PyUnicode_FromWideChar(w, len);
609 12688 : PyMem_RawFree((void *)w);
610 : }
611 12688 : if (!u) {
612 0 : return 0;
613 : }
614 : } else {
615 12688 : u = Py_None;
616 12688 : Py_INCREF(u);
617 : }
618 25376 : r = PyDict_SetItemString(dict, key, u) == 0;
619 25376 : Py_DECREF(u);
620 25376 : return r;
621 : }
622 :
623 : /* Add an environment variable to the dict, optionally clearing it afterwards */
624 : static int
625 12688 : env_to_dict(PyObject *dict, const char *key, int and_clear)
626 : {
627 12688 : PyObject *u = NULL;
628 12688 : int r = 0;
629 12688 : assert(strncmp(key, "ENV_", 4) == 0);
630 12688 : assert(strlen(key) < 64);
631 : #ifdef MS_WINDOWS
632 : wchar_t wkey[64];
633 : // Quick convert to wchar_t, since we know key is ASCII
634 : wchar_t *wp = wkey;
635 : for (const char *p = &key[4]; *p; ++p) {
636 : assert(*p < 128);
637 : *wp++ = *p;
638 : }
639 : *wp = L'\0';
640 : const wchar_t *v = _wgetenv(wkey);
641 : if (v) {
642 : u = PyUnicode_FromWideChar(v, -1);
643 : if (!u) {
644 : PyErr_Clear();
645 : }
646 : }
647 : #else
648 12688 : const char *v = getenv(&key[4]);
649 12688 : if (v) {
650 : size_t len;
651 3170 : const wchar_t *w = Py_DecodeLocale(v, &len);
652 3170 : if (w) {
653 3170 : u = PyUnicode_FromWideChar(w, len);
654 3170 : if (!u) {
655 0 : PyErr_Clear();
656 : }
657 3170 : PyMem_RawFree((void *)w);
658 : }
659 : }
660 : #endif
661 12688 : if (u) {
662 3170 : r = PyDict_SetItemString(dict, key, u) == 0;
663 3170 : Py_DECREF(u);
664 : } else {
665 9518 : r = PyDict_SetItemString(dict, key, Py_None) == 0;
666 : }
667 12688 : if (r && and_clear) {
668 : #ifdef MS_WINDOWS
669 : _wputenv_s(wkey, L"");
670 : #else
671 3172 : unsetenv(&key[4]);
672 : #endif
673 : }
674 12688 : return r;
675 : }
676 :
677 :
678 : /* Add an integer constant to the dict */
679 : static int
680 9516 : int_to_dict(PyObject *dict, const char *key, int v)
681 : {
682 : PyObject *o;
683 : int r;
684 9516 : o = PyLong_FromLong(v);
685 9516 : if (!o) {
686 0 : return 0;
687 : }
688 9516 : r = PyDict_SetItemString(dict, key, o) == 0;
689 9516 : Py_DECREF(o);
690 9516 : return r;
691 : }
692 :
693 :
694 : #ifdef MS_WINDOWS
695 : static int
696 : winmodule_to_dict(PyObject *dict, const char *key, HMODULE mod)
697 : {
698 : wchar_t *buffer = NULL;
699 : for (DWORD cch = 256; buffer == NULL && cch < (1024 * 1024); cch *= 2) {
700 : buffer = (wchar_t*)PyMem_RawMalloc(cch * sizeof(wchar_t));
701 : if (buffer) {
702 : if (GetModuleFileNameW(mod, buffer, cch) == cch) {
703 : PyMem_RawFree(buffer);
704 : buffer = NULL;
705 : }
706 : }
707 : }
708 : int r = wchar_to_dict(dict, key, buffer);
709 : PyMem_RawFree(buffer);
710 : return r;
711 : }
712 : #endif
713 :
714 :
715 : /* Add the current executable's path to the dict */
716 : static int
717 3172 : progname_to_dict(PyObject *dict, const char *key)
718 : {
719 : #ifdef MS_WINDOWS
720 : return winmodule_to_dict(dict, key, NULL);
721 : #elif defined(__APPLE__)
722 : char *path;
723 : uint32_t pathLen = 256;
724 : while (pathLen) {
725 : path = PyMem_RawMalloc((pathLen + 1) * sizeof(char));
726 : if (!path) {
727 : return 0;
728 : }
729 : if (_NSGetExecutablePath(path, &pathLen) != 0) {
730 : PyMem_RawFree(path);
731 : continue;
732 : }
733 : // Only keep if the path is absolute
734 : if (path[0] == SEP) {
735 : int r = decode_to_dict(dict, key, path);
736 : PyMem_RawFree(path);
737 : return r;
738 : }
739 : // Fall back and store None
740 : PyMem_RawFree(path);
741 : break;
742 : }
743 : #endif
744 3172 : return PyDict_SetItemString(dict, key, Py_None) == 0;
745 : }
746 :
747 :
748 : /* Add the runtime library's path to the dict */
749 : static int
750 3172 : library_to_dict(PyObject *dict, const char *key)
751 : {
752 : #ifdef MS_WINDOWS
753 : extern HMODULE PyWin_DLLhModule;
754 : if (PyWin_DLLhModule) {
755 : return winmodule_to_dict(dict, key, PyWin_DLLhModule);
756 : }
757 : #elif defined(WITH_NEXT_FRAMEWORK)
758 : static char modPath[MAXPATHLEN + 1];
759 : static int modPathInitialized = -1;
760 : if (modPathInitialized < 0) {
761 : modPathInitialized = 0;
762 :
763 : /* On Mac OS X we have a special case if we're running from a framework.
764 : This is because the python home should be set relative to the library,
765 : which is in the framework, not relative to the executable, which may
766 : be outside of the framework. Except when we're in the build
767 : directory... */
768 : NSSymbol symbol = NSLookupAndBindSymbol("_Py_Initialize");
769 : if (symbol != NULL) {
770 : NSModule pythonModule = NSModuleForSymbol(symbol);
771 : if (pythonModule != NULL) {
772 : /* Use dylib functions to find out where the framework was loaded from */
773 : const char *path = NSLibraryNameForModule(pythonModule);
774 : if (path) {
775 : strncpy(modPath, path, MAXPATHLEN);
776 : modPathInitialized = 1;
777 : }
778 : }
779 : }
780 : }
781 : if (modPathInitialized > 0) {
782 : return decode_to_dict(dict, key, modPath);
783 : }
784 : #endif
785 3172 : return PyDict_SetItemString(dict, key, Py_None) == 0;
786 : }
787 :
788 :
789 : PyObject *
790 3172 : _Py_Get_Getpath_CodeObject(void)
791 : {
792 3172 : return PyMarshal_ReadObjectFromString(
793 : (const char*)_Py_M__getpath, sizeof(_Py_M__getpath));
794 : }
795 :
796 :
797 : /* Perform the actual path calculation.
798 :
799 : When compute_path_config is 0, this only reads any initialised path
800 : config values into the PyConfig struct. For example, Py_SetHome() or
801 : Py_SetPath(). The only error should be due to failed memory allocation.
802 :
803 : When compute_path_config is 1, full path calculation is performed.
804 : The GIL must be held, and there may be filesystem access, side
805 : effects, and potential unraisable errors that are reported directly
806 : to stderr.
807 :
808 : Calling this function multiple times on the same PyConfig is only
809 : safe because already-configured values are not recalculated. To
810 : actually recalculate paths, you need a clean PyConfig.
811 : */
812 : PyStatus
813 6155 : _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
814 : {
815 6155 : PyStatus status = _PyPathConfig_ReadGlobal(config);
816 :
817 6155 : if (_PyStatus_EXCEPTION(status) || !compute_path_config) {
818 2983 : return status;
819 : }
820 :
821 3172 : if (!_PyThreadState_UncheckedGet()) {
822 0 : return PyStatus_Error("cannot calculate path configuration without GIL");
823 : }
824 :
825 3172 : PyObject *configDict = _PyConfig_AsDict(config);
826 3172 : if (!configDict) {
827 0 : PyErr_Clear();
828 0 : return PyStatus_NoMemory();
829 : }
830 :
831 3172 : PyObject *dict = PyDict_New();
832 3172 : if (!dict) {
833 0 : PyErr_Clear();
834 0 : Py_DECREF(configDict);
835 0 : return PyStatus_NoMemory();
836 : }
837 :
838 3172 : if (PyDict_SetItemString(dict, "config", configDict) < 0) {
839 0 : PyErr_Clear();
840 0 : Py_DECREF(configDict);
841 0 : Py_DECREF(dict);
842 0 : return PyStatus_NoMemory();
843 : }
844 : /* reference now held by dict */
845 3172 : Py_DECREF(configDict);
846 :
847 3172 : PyObject *co = _Py_Get_Getpath_CodeObject();
848 3172 : if (!co || !PyCode_Check(co)) {
849 0 : PyErr_Clear();
850 0 : Py_XDECREF(co);
851 0 : Py_DECREF(dict);
852 0 : return PyStatus_Error("error reading frozen getpath.py");
853 : }
854 :
855 : #ifdef MS_WINDOWS
856 : PyObject *winreg = PyImport_ImportModule("winreg");
857 : if (!winreg || PyDict_SetItemString(dict, "winreg", winreg) < 0) {
858 : PyErr_Clear();
859 : Py_XDECREF(winreg);
860 : if (PyDict_SetItemString(dict, "winreg", Py_None) < 0) {
861 : PyErr_Clear();
862 : Py_DECREF(co);
863 : Py_DECREF(dict);
864 : return PyStatus_Error("error importing winreg module");
865 : }
866 : } else {
867 : Py_DECREF(winreg);
868 : }
869 : #endif
870 :
871 3172 : if (
872 : #ifdef MS_WINDOWS
873 : !decode_to_dict(dict, "os_name", "nt") ||
874 : #elif defined(__APPLE__)
875 : !decode_to_dict(dict, "os_name", "darwin") ||
876 : #else
877 6344 : !decode_to_dict(dict, "os_name", "posix") ||
878 : #endif
879 : #ifdef WITH_NEXT_FRAMEWORK
880 : !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 1) ||
881 : #else
882 6344 : !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 0) ||
883 : #endif
884 6344 : !decode_to_dict(dict, "PREFIX", PREFIX) ||
885 6344 : !decode_to_dict(dict, "EXEC_PREFIX", EXEC_PREFIX) ||
886 6344 : !decode_to_dict(dict, "PYTHONPATH", PYTHONPATH) ||
887 6344 : !decode_to_dict(dict, "VPATH", VPATH) ||
888 6344 : !decode_to_dict(dict, "PLATLIBDIR", PLATLIBDIR) ||
889 6344 : !decode_to_dict(dict, "PYDEBUGEXT", PYDEBUGEXT) ||
890 6344 : !int_to_dict(dict, "VERSION_MAJOR", PY_MAJOR_VERSION) ||
891 6344 : !int_to_dict(dict, "VERSION_MINOR", PY_MINOR_VERSION) ||
892 6344 : !decode_to_dict(dict, "PYWINVER", PYWINVER) ||
893 6344 : !wchar_to_dict(dict, "EXE_SUFFIX", EXE_SUFFIX) ||
894 6344 : !env_to_dict(dict, "ENV_PATH", 0) ||
895 6344 : !env_to_dict(dict, "ENV_PYTHONHOME", 0) ||
896 6344 : !env_to_dict(dict, "ENV_PYTHONEXECUTABLE", 0) ||
897 6344 : !env_to_dict(dict, "ENV___PYVENV_LAUNCHER__", 1) ||
898 6344 : !progname_to_dict(dict, "real_executable") ||
899 6344 : !library_to_dict(dict, "library") ||
900 6344 : !wchar_to_dict(dict, "executable_dir", NULL) ||
901 6344 : !wchar_to_dict(dict, "py_setpath", _PyPathConfig_GetGlobalModuleSearchPath()) ||
902 6344 : !funcs_to_dict(dict, config->pathconfig_warnings) ||
903 : #ifndef MS_WINDOWS
904 6344 : PyDict_SetItemString(dict, "winreg", Py_None) < 0 ||
905 : #endif
906 3172 : PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0
907 : ) {
908 0 : Py_DECREF(co);
909 0 : Py_DECREF(dict);
910 0 : _PyErr_WriteUnraisableMsg("error evaluating initial values", NULL);
911 0 : return PyStatus_Error("error evaluating initial values");
912 : }
913 :
914 3172 : PyObject *r = PyEval_EvalCode(co, dict, dict);
915 3172 : Py_DECREF(co);
916 :
917 3172 : if (!r) {
918 0 : Py_DECREF(dict);
919 0 : _PyErr_WriteUnraisableMsg("error evaluating path", NULL);
920 0 : return PyStatus_Error("error evaluating path");
921 : }
922 3172 : Py_DECREF(r);
923 :
924 : #if 0
925 : PyObject *it = PyObject_GetIter(configDict);
926 : for (PyObject *k = PyIter_Next(it); k; k = PyIter_Next(it)) {
927 : if (!strcmp("__builtins__", PyUnicode_AsUTF8(k))) {
928 : Py_DECREF(k);
929 : continue;
930 : }
931 : fprintf(stderr, "%s = ", PyUnicode_AsUTF8(k));
932 : PyObject *o = PyDict_GetItem(configDict, k);
933 : o = PyObject_Repr(o);
934 : fprintf(stderr, "%s\n", PyUnicode_AsUTF8(o));
935 : Py_DECREF(o);
936 : Py_DECREF(k);
937 : }
938 : Py_DECREF(it);
939 : #endif
940 :
941 3172 : if (_PyConfig_FromDict(config, configDict) < 0) {
942 0 : _PyErr_WriteUnraisableMsg("reading getpath results", NULL);
943 0 : Py_DECREF(dict);
944 0 : return PyStatus_Error("error getting getpath results");
945 : }
946 :
947 3172 : Py_DECREF(dict);
948 :
949 3172 : return _PyStatus_OK();
950 : }
951 :
|