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 * 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 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* 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* 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* 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* 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 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 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 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 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 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 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 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 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 775 _Py_get_inheritable(int fd) 776 { 777 return get_inheritable(fd, 1); 778 } 779 780 static int 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 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 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 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 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 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 * 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* 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* 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 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 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 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 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 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* 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* 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 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 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 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