Coverage Report

Created: 2022-07-08 09:39

/home/mdboom/Work/builds/cpython/Modules/getpath.c
Line
Count
Source (jump to first uncovered line)
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)) {
  Branch (63:9): [True: 0, False: 104]
64
        return NULL;
65
    }
66
    Py_ssize_t len;
67
    path = PyUnicode_AsWideCharString(pathobj, &len);
68
    if (path) {
  Branch (68:9): [True: 104, False: 0]
69
        wchar_t *abs;
70
        if (_Py_abspath((const wchar_t *)_Py_normpath(path, -1), &abs) == 0 && abs) {
  Branch (70:13): [True: 104, False: 0]
  Branch (70:80): [True: 104, False: 0]
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
    const char *path;
86
    if (!PyArg_ParseTuple(args, "s", &path)) {
  Branch (86:9): [True: 0, False: 0]
87
        return NULL;
88
    }
89
    const char *name = strrchr(path, SEP);
90
    return PyUnicode_FromString(name ? name + 1 : path);
  Branch (90:33): [True: 0, False: 0]
91
}
92
93
94
static PyObject *
95
getpath_dirname(PyObject *Py_UNUSED(self), PyObject *args)
96
{
97
    const char *path;
98
    if (!PyArg_ParseTuple(args, "s", &path)) {
  Branch (98:9): [True: 0, False: 814]
99
        return NULL;
100
    }
101
    const char *name = strrchr(path, SEP);
102
    if (!name) {
  Branch (102:9): [True: 2, False: 812]
103
        return PyUnicode_FromStringAndSize(NULL, 0);
104
    }
105
    return PyUnicode_FromStringAndSize(path, (name - path));
106
}
107
108
109
static PyObject *
110
getpath_isabs(PyObject *Py_UNUSED(self), PyObject *args)
111
{
112
    PyObject *r = NULL;
113
    PyObject *pathobj;
114
    const wchar_t *path;
115
    if (!PyArg_ParseTuple(args, "U", &pathobj)) {
  Branch (115:9): [True: 0, False: 0]
116
        return NULL;
117
    }
118
    path = PyUnicode_AsWideCharString(pathobj, NULL);
119
    if (path) {
  Branch (119:9): [True: 0, False: 0]
120
        r = _Py_isabs(path) ? Py_True : Py_False;
  Branch (120:13): [True: 0, False: 0]
121
        PyMem_Free((void *)path);
122
    }
123
    Py_XINCREF(r);
124
    return r;
125
}
126
127
128
static PyObject *
129
getpath_hassuffix(PyObject *Py_UNUSED(self), PyObject *args)
130
{
131
    PyObject *r = NULL;
132
    PyObject *pathobj;
133
    PyObject *suffixobj;
134
    const wchar_t *path;
135
    const wchar_t *suffix;
136
    if (!PyArg_ParseTuple(args, "UU", &pathobj, &suffixobj)) {
  Branch (136:9): [True: 0, False: 0]
137
        return NULL;
138
    }
139
    Py_ssize_t len, suffixLen;
140
    path = PyUnicode_AsWideCharString(pathobj, &len);
141
    if (path) {
  Branch (141:9): [True: 0, False: 0]
142
        suffix = PyUnicode_AsWideCharString(suffixobj, &suffixLen);
143
        if (suffix) {
  Branch (143:13): [True: 0, False: 0]
144
            if (suffixLen > len ||
  Branch (144:17): [True: 0, False: 0]
145
#ifdef MS_WINDOWS
146
                wcsicmp(&path[len - suffixLen], suffix) != 0
147
#else
148
                wcscmp(&path[len - suffixLen], suffix) != 0
  Branch (148:17): [True: 0, False: 0]
149
#endif
150
            ) {
151
                r = Py_False;
152
            } else {
153
                r = Py_True;
154
            }
155
            Py_INCREF(r);
156
            PyMem_Free((void *)suffix);
157
        }
158
        PyMem_Free((void *)path);
159
    }
160
    return r;
161
}
162
163
164
static PyObject *
165
getpath_isdir(PyObject *Py_UNUSED(self), PyObject *args)
166
{
167
    PyObject *r = NULL;
168
    PyObject *pathobj;
169
    const wchar_t *path;
170
    if (!PyArg_ParseTuple(args, "U", &pathobj)) {
  Branch (170:9): [True: 0, False: 0]
171
        return NULL;
172
    }
173
    path = PyUnicode_AsWideCharString(pathobj, NULL);
174
    if (path) {
  Branch (174:9): [True: 0, False: 0]
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
        r = (_Py_wstat(path, &st) == 0) && S_ISDIR(st.st_mode) ? Py_True : Py_False;
  Branch (181:13): [True: 0, False: 0]
182
#endif
183
        PyMem_Free((void *)path);
184
    }
185
    Py_XINCREF(r);
186
    return r;
187
}
188
189
190
static PyObject *
191
getpath_isfile(PyObject *Py_UNUSED(self), PyObject *args)
192
{
193
    PyObject *r = NULL;
194
    PyObject *pathobj;
195
    const wchar_t *path;
196
    if (!PyArg_ParseTuple(args, "U", &pathobj)) {
  Branch (196:9): [True: 0, False: 274]
197
        return NULL;
198
    }
199
    path = PyUnicode_AsWideCharString(pathobj, NULL);
200
    if (path) {
  Branch (200:9): [True: 274, False: 0]
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
        r = (_Py_wstat(path, &st) == 0) && S_ISREG(st.st_mode) ? Py_True : Py_False;
  Branch (207:13): [True: 274, False: 0]
208
#endif
209
        PyMem_Free((void *)path);
210
    }
211
    Py_XINCREF(r);
212
    return r;
213
}
214
215
216
static PyObject *
217
getpath_isxfile(PyObject *Py_UNUSED(self), PyObject *args)
218
{
219
    PyObject *r = NULL;
220
    PyObject *pathobj;
221
    const wchar_t *path;
222
    Py_ssize_t cchPath;
223
    if (!PyArg_ParseTuple(args, "U", &pathobj)) {
  Branch (223:9): [True: 0, False: 194]
224
        return NULL;
225
    }
226
    path = PyUnicode_AsWideCharString(pathobj, &cchPath);
227
    if (path) {
  Branch (227:9): [True: 194, False: 0]
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
        r = (_Py_wstat(path, &st) == 0) &&
  Branch (238:13): [True: 2, False: 192]
239
            S_ISREG(st.st_mode) &&
240
            
(st.st_mode & 0111)2
  Branch (240:13): [True: 2, False: 0]
241
            ? Py_True : Py_False;
242
#endif
243
        PyMem_Free((void *)path);
244
    }
245
    Py_XINCREF(r);
246
    return r;
247
}
248
249
250
static PyObject *
251
getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args)
252
{
253
    if (!PyTuple_Check(args)) {
  Branch (253:9): [True: 0, False: 2.22k]
254
        PyErr_SetString(PyExc_TypeError, "requires tuple of arguments");
255
        return NULL;
256
    }
257
    Py_ssize_t n = PyTuple_GET_SIZE(args);
258
    if (n == 0) {
  Branch (258:9): [True: 0, False: 2.22k]
259
        return PyUnicode_FromString(NULL);
260
    }
261
    /* Convert all parts to wchar and accumulate max final length */
262
    wchar_t **parts = (wchar_t **)PyMem_Malloc(n * sizeof(wchar_t *));
263
    memset(parts, 0, n * sizeof(wchar_t *));
264
    Py_ssize_t cchFinal = 0;
265
    Py_ssize_t first = 0;
266
267
    for (Py_ssize_t i = 0; i < n; 
++i4.44k
) {
  Branch (267:28): [True: 4.44k, False: 2.22k]
268
        PyObject *s = PyTuple_GET_ITEM(args, i);
269
        Py_ssize_t cch;
270
        if (s == Py_None) {
  Branch (270:13): [True: 274, False: 4.16k]
271
            cch = 0;
272
        } else if (PyUnicode_Check(s)) {
273
            parts[i] = PyUnicode_AsWideCharString(s, &cch);
274
            if (!parts[i]) {
  Branch (274:17): [True: 0, False: 4.16k]
275
                cchFinal = -1;
276
                break;
277
            }
278
            if (_Py_isabs(parts[i])) {
  Branch (278:17): [True: 2.22k, False: 1.94k]
279
                first = i;
280
            }
281
        } else {
282
            PyErr_SetString(PyExc_TypeError, "all arguments to joinpath() must be str or None");
283
            cchFinal = -1;
284
            break;
285
        }
286
        cchFinal += cch + 1;
287
    }
288
289
    wchar_t *final = cchFinal > 0 ? (wchar_t *)PyMem_Malloc(cchFinal * sizeof(wchar_t)) : NULL;
  Branch (289:22): [True: 2.22k, False: 0]
290
    if (!final) {
  Branch (290:9): [True: 0, False: 2.22k]
291
        for (Py_ssize_t i = 0; i < n; ++i) {
  Branch (291:32): [True: 0, False: 0]
292
            PyMem_Free(parts[i]);
293
        }
294
        PyMem_Free(parts);
295
        if (cchFinal) {
  Branch (295:13): [True: 0, False: 0]
296
            PyErr_NoMemory();
297
            return NULL;
298
        }
299
        return PyUnicode_FromStringAndSize(NULL, 0);
300
    }
301
302
    final[0] = '\0';
303
    /* Now join all the paths. The final result should be shorter than the buffer */
304
    for (Py_ssize_t i = 0; i < n; 
++i4.44k
) {
  Branch (304:28): [True: 4.44k, False: 2.22k]
305
        if (!parts[i]) {
  Branch (305:13): [True: 274, False: 4.16k]
306
            continue;
307
        }
308
        if (i >= first && final) {
  Branch (308:13): [True: 4.16k, False: 0]
  Branch (308:27): [True: 4.16k, False: 0]
309
            if (!final[0]) {
  Branch (309:17): [True: 2.22k, False: 1.94k]
310
                /* final is definitely long enough to fit any individual part */
311
                wcscpy(final, parts[i]);
312
            } else 
if (1.94k
_Py_add_relfile(final, parts[i], cchFinal) < 01.94k
) {
  Branch (312:24): [True: 0, False: 1.94k]
313
                /* if we fail, keep iterating to free memory, but stop adding parts */
314
                PyMem_Free(final);
315
                final = NULL;
316
            }
317
        }
318
        PyMem_Free(parts[i]);
319
    }
320
    PyMem_Free(parts);
321
    if (!final) {
  Branch (321:9): [True: 0, False: 2.22k]
322
        PyErr_SetString(PyExc_SystemError, "failed to join paths");
323
        return NULL;
324
    }
325
    PyObject *r = PyUnicode_FromWideChar(_Py_normpath(final, -1), -1);
326
    PyMem_Free(final);
327
    return r;
328
}
329
330
331
static PyObject *
332
getpath_readlines(PyObject *Py_UNUSED(self), PyObject *args)
333
{
334
    PyObject *r = NULL;
335
    PyObject *pathobj;
336
    const wchar_t *path;
337
    if (!PyArg_ParseTuple(args, "U", &pathobj)) {
  Branch (337:9): [True: 0, False: 1.35k]
338
        return NULL;
339
    }
340
    path = PyUnicode_AsWideCharString(pathobj, NULL);
341
    if (!path) {
  Branch (341:9): [True: 0, False: 1.35k]
342
        return NULL;
343
    }
344
    FILE *fp = _Py_wfopen(path, L"rb");
345
    PyMem_Free((void *)path);
346
    if (!fp) {
  Branch (346:9): [True: 1.07k, False: 274]
347
        PyErr_SetFromErrno(PyExc_OSError);
348
        return NULL;
349
    }
350
351
    r = PyList_New(0);
352
    if (!r) {
  Branch (352:9): [True: 0, False: 274]
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) {
  Branch (358:9): [True: 0, False: 274]
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) {
  Branch (366:9): [True: 0, False: 274]
367
        return r;
368
    }
369
    if (cb >= MAX_FILE) {
  Branch (369:9): [True: 0, False: 274]
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) {
  Branch (380:9): [True: 0, False: 274]
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) {
  Branch (388:12): [True: 0, False: 274]
389
        Py_ssize_t cb = p2 - p1;
390
        while (cb >= 0 && (p1[cb] == L'\n' || p1[cb] == L'\r')) {
  Branch (390:16): [True: 0, False: 0]
  Branch (390:28): [True: 0, False: 0]
  Branch (390:47): [True: 0, False: 0]
391
            --cb;
392
        }
393
        PyObject *u = PyUnicode_FromWideChar(p1, cb >= 0 ? cb + 1 : 0);
  Branch (393:50): [True: 0, False: 0]
394
        if (!u || PyList_Append(r, u) < 0) {
  Branch (394:13): [True: 0, False: 0]
  Branch (394:19): [True: 0, False: 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) {
  Branch (402:9): [True: 274, False: 0]
  Branch (402:14): [True: 274, False: 0]
  Branch (402:20): [True: 274, False: 0]
403
        PyObject *u = PyUnicode_FromWideChar(p1, -1);
404
        if (!u || PyList_Append(r, u) < 0) {
  Branch (404:13): [True: 0, False: 274]
  Branch (404:19): [True: 0, False: 274]
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)) {
  Branch (418:9): [True: 0, False: 279]
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) {
  Branch (429:9): [True: 0, False: 279]
430
        goto done;
431
    }
432
    wchar_t *path2 = _PyMem_RawWcsdup(path);
433
    PyMem_Free((void *)path);
434
    path = path2;
435
    while (path) {
  Branch (435:12): [True: 279, False: 0]
436
        wchar_t resolved[MAXPATHLEN + 1];
437
        int linklen = _Py_wreadlink(path, resolved, Py_ARRAY_LENGTH(resolved));
438
        if (linklen == -1) {
  Branch (438:13): [True: 279, False: 0]
439
            r = PyUnicode_FromWideChar(path, -1);
440
            break;
441
        }
442
        if (_Py_isabs(resolved)) {
  Branch (442:13): [True: 0, False: 0]
443
            PyMem_RawFree((void *)path);
444
            path = _PyMem_RawWcsdup(resolved);
445
        } else {
446
            wchar_t *s = wcsrchr(path, SEP);
447
            if (s) {
  Branch (447:17): [True: 0, False: 0]
448
                *s = L'\0';
449
            }
450
            path2 = _Py_normpath(_Py_join_relfile(path, resolved), -1);
451
            PyMem_RawFree((void *)path);
452
            path = path2;
453
        }
454
        nlink++;
455
        /* 40 is the Linux kernel 4.2 limit */
456
        if (nlink >= 40) {
  Branch (456:13): [True: 0, False: 0]
457
            PyErr_SetString(PyExc_OSError, "maximum number of symbolic links reached");
458
            break;
459
        }
460
    }
461
    if (!path) {
  Branch (461:9): [True: 0, False: 279]
462
        PyErr_NoMemory();
463
    }
464
done:
465
    PyMem_RawFree((void *)path);
466
    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
getpath_warn(PyObject *Py_UNUSED(self), PyObject *args)
528
{
529
    PyObject *msgobj;
530
    if (!PyArg_ParseTuple(args, "U", &msgobj)) {
  Branch (530:9): [True: 0, False: 0]
531
        return NULL;
532
    }
533
    fprintf(stderr, "%s\n", PyUnicode_AsUTF8(msgobj));
534
    Py_RETURN_NONE;
535
}
536
537
538
static PyObject *
539
getpath_nowarn(PyObject *Py_UNUSED(self), PyObject *args)
540
{
541
    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
funcs_to_dict(PyObject *dict, int warnings)
551
{
552
    for (PyMethodDef *m = getpath_methods; m->ml_name; 
++m3.06k
) {
  Branch (552:44): [True: 3.06k, False: 279]
553
        PyObject *f = PyCFunction_NewEx(m, NULL, NULL);
554
        if (!f) {
  Branch (554:13): [True: 0, False: 3.06k]
555
            return 0;
556
        }
557
        if (PyDict_SetItemString(dict, m->ml_name, f) < 0) {
  Branch (557:13): [True: 0, False: 3.06k]
558
            Py_DECREF(f);
559
            return 0;
560
        }
561
        Py_DECREF(f);
562
    }
563
    PyMethodDef *m2 = warnings ? 
&getpath_warn_method271
:
&getpath_nowarn_method8
;
  Branch (563:23): [True: 271, False: 8]
564
    PyObject *f = PyCFunction_NewEx(m2, NULL, NULL);
565
    if (!f) {
  Branch (565:9): [True: 0, False: 279]
566
        return 0;
567
    }
568
    if (PyDict_SetItemString(dict, m2->ml_name, f) < 0) {
  Branch (568:9): [True: 0, False: 279]
569
        Py_DECREF(f);
570
        return 0;
571
    }
572
    Py_DECREF(f);
573
    return 1;
574
}
575
576
577
/* Add a wide-character string constant to the dict */
578
static int
579
wchar_to_dict(PyObject *dict, const char *key, const wchar_t *s)
580
{
581
    PyObject *u;
582
    int r;
583
    if (s && 
s[0]2
) {
  Branch (583:9): [True: 2, False: 835]
  Branch (583:14): [True: 2, False: 0]
584
        u = PyUnicode_FromWideChar(s, -1);
585
        if (!u) {
  Branch (585:13): [True: 0, False: 2]
586
            return 0;
587
        }
588
    } else {
589
        u = Py_None;
590
        Py_INCREF(u);
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]1.67k
) {
  Branch (604:9): [True: 1.67k, False: 558]
  Branch (604:14): [True: 1.11k, False: 558]
605
        size_t len;
606
        const wchar_t *w = Py_DecodeLocale(s, &len);
607
        if (w) {
  Branch (607:13): [True: 1.11k, False: 0]
608
            u = PyUnicode_FromWideChar(w, len);
609
            PyMem_RawFree((void *)w);
610
        }
611
        if (!u) {
  Branch (611:13): [True: 0, False: 1.11k]
612
            return 0;
613
        }
614
    } else {
615
        u = Py_None;
616
        Py_INCREF(u);
617
    }
618
    r = PyDict_SetItemString(dict, key, u) == 0;
619
    Py_DECREF(u);
620
    return r;
621
}
622
623
/* Add an environment variable to the dict, optionally clearing it afterwards */
624
static int
625
env_to_dict(PyObject *dict, const char *key, int and_clear)
626
{
627
    PyObject *u = NULL;
628
    int r = 0;
629
    assert(strncmp(key, "ENV_", 4) == 0);
630
    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
    const char *v = getenv(&key[4]);
649
    if (v) {
  Branch (649:9): [True: 279, False: 837]
650
        size_t len;
651
        const wchar_t *w = Py_DecodeLocale(v, &len);
652
        if (w) {
  Branch (652:13): [True: 279, False: 0]
653
            u = PyUnicode_FromWideChar(w, len);
654
            if (!u) {
  Branch (654:17): [True: 0, False: 279]
655
                PyErr_Clear();
656
            }
657
            PyMem_RawFree((void *)w);
658
        }
659
    }
660
#endif
661
    if (u) {
  Branch (661:9): [True: 279, False: 837]
662
        r = PyDict_SetItemString(dict, key, u) == 0;
663
        Py_DECREF(u);
664
    } else {
665
        r = PyDict_SetItemString(dict, key, Py_None) == 0;
666
    }
667
    if (r && and_clear) {
  Branch (667:9): [True: 1.11k, False: 0]
  Branch (667:14): [True: 279, False: 837]
668
#ifdef MS_WINDOWS
669
        _wputenv_s(wkey, L"");
670
#else
671
        unsetenv(&key[4]);
672
#endif
673
    }
674
    return r;
675
}
676
677
678
/* Add an integer constant to the dict */
679
static int
680
int_to_dict(PyObject *dict, const char *key, int v)
681
{
682
    PyObject *o;
683
    int r;
684
    o = PyLong_FromLong(v);
685
    if (!o) {
  Branch (685:9): [True: 0, False: 837]
686
        return 0;
687
    }
688
    r = PyDict_SetItemString(dict, key, o) == 0;
689
    Py_DECREF(o);
690
    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
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
    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
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
    return PyDict_SetItemString(dict, key, Py_None) == 0;
786
}
787
788
789
PyObject *
790
_Py_Get_Getpath_CodeObject(void)
791
{
792
    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
_PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
814
{
815
    PyStatus status = _PyPathConfig_ReadGlobal(config);
816
817
    if (_PyStatus_EXCEPTION(status) || !compute_path_config) {
  Branch (817:40): [True: 110, False: 279]
818
        return status;
819
    }
820
821
    if (!_PyThreadState_UncheckedGet()) {
  Branch (821:9): [True: 0, False: 279]
822
        return PyStatus_Error("cannot calculate path configuration without GIL");
823
    }
824
825
    PyObject *configDict = _PyConfig_AsDict(config);
826
    if (!configDict) {
  Branch (826:9): [True: 0, False: 279]
827
        PyErr_Clear();
828
        return PyStatus_NoMemory();
829
    }
830
831
    PyObject *dict = PyDict_New();
832
    if (!dict) {
  Branch (832:9): [True: 0, False: 279]
833
        PyErr_Clear();
834
        Py_DECREF(configDict);
835
        return PyStatus_NoMemory();
836
    }
837
838
    if (PyDict_SetItemString(dict, "config", configDict) < 0) {
  Branch (838:9): [True: 0, False: 279]
839
        PyErr_Clear();
840
        Py_DECREF(configDict);
841
        Py_DECREF(dict);
842
        return PyStatus_NoMemory();
843
    }
844
    /* reference now held by dict */
845
    Py_DECREF(configDict);
846
847
    PyObject *co = _Py_Get_Getpath_CodeObject();
848
    if (!co || !PyCode_Check(co)) {
  Branch (848:9): [True: 0, False: 279]
  Branch (848:16): [True: 0, False: 279]
849
        PyErr_Clear();
850
        Py_XDECREF(co);
851
        Py_DECREF(dict);
852
        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
    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
        !decode_to_dict(dict, "os_name", "posix") ||
  Branch (877:9): [True: 0, False: 279]
878
#endif
879
#ifdef WITH_NEXT_FRAMEWORK
880
        !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 1) ||
881
#else
882
        !int_to_dict(dict, "WITH_NEXT_FRAMEWORK", 0) ||
  Branch (882:9): [True: 0, False: 279]
883
#endif
884
        !decode_to_dict(dict, "PREFIX", PREFIX) ||
  Branch (884:9): [True: 0, False: 279]
885
        !decode_to_dict(dict, "EXEC_PREFIX", EXEC_PREFIX) ||
  Branch (885:9): [True: 0, False: 279]
886
        !decode_to_dict(dict, "PYTHONPATH", PYTHONPATH) ||
  Branch (886:9): [True: 0, False: 279]
887
        !decode_to_dict(dict, "VPATH", VPATH) ||
  Branch (887:9): [True: 0, False: 279]
888
        !decode_to_dict(dict, "PLATLIBDIR", PLATLIBDIR) ||
  Branch (888:9): [True: 0, False: 279]
889
        !decode_to_dict(dict, "PYDEBUGEXT", PYDEBUGEXT) ||
  Branch (889:9): [True: 0, False: 279]
890
        !int_to_dict(dict, "VERSION_MAJOR", PY_MAJOR_VERSION) ||
  Branch (890:9): [True: 0, False: 279]
891
        !int_to_dict(dict, "VERSION_MINOR", PY_MINOR_VERSION) ||
  Branch (891:9): [True: 0, False: 279]
892
        !decode_to_dict(dict, "PYWINVER", PYWINVER) ||
  Branch (892:9): [True: 0, False: 279]
893
        !wchar_to_dict(dict, "EXE_SUFFIX", EXE_SUFFIX) ||
  Branch (893:9): [True: 0, False: 279]
894
        !env_to_dict(dict, "ENV_PATH", 0) ||
  Branch (894:9): [True: 0, False: 279]
895
        !env_to_dict(dict, "ENV_PYTHONHOME", 0) ||
  Branch (895:9): [True: 0, False: 279]
896
        !env_to_dict(dict, "ENV_PYTHONEXECUTABLE", 0) ||
  Branch (896:9): [True: 0, False: 279]
897
        !env_to_dict(dict, "ENV___PYVENV_LAUNCHER__", 1) ||
  Branch (897:9): [True: 0, False: 279]
898
        !progname_to_dict(dict, "real_executable") ||
  Branch (898:9): [True: 0, False: 279]
899
        !library_to_dict(dict, "library") ||
  Branch (899:9): [True: 0, False: 279]
900
        !wchar_to_dict(dict, "executable_dir", NULL) ||
  Branch (900:9): [True: 0, False: 279]
901
        !wchar_to_dict(dict, "py_setpath", _PyPathConfig_GetGlobalModuleSearchPath()) ||
  Branch (901:9): [True: 0, False: 279]
902
        !funcs_to_dict(dict, config->pathconfig_warnings) ||
  Branch (902:9): [True: 0, False: 279]
903
#ifndef MS_WINDOWS
904
        PyDict_SetItemString(dict, "winreg", Py_None) < 0 ||
  Branch (904:9): [True: 0, False: 279]
905
#endif
906
        PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0
  Branch (906:9): [True: 0, False: 279]
907
    ) {
908
        Py_DECREF(co);
909
        Py_DECREF(dict);
910
        _PyErr_WriteUnraisableMsg("error evaluating initial values", NULL);
911
        return PyStatus_Error("error evaluating initial values");
912
    }
913
914
    PyObject *r = PyEval_EvalCode(co, dict, dict);
915
    Py_DECREF(co);
916
917
    if (!r) {
  Branch (917:9): [True: 0, False: 279]
918
        Py_DECREF(dict);
919
        _PyErr_WriteUnraisableMsg("error evaluating path", NULL);
920
        return PyStatus_Error("error evaluating path");
921
    }
922
    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
    if (_PyConfig_FromDict(config, configDict) < 0) {
  Branch (941:9): [True: 0, False: 279]
942
        _PyErr_WriteUnraisableMsg("reading getpath results", NULL);
943
        Py_DECREF(dict);
944
        return PyStatus_Error("error getting getpath results");
945
    }
946
947
    Py_DECREF(dict);
948
949
    return _PyStatus_OK();
950
}
951