You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1123 lines
29 KiB

13 years ago
  1. #include "Python.h"
  2. #include "osdefs.h"
  3. #include <locale.h>
  4. #ifdef MS_WINDOWS
  5. # include <windows.h>
  6. #endif
  7. #ifdef HAVE_LANGINFO_H
  8. #include <langinfo.h>
  9. #endif
  10. #ifdef HAVE_SYS_IOCTL_H
  11. #include <sys/ioctl.h>
  12. #endif
  13. #ifdef HAVE_FCNTL_H
  14. #include <fcntl.h>
  15. #endif /* HAVE_FCNTL_H */
  16. #ifdef __APPLE__
  17. extern wchar_t* _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size);
  18. #endif
  19. #ifdef O_CLOEXEC
  20. /* Does open() support the O_CLOEXEC flag? Possible values:
  21. -1: unknown
  22. 0: open() ignores O_CLOEXEC flag, ex: Linux kernel older than 2.6.23
  23. 1: open() supports O_CLOEXEC flag, close-on-exec is set
  24. The flag is used by _Py_open(), io.FileIO and os.open() */
  25. int _Py_open_cloexec_works = -1;
  26. #endif
  27. PyObject *
  28. _Py_device_encoding(int fd)
  29. {
  30. #if defined(MS_WINDOWS)
  31. UINT cp;
  32. #endif
  33. if (!_PyVerify_fd(fd) || !isatty(fd)) {
  34. Py_RETURN_NONE;
  35. }
  36. #if defined(MS_WINDOWS)
  37. if (fd == 0)
  38. cp = GetConsoleCP();
  39. else if (fd == 1 || fd == 2)
  40. cp = GetConsoleOutputCP();
  41. else
  42. cp = 0;
  43. /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application
  44. has no console */
  45. if (cp != 0)
  46. return PyUnicode_FromFormat("cp%u", (unsigned int)cp);
  47. #elif defined(CODESET)
  48. {
  49. char *codeset = nl_langinfo(CODESET);
  50. if (codeset != NULL && codeset[0] != 0)
  51. return PyUnicode_FromString(codeset);
  52. }
  53. #endif
  54. Py_RETURN_NONE;
  55. }
  56. #if !defined(__APPLE__) && !defined(MS_WINDOWS)
  57. extern int _Py_normalize_encoding(const char *, char *, size_t);
  58. /* Workaround FreeBSD and OpenIndiana locale encoding issue with the C locale.
  59. On these operating systems, nl_langinfo(CODESET) announces an alias of the
  60. ASCII encoding, whereas mbstowcs() and wcstombs() functions use the
  61. ISO-8859-1 encoding. The problem is that os.fsencode() and os.fsdecode() use
  62. locale.getpreferredencoding() codec. For example, if command line arguments
  63. are decoded by mbstowcs() and encoded back by os.fsencode(), we get a
  64. UnicodeEncodeError instead of retrieving the original byte string.
  65. The workaround is enabled if setlocale(LC_CTYPE, NULL) returns "C",
  66. nl_langinfo(CODESET) announces "ascii" (or an alias to ASCII), and at least
  67. one byte in range 0x80-0xff can be decoded from the locale encoding. The
  68. workaround is also enabled on error, for example if getting the locale
  69. failed.
  70. Values of force_ascii:
  71. 1: the workaround is used: Py_EncodeLocale() uses
  72. encode_ascii_surrogateescape() and Py_DecodeLocale() uses
  73. decode_ascii_surrogateescape()
  74. 0: the workaround is not used: Py_EncodeLocale() uses wcstombs() and
  75. Py_DecodeLocale() uses mbstowcs()
  76. -1: unknown, need to call check_force_ascii() to get the value
  77. */
  78. static int force_ascii = -1;
  79. static int
  80. check_force_ascii(void)
  81. {
  82. char *loc;
  83. #if defined(HAVE_LANGINFO_H) && defined(CODESET)
  84. char *codeset, **alias;
  85. char encoding[100];
  86. int is_ascii;
  87. unsigned int i;
  88. char* ascii_aliases[] = {
  89. "ascii",
  90. "646",
  91. "ansi-x3.4-1968",
  92. "ansi-x3-4-1968",
  93. "ansi-x3.4-1986",
  94. "cp367",
  95. "csascii",
  96. "ibm367",
  97. "iso646-us",
  98. "iso-646.irv-1991",
  99. "iso-ir-6",
  100. "us",
  101. "us-ascii",
  102. NULL
  103. };
  104. #endif
  105. loc = setlocale(LC_CTYPE, NULL);
  106. if (loc == NULL)
  107. goto error;
  108. if (strcmp(loc, "C") != 0) {
  109. /* the LC_CTYPE locale is different than C */
  110. return 0;
  111. }
  112. #if defined(HAVE_LANGINFO_H) && defined(CODESET)
  113. codeset = nl_langinfo(CODESET);
  114. if (!codeset || codeset[0] == '\0') {
  115. /* CODESET is not set or empty */
  116. goto error;
  117. }
  118. if (!_Py_normalize_encoding(codeset, encoding, sizeof(encoding)))
  119. goto error;
  120. is_ascii = 0;
  121. for (alias=ascii_aliases; *alias != NULL; alias++) {
  122. if (strcmp(encoding, *alias) == 0) {
  123. is_ascii = 1;
  124. break;
  125. }
  126. }
  127. if (!is_ascii) {
  128. /* nl_langinfo(CODESET) is not "ascii" or an alias of ASCII */
  129. return 0;
  130. }
  131. for (i=0x80; i<0xff; i++) {
  132. unsigned char ch;
  133. wchar_t wch;
  134. size_t res;
  135. ch = (unsigned char)i;
  136. res = mbstowcs(&wch, (char*)&ch, 1);
  137. if (res != (size_t)-1) {
  138. /* decoding a non-ASCII character from the locale encoding succeed:
  139. the locale encoding is not ASCII, force ASCII */
  140. return 1;
  141. }
  142. }
  143. /* None of the bytes in the range 0x80-0xff can be decoded from the locale
  144. encoding: the locale encoding is really ASCII */
  145. return 0;
  146. #else
  147. /* nl_langinfo(CODESET) is not available: always force ASCII */
  148. return 1;
  149. #endif
  150. error:
  151. /* if an error occured, force the ASCII encoding */
  152. return 1;
  153. }
  154. static char*
  155. encode_ascii_surrogateescape(const wchar_t *text, size_t *error_pos)
  156. {
  157. char *result = NULL, *out;
  158. size_t len, i;
  159. wchar_t ch;
  160. if (error_pos != NULL)
  161. *error_pos = (size_t)-1;
  162. len = wcslen(text);
  163. result = PyMem_Malloc(len + 1); /* +1 for NUL byte */
  164. if (result == NULL)
  165. return NULL;
  166. out = result;
  167. for (i=0; i<len; i++) {
  168. ch = text[i];
  169. if (ch <= 0x7f) {
  170. /* ASCII character */
  171. *out++ = (char)ch;
  172. }
  173. else if (0xdc80 <= ch && ch <= 0xdcff) {
  174. /* UTF-8b surrogate */
  175. *out++ = (char)(ch - 0xdc00);
  176. }
  177. else {
  178. if (error_pos != NULL)
  179. *error_pos = i;
  180. PyMem_Free(result);
  181. return NULL;
  182. }
  183. }
  184. *out = '\0';
  185. return result;
  186. }
  187. #endif /* !defined(__APPLE__) && !defined(MS_WINDOWS) */
  188. #if !defined(__APPLE__) && (!defined(MS_WINDOWS) || !defined(HAVE_MBRTOWC))
  189. static wchar_t*
  190. decode_ascii_surrogateescape(const char *arg, size_t *size)
  191. {
  192. wchar_t *res;
  193. unsigned char *in;
  194. wchar_t *out;
  195. res = PyMem_RawMalloc((strlen(arg)+1)*sizeof(wchar_t));
  196. if (!res)
  197. return NULL;
  198. in = (unsigned char*)arg;
  199. out = res;
  200. while(*in)
  201. if(*in < 128)
  202. *out++ = *in++;
  203. else
  204. *out++ = 0xdc00 + *in++;
  205. *out = 0;
  206. if (size != NULL)
  207. *size = out - res;
  208. return res;
  209. }
  210. #endif
  211. /* Decode a byte string from the locale encoding with the
  212. surrogateescape error handler: undecodable bytes are decoded as characters
  213. in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate
  214. character, escape the bytes using the surrogateescape error handler instead
  215. of decoding them.
  216. Return a pointer to a newly allocated wide character string, use
  217. PyMem_RawFree() to free the memory. If size is not NULL, write the number of
  218. wide characters excluding the null character into *size
  219. Return NULL on decoding error or memory allocation error. If *size* is not
  220. NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on
  221. decoding error.
  222. Decoding errors should never happen, unless there is a bug in the C
  223. library.
  224. Use the Py_EncodeLocale() function to encode the character string back to a
  225. byte string. */
  226. wchar_t*
  227. Py_DecodeLocale(const char* arg, size_t *size)
  228. {
  229. #ifdef __APPLE__
  230. wchar_t *wstr;
  231. wstr = _Py_DecodeUTF8_surrogateescape(arg, strlen(arg));
  232. if (size != NULL) {
  233. if (wstr != NULL)
  234. *size = wcslen(wstr);
  235. else
  236. *size = (size_t)-1;
  237. }
  238. return wstr;
  239. #else
  240. wchar_t *res;
  241. size_t argsize;
  242. size_t count;
  243. #ifdef HAVE_MBRTOWC
  244. unsigned char *in;
  245. wchar_t *out;
  246. mbstate_t mbs;
  247. #endif
  248. #ifndef MS_WINDOWS
  249. if (force_ascii == -1)
  250. force_ascii = check_force_ascii();
  251. if (force_ascii) {
  252. /* force ASCII encoding to workaround mbstowcs() issue */
  253. res = decode_ascii_surrogateescape(arg, size);
  254. if (res == NULL)
  255. goto oom;
  256. return res;
  257. }
  258. #endif
  259. #ifdef HAVE_BROKEN_MBSTOWCS
  260. /* Some platforms have a broken implementation of
  261. * mbstowcs which does not count the characters that
  262. * would result from conversion. Use an upper bound.
  263. */
  264. argsize = strlen(arg);
  265. #else
  266. argsize = mbstowcs(NULL, arg, 0);
  267. #endif
  268. if (argsize != (size_t)-1) {
  269. res = (wchar_t *)PyMem_RawMalloc((argsize+1)*sizeof(wchar_t));
  270. if (!res)
  271. goto oom;
  272. count = mbstowcs(res, arg, argsize+1);
  273. if (count != (size_t)-1) {
  274. wchar_t *tmp;
  275. /* Only use the result if it contains no
  276. surrogate characters. */
  277. for (tmp = res; *tmp != 0 &&
  278. !Py_UNICODE_IS_SURROGATE(*tmp); tmp++)
  279. ;
  280. if (*tmp == 0) {
  281. if (size != NULL)
  282. *size = count;
  283. return res;
  284. }
  285. }
  286. PyMem_RawFree(res);
  287. }
  288. /* Conversion failed. Fall back to escaping with surrogateescape. */
  289. #ifdef HAVE_MBRTOWC
  290. /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
  291. /* Overallocate; as multi-byte characters are in the argument, the
  292. actual output could use less memory. */
  293. argsize = strlen(arg) + 1;
  294. res = (wchar_t*)PyMem_RawMalloc(argsize*sizeof(wchar_t));
  295. if (!res)
  296. goto oom;
  297. in = (unsigned char*)arg;
  298. out = res;
  299. memset(&mbs, 0, sizeof mbs);
  300. while (argsize) {
  301. size_t converted = mbrtowc(out, (char*)in, argsize, &mbs);
  302. if (converted == 0)
  303. /* Reached end of string; null char stored. */
  304. break;
  305. if (converted == (size_t)-2) {
  306. /* Incomplete character. This should never happen,
  307. since we provide everything that we have -
  308. unless there is a bug in the C library, or I
  309. misunderstood how mbrtowc works. */
  310. PyMem_RawFree(res);
  311. if (size != NULL)
  312. *size = (size_t)-2;
  313. return NULL;
  314. }
  315. if (converted == (size_t)-1) {
  316. /* Conversion error. Escape as UTF-8b, and start over
  317. in the initial shift state. */
  318. *out++ = 0xdc00 + *in++;
  319. argsize--;
  320. memset(&mbs, 0, sizeof mbs);
  321. continue;
  322. }
  323. if (Py_UNICODE_IS_SURROGATE(*out)) {
  324. /* Surrogate character. Escape the original
  325. byte sequence with surrogateescape. */
  326. argsize -= converted;
  327. while (converted--)
  328. *out++ = 0xdc00 + *in++;
  329. continue;
  330. }
  331. /* successfully converted some bytes */
  332. in += converted;
  333. argsize -= converted;
  334. out++;
  335. }
  336. if (size != NULL)
  337. *size = out - res;
  338. #else /* HAVE_MBRTOWC */
  339. /* Cannot use C locale for escaping; manually escape as if charset
  340. is ASCII (i.e. escape all bytes > 128. This will still roundtrip
  341. correctly in the locale's charset, which must be an ASCII superset. */
  342. res = decode_ascii_surrogateescape(arg, size);
  343. if (res == NULL)
  344. goto oom;
  345. #endif /* HAVE_MBRTOWC */
  346. return res;
  347. oom:
  348. if (size != NULL)
  349. *size = (size_t)-1;
  350. return NULL;
  351. #endif /* __APPLE__ */
  352. }
  353. /* Encode a wide character string to the locale encoding with the
  354. surrogateescape error handler: surrogate characters in the range
  355. U+DC80..U+DCFF are converted to bytes 0x80..0xFF.
  356. Return a pointer to a newly allocated byte string, use PyMem_Free() to free
  357. the memory. Return NULL on encoding or memory allocation error.
  358. If error_pos is not NULL, *error_pos is set to the index of the invalid
  359. character on encoding error, or set to (size_t)-1 otherwise.
  360. Use the Py_DecodeLocale() function to decode the bytes string back to a wide
  361. character string. */
  362. char*
  363. Py_EncodeLocale(const wchar_t *text, size_t *error_pos)
  364. {
  365. #ifdef __APPLE__
  366. Py_ssize_t len;
  367. PyObject *unicode, *bytes = NULL;
  368. char *cpath;
  369. unicode = PyUnicode_FromWideChar(text, wcslen(text));
  370. if (unicode == NULL)
  371. return NULL;
  372. bytes = _PyUnicode_AsUTF8String(unicode, "surrogateescape");
  373. Py_DECREF(unicode);
  374. if (bytes == NULL) {
  375. PyErr_Clear();
  376. if (error_pos != NULL)
  377. *error_pos = (size_t)-1;
  378. return NULL;
  379. }
  380. len = PyBytes_GET_SIZE(bytes);
  381. cpath = PyMem_Malloc(len+1);
  382. if (cpath == NULL) {
  383. PyErr_Clear();
  384. Py_DECREF(bytes);
  385. if (error_pos != NULL)
  386. *error_pos = (size_t)-1;
  387. return NULL;
  388. }
  389. memcpy(cpath, PyBytes_AsString(bytes), len + 1);
  390. Py_DECREF(bytes);
  391. return cpath;
  392. #else /* __APPLE__ */
  393. const size_t len = wcslen(text);
  394. char *result = NULL, *bytes = NULL;
  395. size_t i, size, converted;
  396. wchar_t c, buf[2];
  397. #ifndef MS_WINDOWS
  398. if (force_ascii == -1)
  399. force_ascii = check_force_ascii();
  400. if (force_ascii)
  401. return encode_ascii_surrogateescape(text, error_pos);
  402. #endif
  403. /* The function works in two steps:
  404. 1. compute the length of the output buffer in bytes (size)
  405. 2. outputs the bytes */
  406. size = 0;
  407. buf[1] = 0;
  408. while (1) {
  409. for (i=0; i < len; i++) {
  410. c = text[i];
  411. if (c >= 0xdc80 && c <= 0xdcff) {
  412. /* UTF-8b surrogate */
  413. if (bytes != NULL) {
  414. *bytes++ = c - 0xdc00;
  415. size--;
  416. }
  417. else
  418. size++;
  419. continue;
  420. }
  421. else {
  422. buf[0] = c;
  423. if (bytes != NULL)
  424. converted = wcstombs(bytes, buf, size);
  425. else
  426. converted = wcstombs(NULL, buf, 0);
  427. if (converted == (size_t)-1) {
  428. if (result != NULL)
  429. PyMem_Free(result);
  430. if (error_pos != NULL)
  431. *error_pos = i;
  432. return NULL;
  433. }
  434. if (bytes != NULL) {
  435. bytes += converted;
  436. size -= converted;
  437. }
  438. else
  439. size += converted;
  440. }
  441. }
  442. if (result != NULL) {
  443. *bytes = '\0';
  444. break;
  445. }
  446. size += 1; /* nul byte at the end */
  447. result = PyMem_Malloc(size);
  448. if (result == NULL) {
  449. if (error_pos != NULL)
  450. *error_pos = (size_t)-1;
  451. return NULL;
  452. }
  453. bytes = result;
  454. }
  455. return result;
  456. #endif /* __APPLE__ */
  457. }
  458. /* In principle, this should use HAVE__WSTAT, and _wstat
  459. should be detected by autoconf. However, no current
  460. POSIX system provides that function, so testing for
  461. it is pointless.
  462. Not sure whether the MS_WINDOWS guards are necessary:
  463. perhaps for cygwin/mingw builds?
  464. */
  465. #if defined(HAVE_STAT) && !defined(MS_WINDOWS)
  466. /* Get file status. Encode the path to the locale encoding. */
  467. int
  468. _Py_wstat(const wchar_t* path, struct stat *buf)
  469. {
  470. int err;
  471. char *fname;
  472. fname = Py_EncodeLocale(path, NULL);
  473. if (fname == NULL) {
  474. errno = EINVAL;
  475. return -1;
  476. }
  477. err = stat(fname, buf);
  478. PyMem_Free(fname);
  479. return err;
  480. }
  481. #endif
  482. #ifdef HAVE_STAT
  483. /* Call _wstat() on Windows, or encode the path to the filesystem encoding and
  484. call stat() otherwise. Only fill st_mode attribute on Windows.
  485. Return 0 on success, -1 on _wstat() / stat() error, -2 if an exception was
  486. raised. */
  487. int
  488. _Py_stat(PyObject *path, struct stat *statbuf)
  489. {
  490. #ifdef MS_WINDOWS
  491. int err;
  492. struct _stat wstatbuf;
  493. wchar_t *wpath;
  494. wpath = PyUnicode_AsUnicode(path);
  495. if (wpath == NULL)
  496. return -2;
  497. err = _wstat(wpath, &wstatbuf);
  498. if (!err)
  499. statbuf->st_mode = wstatbuf.st_mode;
  500. return err;
  501. #else
  502. int ret;
  503. PyObject *bytes = PyUnicode_EncodeFSDefault(path);
  504. if (bytes == NULL)
  505. return -2;
  506. ret = stat(PyBytes_AS_STRING(bytes), statbuf);
  507. Py_DECREF(bytes);
  508. return ret;
  509. #endif
  510. }
  511. #endif
  512. static int
  513. get_inheritable(int fd, int raise)
  514. {
  515. #ifdef MS_WINDOWS
  516. HANDLE handle;
  517. DWORD flags;
  518. if (!_PyVerify_fd(fd)) {
  519. if (raise)
  520. PyErr_SetFromErrno(PyExc_OSError);
  521. return -1;
  522. }
  523. handle = (HANDLE)_get_osfhandle(fd);
  524. if (handle == INVALID_HANDLE_VALUE) {
  525. if (raise)
  526. PyErr_SetFromWindowsErr(0);
  527. return -1;
  528. }
  529. if (!GetHandleInformation(handle, &flags)) {
  530. if (raise)
  531. PyErr_SetFromWindowsErr(0);
  532. return -1;
  533. }
  534. return (flags & HANDLE_FLAG_INHERIT);
  535. #else
  536. int flags;
  537. flags = fcntl(fd, F_GETFD, 0);
  538. if (flags == -1) {
  539. if (raise)
  540. PyErr_SetFromErrno(PyExc_OSError);
  541. return -1;
  542. }
  543. return !(flags & FD_CLOEXEC);
  544. #endif
  545. }
  546. /* Get the inheritable flag of the specified file descriptor.
  547. Return 1 if the file descriptor can be inherited, 0 if it cannot,
  548. raise an exception and return -1 on error. */
  549. int
  550. _Py_get_inheritable(int fd)
  551. {
  552. return get_inheritable(fd, 1);
  553. }
  554. static int
  555. set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
  556. {
  557. #ifdef MS_WINDOWS
  558. HANDLE handle;
  559. DWORD flags;
  560. #else
  561. #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
  562. static int ioctl_works = -1;
  563. int request;
  564. int err;
  565. #endif
  566. int flags;
  567. int res;
  568. #endif
  569. /* atomic_flag_works can only be used to make the file descriptor
  570. non-inheritable */
  571. assert(!(atomic_flag_works != NULL && inheritable));
  572. if (atomic_flag_works != NULL && !inheritable) {
  573. if (*atomic_flag_works == -1) {
  574. int inheritable = get_inheritable(fd, raise);
  575. if (inheritable == -1)
  576. return -1;
  577. *atomic_flag_works = !inheritable;
  578. }
  579. if (*atomic_flag_works)
  580. return 0;
  581. }
  582. #ifdef MS_WINDOWS
  583. if (!_PyVerify_fd(fd)) {
  584. if (raise)
  585. PyErr_SetFromErrno(PyExc_OSError);
  586. return -1;
  587. }
  588. handle = (HANDLE)_get_osfhandle(fd);
  589. if (handle == INVALID_HANDLE_VALUE) {
  590. if (raise)
  591. PyErr_SetFromWindowsErr(0);
  592. return -1;
  593. }
  594. if (inheritable)
  595. flags = HANDLE_FLAG_INHERIT;
  596. else
  597. flags = 0;
  598. if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
  599. if (raise)
  600. PyErr_SetFromWindowsErr(0);
  601. return -1;
  602. }
  603. return 0;
  604. #else
  605. #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
  606. if (ioctl_works != 0) {
  607. /* fast-path: ioctl() only requires one syscall */
  608. if (inheritable)
  609. request = FIONCLEX;
  610. else
  611. request = FIOCLEX;
  612. err = ioctl(fd, request, NULL);
  613. if (!err) {
  614. ioctl_works = 1;
  615. return 0;
  616. }
  617. if (errno != ENOTTY) {
  618. if (raise)
  619. PyErr_SetFromErrno(PyExc_OSError);
  620. return -1;
  621. }
  622. else {
  623. /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for
  624. device". The ioctl is declared but not supported by the kernel.
  625. Remember that ioctl() doesn't work. It is the case on
  626. Illumos-based OS for example. */
  627. ioctl_works = 0;
  628. }
  629. /* fallback to fcntl() if ioctl() does not work */
  630. }
  631. #endif
  632. /* slow-path: fcntl() requires two syscalls */
  633. flags = fcntl(fd, F_GETFD);
  634. if (flags < 0) {
  635. if (raise)
  636. PyErr_SetFromErrno(PyExc_OSError);
  637. return -1;
  638. }
  639. if (inheritable)
  640. flags &= ~FD_CLOEXEC;
  641. else
  642. flags |= FD_CLOEXEC;
  643. res = fcntl(fd, F_SETFD, flags);
  644. if (res < 0) {
  645. if (raise)
  646. PyErr_SetFromErrno(PyExc_OSError);
  647. return -1;
  648. }
  649. return 0;
  650. #endif
  651. }
  652. /* Make the file descriptor non-inheritable.
  653. Return 0 on success, set errno and return -1 on error. */
  654. static int
  655. make_non_inheritable(int fd)
  656. {
  657. return set_inheritable(fd, 0, 0, NULL);
  658. }
  659. /* Set the inheritable flag of the specified file descriptor.
  660. On success: return 0, on error: raise an exception if raise is nonzero
  661. and return -1.
  662. If atomic_flag_works is not NULL:
  663. * if *atomic_flag_works==-1, check if the inheritable is set on the file
  664. descriptor: if yes, set *atomic_flag_works to 1, otherwise set to 0 and
  665. set the inheritable flag
  666. * if *atomic_flag_works==1: do nothing
  667. * if *atomic_flag_works==0: set inheritable flag to False
  668. Set atomic_flag_works to NULL if no atomic flag was used to create the
  669. file descriptor.
  670. atomic_flag_works can only be used to make a file descriptor
  671. non-inheritable: atomic_flag_works must be NULL if inheritable=1. */
  672. int
  673. _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works)
  674. {
  675. return set_inheritable(fd, inheritable, 1, atomic_flag_works);
  676. }
  677. /* Open a file with the specified flags (wrapper to open() function).
  678. The file descriptor is created non-inheritable. */
  679. int
  680. _Py_open(const char *pathname, int flags)
  681. {
  682. int fd;
  683. #ifdef MS_WINDOWS
  684. fd = open(pathname, flags | O_NOINHERIT);
  685. if (fd < 0)
  686. return fd;
  687. #else
  688. int *atomic_flag_works;
  689. #ifdef O_CLOEXEC
  690. atomic_flag_works = &_Py_open_cloexec_works;
  691. flags |= O_CLOEXEC;
  692. #else
  693. atomic_flag_works = NULL;
  694. #endif
  695. fd = open(pathname, flags);
  696. if (fd < 0)
  697. return fd;
  698. if (set_inheritable(fd, 0, 0, atomic_flag_works) < 0) {
  699. close(fd);
  700. return -1;
  701. }
  702. #endif /* !MS_WINDOWS */
  703. return fd;
  704. }
  705. /* Open a file. Use _wfopen() on Windows, encode the path to the locale
  706. encoding and use fopen() otherwise. The file descriptor is created
  707. non-inheritable. */
  708. FILE *
  709. _Py_wfopen(const wchar_t *path, const wchar_t *mode)
  710. {
  711. FILE *f;
  712. #ifndef MS_WINDOWS
  713. char *cpath;
  714. char cmode[10];
  715. size_t r;
  716. r = wcstombs(cmode, mode, 10);
  717. if (r == (size_t)-1 || r >= 10) {
  718. errno = EINVAL;
  719. return NULL;
  720. }
  721. cpath = Py_EncodeLocale(path, NULL);
  722. if (cpath == NULL)
  723. return NULL;
  724. f = fopen(cpath, cmode);
  725. PyMem_Free(cpath);
  726. #else
  727. f = _wfopen(path, mode);
  728. #endif
  729. if (f == NULL)
  730. return NULL;
  731. if (make_non_inheritable(fileno(f)) < 0) {
  732. fclose(f);
  733. return NULL;
  734. }
  735. return f;
  736. }
  737. /* Wrapper to fopen(). The file descriptor is created non-inheritable. */
  738. FILE*
  739. _Py_fopen(const char *pathname, const char *mode)
  740. {
  741. FILE *f = fopen(pathname, mode);
  742. if (f == NULL)
  743. return NULL;
  744. if (make_non_inheritable(fileno(f)) < 0) {
  745. fclose(f);
  746. return NULL;
  747. }
  748. return f;
  749. }
  750. /* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem
  751. encoding and call fopen() otherwise. The file descriptor is created
  752. non-inheritable.
  753. Return the new file object on success, or NULL if the file cannot be open or
  754. (if PyErr_Occurred()) on unicode error. */
  755. FILE*
  756. _Py_fopen_obj(PyObject *path, const char *mode)
  757. {
  758. FILE *f;
  759. #ifdef MS_WINDOWS
  760. wchar_t *wpath;
  761. wchar_t wmode[10];
  762. int usize;
  763. if (!PyUnicode_Check(path)) {
  764. PyErr_Format(PyExc_TypeError,
  765. "str file path expected under Windows, got %R",
  766. Py_TYPE(path));
  767. return NULL;
  768. }
  769. wpath = PyUnicode_AsUnicode(path);
  770. if (wpath == NULL)
  771. return NULL;
  772. usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
  773. if (usize == 0)
  774. return NULL;
  775. f = _wfopen(wpath, wmode);
  776. #else
  777. PyObject *bytes;
  778. if (!PyUnicode_FSConverter(path, &bytes))
  779. return NULL;
  780. f = fopen(PyBytes_AS_STRING(bytes), mode);
  781. Py_DECREF(bytes);
  782. #endif
  783. if (f == NULL)
  784. return NULL;
  785. if (make_non_inheritable(fileno(f)) < 0) {
  786. fclose(f);
  787. return NULL;
  788. }
  789. return f;
  790. }
  791. #ifdef HAVE_READLINK
  792. /* Read value of symbolic link. Encode the path to the locale encoding, decode
  793. the result from the locale encoding. Return -1 on error. */
  794. int
  795. _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
  796. {
  797. char *cpath;
  798. char cbuf[MAXPATHLEN];
  799. wchar_t *wbuf;
  800. int res;
  801. size_t r1;
  802. cpath = Py_EncodeLocale(path, NULL);
  803. if (cpath == NULL) {
  804. errno = EINVAL;
  805. return -1;
  806. }
  807. res = (int)readlink(cpath, cbuf, Py_ARRAY_LENGTH(cbuf));
  808. PyMem_Free(cpath);
  809. if (res == -1)
  810. return -1;
  811. if (res == Py_ARRAY_LENGTH(cbuf)) {
  812. errno = EINVAL;
  813. return -1;
  814. }
  815. cbuf[res] = '\0'; /* buf will be null terminated */
  816. wbuf = Py_DecodeLocale(cbuf, &r1);
  817. if (wbuf == NULL) {
  818. errno = EINVAL;
  819. return -1;
  820. }
  821. if (bufsiz <= r1) {
  822. PyMem_RawFree(wbuf);
  823. errno = EINVAL;
  824. return -1;
  825. }
  826. wcsncpy(buf, wbuf, bufsiz);
  827. PyMem_RawFree(wbuf);
  828. return (int)r1;
  829. }
  830. #endif
  831. #ifdef HAVE_REALPATH
  832. /* Return the canonicalized absolute pathname. Encode path to the locale
  833. encoding, decode the result from the locale encoding.
  834. Return NULL on error. */
  835. wchar_t*
  836. _Py_wrealpath(const wchar_t *path,
  837. wchar_t *resolved_path, size_t resolved_path_size)
  838. {
  839. char *cpath;
  840. char cresolved_path[MAXPATHLEN];
  841. wchar_t *wresolved_path;
  842. char *res;
  843. size_t r;
  844. cpath = Py_EncodeLocale(path, NULL);
  845. if (cpath == NULL) {
  846. errno = EINVAL;
  847. return NULL;
  848. }
  849. res = realpath(cpath, cresolved_path);
  850. PyMem_Free(cpath);
  851. if (res == NULL)
  852. return NULL;
  853. wresolved_path = Py_DecodeLocale(cresolved_path, &r);
  854. if (wresolved_path == NULL) {
  855. errno = EINVAL;
  856. return NULL;
  857. }
  858. if (resolved_path_size <= r) {
  859. PyMem_RawFree(wresolved_path);
  860. errno = EINVAL;
  861. return NULL;
  862. }
  863. wcsncpy(resolved_path, wresolved_path, resolved_path_size);
  864. PyMem_RawFree(wresolved_path);
  865. return resolved_path;
  866. }
  867. #endif
  868. /* Get the current directory. size is the buffer size in wide characters
  869. including the null character. Decode the path from the locale encoding.
  870. Return NULL on error. */
  871. wchar_t*
  872. _Py_wgetcwd(wchar_t *buf, size_t size)
  873. {
  874. #ifdef MS_WINDOWS
  875. int isize = (int)Py_MIN(size, INT_MAX);
  876. return _wgetcwd(buf, isize);
  877. #else
  878. char fname[MAXPATHLEN];
  879. wchar_t *wname;
  880. size_t len;
  881. if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL)
  882. return NULL;
  883. wname = Py_DecodeLocale(fname, &len);
  884. if (wname == NULL)
  885. return NULL;
  886. if (size <= len) {
  887. PyMem_RawFree(wname);
  888. return NULL;
  889. }
  890. wcsncpy(buf, wname, size);
  891. PyMem_RawFree(wname);
  892. return buf;
  893. #endif
  894. }
  895. /* Duplicate a file descriptor. The new file descriptor is created as
  896. non-inheritable. Return a new file descriptor on success, raise an OSError
  897. exception and return -1 on error.
  898. The GIL is released to call dup(). The caller must hold the GIL. */
  899. int
  900. _Py_dup(int fd)
  901. {
  902. #ifdef MS_WINDOWS
  903. HANDLE handle;
  904. DWORD ftype;
  905. #endif
  906. if (!_PyVerify_fd(fd)) {
  907. PyErr_SetFromErrno(PyExc_OSError);
  908. return -1;
  909. }
  910. #ifdef MS_WINDOWS
  911. handle = (HANDLE)_get_osfhandle(fd);
  912. if (handle == INVALID_HANDLE_VALUE) {
  913. PyErr_SetFromWindowsErr(0);
  914. return -1;
  915. }
  916. /* get the file type, ignore the error if it failed */
  917. ftype = GetFileType(handle);
  918. Py_BEGIN_ALLOW_THREADS
  919. fd = dup(fd);
  920. Py_END_ALLOW_THREADS
  921. if (fd < 0) {
  922. PyErr_SetFromErrno(PyExc_OSError);
  923. return -1;
  924. }
  925. /* Character files like console cannot be make non-inheritable */
  926. if (ftype != FILE_TYPE_CHAR) {
  927. if (_Py_set_inheritable(fd, 0, NULL) < 0) {
  928. close(fd);
  929. return -1;
  930. }
  931. }
  932. #elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC)
  933. Py_BEGIN_ALLOW_THREADS
  934. fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
  935. Py_END_ALLOW_THREADS
  936. if (fd < 0) {
  937. PyErr_SetFromErrno(PyExc_OSError);
  938. return -1;
  939. }
  940. #else
  941. Py_BEGIN_ALLOW_THREADS
  942. fd = dup(fd);
  943. Py_END_ALLOW_THREADS
  944. if (fd < 0) {
  945. PyErr_SetFromErrno(PyExc_OSError);
  946. return -1;
  947. }
  948. if (_Py_set_inheritable(fd, 0, NULL) < 0) {
  949. close(fd);
  950. return -1;
  951. }
  952. #endif
  953. return fd;
  954. }
  955. #ifndef MS_WINDOWS
  956. /* Get the blocking mode of the file descriptor.
  957. Return 0 if the O_NONBLOCK flag is set, 1 if the flag is cleared,
  958. raise an exception and return -1 on error. */
  959. int
  960. _Py_get_blocking(int fd)
  961. {
  962. int flags = fcntl(fd, F_GETFL, 0);
  963. if (flags < 0) {
  964. PyErr_SetFromErrno(PyExc_OSError);
  965. return -1;
  966. }
  967. return !(flags & O_NONBLOCK);
  968. }
  969. /* Set the blocking mode of the specified file descriptor.
  970. Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag
  971. otherwise.
  972. Return 0 on success, raise an exception and return -1 on error. */
  973. int
  974. _Py_set_blocking(int fd, int blocking)
  975. {
  976. #if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)
  977. int arg = !blocking;
  978. if (ioctl(fd, FIONBIO, &arg) < 0)
  979. goto error;
  980. #else
  981. int flags, res;
  982. flags = fcntl(fd, F_GETFL, 0);
  983. if (flags < 0)
  984. goto error;
  985. if (blocking)
  986. flags = flags & (~O_NONBLOCK);
  987. else
  988. flags = flags | O_NONBLOCK;
  989. res = fcntl(fd, F_SETFL, flags);
  990. if (res < 0)
  991. goto error;
  992. #endif
  993. return 0;
  994. error:
  995. PyErr_SetFromErrno(PyExc_OSError);
  996. return -1;
  997. }
  998. #endif