1 #include "Python.h"
2 #include "osdefs.h"
3 #include <locale.h>
4
5 #ifdef MS_WINDOWS
6 # include <malloc.h>
7 # include <windows.h>
8 extern int winerror_to_errno(int);
9 #endif
10
11 #ifdef HAVE_LANGINFO_H
12 #include <langinfo.h>
13 #endif
14
15 #ifdef HAVE_SYS_IOCTL_H
16 #include <sys/ioctl.h>
17 #endif
18
19 #ifdef HAVE_FCNTL_H
20 #include <fcntl.h>
21 #endif /* HAVE_FCNTL_H */
22
23 #if defined(__APPLE__) || defined(__ANDROID__)
24 extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size);
25 #endif
26
27 #ifdef O_CLOEXEC
28 /* Does open() support the O_CLOEXEC flag? Possible values:
29
30 -1: unknown
31 0: open() ignores O_CLOEXEC flag, ex: Linux kernel older than 2.6.23
32 1: open() supports O_CLOEXEC flag, close-on-exec is set
33
34 The flag is used by _Py_open(), _Py_open_noraise(), io.FileIO
35 and os.open(). */
36 int _Py_open_cloexec_works = -1;
37 #endif
38
39 PyObject *
_Py_device_encoding(int fd)40 _Py_device_encoding(int fd)
41 {
42 #if defined(MS_WINDOWS)
43 UINT cp;
44 #endif
45 int valid;
46 _Py_BEGIN_SUPPRESS_IPH
47 valid = isatty(fd);
48 _Py_END_SUPPRESS_IPH
49 if (!valid)
50 Py_RETURN_NONE;
51
52 #if defined(MS_WINDOWS)
53 if (fd == 0)
54 cp = GetConsoleCP();
55 else if (fd == 1 || fd == 2)
56 cp = GetConsoleOutputCP();
57 else
58 cp = 0;
59 /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application
60 has no console */
61 if (cp != 0)
62 return PyUnicode_FromFormat("cp%u", (unsigned int)cp);
63 #elif defined(CODESET)
64 {
65 char *codeset = nl_langinfo(CODESET);
66 if (codeset != NULL && codeset[0] != 0)
67 return PyUnicode_FromString(codeset);
68 }
69 #endif
70 Py_RETURN_NONE;
71 }
72
73 #if !defined(__APPLE__) && !defined(MS_WINDOWS)
74 extern int _Py_normalize_encoding(const char *, char *, size_t);
75
76 /* Workaround FreeBSD and OpenIndiana locale encoding issue with the C locale.
77 On these operating systems, nl_langinfo(CODESET) announces an alias of the
78 ASCII encoding, whereas mbstowcs() and wcstombs() functions use the
79 ISO-8859-1 encoding. The problem is that os.fsencode() and os.fsdecode() use
80 locale.getpreferredencoding() codec. For example, if command line arguments
81 are decoded by mbstowcs() and encoded back by os.fsencode(), we get a
82 UnicodeEncodeError instead of retrieving the original byte string.
83
84 The workaround is enabled if setlocale(LC_CTYPE, NULL) returns "C",
85 nl_langinfo(CODESET) announces "ascii" (or an alias to ASCII), and at least
86 one byte in range 0x80-0xff can be decoded from the locale encoding. The
87 workaround is also enabled on error, for example if getting the locale
88 failed.
89
90 Values of force_ascii:
91
92 1: the workaround is used: Py_EncodeLocale() uses
93 encode_ascii_surrogateescape() and Py_DecodeLocale() uses
94 decode_ascii_surrogateescape()
95 0: the workaround is not used: Py_EncodeLocale() uses wcstombs() and
96 Py_DecodeLocale() uses mbstowcs()
97 -1: unknown, need to call check_force_ascii() to get the value
98 */
99 static int force_ascii = -1;
100
101 static int
check_force_ascii(void)102 check_force_ascii(void)
103 {
104 char *loc;
105 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
106 char *codeset, **alias;
107 char encoding[20]; /* longest name: "iso_646.irv_1991\0" */
108 int is_ascii;
109 unsigned int i;
110 char* ascii_aliases[] = {
111 "ascii",
112 /* Aliases from Lib/encodings/aliases.py */
113 "646",
114 "ansi_x3.4_1968",
115 "ansi_x3.4_1986",
116 "ansi_x3_4_1968",
117 "cp367",
118 "csascii",
119 "ibm367",
120 "iso646_us",
121 "iso_646.irv_1991",
122 "iso_ir_6",
123 "us",
124 "us_ascii",
125 NULL
126 };
127 #endif
128
129 loc = setlocale(LC_CTYPE, NULL);
130 if (loc == NULL)
131 goto error;
132 if (strcmp(loc, "C") != 0) {
133 /* the LC_CTYPE locale is different than C */
134 return 0;
135 }
136
137 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
138 codeset = nl_langinfo(CODESET);
139 if (!codeset || codeset[0] == '\0') {
140 /* CODESET is not set or empty */
141 goto error;
142 }
143 if (!_Py_normalize_encoding(codeset, encoding, sizeof(encoding)))
144 goto error;
145
146 is_ascii = 0;
147 for (alias=ascii_aliases; *alias != NULL; alias++) {
148 if (strcmp(encoding, *alias) == 0) {
149 is_ascii = 1;
150 break;
151 }
152 }
153 if (!is_ascii) {
154 /* nl_langinfo(CODESET) is not "ascii" or an alias of ASCII */
155 return 0;
156 }
157
158 for (i=0x80; i<0xff; i++) {
159 unsigned char ch;
160 wchar_t wch;
161 size_t res;
162
163 ch = (unsigned char)i;
164 res = mbstowcs(&wch, (char*)&ch, 1);
165 if (res != (size_t)-1) {
166 /* decoding a non-ASCII character from the locale encoding succeed:
167 the locale encoding is not ASCII, force ASCII */
168 return 1;
169 }
170 }
171 /* None of the bytes in the range 0x80-0xff can be decoded from the locale
172 encoding: the locale encoding is really ASCII */
173 return 0;
174 #else
175 /* nl_langinfo(CODESET) is not available: always force ASCII */
176 return 1;
177 #endif
178
179 error:
180 /* if an error occurred, force the ASCII encoding */
181 return 1;
182 }
183
184 static char*
encode_ascii_surrogateescape(const wchar_t * text,size_t * error_pos)185 encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos)
186 {
187 char *result = NULL, *out;
188 size_t len, i;
189 wchar_t ch;
190
191 if (error_pos != NULL)
192 *error_pos = (size_t)-1;
193
194 len = wcslen(text);
195
196 result = PyMem_Malloc(len + 1); /* +1 for NUL byte */
197 if (result == NULL)
198 return NULL;
199
200 out = result;
201 for (i=0; i<len; i++) {
202 ch = text[i];
203
204 if (ch <= 0x7f) {
205 /* ASCII character */
206 *out++ = (char)ch;
207 }
208 else if (0xdc80 <= ch && ch <= 0xdcff) {
209 /* UTF-8b surrogate */
210 *out++ = (char)(ch - 0xdc00);
211 }
212 else {
213 if (error_pos != NULL)
214 *error_pos = i;
215 PyMem_Free(result);
216 return NULL;
217 }
218 }
219 *out = '\0';
220 return result;
221 }
222 #endif /* !defined(__APPLE__) && !defined(MS_WINDOWS) */
223
224 #if !defined(__APPLE__) && (!defined(MS_WINDOWS) || !defined(HAVE_MBRTOWC))
225 static wchar_t*
decode_ascii_surrogateescape(const char * arg,size_t * size)226 decode_ascii_surrogateescape(const char *arg, size_t *size)
227 {
228 wchar_t *res;
229 unsigned char *in;
230 wchar_t *out;
231 size_t argsize = strlen(arg) + 1;
232
233 if (argsize > PY_SSIZE_T_MAX/sizeof(wchar_t))
234 return NULL;
235 res = PyMem_RawMalloc(argsize*sizeof(wchar_t));
236 if (!res)
237 return NULL;
238
239 in = (unsigned char*)arg;
240 out = res;
241 while(*in)
242 if(*in < 128)
243 *out++ = *in++;
244 else
245 *out++ = 0xdc00 + *in++;
246 *out = 0;
247 if (size != NULL)
248 *size = out - res;
249 return res;
250 }
251 #endif
252
253
254 /* Decode a byte string from the locale encoding with the
255 surrogateescape error handler: undecodable bytes are decoded as characters
256 in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate
257 character, escape the bytes using the surrogateescape error handler instead
258 of decoding them.
259
260 Return a pointer to a newly allocated wide character string, use
261 PyMem_RawFree() to free the memory. If size is not NULL, write the number of
262 wide characters excluding the null character into *size
263
264 Return NULL on decoding error or memory allocation error. If *size* is not
265 NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on
266 decoding error.
267
268 Decoding errors should never happen, unless there is a bug in the C
269 library.
270
271 Use the Py_EncodeLocale() function to encode the character string back to a
272 byte string. */
273 wchar_t*
Py_DecodeLocale(const char * arg,size_t * size)274 Py_DecodeLocale(const char* arg, size_t *size)
275 {
276 #if defined(__APPLE__) || defined(__ANDROID__)
277 wchar_t *wstr;
278 wstr = _Py_DecodeUTF8_surrogateescape(arg, strlen(arg));
279 if (size != NULL) {
280 if (wstr != NULL)
281 *size = wcslen(wstr);
282 else
283 *size = (size_t)-1;
284 }
285 return wstr;
286 #else
287 wchar_t *res;
288 size_t argsize;
289 size_t count;
290 #ifdef HAVE_MBRTOWC
291 unsigned char *in;
292 wchar_t *out;
293 mbstate_t mbs;
294 #endif
295
296 #ifndef MS_WINDOWS
297 if (force_ascii == -1)
298 force_ascii = check_force_ascii();
299
300 if (force_ascii) {
301 /* force ASCII encoding to workaround mbstowcs() issue */
302 res = decode_ascii_surrogateescape(arg, size);
303 if (res == NULL)
304 goto oom;
305 return res;
306 }
307 #endif
308
309 #ifdef HAVE_BROKEN_MBSTOWCS
310 /* Some platforms have a broken implementation of
311 * mbstowcs which does not count the characters that
312 * would result from conversion. Use an upper bound.
313 */
314 argsize = strlen(arg);
315 #else
316 argsize = mbstowcs(NULL, arg, 0);
317 #endif
318 if (argsize != (size_t)-1) {
319 if (argsize == PY_SSIZE_T_MAX)
320 goto oom;
321 argsize += 1;
322 if (argsize > PY_SSIZE_T_MAX/sizeof(wchar_t))
323 goto oom;
324 res = (wchar_t *)PyMem_RawMalloc(argsize*sizeof(wchar_t));
325 if (!res)
326 goto oom;
327 count = mbstowcs(res, arg, argsize);
328 if (count != (size_t)-1) {
329 wchar_t *tmp;
330 /* Only use the result if it contains no
331 surrogate characters. */
332 for (tmp = res; *tmp != 0 &&
333 !Py_UNICODE_IS_SURROGATE(*tmp); tmp++)
334 ;
335 if (*tmp == 0) {
336 if (size != NULL)
337 *size = count;
338 return res;
339 }
340 }
341 PyMem_RawFree(res);
342 }
343 /* Conversion failed. Fall back to escaping with surrogateescape. */
344 #ifdef HAVE_MBRTOWC
345 /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
346
347 /* Overallocate; as multi-byte characters are in the argument, the
348 actual output could use less memory. */
349 argsize = strlen(arg) + 1;
350 if (argsize > PY_SSIZE_T_MAX/sizeof(wchar_t))
351 goto oom;
352 res = (wchar_t*)PyMem_RawMalloc(argsize*sizeof(wchar_t));
353 if (!res)
354 goto oom;
355 in = (unsigned char*)arg;
356 out = res;
357 memset(&mbs, 0, sizeof mbs);
358 while (argsize) {
359 size_t converted = mbrtowc(out, (char*)in, argsize, &mbs);
360 if (converted == 0)
361 /* Reached end of string; null char stored. */
362 break;
363 if (converted == (size_t)-2) {
364 /* Incomplete character. This should never happen,
365 since we provide everything that we have -
366 unless there is a bug in the C library, or I
367 misunderstood how mbrtowc works. */
368 PyMem_RawFree(res);
369 if (size != NULL)
370 *size = (size_t)-2;
371 return NULL;
372 }
373 if (converted == (size_t)-1) {
374 /* Conversion error. Escape as UTF-8b, and start over
375 in the initial shift state. */
376 *out++ = 0xdc00 + *in++;
377 argsize--;
378 memset(&mbs, 0, sizeof mbs);
379 continue;
380 }
381 if (Py_UNICODE_IS_SURROGATE(*out)) {
382 /* Surrogate character. Escape the original
383 byte sequence with surrogateescape. */
384 argsize -= converted;
385 while (converted--)
386 *out++ = 0xdc00 + *in++;
387 continue;
388 }
389 /* successfully converted some bytes */
390 in += converted;
391 argsize -= converted;
392 out++;
393 }
394 if (size != NULL)
395 *size = out - res;
396 #else /* HAVE_MBRTOWC */
397 /* Cannot use C locale for escaping; manually escape as if charset
398 is ASCII (i.e. escape all bytes > 128. This will still roundtrip
399 correctly in the locale's charset, which must be an ASCII superset. */
400 res = decode_ascii_surrogateescape(arg, size);
401 if (res == NULL)
402 goto oom;
403 #endif /* HAVE_MBRTOWC */
404 return res;
405 oom:
406 if (size != NULL)
407 *size = (size_t)-1;
408 return NULL;
409 #endif /* __APPLE__ or __ANDROID__ */
410 }
411
412 /* Encode a wide character string to the locale encoding with the
413 surrogateescape error handler: surrogate characters in the range
414 U+DC80..U+DCFF are converted to bytes 0x80..0xFF.
415
416 Return a pointer to a newly allocated byte string, use PyMem_Free() to free
417 the memory. Return NULL on encoding or memory allocation error.
418
419 If error_pos is not NULL, *error_pos is set to the index of the invalid
420 character on encoding error, or set to (size_t)-1 otherwise.
421
422 Use the Py_DecodeLocale() function to decode the bytes string back to a wide
423 character string. */
424 char*
Py_EncodeLocale(const wchar_t * text,size_t * error_pos)425 Py_EncodeLocale(const wchar_t *text, size_t *error_pos)
426 {
427 #if defined(__APPLE__) || defined(__ANDROID__)
428 Py_ssize_t len;
429 PyObject *unicode, *bytes = NULL;
430 char *cpath;
431
432 unicode = PyUnicode_FromWideChar(text, wcslen(text));
433 if (unicode == NULL)
434 return NULL;
435
436 bytes = _PyUnicode_AsUTF8String(unicode, "surrogateescape");
437 Py_DECREF(unicode);
438 if (bytes == NULL) {
439 PyErr_Clear();
440 if (error_pos != NULL)
441 *error_pos = (size_t)-1;
442 return NULL;
443 }
444
445 len = PyBytes_GET_SIZE(bytes);
446 cpath = PyMem_Malloc(len+1);
447 if (cpath == NULL) {
448 PyErr_Clear();
449 Py_DECREF(bytes);
450 if (error_pos != NULL)
451 *error_pos = (size_t)-1;
452 return NULL;
453 }
454 memcpy(cpath, PyBytes_AsString(bytes), len + 1);
455 Py_DECREF(bytes);
456 return cpath;
457 #else /* __APPLE__ */
458 const size_t len = wcslen(text);
459 char *result = NULL, *bytes = NULL;
460 size_t i, size, converted;
461 wchar_t c, buf[2];
462
463 #ifndef MS_WINDOWS
464 if (force_ascii == -1)
465 force_ascii = check_force_ascii();
466
467 if (force_ascii)
468 return encode_ascii_surrogateescape(text, error_pos);
469 #endif
470
471 /* The function works in two steps:
472 1. compute the length of the output buffer in bytes (size)
473 2. outputs the bytes */
474 size = 0;
475 buf[1] = 0;
476 while (1) {
477 for (i=0; i < len; i++) {
478 c = text[i];
479 if (c >= 0xdc80 && c <= 0xdcff) {
480 /* UTF-8b surrogate */
481 if (bytes != NULL) {
482 *bytes++ = c - 0xdc00;
483 size--;
484 }
485 else
486 size++;
487 continue;
488 }
489 else {
490 buf[0] = c;
491 if (bytes != NULL)
492 converted = wcstombs(bytes, buf, size);
493 else
494 converted = wcstombs(NULL, buf, 0);
495 if (converted == (size_t)-1) {
496 if (result != NULL)
497 PyMem_Free(result);
498 if (error_pos != NULL)
499 *error_pos = i;
500 return NULL;
501 }
502 if (bytes != NULL) {
503 bytes += converted;
504 size -= converted;
505 }
506 else
507 size += converted;
508 }
509 }
510 if (result != NULL) {
511 *bytes = '\0';
512 break;
513 }
514
515 size += 1; /* nul byte at the end */
516 result = PyMem_Malloc(size);
517 if (result == NULL) {
518 if (error_pos != NULL)
519 *error_pos = (size_t)-1;
520 return NULL;
521 }
522 bytes = result;
523 }
524 return result;
525 #endif /* __APPLE__ or __ANDROID__ */
526 }
527
528
529 #ifdef MS_WINDOWS
530 static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
531
532 static void
FILE_TIME_to_time_t_nsec(FILETIME * in_ptr,time_t * time_out,int * nsec_out)533 FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
534 {
535 /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
536 /* Cannot simply cast and dereference in_ptr,
537 since it might not be aligned properly */
538 __int64 in;
539 memcpy(&in, in_ptr, sizeof(in));
540 *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
541 *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
542 }
543
544 void
_Py_time_t_to_FILE_TIME(time_t time_in,int nsec_in,FILETIME * out_ptr)545 _Py_time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
546 {
547 /* XXX endianness */
548 __int64 out;
549 out = time_in + secs_between_epochs;
550 out = out * 10000000 + nsec_in / 100;
551 memcpy(out_ptr, &out, sizeof(out));
552 }
553
554 /* Below, we *know* that ugo+r is 0444 */
555 #if _S_IREAD != 0400
556 #error Unsupported C library
557 #endif
558 static int
attributes_to_mode(DWORD attr)559 attributes_to_mode(DWORD attr)
560 {
561 int m = 0;
562 if (attr & FILE_ATTRIBUTE_DIRECTORY)
563 m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
564 else
565 m |= _S_IFREG;
566 if (attr & FILE_ATTRIBUTE_READONLY)
567 m |= 0444;
568 else
569 m |= 0666;
570 return m;
571 }
572
573 void
_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION * info,ULONG reparse_tag,struct _Py_stat_struct * result)574 _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
575 struct _Py_stat_struct *result)
576 {
577 memset(result, 0, sizeof(*result));
578 result->st_mode = attributes_to_mode(info->dwFileAttributes);
579 result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
580 result->st_dev = info->dwVolumeSerialNumber;
581 result->st_rdev = result->st_dev;
582 FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
583 FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
584 FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
585 result->st_nlink = info->nNumberOfLinks;
586 result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
587 if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
588 /* first clear the S_IFMT bits */
589 result->st_mode ^= (result->st_mode & S_IFMT);
590 /* now set the bits that make this a symlink */
591 result->st_mode |= S_IFLNK;
592 }
593 result->st_file_attributes = info->dwFileAttributes;
594 }
595 #endif
596
597 /* Return information about a file.
598
599 On POSIX, use fstat().
600
601 On Windows, use GetFileType() and GetFileInformationByHandle() which support
602 files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger
603 than 2 GB because the file size type is a signed 32-bit integer: see issue
604 #23152.
605
606 On Windows, set the last Windows error and return nonzero on error. On
607 POSIX, set errno and return nonzero on error. Fill status and return 0 on
608 success. */
609 int
_Py_fstat_noraise(int fd,struct _Py_stat_struct * status)610 _Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
611 {
612 #ifdef MS_WINDOWS
613 BY_HANDLE_FILE_INFORMATION info;
614 HANDLE h;
615 int type;
616
617 _Py_BEGIN_SUPPRESS_IPH
618 h = (HANDLE)_get_osfhandle(fd);
619 _Py_END_SUPPRESS_IPH
620
621 if (h == INVALID_HANDLE_VALUE) {
622 /* errno is already set by _get_osfhandle, but we also set
623 the Win32 error for callers who expect that */
624 SetLastError(ERROR_INVALID_HANDLE);
625 return -1;
626 }
627 memset(status, 0, sizeof(*status));
628
629 type = GetFileType(h);
630 if (type == FILE_TYPE_UNKNOWN) {
631 DWORD error = GetLastError();
632 if (error != 0) {
633 errno = winerror_to_errno(error);
634 return -1;
635 }
636 /* else: valid but unknown file */
637 }
638
639 if (type != FILE_TYPE_DISK) {
640 if (type == FILE_TYPE_CHAR)
641 status->st_mode = _S_IFCHR;
642 else if (type == FILE_TYPE_PIPE)
643 status->st_mode = _S_IFIFO;
644 return 0;
645 }
646
647 if (!GetFileInformationByHandle(h, &info)) {
648 /* The Win32 error is already set, but we also set errno for
649 callers who expect it */
650 errno = winerror_to_errno(GetLastError());
651 return -1;
652 }
653
654 _Py_attribute_data_to_stat(&info, 0, status);
655 /* specific to fstat() */
656 status->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
657 return 0;
658 #else
659 return fstat(fd, status);
660 #endif
661 }
662
663 /* Return information about a file.
664
665 On POSIX, use fstat().
666
667 On Windows, use GetFileType() and GetFileInformationByHandle() which support
668 files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger
669 than 2 GB because the file size type is a signed 32-bit integer: see issue
670 #23152.
671
672 Raise an exception and return -1 on error. On Windows, set the last Windows
673 error on error. On POSIX, set errno on error. Fill status and return 0 on
674 success.
675
676 Release the GIL to call GetFileType() and GetFileInformationByHandle(), or
677 to call fstat(). The caller must hold the GIL. */
678 int
_Py_fstat(int fd,struct _Py_stat_struct * status)679 _Py_fstat(int fd, struct _Py_stat_struct *status)
680 {
681 int res;
682
683 #ifdef WITH_THREAD
684 assert(PyGILState_Check());
685 #endif
686
687 Py_BEGIN_ALLOW_THREADS
688 res = _Py_fstat_noraise(fd, status);
689 Py_END_ALLOW_THREADS
690
691 if (res != 0) {
692 #ifdef MS_WINDOWS
693 PyErr_SetFromWindowsErr(0);
694 #else
695 PyErr_SetFromErrno(PyExc_OSError);
696 #endif
697 return -1;
698 }
699 return 0;
700 }
701
702 /* Call _wstat() on Windows, or encode the path to the filesystem encoding and
703 call stat() otherwise. Only fill st_mode attribute on Windows.
704
705 Return 0 on success, -1 on _wstat() / stat() error, -2 if an exception was
706 raised. */
707
708 int
_Py_stat(PyObject * path,struct stat * statbuf)709 _Py_stat(PyObject *path, struct stat *statbuf)
710 {
711 #ifdef MS_WINDOWS
712 int err;
713 struct _stat wstatbuf;
714 wchar_t *wpath;
715
716 wpath = PyUnicode_AsUnicode(path);
717 if (wpath == NULL)
718 return -2;
719 err = _wstat(wpath, &wstatbuf);
720 if (!err)
721 statbuf->st_mode = wstatbuf.st_mode;
722 return err;
723 #else
724 int ret;
725 PyObject *bytes = PyUnicode_EncodeFSDefault(path);
726 if (bytes == NULL)
727 return -2;
728 ret = stat(PyBytes_AS_STRING(bytes), statbuf);
729 Py_DECREF(bytes);
730 return ret;
731 #endif
732 }
733
734
735 static int
get_inheritable(int fd,int raise)736 get_inheritable(int fd, int raise)
737 {
738 #ifdef MS_WINDOWS
739 HANDLE handle;
740 DWORD flags;
741
742 _Py_BEGIN_SUPPRESS_IPH
743 handle = (HANDLE)_get_osfhandle(fd);
744 _Py_END_SUPPRESS_IPH
745 if (handle == INVALID_HANDLE_VALUE) {
746 if (raise)
747 PyErr_SetFromErrno(PyExc_OSError);
748 return -1;
749 }
750
751 if (!GetHandleInformation(handle, &flags)) {
752 if (raise)
753 PyErr_SetFromWindowsErr(0);
754 return -1;
755 }
756
757 return (flags & HANDLE_FLAG_INHERIT);
758 #else
759 int flags;
760
761 flags = fcntl(fd, F_GETFD, 0);
762 if (flags == -1) {
763 if (raise)
764 PyErr_SetFromErrno(PyExc_OSError);
765 return -1;
766 }
767 return !(flags & FD_CLOEXEC);
768 #endif
769 }
770
771 /* Get the inheritable flag of the specified file descriptor.
772 Return 1 if the file descriptor can be inherited, 0 if it cannot,
773 raise an exception and return -1 on error. */
774 int
_Py_get_inheritable(int fd)775 _Py_get_inheritable(int fd)
776 {
777 return get_inheritable(fd, 1);
778 }
779
780 static int
set_inheritable(int fd,int inheritable,int raise,int * atomic_flag_works)781 set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
782 {
783 #ifdef MS_WINDOWS
784 HANDLE handle;
785 DWORD flags;
786 #else
787 #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
788 static int ioctl_works = -1;
789 int request;
790 int err;
791 #endif
792 int flags, new_flags;
793 int res;
794 #endif
795
796 /* atomic_flag_works can only be used to make the file descriptor
797 non-inheritable */
798 assert(!(atomic_flag_works != NULL && inheritable));
799
800 if (atomic_flag_works != NULL && !inheritable) {
801 if (*atomic_flag_works == -1) {
802 int isInheritable = get_inheritable(fd, raise);
803 if (isInheritable == -1)
804 return -1;
805 *atomic_flag_works = !isInheritable;
806 }
807
808 if (*atomic_flag_works)
809 return 0;
810 }
811
812 #ifdef MS_WINDOWS
813 _Py_BEGIN_SUPPRESS_IPH
814 handle = (HANDLE)_get_osfhandle(fd);
815 _Py_END_SUPPRESS_IPH
816 if (handle == INVALID_HANDLE_VALUE) {
817 if (raise)
818 PyErr_SetFromErrno(PyExc_OSError);
819 return -1;
820 }
821
822 if (inheritable)
823 flags = HANDLE_FLAG_INHERIT;
824 else
825 flags = 0;
826 if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
827 if (raise)
828 PyErr_SetFromWindowsErr(0);
829 return -1;
830 }
831 return 0;
832
833 #else
834
835 #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
836 if (ioctl_works != 0) {
837 /* fast-path: ioctl() only requires one syscall */
838 if (inheritable)
839 request = FIONCLEX;
840 else
841 request = FIOCLEX;
842 err = ioctl(fd, request, NULL);
843 if (!err) {
844 ioctl_works = 1;
845 return 0;
846 }
847
848 if (errno != ENOTTY && errno != EACCES) {
849 if (raise)
850 PyErr_SetFromErrno(PyExc_OSError);
851 return -1;
852 }
853 else {
854 /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for
855 device". The ioctl is declared but not supported by the kernel.
856 Remember that ioctl() doesn't work. It is the case on
857 Illumos-based OS for example.
858
859 Issue #27057: When SELinux policy disallows ioctl it will fail
860 with EACCES. While FIOCLEX is safe operation it may be
861 unavailable because ioctl was denied altogether.
862 This can be the case on Android. */
863 ioctl_works = 0;
864 }
865 /* fallback to fcntl() if ioctl() does not work */
866 }
867 #endif
868
869 /* slow-path: fcntl() requires two syscalls */
870 flags = fcntl(fd, F_GETFD);
871 if (flags < 0) {
872 if (raise)
873 PyErr_SetFromErrno(PyExc_OSError);
874 return -1;
875 }
876
877 if (inheritable) {
878 new_flags = flags & ~FD_CLOEXEC;
879 }
880 else {
881 new_flags = flags | FD_CLOEXEC;
882 }
883
884 if (new_flags == flags) {
885 /* FD_CLOEXEC flag already set/cleared: nothing to do */
886 return 0;
887 }
888
889 res = fcntl(fd, F_SETFD, new_flags);
890 if (res < 0) {
891 if (raise)
892 PyErr_SetFromErrno(PyExc_OSError);
893 return -1;
894 }
895 return 0;
896 #endif
897 }
898
899 /* Make the file descriptor non-inheritable.
900 Return 0 on success, set errno and return -1 on error. */
901 static int
make_non_inheritable(int fd)902 make_non_inheritable(int fd)
903 {
904 return set_inheritable(fd, 0, 0, NULL);
905 }
906
907 /* Set the inheritable flag of the specified file descriptor.
908 On success: return 0, on error: raise an exception if raise is nonzero
909 and return -1.
910
911 If atomic_flag_works is not NULL:
912
913 * if *atomic_flag_works==-1, check if the inheritable is set on the file
914 descriptor: if yes, set *atomic_flag_works to 1, otherwise set to 0 and
915 set the inheritable flag
916 * if *atomic_flag_works==1: do nothing
917 * if *atomic_flag_works==0: set inheritable flag to False
918
919 Set atomic_flag_works to NULL if no atomic flag was used to create the
920 file descriptor.
921
922 atomic_flag_works can only be used to make a file descriptor
923 non-inheritable: atomic_flag_works must be NULL if inheritable=1. */
924 int
_Py_set_inheritable(int fd,int inheritable,int * atomic_flag_works)925 _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works)
926 {
927 return set_inheritable(fd, inheritable, 1, atomic_flag_works);
928 }
929
930 static int
_Py_open_impl(const char * pathname,int flags,int gil_held)931 _Py_open_impl(const char *pathname, int flags, int gil_held)
932 {
933 int fd;
934 int async_err = 0;
935 #ifndef MS_WINDOWS
936 int *atomic_flag_works;
937 #endif
938
939 #ifdef MS_WINDOWS
940 flags |= O_NOINHERIT;
941 #elif defined(O_CLOEXEC)
942 atomic_flag_works = &_Py_open_cloexec_works;
943 flags |= O_CLOEXEC;
944 #else
945 atomic_flag_works = NULL;
946 #endif
947
948 if (gil_held) {
949 do {
950 Py_BEGIN_ALLOW_THREADS
951 fd = open(pathname, flags);
952 Py_END_ALLOW_THREADS
953 } while (fd < 0
954 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
955 if (async_err)
956 return -1;
957 if (fd < 0) {
958 PyErr_SetFromErrnoWithFilename(PyExc_OSError, pathname);
959 return -1;
960 }
961 }
962 else {
963 fd = open(pathname, flags);
964 if (fd < 0)
965 return -1;
966 }
967
968 #ifndef MS_WINDOWS
969 if (set_inheritable(fd, 0, gil_held, atomic_flag_works) < 0) {
970 close(fd);
971 return -1;
972 }
973 #endif
974
975 return fd;
976 }
977
978 /* Open a file with the specified flags (wrapper to open() function).
979 Return a file descriptor on success. Raise an exception and return -1 on
980 error.
981
982 The file descriptor is created non-inheritable.
983
984 When interrupted by a signal (open() fails with EINTR), retry the syscall,
985 except if the Python signal handler raises an exception.
986
987 Release the GIL to call open(). The caller must hold the GIL. */
988 int
_Py_open(const char * pathname,int flags)989 _Py_open(const char *pathname, int flags)
990 {
991 #ifdef WITH_THREAD
992 /* _Py_open() must be called with the GIL held. */
993 assert(PyGILState_Check());
994 #endif
995 return _Py_open_impl(pathname, flags, 1);
996 }
997
998 /* Open a file with the specified flags (wrapper to open() function).
999 Return a file descriptor on success. Set errno and return -1 on error.
1000
1001 The file descriptor is created non-inheritable.
1002
1003 If interrupted by a signal, fail with EINTR. */
1004 int
_Py_open_noraise(const char * pathname,int flags)1005 _Py_open_noraise(const char *pathname, int flags)
1006 {
1007 return _Py_open_impl(pathname, flags, 0);
1008 }
1009
1010 /* Open a file. Use _wfopen() on Windows, encode the path to the locale
1011 encoding and use fopen() otherwise.
1012
1013 The file descriptor is created non-inheritable.
1014
1015 If interrupted by a signal, fail with EINTR. */
1016 FILE *
_Py_wfopen(const wchar_t * path,const wchar_t * mode)1017 _Py_wfopen(const wchar_t *path, const wchar_t *mode)
1018 {
1019 FILE *f;
1020 #ifndef MS_WINDOWS
1021 char *cpath;
1022 char cmode[10];
1023 size_t r;
1024 r = wcstombs(cmode, mode, 10);
1025 if (r == (size_t)-1 || r >= 10) {
1026 errno = EINVAL;
1027 return NULL;
1028 }
1029 cpath = Py_EncodeLocale(path, NULL);
1030 if (cpath == NULL)
1031 return NULL;
1032 f = fopen(cpath, cmode);
1033 PyMem_Free(cpath);
1034 #else
1035 f = _wfopen(path, mode);
1036 #endif
1037 if (f == NULL)
1038 return NULL;
1039 if (make_non_inheritable(fileno(f)) < 0) {
1040 fclose(f);
1041 return NULL;
1042 }
1043 return f;
1044 }
1045
1046 /* Wrapper to fopen().
1047
1048 The file descriptor is created non-inheritable.
1049
1050 If interrupted by a signal, fail with EINTR. */
1051 FILE*
_Py_fopen(const char * pathname,const char * mode)1052 _Py_fopen(const char *pathname, const char *mode)
1053 {
1054 FILE *f = fopen(pathname, mode);
1055 if (f == NULL)
1056 return NULL;
1057 if (make_non_inheritable(fileno(f)) < 0) {
1058 fclose(f);
1059 return NULL;
1060 }
1061 return f;
1062 }
1063
1064 /* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
1065 encoding and call fopen() otherwise.
1066
1067 Return the new file object on success. Raise an exception and return NULL
1068 on error.
1069
1070 The file descriptor is created non-inheritable.
1071
1072 When interrupted by a signal (open() fails with EINTR), retry the syscall,
1073 except if the Python signal handler raises an exception.
1074
1075 Release the GIL to call _wfopen() or fopen(). The caller must hold
1076 the GIL. */
1077 FILE*
_Py_fopen_obj(PyObject * path,const char * mode)1078 _Py_fopen_obj(PyObject *path, const char *mode)
1079 {
1080 FILE *f;
1081 int async_err = 0;
1082 #ifdef MS_WINDOWS
1083 wchar_t *wpath;
1084 wchar_t wmode[10];
1085 int usize;
1086
1087 #ifdef WITH_THREAD
1088 assert(PyGILState_Check());
1089 #endif
1090
1091 if (!PyUnicode_Check(path)) {
1092 PyErr_Format(PyExc_TypeError,
1093 "str file path expected under Windows, got %R",
1094 Py_TYPE(path));
1095 return NULL;
1096 }
1097 wpath = PyUnicode_AsUnicode(path);
1098 if (wpath == NULL)
1099 return NULL;
1100
1101 usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
1102 if (usize == 0) {
1103 PyErr_SetFromWindowsErr(0);
1104 return NULL;
1105 }
1106
1107 do {
1108 Py_BEGIN_ALLOW_THREADS
1109 f = _wfopen(wpath, wmode);
1110 Py_END_ALLOW_THREADS
1111 } while (f == NULL
1112 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1113 #else
1114 PyObject *bytes;
1115 char *path_bytes;
1116
1117 #ifdef WITH_THREAD
1118 assert(PyGILState_Check());
1119 #endif
1120
1121 if (!PyUnicode_FSConverter(path, &bytes))
1122 return NULL;
1123 path_bytes = PyBytes_AS_STRING(bytes);
1124
1125 do {
1126 Py_BEGIN_ALLOW_THREADS
1127 f = fopen(path_bytes, mode);
1128 Py_END_ALLOW_THREADS
1129 } while (f == NULL
1130 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1131
1132 Py_DECREF(bytes);
1133 #endif
1134 if (async_err)
1135 return NULL;
1136
1137 if (f == NULL) {
1138 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1139 return NULL;
1140 }
1141
1142 if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {
1143 fclose(f);
1144 return NULL;
1145 }
1146 return f;
1147 }
1148
1149 /* Read count bytes from fd into buf.
1150
1151 On success, return the number of read bytes, it can be lower than count.
1152 If the current file offset is at or past the end of file, no bytes are read,
1153 and read() returns zero.
1154
1155 On error, raise an exception, set errno and return -1.
1156
1157 When interrupted by a signal (read() fails with EINTR), retry the syscall.
1158 If the Python signal handler raises an exception, the function returns -1
1159 (the syscall is not retried).
1160
1161 Release the GIL to call read(). The caller must hold the GIL. */
1162 Py_ssize_t
_Py_read(int fd,void * buf,size_t count)1163 _Py_read(int fd, void *buf, size_t count)
1164 {
1165 Py_ssize_t n;
1166 int err;
1167 int async_err = 0;
1168
1169 #ifdef WITH_THREAD
1170 assert(PyGILState_Check());
1171 #endif
1172
1173 /* _Py_read() must not be called with an exception set, otherwise the
1174 * caller may think that read() was interrupted by a signal and the signal
1175 * handler raised an exception. */
1176 assert(!PyErr_Occurred());
1177
1178 #ifdef MS_WINDOWS
1179 if (count > INT_MAX) {
1180 /* On Windows, the count parameter of read() is an int */
1181 count = INT_MAX;
1182 }
1183 #else
1184 if (count > PY_SSIZE_T_MAX) {
1185 /* if count is greater than PY_SSIZE_T_MAX,
1186 * read() result is undefined */
1187 count = PY_SSIZE_T_MAX;
1188 }
1189 #endif
1190
1191 _Py_BEGIN_SUPPRESS_IPH
1192 do {
1193 Py_BEGIN_ALLOW_THREADS
1194 errno = 0;
1195 #ifdef MS_WINDOWS
1196 n = read(fd, buf, (int)count);
1197 #else
1198 n = read(fd, buf, count);
1199 #endif
1200 /* save/restore errno because PyErr_CheckSignals()
1201 * and PyErr_SetFromErrno() can modify it */
1202 err = errno;
1203 Py_END_ALLOW_THREADS
1204 } while (n < 0 && err == EINTR &&
1205 !(async_err = PyErr_CheckSignals()));
1206 _Py_END_SUPPRESS_IPH
1207
1208 if (async_err) {
1209 /* read() was interrupted by a signal (failed with EINTR)
1210 * and the Python signal handler raised an exception */
1211 errno = err;
1212 assert(errno == EINTR && PyErr_Occurred());
1213 return -1;
1214 }
1215 if (n < 0) {
1216 PyErr_SetFromErrno(PyExc_OSError);
1217 errno = err;
1218 return -1;
1219 }
1220
1221 return n;
1222 }
1223
1224 static Py_ssize_t
_Py_write_impl(int fd,const void * buf,size_t count,int gil_held)1225 _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
1226 {
1227 Py_ssize_t n;
1228 int err;
1229 int async_err = 0;
1230
1231 _Py_BEGIN_SUPPRESS_IPH
1232 #ifdef MS_WINDOWS
1233 if (count > 32767 && isatty(fd)) {
1234 /* Issue #11395: the Windows console returns an error (12: not
1235 enough space error) on writing into stdout if stdout mode is
1236 binary and the length is greater than 66,000 bytes (or less,
1237 depending on heap usage). */
1238 count = 32767;
1239 }
1240 else if (count > INT_MAX)
1241 count = INT_MAX;
1242 #else
1243 if (count > PY_SSIZE_T_MAX) {
1244 /* write() should truncate count to PY_SSIZE_T_MAX, but it's safer
1245 * to do it ourself to have a portable behaviour. */
1246 count = PY_SSIZE_T_MAX;
1247 }
1248 #endif
1249
1250 if (gil_held) {
1251 do {
1252 Py_BEGIN_ALLOW_THREADS
1253 errno = 0;
1254 #ifdef MS_WINDOWS
1255 n = write(fd, buf, (int)count);
1256 #else
1257 n = write(fd, buf, count);
1258 #endif
1259 /* save/restore errno because PyErr_CheckSignals()
1260 * and PyErr_SetFromErrno() can modify it */
1261 err = errno;
1262 Py_END_ALLOW_THREADS
1263 } while (n < 0 && err == EINTR &&
1264 !(async_err = PyErr_CheckSignals()));
1265 }
1266 else {
1267 do {
1268 errno = 0;
1269 #ifdef MS_WINDOWS
1270 n = write(fd, buf, (int)count);
1271 #else
1272 n = write(fd, buf, count);
1273 #endif
1274 err = errno;
1275 } while (n < 0 && err == EINTR);
1276 }
1277 _Py_END_SUPPRESS_IPH
1278
1279 if (async_err) {
1280 /* write() was interrupted by a signal (failed with EINTR)
1281 and the Python signal handler raised an exception (if gil_held is
1282 nonzero). */
1283 errno = err;
1284 assert(errno == EINTR && (!gil_held || PyErr_Occurred()));
1285 return -1;
1286 }
1287 if (n < 0) {
1288 if (gil_held)
1289 PyErr_SetFromErrno(PyExc_OSError);
1290 errno = err;
1291 return -1;
1292 }
1293
1294 return n;
1295 }
1296
1297 /* Write count bytes of buf into fd.
1298
1299 On success, return the number of written bytes, it can be lower than count
1300 including 0. On error, raise an exception, set errno and return -1.
1301
1302 When interrupted by a signal (write() fails with EINTR), retry the syscall.
1303 If the Python signal handler raises an exception, the function returns -1
1304 (the syscall is not retried).
1305
1306 Release the GIL to call write(). The caller must hold the GIL. */
1307 Py_ssize_t
_Py_write(int fd,const void * buf,size_t count)1308 _Py_write(int fd, const void *buf, size_t count)
1309 {
1310 #ifdef WITH_THREAD
1311 assert(PyGILState_Check());
1312 #endif
1313
1314 /* _Py_write() must not be called with an exception set, otherwise the
1315 * caller may think that write() was interrupted by a signal and the signal
1316 * handler raised an exception. */
1317 assert(!PyErr_Occurred());
1318
1319 return _Py_write_impl(fd, buf, count, 1);
1320 }
1321
1322 /* Write count bytes of buf into fd.
1323 *
1324 * On success, return the number of written bytes, it can be lower than count
1325 * including 0. On error, set errno and return -1.
1326 *
1327 * When interrupted by a signal (write() fails with EINTR), retry the syscall
1328 * without calling the Python signal handler. */
1329 Py_ssize_t
_Py_write_noraise(int fd,const void * buf,size_t count)1330 _Py_write_noraise(int fd, const void *buf, size_t count)
1331 {
1332 return _Py_write_impl(fd, buf, count, 0);
1333 }
1334
1335 #ifdef HAVE_READLINK
1336
1337 /* Read value of symbolic link. Encode the path to the locale encoding, decode
1338 the result from the locale encoding. Return -1 on error. */
1339
1340 int
_Py_wreadlink(const wchar_t * path,wchar_t * buf,size_t bufsiz)1341 _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
1342 {
1343 char *cpath;
1344 char cbuf[MAXPATHLEN];
1345 wchar_t *wbuf;
1346 int res;
1347 size_t r1;
1348
1349 cpath = Py_EncodeLocale(path, NULL);
1350 if (cpath == NULL) {
1351 errno = EINVAL;
1352 return -1;
1353 }
1354 res = (int)readlink(cpath, cbuf, Py_ARRAY_LENGTH(cbuf));
1355 PyMem_Free(cpath);
1356 if (res == -1)
1357 return -1;
1358 if (res == Py_ARRAY_LENGTH(cbuf)) {
1359 errno = EINVAL;
1360 return -1;
1361 }
1362 cbuf[res] = '\0'; /* buf will be null terminated */
1363 wbuf = Py_DecodeLocale(cbuf, &r1);
1364 if (wbuf == NULL) {
1365 errno = EINVAL;
1366 return -1;
1367 }
1368 if (bufsiz <= r1) {
1369 PyMem_RawFree(wbuf);
1370 errno = EINVAL;
1371 return -1;
1372 }
1373 wcsncpy(buf, wbuf, bufsiz);
1374 PyMem_RawFree(wbuf);
1375 return (int)r1;
1376 }
1377 #endif
1378
1379 #ifdef HAVE_REALPATH
1380
1381 /* Return the canonicalized absolute pathname. Encode path to the locale
1382 encoding, decode the result from the locale encoding.
1383 Return NULL on error. */
1384
1385 wchar_t*
_Py_wrealpath(const wchar_t * path,wchar_t * resolved_path,size_t resolved_path_size)1386 _Py_wrealpath(const wchar_t *path,
1387 wchar_t *resolved_path, size_t resolved_path_size)
1388 {
1389 char *cpath;
1390 char cresolved_path[MAXPATHLEN];
1391 wchar_t *wresolved_path;
1392 char *res;
1393 size_t r;
1394 cpath = Py_EncodeLocale(path, NULL);
1395 if (cpath == NULL) {
1396 errno = EINVAL;
1397 return NULL;
1398 }
1399 res = realpath(cpath, cresolved_path);
1400 PyMem_Free(cpath);
1401 if (res == NULL)
1402 return NULL;
1403
1404 wresolved_path = Py_DecodeLocale(cresolved_path, &r);
1405 if (wresolved_path == NULL) {
1406 errno = EINVAL;
1407 return NULL;
1408 }
1409 if (resolved_path_size <= r) {
1410 PyMem_RawFree(wresolved_path);
1411 errno = EINVAL;
1412 return NULL;
1413 }
1414 wcsncpy(resolved_path, wresolved_path, resolved_path_size);
1415 PyMem_RawFree(wresolved_path);
1416 return resolved_path;
1417 }
1418 #endif
1419
1420 /* Get the current directory. size is the buffer size in wide characters
1421 including the null character. Decode the path from the locale encoding.
1422 Return NULL on error. */
1423
1424 wchar_t*
_Py_wgetcwd(wchar_t * buf,size_t size)1425 _Py_wgetcwd(wchar_t *buf, size_t size)
1426 {
1427 #ifdef MS_WINDOWS
1428 int isize = (int)Py_MIN(size, INT_MAX);
1429 return _wgetcwd(buf, isize);
1430 #else
1431 char fname[MAXPATHLEN];
1432 wchar_t *wname;
1433 size_t len;
1434
1435 if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL)
1436 return NULL;
1437 wname = Py_DecodeLocale(fname, &len);
1438 if (wname == NULL)
1439 return NULL;
1440 if (size <= len) {
1441 PyMem_RawFree(wname);
1442 return NULL;
1443 }
1444 wcsncpy(buf, wname, size);
1445 PyMem_RawFree(wname);
1446 return buf;
1447 #endif
1448 }
1449
1450 /* Duplicate a file descriptor. The new file descriptor is created as
1451 non-inheritable. Return a new file descriptor on success, raise an OSError
1452 exception and return -1 on error.
1453
1454 The GIL is released to call dup(). The caller must hold the GIL. */
1455 int
_Py_dup(int fd)1456 _Py_dup(int fd)
1457 {
1458 #ifdef MS_WINDOWS
1459 HANDLE handle;
1460 DWORD ftype;
1461 #endif
1462
1463 #ifdef WITH_THREAD
1464 assert(PyGILState_Check());
1465 #endif
1466
1467 #ifdef MS_WINDOWS
1468 _Py_BEGIN_SUPPRESS_IPH
1469 handle = (HANDLE)_get_osfhandle(fd);
1470 _Py_END_SUPPRESS_IPH
1471 if (handle == INVALID_HANDLE_VALUE) {
1472 PyErr_SetFromErrno(PyExc_OSError);
1473 return -1;
1474 }
1475
1476 /* get the file type, ignore the error if it failed */
1477 ftype = GetFileType(handle);
1478
1479 Py_BEGIN_ALLOW_THREADS
1480 _Py_BEGIN_SUPPRESS_IPH
1481 fd = dup(fd);
1482 _Py_END_SUPPRESS_IPH
1483 Py_END_ALLOW_THREADS
1484 if (fd < 0) {
1485 PyErr_SetFromErrno(PyExc_OSError);
1486 return -1;
1487 }
1488
1489 /* Character files like console cannot be make non-inheritable */
1490 if (ftype != FILE_TYPE_CHAR) {
1491 if (_Py_set_inheritable(fd, 0, NULL) < 0) {
1492 _Py_BEGIN_SUPPRESS_IPH
1493 close(fd);
1494 _Py_END_SUPPRESS_IPH
1495 return -1;
1496 }
1497 }
1498 #elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC)
1499 Py_BEGIN_ALLOW_THREADS
1500 _Py_BEGIN_SUPPRESS_IPH
1501 fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
1502 _Py_END_SUPPRESS_IPH
1503 Py_END_ALLOW_THREADS
1504 if (fd < 0) {
1505 PyErr_SetFromErrno(PyExc_OSError);
1506 return -1;
1507 }
1508
1509 #else
1510 Py_BEGIN_ALLOW_THREADS
1511 _Py_BEGIN_SUPPRESS_IPH
1512 fd = dup(fd);
1513 _Py_END_SUPPRESS_IPH
1514 Py_END_ALLOW_THREADS
1515 if (fd < 0) {
1516 PyErr_SetFromErrno(PyExc_OSError);
1517 return -1;
1518 }
1519
1520 if (_Py_set_inheritable(fd, 0, NULL) < 0) {
1521 _Py_BEGIN_SUPPRESS_IPH
1522 close(fd);
1523 _Py_END_SUPPRESS_IPH
1524 return -1;
1525 }
1526 #endif
1527 return fd;
1528 }
1529
1530 #ifndef MS_WINDOWS
1531 /* Get the blocking mode of the file descriptor.
1532 Return 0 if the O_NONBLOCK flag is set, 1 if the flag is cleared,
1533 raise an exception and return -1 on error. */
1534 int
_Py_get_blocking(int fd)1535 _Py_get_blocking(int fd)
1536 {
1537 int flags;
1538 _Py_BEGIN_SUPPRESS_IPH
1539 flags = fcntl(fd, F_GETFL, 0);
1540 _Py_END_SUPPRESS_IPH
1541 if (flags < 0) {
1542 PyErr_SetFromErrno(PyExc_OSError);
1543 return -1;
1544 }
1545
1546 return !(flags & O_NONBLOCK);
1547 }
1548
1549 /* Set the blocking mode of the specified file descriptor.
1550
1551 Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag
1552 otherwise.
1553
1554 Return 0 on success, raise an exception and return -1 on error. */
1555 int
_Py_set_blocking(int fd,int blocking)1556 _Py_set_blocking(int fd, int blocking)
1557 {
1558 #if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)
1559 int arg = !blocking;
1560 if (ioctl(fd, FIONBIO, &arg) < 0)
1561 goto error;
1562 #else
1563 int flags, res;
1564
1565 _Py_BEGIN_SUPPRESS_IPH
1566 flags = fcntl(fd, F_GETFL, 0);
1567 if (flags >= 0) {
1568 if (blocking)
1569 flags = flags & (~O_NONBLOCK);
1570 else
1571 flags = flags | O_NONBLOCK;
1572
1573 res = fcntl(fd, F_SETFL, flags);
1574 } else {
1575 res = -1;
1576 }
1577 _Py_END_SUPPRESS_IPH
1578
1579 if (res < 0)
1580 goto error;
1581 #endif
1582 return 0;
1583
1584 error:
1585 PyErr_SetFromErrno(PyExc_OSError);
1586 return -1;
1587 }
1588 #endif
1589