Coverage Report

Created: 2026-10-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/fileutils.c
Line
Count
Source
1
#include "Python.h"
2
#include "pycore_fileutils.h"     // fileutils definitions
3
#include "pycore_runtime.h"       // _PyRuntime
4
#include "pycore_pystate.h"       // _Py_AssertHoldsTstate()
5
#include "pycore_unicodeobject.h" // _Py_MAX_UNICODE
6
#include "osdefs.h"               // SEP
7
8
#include <stdlib.h>               // mbstowcs()
9
#ifdef HAVE_UNISTD_H
10
#  include <unistd.h>             // getcwd()
11
#endif
12
13
#ifdef MS_WINDOWS
14
#  include <malloc.h>
15
#  include <windows.h>
16
#  include <winioctl.h>             // FILE_DEVICE_* constants
17
#  include "pycore_fileutils_windows.h" // FILE_STAT_BASIC_INFORMATION
18
#  if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)
19
#    define PATHCCH_ALLOW_LONG_PATHS 0x01
20
#  else
21
#    include <pathcch.h>            // PathCchCombineEx
22
#  endif
23
extern int winerror_to_errno(int);
24
#endif
25
26
#ifdef HAVE_LANGINFO_H
27
#  include <langinfo.h>           // nl_langinfo(CODESET)
28
#endif
29
30
#ifdef HAVE_SYS_IOCTL_H
31
#include <sys/ioctl.h>
32
#endif
33
34
#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION
35
#  include <iconv.h>              // iconv_open()
36
#endif
37
38
#ifdef HAVE_FCNTL_H
39
#  include <fcntl.h>              // fcntl(F_GETFD)
40
#endif
41
42
#ifdef O_CLOEXEC
43
/* Does open() support the O_CLOEXEC flag? Possible values:
44
45
   -1: unknown
46
    0: open() ignores O_CLOEXEC flag, ex: Linux kernel older than 2.6.23
47
    1: open() supports O_CLOEXEC flag, close-on-exec is set
48
49
   The flag is used by _Py_open(), _Py_open_noraise(), io.FileIO
50
   and os.open(). */
51
int _Py_open_cloexec_works = -1;
52
#endif
53
54
// wcstombs() error
55
static const size_t ENCODE_ERROR = (size_t)-1;
56
// mbstowcs() and mbrtowc() errors
57
static const size_t DECODE_ERROR = (size_t)-1;
58
#ifdef HAVE_MBRTOWC
59
static const size_t INCOMPLETE_CHARACTER = (size_t)-2;
60
#endif
61
62
63
// Get the error handler as 'int surrogateescape'.
64
// Set '*surrogateescape' and return 0 on success.
65
// Return -1 if the error handler is not supported: other than "strict" and
66
// "surrogateescape".
67
static int
68
get_surrogateescape(_Py_error_handler errors, int *surrogateescape)
69
232k
{
70
232k
    switch (errors)
71
232k
    {
72
0
    case _Py_ERROR_STRICT:
73
0
        *surrogateescape = 0;
74
0
        return 0;
75
232k
    case _Py_ERROR_SURROGATEESCAPE:
76
232k
        *surrogateescape = 1;
77
232k
        return 0;
78
0
    default:
79
0
        return -1;
80
232k
    }
81
232k
}
82
83
84
PyObject *
85
_Py_device_encoding(int fd)
86
0
{
87
#if defined(MS_WINDOWS) && defined(HAVE_WINDOWS_CONSOLE_IO)
88
    HANDLE handle;
89
    DWORD temp;
90
    UINT cp = 0;
91
92
    _Py_BEGIN_SUPPRESS_IPH
93
    handle = (HANDLE)_get_osfhandle(fd);
94
    _Py_END_SUPPRESS_IPH
95
    if (handle == INVALID_HANDLE_VALUE) {
96
        Py_RETURN_NONE;
97
    }
98
99
    Py_BEGIN_ALLOW_THREADS
100
    if (GetFileType(handle) == FILE_TYPE_CHAR) {
101
        /* GetConsoleMode() only succeeds for a console handle. */
102
        if (!GetConsoleMode(handle, &temp)) {
103
            /* Assume that access denied implies an output handle. */
104
            if (GetLastError() == ERROR_ACCESS_DENIED) {
105
                cp = GetConsoleOutputCP();
106
            }
107
        }
108
        else if (GetNumberOfConsoleInputEvents(handle, &temp)) {
109
            cp = GetConsoleCP();
110
        }
111
        else {
112
            cp = GetConsoleOutputCP();
113
        }
114
    }
115
    Py_END_ALLOW_THREADS
116
117
    /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application
118
       has no console */
119
    if (cp == CP_UTF8) {
120
        _Py_DECLARE_STR(utf_8, "utf-8");
121
        return &_Py_STR(utf_8);
122
    }
123
    if (cp == 0) {
124
        Py_RETURN_NONE;
125
    }
126
    return PyUnicode_FromFormat("cp%u", (unsigned int)cp);
127
#else
128
0
    int valid;
129
0
    Py_BEGIN_ALLOW_THREADS
130
0
    _Py_BEGIN_SUPPRESS_IPH
131
0
    valid = isatty(fd);
132
0
    _Py_END_SUPPRESS_IPH
133
0
    Py_END_ALLOW_THREADS
134
0
    if (!valid) {
135
0
        Py_RETURN_NONE;
136
0
    }
137
138
#ifdef MS_WINDOWS
139
    Py_RETURN_NONE;
140
#else
141
0
    if (_PyRuntime.preconfig.utf8_mode) {
142
0
        _Py_DECLARE_STR(utf_8, "utf-8");
143
0
        return &_Py_STR(utf_8);
144
0
    }
145
0
    return _Py_GetLocaleEncodingObject();
146
0
#endif
147
0
#endif /* MS_WINDOWS && HAVE_WINDOWS_CONSOLE_IO */
148
0
}
149
150
151
static int
152
is_valid_wide_char(wchar_t ch)
153
5.61M
{
154
#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION
155
    /* Oracle Solaris doesn't use Unicode code points as wchar_t encoding
156
       for non-Unicode locales, which makes values higher than _Py_MAX_UNICODE
157
       possibly valid. */
158
    return 1;
159
#endif
160
5.61M
    if (Py_UNICODE_IS_SURROGATE(ch)) {
161
        // Reject lone surrogate characters
162
0
        return 0;
163
0
    }
164
5.61M
#if SIZEOF_WCHAR_T > 2
165
5.61M
    if (ch > _Py_MAX_UNICODE) {
166
        // bpo-35883: Reject characters outside [U+0000; U+10ffff] range.
167
        // The glibc mbstowcs() UTF-8 decoder does not respect the RFC 3629,
168
        // it creates characters outside the [U+0000; U+10ffff] range:
169
        // https://sourceware.org/bugzilla/show_bug.cgi?id=2373
170
0
        return 0;
171
0
    }
172
5.61M
#endif
173
5.61M
    return 1;
174
5.61M
}
175
176
177
static size_t
178
_Py_mbstowcs(wchar_t *dest, const char *src, size_t n)
179
465k
{
180
465k
    size_t count = mbstowcs(dest, src, n);
181
465k
    if (dest != NULL && count != DECODE_ERROR) {
182
5.84M
        for (size_t i=0; i < count; i++) {
183
5.61M
            wchar_t ch = dest[i];
184
5.61M
            if (!is_valid_wide_char(ch)) {
185
0
                return DECODE_ERROR;
186
0
            }
187
5.61M
        }
188
232k
    }
189
465k
    return count;
190
465k
}
191
192
193
#ifdef HAVE_MBRTOWC
194
static size_t
195
_Py_mbrtowc(wchar_t *pwc, const char *str, size_t len, mbstate_t *pmbs)
196
0
{
197
0
    assert(pwc != NULL);
198
0
    size_t count = mbrtowc(pwc, str, len, pmbs);
199
0
    if (count != 0 && count != DECODE_ERROR && count != INCOMPLETE_CHARACTER) {
200
0
        if (!is_valid_wide_char(*pwc)) {
201
0
            return DECODE_ERROR;
202
0
        }
203
0
    }
204
0
    return count;
205
0
}
206
#endif
207
208
209
#if !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS)
210
211
#define USE_FORCE_ASCII
212
213
extern int _Py_normalize_encoding(const char *, char *, size_t, int);
214
215
/* Workaround FreeBSD and OpenIndiana locale encoding issue with the C locale
216
   and POSIX locale. nl_langinfo(CODESET) announces an alias of the
217
   ASCII encoding, whereas mbstowcs() and wcstombs() functions use the
218
   ISO-8859-1 encoding. The problem is that os.fsencode() and os.fsdecode() use
219
   locale.getpreferredencoding() codec. For example, if command line arguments
220
   are decoded by mbstowcs() and encoded back by os.fsencode(), we get a
221
   UnicodeEncodeError instead of retrieving the original byte string.
222
223
   The workaround is enabled if setlocale(LC_CTYPE, NULL) returns "C",
224
   nl_langinfo(CODESET) announces "ascii" (or an alias to ASCII), and at least
225
   one byte in range 0x80-0xff can be decoded from the locale encoding. The
226
   workaround is also enabled on error, for example if getting the locale
227
   failed.
228
229
   On HP-UX with the C locale or the POSIX locale, nl_langinfo(CODESET)
230
   announces "roman8" but mbstowcs() uses Latin1 in practice. Force also the
231
   ASCII encoding in this case.
232
233
   Values of force_ascii:
234
235
       1: the workaround is used: Py_EncodeLocale() uses
236
          encode_ascii() and Py_DecodeLocale() uses decode_ascii()
237
       0: the workaround is not used: Py_EncodeLocale() uses wcstombs() and
238
          Py_DecodeLocale() uses mbstowcs()
239
      -1: unknown, need to call check_force_ascii() to get the value
240
*/
241
74
#define force_ascii (_PyRuntime.fileutils.force_ascii)
242
243
static int
244
check_force_ascii(void)
245
0
{
246
0
    char *loc = setlocale(LC_CTYPE, NULL);
247
0
    if (loc == NULL) {
248
0
        goto error;
249
0
    }
250
0
    if (strcmp(loc, "C") != 0 && strcmp(loc, "POSIX") != 0) {
251
        /* the LC_CTYPE locale is different than C and POSIX */
252
0
        return 0;
253
0
    }
254
255
0
#if defined(HAVE_LANGINFO_H) && defined(CODESET)
256
0
    const char *codeset = nl_langinfo(CODESET);
257
0
    if (!codeset || codeset[0] == '\0') {
258
        /* CODESET is not set or empty */
259
0
        goto error;
260
0
    }
261
262
0
    char encoding[20];   /* longest name: "iso_646.irv_1991\0" */
263
0
    if (!_Py_normalize_encoding(codeset, encoding, sizeof(encoding), 1)) {
264
0
        goto error;
265
0
    }
266
267
#ifdef __hpux
268
    if (strcmp(encoding, "roman8") == 0) {
269
        unsigned char ch;
270
        wchar_t wch;
271
        size_t res;
272
273
        ch = (unsigned char)0xA7;
274
        res = _Py_mbstowcs(&wch, (char*)&ch, 1);
275
        if (res != DECODE_ERROR && wch == L'\xA7') {
276
            /* On HP-UX with C locale or the POSIX locale,
277
               nl_langinfo(CODESET) announces "roman8", whereas mbstowcs() uses
278
               Latin1 encoding in practice. Force ASCII in this case.
279
280
               Roman8 decodes 0xA7 to U+00CF. Latin1 decodes 0xA7 to U+00A7. */
281
            return 1;
282
        }
283
    }
284
#else
285
0
    const char* ascii_aliases[] = {
286
0
        "ascii",
287
        /* Aliases from Lib/encodings/aliases.py */
288
0
        "646",
289
0
        "ansi_x3.4_1968",
290
0
        "ansi_x3.4_1986",
291
0
        "ansi_x3_4_1968",
292
0
        "cp367",
293
0
        "csascii",
294
0
        "ibm367",
295
0
        "iso646_us",
296
0
        "iso_646.irv_1991",
297
0
        "iso_ir_6",
298
0
        "us",
299
0
        "us_ascii",
300
0
        NULL
301
0
    };
302
303
0
    int is_ascii = 0;
304
0
    for (const char **alias=ascii_aliases; *alias != NULL; alias++) {
305
0
        if (strcmp(encoding, *alias) == 0) {
306
0
            is_ascii = 1;
307
0
            break;
308
0
        }
309
0
    }
310
0
    if (!is_ascii) {
311
        /* nl_langinfo(CODESET) is not "ascii" or an alias of ASCII */
312
0
        return 0;
313
0
    }
314
315
0
    for (unsigned int i=0x80; i<=0xff; i++) {
316
0
        char ch[1];
317
0
        wchar_t wch[1];
318
0
        size_t res;
319
320
0
        unsigned uch = (unsigned char)i;
321
0
        ch[0] = (char)uch;
322
0
        res = _Py_mbstowcs(wch, ch, 1);
323
0
        if (res != DECODE_ERROR) {
324
            /* decoding a non-ASCII character from the locale encoding succeed:
325
               the locale encoding is not ASCII, force ASCII */
326
0
            return 1;
327
0
        }
328
0
    }
329
    /* None of the bytes in the range 0x80-0xff can be decoded from the locale
330
       encoding: the locale encoding is really ASCII */
331
0
#endif   /* !defined(__hpux) */
332
0
    return 0;
333
#else
334
    /* nl_langinfo(CODESET) is not available: always force ASCII */
335
    return 1;
336
#endif   /* defined(HAVE_LANGINFO_H) && defined(CODESET) */
337
338
0
error:
339
    /* if an error occurred, force the ASCII encoding */
340
0
    return 1;
341
0
}
342
343
344
int
345
_Py_GetForceASCII(void)
346
0
{
347
0
    if (force_ascii == -1) {
348
0
        force_ascii = check_force_ascii();
349
0
    }
350
0
    return force_ascii;
351
0
}
352
353
354
void
355
_Py_ResetForceASCII(void)
356
74
{
357
74
    force_ascii = -1;
358
74
}
359
360
361
// Encode a wide string to the ASCII encoding. If errors is
362
// _Py_ERROR_SURROGATEESCAPE, handle non-ASCII character using the
363
// surrogateescape error handler. In that case, the output is non-ASCII.
364
//
365
// Set *str to a newly allocated string on success.
366
// Return a negative number on error: _Py_CODEC_MEMORY_ERROR,
367
// _Py_CODEC_ENCODE_ERROR or _Py_CODEC_UNSUPPORTED_ERROR_HANDLER.
368
//
369
// str and output_length must not be NULL
370
static int
371
encode_ascii(const wchar_t *text, char **str, size_t *output_length,
372
             size_t *error_pos, int raw_malloc, _Py_error_handler errors)
373
0
{
374
0
    assert(str != NULL);
375
0
    assert(output_length != NULL);
376
377
0
    int surrogateescape;
378
0
    if (get_surrogateescape(errors, &surrogateescape) < 0) {
379
        // Only support "strict" and "surrogateescape"
380
0
        return _Py_CODEC_UNSUPPORTED_ERROR_HANDLER;
381
0
    }
382
383
0
    size_t len = wcslen(text);
384
0
    *output_length = len;
385
386
    /* +1 for NULL byte */
387
0
    char *result;
388
0
    result = raw_malloc ? PyMem_RawMalloc(len + 1) : PyMem_Malloc(len + 1);
389
0
    if (result == NULL) {
390
0
        return _Py_CODEC_MEMORY_ERROR;
391
0
    }
392
393
0
    char *out = result;
394
0
    for (size_t i=0; i < len; i++) {
395
0
        wchar_t ch = text[i];
396
397
0
        if (ch <= 0x7f) {
398
            /* ASCII character */
399
0
            *out++ = (char)ch;
400
0
        }
401
0
        else if (surrogateescape && 0xdc80 <= ch && ch <= 0xdcff) {
402
            /* UTF-8b surrogate */
403
0
            *out++ = (char)(ch - 0xdc00);
404
0
        }
405
0
        else {
406
0
            if (raw_malloc) {
407
0
                PyMem_RawFree(result);
408
0
            }
409
0
            else {
410
0
                PyMem_Free(result);
411
0
            }
412
0
            if (error_pos != NULL) {
413
0
                *error_pos = i;
414
0
            }
415
0
            return _Py_CODEC_ENCODE_ERROR;
416
0
        }
417
0
    }
418
0
    *out++ = '\0';
419
0
    assert((size_t)(out - result) == (*output_length + 1));
420
421
0
    *str = result;
422
0
    return 0;
423
0
}
424
#else
425
int
426
_Py_GetForceASCII(void)
427
{
428
    return 0;
429
}
430
431
void
432
_Py_ResetForceASCII(void)
433
{
434
    /* nothing to do */
435
}
436
#endif   /* defined(_Py_FORCE_UTF8_FS_ENCODING) || defined(MS_WINDOWS) */
437
438
439
#if !defined(HAVE_MBRTOWC) || defined(USE_FORCE_ASCII)
440
// Decode a bytes string from the ASCII encoding. If 'errors' is
441
// "surrogateescape", decode non-ASCII bytes with "surrogateescape" error
442
// handler and so the output is non-ASCII.
443
//
444
// On success, set *wstr and *wlen (if set) and return 0.
445
// On error, return a negative number: _Py_CODEC_MEMORY_ERROR,
446
// _Py_CODEC_DECODE_ERROR or _Py_CODEC_UNSUPPORTED_ERROR_HANDLER.
447
// On decode, set *wlen (if set).
448
static int
449
decode_ascii(const char *arg, wchar_t **wstr, size_t *wlen,
450
             _Py_error_handler errors)
451
0
{
452
0
    assert(arg != NULL);
453
0
    assert(wstr != NULL);
454
455
0
    wchar_t *res;
456
0
    unsigned char *in;
457
0
    wchar_t *out;
458
0
    size_t argsize = strlen(arg) + 1;
459
460
0
    int surrogateescape;
461
0
    if (get_surrogateescape(errors, &surrogateescape) < 0) {
462
        // Only support "strict" and "surrogateescape"
463
0
        return _Py_CODEC_UNSUPPORTED_ERROR_HANDLER;
464
0
    }
465
466
0
    if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t)) {
467
0
        return _Py_CODEC_MEMORY_ERROR;
468
0
    }
469
0
    res = PyMem_RawMalloc(argsize * sizeof(wchar_t));
470
0
    if (!res) {
471
0
        return _Py_CODEC_MEMORY_ERROR;
472
0
    }
473
474
0
    out = res;
475
0
    for (in = (unsigned char*)arg; *in; in++) {
476
0
        unsigned char ch = *in;
477
0
        if (ch <= 127) {
478
0
            *out++ = ch;
479
0
        }
480
0
        else {
481
0
            if (!surrogateescape) {
482
0
                PyMem_RawFree(res);
483
0
                if (wlen) {
484
0
                    *wlen = in - (unsigned char*)arg;
485
0
                }
486
0
                return _Py_CODEC_DECODE_ERROR;
487
0
            }
488
0
            *out++ = 0xdc00 + ch;
489
0
        }
490
0
    }
491
0
    *out = 0;
492
493
0
    if (wlen != NULL) {
494
0
        *wlen = out - res;
495
0
    }
496
0
    *wstr = res;
497
0
    return 0;
498
0
}
499
#endif   /* !HAVE_MBRTOWC */
500
501
// Decode a bytes string from the current locale encoding.
502
// On success, set *wstr and *wlen (if set) and return 0.
503
// On error, return a negative number: _Py_CODEC_MEMORY_ERROR,
504
// _Py_CODEC_DECODE_ERROR or _Py_CODEC_UNSUPPORTED_ERROR_HANDLER.
505
// On decode, set *wlen (if set).
506
static int
507
decode_current_locale(const char* arg, wchar_t **wstr, size_t *wlen,
508
                      _Py_error_handler errors)
509
232k
{
510
232k
    assert(arg != NULL);
511
232k
    assert(wstr != NULL);
512
513
232k
    int surrogateescape;
514
232k
    if (get_surrogateescape(errors, &surrogateescape) < 0) {
515
        // Only support "strict" and "surrogateescape"
516
0
        return _Py_CODEC_UNSUPPORTED_ERROR_HANDLER;
517
0
    }
518
519
#ifdef HAVE_BROKEN_MBSTOWCS
520
    /* Some platforms have a broken implementation of
521
     * mbstowcs which does not count the characters that
522
     * would result from conversion.  Use an upper bound.
523
     */
524
    size_t argsize = strlen(arg);
525
#else
526
232k
    size_t argsize = _Py_mbstowcs(NULL, arg, 0);
527
232k
#endif
528
232k
    wchar_t *res;
529
232k
    if (argsize != DECODE_ERROR) {
530
232k
        if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) {
531
0
            return _Py_CODEC_MEMORY_ERROR;
532
0
        }
533
232k
        res = (wchar_t *)PyMem_RawMalloc((argsize + 1) * sizeof(wchar_t));
534
232k
        if (!res) {
535
0
            return _Py_CODEC_MEMORY_ERROR;
536
0
        }
537
538
        // +1 to write also the trailing NUL character
539
232k
        size_t count = _Py_mbstowcs(res, arg, argsize + 1);
540
232k
        if (count != DECODE_ERROR) {
541
            // String decoded successfully.
542
543
            // gh-158893: This assertion can fail if the input string was
544
            // mutated during this function call. For example, the assertion
545
            // fails on decoding strerror() result if another thread mutated
546
            // the string in-place by calling strerror() in parallel.
547
232k
            assert(count == argsize);
548
549
232k
            *wstr = res;
550
232k
            if (wlen != NULL) {
551
232k
                *wlen = count;
552
232k
            }
553
232k
            return 0;
554
232k
        }
555
0
        PyMem_RawFree(res);
556
0
    }
557
558
    /* Conversion failed. Fall back to escaping with surrogateescape. */
559
0
#ifdef HAVE_MBRTOWC
560
    /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
561
562
    /* Overallocate; as multi-byte characters are in the argument, the
563
       actual output could use less memory. */
564
0
    argsize = strlen(arg) + 1;
565
0
    if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t)) {
566
0
        return _Py_CODEC_MEMORY_ERROR;
567
0
    }
568
0
    res = (wchar_t*)PyMem_RawMalloc(argsize * sizeof(wchar_t));
569
0
    if (!res) {
570
0
        return _Py_CODEC_MEMORY_ERROR;
571
0
    }
572
573
0
    unsigned char *in = (unsigned char*)arg;
574
0
    wchar_t *out = res;
575
0
    mbstate_t mbs;
576
0
    memset(&mbs, 0, sizeof mbs);
577
0
    while (argsize) {
578
0
        size_t converted = _Py_mbrtowc(out, (char*)in, argsize, &mbs);
579
0
        if (converted == 0) {
580
            /* Reached end of string; null char stored. */
581
0
            break;
582
0
        }
583
584
0
        if (converted == DECODE_ERROR || converted == INCOMPLETE_CHARACTER) {
585
0
            if (!surrogateescape) {
586
0
                goto decode_error;
587
0
            }
588
589
            /* Decoding error. Escape as UTF-8b, and start over in the initial
590
               shift state. */
591
0
            *out++ = 0xdc00 + *in++;
592
0
            argsize--;
593
0
            memset(&mbs, 0, sizeof mbs);
594
0
            continue;
595
0
        }
596
597
        // _Py_mbrtowc() reject lone surrogate characters
598
0
        assert(!Py_UNICODE_IS_SURROGATE(*out));
599
600
        /* successfully converted some bytes */
601
0
        in += converted;
602
0
        argsize -= converted;
603
0
        out++;
604
0
    }
605
0
    if (wlen != NULL) {
606
0
        *wlen = out - res;
607
0
        assert(res[*wlen] == 0);
608
0
    }
609
0
    *wstr = res;
610
0
    return 0;
611
612
0
decode_error:
613
0
    PyMem_RawFree(res);
614
0
    if (wlen) {
615
0
        *wlen = in - (unsigned char*)arg;
616
0
    }
617
0
    return _Py_CODEC_DECODE_ERROR;
618
#else   /* HAVE_MBRTOWC */
619
    /* Cannot use C locale for escaping; manually escape as if charset
620
       is ASCII (i.e. escape all bytes > 128. This will still roundtrip
621
       correctly in the locale's charset, which must be an ASCII superset. */
622
    return decode_ascii(arg, wstr, wlen, errors);
623
#endif   /* HAVE_MBRTOWC */
624
0
}
625
626
627
static int
628
decode_locale_impl(const char* arg, wchar_t **wstr, size_t *wlen,
629
                   int current_locale, _Py_error_handler errors)
630
245k
{
631
245k
    if (current_locale) {
632
#ifdef _Py_FORCE_UTF8_LOCALE
633
        return _Py_DecodeUTF8(arg, strlen(arg), wstr, wlen, errors);
634
#else
635
232k
        return decode_current_locale(arg, wstr, wlen, errors);
636
232k
#endif
637
232k
    }
638
639
#ifdef _Py_FORCE_UTF8_FS_ENCODING
640
    return _Py_DecodeUTF8(arg, strlen(arg), wstr, wlen, errors);
641
#else
642
12.2k
    int use_utf8 = (_PyRuntime.preconfig.utf8_mode >= 1);
643
#ifdef MS_WINDOWS
644
    use_utf8 |= (_PyRuntime.preconfig.legacy_windows_fs_encoding == 0);
645
#endif
646
12.2k
    if (use_utf8) {
647
12.2k
        return _Py_DecodeUTF8(arg, strlen(arg), wstr, wlen, errors);
648
12.2k
    }
649
650
0
#ifdef USE_FORCE_ASCII
651
0
    if (force_ascii == -1) {
652
0
        force_ascii = check_force_ascii();
653
0
    }
654
655
0
    if (force_ascii) {
656
        /* force ASCII encoding to workaround mbstowcs() issue */
657
0
        return decode_ascii(arg, wstr, wlen, errors);
658
0
    }
659
0
#endif
660
661
0
    return decode_current_locale(arg, wstr, wlen, errors);
662
0
#endif   /* !_Py_FORCE_UTF8_FS_ENCODING */
663
0
}
664
665
666
// Decode a byte string from the locale encoding.
667
//
668
// Supported error handlers are _Py_ERROR_STRICT and _Py_ERROR_SURROGATEESCAPE.
669
// The UTF-8 decoder also supports _Py_ERROR_SURROGATEPASS.
670
//
671
// If errors is _Py_ERROR_SURROGATEESCAPE, undecodable bytes are decoded as
672
// characters in range U+DC80..U+DCFF. If a byte sequence can be decoded as a
673
// surrogate character, escape the bytes using the surrogateescape error
674
// handler instead of decoding them.
675
//
676
// On success, return 0 and write the newly allocated wide character string into
677
// *wstr (use PyMem_RawFree() to free the memory). If wlen is not NULL, write
678
// the number of wide characters excluding the null character into *wlen.
679
//
680
// On error, return a negative number.
681
//
682
// On memory allocation failure, return _Py_CODEC_MEMORY_ERROR.
683
//
684
// On decoding error, return _Py_CODEC_DECODE_ERROR. If wlen is not NULL,
685
// write the start of invalid byte sequence in the input string into *wlen. If
686
// reason is not NULL, write the decoding error message into *reason.
687
//
688
// Return _Py_CODEC_UNSUPPORTED_ERROR_HANDLER if the 'errors' error
689
// handler is not supported: other than "strict" and "surrogateescape".
690
//
691
// Use the _Py_EncodeLocale() function to encode the character string back to
692
// a byte string.
693
//
694
// arg and wstr must not be NULL.
695
int
696
_Py_DecodeLocale(const char* arg, wchar_t **wstr, size_t *wlen,
697
                 int current_locale, _Py_error_handler errors)
698
245k
{
699
245k
    assert(arg != NULL);
700
245k
    assert(wstr != NULL);
701
702
#ifdef Py_DEBUG
703
    size_t arglen = strlen(arg);
704
    size_t wlen_canary = (size_t)-2;
705
    if (wlen) {
706
        *wlen = wlen_canary;
707
    }
708
#endif
709
710
245k
    int res = decode_locale_impl(arg, wstr, wlen, current_locale, errors);
711
245k
    if (res < 0) {
712
        // Error
713
0
        *wstr = NULL;
714
0
        if (res == _Py_CODEC_DECODE_ERROR) {
715
#ifdef Py_DEBUG
716
            assert(wlen == NULL || *wlen != wlen_canary);
717
#endif
718
0
        }
719
0
        else {
720
0
            if (wlen) {
721
0
                *wlen = 0;
722
0
            }
723
0
        }
724
0
    }
725
245k
    else {
726
        // Success
727
245k
        assert(*wstr != NULL);
728
#ifdef Py_DEBUG
729
        // gh-158893: Detect if the input string was mutated during the
730
        // function call. For example, the assertion fails on decoding
731
        // strerror() result if another thread mutated the string in-place by
732
        // calling strerror() in parallel.
733
        assert(strlen(arg) == arglen);
734
        if (wlen != NULL) {
735
            assert(*wlen == wcslen(*wstr));
736
        }
737
#endif
738
245k
    }
739
245k
    return res;
740
245k
}
741
742
743
// Decode a byte string from the locale encoding with the
744
// surrogateescape error handler. Undecodable bytes are decoded as characters
745
// in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate
746
// character, escape the bytes using the surrogateescape error handler instead
747
// of decoding them.
748
//
749
// Return a pointer to a newly allocated wide character string, use
750
// PyMem_RawFree() to free the memory. If size is not NULL, write the number of
751
// wide characters excluding the null character into *size.
752
//
753
// On memory allocation failure, set *size to (size_t)-1 and return NULL.
754
//
755
// On decode error, set *size to (size_t)-2 and return NULL.
756
// Decoding errors should never happen, unless there is a bug in the C library.
757
//
758
// Use the Py_EncodeLocale() function to encode the character string back to a
759
// byte string.
760
wchar_t*
761
Py_DecodeLocale(const char* arg, size_t *size)
762
259
{
763
259
    wchar_t *wstr;
764
259
    int res = _Py_DecodeLocale(arg, &wstr, size, 0, _Py_ERROR_SURROGATEESCAPE);
765
259
    if (res != 0) {
766
0
        assert(res == _Py_CODEC_MEMORY_ERROR || res == _Py_CODEC_DECODE_ERROR);
767
0
        if (size != NULL) {
768
0
            *size = (size_t)res;
769
0
        }
770
0
        return NULL;
771
0
    }
772
259
    return wstr;
773
259
}
774
775
776
// If bytes is NULL, compute the length in 'bytes' of the encoded string.
777
// Otherwise, encode the wide string into 'bytes', decrements 'size', and
778
// return 0 on success.
779
// On encoding error, set 'error_pos' (if set) and return ENCODE_ERROR.
780
static size_t
781
encode_current_locale_impl(const wchar_t *text, const size_t len,
782
                           int surrogateescape,
783
                           char *bytes, size_t size,
784
                           size_t *error_pos)
785
0
{
786
0
    wchar_t buf[2];
787
    // The second character is always the NUL character
788
0
    buf[1] = 0;
789
790
0
    for (size_t i=0; i < len; i++) {
791
0
        wchar_t c = text[i];
792
0
        if (c >= 0xdc80 && c <= 0xdcff) {
793
0
            if (!surrogateescape) {
794
0
                if (error_pos != NULL) {
795
0
                    *error_pos = i;
796
0
                }
797
0
                return ENCODE_ERROR;
798
0
            }
799
            /* UTF-8b surrogate */
800
0
            if (bytes != NULL) {
801
0
                *bytes++ = c - 0xdc00;
802
0
                size--;
803
0
            }
804
0
            else {
805
0
                size++;
806
0
            }
807
0
        }
808
0
        else {
809
            // Encode a single character using wcstombs()
810
0
            buf[0] = c;
811
0
            size_t converted;
812
0
            if (bytes != NULL) {
813
0
                converted = wcstombs(bytes, buf, size);
814
0
            }
815
0
            else {
816
0
                converted = wcstombs(NULL, buf, 0);
817
0
            }
818
0
            if (converted == ENCODE_ERROR) {
819
0
                if (error_pos != NULL) {
820
0
                    *error_pos = i;
821
0
                }
822
0
                return ENCODE_ERROR;
823
0
            }
824
0
            if (bytes != NULL) {
825
0
                bytes += converted;
826
0
                size -= converted;
827
0
            }
828
0
            else {
829
0
                size += converted;
830
0
            }
831
0
        }
832
0
    }
833
0
    if (bytes) {
834
0
        *bytes = '\0';
835
0
    }
836
    // Sanity check, it cannot happen in practice
837
0
    assert(size != ENCODE_ERROR);
838
0
    return size;
839
0
}
840
841
842
// Encode a wide string to the current locale encoding.
843
// Set *str to a newly allocated string on success.
844
// Return a negative number on error: _Py_CODEC_MEMORY_ERROR,
845
// _Py_CODEC_ENCODE_ERROR or _Py_CODEC_UNSUPPORTED_ERROR_HANDLER.
846
//
847
// str and output_length must not be NULL
848
static int
849
encode_current_locale(const wchar_t *text, char **str, size_t *output_length,
850
                      size_t *error_pos, int raw_malloc,
851
                      _Py_error_handler errors)
852
0
{
853
0
    assert(str != NULL);
854
0
    assert(output_length != NULL);
855
856
0
    int surrogateescape;
857
0
    if (get_surrogateescape(errors, &surrogateescape) < 0) {
858
        // Only support "strict" and "surrogateescape"
859
0
        return _Py_CODEC_UNSUPPORTED_ERROR_HANDLER;
860
0
    }
861
862
    // First, compute the output length
863
0
    const size_t len = wcslen(text);
864
    // Sanity check, it cannot happen in practice
865
0
    assert(len != ENCODE_ERROR);
866
0
    size_t size = encode_current_locale_impl(text, len, surrogateescape,
867
0
                                             NULL, 0, error_pos);
868
0
    if (size == ENCODE_ERROR) {
869
0
        return _Py_CODEC_ENCODE_ERROR;
870
0
    }
871
872
0
    *output_length = size;
873
0
    char *result;
874
0
    result = raw_malloc ? PyMem_RawMalloc(size + 1) : PyMem_Malloc(size + 1);
875
0
    if (result == NULL) {
876
0
        return _Py_CODEC_MEMORY_ERROR;
877
0
    }
878
879
    // Second, encode characters
880
0
    size = encode_current_locale_impl(text, len, surrogateescape,
881
0
                                      result, size, error_pos);
882
0
    if (size == ENCODE_ERROR) {
883
0
        if (raw_malloc) {
884
0
            PyMem_RawFree(result);
885
0
        }
886
0
        else {
887
0
            PyMem_Free(result);
888
0
        }
889
0
        return _Py_CODEC_ENCODE_ERROR;
890
0
    }
891
0
    assert(size == 0);
892
893
0
    *str = result;
894
0
    return 0;
895
0
}
896
897
898
static int
899
encode_locale_inner(const wchar_t *text, char **str, size_t *output_length,
900
                    size_t *error_pos, int raw_malloc,
901
                    int current_locale, _Py_error_handler errors)
902
1.59k
{
903
1.59k
    if (current_locale) {
904
#ifdef _Py_FORCE_UTF8_LOCALE
905
        return _Py_EncodeUTF8(text, str, output_length,
906
                              error_pos, raw_malloc, errors);
907
#else
908
0
        return encode_current_locale(text, str, output_length,
909
0
                                     error_pos, raw_malloc, errors);
910
0
#endif
911
0
    }
912
913
#ifdef _Py_FORCE_UTF8_FS_ENCODING
914
    return _Py_EncodeUTF8(text, str, output_length,
915
                          error_pos, raw_malloc, errors);
916
#else
917
1.59k
    int use_utf8 = (_PyRuntime.preconfig.utf8_mode >= 1);
918
#ifdef MS_WINDOWS
919
    use_utf8 |= (_PyRuntime.preconfig.legacy_windows_fs_encoding == 0);
920
#endif
921
1.59k
    if (use_utf8) {
922
1.59k
        return _Py_EncodeUTF8(text, str, output_length,
923
1.59k
                              error_pos, raw_malloc, errors);
924
1.59k
    }
925
926
0
#ifdef USE_FORCE_ASCII
927
0
    if (force_ascii == -1) {
928
0
        force_ascii = check_force_ascii();
929
0
    }
930
931
0
    if (force_ascii) {
932
0
        return encode_ascii(text, str, output_length,
933
0
                            error_pos, raw_malloc, errors);
934
0
    }
935
0
#endif
936
937
0
    return encode_current_locale(text, str, output_length,
938
0
                                 error_pos, raw_malloc, errors);
939
0
#endif   /* _Py_FORCE_UTF8_FS_ENCODING */
940
0
}
941
942
943
// Encode a wide string to the locale encoding.
944
//
945
// Parameters:
946
//
947
// * raw_malloc: if non-zero, allocate memory using PyMem_RawMalloc() instead
948
//   of PyMem_Malloc().
949
// * current_locale: if non-zero, use the current LC_CTYPE, otherwise use
950
//   Python filesystem encoding.
951
// * errors: supported error handlers are _Py_ERROR_STRICT and
952
//   _Py_ERROR_SURROGATEESCAPE. The UTF-8 encoder also supports
953
//   _Py_ERROR_SURROGATEPASS.
954
//
955
// Set *str to a newly allocated decoded string and return 0 on success.
956
// Return a negative result on error:
957
//
958
// * _Py_CODEC_MEMORY_ERROR: memory allocation failure
959
// * _Py_CODEC_ENCODE_ERROR: encoding error, set *error_pos.
960
// * _Py_CODEC_UNSUPPORTED_ERROR_HANDLER: the 'errors' error handler
961
//   is not supported.
962
//
963
// text, str and output_length must not be NULL.
964
static int
965
encode_locale_impl(const wchar_t *text, char **str, size_t *output_length,
966
                   size_t *error_pos, int raw_malloc,
967
                   int current_locale, _Py_error_handler errors)
968
1.59k
{
969
1.59k
    assert(text != NULL);
970
1.59k
    assert(str != NULL);
971
1.59k
    assert(output_length != NULL);
972
973
1.59k
    int res = encode_locale_inner(text, str, output_length,
974
1.59k
                                  error_pos, raw_malloc,
975
1.59k
                                  current_locale, errors);
976
1.59k
    if (res < 0) {
977
        // Error
978
0
        *str = NULL;
979
0
        *output_length = 0;
980
0
        if (res != _Py_CODEC_ENCODE_ERROR) {
981
0
            if (error_pos) {
982
0
                *error_pos = 0;
983
0
            }
984
0
        }
985
0
    }
986
1.59k
    else {
987
1.59k
        assert(*str != NULL);
988
1.59k
        assert(*output_length == strlen(*str));
989
        // *error_pos is left unchanged
990
1.59k
    }
991
1.59k
    return res;
992
1.59k
}
993
994
static char*
995
encode_locale(const wchar_t *text, size_t *error_pos,
996
              int raw_malloc, int current_locale)
997
148
{
998
148
    char *str;
999
148
    size_t unused_output_length;
1000
148
    int res = encode_locale_impl(text, &str, &unused_output_length,
1001
148
                                 error_pos, raw_malloc, current_locale,
1002
148
                                 _Py_ERROR_SURROGATEESCAPE);
1003
148
    if (res != 0) {
1004
0
        assert(res == _Py_CODEC_MEMORY_ERROR || res == _Py_CODEC_ENCODE_ERROR);
1005
0
        if (res == _Py_CODEC_MEMORY_ERROR && error_pos != NULL) {
1006
0
            *error_pos = (size_t)-1;
1007
0
        }
1008
0
        return NULL;
1009
0
    }
1010
148
    return str;
1011
148
}
1012
1013
// Encode a wide character string to the locale encoding with the
1014
// surrogateescape error handler. Surrogate characters in the range
1015
// U+DC80..U+DCFF are encoded to bytes 0x80..0xFF.
1016
//
1017
// Return a pointer to a newly allocated byte string, use PyMem_Free() to free
1018
// the memory. Return NULL on encoding or memory allocation error.
1019
//
1020
// On memory allocation failure, set *error_pos to (size_t)-1 and return NULL.
1021
//
1022
// On encoding error, set *error_pos to the index of the first unencodable
1023
// character and return NULL.
1024
//
1025
// Use the Py_DecodeLocale() function to decode the bytes string back to a wide
1026
// character string.
1027
char*
1028
Py_EncodeLocale(const wchar_t *text, size_t *error_pos)
1029
0
{
1030
0
    return encode_locale(text, error_pos, 0, 0);
1031
0
}
1032
1033
1034
/* Similar to Py_EncodeLocale(), but result must be freed by PyMem_RawFree()
1035
   instead of PyMem_Free(). */
1036
static char*
1037
_Py_EncodeLocaleRaw(const wchar_t *text, size_t *error_pos)
1038
148
{
1039
148
    return encode_locale(text, error_pos, 1, 0);
1040
148
}
1041
1042
1043
int
1044
_Py_EncodeLocale(const wchar_t *text, char **str, size_t *output_length,
1045
                 size_t *error_pos, int current_locale,
1046
                 _Py_error_handler errors)
1047
1.44k
{
1048
1.44k
    return encode_locale_impl(text, str, output_length,
1049
1.44k
                              error_pos, 1, current_locale, errors);
1050
1.44k
}
1051
1052
1053
// Get the current locale encoding name:
1054
//
1055
// - Return "utf-8" if _Py_FORCE_UTF8_LOCALE macro is defined (ex: on Android)
1056
// - Return "utf-8" if the UTF-8 Mode is enabled
1057
// - On Windows, return the ANSI code page (ex: "cp1250")
1058
// - Return "utf-8" if nl_langinfo(CODESET) returns an empty string.
1059
// - Otherwise, return nl_langinfo(CODESET).
1060
//
1061
// Return NULL on memory allocation failure.
1062
//
1063
// See also config_get_locale_encoding()
1064
wchar_t*
1065
_Py_GetLocaleEncoding(void)
1066
0
{
1067
#ifdef _Py_FORCE_UTF8_LOCALE
1068
    // On Android langinfo.h and CODESET are missing,
1069
    // and UTF-8 is always used in mbstowcs() and wcstombs().
1070
    return _PyMem_RawWcsdup(L"utf-8");
1071
#else
1072
1073
#ifdef MS_WINDOWS
1074
    wchar_t encoding[23];
1075
    unsigned int ansi_codepage = GetACP();
1076
    swprintf(encoding, Py_ARRAY_LENGTH(encoding), L"cp%u", ansi_codepage);
1077
    encoding[Py_ARRAY_LENGTH(encoding) - 1] = 0;
1078
    return _PyMem_RawWcsdup(encoding);
1079
#else
1080
0
    const char *encoding = nl_langinfo(CODESET);
1081
0
    if (!encoding || encoding[0] == '\0') {
1082
        // Use UTF-8 if nl_langinfo() returns an empty string. It can happen on
1083
        // macOS if the LC_CTYPE locale is not supported.
1084
0
        return _PyMem_RawWcsdup(L"utf-8");
1085
0
    }
1086
1087
0
    wchar_t *wstr;
1088
0
    if (decode_current_locale(encoding, &wstr, NULL,
1089
0
                              _Py_ERROR_SURROGATEESCAPE) < 0) {
1090
0
        return NULL;
1091
0
    }
1092
0
    return wstr;
1093
0
#endif  // !MS_WINDOWS
1094
1095
0
#endif  // !_Py_FORCE_UTF8_LOCALE
1096
0
}
1097
1098
1099
PyObject *
1100
_Py_GetLocaleEncodingObject(void)
1101
0
{
1102
0
    wchar_t *encoding = _Py_GetLocaleEncoding();
1103
0
    if (encoding == NULL) {
1104
0
        PyErr_NoMemory();
1105
0
        return NULL;
1106
0
    }
1107
1108
0
    PyObject *str = PyUnicode_FromWideChar(encoding, -1);
1109
0
    PyMem_RawFree(encoding);
1110
0
    return str;
1111
0
}
1112
1113
#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION
1114
1115
/* Check whether current locale uses Unicode as internal wchar_t form. */
1116
int
1117
_Py_LocaleUsesNonUnicodeWchar(void)
1118
{
1119
    /* Oracle Solaris uses non-Unicode internal wchar_t form for
1120
       non-Unicode locales and hence needs conversion to UTF first. */
1121
    char* codeset = nl_langinfo(CODESET);
1122
    if (!codeset) {
1123
        return 0;
1124
    }
1125
    /* 646 refers to ISO/IEC 646 standard that corresponds to ASCII encoding */
1126
    return (strcmp(codeset, "UTF-8") != 0 && strcmp(codeset, "646") != 0);
1127
}
1128
1129
static wchar_t *
1130
_Py_ConvertWCharForm(const wchar_t *source, Py_ssize_t size,
1131
                     const char *tocode, const char *fromcode)
1132
{
1133
    static_assert(sizeof(wchar_t) == 4, "wchar_t must be 32-bit");
1134
1135
    /* Ensure we won't overflow the size. */
1136
    if (size > (PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t))) {
1137
        PyErr_NoMemory();
1138
        return NULL;
1139
    }
1140
1141
    /* the string doesn't have to be NULL terminated */
1142
    wchar_t* target = PyMem_Malloc(size * sizeof(wchar_t));
1143
    if (target == NULL) {
1144
        PyErr_NoMemory();
1145
        return NULL;
1146
    }
1147
1148
    iconv_t cd = iconv_open(tocode, fromcode);
1149
    if (cd == (iconv_t)-1) {
1150
        PyErr_Format(PyExc_ValueError, "iconv_open() failed");
1151
        PyMem_Free(target);
1152
        return NULL;
1153
    }
1154
1155
    char *inbuf = (char *) source;
1156
    char *outbuf = (char *) target;
1157
    size_t inbytesleft = sizeof(wchar_t) * size;
1158
    size_t outbytesleft = inbytesleft;
1159
1160
    size_t ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
1161
    if (ret == DECODE_ERROR) {
1162
        PyErr_Format(PyExc_ValueError, "iconv() failed");
1163
        PyMem_Free(target);
1164
        iconv_close(cd);
1165
        return NULL;
1166
    }
1167
1168
    iconv_close(cd);
1169
    return target;
1170
}
1171
1172
/* Convert a wide character string to the UCS-4 encoded string. This
1173
   is necessary on systems where internal form of wchar_t are not Unicode
1174
   code points (e.g. Oracle Solaris).
1175
1176
   Return a pointer to a newly allocated string, use PyMem_Free() to free
1177
   the memory. Return NULL and raise exception on conversion or memory
1178
   allocation error. */
1179
wchar_t *
1180
_Py_DecodeNonUnicodeWchar(const wchar_t *native, Py_ssize_t size)
1181
{
1182
    return _Py_ConvertWCharForm(native, size, "UCS-4-INTERNAL", "wchar_t");
1183
}
1184
1185
/* Convert a UCS-4 encoded string to native wide character string. This
1186
   is necessary on systems where internal form of wchar_t are not Unicode
1187
   code points (e.g. Oracle Solaris).
1188
1189
   The conversion is done in place. This can be done because both wchar_t
1190
   and UCS-4 use 4-byte encoding, and one wchar_t symbol always correspond
1191
   to a single UCS-4 symbol and vice versa. (This is true for Oracle Solaris,
1192
   which is currently the only system using these functions; it doesn't have
1193
   to be for other systems).
1194
1195
   Return 0 on success. Return -1 and raise exception on conversion
1196
   or memory allocation error. */
1197
int
1198
_Py_EncodeNonUnicodeWchar_InPlace(wchar_t *unicode, Py_ssize_t size)
1199
{
1200
    wchar_t* result = _Py_ConvertWCharForm(unicode, size, "wchar_t", "UCS-4-INTERNAL");
1201
    if (!result) {
1202
        return -1;
1203
    }
1204
    memcpy(unicode, result, size * sizeof(wchar_t));
1205
    PyMem_Free(result);
1206
    return 0;
1207
}
1208
#endif /* HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION */
1209
1210
#ifdef MS_WINDOWS
1211
static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
1212
1213
static void
1214
FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
1215
{
1216
    /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
1217
    /* Cannot simply cast and dereference in_ptr,
1218
       since it might not be aligned properly */
1219
    __int64 in;
1220
    memcpy(&in, in_ptr, sizeof(in));
1221
    *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
1222
    *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
1223
}
1224
1225
static void
1226
LARGE_INTEGER_to_time_t_nsec(LARGE_INTEGER *in_ptr, time_t *time_out, int* nsec_out)
1227
{
1228
    *nsec_out = (int)(in_ptr->QuadPart % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
1229
    *time_out = Py_SAFE_DOWNCAST((in_ptr->QuadPart / 10000000) - secs_between_epochs, __int64, time_t);
1230
}
1231
1232
void
1233
_Py_time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
1234
{
1235
    /* XXX endianness */
1236
    __int64 out;
1237
    out = time_in + secs_between_epochs;
1238
    out = out * 10000000 + nsec_in / 100;
1239
    memcpy(out_ptr, &out, sizeof(out));
1240
}
1241
1242
/* Below, we *know* that ugo+r is 0444 */
1243
#if _S_IREAD != 0400
1244
#error Unsupported C library
1245
#endif
1246
static int
1247
attributes_to_mode(DWORD attr)
1248
{
1249
    int m = 0;
1250
    if (attr & FILE_ATTRIBUTE_DIRECTORY)
1251
        m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
1252
    else
1253
        m |= _S_IFREG;
1254
    if (attr & FILE_ATTRIBUTE_READONLY)
1255
        m |= 0444;
1256
    else
1257
        m |= 0666;
1258
    return m;
1259
}
1260
1261
1262
typedef union {
1263
    FILE_ID_128 id;
1264
    struct {
1265
        uint64_t st_ino;
1266
        uint64_t st_ino_high;
1267
    };
1268
} id_128_to_ino;
1269
1270
1271
void
1272
_Py_attribute_data_to_stat(FILE_STANDARD_INFO* standard_info, ULONG reparse_tag,
1273
                           FILE_BASIC_INFO *basic_info, FILE_ID_INFO *id_info,
1274
                           struct _Py_stat_struct *result)
1275
{
1276
    memset(result, 0, sizeof(*result));
1277
1278
    result->st_size = standard_info->EndOfFile.QuadPart;
1279
    result->st_nlink = standard_info->NumberOfLinks;
1280
1281
    /* st_ctime is deprecated, but we preserve the legacy value in our caller, not here */
1282
    LARGE_INTEGER_to_time_t_nsec(&basic_info->CreationTime, &result->st_birthtime, &result->st_birthtime_nsec);
1283
    LARGE_INTEGER_to_time_t_nsec(&basic_info->ChangeTime, &result->st_ctime, &result->st_ctime_nsec);
1284
    LARGE_INTEGER_to_time_t_nsec(&basic_info->LastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1285
    LARGE_INTEGER_to_time_t_nsec(&basic_info->LastAccessTime, &result->st_atime, &result->st_atime_nsec);
1286
1287
    if (id_info) {
1288
        result->st_dev = id_info->VolumeSerialNumber;
1289
        id_128_to_ino file_id;
1290
        file_id.id = id_info->FileId;
1291
        result->st_ino = file_id.st_ino;
1292
        result->st_ino_high = file_id.st_ino_high;
1293
    }
1294
1295
    result->st_file_attributes = basic_info->FileAttributes;
1296
    result->st_mode = attributes_to_mode(result->st_file_attributes);
1297
1298
    /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will
1299
       open other name surrogate reparse points without traversing them. To
1300
       detect/handle these, check st_file_attributes and st_reparse_tag. */
1301
    result->st_reparse_tag = reparse_tag;
1302
    if (result->st_file_attributes & FILE_ATTRIBUTE_REPARSE_POINT &&
1303
        reparse_tag == IO_REPARSE_TAG_SYMLINK) {
1304
        /* set the bits that make this a symlink */
1305
        result->st_mode = (result->st_mode & ~S_IFMT) | S_IFLNK;
1306
    }
1307
}
1308
1309
void
1310
_Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *info,
1311
                            struct _Py_stat_struct *result)
1312
{
1313
    memset(result, 0, sizeof(*result));
1314
    result->st_mode = attributes_to_mode(info->FileAttributes);
1315
    result->st_size = info->EndOfFile.QuadPart;
1316
    LARGE_INTEGER_to_time_t_nsec(&info->CreationTime, &result->st_birthtime, &result->st_birthtime_nsec);
1317
    LARGE_INTEGER_to_time_t_nsec(&info->ChangeTime, &result->st_ctime, &result->st_ctime_nsec);
1318
    LARGE_INTEGER_to_time_t_nsec(&info->LastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1319
    LARGE_INTEGER_to_time_t_nsec(&info->LastAccessTime, &result->st_atime, &result->st_atime_nsec);
1320
    result->st_nlink = info->NumberOfLinks;
1321
    result->st_dev = info->VolumeSerialNumber.QuadPart;
1322
    /* File systems with less than 128-bits zero pad into this field */
1323
    id_128_to_ino file_id;
1324
    file_id.id = info->FileId128;
1325
    result->st_ino = file_id.st_ino;
1326
    result->st_ino_high = file_id.st_ino_high;
1327
    /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will
1328
       open other name surrogate reparse points without traversing them. To
1329
       detect/handle these, check st_file_attributes and st_reparse_tag. */
1330
    result->st_reparse_tag = info->ReparseTag;
1331
    if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
1332
        info->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
1333
        /* set the bits that make this a symlink */
1334
        result->st_mode = (result->st_mode & ~S_IFMT) | S_IFLNK;
1335
    }
1336
    result->st_file_attributes = info->FileAttributes;
1337
    switch (info->DeviceType) {
1338
    case FILE_DEVICE_DISK:
1339
    case FILE_DEVICE_VIRTUAL_DISK:
1340
    case FILE_DEVICE_DFS:
1341
    case FILE_DEVICE_CD_ROM:
1342
    case FILE_DEVICE_CONTROLLER:
1343
    case FILE_DEVICE_DATALINK:
1344
        break;
1345
    case FILE_DEVICE_DISK_FILE_SYSTEM:
1346
    case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
1347
    case FILE_DEVICE_NETWORK_FILE_SYSTEM:
1348
        result->st_mode = (result->st_mode & ~S_IFMT) | 0x6000; /* _S_IFBLK */
1349
        break;
1350
    case FILE_DEVICE_CONSOLE:
1351
    case FILE_DEVICE_NULL:
1352
    case FILE_DEVICE_KEYBOARD:
1353
    case FILE_DEVICE_MODEM:
1354
    case FILE_DEVICE_MOUSE:
1355
    case FILE_DEVICE_PARALLEL_PORT:
1356
    case FILE_DEVICE_PRINTER:
1357
    case FILE_DEVICE_SCREEN:
1358
    case FILE_DEVICE_SERIAL_PORT:
1359
    case FILE_DEVICE_SOUND:
1360
        result->st_mode = (result->st_mode & ~S_IFMT) | _S_IFCHR;
1361
        break;
1362
    case FILE_DEVICE_NAMED_PIPE:
1363
        result->st_mode = (result->st_mode & ~S_IFMT) | _S_IFIFO;
1364
        break;
1365
    default:
1366
        if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1367
            result->st_mode = (result->st_mode & ~S_IFMT) | _S_IFDIR;
1368
        }
1369
        break;
1370
    }
1371
}
1372
1373
#endif
1374
1375
/* Return information about a file.
1376
1377
   On POSIX, use fstat().
1378
1379
   On Windows, use GetFileType() and GetFileInformationByHandle() which support
1380
   files larger than 2 GiB.  fstat() may fail with EOVERFLOW on files larger
1381
   than 2 GiB because the file size type is a signed 32-bit integer: see issue
1382
   #23152.
1383
1384
   On Windows, set the last Windows error and return nonzero on error. On
1385
   POSIX, set errno and return nonzero on error. Fill status and return 0 on
1386
   success. */
1387
int
1388
_Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
1389
24.7k
{
1390
#ifdef MS_WINDOWS
1391
    FILE_STANDARD_INFO standardInfo = {0};
1392
    FILE_BASIC_INFO basicInfo = {0};
1393
    FILE_ID_INFO idInfo = {0};
1394
    FILE_ID_INFO *pIdInfo = &idInfo;
1395
    HANDLE h;
1396
    int type;
1397
1398
    h = _Py_get_osfhandle_noraise(fd);
1399
1400
    if (h == INVALID_HANDLE_VALUE) {
1401
        /* errno is already set by _get_osfhandle, but we also set
1402
           the Win32 error for callers who expect that */
1403
        SetLastError(ERROR_INVALID_HANDLE);
1404
        return -1;
1405
    }
1406
    memset(status, 0, sizeof(*status));
1407
1408
    type = GetFileType(h);
1409
    if (type == FILE_TYPE_UNKNOWN) {
1410
        DWORD error = GetLastError();
1411
        if (error != 0) {
1412
            errno = winerror_to_errno(error);
1413
            return -1;
1414
        }
1415
        /* else: valid but unknown file */
1416
    }
1417
1418
    if (type != FILE_TYPE_DISK) {
1419
        if (type == FILE_TYPE_CHAR)
1420
            status->st_mode = _S_IFCHR;
1421
        else if (type == FILE_TYPE_PIPE)
1422
            status->st_mode = _S_IFIFO;
1423
        return 0;
1424
    }
1425
1426
    if (!GetFileInformationByHandleEx(h,FileStandardInfo, &standardInfo, sizeof(standardInfo)) ||
1427
        !GetFileInformationByHandleEx(h, FileBasicInfo, &basicInfo, sizeof(basicInfo))) {
1428
        /* The Win32 error is already set, but we also set errno for
1429
           callers who expect it */
1430
        errno = winerror_to_errno(GetLastError());
1431
        return -1;
1432
    }
1433
1434
    if (!GetFileInformationByHandleEx(h, FileIdInfo, &idInfo, sizeof(idInfo))) {
1435
        /* Failed to get FileIdInfo, so do not pass it along */
1436
        pIdInfo = NULL;
1437
    }
1438
1439
    _Py_attribute_data_to_stat(&standardInfo, 0, &basicInfo, pIdInfo, status);
1440
    return 0;
1441
#else
1442
24.7k
    return fstat(fd, status);
1443
24.7k
#endif
1444
24.7k
}
1445
1446
/* Return information about a file.
1447
1448
   On POSIX, use fstat().
1449
1450
   On Windows, use GetFileType() and GetFileInformationByHandle() which support
1451
   files larger than 2 GiB.  fstat() may fail with EOVERFLOW on files larger
1452
   than 2 GiB because the file size type is a signed 32-bit integer: see issue
1453
   #23152.
1454
1455
   Raise an exception and return -1 on error. On Windows, set the last Windows
1456
   error on error. On POSIX, set errno on error. Fill status and return 0 on
1457
   success.
1458
1459
   Release the GIL to call GetFileType() and GetFileInformationByHandle(), or
1460
   to call fstat(). The caller must hold the GIL. */
1461
int
1462
_Py_fstat(int fd, struct _Py_stat_struct *status)
1463
0
{
1464
0
    int res;
1465
1466
0
    _Py_AssertHoldsTstate();
1467
1468
0
    Py_BEGIN_ALLOW_THREADS
1469
0
    res = _Py_fstat_noraise(fd, status);
1470
0
    Py_END_ALLOW_THREADS
1471
1472
0
    if (res != 0) {
1473
#ifdef MS_WINDOWS
1474
        PyErr_SetFromWindowsErr(0);
1475
#else
1476
0
        PyErr_SetFromErrno(PyExc_OSError);
1477
0
#endif
1478
0
        return -1;
1479
0
    }
1480
0
    return 0;
1481
0
}
1482
1483
/* Like _Py_stat() but with a raw filename. */
1484
int
1485
_Py_wstat(const wchar_t* path, struct stat *buf)
1486
74
{
1487
74
    int err;
1488
#ifdef MS_WINDOWS
1489
    struct _stat wstatbuf;
1490
    err = _wstat(path, &wstatbuf);
1491
    if (!err) {
1492
        buf->st_mode = wstatbuf.st_mode;
1493
    }
1494
#else
1495
74
    char *fname;
1496
74
    fname = _Py_EncodeLocaleRaw(path, NULL);
1497
74
    if (fname == NULL) {
1498
0
        errno = EINVAL;
1499
0
        return -1;
1500
0
    }
1501
74
    err = stat(fname, buf);
1502
74
    PyMem_RawFree(fname);
1503
74
#endif
1504
74
    return err;
1505
74
}
1506
1507
1508
/* Call _wstat() on Windows, or encode the path to the filesystem encoding and
1509
   call stat() otherwise. Only fill st_mode attribute on Windows.
1510
1511
   Return 0 on success, -1 on _wstat() / stat() error, -2 if an exception was
1512
   raised. */
1513
1514
int
1515
_Py_stat(PyObject *path, struct stat *statbuf)
1516
111
{
1517
#ifdef MS_WINDOWS
1518
    int err;
1519
1520
    wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);
1521
    if (wpath == NULL)
1522
        return -2;
1523
1524
    err = _Py_wstat(wpath, statbuf);
1525
    PyMem_Free(wpath);
1526
    return err;
1527
#else
1528
111
    PyObject *bytes = PyUnicode_EncodeFSDefault(path);
1529
111
    if (bytes == NULL) {
1530
0
        return -2;
1531
0
    }
1532
1533
    /* check for embedded null bytes */
1534
111
    char *cpath;
1535
111
    if (PyBytes_AsStringAndSize(bytes, &cpath, NULL) == -1) {
1536
0
        Py_DECREF(bytes);
1537
0
        return -2;
1538
0
    }
1539
1540
111
    int ret = stat(cpath, statbuf);
1541
111
    Py_DECREF(bytes);
1542
111
    assert(ret == 0 || ret == -1);
1543
111
    return ret;
1544
111
#endif
1545
111
}
1546
1547
#ifdef MS_WINDOWS
1548
// For some Windows API partitions, SetHandleInformation() is declared
1549
// but none of the handle flags are defined.
1550
#ifndef HANDLE_FLAG_INHERIT
1551
#define HANDLE_FLAG_INHERIT 0x00000001
1552
#endif
1553
#endif
1554
1555
/* This function MUST be kept async-signal-safe on POSIX when raise=0. */
1556
static int
1557
get_inheritable(int fd, int raise)
1558
37
{
1559
#ifdef MS_WINDOWS
1560
    HANDLE handle;
1561
    DWORD flags;
1562
1563
    handle = _Py_get_osfhandle_noraise(fd);
1564
    if (handle == INVALID_HANDLE_VALUE) {
1565
        if (raise)
1566
            PyErr_SetFromErrno(PyExc_OSError);
1567
        return -1;
1568
    }
1569
1570
    if (!GetHandleInformation(handle, &flags)) {
1571
        if (raise)
1572
            PyErr_SetFromWindowsErr(0);
1573
        return -1;
1574
    }
1575
1576
    return (flags & HANDLE_FLAG_INHERIT);
1577
#else
1578
37
    int flags;
1579
1580
37
    flags = fcntl(fd, F_GETFD, 0);
1581
37
    if (flags == -1) {
1582
0
        if (raise)
1583
0
            PyErr_SetFromErrno(PyExc_OSError);
1584
0
        return -1;
1585
0
    }
1586
37
    return !(flags & FD_CLOEXEC);
1587
37
#endif
1588
37
}
1589
1590
/* Get the inheritable flag of the specified file descriptor.
1591
   Return 1 if the file descriptor can be inherited, 0 if it cannot,
1592
   raise an exception and return -1 on error. */
1593
int
1594
_Py_get_inheritable(int fd)
1595
0
{
1596
0
    return get_inheritable(fd, 1);
1597
0
}
1598
1599
1600
/* This function MUST be kept async-signal-safe on POSIX when raise=0. */
1601
static int
1602
set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
1603
115k
{
1604
#ifdef MS_WINDOWS
1605
    HANDLE handle;
1606
    DWORD flags;
1607
#else
1608
115k
#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
1609
115k
    static int ioctl_works = -1;
1610
115k
    int request;
1611
115k
    int err;
1612
115k
#endif
1613
115k
    int flags, new_flags;
1614
115k
    int res;
1615
115k
#endif
1616
1617
    /* atomic_flag_works can only be used to make the file descriptor
1618
       non-inheritable */
1619
115k
    assert(!(atomic_flag_works != NULL && inheritable));
1620
1621
115k
    if (atomic_flag_works != NULL && !inheritable) {
1622
115k
        if (_Py_atomic_load_int_relaxed(atomic_flag_works) == -1) {
1623
37
            int isInheritable = get_inheritable(fd, raise);
1624
37
            if (isInheritable == -1)
1625
0
                return -1;
1626
37
            _Py_atomic_store_int_relaxed(atomic_flag_works, !isInheritable);
1627
37
        }
1628
1629
115k
        if (_Py_atomic_load_int_relaxed(atomic_flag_works))
1630
115k
            return 0;
1631
115k
    }
1632
1633
#ifdef MS_WINDOWS
1634
    handle = _Py_get_osfhandle_noraise(fd);
1635
    if (handle == INVALID_HANDLE_VALUE) {
1636
        if (raise)
1637
            PyErr_SetFromErrno(PyExc_OSError);
1638
        return -1;
1639
    }
1640
1641
    if (inheritable)
1642
        flags = HANDLE_FLAG_INHERIT;
1643
    else
1644
        flags = 0;
1645
1646
    if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
1647
        if (raise)
1648
            PyErr_SetFromWindowsErr(0);
1649
        return -1;
1650
    }
1651
    return 0;
1652
1653
#else
1654
1655
0
#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
1656
0
    if (raise != 0 && _Py_atomic_load_int_relaxed(&ioctl_works) != 0) {
1657
        /* fast-path: ioctl() only requires one syscall */
1658
        /* caveat: raise=0 is an indicator that we must be async-signal-safe
1659
         * thus avoid using ioctl() so we skip the fast-path. */
1660
0
        if (inheritable)
1661
0
            request = FIONCLEX;
1662
0
        else
1663
0
            request = FIOCLEX;
1664
0
        err = ioctl(fd, request, NULL);
1665
0
        if (!err) {
1666
0
            if (_Py_atomic_load_int_relaxed(&ioctl_works) == -1) {
1667
0
                _Py_atomic_store_int_relaxed(&ioctl_works, 1);
1668
0
            }
1669
0
            return 0;
1670
0
        }
1671
1672
0
#ifdef O_PATH
1673
0
        if (errno == EBADF) {
1674
            // bpo-44849: On Linux and FreeBSD, ioctl(FIOCLEX) fails with EBADF
1675
            // on O_PATH file descriptors. Fall through to the fcntl()
1676
            // implementation.
1677
0
        }
1678
0
        else
1679
0
#endif
1680
0
        if (errno != ENOTTY && errno != EACCES) {
1681
0
            if (raise)
1682
0
                PyErr_SetFromErrno(PyExc_OSError);
1683
0
            return -1;
1684
0
        }
1685
0
        else {
1686
            /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for
1687
               device". The ioctl is declared but not supported by the kernel.
1688
               Remember that ioctl() doesn't work. It is the case on
1689
               Illumos-based OS for example.
1690
1691
               Issue #27057: When SELinux policy disallows ioctl it will fail
1692
               with EACCES. While FIOCLEX is safe operation it may be
1693
               unavailable because ioctl was denied altogether.
1694
               This can be the case on Android. */
1695
0
            _Py_atomic_store_int_relaxed(&ioctl_works, 0);
1696
0
        }
1697
        /* fallback to fcntl() if ioctl() does not work */
1698
0
    }
1699
0
#endif
1700
1701
    /* slow-path: fcntl() requires two syscalls */
1702
0
    flags = fcntl(fd, F_GETFD);
1703
0
    if (flags < 0) {
1704
0
        if (raise)
1705
0
            PyErr_SetFromErrno(PyExc_OSError);
1706
0
        return -1;
1707
0
    }
1708
1709
0
    if (inheritable) {
1710
0
        new_flags = flags & ~FD_CLOEXEC;
1711
0
    }
1712
0
    else {
1713
0
        new_flags = flags | FD_CLOEXEC;
1714
0
    }
1715
1716
0
    if (new_flags == flags) {
1717
        /* FD_CLOEXEC flag already set/cleared: nothing to do */
1718
0
        return 0;
1719
0
    }
1720
1721
0
    res = fcntl(fd, F_SETFD, new_flags);
1722
0
    if (res < 0) {
1723
0
        if (raise)
1724
0
            PyErr_SetFromErrno(PyExc_OSError);
1725
0
        return -1;
1726
0
    }
1727
0
    return 0;
1728
0
#endif
1729
0
}
1730
1731
/* Make the file descriptor non-inheritable.
1732
   Return 0 on success, set errno and return -1 on error. */
1733
static int
1734
make_non_inheritable(int fd)
1735
0
{
1736
0
    return set_inheritable(fd, 0, 0, NULL);
1737
0
}
1738
1739
/* Set the inheritable flag of the specified file descriptor.
1740
   On success: return 0, on error: raise an exception and return -1.
1741
1742
   If atomic_flag_works is not NULL:
1743
1744
    * if *atomic_flag_works==-1, check if the inheritable is set on the file
1745
      descriptor: if yes, set *atomic_flag_works to 1, otherwise set to 0 and
1746
      set the inheritable flag
1747
    * if *atomic_flag_works==1: do nothing
1748
    * if *atomic_flag_works==0: set inheritable flag to False
1749
1750
   Set atomic_flag_works to NULL if no atomic flag was used to create the
1751
   file descriptor.
1752
1753
   atomic_flag_works can only be used to make a file descriptor
1754
   non-inheritable: atomic_flag_works must be NULL if inheritable=1. */
1755
int
1756
_Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works)
1757
115k
{
1758
115k
    return set_inheritable(fd, inheritable, 1, atomic_flag_works);
1759
115k
}
1760
1761
/* Same as _Py_set_inheritable() but on error, set errno and
1762
   don't raise an exception.
1763
   This function is async-signal-safe. */
1764
int
1765
_Py_set_inheritable_async_safe(int fd, int inheritable, int *atomic_flag_works)
1766
0
{
1767
0
    return set_inheritable(fd, inheritable, 0, atomic_flag_works);
1768
0
}
1769
1770
static int
1771
_Py_open_impl(const char *pathname, int flags, int gil_held)
1772
0
{
1773
0
    int fd;
1774
0
    int async_err = 0;
1775
0
#ifndef MS_WINDOWS
1776
0
    int *atomic_flag_works;
1777
0
#endif
1778
1779
#ifdef MS_WINDOWS
1780
    flags |= O_NOINHERIT;
1781
#elif defined(O_CLOEXEC)
1782
    atomic_flag_works = &_Py_open_cloexec_works;
1783
0
    flags |= O_CLOEXEC;
1784
#else
1785
    atomic_flag_works = NULL;
1786
#endif
1787
1788
0
    if (gil_held) {
1789
0
        PyObject *pathname_obj = PyUnicode_DecodeFSDefault(pathname);
1790
0
        if (pathname_obj == NULL) {
1791
0
            return -1;
1792
0
        }
1793
0
        if (PySys_Audit("open", "OOi", pathname_obj, Py_None, flags) < 0) {
1794
0
            Py_DECREF(pathname_obj);
1795
0
            return -1;
1796
0
        }
1797
1798
0
        do {
1799
0
            Py_BEGIN_ALLOW_THREADS
1800
0
            fd = open(pathname, flags);
1801
0
            Py_END_ALLOW_THREADS
1802
0
        } while (fd < 0
1803
0
                 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1804
0
        if (async_err) {
1805
0
            Py_DECREF(pathname_obj);
1806
0
            return -1;
1807
0
        }
1808
0
        if (fd < 0) {
1809
0
            PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, pathname_obj, NULL);
1810
0
            Py_DECREF(pathname_obj);
1811
0
            return -1;
1812
0
        }
1813
0
        Py_DECREF(pathname_obj);
1814
0
    }
1815
0
    else {
1816
0
        fd = open(pathname, flags);
1817
0
        if (fd < 0)
1818
0
            return -1;
1819
0
    }
1820
1821
0
#ifndef MS_WINDOWS
1822
0
    if (set_inheritable(fd, 0, gil_held, atomic_flag_works) < 0) {
1823
0
        close(fd);
1824
0
        return -1;
1825
0
    }
1826
0
#endif
1827
1828
0
    return fd;
1829
0
}
1830
1831
/* Open a file with the specified flags (wrapper to open() function).
1832
   Return a file descriptor on success. Raise an exception and return -1 on
1833
   error.
1834
1835
   The file descriptor is created non-inheritable.
1836
1837
   When interrupted by a signal (open() fails with EINTR), retry the syscall,
1838
   except if the Python signal handler raises an exception.
1839
1840
   Release the GIL to call open(). The caller must hold the GIL. */
1841
int
1842
_Py_open(const char *pathname, int flags)
1843
0
{
1844
    /* _Py_open() must be called with the GIL held. */
1845
0
    _Py_AssertHoldsTstate();
1846
0
    return _Py_open_impl(pathname, flags, 1);
1847
0
}
1848
1849
/* Open a file with the specified flags (wrapper to open() function).
1850
   Return a file descriptor on success. Set errno and return -1 on error.
1851
1852
   The file descriptor is created non-inheritable.
1853
1854
   If interrupted by a signal, fail with EINTR. */
1855
int
1856
_Py_open_noraise(const char *pathname, int flags)
1857
0
{
1858
0
    return _Py_open_impl(pathname, flags, 0);
1859
0
}
1860
1861
/* Open a file. Use _wfopen() on Windows, encode the path to the locale
1862
   encoding and use fopen() otherwise.
1863
1864
   The file descriptor is created non-inheritable.
1865
1866
   If interrupted by a signal, fail with EINTR. */
1867
FILE *
1868
_Py_wfopen(const wchar_t *path, const wchar_t *mode)
1869
0
{
1870
0
    FILE *f;
1871
0
    if (PySys_Audit("open", "uui", path, mode, 0) < 0) {
1872
0
        return NULL;
1873
0
    }
1874
0
#ifndef MS_WINDOWS
1875
0
    char *cpath;
1876
0
    char cmode[10];
1877
0
    size_t r;
1878
0
    r = wcstombs(cmode, mode, 10);
1879
0
    if (r == DECODE_ERROR || r >= 10) {
1880
0
        errno = EINVAL;
1881
0
        return NULL;
1882
0
    }
1883
0
    cpath = _Py_EncodeLocaleRaw(path, NULL);
1884
0
    if (cpath == NULL) {
1885
0
        return NULL;
1886
0
    }
1887
0
    f = fopen(cpath, cmode);
1888
0
    PyMem_RawFree(cpath);
1889
#else
1890
    f = _wfopen(path, mode);
1891
#endif
1892
0
    if (f == NULL)
1893
0
        return NULL;
1894
0
    if (make_non_inheritable(fileno(f)) < 0) {
1895
0
        fclose(f);
1896
0
        return NULL;
1897
0
    }
1898
0
    return f;
1899
0
}
1900
1901
1902
/* Open a file.
1903
1904
   On Windows, if 'path' is a Unicode string, call _wfopen(). Otherwise, encode
1905
   the path to the filesystem encoding and call fopen().
1906
1907
   Return the new file object on success. Raise an exception and return NULL
1908
   on error.
1909
1910
   The file descriptor is created non-inheritable.
1911
1912
   When interrupted by a signal (open() fails with EINTR), retry the syscall,
1913
   except if the Python signal handler raises an exception.
1914
1915
   Release the GIL to call _wfopen() or fopen(). The caller must hold
1916
   the GIL. */
1917
FILE*
1918
Py_fopen(PyObject *path, const char *mode)
1919
52.7k
{
1920
52.7k
    _Py_AssertHoldsTstate();
1921
1922
52.7k
    if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
1923
0
        return NULL;
1924
0
    }
1925
1926
52.7k
    FILE *f;
1927
52.7k
    int async_err = 0;
1928
52.7k
    int saved_errno;
1929
#ifdef MS_WINDOWS
1930
    PyObject *unicode;
1931
    if (!PyUnicode_FSDecoder(path, &unicode)) {
1932
        return NULL;
1933
    }
1934
1935
    wchar_t *wpath = PyUnicode_AsWideCharString(unicode, NULL);
1936
    Py_DECREF(unicode);
1937
    if (wpath == NULL) {
1938
        return NULL;
1939
    }
1940
1941
    wchar_t wmode[10];
1942
    int usize = MultiByteToWideChar(CP_ACP, 0, mode, -1,
1943
                                    wmode, Py_ARRAY_LENGTH(wmode));
1944
    if (usize == 0) {
1945
        PyErr_SetFromWindowsErr(0);
1946
        PyMem_Free(wpath);
1947
        return NULL;
1948
    }
1949
1950
    do {
1951
        Py_BEGIN_ALLOW_THREADS
1952
        _Py_BEGIN_SUPPRESS_IPH
1953
        f = _wfopen(wpath, wmode);
1954
        _Py_END_SUPPRESS_IPH
1955
        Py_END_ALLOW_THREADS
1956
    } while (f == NULL
1957
             && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1958
    saved_errno = errno;
1959
    PyMem_Free(wpath);
1960
#else
1961
52.7k
    PyObject *bytes;
1962
52.7k
    if (!PyUnicode_FSConverter(path, &bytes)) {
1963
0
        return NULL;
1964
0
    }
1965
52.7k
    const char *path_bytes = PyBytes_AS_STRING(bytes);
1966
1967
52.7k
    do {
1968
52.7k
        Py_BEGIN_ALLOW_THREADS
1969
52.7k
        f = fopen(path_bytes, mode);
1970
52.7k
        Py_END_ALLOW_THREADS
1971
52.7k
    } while (f == NULL
1972
52.7k
             && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1973
52.7k
    saved_errno = errno;
1974
52.7k
    Py_DECREF(bytes);
1975
52.7k
#endif
1976
1977
52.7k
    if (async_err) {
1978
0
        return NULL;
1979
0
    }
1980
1981
52.7k
    if (f == NULL) {
1982
52.7k
        errno = saved_errno;
1983
52.7k
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1984
52.7k
        return NULL;
1985
52.7k
    }
1986
1987
0
    if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
1988
0
        fclose(f);
1989
0
        return NULL;
1990
0
    }
1991
0
    return f;
1992
0
}
1993
1994
1995
// Call fclose().
1996
//
1997
// On Windows, files opened by Py_fopen() in the Python DLL must be closed by
1998
// the Python DLL to use the same C runtime version. Otherwise, calling
1999
// fclose() directly can cause undefined behavior.
2000
int
2001
Py_fclose(FILE *file)
2002
0
{
2003
0
    return fclose(file);
2004
0
}
2005
2006
2007
/* Read count bytes from fd into buf.
2008
2009
   On success, return the number of read bytes, it can be lower than count.
2010
   If the current file offset is at or past the end of file, no bytes are read,
2011
   and read() returns zero.
2012
2013
   On error, raise an exception, set errno and return -1.
2014
2015
   When interrupted by a signal (read() fails with EINTR), retry the syscall.
2016
   If the Python signal handler raises an exception, the function returns -1
2017
   (the syscall is not retried).
2018
2019
   Release the GIL to call read(). The caller must hold the GIL. */
2020
Py_ssize_t
2021
_Py_read(int fd, void *buf, size_t count)
2022
11.5k
{
2023
11.5k
    Py_ssize_t n;
2024
11.5k
    int err;
2025
11.5k
    int async_err = 0;
2026
2027
11.5k
    _Py_AssertHoldsTstate();
2028
2029
    /* _Py_read() must not be called with an exception set, otherwise the
2030
     * caller may think that read() was interrupted by a signal and the signal
2031
     * handler raised an exception. */
2032
11.5k
    assert(!PyErr_Occurred());
2033
2034
11.5k
    if (count > _PY_READ_MAX) {
2035
0
        count = _PY_READ_MAX;
2036
0
    }
2037
2038
11.5k
    _Py_BEGIN_SUPPRESS_IPH
2039
11.5k
    do {
2040
11.5k
        Py_BEGIN_ALLOW_THREADS
2041
11.5k
        errno = 0;
2042
#ifdef MS_WINDOWS
2043
        _doserrno = 0;
2044
        n = read(fd, buf, (int)count);
2045
        // read() on a non-blocking empty pipe fails with EINVAL, which is
2046
        // mapped from the Windows error code ERROR_NO_DATA.
2047
        if (n < 0 && errno == EINVAL) {
2048
            if (_doserrno == ERROR_NO_DATA) {
2049
                errno = EAGAIN;
2050
            }
2051
        }
2052
#else
2053
11.5k
        n = read(fd, buf, count);
2054
11.5k
#endif
2055
        /* save/restore errno because PyErr_CheckSignals()
2056
         * and PyErr_SetFromErrno() can modify it */
2057
11.5k
        err = errno;
2058
11.5k
        Py_END_ALLOW_THREADS
2059
11.5k
    } while (n < 0 && err == EINTR &&
2060
0
            !(async_err = PyErr_CheckSignals()));
2061
11.5k
    _Py_END_SUPPRESS_IPH
2062
2063
11.5k
    if (async_err) {
2064
        /* read() was interrupted by a signal (failed with EINTR)
2065
         * and the Python signal handler raised an exception */
2066
0
        errno = err;
2067
0
        assert(errno == EINTR && PyErr_Occurred());
2068
0
        return -1;
2069
0
    }
2070
11.5k
    if (n < 0) {
2071
0
        PyErr_SetFromErrno(PyExc_OSError);
2072
0
        errno = err;
2073
0
        return -1;
2074
0
    }
2075
2076
11.5k
    return n;
2077
11.5k
}
2078
2079
static Py_ssize_t
2080
_Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
2081
240k
{
2082
240k
    Py_ssize_t n;
2083
240k
    int err;
2084
240k
    int async_err = 0;
2085
2086
240k
    _Py_BEGIN_SUPPRESS_IPH
2087
#ifdef MS_WINDOWS
2088
    if (count > 32767) {
2089
        /* Issue #11395: the Windows console returns an error (12: not
2090
           enough space error) on writing into stdout if stdout mode is
2091
           binary and the length is greater than 66,000 bytes (or less,
2092
           depending on heap usage). */
2093
        if (gil_held) {
2094
            Py_BEGIN_ALLOW_THREADS
2095
            if (isatty(fd)) {
2096
                count = 32767;
2097
            }
2098
            Py_END_ALLOW_THREADS
2099
        } else {
2100
            if (isatty(fd)) {
2101
                count = 32767;
2102
            }
2103
        }
2104
    }
2105
2106
#endif
2107
240k
    if (count > _PY_WRITE_MAX) {
2108
0
        count = _PY_WRITE_MAX;
2109
0
    }
2110
2111
240k
    if (gil_held) {
2112
240k
        do {
2113
240k
            Py_BEGIN_ALLOW_THREADS
2114
240k
            errno = 0;
2115
#ifdef MS_WINDOWS
2116
            // write() on a non-blocking pipe fails with ENOSPC on Windows if
2117
            // the pipe lacks available space for the entire buffer.
2118
            int c = (int)count;
2119
            do {
2120
                _doserrno = 0;
2121
                n = write(fd, buf, c);
2122
                if (n >= 0 || errno != ENOSPC || _doserrno != 0) {
2123
                    break;
2124
                }
2125
                errno = EAGAIN;
2126
                c /= 2;
2127
            } while (c > 0);
2128
#else
2129
240k
            n = write(fd, buf, count);
2130
240k
#endif
2131
            /* save/restore errno because PyErr_CheckSignals()
2132
             * and PyErr_SetFromErrno() can modify it */
2133
240k
            err = errno;
2134
240k
            Py_END_ALLOW_THREADS
2135
240k
        } while (n < 0 && err == EINTR &&
2136
0
                !(async_err = PyErr_CheckSignals()));
2137
240k
    }
2138
0
    else {
2139
0
        do {
2140
0
            errno = 0;
2141
#ifdef MS_WINDOWS
2142
            // write() on a non-blocking pipe fails with ENOSPC on Windows if
2143
            // the pipe lacks available space for the entire buffer.
2144
            int c = (int)count;
2145
            do {
2146
                _doserrno = 0;
2147
                n = write(fd, buf, c);
2148
                if (n >= 0 || errno != ENOSPC || _doserrno != 0) {
2149
                    break;
2150
                }
2151
                errno = EAGAIN;
2152
                c /= 2;
2153
            } while (c > 0);
2154
#else
2155
0
            n = write(fd, buf, count);
2156
0
#endif
2157
0
            err = errno;
2158
0
        } while (n < 0 && err == EINTR);
2159
0
    }
2160
240k
    _Py_END_SUPPRESS_IPH
2161
2162
240k
    if (async_err) {
2163
        /* write() was interrupted by a signal (failed with EINTR)
2164
           and the Python signal handler raised an exception (if gil_held is
2165
           nonzero). */
2166
0
        errno = err;
2167
0
        assert(errno == EINTR && (!gil_held || PyErr_Occurred()));
2168
0
        return -1;
2169
0
    }
2170
240k
    if (n < 0) {
2171
0
        if (gil_held)
2172
0
            PyErr_SetFromErrno(PyExc_OSError);
2173
0
        errno = err;
2174
0
        return -1;
2175
0
    }
2176
2177
240k
    return n;
2178
240k
}
2179
2180
/* Write count bytes of buf into fd.
2181
2182
   On success, return the number of written bytes, it can be lower than count
2183
   including 0. On error, raise an exception, set errno and return -1.
2184
2185
   When interrupted by a signal (write() fails with EINTR), retry the syscall.
2186
   If the Python signal handler raises an exception, the function returns -1
2187
   (the syscall is not retried).
2188
2189
   Release the GIL to call write(). The caller must hold the GIL. */
2190
Py_ssize_t
2191
_Py_write(int fd, const void *buf, size_t count)
2192
240k
{
2193
240k
    _Py_AssertHoldsTstate();
2194
2195
    /* _Py_write() must not be called with an exception set, otherwise the
2196
     * caller may think that write() was interrupted by a signal and the signal
2197
     * handler raised an exception. */
2198
240k
    assert(!PyErr_Occurred());
2199
2200
240k
    return _Py_write_impl(fd, buf, count, 1);
2201
240k
}
2202
2203
/* Write count bytes of buf into fd.
2204
 *
2205
 * On success, return the number of written bytes, it can be lower than count
2206
 * including 0. On error, set errno and return -1.
2207
 *
2208
 * When interrupted by a signal (write() fails with EINTR), retry the syscall
2209
 * without calling the Python signal handler. */
2210
Py_ssize_t
2211
_Py_write_noraise(int fd, const void *buf, size_t count)
2212
0
{
2213
0
    return _Py_write_impl(fd, buf, count, 0);
2214
0
}
2215
2216
#ifdef HAVE_READLINK
2217
2218
/* Read value of symbolic link. Encode the path to the locale encoding, decode
2219
   the result from the locale encoding.
2220
2221
   Return -1 on encoding error, on readlink() error, if the internal buffer is
2222
   too short, on decoding error, or if 'buf' is too short. */
2223
int
2224
_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t buflen)
2225
74
{
2226
74
    char *cpath;
2227
74
    char cbuf[MAXPATHLEN];
2228
74
    size_t cbuf_len = Py_ARRAY_LENGTH(cbuf);
2229
74
    wchar_t *wbuf;
2230
74
    Py_ssize_t res;
2231
74
    size_t r1;
2232
2233
74
    cpath = _Py_EncodeLocaleRaw(path, NULL);
2234
74
    if (cpath == NULL) {
2235
0
        errno = EINVAL;
2236
0
        return -1;
2237
0
    }
2238
74
    res = readlink(cpath, cbuf, cbuf_len);
2239
74
    PyMem_RawFree(cpath);
2240
74
    if (res == -1) {
2241
37
        return -1;
2242
37
    }
2243
37
    if ((size_t)res == cbuf_len) {
2244
0
        errno = EINVAL;
2245
0
        return -1;
2246
0
    }
2247
37
    cbuf[res] = '\0'; /* buf will be null terminated */
2248
37
    wbuf = Py_DecodeLocale(cbuf, &r1);
2249
37
    if (wbuf == NULL) {
2250
0
        errno = EINVAL;
2251
0
        return -1;
2252
0
    }
2253
    /* wbuf must have space to store the trailing NUL character */
2254
37
    if (buflen <= r1) {
2255
0
        PyMem_RawFree(wbuf);
2256
0
        errno = EINVAL;
2257
0
        return -1;
2258
0
    }
2259
37
    wcsncpy(buf, wbuf, buflen);
2260
37
    PyMem_RawFree(wbuf);
2261
37
    return (int)r1;
2262
37
}
2263
#endif
2264
2265
#ifdef HAVE_REALPATH
2266
2267
/* Return the canonicalized absolute pathname. Encode path to the locale
2268
   encoding, decode the result from the locale encoding.
2269
2270
   Return NULL on encoding error, realpath() error, decoding error
2271
   or if 'resolved_path' is too short. */
2272
wchar_t*
2273
_Py_wrealpath(const wchar_t *path,
2274
              wchar_t *resolved_path, size_t resolved_path_len)
2275
0
{
2276
0
    char *cpath;
2277
0
    wchar_t *wresolved_path;
2278
0
    char *res;
2279
0
    size_t r;
2280
0
    cpath = _Py_EncodeLocaleRaw(path, NULL);
2281
0
    if (cpath == NULL) {
2282
0
        errno = EINVAL;
2283
0
        return NULL;
2284
0
    }
2285
0
    res = realpath(cpath, NULL);
2286
0
    PyMem_RawFree(cpath);
2287
0
    if (res == NULL)
2288
0
        return NULL;
2289
2290
0
    wresolved_path = Py_DecodeLocale(res, &r);
2291
0
    free(res);
2292
2293
0
    if (wresolved_path == NULL) {
2294
0
        errno = EINVAL;
2295
0
        return NULL;
2296
0
    }
2297
    /* wresolved_path must have space to store the trailing NUL character */
2298
0
    if (resolved_path_len <= r) {
2299
0
        PyMem_RawFree(wresolved_path);
2300
0
        errno = EINVAL;
2301
0
        return NULL;
2302
0
    }
2303
0
    wcsncpy(resolved_path, wresolved_path, resolved_path_len);
2304
0
    PyMem_RawFree(wresolved_path);
2305
0
    return resolved_path;
2306
0
}
2307
#endif
2308
2309
2310
int
2311
_Py_isabs(const wchar_t *path)
2312
629
{
2313
#ifdef MS_WINDOWS
2314
    const wchar_t *tail;
2315
    HRESULT hr = PathCchSkipRoot(path, &tail);
2316
    if (FAILED(hr) || path == tail) {
2317
        return 0;
2318
    }
2319
    if (tail == &path[1] && (path[0] == SEP || path[0] == ALTSEP)) {
2320
        // Exclude paths with leading SEP
2321
        return 0;
2322
    }
2323
    if (tail == &path[2] && path[1] == L':') {
2324
        // Exclude drive-relative paths (e.g. C:filename.ext)
2325
        return 0;
2326
    }
2327
    return 1;
2328
#else
2329
629
    return (path[0] == SEP);
2330
629
#endif
2331
629
}
2332
2333
2334
/* Get an absolute path.
2335
   On error (ex: fail to get the current directory), return -1.
2336
   On memory allocation failure, set *abspath_p to NULL and return 0.
2337
   On success, return a newly allocated to *abspath_p to and return 0.
2338
   The string must be freed by PyMem_RawFree(). */
2339
int
2340
_Py_abspath(const wchar_t *path, wchar_t **abspath_p)
2341
0
{
2342
0
    if (path[0] == '\0' || !wcscmp(path, L".")) {
2343
0
        wchar_t cwd[MAXPATHLEN + 1];
2344
0
        cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0;
2345
0
        if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) {
2346
            /* unable to get the current directory */
2347
0
            return -1;
2348
0
        }
2349
0
        *abspath_p = _PyMem_RawWcsdup(cwd);
2350
0
        return 0;
2351
0
    }
2352
2353
0
    if (_Py_isabs(path)) {
2354
0
        *abspath_p = _PyMem_RawWcsdup(path);
2355
0
        return 0;
2356
0
    }
2357
2358
#ifdef MS_WINDOWS
2359
    return _PyOS_getfullpathname(path, abspath_p);
2360
#else
2361
0
    wchar_t cwd[MAXPATHLEN + 1];
2362
0
    cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0;
2363
0
    if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) {
2364
        /* unable to get the current directory */
2365
0
        return -1;
2366
0
    }
2367
2368
0
    size_t cwd_len = wcslen(cwd);
2369
0
    size_t path_len = wcslen(path);
2370
0
    size_t len = cwd_len + 1 + path_len + 1;
2371
0
    if (len <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
2372
0
        *abspath_p = PyMem_RawMalloc(len * sizeof(wchar_t));
2373
0
    }
2374
0
    else {
2375
0
        *abspath_p = NULL;
2376
0
    }
2377
0
    if (*abspath_p == NULL) {
2378
0
        return 0;
2379
0
    }
2380
2381
0
    wchar_t *abspath = *abspath_p;
2382
0
    memcpy(abspath, cwd, cwd_len * sizeof(wchar_t));
2383
0
    abspath += cwd_len;
2384
2385
0
    *abspath = (wchar_t)SEP;
2386
0
    abspath++;
2387
2388
0
    memcpy(abspath, path, path_len * sizeof(wchar_t));
2389
0
    abspath += path_len;
2390
2391
0
    *abspath = 0;
2392
0
    return 0;
2393
0
#endif
2394
0
}
2395
2396
// The Windows Games API family implements the PathCch* APIs in the Xbox OS,
2397
// but does not expose them yet. Load them dynamically until
2398
// 1) they are officially exposed
2399
// 2) we stop supporting older versions of the GDK which do not expose them
2400
#if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)
2401
HRESULT
2402
PathCchSkipRoot(const wchar_t *path, const wchar_t **rootEnd)
2403
{
2404
    static int initialized = 0;
2405
    typedef HRESULT(__stdcall *PPathCchSkipRoot) (PCWSTR pszPath,
2406
                                                  PCWSTR *ppszRootEnd);
2407
    static PPathCchSkipRoot _PathCchSkipRoot;
2408
2409
    if (initialized == 0) {
2410
        HMODULE pathapi = LoadLibraryExW(L"api-ms-win-core-path-l1-1-0.dll", NULL,
2411
                                         LOAD_LIBRARY_SEARCH_SYSTEM32);
2412
        if (pathapi) {
2413
            _PathCchSkipRoot = (PPathCchSkipRoot)GetProcAddress(
2414
                pathapi, "PathCchSkipRoot");
2415
        }
2416
        else {
2417
            _PathCchSkipRoot = NULL;
2418
        }
2419
        initialized = 1;
2420
    }
2421
2422
    if (!_PathCchSkipRoot) {
2423
        return E_NOINTERFACE;
2424
    }
2425
2426
    return _PathCchSkipRoot(path, rootEnd);
2427
}
2428
2429
static HRESULT
2430
PathCchCombineEx(wchar_t *buffer, size_t bufsize, const wchar_t *dirname,
2431
                 const wchar_t *relfile, unsigned long flags)
2432
{
2433
    static int initialized = 0;
2434
    typedef HRESULT(__stdcall *PPathCchCombineEx) (PWSTR pszPathOut,
2435
                                                   size_t cchPathOut,
2436
                                                   PCWSTR pszPathIn,
2437
                                                   PCWSTR pszMore,
2438
                                                   unsigned long dwFlags);
2439
    static PPathCchCombineEx _PathCchCombineEx;
2440
2441
    if (initialized == 0) {
2442
        HMODULE pathapi = LoadLibraryExW(L"api-ms-win-core-path-l1-1-0.dll", NULL,
2443
                                         LOAD_LIBRARY_SEARCH_SYSTEM32);
2444
        if (pathapi) {
2445
            _PathCchCombineEx = (PPathCchCombineEx)GetProcAddress(
2446
                pathapi, "PathCchCombineEx");
2447
        }
2448
        else {
2449
            _PathCchCombineEx = NULL;
2450
        }
2451
        initialized = 1;
2452
    }
2453
2454
    if (!_PathCchCombineEx) {
2455
        return E_NOINTERFACE;
2456
    }
2457
2458
    return _PathCchCombineEx(buffer, bufsize, dirname, relfile, flags);
2459
}
2460
2461
#endif /* defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP) */
2462
2463
void
2464
_Py_skiproot(const wchar_t *path, Py_ssize_t size, Py_ssize_t *drvsize,
2465
             Py_ssize_t *rootsize)
2466
160k
{
2467
160k
    assert(drvsize);
2468
160k
    assert(rootsize);
2469
160k
#ifndef MS_WINDOWS
2470
262k
#define IS_SEP(x) (*(x) == SEP)
2471
160k
    *drvsize = 0;
2472
160k
    if (!IS_SEP(&path[0])) {
2473
        // Relative path, e.g.: 'foo'
2474
108k
        *rootsize = 0;
2475
108k
    }
2476
51.0k
    else if (!IS_SEP(&path[1]) || IS_SEP(&path[2])) {
2477
        // Absolute path, e.g.: '/foo', '///foo', '////foo', etc.
2478
51.0k
        *rootsize = 1;
2479
51.0k
    }
2480
61
    else {
2481
        // Precisely two leading slashes, e.g.: '//foo'. Implementation defined per POSIX, see
2482
        // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
2483
61
        *rootsize = 2;
2484
61
    }
2485
160k
#undef IS_SEP
2486
#else
2487
    const wchar_t *pEnd = size >= 0 ? &path[size] : NULL;
2488
#define IS_END(x) (pEnd ? (x) == pEnd : !*(x))
2489
#define IS_SEP(x) (*(x) == SEP || *(x) == ALTSEP)
2490
#define SEP_OR_END(x) (IS_SEP(x) || IS_END(x))
2491
    if (IS_SEP(&path[0])) {
2492
        if (IS_SEP(&path[1])) {
2493
            // Device drives, e.g. \\.\device or \\?\device
2494
            // UNC drives, e.g. \\server\share or \\?\UNC\server\share
2495
            Py_ssize_t idx;
2496
            if (path[2] == L'?' && IS_SEP(&path[3]) &&
2497
                (path[4] == L'U' || path[4] == L'u') &&
2498
                (path[5] == L'N' || path[5] == L'n') &&
2499
                (path[6] == L'C' || path[6] == L'c') &&
2500
                IS_SEP(&path[7]))
2501
            {
2502
                idx = 8;
2503
            }
2504
            else {
2505
                idx = 2;
2506
            }
2507
            while (!SEP_OR_END(&path[idx])) {
2508
                idx++;
2509
            }
2510
            if (IS_END(&path[idx])) {
2511
                *drvsize = idx;
2512
                *rootsize = 0;
2513
            }
2514
            else {
2515
                idx++;
2516
                while (!SEP_OR_END(&path[idx])) {
2517
                    idx++;
2518
                }
2519
                *drvsize = idx;
2520
                if (IS_END(&path[idx])) {
2521
                    *rootsize = 0;
2522
                }
2523
                else {
2524
                    *rootsize = 1;
2525
                }
2526
            }
2527
        }
2528
        else {
2529
            // Relative path with root, e.g. \Windows
2530
            *drvsize = 0;
2531
            *rootsize = 1;
2532
        }
2533
    }
2534
    else if (!IS_END(&path[0]) && path[1] == L':') {
2535
        *drvsize = 2;
2536
        if (IS_SEP(&path[2])) {
2537
            // Absolute drive-letter path, e.g. X:\Windows
2538
            *rootsize = 1;
2539
        }
2540
        else {
2541
            // Relative path with drive, e.g. X:Windows
2542
            *rootsize = 0;
2543
        }
2544
    }
2545
    else {
2546
        // Relative path, e.g. Windows
2547
        *drvsize = 0;
2548
        *rootsize = 0;
2549
    }
2550
#undef SEP_OR_END
2551
#undef IS_SEP
2552
#undef IS_END
2553
#endif
2554
160k
}
2555
2556
// The caller must ensure "buffer" is big enough.
2557
static int
2558
join_relfile(wchar_t *buffer, size_t bufsize,
2559
             const wchar_t *dirname, const wchar_t *relfile)
2560
296
{
2561
#ifdef MS_WINDOWS
2562
    if (FAILED(PathCchCombineEx(buffer, bufsize, dirname, relfile,
2563
        PATHCCH_ALLOW_LONG_PATHS))) {
2564
        return -1;
2565
    }
2566
#else
2567
296
    assert(!_Py_isabs(relfile));
2568
296
    size_t dirlen = wcslen(dirname);
2569
296
    size_t rellen = wcslen(relfile);
2570
296
    size_t maxlen = bufsize - 1;
2571
296
    if (maxlen > MAXPATHLEN || dirlen >= maxlen || rellen >= maxlen - dirlen) {
2572
0
        return -1;
2573
0
    }
2574
296
    if (dirlen == 0) {
2575
        // We do not add a leading separator.
2576
0
        wcscpy(buffer, relfile);
2577
0
    }
2578
296
    else {
2579
296
        if (dirname != buffer) {
2580
0
            wcscpy(buffer, dirname);
2581
0
        }
2582
296
        size_t relstart = dirlen;
2583
296
        if (dirlen > 1 && dirname[dirlen - 1] != SEP) {
2584
296
            buffer[dirlen] = SEP;
2585
296
            relstart += 1;
2586
296
        }
2587
296
        wcscpy(&buffer[relstart], relfile);
2588
296
    }
2589
296
#endif
2590
296
    return 0;
2591
296
}
2592
2593
/* Join the two paths together, like os.path.join().  Return NULL
2594
   if memory could not be allocated.  The caller is responsible
2595
   for calling PyMem_RawFree() on the result. */
2596
wchar_t *
2597
_Py_join_relfile(const wchar_t *dirname, const wchar_t *relfile)
2598
0
{
2599
0
    assert(dirname != NULL && relfile != NULL);
2600
0
#ifndef MS_WINDOWS
2601
0
    assert(!_Py_isabs(relfile));
2602
0
#endif
2603
0
    size_t maxlen = wcslen(dirname) + 1 + wcslen(relfile);
2604
0
    size_t bufsize = maxlen + 1;
2605
0
    wchar_t *filename = PyMem_RawMalloc(bufsize * sizeof(wchar_t));
2606
0
    if (filename == NULL) {
2607
0
        return NULL;
2608
0
    }
2609
0
    assert(wcslen(dirname) < MAXPATHLEN);
2610
0
    assert(wcslen(relfile) < MAXPATHLEN - wcslen(dirname));
2611
0
    if (join_relfile(filename, bufsize, dirname, relfile) < 0) {
2612
0
        PyMem_RawFree(filename);
2613
0
        return NULL;
2614
0
    }
2615
0
    return filename;
2616
0
}
2617
2618
/* Join the two paths together, like os.path.join().
2619
     dirname: the target buffer with the dirname already in place,
2620
              including trailing NUL
2621
     relfile: this must be a relative path
2622
     bufsize: total allocated size of the buffer
2623
   Return -1 if anything is wrong with the path lengths. */
2624
int
2625
_Py_add_relfile(wchar_t *dirname, const wchar_t *relfile, size_t bufsize)
2626
296
{
2627
296
    assert(dirname != NULL && relfile != NULL);
2628
296
    assert(bufsize > 0);
2629
296
    return join_relfile(dirname, bufsize, dirname, relfile);
2630
296
}
2631
2632
2633
size_t
2634
_Py_find_basename(const wchar_t *filename)
2635
0
{
2636
0
    for (size_t i = wcslen(filename); i > 0; --i) {
2637
0
        if (filename[i] == SEP) {
2638
0
            return i + 1;
2639
0
        }
2640
0
    }
2641
0
    return 0;
2642
0
}
2643
2644
/* In-place path normalisation. Returns the start of the normalized
2645
   path, which will be within the original buffer. Guaranteed to not
2646
   make the path longer, and will not fail. 'size' is the length of
2647
   the path, if known. If -1, the first null character will be assumed
2648
   to be the end of the path. 'normsize' will be set to contain the
2649
   length of the resulting normalized path. */
2650
wchar_t *
2651
_Py_normpath_and_size(wchar_t *path, Py_ssize_t size, Py_ssize_t *normsize)
2652
27.1k
{
2653
27.1k
    assert(path != NULL);
2654
27.1k
    if ((size < 0 && !path[0]) || size == 0) {
2655
0
        *normsize = 0;
2656
0
        return path;
2657
0
    }
2658
27.1k
    wchar_t *pEnd = size >= 0 ? &path[size] : NULL;
2659
27.1k
    wchar_t *p1 = path;     // sequentially scanned address in the path
2660
27.1k
    wchar_t *p2 = path;     // destination of a scanned character to be ljusted
2661
27.1k
    wchar_t *minP2 = path;  // the beginning of the destination range
2662
27.1k
    wchar_t lastC = L'\0';  // the last ljusted character, p2[-1] in most cases
2663
2664
1.94M
#define IS_END(x) (pEnd ? (x) == pEnd : !*(x))
2665
#ifdef ALTSEP
2666
#define IS_SEP(x) (*(x) == SEP || *(x) == ALTSEP)
2667
#else
2668
27.1k
#define IS_SEP(x) (*(x) == SEP)
2669
27.1k
#endif
2670
27.1k
#define SEP_OR_END(x) (IS_SEP(x) || IS_END(x))
2671
2672
27.1k
    Py_ssize_t drvsize, rootsize;
2673
27.1k
    _Py_skiproot(path, size, &drvsize, &rootsize);
2674
27.1k
    if (drvsize || rootsize) {
2675
        // Skip past root and update minP2
2676
27.1k
        p1 = &path[drvsize + rootsize];
2677
27.1k
#ifndef ALTSEP
2678
27.1k
        p2 = p1;
2679
#else
2680
        for (; p2 < p1; ++p2) {
2681
            if (*p2 == ALTSEP) {
2682
                *p2 = SEP;
2683
            }
2684
        }
2685
#endif
2686
27.1k
        minP2 = p2 - 1;
2687
27.1k
        lastC = *minP2;
2688
#ifdef MS_WINDOWS
2689
        if (lastC != SEP) {
2690
            minP2++;
2691
        }
2692
#endif
2693
27.1k
    }
2694
27.1k
    if (p1[0] == L'.' && SEP_OR_END(&p1[1])) {
2695
        // Skip leading '.\'
2696
0
        lastC = *++p1;
2697
#ifdef ALTSEP
2698
        if (lastC == ALTSEP) {
2699
            lastC = SEP;
2700
        }
2701
#endif
2702
0
        while (IS_SEP(p1)) {
2703
0
            p1++;
2704
0
        }
2705
0
    }
2706
2707
    /* if pEnd is specified, check that. Else, check for null terminator */
2708
1.94M
    for (; !IS_END(p1); ++p1) {
2709
1.92M
        wchar_t c = *p1;
2710
#ifdef ALTSEP
2711
        if (c == ALTSEP) {
2712
            c = SEP;
2713
        }
2714
#endif
2715
1.92M
        if (lastC == SEP) {
2716
257k
            if (c == L'.') {
2717
1.25k
                int sep_at_1 = SEP_OR_END(&p1[1]);
2718
1.25k
                int sep_at_2 = !sep_at_1 && SEP_OR_END(&p1[2]);
2719
1.25k
                if (sep_at_2 && p1[1] == L'.') {
2720
0
                    wchar_t *p3 = p2;
2721
0
                    while (p3 != minP2 && *--p3 == SEP) { }
2722
0
                    while (p3 != minP2 && *(p3 - 1) != SEP) { --p3; }
2723
0
                    if (p2 == minP2
2724
0
                        || (p3[0] == L'.' && p3[1] == L'.' && IS_SEP(&p3[2])))
2725
0
                    {
2726
                        // Previous segment is also ../, so append instead.
2727
                        // Relative path does not absorb ../ at minP2 as well.
2728
0
                        *p2++ = L'.';
2729
0
                        *p2++ = L'.';
2730
0
                        lastC = L'.';
2731
0
                    } else if (p3[0] == SEP) {
2732
                        // Absolute path, so absorb segment
2733
0
                        p2 = p3 + 1;
2734
0
                    } else {
2735
0
                        p2 = p3;
2736
0
                    }
2737
0
                    p1 += 1;
2738
1.25k
                } else if (sep_at_1) {
2739
1.25k
                } else {
2740
1.25k
                    *p2++ = lastC = c;
2741
1.25k
                }
2742
256k
            } else if (c == SEP) {
2743
256k
            } else {
2744
256k
                *p2++ = lastC = c;
2745
256k
            }
2746
1.66M
        } else {
2747
1.66M
            *p2++ = lastC = c;
2748
1.66M
        }
2749
1.92M
    }
2750
27.1k
    *p2 = L'\0';
2751
27.1k
    if (p2 != minP2) {
2752
27.1k
        while (--p2 != minP2 && *p2 == SEP) {
2753
47
            *p2 = L'\0';
2754
47
        }
2755
27.1k
    } else {
2756
0
        --p2;
2757
0
    }
2758
27.1k
    *normsize = p2 - path + 1;
2759
27.1k
#undef SEP_OR_END
2760
27.1k
#undef IS_SEP
2761
27.1k
#undef IS_END
2762
27.1k
    return path;
2763
27.1k
}
2764
2765
/* In-place path normalisation. Returns the start of the normalized
2766
   path, which will be within the original buffer. Guaranteed to not
2767
   make the path longer, and will not fail. 'size' is the length of
2768
   the path, if known. If -1, the first null character will be assumed
2769
   to be the end of the path. */
2770
wchar_t *
2771
_Py_normpath(wchar_t *path, Py_ssize_t size)
2772
296
{
2773
296
    Py_ssize_t norm_length;
2774
296
    return _Py_normpath_and_size(path, size, &norm_length);
2775
296
}
2776
2777
2778
/* Get the current directory. buflen is the buffer size in wide characters
2779
   including the null character. Decode the path from the locale encoding.
2780
2781
   Return NULL on getcwd() error, on decoding error, or if 'buf' is
2782
   too short. */
2783
wchar_t*
2784
_Py_wgetcwd(wchar_t *buf, size_t buflen)
2785
0
{
2786
#ifdef MS_WINDOWS
2787
    int ibuflen = (int)Py_MIN(buflen, INT_MAX);
2788
    return _wgetcwd(buf, ibuflen);
2789
#else
2790
0
    char fname[MAXPATHLEN];
2791
0
    wchar_t *wname;
2792
0
    size_t len;
2793
2794
0
    if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL)
2795
0
        return NULL;
2796
0
    wname = Py_DecodeLocale(fname, &len);
2797
0
    if (wname == NULL)
2798
0
        return NULL;
2799
    /* wname must have space to store the trailing NUL character */
2800
0
    if (buflen <= len) {
2801
0
        PyMem_RawFree(wname);
2802
0
        return NULL;
2803
0
    }
2804
0
    wcsncpy(buf, wname, buflen);
2805
0
    PyMem_RawFree(wname);
2806
0
    return buf;
2807
0
#endif
2808
0
}
2809
2810
/* Duplicate a file descriptor. The new file descriptor is created as
2811
   non-inheritable. Return a new file descriptor on success, raise an OSError
2812
   exception and return -1 on error.
2813
2814
   The GIL is released to call dup(). The caller must hold the GIL. */
2815
int
2816
_Py_dup(int fd)
2817
91.0k
{
2818
#ifdef MS_WINDOWS
2819
    HANDLE handle;
2820
#endif
2821
2822
91.0k
    _Py_AssertHoldsTstate();
2823
2824
#ifdef MS_WINDOWS
2825
    handle = _Py_get_osfhandle(fd);
2826
    if (handle == INVALID_HANDLE_VALUE)
2827
        return -1;
2828
2829
    Py_BEGIN_ALLOW_THREADS
2830
    _Py_BEGIN_SUPPRESS_IPH
2831
    fd = dup(fd);
2832
    _Py_END_SUPPRESS_IPH
2833
    Py_END_ALLOW_THREADS
2834
    if (fd < 0) {
2835
        PyErr_SetFromErrno(PyExc_OSError);
2836
        return -1;
2837
    }
2838
2839
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
2840
        _Py_BEGIN_SUPPRESS_IPH
2841
        close(fd);
2842
        _Py_END_SUPPRESS_IPH
2843
        return -1;
2844
    }
2845
#elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC)
2846
91.0k
    Py_BEGIN_ALLOW_THREADS
2847
91.0k
    _Py_BEGIN_SUPPRESS_IPH
2848
91.0k
    fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
2849
91.0k
    _Py_END_SUPPRESS_IPH
2850
91.0k
    Py_END_ALLOW_THREADS
2851
91.0k
    if (fd < 0) {
2852
0
        PyErr_SetFromErrno(PyExc_OSError);
2853
0
        return -1;
2854
0
    }
2855
2856
#elif HAVE_DUP
2857
    Py_BEGIN_ALLOW_THREADS
2858
    _Py_BEGIN_SUPPRESS_IPH
2859
    fd = dup(fd);
2860
    _Py_END_SUPPRESS_IPH
2861
    Py_END_ALLOW_THREADS
2862
    if (fd < 0) {
2863
        PyErr_SetFromErrno(PyExc_OSError);
2864
        return -1;
2865
    }
2866
2867
    if (_Py_set_inheritable(fd, 0, NULL) < 0) {
2868
        _Py_BEGIN_SUPPRESS_IPH
2869
        close(fd);
2870
        _Py_END_SUPPRESS_IPH
2871
        return -1;
2872
    }
2873
#else
2874
    errno = ENOTSUP;
2875
    PyErr_SetFromErrno(PyExc_OSError);
2876
    return -1;
2877
#endif
2878
91.0k
    return fd;
2879
91.0k
}
2880
2881
#ifndef MS_WINDOWS
2882
/* Get the blocking mode of the file descriptor.
2883
   Return 0 if the O_NONBLOCK flag is set, 1 if the flag is cleared,
2884
   raise an exception and return -1 on error. */
2885
int
2886
_Py_get_blocking(int fd)
2887
0
{
2888
0
    int flags;
2889
0
    _Py_BEGIN_SUPPRESS_IPH
2890
0
    flags = fcntl(fd, F_GETFL, 0);
2891
0
    _Py_END_SUPPRESS_IPH
2892
0
    if (flags < 0) {
2893
0
        PyErr_SetFromErrno(PyExc_OSError);
2894
0
        return -1;
2895
0
    }
2896
2897
0
    return !(flags & O_NONBLOCK);
2898
0
}
2899
2900
/* Set the blocking mode of the specified file descriptor.
2901
2902
   Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag
2903
   otherwise.
2904
2905
   Return 0 on success, raise an exception and return -1 on error. */
2906
int
2907
_Py_set_blocking(int fd, int blocking)
2908
0
{
2909
/* bpo-41462: On VxWorks, ioctl(FIONBIO) only works on sockets.
2910
   Use fcntl() instead. */
2911
0
#if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO) && !defined(__VXWORKS__)
2912
0
    int arg = !blocking;
2913
0
    if (ioctl(fd, FIONBIO, &arg) < 0)
2914
0
        goto error;
2915
#else
2916
    int flags, res;
2917
2918
    _Py_BEGIN_SUPPRESS_IPH
2919
    flags = fcntl(fd, F_GETFL, 0);
2920
    if (flags >= 0) {
2921
        if (blocking)
2922
            flags = flags & (~O_NONBLOCK);
2923
        else
2924
            flags = flags | O_NONBLOCK;
2925
2926
        res = fcntl(fd, F_SETFL, flags);
2927
    } else {
2928
        res = -1;
2929
    }
2930
    _Py_END_SUPPRESS_IPH
2931
2932
    if (res < 0)
2933
        goto error;
2934
#endif
2935
0
    return 0;
2936
2937
0
error:
2938
0
    PyErr_SetFromErrno(PyExc_OSError);
2939
0
    return -1;
2940
0
}
2941
#else   /* MS_WINDOWS */
2942
2943
// The Windows Games API family doesn't expose GetNamedPipeHandleStateW so attempt
2944
// to load it directly from the Kernel32.dll
2945
#if !defined(MS_WINDOWS_APP) && !defined(MS_WINDOWS_SYSTEM)
2946
BOOL
2947
GetNamedPipeHandleStateW(HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount,
2948
                         LPDWORD lpCollectDataTimeout, LPWSTR lpUserName, DWORD nMaxUserNameSize)
2949
{
2950
    static int initialized = 0;
2951
    typedef BOOL(__stdcall* PGetNamedPipeHandleStateW) (
2952
        HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount,
2953
        LPDWORD lpCollectDataTimeout, LPWSTR lpUserName, DWORD nMaxUserNameSize);
2954
    static PGetNamedPipeHandleStateW _GetNamedPipeHandleStateW;
2955
2956
    if (initialized == 0) {
2957
        HMODULE api = LoadLibraryExW(L"Kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
2958
        if (api) {
2959
            _GetNamedPipeHandleStateW = (PGetNamedPipeHandleStateW)GetProcAddress(
2960
                api, "GetNamedPipeHandleStateW");
2961
        }
2962
        else {
2963
            _GetNamedPipeHandleStateW = NULL;
2964
        }
2965
        initialized = 1;
2966
    }
2967
2968
    if (!_GetNamedPipeHandleStateW) {
2969
        SetLastError(E_NOINTERFACE);
2970
        return FALSE;
2971
    }
2972
2973
    return _GetNamedPipeHandleStateW(
2974
        hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, lpUserName, nMaxUserNameSize
2975
    );
2976
}
2977
#endif /* !MS_WINDOWS_APP && !MS_WINDOWS_SYSTEM */
2978
2979
int
2980
_Py_get_blocking(int fd)
2981
{
2982
    HANDLE handle;
2983
    DWORD mode;
2984
    BOOL success;
2985
2986
    handle = _Py_get_osfhandle(fd);
2987
    if (handle == INVALID_HANDLE_VALUE) {
2988
        return -1;
2989
    }
2990
2991
    Py_BEGIN_ALLOW_THREADS
2992
    success = GetNamedPipeHandleStateW(handle, &mode,
2993
                                       NULL, NULL, NULL, NULL, 0);
2994
    Py_END_ALLOW_THREADS
2995
2996
    if (!success) {
2997
        PyErr_SetFromWindowsErr(0);
2998
        return -1;
2999
    }
3000
3001
    return !(mode & PIPE_NOWAIT);
3002
}
3003
3004
int
3005
_Py_set_blocking(int fd, int blocking)
3006
{
3007
    HANDLE handle;
3008
    DWORD mode;
3009
    BOOL success;
3010
3011
    handle = _Py_get_osfhandle(fd);
3012
    if (handle == INVALID_HANDLE_VALUE) {
3013
        return -1;
3014
    }
3015
3016
    Py_BEGIN_ALLOW_THREADS
3017
    success = GetNamedPipeHandleStateW(handle, &mode,
3018
                                       NULL, NULL, NULL, NULL, 0);
3019
    if (success) {
3020
        if (blocking) {
3021
            mode &= ~PIPE_NOWAIT;
3022
        }
3023
        else {
3024
            mode |= PIPE_NOWAIT;
3025
        }
3026
        success = SetNamedPipeHandleState(handle, &mode, NULL, NULL);
3027
    }
3028
    Py_END_ALLOW_THREADS
3029
3030
    if (!success) {
3031
        PyErr_SetFromWindowsErr(0);
3032
        return -1;
3033
    }
3034
    return 0;
3035
}
3036
3037
void*
3038
_Py_get_osfhandle_noraise(int fd)
3039
{
3040
    void *handle;
3041
    _Py_BEGIN_SUPPRESS_IPH
3042
    handle = (void*)_get_osfhandle(fd);
3043
    _Py_END_SUPPRESS_IPH
3044
    return handle;
3045
}
3046
3047
void*
3048
_Py_get_osfhandle(int fd)
3049
{
3050
    void *handle = _Py_get_osfhandle_noraise(fd);
3051
    if (handle == INVALID_HANDLE_VALUE)
3052
        PyErr_SetFromErrno(PyExc_OSError);
3053
3054
    return handle;
3055
}
3056
3057
int
3058
_Py_open_osfhandle_noraise(void *handle, int flags)
3059
{
3060
    int fd;
3061
    _Py_BEGIN_SUPPRESS_IPH
3062
    fd = _open_osfhandle((intptr_t)handle, flags);
3063
    _Py_END_SUPPRESS_IPH
3064
    return fd;
3065
}
3066
3067
int
3068
_Py_open_osfhandle(void *handle, int flags)
3069
{
3070
    int fd = _Py_open_osfhandle_noraise(handle, flags);
3071
    if (fd == -1)
3072
        PyErr_SetFromErrno(PyExc_OSError);
3073
3074
    return fd;
3075
}
3076
#endif  /* MS_WINDOWS */
3077
3078
int
3079
_Py_GetLocaleconvNumeric(struct lconv *lc,
3080
                         PyObject **decimal_point, PyObject **thousands_sep)
3081
0
{
3082
0
    assert(decimal_point != NULL);
3083
0
    assert(thousands_sep != NULL);
3084
3085
0
#ifndef MS_WINDOWS
3086
0
    int change_locale = 0;
3087
0
    if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {
3088
0
        change_locale = 1;
3089
0
    }
3090
0
    if ((strlen(lc->thousands_sep) > 1 || ((unsigned char)lc->thousands_sep[0]) > 127)) {
3091
0
        change_locale = 1;
3092
0
    }
3093
3094
    /* Keep a copy of the LC_CTYPE locale */
3095
0
    char *oldloc = NULL, *loc = NULL;
3096
0
    if (change_locale) {
3097
0
        oldloc = setlocale(LC_CTYPE, NULL);
3098
0
        if (!oldloc) {
3099
0
            PyErr_SetString(PyExc_RuntimeWarning,
3100
0
                            "failed to get LC_CTYPE locale");
3101
0
            return -1;
3102
0
        }
3103
3104
0
        oldloc = _PyMem_Strdup(oldloc);
3105
0
        if (!oldloc) {
3106
0
            PyErr_NoMemory();
3107
0
            return -1;
3108
0
        }
3109
3110
0
        loc = setlocale(LC_NUMERIC, NULL);
3111
0
        if (loc != NULL && strcmp(loc, oldloc) == 0) {
3112
0
            loc = NULL;
3113
0
        }
3114
3115
0
        if (loc != NULL) {
3116
            /* Only set the locale temporarily the LC_CTYPE locale
3117
               if LC_NUMERIC locale is different than LC_CTYPE locale and
3118
               decimal_point and/or thousands_sep are non-ASCII or longer than
3119
               1 byte */
3120
0
            setlocale(LC_CTYPE, loc);
3121
0
        }
3122
0
    }
3123
3124
0
#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
3125
#else /* MS_WINDOWS */
3126
/* Use _W_* fields of Windows strcut lconv */
3127
#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
3128
#endif /* MS_WINDOWS */
3129
3130
0
    int res = -1;
3131
3132
0
    *decimal_point = GET_LOCALE_STRING(decimal_point);
3133
0
    if (*decimal_point == NULL) {
3134
0
        goto done;
3135
0
    }
3136
3137
0
    *thousands_sep = GET_LOCALE_STRING(thousands_sep);
3138
0
    if (*thousands_sep == NULL) {
3139
0
        goto done;
3140
0
    }
3141
3142
0
    res = 0;
3143
3144
0
done:
3145
0
#ifndef MS_WINDOWS
3146
0
    if (loc != NULL) {
3147
0
        setlocale(LC_CTYPE, oldloc);
3148
0
    }
3149
0
    PyMem_Free(oldloc);
3150
0
#endif
3151
0
    return res;
3152
3153
0
#undef GET_LOCALE_STRING
3154
0
}
3155
3156
/* Our selection logic for which function to use is as follows:
3157
 * 1. If close_range(2) is available, always prefer that; it's better for
3158
 *    contiguous ranges like this than fdwalk(3) which entails iterating over
3159
 *    the entire fd space and simply doing nothing for those outside the range.
3160
 * 2. If closefrom(2) is available, we'll attempt to use that next if we're
3161
 *    closing up to sysconf(_SC_OPEN_MAX).
3162
 * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
3163
 *    as that will be more performant if the range happens to have any chunk of
3164
 *    non-opened fd in the middle.
3165
 * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
3166
 */
3167
#ifdef HAVE_CLOSEFROM
3168
#  define USE_CLOSEFROM
3169
#endif /* HAVE_CLOSEFROM */
3170
3171
#ifdef HAVE_FDWALK
3172
#  define USE_FDWALK
3173
#endif /* HAVE_FDWALK */
3174
3175
#ifdef USE_FDWALK
3176
static int
3177
_fdwalk_close_func(void *lohi, int fd)
3178
{
3179
    int lo = ((int *)lohi)[0];
3180
    int hi = ((int *)lohi)[1];
3181
3182
    if (fd >= hi) {
3183
        return 1;
3184
    }
3185
    else if (fd >= lo) {
3186
        /* Ignore errors */
3187
        (void)close(fd);
3188
    }
3189
    return 0;
3190
}
3191
#endif /* USE_FDWALK */
3192
3193
/* Closes all file descriptors in [first, last], ignoring errors. */
3194
void
3195
_Py_closerange(int first, int last)
3196
0
{
3197
0
    first = Py_MAX(first, 0);
3198
0
    _Py_BEGIN_SUPPRESS_IPH
3199
#ifdef HAVE_CLOSE_RANGE
3200
    if (close_range(first, last, 0) == 0) {
3201
        /* close_range() ignores errors when it closes file descriptors.
3202
         * Possible reasons of an error return are lack of kernel support
3203
         * or denial of the underlying syscall by a seccomp sandbox on Linux.
3204
         * Fallback to other methods in case of any error. */
3205
    }
3206
    else
3207
#endif /* HAVE_CLOSE_RANGE */
3208
#ifdef USE_CLOSEFROM
3209
    if (last >= sysconf(_SC_OPEN_MAX)) {
3210
        /* Any errors encountered while closing file descriptors are ignored */
3211
        (void)closefrom(first);
3212
    }
3213
    else
3214
#endif /* USE_CLOSEFROM */
3215
#ifdef USE_FDWALK
3216
    {
3217
        int lohi[2];
3218
        lohi[0] = first;
3219
        lohi[1] = last + 1;
3220
        fdwalk(_fdwalk_close_func, lohi);
3221
    }
3222
#else
3223
0
    {
3224
0
        for (int i = first; i <= last; i++) {
3225
            /* Ignore errors */
3226
0
            (void)close(i);
3227
0
        }
3228
0
    }
3229
0
#endif /* USE_FDWALK */
3230
0
    _Py_END_SUPPRESS_IPH
3231
0
}
3232
3233
3234
#ifndef MS_WINDOWS
3235
// Ticks per second used by clock() and times() functions.
3236
// See os.times() and time.process_time() implementations.
3237
int
3238
_Py_GetTicksPerSecond(long *ticks_per_second)
3239
74
{
3240
74
#if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
3241
74
    long value = sysconf(_SC_CLK_TCK);
3242
74
    if (value < 1) {
3243
0
        return -1;
3244
0
    }
3245
74
    *ticks_per_second = value;
3246
#elif defined(HZ)
3247
    assert(HZ >= 1);
3248
    *ticks_per_second = HZ;
3249
#else
3250
    // Magic fallback value; may be bogus
3251
    *ticks_per_second = 60;
3252
#endif
3253
74
    return 0;
3254
74
}
3255
#endif
3256
3257
3258
/* Check if a file descriptor is valid or not.
3259
   Return 0 if the file descriptor is invalid, return non-zero otherwise. */
3260
int
3261
_Py_IsValidFD(int fd)
3262
111
{
3263
/* dup() is faster than fstat(): fstat() can require input/output operations,
3264
   whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python
3265
   startup. Problem: dup() doesn't check if the file descriptor is valid on
3266
   some platforms.
3267
3268
   fcntl(fd, F_GETFD) is even faster, because it only checks the process table.
3269
   It is preferred over dup() when available, since it cannot fail with the
3270
   "too many open files" error (EMFILE).
3271
3272
   bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other
3273
   side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with
3274
   EBADF. FreeBSD has similar issue (bpo-32849).
3275
3276
   Only use dup() on Linux where dup() is enough to detect invalid FD
3277
   (bpo-32849).
3278
*/
3279
111
    if (fd < 0) {
3280
0
        return 0;
3281
0
    }
3282
111
#if defined(F_GETFD) && ( \
3283
111
        defined(__linux__) || \
3284
111
        defined(__APPLE__) || \
3285
111
        (defined(__wasm__) && !defined(__wasi__)))
3286
111
    return fcntl(fd, F_GETFD) >= 0;
3287
#elif defined(__linux__)
3288
    int fd2 = dup(fd);
3289
    if (fd2 >= 0) {
3290
        close(fd2);
3291
    }
3292
    return (fd2 >= 0);
3293
#elif defined(MS_WINDOWS)
3294
    HANDLE hfile;
3295
    _Py_BEGIN_SUPPRESS_IPH
3296
    hfile = (HANDLE)_get_osfhandle(fd);
3297
    _Py_END_SUPPRESS_IPH
3298
    return (hfile != INVALID_HANDLE_VALUE
3299
            && GetFileType(hfile) != FILE_TYPE_UNKNOWN);
3300
#else
3301
    struct stat st;
3302
    return (fstat(fd, &st) == 0);
3303
#endif
3304
111
}
3305
3306
3307
// Call strerror_r(code) if available, or use strerror() otherwise. Decode the
3308
// result from the locale encoding using surrogateescape error handler.
3309
//
3310
// On success, return a Unicode string. On error, set an exception and return
3311
// NULL.
3312
PyObject*
3313
_Py_strerror(int code)
3314
/*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
3315
232k
{
3316
232k
    const char *errors = "surrogateescape";
3317
3318
232k
#ifdef _Py_HAVE_STRERROR_R
3319
   // Check which strerror_r() API is used
3320
232k
#  if defined(__GLIBC__) && !((_POSIX_C_SOURCE >= 200112L) && !defined(_GNU_SOURCE))
3321
232k
#    define Py_STRERROR_R_GNU
3322
#  elif defined(__ANDROID__) && defined(_GNU_SOURCE)
3323
#    define Py_STRERROR_R_GNU
3324
#  endif
3325
232k
#endif
3326
3327
232k
#ifdef Py_STRERROR_R_GNU
3328
    // Implementation for the GNU flavor of strerror_r()
3329
3330
    // On Linux, the longest translated strerror() message is 86 bytes
3331
    // (including the NUL byte).
3332
232k
    char buffer[100];
3333
232k
    char *message = strerror_r(code, buffer, Py_ARRAY_LENGTH(buffer));
3334
    // The strerror_r() GNU flavor doesn't provide a way to check if the error
3335
    // message was truncated or not.
3336
    //
3337
    // When the buffer is used, a trailing NUL byte is always written.
3338
232k
    assert(message != buffer || memchr(buffer, 0, Py_ARRAY_LENGTH(buffer)) != NULL);
3339
232k
    return PyUnicode_DecodeLocale(message, errors);
3340
3341
#elif defined(_Py_HAVE_STRERROR_R)
3342
    // Implementation for the XSI-compliant flavor of strerror_r()
3343
3344
    // On Linux and FreeBSD, the longest translated strerror() message is 86
3345
    // bytes (including the NUL byte).
3346
    char small_buffer[100];
3347
    size_t buflen = Py_ARRAY_LENGTH(small_buffer);
3348
    char *buffer = NULL;
3349
#ifndef NDEBUG
3350
    // Make sure that strerror_r() writes a trailing null byte
3351
    small_buffer[buflen - 1] = '#';
3352
#endif
3353
    int len = strerror_r(code, small_buffer, buflen);
3354
    if (len == ERANGE) {
3355
        while (len == ERANGE) {
3356
            if (buflen > (size_t)PY_SSIZE_T_MAX / 2) {
3357
                PyMem_Free(buffer);
3358
                PyErr_NoMemory();
3359
                return NULL;
3360
            }
3361
            buflen = buflen * 2;
3362
3363
            char *new_buffer = PyMem_Realloc(buffer, buflen);
3364
            if (new_buffer == NULL) {
3365
                PyMem_Free(buffer);
3366
                PyErr_NoMemory();
3367
                return NULL;
3368
            }
3369
            buffer = new_buffer;
3370
#ifndef NDEBUG
3371
            buffer[buflen - 1] = '#';
3372
#endif
3373
            len = strerror_r(code, buffer, buflen);
3374
        }
3375
    }
3376
    else {
3377
        buffer = small_buffer;
3378
    }
3379
3380
    // strerror_r() always writes a trailing NUL byte
3381
    assert(memchr(buffer, 0, buflen) != NULL);
3382
    PyObject *result = PyUnicode_DecodeLocale(buffer, errors);
3383
    if (buffer != small_buffer) {
3384
        PyMem_Free(buffer);
3385
    }
3386
    return result;
3387
3388
#else
3389
    // strerror() implementation (usually not thread-safe)
3390
    char *message = strerror(code);
3391
    if (message == NULL) {
3392
        PyErr_SetString(PyExc_ValueError,
3393
                        "strerror() argument out of range");
3394
        return NULL;
3395
    }
3396
    return PyUnicode_DecodeLocale(message, errors);
3397
#endif
3398
232k
}