diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/fileutils.c | |
parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
download | ydb-d4be68e361f4258cf0848fc70018dfe37a2acc24.tar.gz |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Python/fileutils.c')
-rw-r--r-- | contrib/tools/python3/src/Python/fileutils.c | 284 |
1 files changed, 218 insertions, 66 deletions
diff --git a/contrib/tools/python3/src/Python/fileutils.c b/contrib/tools/python3/src/Python/fileutils.c index 26e97df4ef..c3144ee407 100644 --- a/contrib/tools/python3/src/Python/fileutils.c +++ b/contrib/tools/python3/src/Python/fileutils.c @@ -1,5 +1,6 @@ #include "Python.h" -#include "pycore_fileutils.h" +#include "pycore_fileutils.h" // fileutils definitions +#include "pycore_runtime.h" // _PyRuntime #include "osdefs.h" // SEP #include <locale.h> @@ -65,9 +66,6 @@ get_surrogateescape(_Py_error_handler errors, int *surrogateescape) PyObject * _Py_device_encoding(int fd) { -#if defined(MS_WINDOWS) - UINT cp; -#endif int valid; Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH @@ -78,6 +76,7 @@ _Py_device_encoding(int fd) Py_RETURN_NONE; #if defined(MS_WINDOWS) + UINT cp; if (fd == 0) cp = GetConsoleCP(); else if (fd == 1 || fd == 2) @@ -86,16 +85,14 @@ _Py_device_encoding(int fd) cp = 0; /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application has no console */ - if (cp != 0) - return PyUnicode_FromFormat("cp%u", (unsigned int)cp); -#elif defined(CODESET) - { - char *codeset = nl_langinfo(CODESET); - if (codeset != NULL && codeset[0] != 0) - return PyUnicode_FromString(codeset); + if (cp == 0) { + Py_RETURN_NONE; } + + return PyUnicode_FromFormat("cp%u", (unsigned int)cp); +#else + return _Py_GetLocaleEncodingObject(); #endif - Py_RETURN_NONE; } @@ -871,6 +868,72 @@ _Py_EncodeLocaleEx(const wchar_t *text, char **str, current_locale, errors); } + +// Get the current locale encoding name: +// +// - Return "UTF-8" if _Py_FORCE_UTF8_LOCALE macro is defined (ex: on Android) +// - Return "UTF-8" if the UTF-8 Mode is enabled +// - On Windows, return the ANSI code page (ex: "cp1250") +// - Return "UTF-8" if nl_langinfo(CODESET) returns an empty string. +// - Otherwise, return nl_langinfo(CODESET). +// +// Return NULL on memory allocation failure. +// +// See also config_get_locale_encoding() +wchar_t* +_Py_GetLocaleEncoding(void) +{ +#ifdef _Py_FORCE_UTF8_LOCALE + // On Android langinfo.h and CODESET are missing, + // and UTF-8 is always used in mbstowcs() and wcstombs(). + return _PyMem_RawWcsdup(L"UTF-8"); +#else + const PyPreConfig *preconfig = &_PyRuntime.preconfig; + if (preconfig->utf8_mode) { + return _PyMem_RawWcsdup(L"UTF-8"); + } + +#ifdef MS_WINDOWS + wchar_t encoding[23]; + unsigned int ansi_codepage = GetACP(); + swprintf(encoding, Py_ARRAY_LENGTH(encoding), L"cp%u", ansi_codepage); + encoding[Py_ARRAY_LENGTH(encoding) - 1] = 0; + return _PyMem_RawWcsdup(encoding); +#else + const char *encoding = nl_langinfo(CODESET); + if (!encoding || encoding[0] == '\0') { + // Use UTF-8 if nl_langinfo() returns an empty string. It can happen on + // macOS if the LC_CTYPE locale is not supported. + return _PyMem_RawWcsdup(L"UTF-8"); + } + + wchar_t *wstr; + int res = decode_current_locale(encoding, &wstr, NULL, + NULL, _Py_ERROR_SURROGATEESCAPE); + if (res < 0) { + return NULL; + } + return wstr; +#endif // !MS_WINDOWS + +#endif // !_Py_FORCE_UTF8_LOCALE +} + + +PyObject * +_Py_GetLocaleEncodingObject(void) +{ + wchar_t *encoding = _Py_GetLocaleEncoding(); + if (encoding == NULL) { + PyErr_NoMemory(); + return NULL; + } + + PyObject *str = PyUnicode_FromWideChar(encoding, -1); + PyMem_RawFree(encoding); + return str; +} + #ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION /* Check whether current locale uses Unicode as internal wchar_t form. */ @@ -1061,9 +1124,7 @@ _Py_fstat_noraise(int fd, struct _Py_stat_struct *status) HANDLE h; int type; - _Py_BEGIN_SUPPRESS_IPH - h = (HANDLE)_get_osfhandle(fd); - _Py_END_SUPPRESS_IPH + h = _Py_get_osfhandle_noraise(fd); if (h == INVALID_HANDLE_VALUE) { /* errno is already set by _get_osfhandle, but we also set @@ -1156,18 +1217,21 @@ _Py_stat(PyObject *path, struct stat *statbuf) #ifdef MS_WINDOWS int err; struct _stat wstatbuf; - const wchar_t *wpath; -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - wpath = _PyUnicode_AsUnicode(path); -_Py_COMP_DIAG_POP +#if USE_UNICODE_WCHAR_CACHE + const wchar_t *wpath = _PyUnicode_AsUnicode(path); +#else /* USE_UNICODE_WCHAR_CACHE */ + wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (wpath == NULL) return -2; err = _wstat(wpath, &wstatbuf); if (!err) statbuf->st_mode = wstatbuf.st_mode; +#if !USE_UNICODE_WCHAR_CACHE + PyMem_Free(wpath); +#endif /* USE_UNICODE_WCHAR_CACHE */ return err; #else int ret; @@ -1199,9 +1263,7 @@ get_inheritable(int fd, int raise) HANDLE handle; DWORD flags; - _Py_BEGIN_SUPPRESS_IPH - handle = (HANDLE)_get_osfhandle(fd); - _Py_END_SUPPRESS_IPH + handle = _Py_get_osfhandle_noraise(fd); if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromErrno(PyExc_OSError); @@ -1272,9 +1334,7 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) } #ifdef MS_WINDOWS - _Py_BEGIN_SUPPRESS_IPH - handle = (HANDLE)_get_osfhandle(fd); - _Py_END_SUPPRESS_IPH + handle = _Py_get_osfhandle_noraise(fd); if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromErrno(PyExc_OSError); @@ -1545,33 +1605,6 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode) return f; } -/* Wrapper to fopen(). - - The file descriptor is created non-inheritable. - - If interrupted by a signal, fail with EINTR. */ -FILE* -_Py_fopen(const char *pathname, const char *mode) -{ - PyObject *pathname_obj = PyUnicode_DecodeFSDefault(pathname); - if (pathname_obj == NULL) { - return NULL; - } - if (PySys_Audit("open", "Osi", pathname_obj, mode, 0) < 0) { - Py_DECREF(pathname_obj); - return NULL; - } - Py_DECREF(pathname_obj); - - FILE *f = fopen(pathname, mode); - if (f == NULL) - return NULL; - if (make_non_inheritable(fileno(f)) < 0) { - fclose(f); - return NULL; - } - return f; -} /* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem encoding and call fopen() otherwise. @@ -1592,7 +1625,6 @@ _Py_fopen_obj(PyObject *path, const char *mode) FILE *f; int async_err = 0; #ifdef MS_WINDOWS - const wchar_t *wpath; wchar_t wmode[10]; int usize; @@ -1607,10 +1639,11 @@ _Py_fopen_obj(PyObject *path, const char *mode) Py_TYPE(path)); return NULL; } -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - wpath = _PyUnicode_AsUnicode(path); -_Py_COMP_DIAG_POP +#if USE_UNICODE_WCHAR_CACHE + const wchar_t *wpath = _PyUnicode_AsUnicode(path); +#else /* USE_UNICODE_WCHAR_CACHE */ + wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (wpath == NULL) return NULL; @@ -1618,6 +1651,9 @@ _Py_COMP_DIAG_POP wmode, Py_ARRAY_LENGTH(wmode)); if (usize == 0) { PyErr_SetFromWindowsErr(0); +#if !USE_UNICODE_WCHAR_CACHE + PyMem_Free(wpath); +#endif /* USE_UNICODE_WCHAR_CACHE */ return NULL; } @@ -1627,6 +1663,9 @@ _Py_COMP_DIAG_POP Py_END_ALLOW_THREADS } while (f == NULL && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#if !USE_UNICODE_WCHAR_CACHE + PyMem_Free(wpath); +#endif /* USE_UNICODE_WCHAR_CACHE */ #else PyObject *bytes; const char *path_bytes; @@ -2080,13 +2119,9 @@ _Py_dup(int fd) assert(PyGILState_Check()); #ifdef MS_WINDOWS - _Py_BEGIN_SUPPRESS_IPH - handle = (HANDLE)_get_osfhandle(fd); - _Py_END_SUPPRESS_IPH - if (handle == INVALID_HANDLE_VALUE) { - PyErr_SetFromErrno(PyExc_OSError); + handle = _Py_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) return -1; - } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH @@ -2164,7 +2199,9 @@ _Py_get_blocking(int fd) int _Py_set_blocking(int fd, int blocking) { -#if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO) +/* bpo-41462: On VxWorks, ioctl(FIONBIO) only works on sockets. + Use fcntl() instead. */ +#if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO) && !defined(__VXWORKS__) int arg = !blocking; if (ioctl(fd, FIONBIO, &arg) < 0) goto error; @@ -2194,8 +2231,47 @@ error: PyErr_SetFromErrno(PyExc_OSError); return -1; } -#endif +#else /* MS_WINDOWS */ +void* +_Py_get_osfhandle_noraise(int fd) +{ + void *handle; + _Py_BEGIN_SUPPRESS_IPH + handle = (void*)_get_osfhandle(fd); + _Py_END_SUPPRESS_IPH + return handle; +} + +void* +_Py_get_osfhandle(int fd) +{ + void *handle = _Py_get_osfhandle_noraise(fd); + if (handle == INVALID_HANDLE_VALUE) + PyErr_SetFromErrno(PyExc_OSError); + return handle; +} + +int +_Py_open_osfhandle_noraise(void *handle, int flags) +{ + int fd; + _Py_BEGIN_SUPPRESS_IPH + fd = _open_osfhandle((intptr_t)handle, flags); + _Py_END_SUPPRESS_IPH + return fd; +} + +int +_Py_open_osfhandle(void *handle, int flags) +{ + int fd = _Py_open_osfhandle_noraise(handle, flags); + if (fd == -1) + PyErr_SetFromErrno(PyExc_OSError); + + return fd; +} +#endif /* MS_WINDOWS */ int _Py_GetLocaleconvNumeric(struct lconv *lc, @@ -2274,3 +2350,79 @@ done: #undef GET_LOCALE_STRING } + +/* Our selection logic for which function to use is as follows: + * 1. If close_range(2) is available, always prefer that; it's better for + * contiguous ranges like this than fdwalk(3) which entails iterating over + * the entire fd space and simply doing nothing for those outside the range. + * 2. If closefrom(2) is available, we'll attempt to use that next if we're + * closing up to sysconf(_SC_OPEN_MAX). + * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX), + * as that will be more performant if the range happens to have any chunk of + * non-opened fd in the middle. + * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop. + */ +#ifdef __FreeBSD__ +# define USE_CLOSEFROM +#endif /* __FreeBSD__ */ + +#ifdef HAVE_FDWALK +# define USE_FDWALK +#endif /* HAVE_FDWALK */ + +#ifdef USE_FDWALK +static int +_fdwalk_close_func(void *lohi, int fd) +{ + int lo = ((int *)lohi)[0]; + int hi = ((int *)lohi)[1]; + + if (fd >= hi) { + return 1; + } + else if (fd >= lo) { + /* Ignore errors */ + (void)close(fd); + } + return 0; +} +#endif /* USE_FDWALK */ + +/* Closes all file descriptors in [first, last], ignoring errors. */ +void +_Py_closerange(int first, int last) +{ + first = Py_MAX(first, 0); + _Py_BEGIN_SUPPRESS_IPH +#ifdef HAVE_CLOSE_RANGE + if (close_range(first, last, 0) == 0 || errno != ENOSYS) { + /* Any errors encountered while closing file descriptors are ignored; + * ENOSYS means no kernel support, though, + * so we'll fallback to the other methods. */ + } + else +#endif /* HAVE_CLOSE_RANGE */ +#ifdef USE_CLOSEFROM + if (last >= sysconf(_SC_OPEN_MAX)) { + /* Any errors encountered while closing file descriptors are ignored */ + closefrom(first); + } + else +#endif /* USE_CLOSEFROM */ +#ifdef USE_FDWALK + { + int lohi[2]; + lohi[0] = first; + lohi[1] = last + 1; + fdwalk(_fdwalk_close_func, lohi); + } +#else + { + for (int i = first; i <= last; i++) { + /* Ignore errors */ + (void)close(i); + } + } +#endif /* USE_FDWALK */ + _Py_END_SUPPRESS_IPH +} |