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