getpath.c 26 KB

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