aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Python/fileutils.c
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.ru>2022-04-18 12:39:32 +0300
committershadchin <shadchin@yandex-team.ru>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/fileutils.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff)
downloadydb-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.c284
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
+}