diff options
Diffstat (limited to 'Modules/posixmodule.c')
| -rw-r--r-- | Modules/posixmodule.c | 1856 | 
1 files changed, 904 insertions, 952 deletions
| diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 3e446a524e..ae251025cb 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 @@ -799,16 +815,25 @@ 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) { @@ -818,11 +843,19 @@ path_cleanup(path_t *path) {  }  static int -path_converter(PyObject *o, void *p) { +path_converter(PyObject *o, void *p) +{      path_t *path = (path_t *)p; -    PyObject *unicode, *bytes; +    PyObject *bytes, *to_cleanup = NULL;      Py_ssize_t length; -    char *narrow; +    int is_index, is_buffer, is_bytes, is_unicode; +    /* Default to failure, forcing explicit signaling of succcess. */ +    int ret = 0; +    const char *narrow; +#ifdef MS_WINDOWS +    PyObject *wo; +    const wchar_t *wide; +#endif  #define FORMAT_EXCEPTION(exc, fmt) \      PyErr_Format(exc, "%s%s" fmt, \ @@ -836,122 +869,191 @@ path_converter(PyObject *o, void *p) {          return 1;      } -    /* ensure it's always safe to call path_cleanup() */ +    /* Ensure it's always safe to call path_cleanup(). */      path->cleanup = NULL; -    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; +#endif          path->length = 0;          path->object = o;          path->fd = -1;          return 1;      } -    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; -        wide = PyUnicode_AsUnicodeAndSize(unicode, &length); +        func = _PyObject_LookupSpecial(o, &PyId___fspath__); +        if (NULL == func) { +            goto error_exit; +        } + +        o = to_cleanup = PyObject_CallFunctionObjArgs(func, NULL); +        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_exit; +        } +    } + +    if (is_unicode) { +#ifdef MS_WINDOWS +        wide = PyUnicode_AsUnicodeAndSize(o, &length);          if (!wide) { -            Py_DECREF(unicode); -            return 0; +            goto exit;          }          if (length > 32767) {              FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); -            Py_DECREF(unicode); -            return 0; +            goto 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 exit;          }          path->wide = wide; -        path->narrow = NULL;          path->length = length;          path->object = o;          path->fd = -1; -        path->cleanup = unicode; -        return Py_CLEANUP_SUPPORTED; +        ret = 1; +        goto exit;  #else -        int converted = PyUnicode_FSConverter(unicode, &bytes); -        Py_DECREF(unicode); -        if (!converted) -            bytes = NULL; +        if (!PyUnicode_FSConverter(o, &bytes)) { +            goto 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 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 exit;          }      } - -    if (!bytes) { -        if (!PyErr_Occurred()) -            FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter"); -        return 0; -    } - +    else if (is_index) { +        if (!_fd_converter(o, &path->fd)) { +            goto exit; +        } +        path->wide = NULL;  #ifdef MS_WINDOWS -    if (win32_warn_bytes_api()) { -        Py_DECREF(bytes); -        return 0; -    } +        path->narrow = FALSE; +#else +        path->narrow = NULL;  #endif - -    length = PyBytes_GET_SIZE(bytes); -#ifdef MS_WINDOWS -    if (length > MAX_PATH-1) { -        FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); -        Py_DECREF(bytes); -        return 0; +        path->length = 0; +        path->object = o; +        ret = 1; +        goto exit; +    } +    else { + error_exit: +        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 exit;      } -#endif +    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");          Py_DECREF(bytes); -        return 0; +        goto exit;      } +#ifdef MS_WINDOWS +    wo = PyUnicode_DecodeFSDefaultAndSize( +        narrow, +        length +    ); +    if (!wo) { +        goto exit; +    } + +    wide = PyUnicode_AsWideCharString(wo, &length); +    Py_DECREF(wo); + +    if (!wide) { +        goto exit; +    } +    if (length > 32767) { +        FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); +        goto exit; +    } +    if (wcslen(wide) != length) { +        FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); +        goto exit; +    } +    path->wide = wide; +    path->narrow = TRUE; +#else      path->wide = NULL;      path->narrow = narrow; +#endif      path->length = length;      path->object = o;      path->fd = -1; -    path->cleanup = bytes; -    return Py_CLEANUP_SUPPORTED; +    if (bytes == o) { +        Py_DECREF(bytes); +        ret = 1; +    } +    else { +        path->cleanup = bytes; +        ret = Py_CLEANUP_SUPPORTED; +    } + exit: +    Py_XDECREF(to_cleanup); +    return ret;  }  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 +1076,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 +1086,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 +1096,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 +1112,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 +1124,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 +1137,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 +1150,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 +1178,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 +1243,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 +1271,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 +1306,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 +1321,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 +1337,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 +1391,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 +1411,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 +1456,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 +1476,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 +1484,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 +1501,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 +1511,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 +1527,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 +1535,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 +1561,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 +1599,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 +1619,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 +1627,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 +1636,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 +1931,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 +1950,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 +2030,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 +2049,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 +2348,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,7 +2376,7 @@ 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] @@ -2582,10 +2504,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 +2628,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 +2724,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 +2732,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 +3228,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 +3325,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 +3337,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 +3362,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 +3382,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 +3426,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 +3447,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 +3502,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 +3628,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 +3672,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 +3732,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 +3758,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 +3830,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 +3850,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 +3954,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 +3973,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 +4075,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 +4110,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 +4130,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 +4224,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 +4407,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 +4449,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 +4472,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 +4615,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 +4636,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 +4664,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 +4724,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 +4740,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 +4804,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 +4844,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 +4874,7 @@ fail:      free_string_array(argvlist, *argc);      return NULL;  } +  #endif @@ -5029,7 +4882,7 @@ fail:  /*[clinic input]  os.execv -    path: FSConverter +    path: path_t          Path of executable file.      argv: object          Tuple or list of strings. @@ -5039,17 +4892,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 +4916,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 +4955,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 +4969,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 +4984,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 +5037,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 +5062,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 +5081,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 +5088,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 +5096,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 +5118,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 +5130,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 +5146,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 +5159,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 +5182,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 +5202,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 +5670,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 +5838,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 +5950,7 @@ os_getgid_impl(PyObject *module)  #endif /* HAVE_GETGID */ +#ifdef HAVE_GETPID  /*[clinic input]  os.getpid @@ -6075,6 +5963,7 @@ os_getpid_impl(PyObject *module)  {      return PyLong_FromPid(getpid());  } +#endif /* HAVE_GETPID */  #ifdef HAVE_GETGROUPLIST @@ -6276,7 +6165,7 @@ static PyObject *  posix_initgroups(PyObject *self, PyObject *args)  {      PyObject *oname; -    char *username; +    const char *username;      int res;  #ifdef __APPLE__      int gid; @@ -7023,7 +6912,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 +6925,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 +7042,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 +7119,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 +7148,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 +7156,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 +7177,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 +7195,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 +7254,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 +7562,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 +7605,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 +7637,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 +7682,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 +7806,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 +7818,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 +8025,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 +8187,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 +8267,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 +8303,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 +8460,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 +8642,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 +8688,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 +8832,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 +8878,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 +9157,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 +9298,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 +9307,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 +9325,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 +10271,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 +10342,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 +10357,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 +10368,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 +10406,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 +10583,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 +10747,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 +10840,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 +10960,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 +11012,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 +11033,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 +11046,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 +11069,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 +11077,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 +11106,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 +11129,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 +11209,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 +11398,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 +11431,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 +11462,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 +11504,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 +11556,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 +11570,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 +11589,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 +11621,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 +11684,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 +11711,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 +11742,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 +11777,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 +11814,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 +11905,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 +11914,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 +11945,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 +11972,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 +12012,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 +12229,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 +12338,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 +12351,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 +12453,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 +12763,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 +12807,7 @@ static struct PyModuleDef posixmodule = {  }; -static char *have_functions[] = { +static const char * const have_functions[] = {  #ifdef HAVE_FACCESSAT      "HAVE_FACCESSAT", @@ -12993,7 +12942,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 +13118,9 @@ INITFUNC(void)      }      PyModule_AddObject(m, "_have_functions", list); +    Py_INCREF((PyObject *) &DirEntryType); +    PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType); +      initialized = 1;      return m; | 
