blob: 4997f922251c1e9c7a85ef177addd6bba1e8c714 [file] [log] [blame]
Victor Stinner4e314432010-10-07 21:45:39 +00001#include "Python.h"
Victor Stinner710e8262020-10-31 01:02:09 +01002#include "pycore_fileutils.h" // fileutils definitions
3#include "pycore_runtime.h" // _PyRuntime
Victor Stinner361dcdc2020-04-15 03:24:57 +02004#include "osdefs.h" // SEP
Stefan Krah6c01e382014-01-20 15:31:08 +01005#include <locale.h>
6
Victor Stinnerb306d752010-10-07 22:09:40 +00007#ifdef MS_WINDOWS
Steve Dowerd81431f2015-03-06 14:47:02 -08008# include <malloc.h>
Victor Stinnerb306d752010-10-07 22:09:40 +00009# include <windows.h>
Steve Dower8fc89802015-04-12 00:26:27 -040010extern int winerror_to_errno(int);
Victor Stinnerb306d752010-10-07 22:09:40 +000011#endif
Victor Stinner4e314432010-10-07 21:45:39 +000012
Brett Cannonefb00c02012-02-29 18:31:31 -050013#ifdef HAVE_LANGINFO_H
14#include <langinfo.h>
15#endif
16
Victor Stinnerdaf45552013-08-28 00:53:59 +020017#ifdef HAVE_SYS_IOCTL_H
18#include <sys/ioctl.h>
19#endif
20
21#ifdef HAVE_FCNTL_H
22#include <fcntl.h>
23#endif /* HAVE_FCNTL_H */
24
Victor Stinnerdaf45552013-08-28 00:53:59 +020025#ifdef O_CLOEXEC
Victor Stinnerb034eee2013-09-07 10:36:04 +020026/* Does open() support the O_CLOEXEC flag? Possible values:
Victor Stinnerdaf45552013-08-28 00:53:59 +020027
28 -1: unknown
29 0: open() ignores O_CLOEXEC flag, ex: Linux kernel older than 2.6.23
30 1: open() supports O_CLOEXEC flag, close-on-exec is set
31
Victor Stinnera555cfc2015-03-18 00:22:14 +010032 The flag is used by _Py_open(), _Py_open_noraise(), io.FileIO
33 and os.open(). */
Victor Stinnerdaf45552013-08-28 00:53:59 +020034int _Py_open_cloexec_works = -1;
35#endif
36
Victor Stinner99768342021-03-17 21:46:53 +010037// The value must be the same in unicodeobject.c.
38#define MAX_UNICODE 0x10ffff
39
40// mbstowcs() and mbrtowc() errors
41static const size_t DECODE_ERROR = ((size_t)-1);
42static const size_t INCOMPLETE_CHARACTER = (size_t)-2;
43
Victor Stinner3d4226a2018-08-29 22:21:32 +020044
45static int
46get_surrogateescape(_Py_error_handler errors, int *surrogateescape)
47{
48 switch (errors)
49 {
50 case _Py_ERROR_STRICT:
51 *surrogateescape = 0;
52 return 0;
53 case _Py_ERROR_SURROGATEESCAPE:
54 *surrogateescape = 1;
55 return 0;
56 default:
57 return -1;
58 }
59}
60
61
Brett Cannonefb00c02012-02-29 18:31:31 -050062PyObject *
63_Py_device_encoding(int fd)
64{
Steve Dower8fc89802015-04-12 00:26:27 -040065 int valid;
66 _Py_BEGIN_SUPPRESS_IPH
Steve Dower940f33a2016-09-08 11:21:54 -070067 valid = isatty(fd);
Steve Dower8fc89802015-04-12 00:26:27 -040068 _Py_END_SUPPRESS_IPH
69 if (!valid)
Brett Cannonefb00c02012-02-29 18:31:31 -050070 Py_RETURN_NONE;
Steve Dower8fc89802015-04-12 00:26:27 -040071
Victor Stinner14b9b112013-06-25 00:37:25 +020072#if defined(MS_WINDOWS)
Victor Stinner35297182020-11-04 11:20:10 +010073 UINT cp;
Brett Cannonefb00c02012-02-29 18:31:31 -050074 if (fd == 0)
75 cp = GetConsoleCP();
76 else if (fd == 1 || fd == 2)
77 cp = GetConsoleOutputCP();
78 else
79 cp = 0;
80 /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application
81 has no console */
Victor Stinner35297182020-11-04 11:20:10 +010082 if (cp == 0) {
83 Py_RETURN_NONE;
Brett Cannonefb00c02012-02-29 18:31:31 -050084 }
Victor Stinner35297182020-11-04 11:20:10 +010085
86 return PyUnicode_FromFormat("cp%u", (unsigned int)cp);
87#else
88 return _Py_GetLocaleEncodingObject();
Brett Cannonefb00c02012-02-29 18:31:31 -050089#endif
Brett Cannonefb00c02012-02-29 18:31:31 -050090}
91
Victor Stinner99768342021-03-17 21:46:53 +010092
93static size_t
94is_valid_wide_char(wchar_t ch)
95{
96 if (Py_UNICODE_IS_SURROGATE(ch)) {
97 // Reject lone surrogate characters
98 return 0;
99 }
100 if (ch > MAX_UNICODE) {
101 // bpo-35883: Reject characters outside [U+0000; U+10ffff] range.
102 // The glibc mbstowcs() UTF-8 decoder does not respect the RFC 3629,
103 // it creates characters outside the [U+0000; U+10ffff] range:
104 // https://sourceware.org/bugzilla/show_bug.cgi?id=2373
105 return 0;
106 }
107 return 1;
108}
109
110
111static size_t
112_Py_mbstowcs(wchar_t *dest, const char *src, size_t n)
113{
114 size_t count = mbstowcs(dest, src, n);
115 if (dest != NULL && count != DECODE_ERROR) {
116 for (size_t i=0; i < count; i++) {
117 wchar_t ch = dest[i];
118 if (!is_valid_wide_char(ch)) {
119 return DECODE_ERROR;
120 }
121 }
122 }
123 return count;
124}
125
126
127#ifdef HAVE_MBRTOWC
128static size_t
129_Py_mbrtowc(wchar_t *pwc, const char *str, size_t len, mbstate_t *pmbs)
130{
131 assert(pwc != NULL);
132 size_t count = mbrtowc(pwc, str, len, pmbs);
133 if (count != 0 && count != DECODE_ERROR && count != INCOMPLETE_CHARACTER) {
134 if (!is_valid_wide_char(*pwc)) {
135 return DECODE_ERROR;
136 }
137 }
138 return count;
139}
140#endif
141
142
Victor Stinnere2510952019-05-02 11:28:57 -0400143#if !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS)
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100144
145#define USE_FORCE_ASCII
146
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100147extern int _Py_normalize_encoding(const char *, char *, size_t);
148
Victor Stinnerd500e532018-08-28 17:27:36 +0200149/* Workaround FreeBSD and OpenIndiana locale encoding issue with the C locale
150 and POSIX locale. nl_langinfo(CODESET) announces an alias of the
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100151 ASCII encoding, whereas mbstowcs() and wcstombs() functions use the
152 ISO-8859-1 encoding. The problem is that os.fsencode() and os.fsdecode() use
153 locale.getpreferredencoding() codec. For example, if command line arguments
154 are decoded by mbstowcs() and encoded back by os.fsencode(), we get a
155 UnicodeEncodeError instead of retrieving the original byte string.
156
157 The workaround is enabled if setlocale(LC_CTYPE, NULL) returns "C",
158 nl_langinfo(CODESET) announces "ascii" (or an alias to ASCII), and at least
159 one byte in range 0x80-0xff can be decoded from the locale encoding. The
160 workaround is also enabled on error, for example if getting the locale
161 failed.
162
Victor Stinnerd500e532018-08-28 17:27:36 +0200163 On HP-UX with the C locale or the POSIX locale, nl_langinfo(CODESET)
164 announces "roman8" but mbstowcs() uses Latin1 in practice. Force also the
165 ASCII encoding in this case.
166
Philip Jenvey215c49a2013-01-15 13:24:12 -0800167 Values of force_ascii:
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100168
Victor Stinnerf6a271a2014-08-01 12:28:48 +0200169 1: the workaround is used: Py_EncodeLocale() uses
170 encode_ascii_surrogateescape() and Py_DecodeLocale() uses
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100171 decode_ascii()
Victor Stinnerf6a271a2014-08-01 12:28:48 +0200172 0: the workaround is not used: Py_EncodeLocale() uses wcstombs() and
173 Py_DecodeLocale() uses mbstowcs()
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100174 -1: unknown, need to call check_force_ascii() to get the value
175*/
176static int force_ascii = -1;
177
178static int
179check_force_ascii(void)
180{
Victor Stinnerd500e532018-08-28 17:27:36 +0200181 char *loc = setlocale(LC_CTYPE, NULL);
182 if (loc == NULL) {
183 goto error;
184 }
185 if (strcmp(loc, "C") != 0 && strcmp(loc, "POSIX") != 0) {
186 /* the LC_CTYPE locale is different than C and POSIX */
187 return 0;
188 }
189
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100190#if defined(HAVE_LANGINFO_H) && defined(CODESET)
Victor Stinnerd500e532018-08-28 17:27:36 +0200191 const char *codeset = nl_langinfo(CODESET);
192 if (!codeset || codeset[0] == '\0') {
193 /* CODESET is not set or empty */
194 goto error;
195 }
196
Victor Stinner54de2b12016-09-09 23:11:52 -0700197 char encoding[20]; /* longest name: "iso_646.irv_1991\0" */
Victor Stinnerd500e532018-08-28 17:27:36 +0200198 if (!_Py_normalize_encoding(codeset, encoding, sizeof(encoding))) {
199 goto error;
200 }
201
202#ifdef __hpux
203 if (strcmp(encoding, "roman8") == 0) {
204 unsigned char ch;
205 wchar_t wch;
206 size_t res;
207
208 ch = (unsigned char)0xA7;
Victor Stinner99768342021-03-17 21:46:53 +0100209 res = _Py_mbstowcs(&wch, (char*)&ch, 1);
210 if (res != DECODE_ERROR && wch == L'\xA7') {
Victor Stinnerd500e532018-08-28 17:27:36 +0200211 /* On HP-UX withe C locale or the POSIX locale,
212 nl_langinfo(CODESET) announces "roman8", whereas mbstowcs() uses
213 Latin1 encoding in practice. Force ASCII in this case.
214
215 Roman8 decodes 0xA7 to U+00CF. Latin1 decodes 0xA7 to U+00A7. */
216 return 1;
217 }
218 }
219#else
220 const char* ascii_aliases[] = {
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100221 "ascii",
Victor Stinner54de2b12016-09-09 23:11:52 -0700222 /* Aliases from Lib/encodings/aliases.py */
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100223 "646",
Victor Stinner54de2b12016-09-09 23:11:52 -0700224 "ansi_x3.4_1968",
225 "ansi_x3.4_1986",
226 "ansi_x3_4_1968",
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100227 "cp367",
228 "csascii",
229 "ibm367",
Victor Stinner54de2b12016-09-09 23:11:52 -0700230 "iso646_us",
231 "iso_646.irv_1991",
232 "iso_ir_6",
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100233 "us",
Victor Stinner54de2b12016-09-09 23:11:52 -0700234 "us_ascii",
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100235 NULL
236 };
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100237
Victor Stinnerd500e532018-08-28 17:27:36 +0200238 int is_ascii = 0;
239 for (const char **alias=ascii_aliases; *alias != NULL; alias++) {
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100240 if (strcmp(encoding, *alias) == 0) {
241 is_ascii = 1;
242 break;
243 }
244 }
245 if (!is_ascii) {
246 /* nl_langinfo(CODESET) is not "ascii" or an alias of ASCII */
247 return 0;
248 }
249
Victor Stinnerd500e532018-08-28 17:27:36 +0200250 for (unsigned int i=0x80; i<=0xff; i++) {
251 char ch[1];
252 wchar_t wch[1];
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100253 size_t res;
254
Victor Stinnerd500e532018-08-28 17:27:36 +0200255 unsigned uch = (unsigned char)i;
256 ch[0] = (char)uch;
Victor Stinner99768342021-03-17 21:46:53 +0100257 res = _Py_mbstowcs(wch, ch, 1);
258 if (res != DECODE_ERROR) {
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100259 /* decoding a non-ASCII character from the locale encoding succeed:
260 the locale encoding is not ASCII, force ASCII */
261 return 1;
262 }
263 }
264 /* None of the bytes in the range 0x80-0xff can be decoded from the locale
265 encoding: the locale encoding is really ASCII */
Victor Stinnerd500e532018-08-28 17:27:36 +0200266#endif /* !defined(__hpux) */
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100267 return 0;
268#else
269 /* nl_langinfo(CODESET) is not available: always force ASCII */
270 return 1;
Victor Stinnerd500e532018-08-28 17:27:36 +0200271#endif /* defined(HAVE_LANGINFO_H) && defined(CODESET) */
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100272
273error:
Martin Panter46f50722016-05-26 05:35:26 +0000274 /* if an error occurred, force the ASCII encoding */
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100275 return 1;
276}
277
Victor Stinnerd500e532018-08-28 17:27:36 +0200278
279int
280_Py_GetForceASCII(void)
281{
282 if (force_ascii == -1) {
283 force_ascii = check_force_ascii();
284 }
285 return force_ascii;
286}
287
288
Victor Stinner353933e2018-11-23 13:08:26 +0100289void
290_Py_ResetForceASCII(void)
291{
292 force_ascii = -1;
293}
294
295
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100296static int
297encode_ascii(const wchar_t *text, char **str,
298 size_t *error_pos, const char **reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200299 int raw_malloc, _Py_error_handler errors)
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100300{
301 char *result = NULL, *out;
302 size_t len, i;
303 wchar_t ch;
304
Victor Stinner3d4226a2018-08-29 22:21:32 +0200305 int surrogateescape;
306 if (get_surrogateescape(errors, &surrogateescape) < 0) {
307 return -3;
308 }
309
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100310 len = wcslen(text);
311
Victor Stinner9bee3292017-12-21 16:49:13 +0100312 /* +1 for NULL byte */
Victor Stinner9dd76202017-12-21 16:20:32 +0100313 if (raw_malloc) {
314 result = PyMem_RawMalloc(len + 1);
315 }
316 else {
317 result = PyMem_Malloc(len + 1);
318 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100319 if (result == NULL) {
320 return -1;
321 }
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100322
323 out = result;
324 for (i=0; i<len; i++) {
325 ch = text[i];
326
327 if (ch <= 0x7f) {
328 /* ASCII character */
329 *out++ = (char)ch;
330 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100331 else if (surrogateescape && 0xdc80 <= ch && ch <= 0xdcff) {
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100332 /* UTF-8b surrogate */
333 *out++ = (char)(ch - 0xdc00);
334 }
335 else {
Victor Stinner9dd76202017-12-21 16:20:32 +0100336 if (raw_malloc) {
337 PyMem_RawFree(result);
338 }
339 else {
340 PyMem_Free(result);
341 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100342 if (error_pos != NULL) {
343 *error_pos = i;
344 }
345 if (reason) {
346 *reason = "encoding error";
347 }
348 return -2;
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100349 }
350 }
351 *out = '\0';
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100352 *str = result;
353 return 0;
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100354}
Victor Stinnerd500e532018-08-28 17:27:36 +0200355#else
356int
357_Py_GetForceASCII(void)
358{
359 return 0;
360}
Victor Stinner353933e2018-11-23 13:08:26 +0100361
362void
363_Py_ResetForceASCII(void)
364{
365 /* nothing to do */
366}
Victor Stinnere2510952019-05-02 11:28:57 -0400367#endif /* !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS) */
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100368
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100369
370#if !defined(HAVE_MBRTOWC) || defined(USE_FORCE_ASCII)
371static int
372decode_ascii(const char *arg, wchar_t **wstr, size_t *wlen,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200373 const char **reason, _Py_error_handler errors)
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100374{
375 wchar_t *res;
376 unsigned char *in;
377 wchar_t *out;
Benjamin Petersonf18bf6f2015-01-04 16:03:17 -0600378 size_t argsize = strlen(arg) + 1;
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100379
Victor Stinner3d4226a2018-08-29 22:21:32 +0200380 int surrogateescape;
381 if (get_surrogateescape(errors, &surrogateescape) < 0) {
382 return -3;
383 }
384
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100385 if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t)) {
386 return -1;
387 }
388 res = PyMem_RawMalloc(argsize * sizeof(wchar_t));
389 if (!res) {
390 return -1;
391 }
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100392
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100393 out = res;
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100394 for (in = (unsigned char*)arg; *in; in++) {
395 unsigned char ch = *in;
396 if (ch < 128) {
397 *out++ = ch;
398 }
399 else {
400 if (!surrogateescape) {
401 PyMem_RawFree(res);
402 if (wlen) {
403 *wlen = in - (unsigned char*)arg;
404 }
405 if (reason) {
406 *reason = "decoding error";
407 }
408 return -2;
409 }
410 *out++ = 0xdc00 + ch;
411 }
412 }
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100413 *out = 0;
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100414
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100415 if (wlen != NULL) {
416 *wlen = out - res;
417 }
418 *wstr = res;
419 return 0;
420}
421#endif /* !HAVE_MBRTOWC */
422
423static int
424decode_current_locale(const char* arg, wchar_t **wstr, size_t *wlen,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200425 const char **reason, _Py_error_handler errors)
Victor Stinner4e314432010-10-07 21:45:39 +0000426{
427 wchar_t *res;
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100428 size_t argsize;
Victor Stinner4e314432010-10-07 21:45:39 +0000429 size_t count;
Victor Stinner313f10c2013-05-07 23:48:56 +0200430#ifdef HAVE_MBRTOWC
Victor Stinner4e314432010-10-07 21:45:39 +0000431 unsigned char *in;
432 wchar_t *out;
Victor Stinner4e314432010-10-07 21:45:39 +0000433 mbstate_t mbs;
434#endif
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100435
Victor Stinner3d4226a2018-08-29 22:21:32 +0200436 int surrogateescape;
437 if (get_surrogateescape(errors, &surrogateescape) < 0) {
438 return -3;
439 }
440
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100441#ifdef HAVE_BROKEN_MBSTOWCS
442 /* Some platforms have a broken implementation of
443 * mbstowcs which does not count the characters that
444 * would result from conversion. Use an upper bound.
445 */
446 argsize = strlen(arg);
447#else
Victor Stinner99768342021-03-17 21:46:53 +0100448 argsize = _Py_mbstowcs(NULL, arg, 0);
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100449#endif
Victor Stinner99768342021-03-17 21:46:53 +0100450 if (argsize != DECODE_ERROR) {
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100451 if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) {
452 return -1;
453 }
454 res = (wchar_t *)PyMem_RawMalloc((argsize + 1) * sizeof(wchar_t));
455 if (!res) {
456 return -1;
457 }
458
Victor Stinner99768342021-03-17 21:46:53 +0100459 count = _Py_mbstowcs(res, arg, argsize + 1);
460 if (count != DECODE_ERROR) {
461 *wstr = res;
462 if (wlen != NULL) {
463 *wlen = count;
Victor Stinner168e1172010-10-16 23:16:16 +0000464 }
Victor Stinner99768342021-03-17 21:46:53 +0100465 return 0;
Victor Stinner4e314432010-10-07 21:45:39 +0000466 }
Victor Stinner1a7425f2013-07-07 16:25:15 +0200467 PyMem_RawFree(res);
Victor Stinner4e314432010-10-07 21:45:39 +0000468 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100469
Victor Stinner4e314432010-10-07 21:45:39 +0000470 /* Conversion failed. Fall back to escaping with surrogateescape. */
471#ifdef HAVE_MBRTOWC
472 /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
473
474 /* Overallocate; as multi-byte characters are in the argument, the
475 actual output could use less memory. */
476 argsize = strlen(arg) + 1;
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100477 if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t)) {
478 return -1;
479 }
480 res = (wchar_t*)PyMem_RawMalloc(argsize * sizeof(wchar_t));
481 if (!res) {
482 return -1;
483 }
484
Victor Stinner4e314432010-10-07 21:45:39 +0000485 in = (unsigned char*)arg;
486 out = res;
487 memset(&mbs, 0, sizeof mbs);
488 while (argsize) {
Victor Stinner99768342021-03-17 21:46:53 +0100489 size_t converted = _Py_mbrtowc(out, (char*)in, argsize, &mbs);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100490 if (converted == 0) {
Victor Stinner4e314432010-10-07 21:45:39 +0000491 /* Reached end of string; null char stored. */
492 break;
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100493 }
494
Victor Stinner99768342021-03-17 21:46:53 +0100495 if (converted == INCOMPLETE_CHARACTER) {
Victor Stinner4e314432010-10-07 21:45:39 +0000496 /* Incomplete character. This should never happen,
497 since we provide everything that we have -
498 unless there is a bug in the C library, or I
499 misunderstood how mbrtowc works. */
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100500 goto decode_error;
Victor Stinner4e314432010-10-07 21:45:39 +0000501 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100502
Victor Stinner99768342021-03-17 21:46:53 +0100503 if (converted == DECODE_ERROR) {
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100504 if (!surrogateescape) {
505 goto decode_error;
506 }
507
Victor Stinner99768342021-03-17 21:46:53 +0100508 /* Decoding error. Escape as UTF-8b, and start over in the initial
509 shift state. */
Victor Stinner4e314432010-10-07 21:45:39 +0000510 *out++ = 0xdc00 + *in++;
511 argsize--;
512 memset(&mbs, 0, sizeof mbs);
513 continue;
514 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100515
Victor Stinner99768342021-03-17 21:46:53 +0100516 // _Py_mbrtowc() reject lone surrogate characters
517 assert(!Py_UNICODE_IS_SURROGATE(*out));
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100518
Victor Stinner4e314432010-10-07 21:45:39 +0000519 /* successfully converted some bytes */
520 in += converted;
521 argsize -= converted;
522 out++;
523 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100524 if (wlen != NULL) {
525 *wlen = out - res;
526 }
527 *wstr = res;
528 return 0;
529
530decode_error:
531 PyMem_RawFree(res);
532 if (wlen) {
533 *wlen = in - (unsigned char*)arg;
534 }
535 if (reason) {
536 *reason = "decoding error";
537 }
538 return -2;
Victor Stinnere2623772012-11-12 23:04:02 +0100539#else /* HAVE_MBRTOWC */
Victor Stinner4e314432010-10-07 21:45:39 +0000540 /* Cannot use C locale for escaping; manually escape as if charset
541 is ASCII (i.e. escape all bytes > 128. This will still roundtrip
542 correctly in the locale's charset, which must be an ASCII superset. */
Victor Stinner3d4226a2018-08-29 22:21:32 +0200543 return decode_ascii(arg, wstr, wlen, reason, errors);
Victor Stinnere2623772012-11-12 23:04:02 +0100544#endif /* HAVE_MBRTOWC */
Victor Stinner91106cd2017-12-13 12:29:09 +0100545}
546
547
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100548/* Decode a byte string from the locale encoding.
549
550 Use the strict error handler if 'surrogateescape' is zero. Use the
551 surrogateescape error handler if 'surrogateescape' is non-zero: undecodable
552 bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence
553 can be decoded as a surrogate character, escape the bytes using the
554 surrogateescape error handler instead of decoding them.
555
Ville Skyttä61f82e02018-04-20 23:08:45 +0300556 On success, return 0 and write the newly allocated wide character string into
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100557 *wstr (use PyMem_RawFree() to free the memory). If wlen is not NULL, write
558 the number of wide characters excluding the null character into *wlen.
559
560 On memory allocation failure, return -1.
561
562 On decoding error, return -2. If wlen is not NULL, write the start of
563 invalid byte sequence in the input string into *wlen. If reason is not NULL,
564 write the decoding error message into *reason.
565
Victor Stinner3d4226a2018-08-29 22:21:32 +0200566 Return -3 if the error handler 'errors' is not supported.
567
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100568 Use the Py_EncodeLocaleEx() function to encode the character string back to
569 a byte string. */
570int
571_Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen,
572 const char **reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200573 int current_locale, _Py_error_handler errors)
Victor Stinner2cba6b82018-01-10 22:46:15 +0100574{
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100575 if (current_locale) {
Victor Stinnere2510952019-05-02 11:28:57 -0400576#ifdef _Py_FORCE_UTF8_LOCALE
Victor Stinner9089a262018-01-22 19:07:32 +0100577 return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200578 errors);
Victor Stinner9089a262018-01-22 19:07:32 +0100579#else
Victor Stinner3d4226a2018-08-29 22:21:32 +0200580 return decode_current_locale(arg, wstr, wlen, reason, errors);
Victor Stinner9089a262018-01-22 19:07:32 +0100581#endif
Victor Stinner2cba6b82018-01-10 22:46:15 +0100582 }
583
Victor Stinnere2510952019-05-02 11:28:57 -0400584#ifdef _Py_FORCE_UTF8_FS_ENCODING
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100585 return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200586 errors);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100587#else
Victor Stinnerc5989cd2018-08-29 19:32:47 +0200588 int use_utf8 = (Py_UTF8Mode == 1);
589#ifdef MS_WINDOWS
590 use_utf8 |= !Py_LegacyWindowsFSEncodingFlag;
591#endif
592 if (use_utf8) {
Victor Stinner3d4226a2018-08-29 22:21:32 +0200593 return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason,
594 errors);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100595 }
596
597#ifdef USE_FORCE_ASCII
598 if (force_ascii == -1) {
Victor Stinner2cba6b82018-01-10 22:46:15 +0100599 force_ascii = check_force_ascii();
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100600 }
Victor Stinner2cba6b82018-01-10 22:46:15 +0100601
602 if (force_ascii) {
603 /* force ASCII encoding to workaround mbstowcs() issue */
Victor Stinner3d4226a2018-08-29 22:21:32 +0200604 return decode_ascii(arg, wstr, wlen, reason, errors);
Victor Stinner2cba6b82018-01-10 22:46:15 +0100605 }
606#endif
607
Victor Stinner3d4226a2018-08-29 22:21:32 +0200608 return decode_current_locale(arg, wstr, wlen, reason, errors);
Victor Stinnere2510952019-05-02 11:28:57 -0400609#endif /* !_Py_FORCE_UTF8_FS_ENCODING */
Victor Stinner2cba6b82018-01-10 22:46:15 +0100610}
611
612
Victor Stinner91106cd2017-12-13 12:29:09 +0100613/* Decode a byte string from the locale encoding with the
614 surrogateescape error handler: undecodable bytes are decoded as characters
615 in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate
616 character, escape the bytes using the surrogateescape error handler instead
617 of decoding them.
618
619 Return a pointer to a newly allocated wide character string, use
620 PyMem_RawFree() to free the memory. If size is not NULL, write the number of
621 wide characters excluding the null character into *size
622
623 Return NULL on decoding error or memory allocation error. If *size* is not
624 NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on
625 decoding error.
626
627 Decoding errors should never happen, unless there is a bug in the C
628 library.
629
630 Use the Py_EncodeLocale() function to encode the character string back to a
631 byte string. */
632wchar_t*
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100633Py_DecodeLocale(const char* arg, size_t *wlen)
Victor Stinner91106cd2017-12-13 12:29:09 +0100634{
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100635 wchar_t *wstr;
Victor Stinner3d4226a2018-08-29 22:21:32 +0200636 int res = _Py_DecodeLocaleEx(arg, &wstr, wlen,
637 NULL, 0,
638 _Py_ERROR_SURROGATEESCAPE);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100639 if (res != 0) {
Victor Stinner3d4226a2018-08-29 22:21:32 +0200640 assert(res != -3);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100641 if (wlen != NULL) {
642 *wlen = (size_t)res;
643 }
644 return NULL;
645 }
646 return wstr;
Victor Stinner2cba6b82018-01-10 22:46:15 +0100647}
Victor Stinner91106cd2017-12-13 12:29:09 +0100648
Victor Stinner91106cd2017-12-13 12:29:09 +0100649
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100650static int
651encode_current_locale(const wchar_t *text, char **str,
652 size_t *error_pos, const char **reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200653 int raw_malloc, _Py_error_handler errors)
Victor Stinner91106cd2017-12-13 12:29:09 +0100654{
Victor Stinner4e314432010-10-07 21:45:39 +0000655 const size_t len = wcslen(text);
656 char *result = NULL, *bytes = NULL;
657 size_t i, size, converted;
658 wchar_t c, buf[2];
659
Victor Stinner3d4226a2018-08-29 22:21:32 +0200660 int surrogateescape;
661 if (get_surrogateescape(errors, &surrogateescape) < 0) {
662 return -3;
663 }
664
Victor Stinner4e314432010-10-07 21:45:39 +0000665 /* The function works in two steps:
666 1. compute the length of the output buffer in bytes (size)
667 2. outputs the bytes */
668 size = 0;
669 buf[1] = 0;
670 while (1) {
671 for (i=0; i < len; i++) {
672 c = text[i];
673 if (c >= 0xdc80 && c <= 0xdcff) {
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100674 if (!surrogateescape) {
675 goto encode_error;
676 }
Victor Stinner4e314432010-10-07 21:45:39 +0000677 /* UTF-8b surrogate */
678 if (bytes != NULL) {
679 *bytes++ = c - 0xdc00;
680 size--;
681 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100682 else {
Victor Stinner4e314432010-10-07 21:45:39 +0000683 size++;
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100684 }
Victor Stinner4e314432010-10-07 21:45:39 +0000685 continue;
686 }
687 else {
688 buf[0] = c;
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100689 if (bytes != NULL) {
Victor Stinner4e314432010-10-07 21:45:39 +0000690 converted = wcstombs(bytes, buf, size);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100691 }
692 else {
Victor Stinner4e314432010-10-07 21:45:39 +0000693 converted = wcstombs(NULL, buf, 0);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100694 }
Victor Stinner99768342021-03-17 21:46:53 +0100695 if (converted == DECODE_ERROR) {
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100696 goto encode_error;
Victor Stinner4e314432010-10-07 21:45:39 +0000697 }
698 if (bytes != NULL) {
699 bytes += converted;
700 size -= converted;
701 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100702 else {
Victor Stinner4e314432010-10-07 21:45:39 +0000703 size += converted;
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100704 }
Victor Stinner4e314432010-10-07 21:45:39 +0000705 }
706 }
707 if (result != NULL) {
Victor Stinnerd45c7f82012-12-04 01:34:47 +0100708 *bytes = '\0';
Victor Stinner4e314432010-10-07 21:45:39 +0000709 break;
710 }
711
712 size += 1; /* nul byte at the end */
Victor Stinner9dd76202017-12-21 16:20:32 +0100713 if (raw_malloc) {
714 result = PyMem_RawMalloc(size);
715 }
716 else {
717 result = PyMem_Malloc(size);
718 }
Victor Stinner0d92c4f2012-11-12 23:32:21 +0100719 if (result == NULL) {
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100720 return -1;
Victor Stinner0d92c4f2012-11-12 23:32:21 +0100721 }
Victor Stinner4e314432010-10-07 21:45:39 +0000722 bytes = result;
723 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100724 *str = result;
725 return 0;
726
727encode_error:
728 if (raw_malloc) {
729 PyMem_RawFree(result);
730 }
731 else {
732 PyMem_Free(result);
733 }
734 if (error_pos != NULL) {
735 *error_pos = i;
736 }
737 if (reason) {
738 *reason = "encoding error";
739 }
740 return -2;
Victor Stinner91106cd2017-12-13 12:29:09 +0100741}
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100742
Victor Stinner3d4226a2018-08-29 22:21:32 +0200743
744/* Encode a string to the locale encoding.
745
746 Parameters:
747
748 * raw_malloc: if non-zero, allocate memory using PyMem_RawMalloc() instead
749 of PyMem_Malloc().
750 * current_locale: if non-zero, use the current LC_CTYPE, otherwise use
751 Python filesystem encoding.
752 * errors: error handler like "strict" or "surrogateescape".
753
754 Return value:
755
756 0: success, *str is set to a newly allocated decoded string.
757 -1: memory allocation failure
758 -2: encoding error, set *error_pos and *reason (if set).
759 -3: the error handler 'errors' is not supported.
760 */
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100761static int
762encode_locale_ex(const wchar_t *text, char **str, size_t *error_pos,
763 const char **reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200764 int raw_malloc, int current_locale, _Py_error_handler errors)
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100765{
766 if (current_locale) {
Victor Stinnere2510952019-05-02 11:28:57 -0400767#ifdef _Py_FORCE_UTF8_LOCALE
Victor Stinner9089a262018-01-22 19:07:32 +0100768 return _Py_EncodeUTF8Ex(text, str, error_pos, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200769 raw_malloc, errors);
Victor Stinner9089a262018-01-22 19:07:32 +0100770#else
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100771 return encode_current_locale(text, str, error_pos, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200772 raw_malloc, errors);
Victor Stinner9089a262018-01-22 19:07:32 +0100773#endif
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100774 }
775
Victor Stinnere2510952019-05-02 11:28:57 -0400776#ifdef _Py_FORCE_UTF8_FS_ENCODING
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100777 return _Py_EncodeUTF8Ex(text, str, error_pos, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200778 raw_malloc, errors);
779#else
Victor Stinnerc5989cd2018-08-29 19:32:47 +0200780 int use_utf8 = (Py_UTF8Mode == 1);
781#ifdef MS_WINDOWS
782 use_utf8 |= !Py_LegacyWindowsFSEncodingFlag;
783#endif
784 if (use_utf8) {
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100785 return _Py_EncodeUTF8Ex(text, str, error_pos, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200786 raw_malloc, errors);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100787 }
788
789#ifdef USE_FORCE_ASCII
790 if (force_ascii == -1) {
791 force_ascii = check_force_ascii();
792 }
793
794 if (force_ascii) {
795 return encode_ascii(text, str, error_pos, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200796 raw_malloc, errors);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100797 }
Victor Stinnerd2b02312017-12-15 23:06:17 +0100798#endif
Victor Stinner91106cd2017-12-13 12:29:09 +0100799
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100800 return encode_current_locale(text, str, error_pos, reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200801 raw_malloc, errors);
Victor Stinnere2510952019-05-02 11:28:57 -0400802#endif /* _Py_FORCE_UTF8_FS_ENCODING */
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100803}
804
Victor Stinner9dd76202017-12-21 16:20:32 +0100805static char*
Victor Stinner2cba6b82018-01-10 22:46:15 +0100806encode_locale(const wchar_t *text, size_t *error_pos,
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100807 int raw_malloc, int current_locale)
Victor Stinner9dd76202017-12-21 16:20:32 +0100808{
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100809 char *str;
810 int res = encode_locale_ex(text, &str, error_pos, NULL,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200811 raw_malloc, current_locale,
812 _Py_ERROR_SURROGATEESCAPE);
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100813 if (res != -2 && error_pos) {
814 *error_pos = (size_t)-1;
Victor Stinner9dd76202017-12-21 16:20:32 +0100815 }
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100816 if (res != 0) {
817 return NULL;
818 }
819 return str;
Victor Stinner9dd76202017-12-21 16:20:32 +0100820}
821
Victor Stinner91106cd2017-12-13 12:29:09 +0100822/* Encode a wide character string to the locale encoding with the
823 surrogateescape error handler: surrogate characters in the range
824 U+DC80..U+DCFF are converted to bytes 0x80..0xFF.
825
826 Return a pointer to a newly allocated byte string, use PyMem_Free() to free
827 the memory. Return NULL on encoding or memory allocation error.
828
829 If error_pos is not NULL, *error_pos is set to (size_t)-1 on success, or set
830 to the index of the invalid character on encoding error.
831
832 Use the Py_DecodeLocale() function to decode the bytes string back to a wide
833 character string. */
834char*
835Py_EncodeLocale(const wchar_t *text, size_t *error_pos)
836{
Victor Stinner2cba6b82018-01-10 22:46:15 +0100837 return encode_locale(text, error_pos, 0, 0);
Victor Stinner9dd76202017-12-21 16:20:32 +0100838}
Victor Stinner91106cd2017-12-13 12:29:09 +0100839
Victor Stinner91106cd2017-12-13 12:29:09 +0100840
Victor Stinner9dd76202017-12-21 16:20:32 +0100841/* Similar to Py_EncodeLocale(), but result must be freed by PyMem_RawFree()
842 instead of PyMem_Free(). */
843char*
844_Py_EncodeLocaleRaw(const wchar_t *text, size_t *error_pos)
845{
Victor Stinner2cba6b82018-01-10 22:46:15 +0100846 return encode_locale(text, error_pos, 1, 0);
847}
848
849
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100850int
851_Py_EncodeLocaleEx(const wchar_t *text, char **str,
852 size_t *error_pos, const char **reason,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200853 int current_locale, _Py_error_handler errors)
Victor Stinner2cba6b82018-01-10 22:46:15 +0100854{
Victor Stinner7ed7aea2018-01-15 10:45:49 +0100855 return encode_locale_ex(text, str, error_pos, reason, 1,
Victor Stinner3d4226a2018-08-29 22:21:32 +0200856 current_locale, errors);
Victor Stinner4e314432010-10-07 21:45:39 +0000857}
858
Victor Stinner6672d0c2010-10-07 22:53:43 +0000859
Victor Stinner82458b62020-11-01 20:59:35 +0100860// Get the current locale encoding name:
861//
862// - Return "UTF-8" if _Py_FORCE_UTF8_LOCALE macro is defined (ex: on Android)
863// - Return "UTF-8" if the UTF-8 Mode is enabled
864// - On Windows, return the ANSI code page (ex: "cp1250")
Victor Stinnere662c392020-11-01 23:07:23 +0100865// - Return "UTF-8" if nl_langinfo(CODESET) returns an empty string.
Victor Stinner82458b62020-11-01 20:59:35 +0100866// - Otherwise, return nl_langinfo(CODESET).
867//
Victor Stinnere662c392020-11-01 23:07:23 +0100868// Return NULL on memory allocation failure.
Victor Stinner82458b62020-11-01 20:59:35 +0100869//
Victor Stinner710e8262020-10-31 01:02:09 +0100870// See also config_get_locale_encoding()
Victor Stinner82458b62020-11-01 20:59:35 +0100871wchar_t*
Victor Stinnere662c392020-11-01 23:07:23 +0100872_Py_GetLocaleEncoding(void)
Victor Stinner710e8262020-10-31 01:02:09 +0100873{
874#ifdef _Py_FORCE_UTF8_LOCALE
875 // On Android langinfo.h and CODESET are missing,
876 // and UTF-8 is always used in mbstowcs() and wcstombs().
Victor Stinner82458b62020-11-01 20:59:35 +0100877 return _PyMem_RawWcsdup(L"UTF-8");
Victor Stinner710e8262020-10-31 01:02:09 +0100878#else
879 const PyPreConfig *preconfig = &_PyRuntime.preconfig;
880 if (preconfig->utf8_mode) {
Victor Stinner82458b62020-11-01 20:59:35 +0100881 return _PyMem_RawWcsdup(L"UTF-8");
Victor Stinner710e8262020-10-31 01:02:09 +0100882 }
883
Victor Stinner82458b62020-11-01 20:59:35 +0100884#ifdef MS_WINDOWS
885 wchar_t encoding[23];
886 unsigned int ansi_codepage = GetACP();
887 swprintf(encoding, Py_ARRAY_LENGTH(encoding), L"cp%u", ansi_codepage);
888 encoding[Py_ARRAY_LENGTH(encoding) - 1] = 0;
889 return _PyMem_RawWcsdup(encoding);
Victor Stinner710e8262020-10-31 01:02:09 +0100890#else
891 const char *encoding = nl_langinfo(CODESET);
892 if (!encoding || encoding[0] == '\0') {
Victor Stinnere662c392020-11-01 23:07:23 +0100893 // Use UTF-8 if nl_langinfo() returns an empty string. It can happen on
894 // macOS if the LC_CTYPE locale is not supported.
Victor Stinner82458b62020-11-01 20:59:35 +0100895 return _PyMem_RawWcsdup(L"UTF-8");
Victor Stinner710e8262020-10-31 01:02:09 +0100896 }
Victor Stinner710e8262020-10-31 01:02:09 +0100897
Victor Stinner82458b62020-11-01 20:59:35 +0100898 wchar_t *wstr;
899 int res = decode_current_locale(encoding, &wstr, NULL,
Victor Stinnere662c392020-11-01 23:07:23 +0100900 NULL, _Py_ERROR_SURROGATEESCAPE);
Victor Stinner82458b62020-11-01 20:59:35 +0100901 if (res < 0) {
902 return NULL;
903 }
904 return wstr;
905#endif // !MS_WINDOWS
906
907#endif // !_Py_FORCE_UTF8_LOCALE
908}
909
910
911PyObject *
912_Py_GetLocaleEncodingObject(void)
913{
Victor Stinnere662c392020-11-01 23:07:23 +0100914 wchar_t *encoding = _Py_GetLocaleEncoding();
Victor Stinner82458b62020-11-01 20:59:35 +0100915 if (encoding == NULL) {
Victor Stinnere662c392020-11-01 23:07:23 +0100916 PyErr_NoMemory();
Victor Stinner82458b62020-11-01 20:59:35 +0100917 return NULL;
918 }
919
920 PyObject *str = PyUnicode_FromWideChar(encoding, -1);
921 PyMem_RawFree(encoding);
922 return str;
Victor Stinner710e8262020-10-31 01:02:09 +0100923}
924
925
Steve Dowerf2f373f2015-02-21 08:44:05 -0800926#ifdef MS_WINDOWS
927static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
928
929static void
930FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
931{
932 /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
933 /* Cannot simply cast and dereference in_ptr,
934 since it might not be aligned properly */
935 __int64 in;
936 memcpy(&in, in_ptr, sizeof(in));
937 *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
938 *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
939}
940
941void
Steve Dowerbf1f3762015-02-21 15:26:02 -0800942_Py_time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
Steve Dowerf2f373f2015-02-21 08:44:05 -0800943{
944 /* XXX endianness */
945 __int64 out;
946 out = time_in + secs_between_epochs;
947 out = out * 10000000 + nsec_in / 100;
948 memcpy(out_ptr, &out, sizeof(out));
949}
950
951/* Below, we *know* that ugo+r is 0444 */
952#if _S_IREAD != 0400
953#error Unsupported C library
954#endif
955static int
956attributes_to_mode(DWORD attr)
957{
958 int m = 0;
959 if (attr & FILE_ATTRIBUTE_DIRECTORY)
960 m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
961 else
962 m |= _S_IFREG;
963 if (attr & FILE_ATTRIBUTE_READONLY)
964 m |= 0444;
965 else
966 m |= 0666;
967 return m;
968}
969
Steve Dowerbf1f3762015-02-21 15:26:02 -0800970void
Victor Stinnere134a7f2015-03-30 10:09:31 +0200971_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
972 struct _Py_stat_struct *result)
Steve Dowerf2f373f2015-02-21 08:44:05 -0800973{
974 memset(result, 0, sizeof(*result));
975 result->st_mode = attributes_to_mode(info->dwFileAttributes);
976 result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
977 result->st_dev = info->dwVolumeSerialNumber;
978 result->st_rdev = result->st_dev;
979 FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
980 FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
981 FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
982 result->st_nlink = info->nNumberOfLinks;
Victor Stinner0f6d7332017-03-09 17:34:28 +0100983 result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700984 /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will
985 open other name surrogate reparse points without traversing them. To
986 detect/handle these, check st_file_attributes and st_reparse_tag. */
987 result->st_reparse_tag = reparse_tag;
988 if (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
989 reparse_tag == IO_REPARSE_TAG_SYMLINK) {
Steve Dowerf2f373f2015-02-21 08:44:05 -0800990 /* first clear the S_IFMT bits */
991 result->st_mode ^= (result->st_mode & S_IFMT);
992 /* now set the bits that make this a symlink */
993 result->st_mode |= S_IFLNK;
994 }
995 result->st_file_attributes = info->dwFileAttributes;
Steve Dowerf2f373f2015-02-21 08:44:05 -0800996}
997#endif
998
999/* Return information about a file.
1000
1001 On POSIX, use fstat().
1002
1003 On Windows, use GetFileType() and GetFileInformationByHandle() which support
Victor Stinner8c663fd2017-11-08 14:44:44 -08001004 files larger than 2 GiB. fstat() may fail with EOVERFLOW on files larger
1005 than 2 GiB because the file size type is a signed 32-bit integer: see issue
Steve Dowerf2f373f2015-02-21 08:44:05 -08001006 #23152.
Victor Stinnere134a7f2015-03-30 10:09:31 +02001007
1008 On Windows, set the last Windows error and return nonzero on error. On
1009 POSIX, set errno and return nonzero on error. Fill status and return 0 on
1010 success. */
Steve Dowerf2f373f2015-02-21 08:44:05 -08001011int
Victor Stinnere134a7f2015-03-30 10:09:31 +02001012_Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
Steve Dowerf2f373f2015-02-21 08:44:05 -08001013{
1014#ifdef MS_WINDOWS
1015 BY_HANDLE_FILE_INFORMATION info;
1016 HANDLE h;
1017 int type;
1018
Steve Dower940f33a2016-09-08 11:21:54 -07001019 _Py_BEGIN_SUPPRESS_IPH
1020 h = (HANDLE)_get_osfhandle(fd);
1021 _Py_END_SUPPRESS_IPH
Steve Dowerf2f373f2015-02-21 08:44:05 -08001022
1023 if (h == INVALID_HANDLE_VALUE) {
Steve Dower8fc89802015-04-12 00:26:27 -04001024 /* errno is already set by _get_osfhandle, but we also set
1025 the Win32 error for callers who expect that */
Steve Dower8acde7d2015-03-07 18:14:07 -08001026 SetLastError(ERROR_INVALID_HANDLE);
Steve Dowerf2f373f2015-02-21 08:44:05 -08001027 return -1;
1028 }
Victor Stinnere134a7f2015-03-30 10:09:31 +02001029 memset(status, 0, sizeof(*status));
Steve Dowerf2f373f2015-02-21 08:44:05 -08001030
1031 type = GetFileType(h);
1032 if (type == FILE_TYPE_UNKNOWN) {
1033 DWORD error = GetLastError();
Steve Dower8fc89802015-04-12 00:26:27 -04001034 if (error != 0) {
1035 errno = winerror_to_errno(error);
Steve Dowerf2f373f2015-02-21 08:44:05 -08001036 return -1;
Steve Dower8fc89802015-04-12 00:26:27 -04001037 }
Steve Dowerf2f373f2015-02-21 08:44:05 -08001038 /* else: valid but unknown file */
1039 }
1040
1041 if (type != FILE_TYPE_DISK) {
1042 if (type == FILE_TYPE_CHAR)
Victor Stinnere134a7f2015-03-30 10:09:31 +02001043 status->st_mode = _S_IFCHR;
Steve Dowerf2f373f2015-02-21 08:44:05 -08001044 else if (type == FILE_TYPE_PIPE)
Victor Stinnere134a7f2015-03-30 10:09:31 +02001045 status->st_mode = _S_IFIFO;
Steve Dowerf2f373f2015-02-21 08:44:05 -08001046 return 0;
1047 }
1048
1049 if (!GetFileInformationByHandle(h, &info)) {
Steve Dower8fc89802015-04-12 00:26:27 -04001050 /* The Win32 error is already set, but we also set errno for
1051 callers who expect it */
1052 errno = winerror_to_errno(GetLastError());
Steve Dowerf2f373f2015-02-21 08:44:05 -08001053 return -1;
1054 }
1055
Victor Stinnere134a7f2015-03-30 10:09:31 +02001056 _Py_attribute_data_to_stat(&info, 0, status);
Steve Dowerf2f373f2015-02-21 08:44:05 -08001057 /* specific to fstat() */
Victor Stinner0f6d7332017-03-09 17:34:28 +01001058 status->st_ino = (((uint64_t)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
Steve Dowerf2f373f2015-02-21 08:44:05 -08001059 return 0;
1060#else
Victor Stinnere134a7f2015-03-30 10:09:31 +02001061 return fstat(fd, status);
Steve Dowerf2f373f2015-02-21 08:44:05 -08001062#endif
1063}
Steve Dowerf2f373f2015-02-21 08:44:05 -08001064
Victor Stinnere134a7f2015-03-30 10:09:31 +02001065/* Return information about a file.
1066
1067 On POSIX, use fstat().
1068
1069 On Windows, use GetFileType() and GetFileInformationByHandle() which support
Victor Stinner8c663fd2017-11-08 14:44:44 -08001070 files larger than 2 GiB. fstat() may fail with EOVERFLOW on files larger
1071 than 2 GiB because the file size type is a signed 32-bit integer: see issue
Victor Stinnere134a7f2015-03-30 10:09:31 +02001072 #23152.
1073
1074 Raise an exception and return -1 on error. On Windows, set the last Windows
1075 error on error. On POSIX, set errno on error. Fill status and return 0 on
1076 success.
1077
Victor Stinner6f4fae82015-04-01 18:34:32 +02001078 Release the GIL to call GetFileType() and GetFileInformationByHandle(), or
1079 to call fstat(). The caller must hold the GIL. */
Victor Stinnere134a7f2015-03-30 10:09:31 +02001080int
1081_Py_fstat(int fd, struct _Py_stat_struct *status)
1082{
1083 int res;
1084
Victor Stinner8a1be612016-03-14 22:07:55 +01001085 assert(PyGILState_Check());
Victor Stinner8a1be612016-03-14 22:07:55 +01001086
Victor Stinnere134a7f2015-03-30 10:09:31 +02001087 Py_BEGIN_ALLOW_THREADS
1088 res = _Py_fstat_noraise(fd, status);
1089 Py_END_ALLOW_THREADS
1090
1091 if (res != 0) {
1092#ifdef MS_WINDOWS
1093 PyErr_SetFromWindowsErr(0);
1094#else
1095 PyErr_SetFromErrno(PyExc_OSError);
1096#endif
1097 return -1;
1098 }
1099 return 0;
1100}
Steve Dowerf2f373f2015-02-21 08:44:05 -08001101
Victor Stinner6672d0c2010-10-07 22:53:43 +00001102/* Call _wstat() on Windows, or encode the path to the filesystem encoding and
1103 call stat() otherwise. Only fill st_mode attribute on Windows.
1104
Victor Stinnerbd0850b2011-12-18 20:47:30 +01001105 Return 0 on success, -1 on _wstat() / stat() error, -2 if an exception was
1106 raised. */
Victor Stinner4e314432010-10-07 21:45:39 +00001107
1108int
Victor Stinnera4a75952010-10-07 22:23:10 +00001109_Py_stat(PyObject *path, struct stat *statbuf)
Victor Stinner4e314432010-10-07 21:45:39 +00001110{
1111#ifdef MS_WINDOWS
Victor Stinner4e314432010-10-07 21:45:39 +00001112 int err;
1113 struct _stat wstatbuf;
1114
Serhiy Storchaka4c8f09d2020-07-10 23:26:06 +03001115#if USE_UNICODE_WCHAR_CACHE
1116 const wchar_t *wpath = _PyUnicode_AsUnicode(path);
1117#else /* USE_UNICODE_WCHAR_CACHE */
1118 wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);
1119#endif /* USE_UNICODE_WCHAR_CACHE */
Victor Stinneree587ea2011-11-17 00:51:38 +01001120 if (wpath == NULL)
Victor Stinnerbd0850b2011-12-18 20:47:30 +01001121 return -2;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +03001122
Victor Stinneree587ea2011-11-17 00:51:38 +01001123 err = _wstat(wpath, &wstatbuf);
Victor Stinner4e314432010-10-07 21:45:39 +00001124 if (!err)
1125 statbuf->st_mode = wstatbuf.st_mode;
Serhiy Storchaka4c8f09d2020-07-10 23:26:06 +03001126#if !USE_UNICODE_WCHAR_CACHE
1127 PyMem_Free(wpath);
1128#endif /* USE_UNICODE_WCHAR_CACHE */
Victor Stinner4e314432010-10-07 21:45:39 +00001129 return err;
1130#else
1131 int ret;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +03001132 PyObject *bytes;
1133 char *cpath;
1134
1135 bytes = PyUnicode_EncodeFSDefault(path);
Victor Stinner4e314432010-10-07 21:45:39 +00001136 if (bytes == NULL)
Victor Stinnerbd0850b2011-12-18 20:47:30 +01001137 return -2;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +03001138
1139 /* check for embedded null bytes */
1140 if (PyBytes_AsStringAndSize(bytes, &cpath, NULL) == -1) {
1141 Py_DECREF(bytes);
1142 return -2;
1143 }
1144
1145 ret = stat(cpath, statbuf);
Victor Stinner4e314432010-10-07 21:45:39 +00001146 Py_DECREF(bytes);
1147 return ret;
1148#endif
1149}
1150
Victor Stinnerd45c7f82012-12-04 01:34:47 +01001151
Alexey Izbyshevc1e46e92018-02-06 09:09:34 +03001152/* This function MUST be kept async-signal-safe on POSIX when raise=0. */
Antoine Pitrou409b5382013-10-12 22:41:17 +02001153static int
Victor Stinnerdaf45552013-08-28 00:53:59 +02001154get_inheritable(int fd, int raise)
1155{
1156#ifdef MS_WINDOWS
1157 HANDLE handle;
1158 DWORD flags;
Victor Stinner6672d0c2010-10-07 22:53:43 +00001159
Steve Dower8fc89802015-04-12 00:26:27 -04001160 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02001161 handle = (HANDLE)_get_osfhandle(fd);
Steve Dower8fc89802015-04-12 00:26:27 -04001162 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02001163 if (handle == INVALID_HANDLE_VALUE) {
1164 if (raise)
Steve Dower41e72442015-03-14 11:38:27 -07001165 PyErr_SetFromErrno(PyExc_OSError);
Victor Stinnerdaf45552013-08-28 00:53:59 +02001166 return -1;
1167 }
1168
1169 if (!GetHandleInformation(handle, &flags)) {
1170 if (raise)
1171 PyErr_SetFromWindowsErr(0);
1172 return -1;
1173 }
1174
1175 return (flags & HANDLE_FLAG_INHERIT);
1176#else
1177 int flags;
1178
1179 flags = fcntl(fd, F_GETFD, 0);
1180 if (flags == -1) {
1181 if (raise)
1182 PyErr_SetFromErrno(PyExc_OSError);
1183 return -1;
1184 }
1185 return !(flags & FD_CLOEXEC);
1186#endif
1187}
1188
1189/* Get the inheritable flag of the specified file descriptor.
Victor Stinnerb034eee2013-09-07 10:36:04 +02001190 Return 1 if the file descriptor can be inherited, 0 if it cannot,
Victor Stinnerdaf45552013-08-28 00:53:59 +02001191 raise an exception and return -1 on error. */
1192int
1193_Py_get_inheritable(int fd)
1194{
1195 return get_inheritable(fd, 1);
1196}
1197
Alexey Izbyshevc1e46e92018-02-06 09:09:34 +03001198
1199/* This function MUST be kept async-signal-safe on POSIX when raise=0. */
Victor Stinnerdaf45552013-08-28 00:53:59 +02001200static int
1201set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
1202{
1203#ifdef MS_WINDOWS
1204 HANDLE handle;
1205 DWORD flags;
Victor Stinner282124b2014-09-02 11:41:04 +02001206#else
1207#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
1208 static int ioctl_works = -1;
Victor Stinnerdaf45552013-08-28 00:53:59 +02001209 int request;
1210 int err;
Victor Stinner282124b2014-09-02 11:41:04 +02001211#endif
Victor Stinnera858bbd2016-04-17 16:51:52 +02001212 int flags, new_flags;
Victor Stinnerdaf45552013-08-28 00:53:59 +02001213 int res;
1214#endif
1215
1216 /* atomic_flag_works can only be used to make the file descriptor
1217 non-inheritable */
1218 assert(!(atomic_flag_works != NULL && inheritable));
1219
1220 if (atomic_flag_works != NULL && !inheritable) {
1221 if (*atomic_flag_works == -1) {
Steve Dower41e72442015-03-14 11:38:27 -07001222 int isInheritable = get_inheritable(fd, raise);
1223 if (isInheritable == -1)
Victor Stinnerdaf45552013-08-28 00:53:59 +02001224 return -1;
Steve Dower41e72442015-03-14 11:38:27 -07001225 *atomic_flag_works = !isInheritable;
Victor Stinnerdaf45552013-08-28 00:53:59 +02001226 }
1227
1228 if (*atomic_flag_works)
1229 return 0;
1230 }
1231
1232#ifdef MS_WINDOWS
Steve Dower8fc89802015-04-12 00:26:27 -04001233 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02001234 handle = (HANDLE)_get_osfhandle(fd);
Steve Dower8fc89802015-04-12 00:26:27 -04001235 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02001236 if (handle == INVALID_HANDLE_VALUE) {
1237 if (raise)
Steve Dower41e72442015-03-14 11:38:27 -07001238 PyErr_SetFromErrno(PyExc_OSError);
Victor Stinnerdaf45552013-08-28 00:53:59 +02001239 return -1;
1240 }
1241
1242 if (inheritable)
1243 flags = HANDLE_FLAG_INHERIT;
1244 else
1245 flags = 0;
Zackery Spytz5be66602019-08-23 12:38:41 -06001246
1247 /* This check can be removed once support for Windows 7 ends. */
1248#define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && \
1249 GetFileType(handle) == FILE_TYPE_CHAR)
1250
1251 if (!CONSOLE_PSEUDOHANDLE(handle) &&
1252 !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
Victor Stinnerdaf45552013-08-28 00:53:59 +02001253 if (raise)
1254 PyErr_SetFromWindowsErr(0);
1255 return -1;
1256 }
Zackery Spytz5be66602019-08-23 12:38:41 -06001257#undef CONSOLE_PSEUDOHANDLE
Victor Stinnerdaf45552013-08-28 00:53:59 +02001258 return 0;
1259
Victor Stinnerdaf45552013-08-28 00:53:59 +02001260#else
Victor Stinner282124b2014-09-02 11:41:04 +02001261
1262#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
Alexey Izbyshevc1e46e92018-02-06 09:09:34 +03001263 if (ioctl_works != 0 && raise != 0) {
Victor Stinner282124b2014-09-02 11:41:04 +02001264 /* fast-path: ioctl() only requires one syscall */
Alexey Izbyshevc1e46e92018-02-06 09:09:34 +03001265 /* caveat: raise=0 is an indicator that we must be async-signal-safe
1266 * thus avoid using ioctl() so we skip the fast-path. */
Victor Stinner282124b2014-09-02 11:41:04 +02001267 if (inheritable)
1268 request = FIONCLEX;
1269 else
1270 request = FIOCLEX;
1271 err = ioctl(fd, request, NULL);
1272 if (!err) {
1273 ioctl_works = 1;
1274 return 0;
1275 }
1276
cptpcrd7dc71c42021-01-20 09:05:51 -05001277#ifdef __linux__
1278 if (errno == EBADF) {
1279 // On Linux, ioctl(FIOCLEX) will fail with EBADF for O_PATH file descriptors
1280 // Fall through to the fcntl() path
1281 }
1282 else
1283#endif
Victor Stinner3116cc42016-05-19 16:46:18 +02001284 if (errno != ENOTTY && errno != EACCES) {
Victor Stinner282124b2014-09-02 11:41:04 +02001285 if (raise)
1286 PyErr_SetFromErrno(PyExc_OSError);
1287 return -1;
1288 }
1289 else {
1290 /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for
1291 device". The ioctl is declared but not supported by the kernel.
1292 Remember that ioctl() doesn't work. It is the case on
Victor Stinner3116cc42016-05-19 16:46:18 +02001293 Illumos-based OS for example.
1294
1295 Issue #27057: When SELinux policy disallows ioctl it will fail
1296 with EACCES. While FIOCLEX is safe operation it may be
1297 unavailable because ioctl was denied altogether.
1298 This can be the case on Android. */
Victor Stinner282124b2014-09-02 11:41:04 +02001299 ioctl_works = 0;
1300 }
1301 /* fallback to fcntl() if ioctl() does not work */
1302 }
1303#endif
1304
1305 /* slow-path: fcntl() requires two syscalls */
Victor Stinnerdaf45552013-08-28 00:53:59 +02001306 flags = fcntl(fd, F_GETFD);
1307 if (flags < 0) {
1308 if (raise)
1309 PyErr_SetFromErrno(PyExc_OSError);
1310 return -1;
1311 }
1312
Victor Stinnera858bbd2016-04-17 16:51:52 +02001313 if (inheritable) {
1314 new_flags = flags & ~FD_CLOEXEC;
1315 }
1316 else {
1317 new_flags = flags | FD_CLOEXEC;
1318 }
1319
1320 if (new_flags == flags) {
1321 /* FD_CLOEXEC flag already set/cleared: nothing to do */
1322 return 0;
1323 }
1324
Xavier de Gayeec5d3cd2016-11-19 16:19:29 +01001325 res = fcntl(fd, F_SETFD, new_flags);
Victor Stinnerdaf45552013-08-28 00:53:59 +02001326 if (res < 0) {
1327 if (raise)
1328 PyErr_SetFromErrno(PyExc_OSError);
1329 return -1;
1330 }
1331 return 0;
1332#endif
1333}
1334
1335/* Make the file descriptor non-inheritable.
Victor Stinnerb034eee2013-09-07 10:36:04 +02001336 Return 0 on success, set errno and return -1 on error. */
Victor Stinnerdaf45552013-08-28 00:53:59 +02001337static int
1338make_non_inheritable(int fd)
1339{
1340 return set_inheritable(fd, 0, 0, NULL);
1341}
1342
1343/* Set the inheritable flag of the specified file descriptor.
Alexey Izbyshevc1e46e92018-02-06 09:09:34 +03001344 On success: return 0, on error: raise an exception and return -1.
Victor Stinnerdaf45552013-08-28 00:53:59 +02001345
1346 If atomic_flag_works is not NULL:
1347
1348 * if *atomic_flag_works==-1, check if the inheritable is set on the file
1349 descriptor: if yes, set *atomic_flag_works to 1, otherwise set to 0 and
1350 set the inheritable flag
1351 * if *atomic_flag_works==1: do nothing
1352 * if *atomic_flag_works==0: set inheritable flag to False
1353
1354 Set atomic_flag_works to NULL if no atomic flag was used to create the
1355 file descriptor.
1356
1357 atomic_flag_works can only be used to make a file descriptor
1358 non-inheritable: atomic_flag_works must be NULL if inheritable=1. */
1359int
1360_Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works)
1361{
1362 return set_inheritable(fd, inheritable, 1, atomic_flag_works);
1363}
1364
Alexey Izbyshevc1e46e92018-02-06 09:09:34 +03001365/* Same as _Py_set_inheritable() but on error, set errno and
1366 don't raise an exception.
1367 This function is async-signal-safe. */
1368int
1369_Py_set_inheritable_async_safe(int fd, int inheritable, int *atomic_flag_works)
1370{
1371 return set_inheritable(fd, inheritable, 0, atomic_flag_works);
1372}
1373
Victor Stinnera555cfc2015-03-18 00:22:14 +01001374static int
1375_Py_open_impl(const char *pathname, int flags, int gil_held)
Victor Stinnerdaf45552013-08-28 00:53:59 +02001376{
1377 int fd;
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001378 int async_err = 0;
Victor Stinnera555cfc2015-03-18 00:22:14 +01001379#ifndef MS_WINDOWS
Victor Stinnerdaf45552013-08-28 00:53:59 +02001380 int *atomic_flag_works;
Victor Stinnera555cfc2015-03-18 00:22:14 +01001381#endif
1382
1383#ifdef MS_WINDOWS
1384 flags |= O_NOINHERIT;
1385#elif defined(O_CLOEXEC)
Victor Stinnerdaf45552013-08-28 00:53:59 +02001386 atomic_flag_works = &_Py_open_cloexec_works;
1387 flags |= O_CLOEXEC;
1388#else
1389 atomic_flag_works = NULL;
1390#endif
Victor Stinnerdaf45552013-08-28 00:53:59 +02001391
Victor Stinnera555cfc2015-03-18 00:22:14 +01001392 if (gil_held) {
Serhiy Storchaka6c6810d2020-06-24 08:46:05 +03001393 PyObject *pathname_obj = PyUnicode_DecodeFSDefault(pathname);
1394 if (pathname_obj == NULL) {
1395 return -1;
1396 }
1397 if (PySys_Audit("open", "OOi", pathname_obj, Py_None, flags) < 0) {
1398 Py_DECREF(pathname_obj);
Steve Dowerb82e17e2019-05-23 08:45:22 -07001399 return -1;
1400 }
1401
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001402 do {
1403 Py_BEGIN_ALLOW_THREADS
1404 fd = open(pathname, flags);
1405 Py_END_ALLOW_THREADS
1406 } while (fd < 0
1407 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
Serhiy Storchaka6c6810d2020-06-24 08:46:05 +03001408 if (async_err) {
1409 Py_DECREF(pathname_obj);
Victor Stinnera555cfc2015-03-18 00:22:14 +01001410 return -1;
1411 }
Serhiy Storchaka6c6810d2020-06-24 08:46:05 +03001412 if (fd < 0) {
1413 PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, pathname_obj, NULL);
1414 Py_DECREF(pathname_obj);
1415 return -1;
1416 }
1417 Py_DECREF(pathname_obj);
Victor Stinnera555cfc2015-03-18 00:22:14 +01001418 }
1419 else {
1420 fd = open(pathname, flags);
1421 if (fd < 0)
1422 return -1;
1423 }
1424
1425#ifndef MS_WINDOWS
1426 if (set_inheritable(fd, 0, gil_held, atomic_flag_works) < 0) {
Victor Stinnerdaf45552013-08-28 00:53:59 +02001427 close(fd);
1428 return -1;
1429 }
Victor Stinnera555cfc2015-03-18 00:22:14 +01001430#endif
1431
Victor Stinnerdaf45552013-08-28 00:53:59 +02001432 return fd;
1433}
1434
Victor Stinnera555cfc2015-03-18 00:22:14 +01001435/* Open a file with the specified flags (wrapper to open() function).
1436 Return a file descriptor on success. Raise an exception and return -1 on
1437 error.
1438
1439 The file descriptor is created non-inheritable.
1440
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001441 When interrupted by a signal (open() fails with EINTR), retry the syscall,
1442 except if the Python signal handler raises an exception.
1443
Victor Stinner6f4fae82015-04-01 18:34:32 +02001444 Release the GIL to call open(). The caller must hold the GIL. */
Victor Stinnera555cfc2015-03-18 00:22:14 +01001445int
1446_Py_open(const char *pathname, int flags)
1447{
1448 /* _Py_open() must be called with the GIL held. */
1449 assert(PyGILState_Check());
1450 return _Py_open_impl(pathname, flags, 1);
1451}
1452
1453/* Open a file with the specified flags (wrapper to open() function).
1454 Return a file descriptor on success. Set errno and return -1 on error.
1455
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001456 The file descriptor is created non-inheritable.
1457
1458 If interrupted by a signal, fail with EINTR. */
Victor Stinnera555cfc2015-03-18 00:22:14 +01001459int
1460_Py_open_noraise(const char *pathname, int flags)
1461{
1462 return _Py_open_impl(pathname, flags, 0);
1463}
1464
Victor Stinnerdaf45552013-08-28 00:53:59 +02001465/* Open a file. Use _wfopen() on Windows, encode the path to the locale
Victor Stinnere42ccd22015-03-18 01:39:23 +01001466 encoding and use fopen() otherwise.
1467
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001468 The file descriptor is created non-inheritable.
1469
1470 If interrupted by a signal, fail with EINTR. */
Victor Stinner4e314432010-10-07 21:45:39 +00001471FILE *
1472_Py_wfopen(const wchar_t *path, const wchar_t *mode)
1473{
Victor Stinner4e314432010-10-07 21:45:39 +00001474 FILE *f;
Steve Dowerb82e17e2019-05-23 08:45:22 -07001475 if (PySys_Audit("open", "uui", path, mode, 0) < 0) {
1476 return NULL;
1477 }
Victor Stinnerdaf45552013-08-28 00:53:59 +02001478#ifndef MS_WINDOWS
Victor Stinner4e314432010-10-07 21:45:39 +00001479 char *cpath;
1480 char cmode[10];
1481 size_t r;
1482 r = wcstombs(cmode, mode, 10);
Victor Stinner99768342021-03-17 21:46:53 +01001483 if (r == DECODE_ERROR || r >= 10) {
Victor Stinner4e314432010-10-07 21:45:39 +00001484 errno = EINVAL;
1485 return NULL;
1486 }
Victor Stinner9dd76202017-12-21 16:20:32 +01001487 cpath = _Py_EncodeLocaleRaw(path, NULL);
1488 if (cpath == NULL) {
Victor Stinner4e314432010-10-07 21:45:39 +00001489 return NULL;
Victor Stinner9dd76202017-12-21 16:20:32 +01001490 }
Victor Stinner4e314432010-10-07 21:45:39 +00001491 f = fopen(cpath, cmode);
Victor Stinner9dd76202017-12-21 16:20:32 +01001492 PyMem_RawFree(cpath);
Victor Stinner4e314432010-10-07 21:45:39 +00001493#else
Victor Stinnerdaf45552013-08-28 00:53:59 +02001494 f = _wfopen(path, mode);
Victor Stinner4e314432010-10-07 21:45:39 +00001495#endif
Victor Stinnerdaf45552013-08-28 00:53:59 +02001496 if (f == NULL)
1497 return NULL;
1498 if (make_non_inheritable(fileno(f)) < 0) {
1499 fclose(f);
1500 return NULL;
1501 }
1502 return f;
Victor Stinner4e314432010-10-07 21:45:39 +00001503}
1504
Victor Stinnerdaf45552013-08-28 00:53:59 +02001505
1506/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
Victor Stinnere42ccd22015-03-18 01:39:23 +01001507 encoding and call fopen() otherwise.
Victor Stinner6672d0c2010-10-07 22:53:43 +00001508
Victor Stinnere42ccd22015-03-18 01:39:23 +01001509 Return the new file object on success. Raise an exception and return NULL
1510 on error.
1511
1512 The file descriptor is created non-inheritable.
1513
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001514 When interrupted by a signal (open() fails with EINTR), retry the syscall,
1515 except if the Python signal handler raises an exception.
1516
Victor Stinner6f4fae82015-04-01 18:34:32 +02001517 Release the GIL to call _wfopen() or fopen(). The caller must hold
1518 the GIL. */
Victor Stinner4e314432010-10-07 21:45:39 +00001519FILE*
Victor Stinnerdaf45552013-08-28 00:53:59 +02001520_Py_fopen_obj(PyObject *path, const char *mode)
Victor Stinner4e314432010-10-07 21:45:39 +00001521{
Victor Stinnerdaf45552013-08-28 00:53:59 +02001522 FILE *f;
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001523 int async_err = 0;
Victor Stinner4e314432010-10-07 21:45:39 +00001524#ifdef MS_WINDOWS
Victor Stinner4e314432010-10-07 21:45:39 +00001525 wchar_t wmode[10];
1526 int usize;
Victor Stinner4e314432010-10-07 21:45:39 +00001527
Victor Stinnere42ccd22015-03-18 01:39:23 +01001528 assert(PyGILState_Check());
1529
Steve Dowerb82e17e2019-05-23 08:45:22 -07001530 if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
1531 return NULL;
1532 }
Antoine Pitrou0e576f12011-12-22 10:03:38 +01001533 if (!PyUnicode_Check(path)) {
1534 PyErr_Format(PyExc_TypeError,
1535 "str file path expected under Windows, got %R",
1536 Py_TYPE(path));
1537 return NULL;
1538 }
Serhiy Storchaka4c8f09d2020-07-10 23:26:06 +03001539#if USE_UNICODE_WCHAR_CACHE
1540 const wchar_t *wpath = _PyUnicode_AsUnicode(path);
1541#else /* USE_UNICODE_WCHAR_CACHE */
1542 wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);
1543#endif /* USE_UNICODE_WCHAR_CACHE */
Victor Stinneree587ea2011-11-17 00:51:38 +01001544 if (wpath == NULL)
1545 return NULL;
1546
Alexey Izbyshevb3b4a9d2018-02-18 20:57:24 +03001547 usize = MultiByteToWideChar(CP_ACP, 0, mode, -1,
1548 wmode, Py_ARRAY_LENGTH(wmode));
Victor Stinnere42ccd22015-03-18 01:39:23 +01001549 if (usize == 0) {
1550 PyErr_SetFromWindowsErr(0);
Serhiy Storchaka4c8f09d2020-07-10 23:26:06 +03001551#if !USE_UNICODE_WCHAR_CACHE
1552 PyMem_Free(wpath);
1553#endif /* USE_UNICODE_WCHAR_CACHE */
Victor Stinner4e314432010-10-07 21:45:39 +00001554 return NULL;
Victor Stinnere42ccd22015-03-18 01:39:23 +01001555 }
Victor Stinner4e314432010-10-07 21:45:39 +00001556
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001557 do {
1558 Py_BEGIN_ALLOW_THREADS
1559 f = _wfopen(wpath, wmode);
1560 Py_END_ALLOW_THREADS
1561 } while (f == NULL
1562 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
Serhiy Storchaka4c8f09d2020-07-10 23:26:06 +03001563#if !USE_UNICODE_WCHAR_CACHE
1564 PyMem_Free(wpath);
1565#endif /* USE_UNICODE_WCHAR_CACHE */
Victor Stinner4e314432010-10-07 21:45:39 +00001566#else
Antoine Pitrou2b1cc892011-12-19 18:19:06 +01001567 PyObject *bytes;
Serhiy Storchaka8f87eef2020-04-12 14:58:27 +03001568 const char *path_bytes;
Victor Stinnere42ccd22015-03-18 01:39:23 +01001569
1570 assert(PyGILState_Check());
1571
Antoine Pitrou2b1cc892011-12-19 18:19:06 +01001572 if (!PyUnicode_FSConverter(path, &bytes))
Victor Stinner4e314432010-10-07 21:45:39 +00001573 return NULL;
Victor Stinnere42ccd22015-03-18 01:39:23 +01001574 path_bytes = PyBytes_AS_STRING(bytes);
1575
Steve Dowerb82e17e2019-05-23 08:45:22 -07001576 if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
Christian Heimes96729122020-06-13 17:57:22 +02001577 Py_DECREF(bytes);
Steve Dowerb82e17e2019-05-23 08:45:22 -07001578 return NULL;
1579 }
1580
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001581 do {
1582 Py_BEGIN_ALLOW_THREADS
1583 f = fopen(path_bytes, mode);
1584 Py_END_ALLOW_THREADS
1585 } while (f == NULL
1586 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
Victor Stinnere42ccd22015-03-18 01:39:23 +01001587
Victor Stinner4e314432010-10-07 21:45:39 +00001588 Py_DECREF(bytes);
Victor Stinner4e314432010-10-07 21:45:39 +00001589#endif
Victor Stinnera47fc5c2015-03-18 09:52:54 +01001590 if (async_err)
1591 return NULL;
1592
Victor Stinnere42ccd22015-03-18 01:39:23 +01001593 if (f == NULL) {
1594 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
Victor Stinnerdaf45552013-08-28 00:53:59 +02001595 return NULL;
Victor Stinnere42ccd22015-03-18 01:39:23 +01001596 }
1597
1598 if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
Victor Stinnerdaf45552013-08-28 00:53:59 +02001599 fclose(f);
1600 return NULL;
1601 }
1602 return f;
Victor Stinner4e314432010-10-07 21:45:39 +00001603}
1604
Victor Stinner66aab0c2015-03-19 22:53:20 +01001605/* Read count bytes from fd into buf.
Victor Stinner82c3e452015-04-01 18:34:45 +02001606
1607 On success, return the number of read bytes, it can be lower than count.
1608 If the current file offset is at or past the end of file, no bytes are read,
1609 and read() returns zero.
1610
1611 On error, raise an exception, set errno and return -1.
1612
1613 When interrupted by a signal (read() fails with EINTR), retry the syscall.
1614 If the Python signal handler raises an exception, the function returns -1
1615 (the syscall is not retried).
1616
1617 Release the GIL to call read(). The caller must hold the GIL. */
Victor Stinner66aab0c2015-03-19 22:53:20 +01001618Py_ssize_t
1619_Py_read(int fd, void *buf, size_t count)
1620{
1621 Py_ssize_t n;
Victor Stinnera3c02022015-03-20 11:58:18 +01001622 int err;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001623 int async_err = 0;
1624
Victor Stinner8a1be612016-03-14 22:07:55 +01001625 assert(PyGILState_Check());
Victor Stinner8a1be612016-03-14 22:07:55 +01001626
Victor Stinner66aab0c2015-03-19 22:53:20 +01001627 /* _Py_read() must not be called with an exception set, otherwise the
1628 * caller may think that read() was interrupted by a signal and the signal
1629 * handler raised an exception. */
1630 assert(!PyErr_Occurred());
1631
Stéphane Wirtel74a8b6e2018-10-18 01:05:04 +02001632 if (count > _PY_READ_MAX) {
1633 count = _PY_READ_MAX;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001634 }
Victor Stinner66aab0c2015-03-19 22:53:20 +01001635
Steve Dower8fc89802015-04-12 00:26:27 -04001636 _Py_BEGIN_SUPPRESS_IPH
Victor Stinner66aab0c2015-03-19 22:53:20 +01001637 do {
1638 Py_BEGIN_ALLOW_THREADS
1639 errno = 0;
1640#ifdef MS_WINDOWS
1641 n = read(fd, buf, (int)count);
1642#else
1643 n = read(fd, buf, count);
1644#endif
Victor Stinnera3c02022015-03-20 11:58:18 +01001645 /* save/restore errno because PyErr_CheckSignals()
1646 * and PyErr_SetFromErrno() can modify it */
1647 err = errno;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001648 Py_END_ALLOW_THREADS
Victor Stinnera3c02022015-03-20 11:58:18 +01001649 } while (n < 0 && err == EINTR &&
Victor Stinner66aab0c2015-03-19 22:53:20 +01001650 !(async_err = PyErr_CheckSignals()));
Steve Dower8fc89802015-04-12 00:26:27 -04001651 _Py_END_SUPPRESS_IPH
Victor Stinner66aab0c2015-03-19 22:53:20 +01001652
1653 if (async_err) {
1654 /* read() was interrupted by a signal (failed with EINTR)
1655 * and the Python signal handler raised an exception */
Victor Stinnera3c02022015-03-20 11:58:18 +01001656 errno = err;
1657 assert(errno == EINTR && PyErr_Occurred());
Victor Stinner66aab0c2015-03-19 22:53:20 +01001658 return -1;
1659 }
1660 if (n < 0) {
Victor Stinner66aab0c2015-03-19 22:53:20 +01001661 PyErr_SetFromErrno(PyExc_OSError);
Victor Stinnera3c02022015-03-20 11:58:18 +01001662 errno = err;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001663 return -1;
1664 }
1665
1666 return n;
1667}
1668
Victor Stinner82c3e452015-04-01 18:34:45 +02001669static Py_ssize_t
1670_Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
Victor Stinner66aab0c2015-03-19 22:53:20 +01001671{
1672 Py_ssize_t n;
Victor Stinnera3c02022015-03-20 11:58:18 +01001673 int err;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001674 int async_err = 0;
1675
Steve Dower8fc89802015-04-12 00:26:27 -04001676 _Py_BEGIN_SUPPRESS_IPH
Victor Stinner66aab0c2015-03-19 22:53:20 +01001677#ifdef MS_WINDOWS
1678 if (count > 32767 && isatty(fd)) {
1679 /* Issue #11395: the Windows console returns an error (12: not
1680 enough space error) on writing into stdout if stdout mode is
1681 binary and the length is greater than 66,000 bytes (or less,
1682 depending on heap usage). */
1683 count = 32767;
1684 }
Victor Stinner66aab0c2015-03-19 22:53:20 +01001685#endif
Stéphane Wirtel74a8b6e2018-10-18 01:05:04 +02001686 if (count > _PY_WRITE_MAX) {
1687 count = _PY_WRITE_MAX;
1688 }
Victor Stinner66aab0c2015-03-19 22:53:20 +01001689
Victor Stinner82c3e452015-04-01 18:34:45 +02001690 if (gil_held) {
1691 do {
1692 Py_BEGIN_ALLOW_THREADS
1693 errno = 0;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001694#ifdef MS_WINDOWS
Victor Stinner82c3e452015-04-01 18:34:45 +02001695 n = write(fd, buf, (int)count);
Victor Stinner66aab0c2015-03-19 22:53:20 +01001696#else
Victor Stinner82c3e452015-04-01 18:34:45 +02001697 n = write(fd, buf, count);
Victor Stinner66aab0c2015-03-19 22:53:20 +01001698#endif
Victor Stinner82c3e452015-04-01 18:34:45 +02001699 /* save/restore errno because PyErr_CheckSignals()
1700 * and PyErr_SetFromErrno() can modify it */
1701 err = errno;
1702 Py_END_ALLOW_THREADS
1703 } while (n < 0 && err == EINTR &&
1704 !(async_err = PyErr_CheckSignals()));
1705 }
1706 else {
1707 do {
1708 errno = 0;
1709#ifdef MS_WINDOWS
1710 n = write(fd, buf, (int)count);
1711#else
1712 n = write(fd, buf, count);
1713#endif
1714 err = errno;
1715 } while (n < 0 && err == EINTR);
1716 }
Steve Dower8fc89802015-04-12 00:26:27 -04001717 _Py_END_SUPPRESS_IPH
Victor Stinner66aab0c2015-03-19 22:53:20 +01001718
1719 if (async_err) {
1720 /* write() was interrupted by a signal (failed with EINTR)
Victor Stinner82c3e452015-04-01 18:34:45 +02001721 and the Python signal handler raised an exception (if gil_held is
1722 nonzero). */
Victor Stinnera3c02022015-03-20 11:58:18 +01001723 errno = err;
Victor Stinner82c3e452015-04-01 18:34:45 +02001724 assert(errno == EINTR && (!gil_held || PyErr_Occurred()));
Victor Stinner66aab0c2015-03-19 22:53:20 +01001725 return -1;
1726 }
1727 if (n < 0) {
Victor Stinner82c3e452015-04-01 18:34:45 +02001728 if (gil_held)
1729 PyErr_SetFromErrno(PyExc_OSError);
Victor Stinnera3c02022015-03-20 11:58:18 +01001730 errno = err;
Victor Stinner66aab0c2015-03-19 22:53:20 +01001731 return -1;
1732 }
1733
1734 return n;
1735}
1736
Victor Stinner82c3e452015-04-01 18:34:45 +02001737/* Write count bytes of buf into fd.
1738
1739 On success, return the number of written bytes, it can be lower than count
1740 including 0. On error, raise an exception, set errno and return -1.
1741
1742 When interrupted by a signal (write() fails with EINTR), retry the syscall.
1743 If the Python signal handler raises an exception, the function returns -1
1744 (the syscall is not retried).
1745
1746 Release the GIL to call write(). The caller must hold the GIL. */
1747Py_ssize_t
1748_Py_write(int fd, const void *buf, size_t count)
1749{
Victor Stinner8a1be612016-03-14 22:07:55 +01001750 assert(PyGILState_Check());
Victor Stinner8a1be612016-03-14 22:07:55 +01001751
Victor Stinner82c3e452015-04-01 18:34:45 +02001752 /* _Py_write() must not be called with an exception set, otherwise the
1753 * caller may think that write() was interrupted by a signal and the signal
1754 * handler raised an exception. */
1755 assert(!PyErr_Occurred());
1756
1757 return _Py_write_impl(fd, buf, count, 1);
1758}
1759
1760/* Write count bytes of buf into fd.
1761 *
1762 * On success, return the number of written bytes, it can be lower than count
1763 * including 0. On error, set errno and return -1.
1764 *
1765 * When interrupted by a signal (write() fails with EINTR), retry the syscall
1766 * without calling the Python signal handler. */
1767Py_ssize_t
1768_Py_write_noraise(int fd, const void *buf, size_t count)
1769{
1770 return _Py_write_impl(fd, buf, count, 0);
1771}
1772
Victor Stinner4e314432010-10-07 21:45:39 +00001773#ifdef HAVE_READLINK
Victor Stinner6672d0c2010-10-07 22:53:43 +00001774
1775/* Read value of symbolic link. Encode the path to the locale encoding, decode
Victor Stinner1be0d112019-03-18 17:47:26 +01001776 the result from the locale encoding.
Victor Stinner6672d0c2010-10-07 22:53:43 +00001777
Victor Stinner1be0d112019-03-18 17:47:26 +01001778 Return -1 on encoding error, on readlink() error, if the internal buffer is
1779 too short, on decoding error, or if 'buf' is too short. */
Victor Stinner4e314432010-10-07 21:45:39 +00001780int
Victor Stinner1be0d112019-03-18 17:47:26 +01001781_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t buflen)
Victor Stinner4e314432010-10-07 21:45:39 +00001782{
1783 char *cpath;
Victor Stinnerb11d6cb2013-11-15 18:14:11 +01001784 char cbuf[MAXPATHLEN];
Victor Stinner03a8a562019-10-04 02:22:39 +02001785 size_t cbuf_len = Py_ARRAY_LENGTH(cbuf);
Victor Stinner3f711f42010-10-16 22:47:37 +00001786 wchar_t *wbuf;
Victor Stinner03a8a562019-10-04 02:22:39 +02001787 Py_ssize_t res;
Victor Stinner4e314432010-10-07 21:45:39 +00001788 size_t r1;
1789
Victor Stinner9dd76202017-12-21 16:20:32 +01001790 cpath = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner4e314432010-10-07 21:45:39 +00001791 if (cpath == NULL) {
1792 errno = EINVAL;
1793 return -1;
1794 }
Victor Stinner03a8a562019-10-04 02:22:39 +02001795 res = readlink(cpath, cbuf, cbuf_len);
Victor Stinner9dd76202017-12-21 16:20:32 +01001796 PyMem_RawFree(cpath);
Victor Stinner03a8a562019-10-04 02:22:39 +02001797 if (res == -1) {
Victor Stinner4e314432010-10-07 21:45:39 +00001798 return -1;
Victor Stinner03a8a562019-10-04 02:22:39 +02001799 }
1800 if ((size_t)res == cbuf_len) {
Victor Stinner4e314432010-10-07 21:45:39 +00001801 errno = EINVAL;
1802 return -1;
1803 }
1804 cbuf[res] = '\0'; /* buf will be null terminated */
Victor Stinnerf6a271a2014-08-01 12:28:48 +02001805 wbuf = Py_DecodeLocale(cbuf, &r1);
Victor Stinner350147b2010-10-16 22:52:09 +00001806 if (wbuf == NULL) {
1807 errno = EINVAL;
1808 return -1;
1809 }
Victor Stinner1be0d112019-03-18 17:47:26 +01001810 /* wbuf must have space to store the trailing NUL character */
1811 if (buflen <= r1) {
Victor Stinner1a7425f2013-07-07 16:25:15 +02001812 PyMem_RawFree(wbuf);
Victor Stinner4e314432010-10-07 21:45:39 +00001813 errno = EINVAL;
1814 return -1;
1815 }
Victor Stinner1be0d112019-03-18 17:47:26 +01001816 wcsncpy(buf, wbuf, buflen);
Victor Stinner1a7425f2013-07-07 16:25:15 +02001817 PyMem_RawFree(wbuf);
Victor Stinner4e314432010-10-07 21:45:39 +00001818 return (int)r1;
1819}
1820#endif
1821
1822#ifdef HAVE_REALPATH
Victor Stinner6672d0c2010-10-07 22:53:43 +00001823
1824/* Return the canonicalized absolute pathname. Encode path to the locale
Victor Stinneraf02e1c2011-12-16 23:56:01 +01001825 encoding, decode the result from the locale encoding.
Victor Stinner6672d0c2010-10-07 22:53:43 +00001826
Victor Stinner1be0d112019-03-18 17:47:26 +01001827 Return NULL on encoding error, realpath() error, decoding error
1828 or if 'resolved_path' is too short. */
Victor Stinner4e314432010-10-07 21:45:39 +00001829wchar_t*
Victor Stinner015f4d82010-10-07 22:29:53 +00001830_Py_wrealpath(const wchar_t *path,
Victor Stinner1be0d112019-03-18 17:47:26 +01001831 wchar_t *resolved_path, size_t resolved_path_len)
Victor Stinner4e314432010-10-07 21:45:39 +00001832{
1833 char *cpath;
Victor Stinnerb11d6cb2013-11-15 18:14:11 +01001834 char cresolved_path[MAXPATHLEN];
Victor Stinner0a1b8cb2010-10-16 22:55:47 +00001835 wchar_t *wresolved_path;
Victor Stinner4e314432010-10-07 21:45:39 +00001836 char *res;
1837 size_t r;
Victor Stinner9dd76202017-12-21 16:20:32 +01001838 cpath = _Py_EncodeLocaleRaw(path, NULL);
Victor Stinner4e314432010-10-07 21:45:39 +00001839 if (cpath == NULL) {
1840 errno = EINVAL;
1841 return NULL;
1842 }
1843 res = realpath(cpath, cresolved_path);
Victor Stinner9dd76202017-12-21 16:20:32 +01001844 PyMem_RawFree(cpath);
Victor Stinner4e314432010-10-07 21:45:39 +00001845 if (res == NULL)
1846 return NULL;
Victor Stinner0a1b8cb2010-10-16 22:55:47 +00001847
Victor Stinnerf6a271a2014-08-01 12:28:48 +02001848 wresolved_path = Py_DecodeLocale(cresolved_path, &r);
Victor Stinner0a1b8cb2010-10-16 22:55:47 +00001849 if (wresolved_path == NULL) {
Victor Stinner4e314432010-10-07 21:45:39 +00001850 errno = EINVAL;
1851 return NULL;
1852 }
Victor Stinner1be0d112019-03-18 17:47:26 +01001853 /* wresolved_path must have space to store the trailing NUL character */
1854 if (resolved_path_len <= r) {
Victor Stinner1a7425f2013-07-07 16:25:15 +02001855 PyMem_RawFree(wresolved_path);
Victor Stinner0a1b8cb2010-10-16 22:55:47 +00001856 errno = EINVAL;
1857 return NULL;
1858 }
Victor Stinner1be0d112019-03-18 17:47:26 +01001859 wcsncpy(resolved_path, wresolved_path, resolved_path_len);
Victor Stinner1a7425f2013-07-07 16:25:15 +02001860 PyMem_RawFree(wresolved_path);
Victor Stinner4e314432010-10-07 21:45:39 +00001861 return resolved_path;
1862}
1863#endif
1864
Victor Stinner3939c322019-06-25 15:02:43 +02001865
1866#ifndef MS_WINDOWS
1867int
1868_Py_isabs(const wchar_t *path)
1869{
1870 return (path[0] == SEP);
1871}
1872#endif
1873
1874
1875/* Get an absolute path.
1876 On error (ex: fail to get the current directory), return -1.
1877 On memory allocation failure, set *abspath_p to NULL and return 0.
1878 On success, return a newly allocated to *abspath_p to and return 0.
1879 The string must be freed by PyMem_RawFree(). */
1880int
1881_Py_abspath(const wchar_t *path, wchar_t **abspath_p)
1882{
1883#ifdef MS_WINDOWS
1884 wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
1885 DWORD result;
1886
1887 result = GetFullPathNameW(path,
1888 Py_ARRAY_LENGTH(woutbuf), woutbuf,
1889 NULL);
1890 if (!result) {
1891 return -1;
1892 }
1893
1894 if (result > Py_ARRAY_LENGTH(woutbuf)) {
1895 if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
1896 woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
1897 }
1898 else {
1899 woutbufp = NULL;
1900 }
1901 if (!woutbufp) {
1902 *abspath_p = NULL;
1903 return 0;
1904 }
1905
1906 result = GetFullPathNameW(path, result, woutbufp, NULL);
1907 if (!result) {
1908 PyMem_RawFree(woutbufp);
1909 return -1;
1910 }
1911 }
1912
1913 if (woutbufp != woutbuf) {
1914 *abspath_p = woutbufp;
1915 return 0;
1916 }
1917
1918 *abspath_p = _PyMem_RawWcsdup(woutbufp);
1919 return 0;
1920#else
1921 if (_Py_isabs(path)) {
1922 *abspath_p = _PyMem_RawWcsdup(path);
1923 return 0;
1924 }
1925
1926 wchar_t cwd[MAXPATHLEN + 1];
1927 cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0;
1928 if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) {
1929 /* unable to get the current directory */
1930 return -1;
1931 }
1932
1933 size_t cwd_len = wcslen(cwd);
1934 size_t path_len = wcslen(path);
1935 size_t len = cwd_len + 1 + path_len + 1;
1936 if (len <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
1937 *abspath_p = PyMem_RawMalloc(len * sizeof(wchar_t));
1938 }
1939 else {
1940 *abspath_p = NULL;
1941 }
1942 if (*abspath_p == NULL) {
1943 return 0;
1944 }
1945
1946 wchar_t *abspath = *abspath_p;
1947 memcpy(abspath, cwd, cwd_len * sizeof(wchar_t));
1948 abspath += cwd_len;
1949
1950 *abspath = (wchar_t)SEP;
1951 abspath++;
1952
1953 memcpy(abspath, path, path_len * sizeof(wchar_t));
1954 abspath += path_len;
1955
1956 *abspath = 0;
1957 return 0;
1958#endif
1959}
1960
1961
Victor Stinnerfaddaed2019-03-19 02:58:14 +01001962/* Get the current directory. buflen is the buffer size in wide characters
Victor Stinneraf02e1c2011-12-16 23:56:01 +01001963 including the null character. Decode the path from the locale encoding.
Victor Stinner6672d0c2010-10-07 22:53:43 +00001964
Victor Stinner1be0d112019-03-18 17:47:26 +01001965 Return NULL on getcwd() error, on decoding error, or if 'buf' is
1966 too short. */
Victor Stinner4e314432010-10-07 21:45:39 +00001967wchar_t*
Victor Stinner1be0d112019-03-18 17:47:26 +01001968_Py_wgetcwd(wchar_t *buf, size_t buflen)
Victor Stinner4e314432010-10-07 21:45:39 +00001969{
1970#ifdef MS_WINDOWS
Victor Stinner1be0d112019-03-18 17:47:26 +01001971 int ibuflen = (int)Py_MIN(buflen, INT_MAX);
1972 return _wgetcwd(buf, ibuflen);
Victor Stinner4e314432010-10-07 21:45:39 +00001973#else
Victor Stinnerb11d6cb2013-11-15 18:14:11 +01001974 char fname[MAXPATHLEN];
Victor Stinnerf4061da2010-10-14 12:37:19 +00001975 wchar_t *wname;
Victor Stinner168e1172010-10-16 23:16:16 +00001976 size_t len;
Victor Stinnerf4061da2010-10-14 12:37:19 +00001977
Victor Stinnerb11d6cb2013-11-15 18:14:11 +01001978 if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL)
Victor Stinner4e314432010-10-07 21:45:39 +00001979 return NULL;
Victor Stinnerf6a271a2014-08-01 12:28:48 +02001980 wname = Py_DecodeLocale(fname, &len);
Victor Stinnerf4061da2010-10-14 12:37:19 +00001981 if (wname == NULL)
1982 return NULL;
Victor Stinner1be0d112019-03-18 17:47:26 +01001983 /* wname must have space to store the trailing NUL character */
1984 if (buflen <= len) {
Victor Stinner1a7425f2013-07-07 16:25:15 +02001985 PyMem_RawFree(wname);
Victor Stinner4e314432010-10-07 21:45:39 +00001986 return NULL;
1987 }
Victor Stinner1be0d112019-03-18 17:47:26 +01001988 wcsncpy(buf, wname, buflen);
Victor Stinner1a7425f2013-07-07 16:25:15 +02001989 PyMem_RawFree(wname);
Victor Stinner4e314432010-10-07 21:45:39 +00001990 return buf;
1991#endif
1992}
1993
Victor Stinnerdaf45552013-08-28 00:53:59 +02001994/* Duplicate a file descriptor. The new file descriptor is created as
1995 non-inheritable. Return a new file descriptor on success, raise an OSError
1996 exception and return -1 on error.
1997
1998 The GIL is released to call dup(). The caller must hold the GIL. */
1999int
2000_Py_dup(int fd)
2001{
2002#ifdef MS_WINDOWS
2003 HANDLE handle;
Victor Stinnerdaf45552013-08-28 00:53:59 +02002004#endif
2005
Victor Stinner8a1be612016-03-14 22:07:55 +01002006 assert(PyGILState_Check());
Victor Stinner8a1be612016-03-14 22:07:55 +01002007
Victor Stinnerdaf45552013-08-28 00:53:59 +02002008#ifdef MS_WINDOWS
Steve Dower8fc89802015-04-12 00:26:27 -04002009 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002010 handle = (HANDLE)_get_osfhandle(fd);
Steve Dower8fc89802015-04-12 00:26:27 -04002011 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002012 if (handle == INVALID_HANDLE_VALUE) {
Steve Dower41e72442015-03-14 11:38:27 -07002013 PyErr_SetFromErrno(PyExc_OSError);
Victor Stinnerdaf45552013-08-28 00:53:59 +02002014 return -1;
2015 }
2016
Victor Stinnerdaf45552013-08-28 00:53:59 +02002017 Py_BEGIN_ALLOW_THREADS
Steve Dower8fc89802015-04-12 00:26:27 -04002018 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002019 fd = dup(fd);
Steve Dower8fc89802015-04-12 00:26:27 -04002020 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002021 Py_END_ALLOW_THREADS
2022 if (fd < 0) {
2023 PyErr_SetFromErrno(PyExc_OSError);
2024 return -1;
2025 }
2026
Zackery Spytz28fca0c2019-06-17 01:17:14 -06002027 if (_Py_set_inheritable(fd, 0, NULL) < 0) {
2028 _Py_BEGIN_SUPPRESS_IPH
2029 close(fd);
2030 _Py_END_SUPPRESS_IPH
2031 return -1;
Victor Stinnerdaf45552013-08-28 00:53:59 +02002032 }
2033#elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC)
2034 Py_BEGIN_ALLOW_THREADS
Steve Dower8fc89802015-04-12 00:26:27 -04002035 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002036 fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
Steve Dower8fc89802015-04-12 00:26:27 -04002037 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002038 Py_END_ALLOW_THREADS
2039 if (fd < 0) {
2040 PyErr_SetFromErrno(PyExc_OSError);
2041 return -1;
2042 }
2043
2044#else
2045 Py_BEGIN_ALLOW_THREADS
Steve Dower8fc89802015-04-12 00:26:27 -04002046 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002047 fd = dup(fd);
Steve Dower8fc89802015-04-12 00:26:27 -04002048 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002049 Py_END_ALLOW_THREADS
2050 if (fd < 0) {
2051 PyErr_SetFromErrno(PyExc_OSError);
2052 return -1;
2053 }
2054
2055 if (_Py_set_inheritable(fd, 0, NULL) < 0) {
Steve Dower8fc89802015-04-12 00:26:27 -04002056 _Py_BEGIN_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002057 close(fd);
Steve Dower8fc89802015-04-12 00:26:27 -04002058 _Py_END_SUPPRESS_IPH
Victor Stinnerdaf45552013-08-28 00:53:59 +02002059 return -1;
2060 }
2061#endif
2062 return fd;
2063}
2064
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002065#ifndef MS_WINDOWS
2066/* Get the blocking mode of the file descriptor.
2067 Return 0 if the O_NONBLOCK flag is set, 1 if the flag is cleared,
2068 raise an exception and return -1 on error. */
2069int
2070_Py_get_blocking(int fd)
2071{
Steve Dower8fc89802015-04-12 00:26:27 -04002072 int flags;
2073 _Py_BEGIN_SUPPRESS_IPH
2074 flags = fcntl(fd, F_GETFL, 0);
2075 _Py_END_SUPPRESS_IPH
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002076 if (flags < 0) {
2077 PyErr_SetFromErrno(PyExc_OSError);
2078 return -1;
2079 }
2080
2081 return !(flags & O_NONBLOCK);
2082}
2083
2084/* Set the blocking mode of the specified file descriptor.
2085
2086 Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag
2087 otherwise.
2088
2089 Return 0 on success, raise an exception and return -1 on error. */
2090int
2091_Py_set_blocking(int fd, int blocking)
2092{
pxinwr06afac62020-12-08 04:41:12 +08002093/* bpo-41462: On VxWorks, ioctl(FIONBIO) only works on sockets.
2094 Use fcntl() instead. */
2095#if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO) && !defined(__VXWORKS__)
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002096 int arg = !blocking;
2097 if (ioctl(fd, FIONBIO, &arg) < 0)
2098 goto error;
2099#else
2100 int flags, res;
2101
Steve Dower8fc89802015-04-12 00:26:27 -04002102 _Py_BEGIN_SUPPRESS_IPH
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002103 flags = fcntl(fd, F_GETFL, 0);
Steve Dower8fc89802015-04-12 00:26:27 -04002104 if (flags >= 0) {
2105 if (blocking)
2106 flags = flags & (~O_NONBLOCK);
2107 else
2108 flags = flags | O_NONBLOCK;
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002109
Steve Dower8fc89802015-04-12 00:26:27 -04002110 res = fcntl(fd, F_SETFL, flags);
2111 } else {
2112 res = -1;
2113 }
2114 _Py_END_SUPPRESS_IPH
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002115
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002116 if (res < 0)
2117 goto error;
2118#endif
2119 return 0;
2120
2121error:
2122 PyErr_SetFromErrno(PyExc_OSError);
2123 return -1;
2124}
2125#endif
Victor Stinnercb064fc2018-01-15 15:58:02 +01002126
2127
2128int
Victor Stinner02e6bf72018-11-20 16:20:16 +01002129_Py_GetLocaleconvNumeric(struct lconv *lc,
2130 PyObject **decimal_point, PyObject **thousands_sep)
Victor Stinnercb064fc2018-01-15 15:58:02 +01002131{
Victor Stinner02e6bf72018-11-20 16:20:16 +01002132 assert(decimal_point != NULL);
2133 assert(thousands_sep != NULL);
Victor Stinnercb064fc2018-01-15 15:58:02 +01002134
TIGirardif2312032020-10-20 08:39:52 -03002135#ifndef MS_WINDOWS
Victor Stinnercb064fc2018-01-15 15:58:02 +01002136 int change_locale = 0;
Victor Stinner02e6bf72018-11-20 16:20:16 +01002137 if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {
Victor Stinnercb064fc2018-01-15 15:58:02 +01002138 change_locale = 1;
2139 }
Victor Stinner02e6bf72018-11-20 16:20:16 +01002140 if ((strlen(lc->thousands_sep) > 1 || ((unsigned char)lc->thousands_sep[0]) > 127)) {
Victor Stinnercb064fc2018-01-15 15:58:02 +01002141 change_locale = 1;
2142 }
2143
2144 /* Keep a copy of the LC_CTYPE locale */
2145 char *oldloc = NULL, *loc = NULL;
2146 if (change_locale) {
2147 oldloc = setlocale(LC_CTYPE, NULL);
2148 if (!oldloc) {
Victor Stinner02e6bf72018-11-20 16:20:16 +01002149 PyErr_SetString(PyExc_RuntimeWarning,
2150 "failed to get LC_CTYPE locale");
Victor Stinnercb064fc2018-01-15 15:58:02 +01002151 return -1;
2152 }
2153
2154 oldloc = _PyMem_Strdup(oldloc);
2155 if (!oldloc) {
2156 PyErr_NoMemory();
2157 return -1;
2158 }
2159
2160 loc = setlocale(LC_NUMERIC, NULL);
2161 if (loc != NULL && strcmp(loc, oldloc) == 0) {
2162 loc = NULL;
2163 }
2164
2165 if (loc != NULL) {
Victor Stinner02e6bf72018-11-20 16:20:16 +01002166 /* Only set the locale temporarily the LC_CTYPE locale
Victor Stinnercb064fc2018-01-15 15:58:02 +01002167 if LC_NUMERIC locale is different than LC_CTYPE locale and
2168 decimal_point and/or thousands_sep are non-ASCII or longer than
2169 1 byte */
2170 setlocale(LC_CTYPE, loc);
2171 }
2172 }
2173
TIGirardif2312032020-10-20 08:39:52 -03002174#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
2175#else /* MS_WINDOWS */
2176/* Use _W_* fields of Windows strcut lconv */
2177#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
2178#endif /* MS_WINDOWS */
2179
Victor Stinner02e6bf72018-11-20 16:20:16 +01002180 int res = -1;
2181
TIGirardif2312032020-10-20 08:39:52 -03002182 *decimal_point = GET_LOCALE_STRING(decimal_point);
Victor Stinner02e6bf72018-11-20 16:20:16 +01002183 if (*decimal_point == NULL) {
2184 goto done;
Victor Stinnercb064fc2018-01-15 15:58:02 +01002185 }
2186
TIGirardif2312032020-10-20 08:39:52 -03002187 *thousands_sep = GET_LOCALE_STRING(thousands_sep);
Victor Stinner02e6bf72018-11-20 16:20:16 +01002188 if (*thousands_sep == NULL) {
2189 goto done;
Victor Stinnercb064fc2018-01-15 15:58:02 +01002190 }
2191
2192 res = 0;
2193
Victor Stinner02e6bf72018-11-20 16:20:16 +01002194done:
TIGirardif2312032020-10-20 08:39:52 -03002195#ifndef MS_WINDOWS
Victor Stinnercb064fc2018-01-15 15:58:02 +01002196 if (loc != NULL) {
2197 setlocale(LC_CTYPE, oldloc);
2198 }
2199 PyMem_Free(oldloc);
TIGirardif2312032020-10-20 08:39:52 -03002200#endif
Victor Stinnercb064fc2018-01-15 15:58:02 +01002201 return res;
TIGirardif2312032020-10-20 08:39:52 -03002202
2203#undef GET_LOCALE_STRING
Victor Stinnercb064fc2018-01-15 15:58:02 +01002204}
Kyle Evans79925792020-10-13 15:04:44 -05002205
2206/* Our selection logic for which function to use is as follows:
2207 * 1. If close_range(2) is available, always prefer that; it's better for
2208 * contiguous ranges like this than fdwalk(3) which entails iterating over
2209 * the entire fd space and simply doing nothing for those outside the range.
2210 * 2. If closefrom(2) is available, we'll attempt to use that next if we're
2211 * closing up to sysconf(_SC_OPEN_MAX).
2212 * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
2213 * as that will be more performant if the range happens to have any chunk of
2214 * non-opened fd in the middle.
2215 * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
2216 */
2217#ifdef __FreeBSD__
2218# define USE_CLOSEFROM
2219#endif /* __FreeBSD__ */
2220
2221#ifdef HAVE_FDWALK
2222# define USE_FDWALK
2223#endif /* HAVE_FDWALK */
2224
2225#ifdef USE_FDWALK
2226static int
2227_fdwalk_close_func(void *lohi, int fd)
2228{
2229 int lo = ((int *)lohi)[0];
2230 int hi = ((int *)lohi)[1];
2231
2232 if (fd >= hi) {
2233 return 1;
2234 }
2235 else if (fd >= lo) {
2236 /* Ignore errors */
2237 (void)close(fd);
2238 }
2239 return 0;
2240}
2241#endif /* USE_FDWALK */
2242
2243/* Closes all file descriptors in [first, last], ignoring errors. */
2244void
2245_Py_closerange(int first, int last)
2246{
2247 first = Py_MAX(first, 0);
2248 _Py_BEGIN_SUPPRESS_IPH
2249#ifdef HAVE_CLOSE_RANGE
2250 if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
2251 /* Any errors encountered while closing file descriptors are ignored;
2252 * ENOSYS means no kernel support, though,
2253 * so we'll fallback to the other methods. */
2254 }
2255 else
2256#endif /* HAVE_CLOSE_RANGE */
2257#ifdef USE_CLOSEFROM
2258 if (last >= sysconf(_SC_OPEN_MAX)) {
2259 /* Any errors encountered while closing file descriptors are ignored */
2260 closefrom(first);
2261 }
2262 else
2263#endif /* USE_CLOSEFROM */
2264#ifdef USE_FDWALK
2265 {
2266 int lohi[2];
2267 lohi[0] = first;
2268 lohi[1] = last + 1;
2269 fdwalk(_fdwalk_close_func, lohi);
2270 }
2271#else
2272 {
2273 for (int i = first; i <= last; i++) {
2274 /* Ignore errors */
2275 (void)close(i);
2276 }
2277 }
2278#endif /* USE_FDWALK */
2279 _Py_END_SUPPRESS_IPH
2280}