summaryrefslogtreecommitdiff
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2017-02-09 16:08:17 +0100
committerNick Coghlan <ncoghlan@gmail.com>2017-02-09 16:08:17 +0100
commitc6180bb73c8c7c7f9d8ea9816487b710597b6fc1 (patch)
treefb4a5c18886537b4b7df46ed3b2aa579747ff507 /Modules/posixmodule.c
parent5e0114a832a903518c4af6983161c0c2a8942a24 (diff)
parent819a21a3a4aac38f32e1ba4f68bcef45591fa3f0 (diff)
downloadcpython-c6180bb73c8c7c7f9d8ea9816487b710597b6fc1.tar.gz
Merge issue #26355 fix from Python 3.5
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c1888
1 files changed, 922 insertions, 966 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 3e446a524e..dc3fb94c87 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -32,6 +32,12 @@
#include "winreparse.h"
#endif
+/* On android API level 21, 'AT_EACCESS' is not declared although
+ * HAVE_FACCESSAT is defined. */
+#ifdef __ANDROID__
+#undef HAVE_FACCESSAT
+#endif
+
#include <stdio.h> /* needed for ctermid() */
#ifdef __cplusplus
@@ -127,6 +133,13 @@ corresponding Unix manual entries for more information on calls.");
#include <sys/sysctl.h>
#endif
+#ifdef HAVE_LINUX_RANDOM_H
+# include <linux/random.h>
+#endif
+#ifdef HAVE_GETRANDOM_SYSCALL
+# include <sys/syscall.h>
+#endif
+
#if defined(MS_WINDOWS)
# define TERMSIZE_USE_CONIO
#elif defined(HAVE_SYS_IOCTL_H)
@@ -151,6 +164,8 @@ corresponding Unix manual entries for more information on calls.");
#define HAVE_GETLOGIN 1
#define HAVE_SPAWNV 1
#define HAVE_EXECV 1
+#define HAVE_WSPAWNV 1
+#define HAVE_WEXECV 1
#define HAVE_PIPE 1
#define HAVE_SYSTEM 1
#define HAVE_CWAIT 1
@@ -634,22 +649,14 @@ fail:
#endif /* MS_WINDOWS */
-#ifdef HAVE_LONG_LONG
-# define _PyLong_FromDev PyLong_FromLongLong
-#else
-# define _PyLong_FromDev PyLong_FromLong
-#endif
+#define _PyLong_FromDev PyLong_FromLongLong
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
static int
_Py_Dev_Converter(PyObject *obj, void *p)
{
-#ifdef HAVE_LONG_LONG
*((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
-#else
- *((dev_t *)p) = PyLong_AsUnsignedLong(obj);
-#endif
if (PyErr_Occurred())
return 0;
return 1;
@@ -671,21 +678,20 @@ _Py_Dev_Converter(PyObject *obj, void *p)
#endif
static int
-_fd_converter(PyObject *o, int *p, const char *allowed)
+_fd_converter(PyObject *o, int *p)
{
int overflow;
long long_value;
PyObject *index = PyNumber_Index(o);
if (index == NULL) {
- PyErr_Format(PyExc_TypeError,
- "argument should be %s, not %.200s",
- allowed, Py_TYPE(o)->tp_name);
return 0;
}
+ assert(PyLong_Check(index));
long_value = PyLong_AsLongAndOverflow(index, &overflow);
Py_DECREF(index);
+ assert(!PyErr_Occurred());
if (overflow > 0 || long_value > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"fd is greater than maximum");
@@ -708,7 +714,15 @@ dir_fd_converter(PyObject *o, void *p)
*(int *)p = DEFAULT_DIR_FD;
return 1;
}
- return _fd_converter(o, (int *)p, "integer");
+ else if (PyIndex_Check(o)) {
+ return _fd_converter(o, (int *)p);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "argument should be integer or None, not %.200s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
}
@@ -723,7 +737,7 @@ dir_fd_converter(PyObject *o, void *p)
*
* * On Windows, if we get a (Unicode) string we
* extract the wchar_t * and return it; if we get
- * bytes we extract the char * and return that.
+ * bytes we decode to wchar_t * and return that.
*
* * On all other platforms, strings are encoded
* to bytes using PyUnicode_FSConverter, then we
@@ -755,7 +769,9 @@ dir_fd_converter(PyObject *o, void *p)
* and was not encoded. (Only used on Windows.)
* path.narrow
* Points to the path if it was expressed as bytes,
- * or it was Unicode and was encoded to bytes.
+ * or it was Unicode and was encoded to bytes. (On Windows,
+ * is a non-zero integer if the path was expressed as bytes.
+ * The type is deliberately incompatible to prevent misuse.)
* path.fd
* Contains a file descriptor if path.accept_fd was true
* and the caller provided a signed integer instead of any
@@ -769,7 +785,9 @@ dir_fd_converter(PyObject *o, void *p)
* The length of the path in characters, if specified as
* a string.
* path.object
- * The original object passed in.
+ * The original object passed in (if get a PathLike object,
+ * the result of PyOS_FSPath() is treated as the original object).
+ * Own a reference to the object.
* path.cleanup
* For internal use only. May point to a temporary object.
* (Pay no attention to the man behind the curtain.)
@@ -799,30 +817,45 @@ typedef struct {
const char *argument_name;
int nullable;
int allow_fd;
- wchar_t *wide;
- char *narrow;
+ const wchar_t *wide;
+#ifdef MS_WINDOWS
+ BOOL narrow;
+#else
+ const char *narrow;
+#endif
int fd;
Py_ssize_t length;
PyObject *object;
PyObject *cleanup;
} path_t;
+#ifdef MS_WINDOWS
+#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
+ {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
+#else
#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
{function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
+#endif
static void
-path_cleanup(path_t *path) {
- if (path->cleanup) {
- Py_CLEAR(path->cleanup);
- }
+path_cleanup(path_t *path)
+{
+ Py_CLEAR(path->object);
+ Py_CLEAR(path->cleanup);
}
static int
-path_converter(PyObject *o, void *p) {
+path_converter(PyObject *o, void *p)
+{
path_t *path = (path_t *)p;
- PyObject *unicode, *bytes;
- Py_ssize_t length;
- char *narrow;
+ PyObject *bytes = NULL;
+ Py_ssize_t length = 0;
+ int is_index, is_buffer, is_bytes, is_unicode;
+ const char *narrow;
+#ifdef MS_WINDOWS
+ PyObject *wo = NULL;
+ const wchar_t *wide;
+#endif
#define FORMAT_EXCEPTION(exc, fmt) \
PyErr_Format(exc, "%s%s" fmt, \
@@ -836,122 +869,194 @@ path_converter(PyObject *o, void *p) {
return 1;
}
- /* ensure it's always safe to call path_cleanup() */
- path->cleanup = NULL;
+ /* Ensure it's always safe to call path_cleanup(). */
+ path->object = path->cleanup = NULL;
+ /* path->object owns a reference to the original object */
+ Py_INCREF(o);
- if (o == Py_None) {
- if (!path->nullable) {
- FORMAT_EXCEPTION(PyExc_TypeError,
- "can't specify None for %s argument");
- return 0;
- }
+ if ((o == Py_None) && path->nullable) {
path->wide = NULL;
+#ifdef MS_WINDOWS
+ path->narrow = FALSE;
+#else
path->narrow = NULL;
- path->length = 0;
- path->object = o;
+#endif
path->fd = -1;
- return 1;
+ goto success_exit;
}
- unicode = PyUnicode_FromObject(o);
- if (unicode) {
-#ifdef MS_WINDOWS
- wchar_t *wide;
+ /* Only call this here so that we don't treat the return value of
+ os.fspath() as an fd or buffer. */
+ is_index = path->allow_fd && PyIndex_Check(o);
+ is_buffer = PyObject_CheckBuffer(o);
+ is_bytes = PyBytes_Check(o);
+ is_unicode = PyUnicode_Check(o);
+
+ if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
+ /* Inline PyOS_FSPath() for better error messages. */
+ _Py_IDENTIFIER(__fspath__);
+ PyObject *func = NULL;
+
+ func = _PyObject_LookupSpecial(o, &PyId___fspath__);
+ if (NULL == func) {
+ goto error_format;
+ }
+ /* still owns a reference to the original object */
+ Py_DECREF(o);
+ o = _PyObject_CallNoArg(func);
+ Py_DECREF(func);
+ if (NULL == o) {
+ goto error_exit;
+ }
+ else if (PyUnicode_Check(o)) {
+ is_unicode = 1;
+ }
+ else if (PyBytes_Check(o)) {
+ is_bytes = 1;
+ }
+ else {
+ goto error_format;
+ }
+ }
- wide = PyUnicode_AsUnicodeAndSize(unicode, &length);
+ if (is_unicode) {
+#ifdef MS_WINDOWS
+ wide = PyUnicode_AsUnicodeAndSize(o, &length);
if (!wide) {
- Py_DECREF(unicode);
- return 0;
+ goto error_exit;
}
if (length > 32767) {
FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
- Py_DECREF(unicode);
- return 0;
+ goto error_exit;
}
if (wcslen(wide) != length) {
- FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character");
- Py_DECREF(unicode);
- return 0;
+ FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
+ goto error_exit;
}
path->wide = wide;
- path->narrow = NULL;
- path->length = length;
- path->object = o;
+ path->narrow = FALSE;
path->fd = -1;
- path->cleanup = unicode;
- return Py_CLEANUP_SUPPORTED;
+ goto success_exit;
#else
- int converted = PyUnicode_FSConverter(unicode, &bytes);
- Py_DECREF(unicode);
- if (!converted)
- bytes = NULL;
+ if (!PyUnicode_FSConverter(o, &bytes)) {
+ goto error_exit;
+ }
#endif
}
- else {
- PyErr_Clear();
- if (PyObject_CheckBuffer(o))
- bytes = PyBytes_FromObject(o);
- else
- bytes = NULL;
+ else if (is_bytes) {
+ bytes = o;
+ Py_INCREF(bytes);
+ }
+ else if (is_buffer) {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "%s%s%s should be %s, not %.200s",
+ path->function_name ? path->function_name : "",
+ path->function_name ? ": " : "",
+ path->argument_name ? path->argument_name : "path",
+ path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
+ "integer or None" :
+ path->allow_fd ? "string, bytes, os.PathLike or integer" :
+ path->nullable ? "string, bytes, os.PathLike or None" :
+ "string, bytes or os.PathLike",
+ Py_TYPE(o)->tp_name)) {
+ goto error_exit;
+ }
+ bytes = PyBytes_FromObject(o);
if (!bytes) {
- PyErr_Clear();
- if (path->allow_fd) {
- int fd;
- int result = _fd_converter(o, &fd,
- "string, bytes or integer");
- if (result) {
- path->wide = NULL;
- path->narrow = NULL;
- path->length = 0;
- path->object = o;
- path->fd = fd;
- return result;
- }
- }
+ goto error_exit;
}
}
+ else if (is_index) {
+ if (!_fd_converter(o, &path->fd)) {
+ goto error_exit;
+ }
+ path->wide = NULL;
+#ifdef MS_WINDOWS
+ path->narrow = FALSE;
+#else
+ path->narrow = NULL;
+#endif
+ goto success_exit;
+ }
+ else {
+ error_format:
+ PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
+ path->function_name ? path->function_name : "",
+ path->function_name ? ": " : "",
+ path->argument_name ? path->argument_name : "path",
+ path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
+ "integer or None" :
+ path->allow_fd ? "string, bytes, os.PathLike or integer" :
+ path->nullable ? "string, bytes, os.PathLike or None" :
+ "string, bytes or os.PathLike",
+ Py_TYPE(o)->tp_name);
+ goto error_exit;
+ }
- if (!bytes) {
- if (!PyErr_Occurred())
- FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter");
- return 0;
+ length = PyBytes_GET_SIZE(bytes);
+ narrow = PyBytes_AS_STRING(bytes);
+ if ((size_t)length != strlen(narrow)) {
+ FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
+ goto error_exit;
}
#ifdef MS_WINDOWS
- if (win32_warn_bytes_api()) {
- Py_DECREF(bytes);
- return 0;
+ wo = PyUnicode_DecodeFSDefaultAndSize(
+ narrow,
+ length
+ );
+ if (!wo) {
+ goto error_exit;
}
-#endif
- length = PyBytes_GET_SIZE(bytes);
-#ifdef MS_WINDOWS
- if (length > MAX_PATH-1) {
+ wide = PyUnicode_AsUnicodeAndSize(wo, &length);
+ if (!wide) {
+ goto error_exit;
+ }
+ if (length > 32767) {
FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
- Py_DECREF(bytes);
- return 0;
+ goto error_exit;
}
-#endif
-
- narrow = PyBytes_AS_STRING(bytes);
- if ((size_t)length != strlen(narrow)) {
+ if (wcslen(wide) != length) {
FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
- Py_DECREF(bytes);
- return 0;
+ goto error_exit;
}
-
+ path->wide = wide;
+ path->narrow = TRUE;
+ path->cleanup = wo;
+ Py_DECREF(bytes);
+#else
path->wide = NULL;
path->narrow = narrow;
+ if (bytes == o) {
+ /* Still a reference owned by path->object, don't have to
+ worry about path->narrow is used after free. */
+ Py_DECREF(bytes);
+ }
+ else {
+ path->cleanup = bytes;
+ }
+#endif
+ path->fd = -1;
+
+ success_exit:
path->length = length;
path->object = o;
- path->fd = -1;
- path->cleanup = bytes;
return Py_CLEANUP_SUPPORTED;
+
+ error_exit:
+ Py_XDECREF(o);
+ Py_XDECREF(bytes);
+#ifdef MS_WINDOWS
+ Py_XDECREF(wo);
+#endif
+ return 0;
}
static void
-argument_unavailable_error(char *function_name, char *argument_name) {
+argument_unavailable_error(const char *function_name, const char *argument_name)
+{
PyErr_Format(PyExc_NotImplementedError,
"%s%s%s unavailable on this platform",
(function_name != NULL) ? function_name : "",
@@ -974,7 +1079,8 @@ dir_fd_unavailable(PyObject *o, void *p)
}
static int
-fd_specified(char *function_name, int fd) {
+fd_specified(const char *function_name, int fd)
+{
if (fd == -1)
return 0;
@@ -983,7 +1089,8 @@ fd_specified(char *function_name, int fd) {
}
static int
-follow_symlinks_specified(char *function_name, int follow_symlinks) {
+follow_symlinks_specified(const char *function_name, int follow_symlinks)
+{
if (follow_symlinks)
return 0;
@@ -992,8 +1099,13 @@ follow_symlinks_specified(char *function_name, int follow_symlinks) {
}
static int
-path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) {
- if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) {
+path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
+{
+ if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
+#ifndef MS_WINDOWS
+ && !path->narrow
+#endif
+ ) {
PyErr_Format(PyExc_ValueError,
"%s: can't specify dir_fd without matching path",
function_name);
@@ -1003,7 +1115,8 @@ path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) {
}
static int
-dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) {
+dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
+{
if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
PyErr_Format(PyExc_ValueError,
"%s: can't specify both dir_fd and fd",
@@ -1014,8 +1127,9 @@ dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) {
}
static int
-fd_and_follow_symlinks_invalid(char *function_name, int fd,
- int follow_symlinks) {
+fd_and_follow_symlinks_invalid(const char *function_name, int fd,
+ int follow_symlinks)
+{
if ((fd > 0) && (!follow_symlinks)) {
PyErr_Format(PyExc_ValueError,
"%s: cannot use fd and follow_symlinks together",
@@ -1026,8 +1140,9 @@ fd_and_follow_symlinks_invalid(char *function_name, int fd,
}
static int
-dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd,
- int follow_symlinks) {
+dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
+ int follow_symlinks)
+{
if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
PyErr_Format(PyExc_ValueError,
"%s: cannot use dir_fd and follow_symlinks together",
@@ -1038,7 +1153,7 @@ dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd,
}
#ifdef MS_WINDOWS
- typedef PY_LONG_LONG Py_off_t;
+ typedef long long Py_off_t;
#else
typedef off_t Py_off_t;
#endif
@@ -1066,41 +1181,13 @@ PyLong_FromPy_off_t(Py_off_t offset)
#endif
}
-
-#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900
-/* Legacy implementation of _PyVerify_fd_dup2 while transitioning to
- * MSVC 14.0. This should eventually be removed. (issue23524)
- */
-#define IOINFO_L2E 5
-#define IOINFO_ARRAYS 64
-#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
-#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
-#define _NO_CONSOLE_FILENO (intptr_t)-2
-
-/* the special case of checking dup2. The target fd must be in a sensible range */
-static int
-_PyVerify_fd_dup2(int fd1, int fd2)
-{
- if (!_PyVerify_fd(fd1))
- return 0;
- if (fd2 == _NO_CONSOLE_FILENO)
- return 0;
- if ((unsigned)fd2 < _NHANDLE_)
- return 1;
- else
- return 0;
-}
-#else
-#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0)
-#endif
-
#ifdef MS_WINDOWS
static int
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
{
- char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
- REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
+ char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
DWORD n_bytes_returned;
if (0 == DeviceIoControl(
@@ -1159,7 +1246,7 @@ convertenviron(void)
for (e = _wenviron; *e != NULL; e++) {
PyObject *k;
PyObject *v;
- wchar_t *p = wcschr(*e, L'=');
+ const wchar_t *p = wcschr(*e, L'=');
if (p == NULL)
continue;
k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
@@ -1187,7 +1274,7 @@ convertenviron(void)
for (e = environ; *e != NULL; e++) {
PyObject *k;
PyObject *v;
- char *p = strchr(*e, '=');
+ const char *p = strchr(*e, '=');
if (p == NULL)
continue;
k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
@@ -1222,7 +1309,7 @@ posix_error(void)
#ifdef MS_WINDOWS
static PyObject *
-win32_error(char* function, const char* filename)
+win32_error(const char* function, const char* filename)
{
/* XXX We should pass the function name along in the future.
(winreg.c also wants to pass the function name.)
@@ -1237,7 +1324,7 @@ win32_error(char* function, const char* filename)
}
static PyObject *
-win32_error_object(char* function, PyObject* filename)
+win32_error_object(const char* function, PyObject* filename)
{
/* XXX - see win32_error for comments on 'function' */
errno = GetLastError();
@@ -1253,29 +1340,39 @@ win32_error_object(char* function, PyObject* filename)
#endif /* MS_WINDOWS */
static PyObject *
-path_error(path_t *path)
+path_object_error(PyObject *path)
{
#ifdef MS_WINDOWS
- return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError,
- 0, path->object);
+ return PyErr_SetExcFromWindowsErrWithFilenameObject(
+ PyExc_OSError, 0, path);
#else
- return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
+ return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
#endif
}
-
static PyObject *
-path_error2(path_t *path, path_t *path2)
+path_object_error2(PyObject *path, PyObject *path2)
{
#ifdef MS_WINDOWS
- return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError,
- 0, path->object, path2->object);
+ return PyErr_SetExcFromWindowsErrWithFilenameObjects(
+ PyExc_OSError, 0, path, path2);
#else
- return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError,
- path->object, path2->object);
+ return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
#endif
}
+static PyObject *
+path_error(path_t *path)
+{
+ return path_object_error(path->object);
+}
+
+static PyObject *
+path_error2(path_t *path, path_t *path2)
+{
+ return path_object_error2(path->object, path2->object);
+}
+
/* POSIX generic methods */
@@ -1297,9 +1394,6 @@ posix_fildes_fd(int fd, int (*func)(int))
int res;
int async_err = 0;
- if (!_PyVerify_fd(fd))
- return posix_error();
-
do {
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
@@ -1320,31 +1414,6 @@ posix_fildes_fd(int fd, int (*func)(int))
it also needs to set "magic" environment variables indicating
the per-drive current directory, which are of the form =<drive>: */
static BOOL __stdcall
-win32_chdir(LPCSTR path)
-{
- char new_path[MAX_PATH];
- int result;
- char env[4] = "=x:";
-
- if(!SetCurrentDirectoryA(path))
- return FALSE;
- result = GetCurrentDirectoryA(Py_ARRAY_LENGTH(new_path), new_path);
- if (!result)
- return FALSE;
- /* In the ANSI API, there should not be any paths longer
- than MAX_PATH-1 (not including the final null character). */
- assert(result < Py_ARRAY_LENGTH(new_path));
- if (strncmp(new_path, "\\\\", 2) == 0 ||
- strncmp(new_path, "//", 2) == 0)
- /* UNC path, nothing to do. */
- return TRUE;
- env[1] = new_path[0];
- return SetEnvironmentVariableA(env, new_path);
-}
-
-/* The Unicode version differs from the ANSI version
- since the current directory might exceed MAX_PATH characters */
-static BOOL __stdcall
win32_wchdir(LPCWSTR path)
{
wchar_t path_buf[MAX_PATH], *new_path = path_buf;
@@ -1390,33 +1459,10 @@ win32_wchdir(LPCWSTR path)
#define HAVE_STAT_NSEC 1
#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
-static BOOL
-attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
-{
- HANDLE hFindFile;
- WIN32_FIND_DATAA FileData;
- hFindFile = FindFirstFileA(pszFile, &FileData);
- if (hFindFile == INVALID_HANDLE_VALUE)
- return FALSE;
- FindClose(hFindFile);
- memset(info, 0, sizeof(*info));
- *reparse_tag = 0;
- info->dwFileAttributes = FileData.dwFileAttributes;
- info->ftCreationTime = FileData.ftCreationTime;
- info->ftLastAccessTime = FileData.ftLastAccessTime;
- info->ftLastWriteTime = FileData.ftLastWriteTime;
- info->nFileSizeHigh = FileData.nFileSizeHigh;
- info->nFileSizeLow = FileData.nFileSizeLow;
-/* info->nNumberOfLinks = 1; */
- if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- *reparse_tag = FileData.dwReserved0;
- return TRUE;
-}
-
static void
-find_data_to_file_info_w(WIN32_FIND_DATAW *pFileData,
- BY_HANDLE_FILE_INFORMATION *info,
- ULONG *reparse_tag)
+find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
+ BY_HANDLE_FILE_INFORMATION *info,
+ ULONG *reparse_tag)
{
memset(info, 0, sizeof(*info));
info->dwFileAttributes = pFileData->dwFileAttributes;
@@ -1433,7 +1479,7 @@ find_data_to_file_info_w(WIN32_FIND_DATAW *pFileData,
}
static BOOL
-attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
+attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
{
HANDLE hFindFile;
WIN32_FIND_DATAW FileData;
@@ -1441,7 +1487,7 @@ attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE;
FindClose(hFindFile);
- find_data_to_file_info_w(&FileData, info, reparse_tag);
+ find_data_to_file_info(&FileData, info, reparse_tag);
return TRUE;
}
@@ -1458,7 +1504,7 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
if(!buf_size)
return FALSE;
- buf = PyMem_New(wchar_t, buf_size+1);
+ buf = (wchar_t *)PyMem_RawMalloc((buf_size + 1) * sizeof(wchar_t));
if (!buf) {
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
@@ -1468,12 +1514,12 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
buf, buf_size, VOLUME_NAME_DOS);
if(!result_length) {
- PyMem_Free(buf);
+ PyMem_RawFree(buf);
return FALSE;
}
if(!CloseHandle(hdl)) {
- PyMem_Free(buf);
+ PyMem_RawFree(buf);
return FALSE;
}
@@ -1484,10 +1530,7 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
}
static int
-win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
- BOOL traverse);
-static int
-win32_xstat_impl(const char *path, struct _Py_stat_struct *result,
+win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
BOOL traverse)
{
int code;
@@ -1495,98 +1538,6 @@ win32_xstat_impl(const char *path, struct _Py_stat_struct *result,
BY_HANDLE_FILE_INFORMATION info;
ULONG reparse_tag = 0;
wchar_t *target_path;
- const char *dot;
-
- hFile = CreateFileA(
- path,
- FILE_READ_ATTRIBUTES, /* desired access */
- 0, /* share mode */
- NULL, /* security attributes */
- OPEN_EXISTING,
- /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
- /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
- Because of this, calls like GetFinalPathNameByHandle will return
- the symlink path again and not the actual final path. */
- FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
- FILE_FLAG_OPEN_REPARSE_POINT,
- NULL);
-
- if (hFile == INVALID_HANDLE_VALUE) {
- /* Either the target doesn't exist, or we don't have access to
- get a handle to it. If the former, we need to return an error.
- If the latter, we can use attributes_from_dir. */
- DWORD lastError = GetLastError();
- if (lastError != ERROR_ACCESS_DENIED &&
- lastError != ERROR_SHARING_VIOLATION)
- return -1;
- /* Could not get attributes on open file. Fall back to
- reading the directory. */
- if (!attributes_from_dir(path, &info, &reparse_tag))
- /* Very strange. This should not fail now */
- return -1;
- if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- if (traverse) {
- /* Should traverse, but could not open reparse point handle */
- SetLastError(lastError);
- return -1;
- }
- }
- } else {
- if (!GetFileInformationByHandle(hFile, &info)) {
- CloseHandle(hFile);
- return -1;
- }
- if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- if (!win32_get_reparse_tag(hFile, &reparse_tag))
- return -1;
-
- /* Close the outer open file handle now that we're about to
- reopen it with different flags. */
- if (!CloseHandle(hFile))
- return -1;
-
- if (traverse) {
- /* In order to call GetFinalPathNameByHandle we need to open
- the file without the reparse handling flag set. */
- hFile2 = CreateFileA(
- path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
- NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
- NULL);
- if (hFile2 == INVALID_HANDLE_VALUE)
- return -1;
-
- if (!get_target_path(hFile2, &target_path))
- return -1;
-
- code = win32_xstat_impl_w(target_path, result, FALSE);
- PyMem_Free(target_path);
- return code;
- }
- } else
- CloseHandle(hFile);
- }
- _Py_attribute_data_to_stat(&info, reparse_tag, result);
-
- /* Set S_IEXEC if it is an .exe, .bat, ... */
- dot = strrchr(path, '.');
- if (dot) {
- if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
- stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
- result->st_mode |= 0111;
- }
- return 0;
-}
-
-static int
-win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
- BOOL traverse)
-{
- int code;
- HANDLE hFile, hFile2;
- BY_HANDLE_FILE_INFORMATION info;
- ULONG reparse_tag = 0;
- wchar_t *target_path;
const wchar_t *dot;
hFile = CreateFileW(
@@ -1613,7 +1564,7 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
return -1;
/* Could not get attributes on open file. Fall back to
reading the directory. */
- if (!attributes_from_dir_w(path, &info, &reparse_tag))
+ if (!attributes_from_dir(path, &info, &reparse_tag))
/* Very strange. This should not fail now */
return -1;
if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
@@ -1651,8 +1602,8 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
if (!get_target_path(hFile2, &target_path))
return -1;
- code = win32_xstat_impl_w(target_path, result, FALSE);
- PyMem_Free(target_path);
+ code = win32_xstat_impl(target_path, result, FALSE);
+ PyMem_RawFree(target_path);
return code;
}
} else
@@ -1671,7 +1622,7 @@ win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
}
static int
-win32_xstat(const char *path, struct _Py_stat_struct *result, BOOL traverse)
+win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
{
/* Protocol violation: we explicitly clear errno, instead of
setting it to a POSIX error. Callers should use GetLastError. */
@@ -1679,16 +1630,6 @@ win32_xstat(const char *path, struct _Py_stat_struct *result, BOOL traverse)
errno = 0;
return code;
}
-
-static int
-win32_xstat_w(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
-{
- /* Protocol violation: we explicitly clear errno, instead of
- setting it to a POSIX error. Callers should use GetLastError. */
- int code = win32_xstat_impl_w(path, result, traverse);
- errno = 0;
- return code;
-}
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
In Posix, stat automatically traverses symlinks and returns the stat
@@ -1698,34 +1639,20 @@ win32_xstat_w(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse
Therefore, win32_lstat will get the attributes traditionally, and
win32_stat will first explicitly resolve the symlink target and then will
- call win32_lstat on that result.
-
- The _w represent Unicode equivalents of the aforementioned ANSI functions. */
+ call win32_lstat on that result. */
static int
-win32_lstat(const char* path, struct _Py_stat_struct *result)
+win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
{
return win32_xstat(path, result, FALSE);
}
static int
-win32_lstat_w(const wchar_t* path, struct _Py_stat_struct *result)
-{
- return win32_xstat_w(path, result, FALSE);
-}
-
-static int
-win32_stat(const char* path, struct _Py_stat_struct *result)
+win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
{
return win32_xstat(path, result, TRUE);
}
-static int
-win32_stat_w(const wchar_t* path, struct _Py_stat_struct *result)
-{
- return win32_xstat_w(path, result, TRUE);
-}
-
#endif /* MS_WINDOWS */
PyDoc_STRVAR(stat_result__doc__,
@@ -2007,7 +1934,7 @@ _pystat_fromstructstat(STRUCT_STAT *st)
PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 1,
- PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
+ PyLong_FromLongLong((long long)st->st_ino));
#else
PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
#endif
@@ -2026,7 +1953,7 @@ _pystat_fromstructstat(STRUCT_STAT *st)
#endif
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 6,
- PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
+ PyLong_FromLongLong((long long)st->st_size));
#else
PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
#endif
@@ -2106,7 +2033,7 @@ _pystat_fromstructstat(STRUCT_STAT *st)
static PyObject *
-posix_do_stat(char *function_name, path_t *path,
+posix_do_stat(const char *function_name, path_t *path,
int dir_fd, int follow_symlinks)
{
STRUCT_STAT st;
@@ -2125,28 +2052,26 @@ posix_do_stat(char *function_name, path_t *path,
Py_BEGIN_ALLOW_THREADS
if (path->fd != -1)
result = FSTAT(path->fd, &st);
- else
#ifdef MS_WINDOWS
- if (path->wide) {
- if (follow_symlinks)
- result = win32_stat_w(path->wide, &st);
- else
- result = win32_lstat_w(path->wide, &st);
- }
+ else if (follow_symlinks)
+ result = win32_stat(path->wide, &st);
else
-#endif
-#if defined(HAVE_LSTAT) || defined(MS_WINDOWS)
+ result = win32_lstat(path->wide, &st);
+#else
+ else
+#if defined(HAVE_LSTAT)
if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
result = LSTAT(path->narrow, &st);
else
-#endif
+#endif /* HAVE_LSTAT */
#ifdef HAVE_FSTATAT
if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
result = fstatat(dir_fd, path->narrow, &st,
follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
else
-#endif
+#endif /* HAVE_FSTATAT */
result = STAT(path->narrow, &st);
+#endif /* MS_WINDOWS */
Py_END_ALLOW_THREADS
if (result != 0) {
@@ -2426,8 +2351,8 @@ class id_t_converter(CConverter):
type = 'id_t'
format_unit = '" _Py_PARSE_PID "'
-class Py_intptr_t_converter(CConverter):
- type = 'Py_intptr_t'
+class intptr_t_converter(CConverter):
+ type = 'intptr_t'
format_unit = '" _Py_PARSE_INTPTR "'
class Py_off_t_converter(CConverter):
@@ -2454,14 +2379,15 @@ class sched_param_converter(CConverter):
impl_by_reference = True;
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=affe68316f160401]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/
/*[clinic input]
os.stat
path : path_t(allow_fd=True)
- Path to be examined; can be string, bytes, or open-file-descriptor int.
+ Path to be examined; can be string, bytes, path-like object or
+ open-file-descriptor int.
*
@@ -2488,7 +2414,7 @@ It's an error to use dir_fd or follow_symlinks when specifying path as
static PyObject *
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
-/*[clinic end generated code: output=7d4976e6f18a59c5 input=099d356c306fa24a]*/
+/*[clinic end generated code: output=7d4976e6f18a59c5 input=270bd64e7bb3c8f7]*/
{
return posix_do_stat("stat", path, dir_fd, follow_symlinks);
}
@@ -2582,10 +2508,7 @@ os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path->wide != NULL)
- attr = GetFileAttributesW(path->wide);
- else
- attr = GetFileAttributesA(path->narrow);
+ attr = GetFileAttributesW(path->wide);
Py_END_ALLOW_THREADS
/*
@@ -2709,11 +2632,8 @@ os_chdir_impl(PyObject *module, path_t *path)
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path->wide)
- result = win32_wchdir(path->wide);
- else
- result = win32_chdir(path->narrow);
- result = !result; /* on unix, success = 0, on windows, success = !0 */
+ /* on unix, success = 0, on windows, success = !0 */
+ result = !win32_wchdir(path->wide);
#else
#ifdef HAVE_FCHDIR
if (path->fd != -1)
@@ -2808,10 +2728,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path->wide)
- attr = GetFileAttributesW(path->wide);
- else
- attr = GetFileAttributesA(path->narrow);
+ attr = GetFileAttributesW(path->wide);
if (attr == INVALID_FILE_ATTRIBUTES)
result = 0;
else {
@@ -2819,10 +2736,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
attr &= ~FILE_ATTRIBUTE_READONLY;
else
attr |= FILE_ATTRIBUTE_READONLY;
- if (path->wide)
- result = SetFileAttributesW(path->wide, attr);
- else
- result = SetFileAttributesA(path->narrow, attr);
+ result = SetFileAttributesW(path->wide, attr);
}
Py_END_ALLOW_THREADS
@@ -3318,12 +3232,22 @@ posix_getcwd(int use_bytes)
Py_BEGIN_ALLOW_THREADS
do {
buflen += chunk;
+#ifdef MS_WINDOWS
+ if (buflen > INT_MAX) {
+ PyErr_NoMemory();
+ break;
+ }
+#endif
tmpbuf = PyMem_RawRealloc(buf, buflen);
if (tmpbuf == NULL)
break;
buf = tmpbuf;
+#ifdef MS_WINDOWS
+ cwd = getcwd(buf, (int)buflen);
+#else
cwd = getcwd(buf, buflen);
+#endif
} while (cwd == NULL && errno == ERANGE);
Py_END_ALLOW_THREADS
@@ -3405,7 +3329,7 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
/*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
{
#ifdef MS_WINDOWS
- BOOL result;
+ BOOL result = FALSE;
#else
int result;
#endif
@@ -3417,18 +3341,17 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
}
#endif
+#ifndef MS_WINDOWS
if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
PyErr_SetString(PyExc_NotImplementedError,
"link: src and dst must be the same type");
return NULL;
}
+#endif
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (src->wide)
- result = CreateHardLinkW(dst->wide, src->wide, NULL);
- else
- result = CreateHardLinkA(dst->narrow, src->narrow, NULL);
+ result = CreateHardLinkW(dst->wide, src->wide, NULL);
Py_END_ALLOW_THREADS
if (!result)
@@ -3443,13 +3366,13 @@ os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
dst_dir_fd, dst->narrow,
follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
else
-#endif
+#endif /* HAVE_LINKAT */
result = link(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
if (result)
return path_error2(src, dst);
-#endif
+#endif /* MS_WINDOWS */
Py_RETURN_NONE;
}
@@ -3463,99 +3386,39 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list)
PyObject *v;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
BOOL result;
- WIN32_FIND_DATA FileData;
- char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
- char *bufptr = namebuf;
+ wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
/* only claim to have space for MAX_PATH */
Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
- PyObject *po = NULL;
wchar_t *wnamebuf = NULL;
- if (!path->narrow) {
- WIN32_FIND_DATAW wFileData;
- wchar_t *po_wchars;
-
- if (!path->wide) { /* Default arg: "." */
- po_wchars = L".";
- len = 1;
- } else {
- po_wchars = path->wide;
- len = wcslen(path->wide);
- }
- /* The +5 is so we can append "\\*.*\0" */
- wnamebuf = PyMem_New(wchar_t, len + 5);
- if (!wnamebuf) {
- PyErr_NoMemory();
- goto exit;
- }
- wcscpy(wnamebuf, po_wchars);
- if (len > 0) {
- wchar_t wch = wnamebuf[len-1];
- if (wch != SEP && wch != ALTSEP && wch != L':')
- wnamebuf[len++] = SEP;
- wcscpy(wnamebuf + len, L"*.*");
- }
- if ((list = PyList_New(0)) == NULL) {
- goto exit;
- }
- Py_BEGIN_ALLOW_THREADS
- hFindFile = FindFirstFileW(wnamebuf, &wFileData);
- Py_END_ALLOW_THREADS
- if (hFindFile == INVALID_HANDLE_VALUE) {
- int error = GetLastError();
- if (error == ERROR_FILE_NOT_FOUND)
- goto exit;
- Py_DECREF(list);
- list = path_error(path);
- goto exit;
- }
- do {
- /* Skip over . and .. */
- if (wcscmp(wFileData.cFileName, L".") != 0 &&
- wcscmp(wFileData.cFileName, L"..") != 0) {
- v = PyUnicode_FromWideChar(wFileData.cFileName,
- wcslen(wFileData.cFileName));
- if (v == NULL) {
- Py_DECREF(list);
- list = NULL;
- break;
- }
- if (PyList_Append(list, v) != 0) {
- Py_DECREF(v);
- Py_DECREF(list);
- list = NULL;
- break;
- }
- Py_DECREF(v);
- }
- Py_BEGIN_ALLOW_THREADS
- result = FindNextFileW(hFindFile, &wFileData);
- Py_END_ALLOW_THREADS
- /* FindNextFile sets error to ERROR_NO_MORE_FILES if
- it got to the end of the directory. */
- if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
- Py_DECREF(list);
- list = path_error(path);
- goto exit;
- }
- } while (result == TRUE);
+ WIN32_FIND_DATAW wFileData;
+ const wchar_t *po_wchars;
+ if (!path->wide) { /* Default arg: "." */
+ po_wchars = L".";
+ len = 1;
+ } else {
+ po_wchars = path->wide;
+ len = wcslen(path->wide);
+ }
+ /* The +5 is so we can append "\\*.*\0" */
+ wnamebuf = PyMem_New(wchar_t, len + 5);
+ if (!wnamebuf) {
+ PyErr_NoMemory();
goto exit;
}
- strcpy(namebuf, path->narrow);
- len = path->length;
+ wcscpy(wnamebuf, po_wchars);
if (len > 0) {
- char ch = namebuf[len-1];
- if (ch != '\\' && ch != '/' && ch != ':')
- namebuf[len++] = '\\';
- strcpy(namebuf + len, "*.*");
+ wchar_t wch = wnamebuf[len-1];
+ if (wch != SEP && wch != ALTSEP && wch != L':')
+ wnamebuf[len++] = SEP;
+ wcscpy(wnamebuf + len, L"*.*");
+ }
+ if ((list = PyList_New(0)) == NULL) {
+ goto exit;
}
-
- if ((list = PyList_New(0)) == NULL)
- return NULL;
-
Py_BEGIN_ALLOW_THREADS
- hFindFile = FindFirstFile(namebuf, &FileData);
+ hFindFile = FindFirstFileW(wnamebuf, &wFileData);
Py_END_ALLOW_THREADS
if (hFindFile == INVALID_HANDLE_VALUE) {
int error = GetLastError();
@@ -3567,9 +3430,13 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list)
}
do {
/* Skip over . and .. */
- if (strcmp(FileData.cFileName, ".") != 0 &&
- strcmp(FileData.cFileName, "..") != 0) {
- v = PyBytes_FromString(FileData.cFileName);
+ if (wcscmp(wFileData.cFileName, L".") != 0 &&
+ wcscmp(wFileData.cFileName, L"..") != 0) {
+ v = PyUnicode_FromWideChar(wFileData.cFileName,
+ wcslen(wFileData.cFileName));
+ if (path->narrow && v) {
+ Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
+ }
if (v == NULL) {
Py_DECREF(list);
list = NULL;
@@ -3584,7 +3451,7 @@ _listdir_windows_no_opendir(path_t *path, PyObject *list)
Py_DECREF(v);
}
Py_BEGIN_ALLOW_THREADS
- result = FindNextFile(hFindFile, &FileData);
+ result = FindNextFileW(hFindFile, &wFileData);
Py_END_ALLOW_THREADS
/* FindNextFile sets error to ERROR_NO_MORE_FILES if
it got to the end of the directory. */
@@ -3639,7 +3506,7 @@ _posix_listdir(path_t *path, PyObject *list)
else
#endif
{
- char *name;
+ const char *name;
if (path->narrow) {
name = path->narrow;
/* only return bytes if they specified a bytes object */
@@ -3765,41 +3632,29 @@ static PyObject *
os__getfullpathname_impl(PyObject *module, path_t *path)
/*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
{
- if (!path->narrow)
- {
- wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
- wchar_t *wtemp;
- DWORD result;
- PyObject *v;
-
- result = GetFullPathNameW(path->wide,
- Py_ARRAY_LENGTH(woutbuf),
- woutbuf, &wtemp);
- if (result > Py_ARRAY_LENGTH(woutbuf)) {
- woutbufp = PyMem_New(wchar_t, result);
- if (!woutbufp)
- return PyErr_NoMemory();
- result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
- }
- if (result)
- v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
- else
- v = win32_error_object("GetFullPathNameW", path->object);
- if (woutbufp != woutbuf)
- PyMem_Free(woutbufp);
- return v;
- }
- else {
- char outbuf[MAX_PATH];
- char *temp;
+ wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
+ wchar_t *wtemp;
+ DWORD result;
+ PyObject *v;
- if (!GetFullPathName(path->narrow, Py_ARRAY_LENGTH(outbuf),
- outbuf, &temp)) {
- win32_error_object("GetFullPathName", path->object);
- return NULL;
- }
- return PyBytes_FromString(outbuf);
+ result = GetFullPathNameW(path->wide,
+ Py_ARRAY_LENGTH(woutbuf),
+ woutbuf, &wtemp);
+ if (result > Py_ARRAY_LENGTH(woutbuf)) {
+ woutbufp = PyMem_New(wchar_t, result);
+ if (!woutbufp)
+ return PyErr_NoMemory();
+ result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp);
}
+ if (result) {
+ v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
+ if (path->narrow)
+ Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
+ } else
+ v = win32_error_object("GetFullPathNameW", path->object);
+ if (woutbufp != woutbuf)
+ PyMem_Free(woutbufp);
+ return v;
}
@@ -3821,7 +3676,7 @@ os__getfinalpathname_impl(PyObject *module, PyObject *path)
wchar_t *target_path;
int result_length;
PyObject *result;
- wchar_t *path_wchar;
+ const wchar_t *path_wchar;
path_wchar = PyUnicode_AsUnicode(path);
if (path_wchar == NULL)
@@ -3881,10 +3736,7 @@ os__isdir_impl(PyObject *module, path_t *path)
DWORD attributes;
Py_BEGIN_ALLOW_THREADS
- if (!path->narrow)
- attributes = GetFileAttributesW(path->wide);
- else
- attributes = GetFileAttributesA(path->narrow);
+ attributes = GetFileAttributesW(path->wide);
Py_END_ALLOW_THREADS
if (attributes == INVALID_FILE_ATTRIBUTES)
@@ -3910,7 +3762,8 @@ os__getvolumepathname_impl(PyObject *module, PyObject *path)
/*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*/
{
PyObject *result;
- wchar_t *path_wchar, *mountpath=NULL;
+ const wchar_t *path_wchar;
+ wchar_t *mountpath=NULL;
size_t buflen;
BOOL ret;
@@ -3981,10 +3834,7 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path->wide)
- result = CreateDirectoryW(path->wide, NULL);
- else
- result = CreateDirectoryA(path->narrow, NULL);
+ result = CreateDirectoryW(path->wide, NULL);
Py_END_ALLOW_THREADS
if (!result)
@@ -4004,7 +3854,7 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
Py_END_ALLOW_THREADS
if (result < 0)
return path_error(path);
-#endif
+#endif /* MS_WINDOWS */
Py_RETURN_NONE;
}
@@ -4108,7 +3958,7 @@ os_setpriority_impl(PyObject *module, int which, int who, int priority)
static PyObject *
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
{
- char *function_name = is_replace ? "replace" : "rename";
+ const char *function_name = is_replace ? "replace" : "rename";
int dir_fd_specified;
#ifdef MS_WINDOWS
@@ -4127,31 +3977,28 @@ internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is
}
#endif
- if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
- PyErr_Format(PyExc_ValueError,
- "%s: src and dst must be the same type", function_name);
- return NULL;
- }
-
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (src->wide)
- result = MoveFileExW(src->wide, dst->wide, flags);
- else
- result = MoveFileExA(src->narrow, dst->narrow, flags);
+ result = MoveFileExW(src->wide, dst->wide, flags);
Py_END_ALLOW_THREADS
if (!result)
return path_error2(src, dst);
#else
+ if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
+ PyErr_Format(PyExc_ValueError,
+ "%s: src and dst must be the same type", function_name);
+ return NULL;
+ }
+
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_RENAMEAT
if (dir_fd_specified)
result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
else
#endif
- result = rename(src->narrow, dst->narrow);
+ result = rename(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
if (result)
@@ -4232,11 +4079,8 @@ os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path->wide)
- result = RemoveDirectoryW(path->wide);
- else
- result = RemoveDirectoryA(path->narrow);
- result = !result; /* Windows, success=1, UNIX, success=0 */
+ /* Windows, success=1, UNIX, success=0 */
+ result = !RemoveDirectoryW(path->wide);
#else
#ifdef HAVE_UNLINKAT
if (dir_fd != DEFAULT_DIR_FD)
@@ -4270,7 +4114,9 @@ os_system_impl(PyObject *module, Py_UNICODE *command)
{
long result;
Py_BEGIN_ALLOW_THREADS
+ _Py_BEGIN_SUPPRESS_IPH
result = _wsystem(command);
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
return result;
}
@@ -4288,7 +4134,7 @@ os_system_impl(PyObject *module, PyObject *command)
/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
{
long result;
- char *bytes = PyBytes_AsString(command);
+ const char *bytes = PyBytes_AsString(command);
Py_BEGIN_ALLOW_THREADS
result = system(bytes);
Py_END_ALLOW_THREADS
@@ -4382,11 +4228,8 @@ os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
- if (path->wide)
- result = Py_DeleteFileW(path->wide);
- else
- result = DeleteFileA(path->narrow);
- result = !result; /* Windows, success=1, UNIX, success=0 */
+ /* Windows, success=1, UNIX, success=0 */
+ result = !Py_DeleteFileW(path->wide);
#else
#ifdef HAVE_UNLINKAT
if (dir_fd != DEFAULT_DIR_FD)
@@ -4568,7 +4411,7 @@ typedef struct {
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
static int
-utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks)
+utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
{
#ifdef HAVE_UTIMENSAT
int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
@@ -4610,14 +4453,14 @@ utime_fd(utime_t *ut, int fd)
#define PATH_UTIME_HAVE_FD 0
#endif
+#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
+# define UTIME_HAVE_NOFOLLOW_SYMLINKS
+#endif
-#define UTIME_HAVE_NOFOLLOW_SYMLINKS \
- (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES))
-
-#if UTIME_HAVE_NOFOLLOW_SYMLINKS
+#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
static int
-utime_nofollow_symlinks(utime_t *ut, char *path)
+utime_nofollow_symlinks(utime_t *ut, const char *path)
{
#ifdef HAVE_UTIMENSAT
UTIME_TO_TIMESPEC;
@@ -4633,7 +4476,7 @@ utime_nofollow_symlinks(utime_t *ut, char *path)
#ifndef MS_WINDOWS
static int
-utime_default(utime_t *ut, char *path)
+utime_default(utime_t *ut, const char *path)
{
#ifdef HAVE_UTIMENSAT
UTIME_TO_TIMESPEC;
@@ -4776,7 +4619,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
utime.now = 1;
}
-#if !UTIME_HAVE_NOFOLLOW_SYMLINKS
+#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
if (follow_symlinks_specified("utime", follow_symlinks))
goto exit;
#endif
@@ -4797,14 +4640,9 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path->wide)
- hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
- NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- else
- hFile = CreateFileA(path->narrow, FILE_WRITE_ATTRIBUTES, 0,
- NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
+ NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL);
Py_END_ALLOW_THREADS
if (hFile == INVALID_HANDLE_VALUE) {
path_error(path);
@@ -4830,7 +4668,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
#else /* MS_WINDOWS */
Py_BEGIN_ALLOW_THREADS
-#if UTIME_HAVE_NOFOLLOW_SYMLINKS
+#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
result = utime_nofollow_symlinks(&utime, path->narrow);
else
@@ -4890,9 +4728,15 @@ os__exit_impl(PyObject *module, int status)
return NULL; /* Make gcc -Wall happy */
}
+#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
+#define EXECV_CHAR wchar_t
+#else
+#define EXECV_CHAR char
+#endif
+
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
static void
-free_string_array(char **array, Py_ssize_t count)
+free_string_array(EXECV_CHAR **array, Py_ssize_t count)
{
Py_ssize_t i;
for (i = 0; i < count; i++)
@@ -4900,40 +4744,47 @@ free_string_array(char **array, Py_ssize_t count)
PyMem_DEL(array);
}
-static
-int fsconvert_strdup(PyObject *o, char**out)
+static int
+fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
{
- PyObject *bytes;
Py_ssize_t size;
- if (!PyUnicode_FSConverter(o, &bytes))
+ PyObject *ub;
+ int result = 0;
+#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
+ if (!PyUnicode_FSDecoder(o, &ub))
return 0;
- size = PyBytes_GET_SIZE(bytes);
- *out = PyMem_Malloc(size+1);
- if (!*out) {
- PyErr_NoMemory();
+ *out = PyUnicode_AsWideCharString(ub, &size);
+ if (*out)
+ result = 1;
+#else
+ if (!PyUnicode_FSConverter(o, &ub))
return 0;
- }
- memcpy(*out, PyBytes_AsString(bytes), size+1);
- Py_DECREF(bytes);
- return 1;
+ size = PyBytes_GET_SIZE(ub);
+ *out = PyMem_Malloc(size + 1);
+ if (*out) {
+ memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
+ result = 1;
+ } else
+ PyErr_NoMemory();
+#endif
+ Py_DECREF(ub);
+ return result;
}
#endif
#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE)
-static char**
+static EXECV_CHAR**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
{
- char **envlist;
Py_ssize_t i, pos, envc;
PyObject *keys=NULL, *vals=NULL;
- PyObject *key, *val, *key2, *val2;
- char *p, *k, *v;
- size_t len;
+ PyObject *key, *val, *key2, *val2, *keyval;
+ EXECV_CHAR **envlist;
i = PyMapping_Size(env);
if (i < 0)
return NULL;
- envlist = PyMem_NEW(char *, i + 1);
+ envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
if (envlist == NULL) {
PyErr_NoMemory();
return NULL;
@@ -4957,28 +4808,35 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
if (!key || !val)
goto error;
- if (PyUnicode_FSConverter(key, &key2) == 0)
+#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
+ if (!PyUnicode_FSDecoder(key, &key2))
goto error;
- if (PyUnicode_FSConverter(val, &val2) == 0) {
+ if (!PyUnicode_FSDecoder(val, &val2)) {
Py_DECREF(key2);
goto error;
}
-
- k = PyBytes_AsString(key2);
- v = PyBytes_AsString(val2);
- len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2;
-
- p = PyMem_NEW(char, len);
- if (p == NULL) {
- PyErr_NoMemory();
+ keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
+#else
+ if (!PyUnicode_FSConverter(key, &key2))
+ goto error;
+ if (!PyUnicode_FSConverter(val, &val2)) {
Py_DECREF(key2);
- Py_DECREF(val2);
goto error;
}
- PyOS_snprintf(p, len, "%s=%s", k, v);
- envlist[envc++] = p;
+ keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
+ PyBytes_AS_STRING(val2));
+#endif
Py_DECREF(key2);
Py_DECREF(val2);
+ if (!keyval)
+ goto error;
+
+ if (!fsconvert_strdup(keyval, &envlist[envc++])) {
+ Py_DECREF(keyval);
+ goto error;
+ }
+
+ Py_DECREF(keyval);
}
Py_DECREF(vals);
Py_DECREF(keys);
@@ -4990,17 +4848,15 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
error:
Py_XDECREF(keys);
Py_XDECREF(vals);
- while (--envc >= 0)
- PyMem_DEL(envlist[envc]);
- PyMem_DEL(envlist);
+ free_string_array(envlist, envc);
return NULL;
}
-static char**
+static EXECV_CHAR**
parse_arglist(PyObject* argv, Py_ssize_t *argc)
{
int i;
- char **argvlist = PyMem_NEW(char *, *argc+1);
+ EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
if (argvlist == NULL) {
PyErr_NoMemory();
return NULL;
@@ -5022,6 +4878,7 @@ fail:
free_string_array(argvlist, *argc);
return NULL;
}
+
#endif
@@ -5029,7 +4886,7 @@ fail:
/*[clinic input]
os.execv
- path: FSConverter
+ path: path_t
Path of executable file.
argv: object
Tuple or list of strings.
@@ -5039,17 +4896,15 @@ Execute an executable path with arguments, replacing current process.
[clinic start generated code]*/
static PyObject *
-os_execv_impl(PyObject *module, PyObject *path, PyObject *argv)
-/*[clinic end generated code: output=b21dc34deeb5b004 input=96041559925e5229]*/
+os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
+/*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
{
- char *path_char;
- char **argvlist;
+ EXECV_CHAR **argvlist;
Py_ssize_t argc;
/* execv has two arguments: (path, argv), where
argv is a list or tuple of strings. */
- path_char = PyBytes_AsString(path);
if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
PyErr_SetString(PyExc_TypeError,
"execv() arg 2 must be a tuple or list");
@@ -5065,8 +4920,20 @@ os_execv_impl(PyObject *module, PyObject *path, PyObject *argv)
if (argvlist == NULL) {
return NULL;
}
+ if (!argvlist[0][0]) {
+ PyErr_SetString(PyExc_ValueError,
+ "execv() arg 2 first element cannot be empty");
+ free_string_array(argvlist, argc);
+ return NULL;
+ }
- execv(path_char, argvlist);
+ _Py_BEGIN_SUPPRESS_IPH
+#ifdef HAVE_WEXECV
+ _wexecv(path->wide, argvlist);
+#else
+ execv(path->narrow, argvlist);
+#endif
+ _Py_END_SUPPRESS_IPH
/* If we get here it's definitely an error */
@@ -5092,8 +4959,8 @@ static PyObject *
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
/*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
{
- char **argvlist = NULL;
- char **envlist;
+ EXECV_CHAR **argvlist = NULL;
+ EXECV_CHAR **envlist;
Py_ssize_t argc, envc;
/* execve has three arguments: (path, argv, env), where
@@ -5106,6 +4973,11 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
goto fail;
}
argc = PySequence_Size(argv);
+ if (argc < 1) {
+ PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
+ return NULL;
+ }
+
if (!PyMapping_Check(env)) {
PyErr_SetString(PyExc_TypeError,
"execve: environment must be a mapping object");
@@ -5116,40 +4988,50 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
if (argvlist == NULL) {
goto fail;
}
+ if (!argvlist[0][0]) {
+ PyErr_SetString(PyExc_ValueError,
+ "execve: argv first element cannot be empty");
+ goto fail;
+ }
envlist = parse_envlist(env, &envc);
if (envlist == NULL)
goto fail;
+ _Py_BEGIN_SUPPRESS_IPH
#ifdef HAVE_FEXECVE
if (path->fd > -1)
fexecve(path->fd, argvlist, envlist);
else
#endif
+#ifdef HAVE_WEXECV
+ _wexecve(path->wide, argvlist, envlist);
+#else
execve(path->narrow, argvlist, envlist);
+#endif
+ _Py_END_SUPPRESS_IPH
/* If we get here it's definitely an error */
path_error(path);
- while (--envc >= 0)
- PyMem_DEL(envlist[envc]);
- PyMem_DEL(envlist);
+ free_string_array(envlist, envc);
fail:
if (argvlist)
free_string_array(argvlist, argc);
return NULL;
}
+
#endif /* HAVE_EXECV */
-#ifdef HAVE_SPAWNV
+#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)
/*[clinic input]
os.spawnv
mode: int
Mode of process creation.
- path: FSConverter
+ path: path_t
Path of executable file.
argv: object
Tuple or list of strings.
@@ -5159,20 +5041,18 @@ Execute the program specified by path in a new process.
[clinic start generated code]*/
static PyObject *
-os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv)
-/*[clinic end generated code: output=c427c0ce40f10638 input=042c91dfc1e6debc]*/
+os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
+/*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
{
- char *path_char;
- char **argvlist;
+ EXECV_CHAR **argvlist;
int i;
Py_ssize_t argc;
- Py_intptr_t spawnval;
+ intptr_t spawnval;
PyObject *(*getitem)(PyObject *, Py_ssize_t);
/* spawnv has three arguments: (mode, path, argv), where
argv is a list or tuple of strings. */
- path_char = PyBytes_AsString(path);
if (PyList_Check(argv)) {
argc = PyList_Size(argv);
getitem = PyList_GetItem;
@@ -5186,18 +5066,13 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv)
"spawnv() arg 2 must be a tuple or list");
return NULL;
}
-#ifdef MS_WINDOWS
- /* Avoid changing behavior in maintenance release, but
- the previous Windows behavior was to crash, so this
- is a "compatible" improvement. */
if (argc == 0) {
PyErr_SetString(PyExc_ValueError,
- "spawnv() arg 2 cannot be empty");
+ "spawnv() arg 2 cannot be empty");
return NULL;
}
-#endif
- argvlist = PyMem_NEW(char *, argc+1);
+ argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
if (argvlist == NULL) {
return PyErr_NoMemory();
}
@@ -5210,7 +5085,6 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv)
"spawnv() arg 2 must contain only strings");
return NULL;
}
-#ifdef MS_WINDOWS
if (i == 0 && !argvlist[0][0]) {
free_string_array(argvlist, i);
PyErr_SetString(
@@ -5218,7 +5092,6 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv)
"spawnv() arg 2 first element cannot be empty");
return NULL;
}
-#endif
}
argvlist[argc] = NULL;
@@ -5227,7 +5100,11 @@ os_spawnv_impl(PyObject *module, int mode, PyObject *path, PyObject *argv)
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
- spawnval = _spawnv(mode, path_char, argvlist);
+#ifdef HAVE_WSPAWNV
+ spawnval = _wspawnv(mode, path->wide, argvlist);
+#else
+ spawnval = _spawnv(mode, path->narrow, argvlist);
+#endif
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
@@ -5245,7 +5122,7 @@ os.spawnve
mode: int
Mode of process creation.
- path: FSConverter
+ path: path_t
Path of executable file.
argv: object
Tuple or list of strings.
@@ -5257,16 +5134,15 @@ Execute the program specified by path in a new process.
[clinic start generated code]*/
static PyObject *
-os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv,
+os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
PyObject *env)
-/*[clinic end generated code: output=ebcfa5f7ba2f4219 input=02362fd937963f8f]*/
+/*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
{
- char *path_char;
- char **argvlist;
- char **envlist;
+ EXECV_CHAR **argvlist;
+ EXECV_CHAR **envlist;
PyObject *res = NULL;
Py_ssize_t argc, i, envc;
- Py_intptr_t spawnval;
+ intptr_t spawnval;
PyObject *(*getitem)(PyObject *, Py_ssize_t);
Py_ssize_t lastarg = 0;
@@ -5274,7 +5150,6 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv,
argv is a list or tuple of strings and env is a dictionary
like posix.environ. */
- path_char = PyBytes_AsString(path);
if (PyList_Check(argv)) {
argc = PyList_Size(argv);
getitem = PyList_GetItem;
@@ -5288,13 +5163,18 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv,
"spawnve() arg 2 must be a tuple or list");
goto fail_0;
}
+ if (argc == 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "spawnve() arg 2 cannot be empty");
+ goto fail_0;
+ }
if (!PyMapping_Check(env)) {
PyErr_SetString(PyExc_TypeError,
"spawnve() arg 3 must be a mapping object");
goto fail_0;
}
- argvlist = PyMem_NEW(char *, argc+1);
+ argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
if (argvlist == NULL) {
PyErr_NoMemory();
goto fail_0;
@@ -5306,6 +5186,13 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv,
lastarg = i;
goto fail_1;
}
+ if (i == 0 && !argvlist[0][0]) {
+ lastarg = i;
+ PyErr_SetString(
+ PyExc_ValueError,
+ "spawnv() arg 2 first element cannot be empty");
+ goto fail_1;
+ }
}
lastarg = argc;
argvlist[argc] = NULL;
@@ -5319,7 +5206,11 @@ os_spawnve_impl(PyObject *module, int mode, PyObject *path, PyObject *argv,
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
- spawnval = _spawnve(mode, path_char, argvlist, envlist);
+#ifdef HAVE_WSPAWNV
+ spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
+#else
+ spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
+#endif
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
@@ -5783,14 +5674,14 @@ os.sched_getaffinity
pid: pid_t
/
-Return the affinity of the process identified by pid.
+Return the affinity of the process identified by pid (or the current process if zero).
The affinity is returned as a set of CPU identifiers.
[clinic start generated code]*/
static PyObject *
os_sched_getaffinity_impl(PyObject *module, pid_t pid)
-/*[clinic end generated code: output=f726f2c193c17a4f input=eaf161936874b8a1]*/
+/*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
{
int cpu, ncpus, count;
size_t setsize;
@@ -5951,7 +5842,7 @@ os_openpty_impl(PyObject *module)
if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
goto posix_error;
-#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
+#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
#ifndef __hpux
@@ -6063,6 +5954,7 @@ os_getgid_impl(PyObject *module)
#endif /* HAVE_GETGID */
+#ifdef HAVE_GETPID
/*[clinic input]
os.getpid
@@ -6075,6 +5967,7 @@ os_getpid_impl(PyObject *module)
{
return PyLong_FromPid(getpid());
}
+#endif /* HAVE_GETPID */
#ifdef HAVE_GETGROUPLIST
@@ -6276,7 +6169,7 @@ static PyObject *
posix_initgroups(PyObject *self, PyObject *args)
{
PyObject *oname;
- char *username;
+ const char *username;
int res;
#ifdef __APPLE__
int gid;
@@ -7023,7 +6916,7 @@ os_waitpid_impl(PyObject *module, pid_t pid, int options)
/* MS C has a variant of waitpid() that's usable for most purposes. */
/*[clinic input]
os.waitpid
- pid: Py_intptr_t
+ pid: intptr_t
options: int
/
@@ -7036,11 +6929,11 @@ The options argument is ignored on Windows.
[clinic start generated code]*/
static PyObject *
-os_waitpid_impl(PyObject *module, Py_intptr_t pid, int options)
-/*[clinic end generated code: output=15f1ce005a346b09 input=444c8f51cca5b862]*/
+os_waitpid_impl(PyObject *module, intptr_t pid, int options)
+/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
{
int status;
- Py_intptr_t res;
+ intptr_t res;
int async_err = 0;
do {
@@ -7153,16 +7046,16 @@ exit:
static PyObject *
win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
{
- wchar_t *path;
+ const wchar_t *path;
DWORD n_bytes_returned;
DWORD io_result;
PyObject *po, *result;
- int dir_fd;
+ int dir_fd;
HANDLE reparse_point_handle;
- char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
- REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
- wchar_t *print_name;
+ char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
+ const wchar_t *print_name;
static char *keywords[] = {"path", "dir_fd", NULL};
@@ -7230,22 +7123,19 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
#if defined(MS_WINDOWS)
/* Grab CreateSymbolicLinkW dynamically from kernel32 */
-static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL;
-static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL;
+static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL;
static int
check_CreateSymbolicLink(void)
{
HINSTANCE hKernel32;
/* only recheck */
- if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA)
+ if (Py_CreateSymbolicLinkW)
return 1;
hKernel32 = GetModuleHandleW(L"KERNEL32");
*(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
"CreateSymbolicLinkW");
- *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32,
- "CreateSymbolicLinkA");
- return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA);
+ return Py_CreateSymbolicLinkW != NULL;
}
/* Remove the last portion of the path */
@@ -7262,20 +7152,6 @@ _dirnameW(WCHAR *path)
*ptr = 0;
}
-/* Remove the last portion of the path */
-static void
-_dirnameA(char *path)
-{
- char *ptr;
-
- /* walk the path from the end until a backslash is encountered */
- for(ptr = path + strlen(path); ptr != path; ptr--) {
- if (*ptr == '\\' || *ptr == '/')
- break;
- }
- *ptr = 0;
-}
-
/* Is this path absolute? */
static int
_is_absW(const WCHAR *path)
@@ -7284,14 +7160,6 @@ _is_absW(const WCHAR *path)
}
-/* Is this path absolute? */
-static int
-_is_absA(const char *path)
-{
- return path[0] == '\\' || path[0] == '/' || path[1] == ':';
-
-}
-
/* join root and rest with a backslash */
static void
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
@@ -7313,30 +7181,9 @@ _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
wcscpy(dest_path+root_len, rest);
}
-/* join root and rest with a backslash */
-static void
-_joinA(char *dest_path, const char *root, const char *rest)
-{
- size_t root_len;
-
- if (_is_absA(rest)) {
- strcpy(dest_path, rest);
- return;
- }
-
- root_len = strlen(root);
-
- strcpy(dest_path, root);
- if(root_len) {
- dest_path[root_len] = '\\';
- root_len++;
- }
- strcpy(dest_path+root_len, rest);
-}
-
/* Return True if the path at src relative to dest is a directory */
static int
-_check_dirW(WCHAR *src, WCHAR *dest)
+_check_dirW(LPCWSTR src, LPCWSTR dest)
{
WIN32_FILE_ATTRIBUTE_DATA src_info;
WCHAR dest_parent[MAX_PATH];
@@ -7352,25 +7199,6 @@ _check_dirW(WCHAR *src, WCHAR *dest)
&& src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
);
}
-
-/* Return True if the path at src relative to dest is a directory */
-static int
-_check_dirA(char *src, char *dest)
-{
- WIN32_FILE_ATTRIBUTE_DATA src_info;
- char dest_parent[MAX_PATH];
- char src_resolved[MAX_PATH] = "";
-
- /* dest_parent = os.path.dirname(dest) */
- strcpy(dest_parent, dest);
- _dirnameA(dest_parent);
- /* src_resolved = os.path.join(dest_parent, src) */
- _joinA(src_resolved, dest_parent, src);
- return (
- GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info)
- && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
- );
-}
#endif
@@ -7430,18 +7258,10 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (dst->wide) {
- /* if src is a directory, ensure target_is_directory==1 */
- target_is_directory |= _check_dirW(src->wide, dst->wide);
- result = Py_CreateSymbolicLinkW(dst->wide, src->wide,
- target_is_directory);
- }
- else {
- /* if src is a directory, ensure target_is_directory==1 */
- target_is_directory |= _check_dirA(src->narrow, dst->narrow);
- result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow,
- target_is_directory);
- }
+ /* if src is a directory, ensure target_is_directory==1 */
+ target_is_directory |= _check_dirW(src->wide, dst->wide);
+ result = Py_CreateSymbolicLinkW(dst->wide, src->wide,
+ target_is_directory);
Py_END_ALLOW_THREADS
if (!result)
@@ -7746,16 +7566,15 @@ os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
do {
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path->wide)
- fd = _wopen(path->wide, flags, mode);
- else
-#endif
+ fd = _wopen(path->wide, flags, mode);
+#else
#ifdef HAVE_OPENAT
if (dir_fd != DEFAULT_DIR_FD)
fd = openat(dir_fd, path->narrow, flags, mode);
else
-#endif
+#endif /* HAVE_OPENAT */
fd = open(path->narrow, flags, mode);
+#endif /* !MS_WINDOWS */
Py_END_ALLOW_THREADS
} while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
_Py_END_SUPPRESS_IPH
@@ -7790,8 +7609,6 @@ os_close_impl(PyObject *module, int fd)
/*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
{
int res;
- if (!_PyVerify_fd(fd))
- return posix_error();
/* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
* and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
* for more details.
@@ -7824,9 +7641,8 @@ os_closerange_impl(PyObject *module, int fd_low, int fd_high)
int i;
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
- for (i = fd_low; i < fd_high; i++)
- if (_PyVerify_fd(i))
- close(i);
+ for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
+ close(i);
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
Py_RETURN_NONE;
@@ -7870,7 +7686,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
int dup3_works = -1;
#endif
- if (!_PyVerify_fd_dup2(fd, fd2))
+ if (fd < 0 || fd2 < 0)
return posix_error();
/* dup2() can fail with EINTR if the target FD is already open, because it
@@ -7994,10 +7810,6 @@ os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
{
Py_off_t result;
- if (!_PyVerify_fd(fd)) {
- posix_error();
- return -1;
- }
#ifdef SEEK_SET
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
switch (how) {
@@ -8010,10 +7822,6 @@ os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
if (PyErr_Occurred())
return -1;
- if (!_PyVerify_fd(fd)) {
- posix_error();
- return -1;
- }
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
@@ -8221,10 +8029,6 @@ os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
buffer = PyBytes_FromStringAndSize((char *)NULL, length);
if (buffer == NULL)
return NULL;
- if (!_PyVerify_fd(fd)) {
- Py_DECREF(buffer);
- return posix_error();
- }
do {
Py_BEGIN_ALLOW_THREADS
@@ -8387,7 +8191,7 @@ done:
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
keywords, &out, &in, &offobj, &count))
return NULL;
-#ifdef linux
+#ifdef __linux__
if (offobj == Py_None) {
do {
Py_BEGIN_ALLOW_THREADS
@@ -8467,8 +8271,6 @@ os_isatty_impl(PyObject *module, int fd)
/*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
{
int return_value;
- if (!_PyVerify_fd(fd))
- return 0;
_Py_BEGIN_SUPPRESS_IPH
return_value = isatty(fd);
_Py_END_SUPPRESS_IPH
@@ -8505,16 +8307,18 @@ os_pipe_impl(PyObject *module)
attr.bInheritHandle = FALSE;
Py_BEGIN_ALLOW_THREADS
+ _Py_BEGIN_SUPPRESS_IPH
ok = CreatePipe(&read, &write, &attr, 0);
if (ok) {
- fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY);
- fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY);
+ fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY);
+ fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY);
if (fds[0] == -1 || fds[1] == -1) {
CloseHandle(read);
CloseHandle(write);
ok = 0;
}
}
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
if (!ok)
@@ -8660,11 +8464,6 @@ os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
Py_ssize_t size;
int async_err = 0;
- if (!_PyVerify_fd(fd)) {
- posix_error();
- return -1;
- }
-
do {
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
@@ -8847,9 +8646,6 @@ os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
int result;
int async_err = 0;
- if (!_PyVerify_fd(fd))
- return posix_error();
-
do {
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
@@ -8896,10 +8692,7 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
- if (path->wide)
- fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
- else
- fd = _open(path->narrow, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
+ fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
if (fd < 0)
result = -1;
else {
@@ -9043,7 +8836,7 @@ static PyObject *
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
{
- wchar_t *env;
+ const wchar_t *env;
PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
if (unicode == NULL) {
@@ -9089,8 +8882,8 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
{
PyObject *bytes = NULL;
char *env;
- char *name_string = PyBytes_AsString(name);
- char *value_string = PyBytes_AsString(value);
+ const char *name_string = PyBytes_AsString(name);
+ const char *value_string = PyBytes_AsString(value);
bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
if (bytes == NULL) {
@@ -9368,17 +9161,17 @@ _pystatvfs_fromstructstatvfs(struct statvfs st) {
PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
PyStructSequence_SET_ITEM(v, 2,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
+ PyLong_FromLongLong((long long) st.f_blocks));
PyStructSequence_SET_ITEM(v, 3,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
+ PyLong_FromLongLong((long long) st.f_bfree));
PyStructSequence_SET_ITEM(v, 4,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
+ PyLong_FromLongLong((long long) st.f_bavail));
PyStructSequence_SET_ITEM(v, 5,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
+ PyLong_FromLongLong((long long) st.f_files));
PyStructSequence_SET_ITEM(v, 6,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
+ PyLong_FromLongLong((long long) st.f_ffree));
PyStructSequence_SET_ITEM(v, 7,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
+ PyLong_FromLongLong((long long) st.f_favail));
PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
#endif
@@ -9509,8 +9302,8 @@ os__getdiskusage_impl(PyObject *module, Py_UNICODE *path)
* sufficiently pervasive that it's not worth the loss of readability.
*/
struct constdef {
- char *name;
- long value;
+ const char *name;
+ int value;
};
static int
@@ -9518,7 +9311,10 @@ conv_confname(PyObject *arg, int *valuep, struct constdef *table,
size_t tablesize)
{
if (PyLong_Check(arg)) {
- *valuep = PyLong_AS_LONG(arg);
+ int value = _PyLong_AsInt(arg);
+ if (value == -1 && PyErr_Occurred())
+ return 0;
+ *valuep = value;
return 1;
}
else {
@@ -9533,7 +9329,7 @@ conv_confname(PyObject *arg, int *valuep, struct constdef *table,
"configuration names must be strings or integers");
return 0;
}
- confname = _PyUnicode_AsString(arg);
+ confname = PyUnicode_AsUTF8(arg);
if (confname == NULL)
return 0;
while (lo < hi) {
@@ -10479,7 +10275,7 @@ cmp_constdefs(const void *v1, const void *v2)
static int
setup_confname_table(struct constdef *table, size_t tablesize,
- char *tablename, PyObject *module)
+ const char *tablename, PyObject *module)
{
PyObject *d = NULL;
size_t i;
@@ -10550,31 +10346,8 @@ os_abort_impl(PyObject *module)
}
#ifdef MS_WINDOWS
-/* AC 3.5: change to path_t? but that might change exceptions */
-PyDoc_STRVAR(win32_startfile__doc__,
-"startfile(filepath [, operation])\n\
-\n\
-Start a file with its associated application.\n\
-\n\
-When \"operation\" is not specified or \"open\", this acts like\n\
-double-clicking the file in Explorer, or giving the file name as an\n\
-argument to the DOS \"start\" command: the file is opened with whatever\n\
-application (if any) its extension is associated.\n\
-When another \"operation\" is given, it specifies what should be done with\n\
-the file. A typical operation is \"print\".\n\
-\n\
-startfile returns as soon as the associated application is launched.\n\
-There is no option to wait for the application to close, and no way\n\
-to retrieve the application's exit status.\n\
-\n\
-The filepath is relative to the current directory. If you want to use\n\
-an absolute path, make sure the first character is not a slash (\"/\");\n\
-the underlying Win32 ShellExecute function doesn't work if it is.");
-
/* Grab ShellExecute dynamically from shell32 */
static int has_ShellExecute = -1;
-static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR,
- LPCSTR, INT);
static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
LPCWSTR, INT);
static int
@@ -10588,12 +10361,9 @@ check_ShellExecute()
hShell32 = LoadLibraryW(L"SHELL32");
Py_END_ALLOW_THREADS
if (hShell32) {
- *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32,
- "ShellExecuteA");
*(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
"ShellExecuteW");
- has_ShellExecute = Py_ShellExecuteA &&
- Py_ShellExecuteW;
+ has_ShellExecute = Py_ShellExecuteW != NULL;
} else {
has_ShellExecute = 0;
}
@@ -10602,17 +10372,37 @@ check_ShellExecute()
}
+/*[clinic input]
+os.startfile
+ filepath: path_t
+ operation: Py_UNICODE = NULL
+
+startfile(filepath [, operation])
+
+Start a file with its associated application.
+
+When "operation" is not specified or "open", this acts like
+double-clicking the file in Explorer, or giving the file name as an
+argument to the DOS "start" command: the file is opened with whatever
+application (if any) its extension is associated.
+When another "operation" is given, it specifies what should be done with
+the file. A typical operation is "print".
+
+startfile returns as soon as the associated application is launched.
+There is no option to wait for the application to close, and no way
+to retrieve the application's exit status.
+
+The filepath is relative to the current directory. If you want to use
+an absolute path, make sure the first character is not a slash ("/");
+the underlying Win32 ShellExecute function doesn't work if it is.
+[clinic start generated code]*/
+
static PyObject *
-win32_startfile(PyObject *self, PyObject *args)
+os_startfile_impl(PyObject *module, path_t *filepath, Py_UNICODE *operation)
+/*[clinic end generated code: output=912ceba79acfa1c9 input=63950bf2986380d0]*/
{
- PyObject *ofilepath;
- char *filepath;
- char *operation = NULL;
- wchar_t *wpath, *woperation;
HINSTANCE rc;
- PyObject *unipath, *uoperation = NULL;
-
if(!check_ShellExecute()) {
/* If the OS doesn't have ShellExecute, return a
NotImplementedError. */
@@ -10620,68 +10410,16 @@ win32_startfile(PyObject *self, PyObject *args)
"startfile not available on this platform");
}
- if (!PyArg_ParseTuple(args, "U|s:startfile",
- &unipath, &operation)) {
- PyErr_Clear();
- goto normal;
- }
-
- if (operation) {
- uoperation = PyUnicode_DecodeASCII(operation,
- strlen(operation), NULL);
- if (!uoperation) {
- PyErr_Clear();
- operation = NULL;
- goto normal;
- }
- }
-
- wpath = PyUnicode_AsUnicode(unipath);
- if (wpath == NULL)
- goto normal;
- if (uoperation) {
- woperation = PyUnicode_AsUnicode(uoperation);
- if (woperation == NULL)
- goto normal;
- }
- else
- woperation = NULL;
-
Py_BEGIN_ALLOW_THREADS
- rc = Py_ShellExecuteW((HWND)0, woperation, wpath,
+ rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
NULL, NULL, SW_SHOWNORMAL);
Py_END_ALLOW_THREADS
- Py_XDECREF(uoperation);
if (rc <= (HINSTANCE)32) {
- win32_error_object("startfile", unipath);
+ win32_error_object("startfile", filepath->object);
return NULL;
}
- Py_INCREF(Py_None);
- return Py_None;
-
-normal:
- if (!PyArg_ParseTuple(args, "O&|s:startfile",
- PyUnicode_FSConverter, &ofilepath,
- &operation))
- return NULL;
- if (win32_warn_bytes_api()) {
- Py_DECREF(ofilepath);
- return NULL;
- }
- filepath = PyBytes_AsString(ofilepath);
- Py_BEGIN_ALLOW_THREADS
- rc = Py_ShellExecuteA((HWND)0, operation, filepath,
- NULL, NULL, SW_SHOWNORMAL);
- Py_END_ALLOW_THREADS
- if (rc <= (HINSTANCE)32) {
- PyObject *errval = win32_error("startfile", filepath);
- Py_DECREF(ofilepath);
- return errval;
- }
- Py_DECREF(ofilepath);
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* MS_WINDOWS */
@@ -10849,7 +10587,7 @@ os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
for (i = 0; ; i++) {
void *ptr;
ssize_t result;
- static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
+ static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
Py_ssize_t buffer_size = buffer_sizes[i];
if (!buffer_size) {
path_error(path);
@@ -11013,9 +10751,9 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
name = path->narrow ? path->narrow : ".";
for (i = 0; ; i++) {
- char *start, *trace, *end;
+ const char *start, *trace, *end;
ssize_t length;
- static Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
+ static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
Py_ssize_t buffer_size = buffer_sizes[i];
if (!buffer_size) {
/* ERANGE */
@@ -11106,8 +10844,7 @@ os_urandom_impl(PyObject *module, Py_ssize_t size)
if (bytes == NULL)
return NULL;
- result = _PyOS_URandom(PyBytes_AS_STRING(bytes),
- PyBytes_GET_SIZE(bytes));
+ result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
if (result == -1) {
Py_DECREF(bytes);
return NULL;
@@ -11227,11 +10964,15 @@ get_terminal_size(PyObject *self, PyObject *args)
os.cpu_count
Return the number of CPUs in the system; return None if indeterminable.
+
+This number is not equivalent to the number of CPUs the current process can
+use. The number of usable CPUs can be obtained with
+``len(os.sched_getaffinity(0))``
[clinic start generated code]*/
static PyObject *
os_cpu_count_impl(PyObject *module)
-/*[clinic end generated code: output=5fc29463c3936a9c input=d55e2f8f3823a628]*/
+/*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
{
int ncpu = 0;
#ifdef MS_WINDOWS
@@ -11275,11 +11016,6 @@ os_get_inheritable_impl(PyObject *module, int fd)
/*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
{
int return_value;
- if (!_PyVerify_fd(fd)) {
- posix_error();
- return -1;
- }
-
_Py_BEGIN_SUPPRESS_IPH
return_value = _Py_get_inheritable(fd);
_Py_END_SUPPRESS_IPH
@@ -11301,8 +11037,6 @@ os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
/*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
{
int result;
- if (!_PyVerify_fd(fd))
- return posix_error();
_Py_BEGIN_SUPPRESS_IPH
result = _Py_set_inheritable(fd, inheritable, NULL);
@@ -11316,15 +11050,15 @@ os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
#ifdef MS_WINDOWS
/*[clinic input]
os.get_handle_inheritable -> bool
- handle: Py_intptr_t
+ handle: intptr_t
/
Get the close-on-exe flag of the specified file descriptor.
[clinic start generated code]*/
static int
-os_get_handle_inheritable_impl(PyObject *module, Py_intptr_t handle)
-/*[clinic end generated code: output=9e5389b0aa0916ce input=5f7759443aae3dc5]*/
+os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
+/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
{
DWORD flags;
@@ -11339,7 +11073,7 @@ os_get_handle_inheritable_impl(PyObject *module, Py_intptr_t handle)
/*[clinic input]
os.set_handle_inheritable
- handle: Py_intptr_t
+ handle: intptr_t
inheritable: bool
/
@@ -11347,9 +11081,9 @@ Set the inheritable flag of the specified handle.
[clinic start generated code]*/
static PyObject *
-os_set_handle_inheritable_impl(PyObject *module, Py_intptr_t handle,
+os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
int inheritable)
-/*[clinic end generated code: output=b1e67bfa3213d745 input=e64b2b2730469def]*/
+/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
{
DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
@@ -11376,9 +11110,6 @@ posix_get_blocking(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "i:get_blocking", &fd))
return NULL;
- if (!_PyVerify_fd(fd))
- return posix_error();
-
_Py_BEGIN_SUPPRESS_IPH
blocking = _Py_get_blocking(fd);
_Py_END_SUPPRESS_IPH
@@ -11402,9 +11133,6 @@ posix_set_blocking(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking))
return NULL;
- if (!_PyVerify_fd(fd))
- return posix_error();
-
_Py_BEGIN_SUPPRESS_IPH
result = _Py_set_blocking(fd, blocking);
_Py_END_SUPPRESS_IPH
@@ -11485,41 +11213,26 @@ static PyObject *
DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
{
int result;
- struct _Py_stat_struct st;
+ STRUCT_STAT st;
+ PyObject *ub;
#ifdef MS_WINDOWS
- wchar_t *path;
-
- path = PyUnicode_AsUnicode(self->path);
- if (!path)
- return NULL;
-
- if (follow_symlinks)
- result = win32_stat_w(path, &st);
- else
- result = win32_lstat_w(path, &st);
-
- if (result != 0) {
- return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError,
- 0, self->path);
- }
+ if (PyUnicode_FSDecoder(self->path, &ub)) {
+ const wchar_t *path = PyUnicode_AsUnicode(ub);
#else /* POSIX */
- PyObject *bytes;
- char *path;
-
- if (!PyUnicode_FSConverter(self->path, &bytes))
+ if (PyUnicode_FSConverter(self->path, &ub)) {
+ const char *path = PyBytes_AS_STRING(ub);
+#endif
+ if (follow_symlinks)
+ result = STAT(path, &st);
+ else
+ result = LSTAT(path, &st);
+ Py_DECREF(ub);
+ } else
return NULL;
- path = PyBytes_AS_STRING(bytes);
-
- if (follow_symlinks)
- result = STAT(path, &st);
- else
- result = LSTAT(path, &st);
- Py_DECREF(bytes);
if (result != 0)
- return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, self->path);
-#endif
+ return path_object_error(self->path);
return _pystat_fromstructstat(&st);
}
@@ -11689,25 +11402,27 @@ DirEntry_inode(DirEntry *self)
{
#ifdef MS_WINDOWS
if (!self->got_file_index) {
- wchar_t *path;
- struct _Py_stat_struct stat;
+ PyObject *unicode;
+ const wchar_t *path;
+ STRUCT_STAT stat;
+ int result;
- path = PyUnicode_AsUnicode(self->path);
- if (!path)
+ if (!PyUnicode_FSDecoder(self->path, &unicode))
return NULL;
+ path = PyUnicode_AsUnicode(unicode);
+ result = LSTAT(path, &stat);
+ Py_DECREF(unicode);
- if (win32_lstat_w(path, &stat) != 0) {
- return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError,
- 0, self->path);
- }
+ if (result != 0)
+ return path_object_error(self->path);
self->win32_file_index = stat.st_ino;
self->got_file_index = 1;
}
- return PyLong_FromLongLong((PY_LONG_LONG)self->win32_file_index);
+ return PyLong_FromLongLong((long long)self->win32_file_index);
#else /* POSIX */
#ifdef HAVE_LARGEFILE_SUPPORT
- return PyLong_FromLongLong((PY_LONG_LONG)self->d_ino);
+ return PyLong_FromLongLong((long long)self->d_ino);
#else
return PyLong_FromLong((long)self->d_ino);
#endif
@@ -11720,6 +11435,13 @@ DirEntry_repr(DirEntry *self)
return PyUnicode_FromFormat("<DirEntry %R>", self->name);
}
+static PyObject *
+DirEntry_fspath(DirEntry *self)
+{
+ Py_INCREF(self->path);
+ return self->path;
+}
+
static PyMemberDef DirEntry_members[] = {
{"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
"the entry's base filename, relative to scandir() \"path\" argument"},
@@ -11744,6 +11466,9 @@ static PyMethodDef DirEntry_methods[] = {
{"inode", (PyCFunction)DirEntry_inode, METH_NOARGS,
"return inode of the entry; cached per entry",
},
+ {"__fspath__", (PyCFunction)DirEntry_fspath, METH_NOARGS,
+ "returns the path for the entry",
+ },
{NULL}
};
@@ -11783,7 +11508,7 @@ static PyTypeObject DirEntryType = {
#ifdef MS_WINDOWS
static wchar_t *
-join_path_filenameW(wchar_t *path_wide, wchar_t* filename)
+join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
{
Py_ssize_t path_len;
Py_ssize_t size;
@@ -11835,6 +11560,11 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
if (!entry->name)
goto error;
+ if (path->narrow) {
+ Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
+ if (!entry->name)
+ goto error;
+ }
joined_path = join_path_filenameW(path->wide, dataW->cFileName);
if (!joined_path)
@@ -11844,8 +11574,13 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
PyMem_Free(joined_path);
if (!entry->path)
goto error;
+ if (path->narrow) {
+ Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
+ if (!entry->path)
+ goto error;
+ }
- find_data_to_file_info_w(dataW, &file_info, &reparse_tag);
+ find_data_to_file_info(dataW, &file_info, &reparse_tag);
_Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
return (PyObject *)entry;
@@ -11858,7 +11593,7 @@ error:
#else /* POSIX */
static char *
-join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len)
+join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
{
Py_ssize_t path_len;
Py_ssize_t size;
@@ -11890,7 +11625,7 @@ join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len)
}
static PyObject *
-DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len,
+DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
ino_t d_ino
#ifdef HAVE_DIRENT_D_TYPE
, unsigned char d_type
@@ -11953,8 +11688,14 @@ typedef struct {
#ifdef MS_WINDOWS
+static int
+ScandirIterator_is_closed(ScandirIterator *iterator)
+{
+ return iterator->handle == INVALID_HANDLE_VALUE;
+}
+
static void
-ScandirIterator_close(ScandirIterator *iterator)
+ScandirIterator_closedir(ScandirIterator *iterator)
{
HANDLE handle = iterator->handle;
@@ -11974,7 +11715,7 @@ ScandirIterator_iternext(ScandirIterator *iterator)
BOOL success;
PyObject *entry;
- /* Happens if the iterator is iterated twice */
+ /* Happens if the iterator is iterated twice, or closed explicitly */
if (iterator->handle == INVALID_HANDLE_VALUE)
return NULL;
@@ -12005,14 +11746,20 @@ ScandirIterator_iternext(ScandirIterator *iterator)
}
/* Error or no more files */
- ScandirIterator_close(iterator);
+ ScandirIterator_closedir(iterator);
return NULL;
}
#else /* POSIX */
+static int
+ScandirIterator_is_closed(ScandirIterator *iterator)
+{
+ return !iterator->dirp;
+}
+
static void
-ScandirIterator_close(ScandirIterator *iterator)
+ScandirIterator_closedir(ScandirIterator *iterator)
{
DIR *dirp = iterator->dirp;
@@ -12034,7 +11781,7 @@ ScandirIterator_iternext(ScandirIterator *iterator)
int is_dot;
PyObject *entry;
- /* Happens if the iterator is iterated twice */
+ /* Happens if the iterator is iterated twice, or closed explicitly */
if (!iterator->dirp)
return NULL;
@@ -12071,21 +11818,76 @@ ScandirIterator_iternext(ScandirIterator *iterator)
}
/* Error or no more files */
- ScandirIterator_close(iterator);
+ ScandirIterator_closedir(iterator);
return NULL;
}
#endif
+static PyObject *
+ScandirIterator_close(ScandirIterator *self, PyObject *args)
+{
+ ScandirIterator_closedir(self);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+ScandirIterator_enter(PyObject *self, PyObject *args)
+{
+ Py_INCREF(self);
+ return self;
+}
+
+static PyObject *
+ScandirIterator_exit(ScandirIterator *self, PyObject *args)
+{
+ ScandirIterator_closedir(self);
+ Py_RETURN_NONE;
+}
+
static void
-ScandirIterator_dealloc(ScandirIterator *iterator)
+ScandirIterator_finalize(ScandirIterator *iterator)
{
- ScandirIterator_close(iterator);
- Py_XDECREF(iterator->path.object);
+ PyObject *error_type, *error_value, *error_traceback;
+
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ if (!ScandirIterator_is_closed(iterator)) {
+ ScandirIterator_closedir(iterator);
+
+ if (PyErr_ResourceWarning((PyObject *)iterator, 1,
+ "unclosed scandir iterator %R", iterator)) {
+ /* Spurious errors can appear at shutdown */
+ if (PyErr_ExceptionMatches(PyExc_Warning)) {
+ PyErr_WriteUnraisable((PyObject *) iterator);
+ }
+ }
+ }
+
+ Py_CLEAR(iterator->path.object);
path_cleanup(&iterator->path);
+
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+}
+
+static void
+ScandirIterator_dealloc(ScandirIterator *iterator)
+{
+ if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
+ return;
+
Py_TYPE(iterator)->tp_free((PyObject *)iterator);
}
+static PyMethodDef ScandirIterator_methods[] = {
+ {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
+ {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
+ {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
+ {NULL}
+};
+
static PyTypeObject ScandirIteratorType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODNAME ".ScandirIterator", /* tp_name */
@@ -12107,7 +11909,8 @@ static PyTypeObject ScandirIteratorType = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
@@ -12115,6 +11918,27 @@ static PyTypeObject ScandirIteratorType = {
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)ScandirIterator_iternext, /* tp_iternext */
+ ScandirIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+ (destructor)ScandirIterator_finalize, /* tp_finalize */
};
static PyObject *
@@ -12125,7 +11949,7 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs)
#ifdef MS_WINDOWS
wchar_t *path_strW;
#else
- char *path;
+ const char *path;
#endif
iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
@@ -12152,11 +11976,6 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs)
Py_XINCREF(iterator->path.object);
#ifdef MS_WINDOWS
- if (iterator->path.narrow) {
- PyErr_SetString(PyExc_TypeError,
- "os.scandir() doesn't support bytes path on Windows, use Unicode instead");
- goto error;
- }
iterator->first_time = 1;
path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
@@ -12197,6 +12016,132 @@ error:
return NULL;
}
+/*
+ Return the file system path representation of the object.
+
+ If the object is str or bytes, then allow it to pass through with
+ an incremented refcount. If the object defines __fspath__(), then
+ return the result of that method. All other types raise a TypeError.
+*/
+PyObject *
+PyOS_FSPath(PyObject *path)
+{
+ /* For error message reasons, this function is manually inlined in
+ path_converter(). */
+ _Py_IDENTIFIER(__fspath__);
+ PyObject *func = NULL;
+ PyObject *path_repr = NULL;
+
+ if (PyUnicode_Check(path) || PyBytes_Check(path)) {
+ Py_INCREF(path);
+ return path;
+ }
+
+ func = _PyObject_LookupSpecial(path, &PyId___fspath__);
+ if (NULL == func) {
+ return PyErr_Format(PyExc_TypeError,
+ "expected str, bytes or os.PathLike object, "
+ "not %.200s",
+ Py_TYPE(path)->tp_name);
+ }
+
+ path_repr = PyObject_CallFunctionObjArgs(func, NULL);
+ Py_DECREF(func);
+ if (NULL == path_repr) {
+ return NULL;
+ }
+
+ if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
+ PyErr_Format(PyExc_TypeError,
+ "expected %.200s.__fspath__() to return str or bytes, "
+ "not %.200s", Py_TYPE(path)->tp_name,
+ Py_TYPE(path_repr)->tp_name);
+ Py_DECREF(path_repr);
+ return NULL;
+ }
+
+ return path_repr;
+}
+
+/*[clinic input]
+os.fspath
+
+ path: object
+
+Return the file system path representation of the object.
+
+If the object is str or bytes, then allow it to pass through as-is. If the
+object defines __fspath__(), then return the result of that method. All other
+types raise a TypeError.
+[clinic start generated code]*/
+
+static PyObject *
+os_fspath_impl(PyObject *module, PyObject *path)
+/*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
+{
+ return PyOS_FSPath(path);
+}
+
+#ifdef HAVE_GETRANDOM_SYSCALL
+/*[clinic input]
+os.getrandom
+
+ size: Py_ssize_t
+ flags: int=0
+
+Obtain a series of random bytes.
+[clinic start generated code]*/
+
+static PyObject *
+os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
+/*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
+{
+ PyObject *bytes;
+ Py_ssize_t n;
+
+ if (size < 0) {
+ errno = EINVAL;
+ return posix_error();
+ }
+
+ bytes = PyBytes_FromStringAndSize(NULL, size);
+ if (bytes == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ while (1) {
+ n = syscall(SYS_getrandom,
+ PyBytes_AS_STRING(bytes),
+ PyBytes_GET_SIZE(bytes),
+ flags);
+ if (n < 0 && errno == EINTR) {
+ if (PyErr_CheckSignals() < 0) {
+ goto error;
+ }
+
+ /* getrandom() was interrupted by a signal: retry */
+ continue;
+ }
+ break;
+ }
+
+ if (n < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ goto error;
+ }
+
+ if (n != size) {
+ _PyBytes_Resize(&bytes, n);
+ }
+
+ return bytes;
+
+error:
+ Py_DECREF(bytes);
+ return NULL;
+}
+#endif /* HAVE_GETRANDOM_SYSCALL */
#include "clinic/posixmodule.c.h"
@@ -12288,7 +12233,7 @@ static PyMethodDef posix_methods[] = {
OS_KILLPG_METHODDEF
OS_PLOCK_METHODDEF
#ifdef MS_WINDOWS
- {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__},
+ OS_STARTFILE_METHODDEF
#endif
OS_SETUID_METHODDEF
OS_SETEUID_METHODDEF
@@ -12397,6 +12342,8 @@ static PyMethodDef posix_methods[] = {
{"scandir", (PyCFunction)posix_scandir,
METH_VARARGS | METH_KEYWORDS,
posix_scandir__doc__},
+ OS_FSPATH_METHODDEF
+ OS_GETRANDOM_METHODDEF
{NULL, NULL} /* Sentinel */
};
@@ -12408,7 +12355,6 @@ enable_symlink()
HANDLE tok;
TOKEN_PRIVILEGES tok_priv;
LUID luid;
- int meth_idx = 0;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok))
return 0;
@@ -12511,12 +12457,14 @@ all_ins(PyObject *m)
#ifdef O_LARGEFILE
if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
#endif
+#ifndef __GNU__
#ifdef O_SHLOCK
if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
#endif
#ifdef O_EXLOCK
if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
#endif
+#endif
#ifdef O_EXEC
if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
#endif
@@ -12819,28 +12767,33 @@ all_ins(PyObject *m)
if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
#endif
-#ifdef RTLD_LAZY
+#if HAVE_DECL_RTLD_LAZY
if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
#endif
-#ifdef RTLD_NOW
+#if HAVE_DECL_RTLD_NOW
if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
#endif
-#ifdef RTLD_GLOBAL
+#if HAVE_DECL_RTLD_GLOBAL
if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
#endif
-#ifdef RTLD_LOCAL
+#if HAVE_DECL_RTLD_LOCAL
if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
#endif
-#ifdef RTLD_NODELETE
+#if HAVE_DECL_RTLD_NODELETE
if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
#endif
-#ifdef RTLD_NOLOAD
+#if HAVE_DECL_RTLD_NOLOAD
if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
#endif
-#ifdef RTLD_DEEPBIND
+#if HAVE_DECL_RTLD_DEEPBIND
if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
#endif
+#ifdef HAVE_GETRANDOM_SYSCALL
+ if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
+ if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
+#endif
+
return 0;
}
@@ -12858,7 +12811,7 @@ static struct PyModuleDef posixmodule = {
};
-static char *have_functions[] = {
+static const char * const have_functions[] = {
#ifdef HAVE_FACCESSAT
"HAVE_FACCESSAT",
@@ -12993,7 +12946,7 @@ INITFUNC(void)
{
PyObject *m, *v;
PyObject *list;
- char **trace;
+ const char * const *trace;
#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
win32_can_symlink = enable_symlink();
@@ -13169,6 +13122,9 @@ INITFUNC(void)
}
PyModule_AddObject(m, "_have_functions", list);
+ Py_INCREF((PyObject *) &DirEntryType);
+ PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
+
initialized = 1;
return m;