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