LCOV - code coverage report
Current view: top level - Modules - posixmodule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 2597 3329 78.0 %
Date: 2022-07-07 18:19:46 Functions: 259 276 93.8 %

          Line data    Source code
       1             : /* POSIX module implementation */
       2             : 
       3             : /* This file is also used for Windows NT/MS-Win.  In that case the
       4             :    module actually calls itself 'nt', not 'posix', and a few
       5             :    functions are either unimplemented or implemented differently.  The source
       6             :    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
       7             :    of the compiler used.  Different compilers define their own feature
       8             :    test macro, e.g. '_MSC_VER'. */
       9             : 
      10             : #define PY_SSIZE_T_CLEAN
      11             : 
      12             : #include "Python.h"
      13             : // Include <windows.h> before pycore internal headers. FSCTL_GET_REPARSE_POINT
      14             : // is not exported by <windows.h> if the WIN32_LEAN_AND_MEAN macro is defined,
      15             : // whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro.
      16             : #ifdef MS_WINDOWS
      17             : #  include <windows.h>
      18             : #  include <pathcch.h>
      19             : #endif
      20             : 
      21             : #ifdef __VXWORKS__
      22             : #  include "pycore_bitutils.h"    // _Py_popcount32()
      23             : #endif
      24             : #include "pycore_call.h"          // _PyObject_CallNoArgs()
      25             : #include "pycore_ceval.h"         // _PyEval_ReInitThreads()
      26             : #include "pycore_fileutils.h"     // _Py_closerange()
      27             : #include "pycore_import.h"        // _PyImport_ReInitLock()
      28             : #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
      29             : #include "pycore_moduleobject.h"  // _PyModule_GetState()
      30             : #include "pycore_object.h"        // _PyObject_LookupSpecial()
      31             : #include "pycore_pystate.h"       // _PyInterpreterState_GET()
      32             : #include "pycore_signal.h"        // Py_NSIG
      33             : 
      34             : #include "structmember.h"         // PyMemberDef
      35             : #ifndef MS_WINDOWS
      36             : #  include "posixmodule.h"
      37             : #else
      38             : #  include "winreparse.h"
      39             : #endif
      40             : 
      41             : #if !defined(EX_OK) && defined(EXIT_SUCCESS)
      42             : #  define EX_OK EXIT_SUCCESS
      43             : #endif
      44             : 
      45             : /* On android API level 21, 'AT_EACCESS' is not declared although
      46             :  * HAVE_FACCESSAT is defined. */
      47             : #ifdef __ANDROID__
      48             : #  undef HAVE_FACCESSAT
      49             : #endif
      50             : 
      51             : #include <stdio.h>                // ctermid()
      52             : #include <stdlib.h>               // system()
      53             : 
      54             : /*
      55             :  * A number of APIs are available on macOS from a certain macOS version.
      56             :  * To support building with a new SDK while deploying to older versions
      57             :  * the availability test is split into two:
      58             :  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
      59             :  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
      60             :  *
      61             :  * The latter is always true when not on macOS, or when using a compiler
      62             :  * that does not support __has_builtin (older versions of Xcode).
      63             :  *
      64             :  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
      65             :  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
      66             :  *
      67             :  * In mixing the test with other tests or using negations will result in compile
      68             :  * errors.
      69             :  */
      70             : #if defined(__APPLE__)
      71             : 
      72             : #if defined(__has_builtin)
      73             : #if __has_builtin(__builtin_available)
      74             : #define HAVE_BUILTIN_AVAILABLE 1
      75             : #endif
      76             : #endif
      77             : 
      78             : #ifdef HAVE_BUILTIN_AVAILABLE
      79             : #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      80             : #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      81             : #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      82             : #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      83             : #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      84             : #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      85             : #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      86             : #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      87             : #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      88             : #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      89             : #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      90             : #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
      91             : #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
      92             : #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
      93             : #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
      94             : 
      95             : #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
      96             : 
      97             : #else /* Xcode 8 or earlier */
      98             : 
      99             :    /* __builtin_available is not present in these compilers, but
     100             :     * some of the symbols might be weak linked (10.10 SDK or later
     101             :     * deploying on 10.9.
     102             :     *
     103             :     * Fall back to the older style of availability checking for
     104             :     * symbols introduced in macOS 10.10.
     105             :     */
     106             : 
     107             : #  ifdef HAVE_FSTATAT
     108             : #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
     109             : #  endif
     110             : 
     111             : #  ifdef HAVE_FACCESSAT
     112             : #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
     113             : #  endif
     114             : 
     115             : #  ifdef HAVE_FCHMODAT
     116             : #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
     117             : #  endif
     118             : 
     119             : #  ifdef HAVE_FCHOWNAT
     120             : #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
     121             : #  endif
     122             : 
     123             : #  ifdef HAVE_LINKAT
     124             : #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
     125             : #  endif
     126             : 
     127             : #  ifdef HAVE_FDOPENDIR
     128             : #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
     129             : #  endif
     130             : 
     131             : #  ifdef HAVE_MKDIRAT
     132             : #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
     133             : #  endif
     134             : 
     135             : #  ifdef HAVE_RENAMEAT
     136             : #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
     137             : #  endif
     138             : 
     139             : #  ifdef HAVE_UNLINKAT
     140             : #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
     141             : #  endif
     142             : 
     143             : #  ifdef HAVE_OPENAT
     144             : #    define HAVE_OPENAT_RUNTIME (openat != NULL)
     145             : #  endif
     146             : 
     147             : #  ifdef HAVE_READLINKAT
     148             : #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
     149             : #  endif
     150             : 
     151             : #  ifdef HAVE_SYMLINKAT
     152             : #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
     153             : #  endif
     154             : 
     155             : #endif
     156             : 
     157             : #ifdef HAVE_FUTIMESAT
     158             : /* Some of the logic for weak linking depends on this assertion */
     159             : # error "HAVE_FUTIMESAT unexpectedly defined"
     160             : #endif
     161             : 
     162             : #else
     163             : #  define HAVE_FSTATAT_RUNTIME 1
     164             : #  define HAVE_FACCESSAT_RUNTIME 1
     165             : #  define HAVE_FCHMODAT_RUNTIME 1
     166             : #  define HAVE_FCHOWNAT_RUNTIME 1
     167             : #  define HAVE_LINKAT_RUNTIME 1
     168             : #  define HAVE_FDOPENDIR_RUNTIME 1
     169             : #  define HAVE_MKDIRAT_RUNTIME 1
     170             : #  define HAVE_RENAMEAT_RUNTIME 1
     171             : #  define HAVE_UNLINKAT_RUNTIME 1
     172             : #  define HAVE_OPENAT_RUNTIME 1
     173             : #  define HAVE_READLINKAT_RUNTIME 1
     174             : #  define HAVE_SYMLINKAT_RUNTIME 1
     175             : #  define HAVE_FUTIMENS_RUNTIME 1
     176             : #  define HAVE_UTIMENSAT_RUNTIME 1
     177             : #  define HAVE_PWRITEV_RUNTIME 1
     178             : #endif
     179             : 
     180             : 
     181             : #ifdef __cplusplus
     182             : extern "C" {
     183             : #endif
     184             : 
     185             : PyDoc_STRVAR(posix__doc__,
     186             : "This module provides access to operating system functionality that is\n\
     187             : standardized by the C Standard and the POSIX standard (a thinly\n\
     188             : disguised Unix interface).  Refer to the library manual and\n\
     189             : corresponding Unix manual entries for more information on calls.");
     190             : 
     191             : 
     192             : #ifdef HAVE_SYS_UIO_H
     193             : #  include <sys/uio.h>
     194             : #endif
     195             : 
     196             : #ifdef HAVE_SYS_SYSMACROS_H
     197             : /* GNU C Library: major(), minor(), makedev() */
     198             : #  include <sys/sysmacros.h>
     199             : #endif
     200             : 
     201             : #ifdef HAVE_SYS_TYPES_H
     202             : #  include <sys/types.h>
     203             : #endif /* HAVE_SYS_TYPES_H */
     204             : 
     205             : #ifdef HAVE_SYS_STAT_H
     206             : #  include <sys/stat.h>
     207             : #endif /* HAVE_SYS_STAT_H */
     208             : 
     209             : #ifdef HAVE_SYS_WAIT_H
     210             : #  include <sys/wait.h>           // WNOHANG
     211             : #endif
     212             : #ifdef HAVE_LINUX_WAIT_H
     213             : #  include <linux/wait.h>         // P_PIDFD
     214             : #endif
     215             : 
     216             : #ifdef HAVE_SIGNAL_H
     217             : #  include <signal.h>
     218             : #endif
     219             : 
     220             : #ifdef HAVE_FCNTL_H
     221             : #  include <fcntl.h>
     222             : #endif
     223             : 
     224             : #ifdef HAVE_GRP_H
     225             : #  include <grp.h>
     226             : #endif
     227             : 
     228             : #ifdef HAVE_SYSEXITS_H
     229             : #  include <sysexits.h>
     230             : #endif
     231             : 
     232             : #ifdef HAVE_SYS_LOADAVG_H
     233             : #  include <sys/loadavg.h>
     234             : #endif
     235             : 
     236             : #ifdef HAVE_SYS_SENDFILE_H
     237             : #  include <sys/sendfile.h>
     238             : #endif
     239             : 
     240             : #if defined(__APPLE__)
     241             : #  include <copyfile.h>
     242             : #endif
     243             : 
     244             : #ifdef HAVE_SCHED_H
     245             : #  include <sched.h>
     246             : #endif
     247             : 
     248             : #ifdef HAVE_COPY_FILE_RANGE
     249             : #  include <unistd.h>
     250             : #endif
     251             : 
     252             : #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
     253             : #  undef HAVE_SCHED_SETAFFINITY
     254             : #endif
     255             : 
     256             : #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
     257             : #  define USE_XATTRS
     258             : #endif
     259             : 
     260             : #ifdef USE_XATTRS
     261             : #  include <sys/xattr.h>
     262             : #endif
     263             : 
     264             : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
     265             : #  ifdef HAVE_SYS_SOCKET_H
     266             : #    include <sys/socket.h>
     267             : #  endif
     268             : #endif
     269             : 
     270             : #ifdef HAVE_DLFCN_H
     271             : #  include <dlfcn.h>
     272             : #endif
     273             : 
     274             : #ifdef __hpux
     275             : #  include <sys/mpctl.h>
     276             : #endif
     277             : 
     278             : #if defined(__DragonFly__) || \
     279             :     defined(__OpenBSD__)   || \
     280             :     defined(__FreeBSD__)   || \
     281             :     defined(__NetBSD__)    || \
     282             :     defined(__APPLE__)
     283             : #  include <sys/sysctl.h>
     284             : #endif
     285             : 
     286             : #ifdef HAVE_LINUX_RANDOM_H
     287             : #  include <linux/random.h>
     288             : #endif
     289             : #ifdef HAVE_GETRANDOM_SYSCALL
     290             : #  include <sys/syscall.h>
     291             : #endif
     292             : 
     293             : #if defined(MS_WINDOWS)
     294             : #  define TERMSIZE_USE_CONIO
     295             : #elif defined(HAVE_SYS_IOCTL_H)
     296             : #  include <sys/ioctl.h>
     297             : #  if defined(HAVE_TERMIOS_H)
     298             : #    include <termios.h>
     299             : #  endif
     300             : #  if defined(TIOCGWINSZ)
     301             : #    define TERMSIZE_USE_IOCTL
     302             : #  endif
     303             : #endif /* MS_WINDOWS */
     304             : 
     305             : /* Various compilers have only certain posix functions */
     306             : /* XXX Gosh I wish these were all moved into pyconfig.h */
     307             : #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
     308             : #  define HAVE_OPENDIR    1
     309             : #  define HAVE_SYSTEM     1
     310             : #  include <process.h>
     311             : #else
     312             : #  ifdef _MSC_VER
     313             :      /* Microsoft compiler */
     314             : #    define HAVE_GETPPID    1
     315             : #    define HAVE_GETLOGIN   1
     316             : #    define HAVE_SPAWNV     1
     317             : #    define HAVE_EXECV      1
     318             : #    define HAVE_WSPAWNV    1
     319             : #    define HAVE_WEXECV     1
     320             : #    define HAVE_PIPE       1
     321             : #    define HAVE_SYSTEM     1
     322             : #    define HAVE_CWAIT      1
     323             : #    define HAVE_FSYNC      1
     324             : #    define fsync _commit
     325             : #  endif  /* _MSC_VER */
     326             : #endif  /* ! __WATCOMC__ || __QNX__ */
     327             : 
     328             : /*[clinic input]
     329             : # one of the few times we lie about this name!
     330             : module os
     331             : [clinic start generated code]*/
     332             : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
     333             : 
     334             : #ifndef _MSC_VER
     335             : 
     336             : #if defined(__sgi)&&_COMPILER_VERSION>=700
     337             : /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
     338             :    (default) */
     339             : extern char        *ctermid_r(char *);
     340             : #endif
     341             : 
     342             : #endif /* !_MSC_VER */
     343             : 
     344             : #if defined(__VXWORKS__)
     345             : #  include <vxCpuLib.h>
     346             : #  include <rtpLib.h>
     347             : #  include <wait.h>
     348             : #  include <taskLib.h>
     349             : #  ifndef _P_WAIT
     350             : #    define _P_WAIT          0
     351             : #    define _P_NOWAIT        1
     352             : #    define _P_NOWAITO       1
     353             : #  endif
     354             : #endif /* __VXWORKS__ */
     355             : 
     356             : #ifdef HAVE_POSIX_SPAWN
     357             : #  include <spawn.h>
     358             : #endif
     359             : 
     360             : #ifdef HAVE_UTIME_H
     361             : #  include <utime.h>
     362             : #endif /* HAVE_UTIME_H */
     363             : 
     364             : #ifdef HAVE_SYS_UTIME_H
     365             : #  include <sys/utime.h>
     366             : #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
     367             : #endif /* HAVE_SYS_UTIME_H */
     368             : 
     369             : #ifdef HAVE_SYS_TIMES_H
     370             : #  include <sys/times.h>
     371             : #endif /* HAVE_SYS_TIMES_H */
     372             : 
     373             : #ifdef HAVE_SYS_PARAM_H
     374             : #  include <sys/param.h>
     375             : #endif /* HAVE_SYS_PARAM_H */
     376             : 
     377             : #ifdef HAVE_SYS_UTSNAME_H
     378             : #  include <sys/utsname.h>
     379             : #endif /* HAVE_SYS_UTSNAME_H */
     380             : 
     381             : #ifdef HAVE_DIRENT_H
     382             : #  include <dirent.h>
     383             : #  define NAMLEN(dirent) strlen((dirent)->d_name)
     384             : #else
     385             : #  if defined(__WATCOMC__) && !defined(__QNX__)
     386             : #    include <direct.h>
     387             : #    define NAMLEN(dirent) strlen((dirent)->d_name)
     388             : #  else
     389             : #    define dirent direct
     390             : #    define NAMLEN(dirent) (dirent)->d_namlen
     391             : #  endif
     392             : #  ifdef HAVE_SYS_NDIR_H
     393             : #    include <sys/ndir.h>
     394             : #  endif
     395             : #  ifdef HAVE_SYS_DIR_H
     396             : #    include <sys/dir.h>
     397             : #  endif
     398             : #  ifdef HAVE_NDIR_H
     399             : #    include <ndir.h>
     400             : #  endif
     401             : #endif
     402             : 
     403             : #ifdef _MSC_VER
     404             : #  ifdef HAVE_DIRECT_H
     405             : #    include <direct.h>
     406             : #  endif
     407             : #  ifdef HAVE_IO_H
     408             : #    include <io.h>
     409             : #  endif
     410             : #  ifdef HAVE_PROCESS_H
     411             : #    include <process.h>
     412             : #  endif
     413             : #  ifndef IO_REPARSE_TAG_SYMLINK
     414             : #    define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
     415             : #  endif
     416             : #  ifndef IO_REPARSE_TAG_MOUNT_POINT
     417             : #    define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
     418             : #  endif
     419             : #  include "osdefs.h"             // SEP
     420             : #  include <malloc.h>
     421             : #  include <windows.h>
     422             : #  include <shellapi.h>           // ShellExecute()
     423             : #  include <lmcons.h>             // UNLEN
     424             : #  define HAVE_SYMLINK
     425             : #endif /* _MSC_VER */
     426             : 
     427             : #ifndef MAXPATHLEN
     428             : #  if defined(PATH_MAX) && PATH_MAX > 1024
     429             : #    define MAXPATHLEN PATH_MAX
     430             : #  else
     431             : #    define MAXPATHLEN 1024
     432             : #  endif
     433             : #endif /* MAXPATHLEN */
     434             : 
     435             : #ifdef UNION_WAIT
     436             :    /* Emulate some macros on systems that have a union instead of macros */
     437             : #  ifndef WIFEXITED
     438             : #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
     439             : #  endif
     440             : #  ifndef WEXITSTATUS
     441             : #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
     442             : #  endif
     443             : #  ifndef WTERMSIG
     444             : #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
     445             : #  endif
     446             : #  define WAIT_TYPE union wait
     447             : #  define WAIT_STATUS_INT(s) (s.w_status)
     448             : #else
     449             :    /* !UNION_WAIT */
     450             : #  define WAIT_TYPE int
     451             : #  define WAIT_STATUS_INT(s) (s)
     452             : #endif /* UNION_WAIT */
     453             : 
     454             : /* Don't use the "_r" form if we don't need it (also, won't have a
     455             :    prototype for it, at least on Solaris -- maybe others as well?). */
     456             : #if defined(HAVE_CTERMID_R)
     457             : #  define USE_CTERMID_R
     458             : #endif
     459             : 
     460             : /* choose the appropriate stat and fstat functions and return structs */
     461             : #undef STAT
     462             : #undef FSTAT
     463             : #undef STRUCT_STAT
     464             : #ifdef MS_WINDOWS
     465             : #  define STAT win32_stat
     466             : #  define LSTAT win32_lstat
     467             : #  define FSTAT _Py_fstat_noraise
     468             : #  define STRUCT_STAT struct _Py_stat_struct
     469             : #else
     470             : #  define STAT stat
     471             : #  define LSTAT lstat
     472             : #  define FSTAT fstat
     473             : #  define STRUCT_STAT struct stat
     474             : #endif
     475             : 
     476             : #if defined(MAJOR_IN_MKDEV)
     477             : #  include <sys/mkdev.h>
     478             : #else
     479             : #  if defined(MAJOR_IN_SYSMACROS)
     480             : #    include <sys/sysmacros.h>
     481             : #  endif
     482             : #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
     483             : #    include <sys/mkdev.h>
     484             : #  endif
     485             : #endif
     486             : 
     487             : #ifdef MS_WINDOWS
     488             : #  define INITFUNC PyInit_nt
     489             : #  define MODNAME "nt"
     490             : #else
     491             : #  define INITFUNC PyInit_posix
     492             : #  define MODNAME "posix"
     493             : #endif
     494             : 
     495             : #if defined(__sun)
     496             : /* Something to implement in autoconf, not present in autoconf 2.69 */
     497             : #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
     498             : #endif
     499             : 
     500             : /* memfd_create is either defined in sys/mman.h or sys/memfd.h
     501             :  * linux/memfd.h defines additional flags
     502             :  */
     503             : #ifdef HAVE_SYS_MMAN_H
     504             : #  include <sys/mman.h>
     505             : #endif
     506             : #ifdef HAVE_SYS_MEMFD_H
     507             : #  include <sys/memfd.h>
     508             : #endif
     509             : #ifdef HAVE_LINUX_MEMFD_H
     510             : #  include <linux/memfd.h>
     511             : #endif
     512             : 
     513             : /* eventfd() */
     514             : #ifdef HAVE_SYS_EVENTFD_H
     515             : #  include <sys/eventfd.h>
     516             : #endif
     517             : 
     518             : #ifdef _Py_MEMORY_SANITIZER
     519             : #  include <sanitizer/msan_interface.h>
     520             : #endif
     521             : 
     522             : #ifdef HAVE_FORK
     523             : static void
     524        3364 : run_at_forkers(PyObject *lst, int reverse)
     525             : {
     526             :     Py_ssize_t i;
     527             :     PyObject *cpy;
     528             : 
     529        3364 :     if (lst != NULL) {
     530        2614 :         assert(PyList_CheckExact(lst));
     531             : 
     532             :         /* Use a list copy in case register_at_fork() is called from
     533             :          * one of the callbacks.
     534             :          */
     535        2614 :         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
     536        2614 :         if (cpy == NULL)
     537           0 :             PyErr_WriteUnraisable(lst);
     538             :         else {
     539        2614 :             if (reverse)
     540        1304 :                 PyList_Reverse(cpy);
     541        6078 :             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
     542             :                 PyObject *func, *res;
     543        3464 :                 func = PyList_GET_ITEM(cpy, i);
     544        3464 :                 res = _PyObject_CallNoArgs(func);
     545        3464 :                 if (res == NULL)
     546           0 :                     PyErr_WriteUnraisable(func);
     547             :                 else
     548        3464 :                     Py_DECREF(res);
     549             :             }
     550        2614 :             Py_DECREF(cpy);
     551             :         }
     552             :     }
     553        3364 : }
     554             : 
     555             : void
     556        1682 : PyOS_BeforeFork(void)
     557             : {
     558        1682 :     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
     559             : 
     560        1682 :     _PyImport_AcquireLock();
     561        1682 : }
     562             : 
     563             : void
     564        1674 : PyOS_AfterFork_Parent(void)
     565             : {
     566        1674 :     if (_PyImport_ReleaseLock() <= 0)
     567           0 :         Py_FatalError("failed releasing import lock after fork");
     568             : 
     569        1674 :     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
     570        1674 : }
     571             : 
     572             : void
     573           8 : PyOS_AfterFork_Child(void)
     574             : {
     575             :     PyStatus status;
     576           8 :     _PyRuntimeState *runtime = &_PyRuntime;
     577             : 
     578           8 :     status = _PyGILState_Reinit(runtime);
     579           8 :     if (_PyStatus_EXCEPTION(status)) {
     580           0 :         goto fatal_error;
     581             :     }
     582             : 
     583           8 :     PyThreadState *tstate = _PyThreadState_GET();
     584           8 :     _Py_EnsureTstateNotNULL(tstate);
     585             : 
     586           8 :     status = _PyEval_ReInitThreads(tstate);
     587           8 :     if (_PyStatus_EXCEPTION(status)) {
     588           0 :         goto fatal_error;
     589             :     }
     590             : 
     591           8 :     status = _PyImport_ReInitLock();
     592           8 :     if (_PyStatus_EXCEPTION(status)) {
     593           0 :         goto fatal_error;
     594             :     }
     595             : 
     596           8 :     _PySignal_AfterFork();
     597             : 
     598           8 :     status = _PyRuntimeState_ReInitThreads(runtime);
     599           8 :     if (_PyStatus_EXCEPTION(status)) {
     600           0 :         goto fatal_error;
     601             :     }
     602             : 
     603           8 :     status = _PyInterpreterState_DeleteExceptMain(runtime);
     604           8 :     if (_PyStatus_EXCEPTION(status)) {
     605           0 :         goto fatal_error;
     606             :     }
     607           8 :     assert(_PyThreadState_GET() == tstate);
     608             : 
     609           8 :     run_at_forkers(tstate->interp->after_forkers_child, 0);
     610           8 :     return;
     611             : 
     612           0 : fatal_error:
     613           0 :     Py_ExitStatusException(status);
     614             : }
     615             : 
     616             : static int
     617        9300 : register_at_forker(PyObject **lst, PyObject *func)
     618             : {
     619        9300 :     if (func == NULL)  /* nothing to register? do nothing. */
     620        4826 :         return 0;
     621        4474 :     if (*lst == NULL) {
     622        2482 :         *lst = PyList_New(0);
     623        2482 :         if (*lst == NULL)
     624           0 :             return -1;
     625             :     }
     626        4474 :     return PyList_Append(*lst, func);
     627             : }
     628             : #endif  /* HAVE_FORK */
     629             : 
     630             : 
     631             : /* Legacy wrapper */
     632             : void
     633           0 : PyOS_AfterFork(void)
     634             : {
     635             : #ifdef HAVE_FORK
     636           0 :     PyOS_AfterFork_Child();
     637             : #endif
     638           0 : }
     639             : 
     640             : 
     641             : #ifdef MS_WINDOWS
     642             : /* defined in fileutils.c */
     643             : void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
     644             : void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
     645             :                                             ULONG, struct _Py_stat_struct *);
     646             : #endif
     647             : 
     648             : 
     649             : #ifndef MS_WINDOWS
     650             : PyObject *
     651     1308050 : _PyLong_FromUid(uid_t uid)
     652             : {
     653     1308050 :     if (uid == (uid_t)-1)
     654           1 :         return PyLong_FromLong(-1);
     655     1308050 :     return PyLong_FromUnsignedLong(uid);
     656             : }
     657             : 
     658             : PyObject *
     659     1308790 : _PyLong_FromGid(gid_t gid)
     660             : {
     661     1308790 :     if (gid == (gid_t)-1)
     662           0 :         return PyLong_FromLong(-1);
     663     1308790 :     return PyLong_FromUnsignedLong(gid);
     664             : }
     665             : 
     666             : int
     667         734 : _Py_Uid_Converter(PyObject *obj, uid_t *p)
     668             : {
     669             :     uid_t uid;
     670             :     PyObject *index;
     671             :     int overflow;
     672             :     long result;
     673             :     unsigned long uresult;
     674             : 
     675         734 :     index = _PyNumber_Index(obj);
     676         734 :     if (index == NULL) {
     677          16 :         PyErr_Format(PyExc_TypeError,
     678             :                      "uid should be integer, not %.200s",
     679             :                      _PyType_Name(Py_TYPE(obj)));
     680          16 :         return 0;
     681             :     }
     682             : 
     683             :     /*
     684             :      * Handling uid_t is complicated for two reasons:
     685             :      *  * Although uid_t is (always?) unsigned, it still
     686             :      *    accepts -1.
     687             :      *  * We don't know its size in advance--it may be
     688             :      *    bigger than an int, or it may be smaller than
     689             :      *    a long.
     690             :      *
     691             :      * So a bit of defensive programming is in order.
     692             :      * Start with interpreting the value passed
     693             :      * in as a signed long and see if it works.
     694             :      */
     695             : 
     696         718 :     result = PyLong_AsLongAndOverflow(index, &overflow);
     697             : 
     698         718 :     if (!overflow) {
     699         715 :         uid = (uid_t)result;
     700             : 
     701         715 :         if (result == -1) {
     702          19 :             if (PyErr_Occurred())
     703           0 :                 goto fail;
     704             :             /* It's a legitimate -1, we're done. */
     705          19 :             goto success;
     706             :         }
     707             : 
     708             :         /* Any other negative number is disallowed. */
     709         696 :         if (result < 0)
     710           0 :             goto underflow;
     711             : 
     712             :         /* Ensure the value wasn't truncated. */
     713         696 :         if (sizeof(uid_t) < sizeof(long) &&
     714         696 :             (long)uid != result)
     715           5 :             goto underflow;
     716         691 :         goto success;
     717             :     }
     718             : 
     719           3 :     if (overflow < 0)
     720           1 :         goto underflow;
     721             : 
     722             :     /*
     723             :      * Okay, the value overflowed a signed long.  If it
     724             :      * fits in an *unsigned* long, it may still be okay,
     725             :      * as uid_t may be unsigned long on this platform.
     726             :      */
     727           2 :     uresult = PyLong_AsUnsignedLong(index);
     728           2 :     if (PyErr_Occurred()) {
     729           2 :         if (PyErr_ExceptionMatches(PyExc_OverflowError))
     730           2 :             goto overflow;
     731           0 :         goto fail;
     732             :     }
     733             : 
     734           0 :     uid = (uid_t)uresult;
     735             : 
     736             :     /*
     737             :      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
     738             :      * but this value would get interpreted as (uid_t)-1  by chown
     739             :      * and its siblings.   That's not what the user meant!  So we
     740             :      * throw an overflow exception instead.   (We already
     741             :      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
     742             :      */
     743           0 :     if (uid == (uid_t)-1)
     744           0 :         goto overflow;
     745             : 
     746             :     /* Ensure the value wasn't truncated. */
     747           0 :     if (sizeof(uid_t) < sizeof(long) &&
     748           0 :         (unsigned long)uid != uresult)
     749           0 :         goto overflow;
     750             :     /* fallthrough */
     751             : 
     752           0 : success:
     753         710 :     Py_DECREF(index);
     754         710 :     *p = uid;
     755         710 :     return 1;
     756             : 
     757           6 : underflow:
     758           6 :     PyErr_SetString(PyExc_OverflowError,
     759             :                     "uid is less than minimum");
     760           6 :     goto fail;
     761             : 
     762           2 : overflow:
     763           2 :     PyErr_SetString(PyExc_OverflowError,
     764             :                     "uid is greater than maximum");
     765             :     /* fallthrough */
     766             : 
     767           8 : fail:
     768           8 :     Py_DECREF(index);
     769           8 :     return 0;
     770             : }
     771             : 
     772             : int
     773         737 : _Py_Gid_Converter(PyObject *obj, gid_t *p)
     774             : {
     775             :     gid_t gid;
     776             :     PyObject *index;
     777             :     int overflow;
     778             :     long result;
     779             :     unsigned long uresult;
     780             : 
     781         737 :     index = _PyNumber_Index(obj);
     782         737 :     if (index == NULL) {
     783          17 :         PyErr_Format(PyExc_TypeError,
     784             :                      "gid should be integer, not %.200s",
     785             :                      _PyType_Name(Py_TYPE(obj)));
     786          17 :         return 0;
     787             :     }
     788             : 
     789             :     /*
     790             :      * Handling gid_t is complicated for two reasons:
     791             :      *  * Although gid_t is (always?) unsigned, it still
     792             :      *    accepts -1.
     793             :      *  * We don't know its size in advance--it may be
     794             :      *    bigger than an int, or it may be smaller than
     795             :      *    a long.
     796             :      *
     797             :      * So a bit of defensive programming is in order.
     798             :      * Start with interpreting the value passed
     799             :      * in as a signed long and see if it works.
     800             :      */
     801             : 
     802         720 :     result = PyLong_AsLongAndOverflow(index, &overflow);
     803             : 
     804         720 :     if (!overflow) {
     805         718 :         gid = (gid_t)result;
     806             : 
     807         718 :         if (result == -1) {
     808          20 :             if (PyErr_Occurred())
     809           0 :                 goto fail;
     810             :             /* It's a legitimate -1, we're done. */
     811          20 :             goto success;
     812             :         }
     813             : 
     814             :         /* Any other negative number is disallowed. */
     815         698 :         if (result < 0) {
     816           0 :             goto underflow;
     817             :         }
     818             : 
     819             :         /* Ensure the value wasn't truncated. */
     820         698 :         if (sizeof(gid_t) < sizeof(long) &&
     821         698 :             (long)gid != result)
     822           4 :             goto underflow;
     823         694 :         goto success;
     824             :     }
     825             : 
     826           2 :     if (overflow < 0)
     827           0 :         goto underflow;
     828             : 
     829             :     /*
     830             :      * Okay, the value overflowed a signed long.  If it
     831             :      * fits in an *unsigned* long, it may still be okay,
     832             :      * as gid_t may be unsigned long on this platform.
     833             :      */
     834           2 :     uresult = PyLong_AsUnsignedLong(index);
     835           2 :     if (PyErr_Occurred()) {
     836           2 :         if (PyErr_ExceptionMatches(PyExc_OverflowError))
     837           2 :             goto overflow;
     838           0 :         goto fail;
     839             :     }
     840             : 
     841           0 :     gid = (gid_t)uresult;
     842             : 
     843             :     /*
     844             :      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
     845             :      * but this value would get interpreted as (gid_t)-1  by chown
     846             :      * and its siblings.   That's not what the user meant!  So we
     847             :      * throw an overflow exception instead.   (We already
     848             :      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
     849             :      */
     850           0 :     if (gid == (gid_t)-1)
     851           0 :         goto overflow;
     852             : 
     853             :     /* Ensure the value wasn't truncated. */
     854           0 :     if (sizeof(gid_t) < sizeof(long) &&
     855           0 :         (unsigned long)gid != uresult)
     856           0 :         goto overflow;
     857             :     /* fallthrough */
     858             : 
     859           0 : success:
     860         714 :     Py_DECREF(index);
     861         714 :     *p = gid;
     862         714 :     return 1;
     863             : 
     864           4 : underflow:
     865           4 :     PyErr_SetString(PyExc_OverflowError,
     866             :                     "gid is less than minimum");
     867           4 :     goto fail;
     868             : 
     869           2 : overflow:
     870           2 :     PyErr_SetString(PyExc_OverflowError,
     871             :                     "gid is greater than maximum");
     872             :     /* fallthrough */
     873             : 
     874           6 : fail:
     875           6 :     Py_DECREF(index);
     876           6 :     return 0;
     877             : }
     878             : #endif /* MS_WINDOWS */
     879             : 
     880             : 
     881             : #define _PyLong_FromDev PyLong_FromLongLong
     882             : 
     883             : 
     884             : #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
     885             : static int
     886          11 : _Py_Dev_Converter(PyObject *obj, void *p)
     887             : {
     888          11 :     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
     889          11 :     if (PyErr_Occurred())
     890           4 :         return 0;
     891           7 :     return 1;
     892             : }
     893             : #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
     894             : 
     895             : 
     896             : #ifdef AT_FDCWD
     897             : /*
     898             :  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
     899             :  * without the int cast, the value gets interpreted as uint (4291925331),
     900             :  * which doesn't play nicely with all the initializer lines in this file that
     901             :  * look like this:
     902             :  *      int dir_fd = DEFAULT_DIR_FD;
     903             :  */
     904             : #define DEFAULT_DIR_FD (int)AT_FDCWD
     905             : #else
     906             : #define DEFAULT_DIR_FD (-100)
     907             : #endif
     908             : 
     909             : static int
     910       70713 : _fd_converter(PyObject *o, int *p)
     911             : {
     912             :     int overflow;
     913             :     long long_value;
     914             : 
     915       70713 :     PyObject *index = _PyNumber_Index(o);
     916       70713 :     if (index == NULL) {
     917           0 :         return 0;
     918             :     }
     919             : 
     920       70713 :     assert(PyLong_Check(index));
     921       70713 :     long_value = PyLong_AsLongAndOverflow(index, &overflow);
     922       70713 :     Py_DECREF(index);
     923       70713 :     assert(!PyErr_Occurred());
     924       70713 :     if (overflow > 0 || long_value > INT_MAX) {
     925           1 :         PyErr_SetString(PyExc_OverflowError,
     926             :                         "fd is greater than maximum");
     927           1 :         return 0;
     928             :     }
     929       70712 :     if (overflow < 0 || long_value < INT_MIN) {
     930           0 :         PyErr_SetString(PyExc_OverflowError,
     931             :                         "fd is less than minimum");
     932           0 :         return 0;
     933             :     }
     934             : 
     935       70712 :     *p = (int)long_value;
     936       70712 :     return 1;
     937             : }
     938             : 
     939             : static int
     940       72148 : dir_fd_converter(PyObject *o, void *p)
     941             : {
     942       72148 :     if (o == Py_None) {
     943       18799 :         *(int *)p = DEFAULT_DIR_FD;
     944       18799 :         return 1;
     945             :     }
     946       53349 :     else if (PyIndex_Check(o)) {
     947       53347 :         return _fd_converter(o, (int *)p);
     948             :     }
     949             :     else {
     950           2 :         PyErr_Format(PyExc_TypeError,
     951             :                      "argument should be integer or None, not %.200s",
     952             :                      _PyType_Name(Py_TYPE(o)));
     953           2 :         return 0;
     954             :     }
     955             : }
     956             : 
     957             : typedef struct {
     958             :     PyObject *billion;
     959             :     PyObject *DirEntryType;
     960             :     PyObject *ScandirIteratorType;
     961             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
     962             :     PyObject *SchedParamType;
     963             : #endif
     964             :     PyObject *StatResultType;
     965             :     PyObject *StatVFSResultType;
     966             :     PyObject *TerminalSizeType;
     967             :     PyObject *TimesResultType;
     968             :     PyObject *UnameResultType;
     969             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
     970             :     PyObject *WaitidResultType;
     971             : #endif
     972             : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
     973             :     PyObject *struct_rusage;
     974             : #endif
     975             :     PyObject *st_mode;
     976             : } _posixstate;
     977             : 
     978             : 
     979             : static inline _posixstate*
     980     5456960 : get_posix_state(PyObject *module)
     981             : {
     982     5456960 :     void *state = _PyModule_GetState(module);
     983     5456960 :     assert(state != NULL);
     984     5456960 :     return (_posixstate *)state;
     985             : }
     986             : 
     987             : /*
     988             :  * A PyArg_ParseTuple "converter" function
     989             :  * that handles filesystem paths in the manner
     990             :  * preferred by the os module.
     991             :  *
     992             :  * path_converter accepts (Unicode) strings and their
     993             :  * subclasses, and bytes and their subclasses.  What
     994             :  * it does with the argument depends on the platform:
     995             :  *
     996             :  *   * On Windows, if we get a (Unicode) string we
     997             :  *     extract the wchar_t * and return it; if we get
     998             :  *     bytes we decode to wchar_t * and return that.
     999             :  *
    1000             :  *   * On all other platforms, strings are encoded
    1001             :  *     to bytes using PyUnicode_FSConverter, then we
    1002             :  *     extract the char * from the bytes object and
    1003             :  *     return that.
    1004             :  *
    1005             :  * path_converter also optionally accepts signed
    1006             :  * integers (representing open file descriptors) instead
    1007             :  * of path strings.
    1008             :  *
    1009             :  * Input fields:
    1010             :  *   path.nullable
    1011             :  *     If nonzero, the path is permitted to be None.
    1012             :  *   path.allow_fd
    1013             :  *     If nonzero, the path is permitted to be a file handle
    1014             :  *     (a signed int) instead of a string.
    1015             :  *   path.function_name
    1016             :  *     If non-NULL, path_converter will use that as the name
    1017             :  *     of the function in error messages.
    1018             :  *     (If path.function_name is NULL it omits the function name.)
    1019             :  *   path.argument_name
    1020             :  *     If non-NULL, path_converter will use that as the name
    1021             :  *     of the parameter in error messages.
    1022             :  *     (If path.argument_name is NULL it uses "path".)
    1023             :  *
    1024             :  * Output fields:
    1025             :  *   path.wide
    1026             :  *     Points to the path if it was expressed as Unicode
    1027             :  *     and was not encoded.  (Only used on Windows.)
    1028             :  *   path.narrow
    1029             :  *     Points to the path if it was expressed as bytes,
    1030             :  *     or it was Unicode and was encoded to bytes. (On Windows,
    1031             :  *     is a non-zero integer if the path was expressed as bytes.
    1032             :  *     The type is deliberately incompatible to prevent misuse.)
    1033             :  *   path.fd
    1034             :  *     Contains a file descriptor if path.accept_fd was true
    1035             :  *     and the caller provided a signed integer instead of any
    1036             :  *     sort of string.
    1037             :  *
    1038             :  *     WARNING: if your "path" parameter is optional, and is
    1039             :  *     unspecified, path_converter will never get called.
    1040             :  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
    1041             :  *     yourself!
    1042             :  *   path.length
    1043             :  *     The length of the path in characters, if specified as
    1044             :  *     a string.
    1045             :  *   path.object
    1046             :  *     The original object passed in (if get a PathLike object,
    1047             :  *     the result of PyOS_FSPath() is treated as the original object).
    1048             :  *     Own a reference to the object.
    1049             :  *   path.cleanup
    1050             :  *     For internal use only.  May point to a temporary object.
    1051             :  *     (Pay no attention to the man behind the curtain.)
    1052             :  *
    1053             :  *   At most one of path.wide or path.narrow will be non-NULL.
    1054             :  *   If path was None and path.nullable was set,
    1055             :  *     or if path was an integer and path.allow_fd was set,
    1056             :  *     both path.wide and path.narrow will be NULL
    1057             :  *     and path.length will be 0.
    1058             :  *
    1059             :  *   path_converter takes care to not write to the path_t
    1060             :  *   unless it's successful.  However it must reset the
    1061             :  *   "cleanup" field each time it's called.
    1062             :  *
    1063             :  * Use as follows:
    1064             :  *      path_t path;
    1065             :  *      memset(&path, 0, sizeof(path));
    1066             :  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
    1067             :  *      // ... use values from path ...
    1068             :  *      path_cleanup(&path);
    1069             :  *
    1070             :  * (Note that if PyArg_Parse fails you don't need to call
    1071             :  * path_cleanup().  However it is safe to do so.)
    1072             :  */
    1073             : typedef struct {
    1074             :     const char *function_name;
    1075             :     const char *argument_name;
    1076             :     int nullable;
    1077             :     int allow_fd;
    1078             :     const wchar_t *wide;
    1079             : #ifdef MS_WINDOWS
    1080             :     BOOL narrow;
    1081             : #else
    1082             :     const char *narrow;
    1083             : #endif
    1084             :     int fd;
    1085             :     Py_ssize_t length;
    1086             :     PyObject *object;
    1087             :     PyObject *cleanup;
    1088             : } path_t;
    1089             : 
    1090             : #ifdef MS_WINDOWS
    1091             : #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
    1092             :     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
    1093             : #else
    1094             : #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
    1095             :     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
    1096             : #endif
    1097             : 
    1098             : static void
    1099     1797190 : path_cleanup(path_t *path)
    1100             : {
    1101     1797190 :     wchar_t *wide = (wchar_t *)path->wide;
    1102     1797190 :     path->wide = NULL;
    1103     1797190 :     PyMem_Free(wide);
    1104     1797190 :     Py_CLEAR(path->object);
    1105     1797190 :     Py_CLEAR(path->cleanup);
    1106     1797190 : }
    1107             : 
    1108             : static int
    1109     1746760 : path_converter(PyObject *o, void *p)
    1110             : {
    1111     1746760 :     path_t *path = (path_t *)p;
    1112     1746760 :     PyObject *bytes = NULL;
    1113     1746760 :     Py_ssize_t length = 0;
    1114             :     int is_index, is_buffer, is_bytes, is_unicode;
    1115             :     const char *narrow;
    1116             : #ifdef MS_WINDOWS
    1117             :     PyObject *wo = NULL;
    1118             :     wchar_t *wide = NULL;
    1119             : #endif
    1120             : 
    1121             : #define FORMAT_EXCEPTION(exc, fmt) \
    1122             :     PyErr_Format(exc, "%s%s" fmt, \
    1123             :         path->function_name ? path->function_name : "", \
    1124             :         path->function_name ? ": "                : "", \
    1125             :         path->argument_name ? path->argument_name : "path")
    1126             : 
    1127             :     /* Py_CLEANUP_SUPPORTED support */
    1128     1746760 :     if (o == NULL) {
    1129           0 :         path_cleanup(path);
    1130           0 :         return 1;
    1131             :     }
    1132             : 
    1133             :     /* Ensure it's always safe to call path_cleanup(). */
    1134     1746760 :     path->object = path->cleanup = NULL;
    1135             :     /* path->object owns a reference to the original object */
    1136     1746760 :     Py_INCREF(o);
    1137             : 
    1138     1746760 :     if ((o == Py_None) && path->nullable) {
    1139           0 :         path->wide = NULL;
    1140             : #ifdef MS_WINDOWS
    1141             :         path->narrow = FALSE;
    1142             : #else
    1143           0 :         path->narrow = NULL;
    1144             : #endif
    1145           0 :         path->fd = -1;
    1146           0 :         goto success_exit;
    1147             :     }
    1148             : 
    1149             :     /* Only call this here so that we don't treat the return value of
    1150             :        os.fspath() as an fd or buffer. */
    1151     1746760 :     is_index = path->allow_fd && PyIndex_Check(o);
    1152     1746760 :     is_buffer = PyObject_CheckBuffer(o);
    1153     1746760 :     is_bytes = PyBytes_Check(o);
    1154     1746760 :     is_unicode = PyUnicode_Check(o);
    1155             : 
    1156     1746760 :     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
    1157             :         /* Inline PyOS_FSPath() for better error messages. */
    1158             :         PyObject *func, *res;
    1159             : 
    1160       32991 :         func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
    1161       32991 :         if (NULL == func) {
    1162          12 :             goto error_format;
    1163             :         }
    1164       32979 :         res = _PyObject_CallNoArgs(func);
    1165       32979 :         Py_DECREF(func);
    1166       32979 :         if (NULL == res) {
    1167           0 :             goto error_exit;
    1168             :         }
    1169       32979 :         else if (PyUnicode_Check(res)) {
    1170       32967 :             is_unicode = 1;
    1171             :         }
    1172          12 :         else if (PyBytes_Check(res)) {
    1173           5 :             is_bytes = 1;
    1174             :         }
    1175             :         else {
    1176           7 :             PyErr_Format(PyExc_TypeError,
    1177             :                  "expected %.200s.__fspath__() to return str or bytes, "
    1178             :                  "not %.200s", _PyType_Name(Py_TYPE(o)),
    1179             :                  _PyType_Name(Py_TYPE(res)));
    1180           7 :             Py_DECREF(res);
    1181           7 :             goto error_exit;
    1182             :         }
    1183             : 
    1184             :         /* still owns a reference to the original object */
    1185       32972 :         Py_DECREF(o);
    1186       32972 :         o = res;
    1187             :     }
    1188             : 
    1189     1746740 :     if (is_unicode) {
    1190             : #ifdef MS_WINDOWS
    1191             :         wide = PyUnicode_AsWideCharString(o, &length);
    1192             :         if (!wide) {
    1193             :             goto error_exit;
    1194             :         }
    1195             :         if (length > 32767) {
    1196             :             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
    1197             :             goto error_exit;
    1198             :         }
    1199             :         if (wcslen(wide) != length) {
    1200             :             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
    1201             :             goto error_exit;
    1202             :         }
    1203             : 
    1204             :         path->wide = wide;
    1205             :         path->narrow = FALSE;
    1206             :         path->fd = -1;
    1207             :         wide = NULL;
    1208             :         goto success_exit;
    1209             : #else
    1210     1711100 :         if (!PyUnicode_FSConverter(o, &bytes)) {
    1211         102 :             goto error_exit;
    1212             :         }
    1213             : #endif
    1214             :     }
    1215       35648 :     else if (is_bytes) {
    1216       18237 :         bytes = o;
    1217       18237 :         Py_INCREF(bytes);
    1218             :     }
    1219       17411 :     else if (is_buffer) {
    1220             :         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
    1221             :            after removing support of non-bytes buffer objects. */
    1222         225 :         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
    1223             :             "%s%s%s should be %s, not %.200s",
    1224          45 :             path->function_name ? path->function_name : "",
    1225          45 :             path->function_name ? ": "                : "",
    1226          45 :             path->argument_name ? path->argument_name : "path",
    1227          45 :             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
    1228             :                                                "integer or None" :
    1229          57 :             path->allow_fd ? "string, bytes, os.PathLike or integer" :
    1230          20 :             path->nullable ? "string, bytes, os.PathLike or None" :
    1231             :                              "string, bytes or os.PathLike",
    1232             :             _PyType_Name(Py_TYPE(o)))) {
    1233           0 :             goto error_exit;
    1234             :         }
    1235          45 :         bytes = PyBytes_FromObject(o);
    1236          45 :         if (!bytes) {
    1237           0 :             goto error_exit;
    1238             :         }
    1239             :     }
    1240       17366 :     else if (is_index) {
    1241       17366 :         if (!_fd_converter(o, &path->fd)) {
    1242           0 :             goto error_exit;
    1243             :         }
    1244       17366 :         path->wide = NULL;
    1245             : #ifdef MS_WINDOWS
    1246             :         path->narrow = FALSE;
    1247             : #else
    1248       17366 :         path->narrow = NULL;
    1249             : #endif
    1250       17366 :         goto success_exit;
    1251             :     }
    1252             :     else {
    1253           0 :  error_format:
    1254          60 :         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
    1255          12 :             path->function_name ? path->function_name : "",
    1256          12 :             path->function_name ? ": "                : "",
    1257          12 :             path->argument_name ? path->argument_name : "path",
    1258          12 :             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
    1259             :                                                "integer or None" :
    1260          14 :             path->allow_fd ? "string, bytes, os.PathLike or integer" :
    1261           5 :             path->nullable ? "string, bytes, os.PathLike or None" :
    1262             :                              "string, bytes or os.PathLike",
    1263             :             _PyType_Name(Py_TYPE(o)));
    1264          12 :         goto error_exit;
    1265             :     }
    1266             : 
    1267     1729280 :     length = PyBytes_GET_SIZE(bytes);
    1268     1729280 :     narrow = PyBytes_AS_STRING(bytes);
    1269     1729280 :     if ((size_t)length != strlen(narrow)) {
    1270          25 :         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
    1271          25 :         goto error_exit;
    1272             :     }
    1273             : 
    1274             : #ifdef MS_WINDOWS
    1275             :     wo = PyUnicode_DecodeFSDefaultAndSize(
    1276             :         narrow,
    1277             :         length
    1278             :     );
    1279             :     if (!wo) {
    1280             :         goto error_exit;
    1281             :     }
    1282             : 
    1283             :     wide = PyUnicode_AsWideCharString(wo, &length);
    1284             :     Py_DECREF(wo);
    1285             :     if (!wide) {
    1286             :         goto error_exit;
    1287             :     }
    1288             :     if (length > 32767) {
    1289             :         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
    1290             :         goto error_exit;
    1291             :     }
    1292             :     if (wcslen(wide) != length) {
    1293             :         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
    1294             :         goto error_exit;
    1295             :     }
    1296             :     path->wide = wide;
    1297             :     path->narrow = TRUE;
    1298             :     Py_DECREF(bytes);
    1299             :     wide = NULL;
    1300             : #else
    1301     1729250 :     path->wide = NULL;
    1302     1729250 :     path->narrow = narrow;
    1303     1729250 :     if (bytes == o) {
    1304             :         /* Still a reference owned by path->object, don't have to
    1305             :            worry about path->narrow is used after free. */
    1306       18212 :         Py_DECREF(bytes);
    1307             :     }
    1308             :     else {
    1309     1711040 :         path->cleanup = bytes;
    1310             :     }
    1311             : #endif
    1312     1729250 :     path->fd = -1;
    1313             : 
    1314     1746620 :  success_exit:
    1315     1746620 :     path->length = length;
    1316     1746620 :     path->object = o;
    1317     1746620 :     return Py_CLEANUP_SUPPORTED;
    1318             : 
    1319         146 :  error_exit:
    1320         146 :     Py_XDECREF(o);
    1321         146 :     Py_XDECREF(bytes);
    1322             : #ifdef MS_WINDOWS
    1323             :     PyMem_Free(wide);
    1324             : #endif
    1325         146 :     return 0;
    1326             : }
    1327             : 
    1328             : static void
    1329           0 : argument_unavailable_error(const char *function_name, const char *argument_name)
    1330             : {
    1331           0 :     PyErr_Format(PyExc_NotImplementedError,
    1332             :         "%s%s%s unavailable on this platform",
    1333             :         (function_name != NULL) ? function_name : "",
    1334             :         (function_name != NULL) ? ": ": "",
    1335             :         argument_name);
    1336           0 : }
    1337             : 
    1338             : static int
    1339        3130 : dir_fd_unavailable(PyObject *o, void *p)
    1340             : {
    1341             :     int dir_fd;
    1342        3130 :     if (!dir_fd_converter(o, &dir_fd))
    1343           0 :         return 0;
    1344        3130 :     if (dir_fd != DEFAULT_DIR_FD) {
    1345           0 :         argument_unavailable_error(NULL, "dir_fd");
    1346           0 :         return 0;
    1347             :     }
    1348        3130 :     *(int *)p = dir_fd;
    1349        3130 :     return 1;
    1350             : }
    1351             : 
    1352             : static int
    1353        3130 : fd_specified(const char *function_name, int fd)
    1354             : {
    1355        3130 :     if (fd == -1)
    1356        3130 :         return 0;
    1357             : 
    1358           0 :     argument_unavailable_error(function_name, "fd");
    1359           0 :     return 1;
    1360             : }
    1361             : 
    1362             : static int
    1363        3130 : follow_symlinks_specified(const char *function_name, int follow_symlinks)
    1364             : {
    1365        3130 :     if (follow_symlinks)
    1366        3130 :         return 0;
    1367             : 
    1368           0 :     argument_unavailable_error(function_name, "follow_symlinks");
    1369           0 :     return 1;
    1370             : }
    1371             : 
    1372             : static int
    1373     1499690 : path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
    1374             : {
    1375     1499690 :     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
    1376             : #ifndef MS_WINDOWS
    1377        3856 :         && !path->narrow
    1378             : #endif
    1379             :     ) {
    1380           0 :         PyErr_Format(PyExc_ValueError,
    1381             :                      "%s: can't specify dir_fd without matching path",
    1382             :                      function_name);
    1383           0 :         return 1;
    1384             :     }
    1385     1499690 :     return 0;
    1386             : }
    1387             : 
    1388             : static int
    1389     1499720 : dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
    1390             : {
    1391     1499720 :     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
    1392           0 :         PyErr_Format(PyExc_ValueError,
    1393             :                      "%s: can't specify both dir_fd and fd",
    1394             :                      function_name);
    1395           0 :         return 1;
    1396             :     }
    1397     1499720 :     return 0;
    1398             : }
    1399             : 
    1400             : static int
    1401     1511610 : fd_and_follow_symlinks_invalid(const char *function_name, int fd,
    1402             :                                int follow_symlinks)
    1403             : {
    1404     1511610 :     if ((fd > 0) && (!follow_symlinks)) {
    1405           0 :         PyErr_Format(PyExc_ValueError,
    1406             :                      "%s: cannot use fd and follow_symlinks together",
    1407             :                      function_name);
    1408           0 :         return 1;
    1409             :     }
    1410     1511610 :     return 0;
    1411             : }
    1412             : 
    1413             : static int
    1414        3130 : dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
    1415             :                                    int follow_symlinks)
    1416             : {
    1417        3130 :     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
    1418           0 :         PyErr_Format(PyExc_ValueError,
    1419             :                      "%s: cannot use dir_fd and follow_symlinks together",
    1420             :                      function_name);
    1421           0 :         return 1;
    1422             :     }
    1423        3130 :     return 0;
    1424             : }
    1425             : 
    1426             : #ifdef MS_WINDOWS
    1427             :     typedef long long Py_off_t;
    1428             : #else
    1429             :     typedef off_t Py_off_t;
    1430             : #endif
    1431             : 
    1432             : static int
    1433       30718 : Py_off_t_converter(PyObject *arg, void *addr)
    1434             : {
    1435             : #ifdef HAVE_LARGEFILE_SUPPORT
    1436             :     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
    1437             : #else
    1438       30718 :     *((Py_off_t *)addr) = PyLong_AsLong(arg);
    1439             : #endif
    1440       30718 :     if (PyErr_Occurred())
    1441           0 :         return 0;
    1442       30718 :     return 1;
    1443             : }
    1444             : 
    1445             : static PyObject *
    1446        8362 : PyLong_FromPy_off_t(Py_off_t offset)
    1447             : {
    1448             : #ifdef HAVE_LARGEFILE_SUPPORT
    1449             :     return PyLong_FromLongLong(offset);
    1450             : #else
    1451        8362 :     return PyLong_FromLong(offset);
    1452             : #endif
    1453             : }
    1454             : 
    1455             : #ifdef HAVE_SIGSET_T
    1456             : /* Convert an iterable of integers to a sigset.
    1457             :    Return 1 on success, return 0 and raise an exception on error. */
    1458             : int
    1459         270 : _Py_Sigset_Converter(PyObject *obj, void *addr)
    1460             : {
    1461         270 :     sigset_t *mask = (sigset_t *)addr;
    1462             :     PyObject *iterator, *item;
    1463             :     long signum;
    1464             :     int overflow;
    1465             : 
    1466             :     // The extra parens suppress the unreachable-code warning with clang on MacOS
    1467         270 :     if (sigemptyset(mask) < (0)) {
    1468             :         /* Probably only if mask == NULL. */
    1469           0 :         PyErr_SetFromErrno(PyExc_OSError);
    1470           0 :         return 0;
    1471             :     }
    1472             : 
    1473         270 :     iterator = PyObject_GetIter(obj);
    1474         270 :     if (iterator == NULL) {
    1475           4 :         return 0;
    1476             :     }
    1477             : 
    1478        1082 :     while ((item = PyIter_Next(iterator)) != NULL) {
    1479         827 :         signum = PyLong_AsLongAndOverflow(item, &overflow);
    1480         827 :         Py_DECREF(item);
    1481         827 :         if (signum <= 0 || signum >= Py_NSIG) {
    1482          11 :             if (overflow || signum != -1 || !PyErr_Occurred()) {
    1483           7 :                 PyErr_Format(PyExc_ValueError,
    1484             :                              "signal number %ld out of range [1; %i]",
    1485             :                              signum, Py_NSIG - 1);
    1486             :             }
    1487          11 :             goto error;
    1488             :         }
    1489         816 :         if (sigaddset(mask, (int)signum)) {
    1490           0 :             if (errno != EINVAL) {
    1491             :                 /* Probably impossible */
    1492           0 :                 PyErr_SetFromErrno(PyExc_OSError);
    1493           0 :                 goto error;
    1494             :             }
    1495             :             /* For backwards compatibility, allow idioms such as
    1496             :              * `range(1, NSIG)` but warn about invalid signal numbers
    1497             :              */
    1498           0 :             const char msg[] =
    1499             :                 "invalid signal number %ld, please use valid_signals()";
    1500           0 :             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
    1501           0 :                 goto error;
    1502             :             }
    1503             :         }
    1504             :     }
    1505         255 :     if (!PyErr_Occurred()) {
    1506         255 :         Py_DECREF(iterator);
    1507         255 :         return 1;
    1508             :     }
    1509             : 
    1510           0 : error:
    1511          11 :     Py_DECREF(iterator);
    1512          11 :     return 0;
    1513             : }
    1514             : #endif /* HAVE_SIGSET_T */
    1515             : 
    1516             : #ifdef MS_WINDOWS
    1517             : 
    1518             : static int
    1519             : win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
    1520             : {
    1521             :     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    1522             :     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
    1523             :     DWORD n_bytes_returned;
    1524             : 
    1525             :     if (0 == DeviceIoControl(
    1526             :         reparse_point_handle,
    1527             :         FSCTL_GET_REPARSE_POINT,
    1528             :         NULL, 0, /* in buffer */
    1529             :         target_buffer, sizeof(target_buffer),
    1530             :         &n_bytes_returned,
    1531             :         NULL)) /* we're not using OVERLAPPED_IO */
    1532             :         return FALSE;
    1533             : 
    1534             :     if (reparse_tag)
    1535             :         *reparse_tag = rdb->ReparseTag;
    1536             : 
    1537             :     return TRUE;
    1538             : }
    1539             : 
    1540             : #endif /* MS_WINDOWS */
    1541             : 
    1542             : /* Return a dictionary corresponding to the POSIX environment table */
    1543             : #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
    1544             : /* On Darwin/MacOSX a shared library or framework has no access to
    1545             : ** environ directly, we must obtain it with _NSGetEnviron(). See also
    1546             : ** man environ(7).
    1547             : */
    1548             : #include <crt_externs.h>
    1549             : #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
    1550             : extern char **environ;
    1551             : #endif /* !_MSC_VER */
    1552             : 
    1553             : static PyObject *
    1554        3130 : convertenviron(void)
    1555             : {
    1556             :     PyObject *d;
    1557             : #ifdef MS_WINDOWS
    1558             :     wchar_t **e;
    1559             : #else
    1560             :     char **e;
    1561             : #endif
    1562             : 
    1563        3130 :     d = PyDict_New();
    1564        3130 :     if (d == NULL)
    1565           0 :         return NULL;
    1566             : #ifdef MS_WINDOWS
    1567             :     /* _wenviron must be initialized in this way if the program is started
    1568             :        through main() instead of wmain(). */
    1569             :     _wgetenv(L"");
    1570             :     e = _wenviron;
    1571             : #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
    1572             :     /* environ is not accessible as an extern in a shared object on OSX; use
    1573             :        _NSGetEnviron to resolve it. The value changes if you add environment
    1574             :        variables between calls to Py_Initialize, so don't cache the value. */
    1575             :     e = *_NSGetEnviron();
    1576             : #else
    1577        3130 :     e = environ;
    1578             : #endif
    1579        3130 :     if (e == NULL)
    1580           0 :         return d;
    1581      355656 :     for (; *e != NULL; e++) {
    1582             :         PyObject *k;
    1583             :         PyObject *v;
    1584             : #ifdef MS_WINDOWS
    1585             :         const wchar_t *p = wcschr(*e, L'=');
    1586             : #else
    1587      352526 :         const char *p = strchr(*e, '=');
    1588             : #endif
    1589      352526 :         if (p == NULL)
    1590           0 :             continue;
    1591             : #ifdef MS_WINDOWS
    1592             :         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
    1593             : #else
    1594      352526 :         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
    1595             : #endif
    1596      352526 :         if (k == NULL) {
    1597           0 :             Py_DECREF(d);
    1598           0 :             return NULL;
    1599             :         }
    1600             : #ifdef MS_WINDOWS
    1601             :         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
    1602             : #else
    1603      352526 :         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
    1604             : #endif
    1605      352526 :         if (v == NULL) {
    1606           0 :             Py_DECREF(k);
    1607           0 :             Py_DECREF(d);
    1608           0 :             return NULL;
    1609             :         }
    1610      352526 :         if (PyDict_SetDefault(d, k, v) == NULL) {
    1611           0 :             Py_DECREF(v);
    1612           0 :             Py_DECREF(k);
    1613           0 :             Py_DECREF(d);
    1614           0 :             return NULL;
    1615             :         }
    1616      352526 :         Py_DECREF(k);
    1617      352526 :         Py_DECREF(v);
    1618             :     }
    1619        3130 :     return d;
    1620             : }
    1621             : 
    1622             : /* Set a POSIX-specific error from errno, and return NULL */
    1623             : 
    1624             : static PyObject *
    1625     1052640 : posix_error(void)
    1626             : {
    1627     1052640 :     return PyErr_SetFromErrno(PyExc_OSError);
    1628             : }
    1629             : 
    1630             : #ifdef MS_WINDOWS
    1631             : static PyObject *
    1632             : win32_error(const char* function, const char* filename)
    1633             : {
    1634             :     /* XXX We should pass the function name along in the future.
    1635             :        (winreg.c also wants to pass the function name.)
    1636             :        This would however require an additional param to the
    1637             :        Windows error object, which is non-trivial.
    1638             :     */
    1639             :     errno = GetLastError();
    1640             :     if (filename)
    1641             :         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
    1642             :     else
    1643             :         return PyErr_SetFromWindowsErr(errno);
    1644             : }
    1645             : 
    1646             : static PyObject *
    1647             : win32_error_object_err(const char* function, PyObject* filename, DWORD err)
    1648             : {
    1649             :     /* XXX - see win32_error for comments on 'function' */
    1650             :     if (filename)
    1651             :         return PyErr_SetExcFromWindowsErrWithFilenameObject(
    1652             :                     PyExc_OSError,
    1653             :                     err,
    1654             :                     filename);
    1655             :     else
    1656             :         return PyErr_SetFromWindowsErr(err);
    1657             : }
    1658             : 
    1659             : static PyObject *
    1660             : win32_error_object(const char* function, PyObject* filename)
    1661             : {
    1662             :     errno = GetLastError();
    1663             :     return win32_error_object_err(function, filename, errno);
    1664             : }
    1665             : 
    1666             : #endif /* MS_WINDOWS */
    1667             : 
    1668             : static PyObject *
    1669      253458 : posix_path_object_error(PyObject *path)
    1670             : {
    1671      253458 :     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
    1672             : }
    1673             : 
    1674             : static PyObject *
    1675      253453 : path_object_error(PyObject *path)
    1676             : {
    1677             : #ifdef MS_WINDOWS
    1678             :     return PyErr_SetExcFromWindowsErrWithFilenameObject(
    1679             :                 PyExc_OSError, 0, path);
    1680             : #else
    1681      253453 :     return posix_path_object_error(path);
    1682             : #endif
    1683             : }
    1684             : 
    1685             : static PyObject *
    1686         127 : path_object_error2(PyObject *path, PyObject *path2)
    1687             : {
    1688             : #ifdef MS_WINDOWS
    1689             :     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
    1690             :                 PyExc_OSError, 0, path, path2);
    1691             : #else
    1692         127 :     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
    1693             : #endif
    1694             : }
    1695             : 
    1696             : static PyObject *
    1697      251270 : path_error(path_t *path)
    1698             : {
    1699      251270 :     return path_object_error(path->object);
    1700             : }
    1701             : 
    1702             : static PyObject *
    1703           5 : posix_path_error(path_t *path)
    1704             : {
    1705           5 :     return posix_path_object_error(path->object);
    1706             : }
    1707             : 
    1708             : static PyObject *
    1709         127 : path_error2(path_t *path, path_t *path2)
    1710             : {
    1711         127 :     return path_object_error2(path->object, path2->object);
    1712             : }
    1713             : 
    1714             : 
    1715             : /* POSIX generic methods */
    1716             : 
    1717             : static PyObject *
    1718         561 : posix_fildes_fd(int fd, int (*func)(int))
    1719             : {
    1720             :     int res;
    1721         561 :     int async_err = 0;
    1722             : 
    1723             :     do {
    1724         561 :         Py_BEGIN_ALLOW_THREADS
    1725             :         _Py_BEGIN_SUPPRESS_IPH
    1726         561 :         res = (*func)(fd);
    1727             :         _Py_END_SUPPRESS_IPH
    1728         561 :         Py_END_ALLOW_THREADS
    1729         561 :     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    1730         561 :     if (res != 0)
    1731           3 :         return (!async_err) ? posix_error() : NULL;
    1732         558 :     Py_RETURN_NONE;
    1733             : }
    1734             : 
    1735             : 
    1736             : #ifdef MS_WINDOWS
    1737             : /* This is a reimplementation of the C library's chdir function,
    1738             :    but one that produces Win32 errors instead of DOS error codes.
    1739             :    chdir is essentially a wrapper around SetCurrentDirectory; however,
    1740             :    it also needs to set "magic" environment variables indicating
    1741             :    the per-drive current directory, which are of the form =<drive>: */
    1742             : static BOOL __stdcall
    1743             : win32_wchdir(LPCWSTR path)
    1744             : {
    1745             :     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
    1746             :     int result;
    1747             :     wchar_t env[4] = L"=x:";
    1748             : 
    1749             :     if(!SetCurrentDirectoryW(path))
    1750             :         return FALSE;
    1751             :     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
    1752             :     if (!result)
    1753             :         return FALSE;
    1754             :     if (result > Py_ARRAY_LENGTH(path_buf)) {
    1755             :         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
    1756             :         if (!new_path) {
    1757             :             SetLastError(ERROR_OUTOFMEMORY);
    1758             :             return FALSE;
    1759             :         }
    1760             :         result = GetCurrentDirectoryW(result, new_path);
    1761             :         if (!result) {
    1762             :             PyMem_RawFree(new_path);
    1763             :             return FALSE;
    1764             :         }
    1765             :     }
    1766             :     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
    1767             :                             wcsncmp(new_path, L"//", 2) == 0);
    1768             :     if (!is_unc_like_path) {
    1769             :         env[1] = new_path[0];
    1770             :         result = SetEnvironmentVariableW(env, new_path);
    1771             :     }
    1772             :     if (new_path != path_buf)
    1773             :         PyMem_RawFree(new_path);
    1774             :     return result ? TRUE : FALSE;
    1775             : }
    1776             : #endif
    1777             : 
    1778             : #ifdef MS_WINDOWS
    1779             : /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
    1780             :    - time stamps are restricted to second resolution
    1781             :    - file modification times suffer from forth-and-back conversions between
    1782             :      UTC and local time
    1783             :    Therefore, we implement our own stat, based on the Win32 API directly.
    1784             : */
    1785             : #define HAVE_STAT_NSEC 1
    1786             : #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
    1787             : #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
    1788             : 
    1789             : static void
    1790             : find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
    1791             :                        BY_HANDLE_FILE_INFORMATION *info,
    1792             :                        ULONG *reparse_tag)
    1793             : {
    1794             :     memset(info, 0, sizeof(*info));
    1795             :     info->dwFileAttributes = pFileData->dwFileAttributes;
    1796             :     info->ftCreationTime   = pFileData->ftCreationTime;
    1797             :     info->ftLastAccessTime = pFileData->ftLastAccessTime;
    1798             :     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
    1799             :     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
    1800             :     info->nFileSizeLow     = pFileData->nFileSizeLow;
    1801             : /*  info->nNumberOfLinks   = 1; */
    1802             :     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
    1803             :         *reparse_tag = pFileData->dwReserved0;
    1804             :     else
    1805             :         *reparse_tag = 0;
    1806             : }
    1807             : 
    1808             : static BOOL
    1809             : attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
    1810             : {
    1811             :     HANDLE hFindFile;
    1812             :     WIN32_FIND_DATAW FileData;
    1813             :     LPCWSTR filename = pszFile;
    1814             :     size_t n = wcslen(pszFile);
    1815             :     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
    1816             :         // cannot use PyMem_Malloc here because we do not hold the GIL
    1817             :         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
    1818             :         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
    1819             :         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
    1820             :             ((LPWSTR)filename)[n] = L'\0';
    1821             :         }
    1822             :         if (!n || (n == 1 && filename[1] == L':')) {
    1823             :             // Nothing left to query
    1824             :             free((void *)filename);
    1825             :             return FALSE;
    1826             :         }
    1827             :     }
    1828             :     hFindFile = FindFirstFileW(filename, &FileData);
    1829             :     if (pszFile != filename) {
    1830             :         free((void *)filename);
    1831             :     }
    1832             :     if (hFindFile == INVALID_HANDLE_VALUE) {
    1833             :         return FALSE;
    1834             :     }
    1835             :     FindClose(hFindFile);
    1836             :     find_data_to_file_info(&FileData, info, reparse_tag);
    1837             :     return TRUE;
    1838             : }
    1839             : 
    1840             : static int
    1841             : win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
    1842             :                  BOOL traverse)
    1843             : {
    1844             :     HANDLE hFile;
    1845             :     BY_HANDLE_FILE_INFORMATION fileInfo;
    1846             :     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
    1847             :     DWORD fileType, error;
    1848             :     BOOL isUnhandledTag = FALSE;
    1849             :     int retval = 0;
    1850             : 
    1851             :     DWORD access = FILE_READ_ATTRIBUTES;
    1852             :     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
    1853             :     if (!traverse) {
    1854             :         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
    1855             :     }
    1856             : 
    1857             :     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
    1858             :     if (hFile == INVALID_HANDLE_VALUE) {
    1859             :         /* Either the path doesn't exist, or the caller lacks access. */
    1860             :         error = GetLastError();
    1861             :         switch (error) {
    1862             :         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
    1863             :         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
    1864             :             /* Try reading the parent directory. */
    1865             :             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
    1866             :                 /* Cannot read the parent directory. */
    1867             :                 switch (GetLastError()) {
    1868             :                 case ERROR_FILE_NOT_FOUND: /* File cannot be found */
    1869             :                 case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
    1870             :                 case ERROR_NOT_READY: /* Drive exists but unavailable */
    1871             :                 case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
    1872             :                     break;
    1873             :                 /* Restore the error from CreateFileW(). */
    1874             :                 default:
    1875             :                     SetLastError(error);
    1876             :                 }
    1877             : 
    1878             :                 return -1;
    1879             :             }
    1880             :             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    1881             :                 if (traverse ||
    1882             :                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
    1883             :                     /* The stat call has to traverse but cannot, so fail. */
    1884             :                     SetLastError(error);
    1885             :                     return -1;
    1886             :                 }
    1887             :             }
    1888             :             break;
    1889             : 
    1890             :         case ERROR_INVALID_PARAMETER:
    1891             :             /* \\.\con requires read or write access. */
    1892             :             hFile = CreateFileW(path, access | GENERIC_READ,
    1893             :                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    1894             :                         OPEN_EXISTING, flags, NULL);
    1895             :             if (hFile == INVALID_HANDLE_VALUE) {
    1896             :                 SetLastError(error);
    1897             :                 return -1;
    1898             :             }
    1899             :             break;
    1900             : 
    1901             :         case ERROR_CANT_ACCESS_FILE:
    1902             :             /* bpo37834: open unhandled reparse points if traverse fails. */
    1903             :             if (traverse) {
    1904             :                 traverse = FALSE;
    1905             :                 isUnhandledTag = TRUE;
    1906             :                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
    1907             :                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
    1908             :             }
    1909             :             if (hFile == INVALID_HANDLE_VALUE) {
    1910             :                 SetLastError(error);
    1911             :                 return -1;
    1912             :             }
    1913             :             break;
    1914             : 
    1915             :         default:
    1916             :             return -1;
    1917             :         }
    1918             :     }
    1919             : 
    1920             :     if (hFile != INVALID_HANDLE_VALUE) {
    1921             :         /* Handle types other than files on disk. */
    1922             :         fileType = GetFileType(hFile);
    1923             :         if (fileType != FILE_TYPE_DISK) {
    1924             :             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
    1925             :                 retval = -1;
    1926             :                 goto cleanup;
    1927             :             }
    1928             :             DWORD fileAttributes = GetFileAttributesW(path);
    1929             :             memset(result, 0, sizeof(*result));
    1930             :             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
    1931             :                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
    1932             :                 /* \\.\pipe\ or \\.\mailslot\ */
    1933             :                 result->st_mode = _S_IFDIR;
    1934             :             } else if (fileType == FILE_TYPE_CHAR) {
    1935             :                 /* \\.\nul */
    1936             :                 result->st_mode = _S_IFCHR;
    1937             :             } else if (fileType == FILE_TYPE_PIPE) {
    1938             :                 /* \\.\pipe\spam */
    1939             :                 result->st_mode = _S_IFIFO;
    1940             :             }
    1941             :             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
    1942             :             goto cleanup;
    1943             :         }
    1944             : 
    1945             :         /* Query the reparse tag, and traverse a non-link. */
    1946             :         if (!traverse) {
    1947             :             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
    1948             :                     &tagInfo, sizeof(tagInfo))) {
    1949             :                 /* Allow devices that do not support FileAttributeTagInfo. */
    1950             :                 switch (GetLastError()) {
    1951             :                 case ERROR_INVALID_PARAMETER:
    1952             :                 case ERROR_INVALID_FUNCTION:
    1953             :                 case ERROR_NOT_SUPPORTED:
    1954             :                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
    1955             :                     tagInfo.ReparseTag = 0;
    1956             :                     break;
    1957             :                 default:
    1958             :                     retval = -1;
    1959             :                     goto cleanup;
    1960             :                 }
    1961             :             } else if (tagInfo.FileAttributes &
    1962             :                          FILE_ATTRIBUTE_REPARSE_POINT) {
    1963             :                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
    1964             :                     if (isUnhandledTag) {
    1965             :                         /* Traversing previously failed for either this link
    1966             :                            or its target. */
    1967             :                         SetLastError(ERROR_CANT_ACCESS_FILE);
    1968             :                         retval = -1;
    1969             :                         goto cleanup;
    1970             :                     }
    1971             :                 /* Traverse a non-link, but not if traversing already failed
    1972             :                    for an unhandled tag. */
    1973             :                 } else if (!isUnhandledTag) {
    1974             :                     CloseHandle(hFile);
    1975             :                     return win32_xstat_impl(path, result, TRUE);
    1976             :                 }
    1977             :             }
    1978             :         }
    1979             : 
    1980             :         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
    1981             :             switch (GetLastError()) {
    1982             :             case ERROR_INVALID_PARAMETER:
    1983             :             case ERROR_INVALID_FUNCTION:
    1984             :             case ERROR_NOT_SUPPORTED:
    1985             :                 /* Volumes and physical disks are block devices, e.g.
    1986             :                    \\.\C: and \\.\PhysicalDrive0. */
    1987             :                 memset(result, 0, sizeof(*result));
    1988             :                 result->st_mode = 0x6000; /* S_IFBLK */
    1989             :                 goto cleanup;
    1990             :             }
    1991             :             retval = -1;
    1992             :             goto cleanup;
    1993             :         }
    1994             :     }
    1995             : 
    1996             :     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
    1997             : 
    1998             :     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
    1999             :         /* Fix the file execute permissions. This hack sets S_IEXEC if
    2000             :            the filename has an extension that is commonly used by files
    2001             :            that CreateProcessW can execute. A real implementation calls
    2002             :            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
    2003             :            AccessCheck to check for generic read, write, and execute
    2004             :            access. */
    2005             :         const wchar_t *fileExtension = wcsrchr(path, '.');
    2006             :         if (fileExtension) {
    2007             :             if (_wcsicmp(fileExtension, L".exe") == 0 ||
    2008             :                 _wcsicmp(fileExtension, L".bat") == 0 ||
    2009             :                 _wcsicmp(fileExtension, L".cmd") == 0 ||
    2010             :                 _wcsicmp(fileExtension, L".com") == 0) {
    2011             :                 result->st_mode |= 0111;
    2012             :             }
    2013             :         }
    2014             :     }
    2015             : 
    2016             : cleanup:
    2017             :     if (hFile != INVALID_HANDLE_VALUE) {
    2018             :         /* Preserve last error if we are failing */
    2019             :         error = retval ? GetLastError() : 0;
    2020             :         if (!CloseHandle(hFile)) {
    2021             :             retval = -1;
    2022             :         } else if (retval) {
    2023             :             /* Restore last error */
    2024             :             SetLastError(error);
    2025             :         }
    2026             :     }
    2027             : 
    2028             :     return retval;
    2029             : }
    2030             : 
    2031             : static int
    2032             : win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
    2033             : {
    2034             :     /* Protocol violation: we explicitly clear errno, instead of
    2035             :        setting it to a POSIX error. Callers should use GetLastError. */
    2036             :     int code = win32_xstat_impl(path, result, traverse);
    2037             :     errno = 0;
    2038             :     return code;
    2039             : }
    2040             : /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
    2041             : 
    2042             :    In Posix, stat automatically traverses symlinks and returns the stat
    2043             :    structure for the target.  In Windows, the equivalent GetFileAttributes by
    2044             :    default does not traverse symlinks and instead returns attributes for
    2045             :    the symlink.
    2046             : 
    2047             :    Instead, we will open the file (which *does* traverse symlinks by default)
    2048             :    and GetFileInformationByHandle(). */
    2049             : 
    2050             : static int
    2051             : win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
    2052             : {
    2053             :     return win32_xstat(path, result, FALSE);
    2054             : }
    2055             : 
    2056             : static int
    2057             : win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
    2058             : {
    2059             :     return win32_xstat(path, result, TRUE);
    2060             : }
    2061             : 
    2062             : #endif /* MS_WINDOWS */
    2063             : 
    2064             : PyDoc_STRVAR(stat_result__doc__,
    2065             : "stat_result: Result from stat, fstat, or lstat.\n\n\
    2066             : This object may be accessed either as a tuple of\n\
    2067             :   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
    2068             : or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
    2069             : \n\
    2070             : Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
    2071             : or st_flags, they are available as attributes only.\n\
    2072             : \n\
    2073             : See os.stat for more information.");
    2074             : 
    2075             : static PyStructSequence_Field stat_result_fields[] = {
    2076             :     {"st_mode",    "protection bits"},
    2077             :     {"st_ino",     "inode"},
    2078             :     {"st_dev",     "device"},
    2079             :     {"st_nlink",   "number of hard links"},
    2080             :     {"st_uid",     "user ID of owner"},
    2081             :     {"st_gid",     "group ID of owner"},
    2082             :     {"st_size",    "total size, in bytes"},
    2083             :     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
    2084             :     {NULL,   "integer time of last access"},
    2085             :     {NULL,   "integer time of last modification"},
    2086             :     {NULL,   "integer time of last change"},
    2087             :     {"st_atime",   "time of last access"},
    2088             :     {"st_mtime",   "time of last modification"},
    2089             :     {"st_ctime",   "time of last change"},
    2090             :     {"st_atime_ns",   "time of last access in nanoseconds"},
    2091             :     {"st_mtime_ns",   "time of last modification in nanoseconds"},
    2092             :     {"st_ctime_ns",   "time of last change in nanoseconds"},
    2093             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    2094             :     {"st_blksize", "blocksize for filesystem I/O"},
    2095             : #endif
    2096             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    2097             :     {"st_blocks",  "number of blocks allocated"},
    2098             : #endif
    2099             : #ifdef HAVE_STRUCT_STAT_ST_RDEV
    2100             :     {"st_rdev",    "device type (if inode device)"},
    2101             : #endif
    2102             : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
    2103             :     {"st_flags",   "user defined flags for file"},
    2104             : #endif
    2105             : #ifdef HAVE_STRUCT_STAT_ST_GEN
    2106             :     {"st_gen",    "generation number"},
    2107             : #endif
    2108             : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
    2109             :     {"st_birthtime",   "time of creation"},
    2110             : #endif
    2111             : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
    2112             :     {"st_file_attributes", "Windows file attribute bits"},
    2113             : #endif
    2114             : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
    2115             :     {"st_fstype",  "Type of filesystem"},
    2116             : #endif
    2117             : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
    2118             :     {"st_reparse_tag", "Windows reparse tag"},
    2119             : #endif
    2120             :     {0}
    2121             : };
    2122             : 
    2123             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    2124             : #define ST_BLKSIZE_IDX 16
    2125             : #else
    2126             : #define ST_BLKSIZE_IDX 15
    2127             : #endif
    2128             : 
    2129             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    2130             : #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
    2131             : #else
    2132             : #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
    2133             : #endif
    2134             : 
    2135             : #ifdef HAVE_STRUCT_STAT_ST_RDEV
    2136             : #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
    2137             : #else
    2138             : #define ST_RDEV_IDX ST_BLOCKS_IDX
    2139             : #endif
    2140             : 
    2141             : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
    2142             : #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
    2143             : #else
    2144             : #define ST_FLAGS_IDX ST_RDEV_IDX
    2145             : #endif
    2146             : 
    2147             : #ifdef HAVE_STRUCT_STAT_ST_GEN
    2148             : #define ST_GEN_IDX (ST_FLAGS_IDX+1)
    2149             : #else
    2150             : #define ST_GEN_IDX ST_FLAGS_IDX
    2151             : #endif
    2152             : 
    2153             : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
    2154             : #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
    2155             : #else
    2156             : #define ST_BIRTHTIME_IDX ST_GEN_IDX
    2157             : #endif
    2158             : 
    2159             : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
    2160             : #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
    2161             : #else
    2162             : #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
    2163             : #endif
    2164             : 
    2165             : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
    2166             : #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
    2167             : #else
    2168             : #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
    2169             : #endif
    2170             : 
    2171             : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
    2172             : #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
    2173             : #else
    2174             : #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
    2175             : #endif
    2176             : 
    2177             : static PyStructSequence_Desc stat_result_desc = {
    2178             :     "stat_result", /* name */
    2179             :     stat_result__doc__, /* doc */
    2180             :     stat_result_fields,
    2181             :     10
    2182             : };
    2183             : 
    2184             : PyDoc_STRVAR(statvfs_result__doc__,
    2185             : "statvfs_result: Result from statvfs or fstatvfs.\n\n\
    2186             : This object may be accessed either as a tuple of\n\
    2187             :   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
    2188             : or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
    2189             : \n\
    2190             : See os.statvfs for more information.");
    2191             : 
    2192             : static PyStructSequence_Field statvfs_result_fields[] = {
    2193             :     {"f_bsize",  },
    2194             :     {"f_frsize", },
    2195             :     {"f_blocks", },
    2196             :     {"f_bfree",  },
    2197             :     {"f_bavail", },
    2198             :     {"f_files",  },
    2199             :     {"f_ffree",  },
    2200             :     {"f_favail", },
    2201             :     {"f_flag",   },
    2202             :     {"f_namemax",},
    2203             :     {"f_fsid",   },
    2204             :     {0}
    2205             : };
    2206             : 
    2207             : static PyStructSequence_Desc statvfs_result_desc = {
    2208             :     "statvfs_result", /* name */
    2209             :     statvfs_result__doc__, /* doc */
    2210             :     statvfs_result_fields,
    2211             :     10
    2212             : };
    2213             : 
    2214             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
    2215             : PyDoc_STRVAR(waitid_result__doc__,
    2216             : "waitid_result: Result from waitid.\n\n\
    2217             : This object may be accessed either as a tuple of\n\
    2218             :   (si_pid, si_uid, si_signo, si_status, si_code),\n\
    2219             : or via the attributes si_pid, si_uid, and so on.\n\
    2220             : \n\
    2221             : See os.waitid for more information.");
    2222             : 
    2223             : static PyStructSequence_Field waitid_result_fields[] = {
    2224             :     {"si_pid",  },
    2225             :     {"si_uid", },
    2226             :     {"si_signo", },
    2227             :     {"si_status",  },
    2228             :     {"si_code", },
    2229             :     {0}
    2230             : };
    2231             : 
    2232             : static PyStructSequence_Desc waitid_result_desc = {
    2233             :     "waitid_result", /* name */
    2234             :     waitid_result__doc__, /* doc */
    2235             :     waitid_result_fields,
    2236             :     5
    2237             : };
    2238             : #endif
    2239             : static newfunc structseq_new;
    2240             : 
    2241             : static PyObject *
    2242          68 : statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    2243             : {
    2244             :     PyStructSequence *result;
    2245             :     int i;
    2246             : 
    2247          68 :     result = (PyStructSequence*)structseq_new(type, args, kwds);
    2248          68 :     if (!result)
    2249           2 :         return NULL;
    2250             :     /* If we have been initialized from a tuple,
    2251             :        st_?time might be set to None. Initialize it
    2252             :        from the int slots.  */
    2253         264 :     for (i = 7; i <= 9; i++) {
    2254         198 :         if (result->ob_item[i+3] == Py_None) {
    2255          66 :             Py_DECREF(Py_None);
    2256          66 :             Py_INCREF(result->ob_item[i]);
    2257          66 :             result->ob_item[i+3] = result->ob_item[i];
    2258             :         }
    2259             :     }
    2260          66 :     return (PyObject*)result;
    2261             : }
    2262             : 
    2263             : static int
    2264        6158 : _posix_clear(PyObject *module)
    2265             : {
    2266        6158 :     _posixstate *state = get_posix_state(module);
    2267        6158 :     Py_CLEAR(state->billion);
    2268        6158 :     Py_CLEAR(state->DirEntryType);
    2269        6158 :     Py_CLEAR(state->ScandirIteratorType);
    2270             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
    2271        6158 :     Py_CLEAR(state->SchedParamType);
    2272             : #endif
    2273        6158 :     Py_CLEAR(state->StatResultType);
    2274        6158 :     Py_CLEAR(state->StatVFSResultType);
    2275        6158 :     Py_CLEAR(state->TerminalSizeType);
    2276        6158 :     Py_CLEAR(state->TimesResultType);
    2277        6158 :     Py_CLEAR(state->UnameResultType);
    2278             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
    2279        6158 :     Py_CLEAR(state->WaitidResultType);
    2280             : #endif
    2281             : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
    2282        6158 :     Py_CLEAR(state->struct_rusage);
    2283             : #endif
    2284        6158 :     Py_CLEAR(state->st_mode);
    2285        6158 :     return 0;
    2286             : }
    2287             : 
    2288             : static int
    2289       55736 : _posix_traverse(PyObject *module, visitproc visit, void *arg)
    2290             : {
    2291       55736 :     _posixstate *state = get_posix_state(module);
    2292       55736 :     Py_VISIT(state->billion);
    2293       55736 :     Py_VISIT(state->DirEntryType);
    2294       55736 :     Py_VISIT(state->ScandirIteratorType);
    2295             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
    2296       55736 :     Py_VISIT(state->SchedParamType);
    2297             : #endif
    2298       55736 :     Py_VISIT(state->StatResultType);
    2299       55736 :     Py_VISIT(state->StatVFSResultType);
    2300       55736 :     Py_VISIT(state->TerminalSizeType);
    2301       55736 :     Py_VISIT(state->TimesResultType);
    2302       55736 :     Py_VISIT(state->UnameResultType);
    2303             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
    2304       55736 :     Py_VISIT(state->WaitidResultType);
    2305             : #endif
    2306             : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
    2307       55736 :     Py_VISIT(state->struct_rusage);
    2308             : #endif
    2309       55736 :     Py_VISIT(state->st_mode);
    2310       55736 :     return 0;
    2311             : }
    2312             : 
    2313             : static void
    2314        3079 : _posix_free(void *module)
    2315             : {
    2316        3079 :    _posix_clear((PyObject *)module);
    2317        3079 : }
    2318             : 
    2319             : static void
    2320     3906860 : fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
    2321             : {
    2322     3906860 :     PyObject *s = _PyLong_FromTime_t(sec);
    2323     3906860 :     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
    2324     3906860 :     PyObject *s_in_ns = NULL;
    2325     3906860 :     PyObject *ns_total = NULL;
    2326     3906860 :     PyObject *float_s = NULL;
    2327             : 
    2328     3906860 :     if (!(s && ns_fractional))
    2329           0 :         goto exit;
    2330             : 
    2331     3906860 :     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
    2332     3906860 :     if (!s_in_ns)
    2333           0 :         goto exit;
    2334             : 
    2335     3906860 :     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
    2336     3906860 :     if (!ns_total)
    2337           0 :         goto exit;
    2338             : 
    2339     3906860 :     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
    2340     3906860 :     if (!float_s) {
    2341           0 :         goto exit;
    2342             :     }
    2343             : 
    2344     3906860 :     PyStructSequence_SET_ITEM(v, index, s);
    2345     3906860 :     PyStructSequence_SET_ITEM(v, index+3, float_s);
    2346     3906860 :     PyStructSequence_SET_ITEM(v, index+6, ns_total);
    2347     3906860 :     s = NULL;
    2348     3906860 :     float_s = NULL;
    2349     3906860 :     ns_total = NULL;
    2350     3906860 : exit:
    2351     3906860 :     Py_XDECREF(s);
    2352     3906860 :     Py_XDECREF(ns_fractional);
    2353     3906860 :     Py_XDECREF(s_in_ns);
    2354     3906860 :     Py_XDECREF(ns_total);
    2355     3906860 :     Py_XDECREF(float_s);
    2356     3906860 : }
    2357             : 
    2358             : /* pack a system stat C structure into the Python stat tuple
    2359             :    (used by posix_stat() and posix_fstat()) */
    2360             : static PyObject*
    2361     1302280 : _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
    2362             : {
    2363             :     unsigned long ansec, mnsec, cnsec;
    2364     1302280 :     PyObject *StatResultType = get_posix_state(module)->StatResultType;
    2365     1302280 :     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
    2366     1302280 :     if (v == NULL)
    2367           0 :         return NULL;
    2368             : 
    2369     1302280 :     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
    2370             :     static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
    2371             :                   "stat.st_ino is larger than unsigned long long");
    2372     1302280 :     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
    2373             : #ifdef MS_WINDOWS
    2374             :     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
    2375             : #else
    2376     1302280 :     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
    2377             : #endif
    2378     1302280 :     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
    2379             : #if defined(MS_WINDOWS)
    2380             :     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
    2381             :     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
    2382             : #else
    2383     1302280 :     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
    2384     1302280 :     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
    2385             : #endif
    2386             :     static_assert(sizeof(long long) >= sizeof(st->st_size),
    2387             :                   "stat.st_size is larger than long long");
    2388     1302280 :     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
    2389             : 
    2390             : #if defined(HAVE_STAT_TV_NSEC)
    2391     1302280 :     ansec = st->st_atim.tv_nsec;
    2392     1302280 :     mnsec = st->st_mtim.tv_nsec;
    2393     1302280 :     cnsec = st->st_ctim.tv_nsec;
    2394             : #elif defined(HAVE_STAT_TV_NSEC2)
    2395             :     ansec = st->st_atimespec.tv_nsec;
    2396             :     mnsec = st->st_mtimespec.tv_nsec;
    2397             :     cnsec = st->st_ctimespec.tv_nsec;
    2398             : #elif defined(HAVE_STAT_NSEC)
    2399             :     ansec = st->st_atime_nsec;
    2400             :     mnsec = st->st_mtime_nsec;
    2401             :     cnsec = st->st_ctime_nsec;
    2402             : #else
    2403             :     ansec = mnsec = cnsec = 0;
    2404             : #endif
    2405     1302280 :     fill_time(module, v, 7, st->st_atime, ansec);
    2406     1302280 :     fill_time(module, v, 8, st->st_mtime, mnsec);
    2407     1302280 :     fill_time(module, v, 9, st->st_ctime, cnsec);
    2408             : 
    2409             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    2410     1302280 :     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
    2411             :                               PyLong_FromLong((long)st->st_blksize));
    2412             : #endif
    2413             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    2414     1302280 :     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
    2415             :                               PyLong_FromLong((long)st->st_blocks));
    2416             : #endif
    2417             : #ifdef HAVE_STRUCT_STAT_ST_RDEV
    2418     1302280 :     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
    2419             :                               PyLong_FromLong((long)st->st_rdev));
    2420             : #endif
    2421             : #ifdef HAVE_STRUCT_STAT_ST_GEN
    2422             :     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
    2423             :                               PyLong_FromLong((long)st->st_gen));
    2424             : #endif
    2425             : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
    2426             :     {
    2427             :       PyObject *val;
    2428             :       unsigned long bsec,bnsec;
    2429             :       bsec = (long)st->st_birthtime;
    2430             : #ifdef HAVE_STAT_TV_NSEC2
    2431             :       bnsec = st->st_birthtimespec.tv_nsec;
    2432             : #else
    2433             :       bnsec = 0;
    2434             : #endif
    2435             :       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
    2436             :       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
    2437             :                                 val);
    2438             :     }
    2439             : #endif
    2440             : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
    2441             :     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
    2442             :                               PyLong_FromLong((long)st->st_flags));
    2443             : #endif
    2444             : #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
    2445             :     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
    2446             :                               PyLong_FromUnsignedLong(st->st_file_attributes));
    2447             : #endif
    2448             : #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
    2449             :    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
    2450             :                               PyUnicode_FromString(st->st_fstype));
    2451             : #endif
    2452             : #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
    2453             :     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
    2454             :                               PyLong_FromUnsignedLong(st->st_reparse_tag));
    2455             : #endif
    2456             : 
    2457     1302280 :     if (PyErr_Occurred()) {
    2458           0 :         Py_DECREF(v);
    2459           0 :         return NULL;
    2460             :     }
    2461             : 
    2462     1302280 :     return v;
    2463             : }
    2464             : 
    2465             : /* POSIX methods */
    2466             : 
    2467             : 
    2468             : static PyObject *
    2469     1488140 : posix_do_stat(PyObject *module, const char *function_name, path_t *path,
    2470             :               int dir_fd, int follow_symlinks)
    2471             : {
    2472             :     STRUCT_STAT st;
    2473             :     int result;
    2474             : 
    2475             : #ifdef HAVE_FSTATAT
    2476     1488140 :     int fstatat_unavailable = 0;
    2477             : #endif
    2478             : 
    2479             : #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
    2480             :     if (follow_symlinks_specified(function_name, follow_symlinks))
    2481             :         return NULL;
    2482             : #endif
    2483             : 
    2484     2976270 :     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
    2485     2976270 :         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
    2486     1488140 :         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
    2487           0 :         return NULL;
    2488             : 
    2489     1488140 :     Py_BEGIN_ALLOW_THREADS
    2490     1488140 :     if (path->fd != -1)
    2491        3769 :         result = FSTAT(path->fd, &st);
    2492             : #ifdef MS_WINDOWS
    2493             :     else if (follow_symlinks)
    2494             :         result = win32_stat(path->wide, &st);
    2495             :     else
    2496             :         result = win32_lstat(path->wide, &st);
    2497             : #else
    2498             :     else
    2499             : #if defined(HAVE_LSTAT)
    2500     1484370 :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    2501      139672 :         result = LSTAT(path->narrow, &st);
    2502             :     else
    2503             : #endif /* HAVE_LSTAT */
    2504             : #ifdef HAVE_FSTATAT
    2505     1344700 :     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
    2506        3848 :         if (HAVE_FSTATAT_RUNTIME) {
    2507        3848 :             result = fstatat(dir_fd, path->narrow, &st,
    2508             :                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
    2509             : 
    2510             :         } else {
    2511             :             fstatat_unavailable = 1;
    2512             :         }
    2513             :     } else
    2514             : #endif /* HAVE_FSTATAT */
    2515     1340850 :         result = STAT(path->narrow, &st);
    2516             : #endif /* MS_WINDOWS */
    2517     1488140 :     Py_END_ALLOW_THREADS
    2518             : 
    2519             : #ifdef HAVE_FSTATAT
    2520     1488130 :     if (fstatat_unavailable) {
    2521           0 :         argument_unavailable_error("stat", "dir_fd");
    2522           0 :         return NULL;
    2523             :     }
    2524             : #endif
    2525             : 
    2526     1488130 :     if (result != 0) {
    2527      234504 :         return path_error(path);
    2528             :     }
    2529             : 
    2530     1253630 :     return _pystat_fromstructstat(module, &st);
    2531             : }
    2532             : 
    2533             : /*[python input]
    2534             : 
    2535             : for s in """
    2536             : 
    2537             : FACCESSAT
    2538             : FCHMODAT
    2539             : FCHOWNAT
    2540             : FSTATAT
    2541             : LINKAT
    2542             : MKDIRAT
    2543             : MKFIFOAT
    2544             : MKNODAT
    2545             : OPENAT
    2546             : READLINKAT
    2547             : SYMLINKAT
    2548             : UNLINKAT
    2549             : 
    2550             : """.strip().split():
    2551             :     s = s.strip()
    2552             :     print("""
    2553             : #ifdef HAVE_{s}
    2554             :     #define {s}_DIR_FD_CONVERTER dir_fd_converter
    2555             : #else
    2556             :     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
    2557             : #endif
    2558             : """.rstrip().format(s=s))
    2559             : 
    2560             : for s in """
    2561             : 
    2562             : FCHDIR
    2563             : FCHMOD
    2564             : FCHOWN
    2565             : FDOPENDIR
    2566             : FEXECVE
    2567             : FPATHCONF
    2568             : FSTATVFS
    2569             : FTRUNCATE
    2570             : 
    2571             : """.strip().split():
    2572             :     s = s.strip()
    2573             :     print("""
    2574             : #ifdef HAVE_{s}
    2575             :     #define PATH_HAVE_{s} 1
    2576             : #else
    2577             :     #define PATH_HAVE_{s} 0
    2578             : #endif
    2579             : 
    2580             : """.rstrip().format(s=s))
    2581             : [python start generated code]*/
    2582             : 
    2583             : #ifdef HAVE_FACCESSAT
    2584             :     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
    2585             : #else
    2586             :     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
    2587             : #endif
    2588             : 
    2589             : #ifdef HAVE_FCHMODAT
    2590             :     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
    2591             : #else
    2592             :     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
    2593             : #endif
    2594             : 
    2595             : #ifdef HAVE_FCHOWNAT
    2596             :     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
    2597             : #else
    2598             :     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
    2599             : #endif
    2600             : 
    2601             : #ifdef HAVE_FSTATAT
    2602             :     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
    2603             : #else
    2604             :     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
    2605             : #endif
    2606             : 
    2607             : #ifdef HAVE_LINKAT
    2608             :     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
    2609             : #else
    2610             :     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
    2611             : #endif
    2612             : 
    2613             : #ifdef HAVE_MKDIRAT
    2614             :     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
    2615             : #else
    2616             :     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
    2617             : #endif
    2618             : 
    2619             : #ifdef HAVE_MKFIFOAT
    2620             :     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
    2621             : #else
    2622             :     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
    2623             : #endif
    2624             : 
    2625             : #ifdef HAVE_MKNODAT
    2626             :     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
    2627             : #else
    2628             :     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
    2629             : #endif
    2630             : 
    2631             : #ifdef HAVE_OPENAT
    2632             :     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
    2633             : #else
    2634             :     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
    2635             : #endif
    2636             : 
    2637             : #ifdef HAVE_READLINKAT
    2638             :     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
    2639             : #else
    2640             :     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
    2641             : #endif
    2642             : 
    2643             : #ifdef HAVE_SYMLINKAT
    2644             :     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
    2645             : #else
    2646             :     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
    2647             : #endif
    2648             : 
    2649             : #ifdef HAVE_UNLINKAT
    2650             :     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
    2651             : #else
    2652             :     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
    2653             : #endif
    2654             : 
    2655             : #ifdef HAVE_FCHDIR
    2656             :     #define PATH_HAVE_FCHDIR 1
    2657             : #else
    2658             :     #define PATH_HAVE_FCHDIR 0
    2659             : #endif
    2660             : 
    2661             : #ifdef HAVE_FCHMOD
    2662             :     #define PATH_HAVE_FCHMOD 1
    2663             : #else
    2664             :     #define PATH_HAVE_FCHMOD 0
    2665             : #endif
    2666             : 
    2667             : #ifdef HAVE_FCHOWN
    2668             :     #define PATH_HAVE_FCHOWN 1
    2669             : #else
    2670             :     #define PATH_HAVE_FCHOWN 0
    2671             : #endif
    2672             : 
    2673             : #ifdef HAVE_FDOPENDIR
    2674             :     #define PATH_HAVE_FDOPENDIR 1
    2675             : #else
    2676             :     #define PATH_HAVE_FDOPENDIR 0
    2677             : #endif
    2678             : 
    2679             : #ifdef HAVE_FEXECVE
    2680             :     #define PATH_HAVE_FEXECVE 1
    2681             : #else
    2682             :     #define PATH_HAVE_FEXECVE 0
    2683             : #endif
    2684             : 
    2685             : #ifdef HAVE_FPATHCONF
    2686             :     #define PATH_HAVE_FPATHCONF 1
    2687             : #else
    2688             :     #define PATH_HAVE_FPATHCONF 0
    2689             : #endif
    2690             : 
    2691             : #ifdef HAVE_FSTATVFS
    2692             :     #define PATH_HAVE_FSTATVFS 1
    2693             : #else
    2694             :     #define PATH_HAVE_FSTATVFS 0
    2695             : #endif
    2696             : 
    2697             : #ifdef HAVE_FTRUNCATE
    2698             :     #define PATH_HAVE_FTRUNCATE 1
    2699             : #else
    2700             :     #define PATH_HAVE_FTRUNCATE 0
    2701             : #endif
    2702             : /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
    2703             : 
    2704             : #ifdef MS_WINDOWS
    2705             :     #undef PATH_HAVE_FTRUNCATE
    2706             :     #define PATH_HAVE_FTRUNCATE 1
    2707             : #endif
    2708             : 
    2709             : /*[python input]
    2710             : 
    2711             : class path_t_converter(CConverter):
    2712             : 
    2713             :     type = "path_t"
    2714             :     impl_by_reference = True
    2715             :     parse_by_reference = True
    2716             : 
    2717             :     converter = 'path_converter'
    2718             : 
    2719             :     def converter_init(self, *, allow_fd=False, nullable=False):
    2720             :         # right now path_t doesn't support default values.
    2721             :         # to support a default value, you'll need to override initialize().
    2722             :         if self.default not in (unspecified, None):
    2723             :             fail("Can't specify a default to the path_t converter!")
    2724             : 
    2725             :         if self.c_default not in (None, 'Py_None'):
    2726             :             raise RuntimeError("Can't specify a c_default to the path_t converter!")
    2727             : 
    2728             :         self.nullable = nullable
    2729             :         self.allow_fd = allow_fd
    2730             : 
    2731             :     def pre_render(self):
    2732             :         def strify(value):
    2733             :             if isinstance(value, str):
    2734             :                 return value
    2735             :             return str(int(bool(value)))
    2736             : 
    2737             :         # add self.py_name here when merging with posixmodule conversion
    2738             :         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
    2739             :             self.function.name,
    2740             :             self.name,
    2741             :             strify(self.nullable),
    2742             :             strify(self.allow_fd),
    2743             :             )
    2744             : 
    2745             :     def cleanup(self):
    2746             :         return "path_cleanup(&" + self.name + ");\n"
    2747             : 
    2748             : 
    2749             : class dir_fd_converter(CConverter):
    2750             :     type = 'int'
    2751             : 
    2752             :     def converter_init(self, requires=None):
    2753             :         if self.default in (unspecified, None):
    2754             :             self.c_default = 'DEFAULT_DIR_FD'
    2755             :         if isinstance(requires, str):
    2756             :             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
    2757             :         else:
    2758             :             self.converter = 'dir_fd_converter'
    2759             : 
    2760             : class uid_t_converter(CConverter):
    2761             :     type = "uid_t"
    2762             :     converter = '_Py_Uid_Converter'
    2763             : 
    2764             : class gid_t_converter(CConverter):
    2765             :     type = "gid_t"
    2766             :     converter = '_Py_Gid_Converter'
    2767             : 
    2768             : class dev_t_converter(CConverter):
    2769             :     type = 'dev_t'
    2770             :     converter = '_Py_Dev_Converter'
    2771             : 
    2772             : class dev_t_return_converter(unsigned_long_return_converter):
    2773             :     type = 'dev_t'
    2774             :     conversion_fn = '_PyLong_FromDev'
    2775             :     unsigned_cast = '(dev_t)'
    2776             : 
    2777             : class FSConverter_converter(CConverter):
    2778             :     type = 'PyObject *'
    2779             :     converter = 'PyUnicode_FSConverter'
    2780             :     def converter_init(self):
    2781             :         if self.default is not unspecified:
    2782             :             fail("FSConverter_converter does not support default values")
    2783             :         self.c_default = 'NULL'
    2784             : 
    2785             :     def cleanup(self):
    2786             :         return "Py_XDECREF(" + self.name + ");\n"
    2787             : 
    2788             : class pid_t_converter(CConverter):
    2789             :     type = 'pid_t'
    2790             :     format_unit = '" _Py_PARSE_PID "'
    2791             : 
    2792             : class idtype_t_converter(int_converter):
    2793             :     type = 'idtype_t'
    2794             : 
    2795             : class id_t_converter(CConverter):
    2796             :     type = 'id_t'
    2797             :     format_unit = '" _Py_PARSE_PID "'
    2798             : 
    2799             : class intptr_t_converter(CConverter):
    2800             :     type = 'intptr_t'
    2801             :     format_unit = '" _Py_PARSE_INTPTR "'
    2802             : 
    2803             : class Py_off_t_converter(CConverter):
    2804             :     type = 'Py_off_t'
    2805             :     converter = 'Py_off_t_converter'
    2806             : 
    2807             : class Py_off_t_return_converter(long_return_converter):
    2808             :     type = 'Py_off_t'
    2809             :     conversion_fn = 'PyLong_FromPy_off_t'
    2810             : 
    2811             : class path_confname_converter(CConverter):
    2812             :     type="int"
    2813             :     converter="conv_path_confname"
    2814             : 
    2815             : class confstr_confname_converter(path_confname_converter):
    2816             :     converter='conv_confstr_confname'
    2817             : 
    2818             : class sysconf_confname_converter(path_confname_converter):
    2819             :     converter="conv_sysconf_confname"
    2820             : 
    2821             : [python start generated code]*/
    2822             : /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
    2823             : 
    2824             : /*[clinic input]
    2825             : 
    2826             : os.stat
    2827             : 
    2828             :     path : path_t(allow_fd=True)
    2829             :         Path to be examined; can be string, bytes, a path-like object or
    2830             :         open-file-descriptor int.
    2831             : 
    2832             :     *
    2833             : 
    2834             :     dir_fd : dir_fd(requires='fstatat') = None
    2835             :         If not None, it should be a file descriptor open to a directory,
    2836             :         and path should be a relative string; path will then be relative to
    2837             :         that directory.
    2838             : 
    2839             :     follow_symlinks: bool = True
    2840             :         If False, and the last element of the path is a symbolic link,
    2841             :         stat will examine the symbolic link itself instead of the file
    2842             :         the link points to.
    2843             : 
    2844             : Perform a stat system call on the given path.
    2845             : 
    2846             : dir_fd and follow_symlinks may not be implemented
    2847             :   on your platform.  If they are unavailable, using them will raise a
    2848             :   NotImplementedError.
    2849             : 
    2850             : It's an error to use dir_fd or follow_symlinks when specifying path as
    2851             :   an open file descriptor.
    2852             : 
    2853             : [clinic start generated code]*/
    2854             : 
    2855             : static PyObject *
    2856     1348890 : os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
    2857             : /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
    2858             : {
    2859     1348890 :     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
    2860             : }
    2861             : 
    2862             : 
    2863             : /*[clinic input]
    2864             : os.lstat
    2865             : 
    2866             :     path : path_t
    2867             : 
    2868             :     *
    2869             : 
    2870             :     dir_fd : dir_fd(requires='fstatat') = None
    2871             : 
    2872             : Perform a stat system call on the given path, without following symbolic links.
    2873             : 
    2874             : Like stat(), but do not follow symbolic links.
    2875             : Equivalent to stat(path, follow_symlinks=False).
    2876             : [clinic start generated code]*/
    2877             : 
    2878             : static PyObject *
    2879      139247 : os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
    2880             : /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
    2881             : {
    2882      139247 :     int follow_symlinks = 0;
    2883      139247 :     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
    2884             : }
    2885             : 
    2886             : 
    2887             : /*[clinic input]
    2888             : os.access -> bool
    2889             : 
    2890             :     path: path_t
    2891             :         Path to be tested; can be string, bytes, or a path-like object.
    2892             : 
    2893             :     mode: int
    2894             :         Operating-system mode bitfield.  Can be F_OK to test existence,
    2895             :         or the inclusive-OR of R_OK, W_OK, and X_OK.
    2896             : 
    2897             :     *
    2898             : 
    2899             :     dir_fd : dir_fd(requires='faccessat') = None
    2900             :         If not None, it should be a file descriptor open to a directory,
    2901             :         and path should be relative; path will then be relative to that
    2902             :         directory.
    2903             : 
    2904             :     effective_ids: bool = False
    2905             :         If True, access will use the effective uid/gid instead of
    2906             :         the real uid/gid.
    2907             : 
    2908             :     follow_symlinks: bool = True
    2909             :         If False, and the last element of the path is a symbolic link,
    2910             :         access will examine the symbolic link itself instead of the file
    2911             :         the link points to.
    2912             : 
    2913             : Use the real uid/gid to test for access to a path.
    2914             : 
    2915             : {parameters}
    2916             : dir_fd, effective_ids, and follow_symlinks may not be implemented
    2917             :   on your platform.  If they are unavailable, using them will raise a
    2918             :   NotImplementedError.
    2919             : 
    2920             : Note that most operations will use the effective uid/gid, therefore this
    2921             :   routine can be used in a suid/sgid environment to test if the invoking user
    2922             :   has the specified access to the path.
    2923             : 
    2924             : [clinic start generated code]*/
    2925             : 
    2926             : static int
    2927         163 : os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
    2928             :                int effective_ids, int follow_symlinks)
    2929             : /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
    2930             : {
    2931             :     int return_value;
    2932             : 
    2933             : #ifdef MS_WINDOWS
    2934             :     DWORD attr;
    2935             : #else
    2936             :     int result;
    2937             : #endif
    2938             : 
    2939             : #ifdef HAVE_FACCESSAT
    2940         163 :     int faccessat_unavailable = 0;
    2941             : #endif
    2942             : 
    2943             : #ifndef HAVE_FACCESSAT
    2944             :     if (follow_symlinks_specified("access", follow_symlinks))
    2945             :         return -1;
    2946             : 
    2947             :     if (effective_ids) {
    2948             :         argument_unavailable_error("access", "effective_ids");
    2949             :         return -1;
    2950             :     }
    2951             : #endif
    2952             : 
    2953             : #ifdef MS_WINDOWS
    2954             :     Py_BEGIN_ALLOW_THREADS
    2955             :     attr = GetFileAttributesW(path->wide);
    2956             :     Py_END_ALLOW_THREADS
    2957             : 
    2958             :     /*
    2959             :      * Access is possible if
    2960             :      *   * we didn't get a -1, and
    2961             :      *     * write access wasn't requested,
    2962             :      *     * or the file isn't read-only,
    2963             :      *     * or it's a directory.
    2964             :      * (Directories cannot be read-only on Windows.)
    2965             :     */
    2966             :     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
    2967             :             (!(mode & 2) ||
    2968             :             !(attr & FILE_ATTRIBUTE_READONLY) ||
    2969             :             (attr & FILE_ATTRIBUTE_DIRECTORY));
    2970             : #else
    2971             : 
    2972         163 :     Py_BEGIN_ALLOW_THREADS
    2973             : #ifdef HAVE_FACCESSAT
    2974         163 :     if ((dir_fd != DEFAULT_DIR_FD) ||
    2975         158 :         effective_ids ||
    2976             :         !follow_symlinks) {
    2977             : 
    2978           5 :         if (HAVE_FACCESSAT_RUNTIME) {
    2979           5 :             int flags = 0;
    2980           5 :             if (!follow_symlinks)
    2981           0 :                 flags |= AT_SYMLINK_NOFOLLOW;
    2982           5 :             if (effective_ids)
    2983           4 :                 flags |= AT_EACCESS;
    2984           5 :             result = faccessat(dir_fd, path->narrow, mode, flags);
    2985             :         } else {
    2986             :             faccessat_unavailable = 1;
    2987             :         }
    2988             :     }
    2989             :     else
    2990             : #endif
    2991         158 :         result = access(path->narrow, mode);
    2992         163 :     Py_END_ALLOW_THREADS
    2993             : 
    2994             : #ifdef HAVE_FACCESSAT
    2995         163 :     if (faccessat_unavailable) {
    2996           0 :         if (dir_fd != DEFAULT_DIR_FD) {
    2997           0 :             argument_unavailable_error("access", "dir_fd");
    2998           0 :             return -1;
    2999             :         }
    3000           0 :         if (follow_symlinks_specified("access", follow_symlinks))
    3001           0 :             return -1;
    3002             : 
    3003           0 :         if (effective_ids) {
    3004           0 :             argument_unavailable_error("access", "effective_ids");
    3005           0 :             return -1;
    3006             :         }
    3007             :         /* should be unreachable */
    3008           0 :         return -1;
    3009             :     }
    3010             : #endif
    3011         163 :     return_value = !result;
    3012             : #endif
    3013             : 
    3014         163 :     return return_value;
    3015             : }
    3016             : 
    3017             : #ifndef F_OK
    3018             : #define F_OK 0
    3019             : #endif
    3020             : #ifndef R_OK
    3021             : #define R_OK 4
    3022             : #endif
    3023             : #ifndef W_OK
    3024             : #define W_OK 2
    3025             : #endif
    3026             : #ifndef X_OK
    3027             : #define X_OK 1
    3028             : #endif
    3029             : 
    3030             : 
    3031             : #ifdef HAVE_TTYNAME
    3032             : /*[clinic input]
    3033             : os.ttyname
    3034             : 
    3035             :     fd: int
    3036             :         Integer file descriptor handle.
    3037             : 
    3038             :     /
    3039             : 
    3040             : Return the name of the terminal device connected to 'fd'.
    3041             : [clinic start generated code]*/
    3042             : 
    3043             : static PyObject *
    3044           1 : os_ttyname_impl(PyObject *module, int fd)
    3045             : /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
    3046             : {
    3047             : 
    3048           1 :     long size = sysconf(_SC_TTY_NAME_MAX);
    3049           1 :     if (size == -1) {
    3050           0 :         return posix_error();
    3051             :     }
    3052           1 :     char *buffer = (char *)PyMem_RawMalloc(size);
    3053           1 :     if (buffer == NULL) {
    3054           0 :         return PyErr_NoMemory();
    3055             :     }
    3056           1 :     int ret = ttyname_r(fd, buffer, size);
    3057           1 :     if (ret != 0) {
    3058           1 :         PyMem_RawFree(buffer);
    3059           1 :         errno = ret;
    3060           1 :         return posix_error();
    3061             :     }
    3062           0 :     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
    3063           0 :     PyMem_RawFree(buffer);
    3064           0 :     return res;
    3065             : }
    3066             : #endif
    3067             : 
    3068             : #ifdef HAVE_CTERMID
    3069             : /*[clinic input]
    3070             : os.ctermid
    3071             : 
    3072             : Return the name of the controlling terminal for this process.
    3073             : [clinic start generated code]*/
    3074             : 
    3075             : static PyObject *
    3076           1 : os_ctermid_impl(PyObject *module)
    3077             : /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
    3078             : {
    3079             :     char *ret;
    3080             :     char buffer[L_ctermid];
    3081             : 
    3082             : #ifdef USE_CTERMID_R
    3083             :     ret = ctermid_r(buffer);
    3084             : #else
    3085           1 :     ret = ctermid(buffer);
    3086             : #endif
    3087           1 :     if (ret == NULL)
    3088           0 :         return posix_error();
    3089           1 :     return PyUnicode_DecodeFSDefault(buffer);
    3090             : }
    3091             : #endif /* HAVE_CTERMID */
    3092             : 
    3093             : 
    3094             : /*[clinic input]
    3095             : os.chdir
    3096             : 
    3097             :     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
    3098             : 
    3099             : Change the current working directory to the specified path.
    3100             : 
    3101             : path may always be specified as a string.
    3102             : On some platforms, path may also be specified as an open file descriptor.
    3103             :   If this functionality is unavailable, using it raises an exception.
    3104             : [clinic start generated code]*/
    3105             : 
    3106             : static PyObject *
    3107        3177 : os_chdir_impl(PyObject *module, path_t *path)
    3108             : /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
    3109             : {
    3110             :     int result;
    3111             : 
    3112        3177 :     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
    3113           0 :         return NULL;
    3114             :     }
    3115             : 
    3116        3177 :     Py_BEGIN_ALLOW_THREADS
    3117             : #ifdef MS_WINDOWS
    3118             :     /* on unix, success = 0, on windows, success = !0 */
    3119             :     result = !win32_wchdir(path->wide);
    3120             : #else
    3121             : #ifdef HAVE_FCHDIR
    3122        3177 :     if (path->fd != -1)
    3123           0 :         result = fchdir(path->fd);
    3124             :     else
    3125             : #endif
    3126        3177 :         result = chdir(path->narrow);
    3127             : #endif
    3128        3177 :     Py_END_ALLOW_THREADS
    3129             : 
    3130        3177 :     if (result) {
    3131         190 :         return path_error(path);
    3132             :     }
    3133             : 
    3134        2987 :     Py_RETURN_NONE;
    3135             : }
    3136             : 
    3137             : 
    3138             : #ifdef HAVE_FCHDIR
    3139             : /*[clinic input]
    3140             : os.fchdir
    3141             : 
    3142             :     fd: fildes
    3143             : 
    3144             : Change to the directory of the given file descriptor.
    3145             : 
    3146             : fd must be opened on a directory, not a file.
    3147             : Equivalent to os.chdir(fd).
    3148             : 
    3149             : [clinic start generated code]*/
    3150             : 
    3151             : static PyObject *
    3152           1 : os_fchdir_impl(PyObject *module, int fd)
    3153             : /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
    3154             : {
    3155           1 :     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
    3156           0 :         return NULL;
    3157             :     }
    3158           1 :     return posix_fildes_fd(fd, fchdir);
    3159             : }
    3160             : #endif /* HAVE_FCHDIR */
    3161             : 
    3162             : 
    3163             : /*[clinic input]
    3164             : os.chmod
    3165             : 
    3166             :     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
    3167             :         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
    3168             :         On some platforms, path may also be specified as an open file descriptor.
    3169             :         If this functionality is unavailable, using it raises an exception.
    3170             : 
    3171             :     mode: int
    3172             :         Operating-system mode bitfield.
    3173             : 
    3174             :     *
    3175             : 
    3176             :     dir_fd : dir_fd(requires='fchmodat') = None
    3177             :         If not None, it should be a file descriptor open to a directory,
    3178             :         and path should be relative; path will then be relative to that
    3179             :         directory.
    3180             : 
    3181             :     follow_symlinks: bool = True
    3182             :         If False, and the last element of the path is a symbolic link,
    3183             :         chmod will modify the symbolic link itself instead of the file
    3184             :         the link points to.
    3185             : 
    3186             : Change the access permissions of a file.
    3187             : 
    3188             : It is an error to use dir_fd or follow_symlinks when specifying path as
    3189             :   an open file descriptor.
    3190             : dir_fd and follow_symlinks may not be implemented on your platform.
    3191             :   If they are unavailable, using them will raise a NotImplementedError.
    3192             : 
    3193             : [clinic start generated code]*/
    3194             : 
    3195             : static PyObject *
    3196       14214 : os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
    3197             :               int follow_symlinks)
    3198             : /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
    3199             : {
    3200             :     int result;
    3201             : 
    3202             : #ifdef MS_WINDOWS
    3203             :     DWORD attr;
    3204             : #endif
    3205             : 
    3206             : #ifdef HAVE_FCHMODAT
    3207       14214 :     int fchmodat_nofollow_unsupported = 0;
    3208       14214 :     int fchmodat_unsupported = 0;
    3209             : #endif
    3210             : 
    3211             : #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
    3212             :     if (follow_symlinks_specified("chmod", follow_symlinks))
    3213             :         return NULL;
    3214             : #endif
    3215             : 
    3216       14214 :     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
    3217             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    3218           0 :         return NULL;
    3219             :     }
    3220             : 
    3221             : #ifdef MS_WINDOWS
    3222             :     Py_BEGIN_ALLOW_THREADS
    3223             :     attr = GetFileAttributesW(path->wide);
    3224             :     if (attr == INVALID_FILE_ATTRIBUTES)
    3225             :         result = 0;
    3226             :     else {
    3227             :         if (mode & _S_IWRITE)
    3228             :             attr &= ~FILE_ATTRIBUTE_READONLY;
    3229             :         else
    3230             :             attr |= FILE_ATTRIBUTE_READONLY;
    3231             :         result = SetFileAttributesW(path->wide, attr);
    3232             :     }
    3233             :     Py_END_ALLOW_THREADS
    3234             : 
    3235             :     if (!result) {
    3236             :         return path_error(path);
    3237             :     }
    3238             : #else /* MS_WINDOWS */
    3239       14214 :     Py_BEGIN_ALLOW_THREADS
    3240             : #ifdef HAVE_FCHMOD
    3241       14214 :     if (path->fd != -1)
    3242           0 :         result = fchmod(path->fd, mode);
    3243             :     else
    3244             : #endif /* HAVE_CHMOD */
    3245             : #ifdef HAVE_LCHMOD
    3246             :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    3247             :         result = lchmod(path->narrow, mode);
    3248             :     else
    3249             : #endif /* HAVE_LCHMOD */
    3250             : #ifdef HAVE_FCHMODAT
    3251       14214 :     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
    3252           1 :         if (HAVE_FCHMODAT_RUNTIME) {
    3253             :             /*
    3254             :              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
    3255             :              * The documentation specifically shows how to use it,
    3256             :              * and then says it isn't implemented yet.
    3257             :              * (true on linux with glibc 2.15, and openindiana 3.x)
    3258             :              *
    3259             :              * Once it is supported, os.chmod will automatically
    3260             :              * support dir_fd and follow_symlinks=False.  (Hopefully.)
    3261             :              * Until then, we need to be careful what exception we raise.
    3262             :              */
    3263           1 :             result = fchmodat(dir_fd, path->narrow, mode,
    3264             :                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
    3265             :             /*
    3266             :              * But wait!  We can't throw the exception without allowing threads,
    3267             :              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
    3268             :              */
    3269           1 :             fchmodat_nofollow_unsupported =
    3270           0 :                              result &&
    3271           1 :                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
    3272             :                              !follow_symlinks;
    3273             :         } else {
    3274             :             fchmodat_unsupported = 1;
    3275             :             fchmodat_nofollow_unsupported = 1;
    3276             : 
    3277             :             result = -1;
    3278             :         }
    3279             :     }
    3280             :     else
    3281             : #endif /* HAVE_FHCMODAT */
    3282             :     {
    3283             : #ifdef HAVE_CHMOD
    3284       14213 :         result = chmod(path->narrow, mode);
    3285             : #elif defined(__wasi__)
    3286             :         // WASI SDK 15.0 does not support chmod.
    3287             :         // Ignore missing syscall for now.
    3288             :         result = 0;
    3289             : #else
    3290             :         result = -1;
    3291             :         errno = ENOSYS;
    3292             : #endif
    3293             :     }
    3294       14214 :     Py_END_ALLOW_THREADS
    3295             : 
    3296       14214 :     if (result) {
    3297             : #ifdef HAVE_FCHMODAT
    3298           5 :         if (fchmodat_unsupported) {
    3299           0 :             if (dir_fd != DEFAULT_DIR_FD) {
    3300           0 :                 argument_unavailable_error("chmod", "dir_fd");
    3301           0 :                 return NULL;
    3302             :             }
    3303             :         }
    3304             : 
    3305           5 :         if (fchmodat_nofollow_unsupported) {
    3306           0 :             if (dir_fd != DEFAULT_DIR_FD)
    3307           0 :                 dir_fd_and_follow_symlinks_invalid("chmod",
    3308             :                                                    dir_fd, follow_symlinks);
    3309             :             else
    3310           0 :                 follow_symlinks_specified("chmod", follow_symlinks);
    3311           0 :             return NULL;
    3312             :         }
    3313             :         else
    3314             : #endif /* HAVE_FCHMODAT */
    3315           5 :         return path_error(path);
    3316             :     }
    3317             : #endif /* MS_WINDOWS */
    3318             : 
    3319       14209 :     Py_RETURN_NONE;
    3320             : }
    3321             : 
    3322             : 
    3323             : #ifdef HAVE_FCHMOD
    3324             : /*[clinic input]
    3325             : os.fchmod
    3326             : 
    3327             :     fd: int
    3328             :     mode: int
    3329             : 
    3330             : Change the access permissions of the file given by file descriptor fd.
    3331             : 
    3332             : Equivalent to os.chmod(fd, mode).
    3333             : [clinic start generated code]*/
    3334             : 
    3335             : static PyObject *
    3336           1 : os_fchmod_impl(PyObject *module, int fd, int mode)
    3337             : /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
    3338             : {
    3339             :     int res;
    3340           1 :     int async_err = 0;
    3341             : 
    3342           1 :     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
    3343           0 :         return NULL;
    3344             :     }
    3345             : 
    3346             :     do {
    3347           1 :         Py_BEGIN_ALLOW_THREADS
    3348           1 :         res = fchmod(fd, mode);
    3349           1 :         Py_END_ALLOW_THREADS
    3350           1 :     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    3351           1 :     if (res != 0)
    3352           1 :         return (!async_err) ? posix_error() : NULL;
    3353             : 
    3354           0 :     Py_RETURN_NONE;
    3355             : }
    3356             : #endif /* HAVE_FCHMOD */
    3357             : 
    3358             : 
    3359             : #ifdef HAVE_LCHMOD
    3360             : /*[clinic input]
    3361             : os.lchmod
    3362             : 
    3363             :     path: path_t
    3364             :     mode: int
    3365             : 
    3366             : Change the access permissions of a file, without following symbolic links.
    3367             : 
    3368             : If path is a symlink, this affects the link itself rather than the target.
    3369             : Equivalent to chmod(path, mode, follow_symlinks=False)."
    3370             : [clinic start generated code]*/
    3371             : 
    3372             : static PyObject *
    3373             : os_lchmod_impl(PyObject *module, path_t *path, int mode)
    3374             : /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
    3375             : {
    3376             :     int res;
    3377             :     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
    3378             :         return NULL;
    3379             :     }
    3380             :     Py_BEGIN_ALLOW_THREADS
    3381             :     res = lchmod(path->narrow, mode);
    3382             :     Py_END_ALLOW_THREADS
    3383             :     if (res < 0) {
    3384             :         path_error(path);
    3385             :         return NULL;
    3386             :     }
    3387             :     Py_RETURN_NONE;
    3388             : }
    3389             : #endif /* HAVE_LCHMOD */
    3390             : 
    3391             : 
    3392             : #ifdef HAVE_CHFLAGS
    3393             : /*[clinic input]
    3394             : os.chflags
    3395             : 
    3396             :     path: path_t
    3397             :     flags: unsigned_long(bitwise=True)
    3398             :     follow_symlinks: bool=True
    3399             : 
    3400             : Set file flags.
    3401             : 
    3402             : If follow_symlinks is False, and the last element of the path is a symbolic
    3403             :   link, chflags will change flags on the symbolic link itself instead of the
    3404             :   file the link points to.
    3405             : follow_symlinks may not be implemented on your platform.  If it is
    3406             : unavailable, using it will raise a NotImplementedError.
    3407             : 
    3408             : [clinic start generated code]*/
    3409             : 
    3410             : static PyObject *
    3411             : os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
    3412             :                 int follow_symlinks)
    3413             : /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
    3414             : {
    3415             :     int result;
    3416             : 
    3417             : #ifndef HAVE_LCHFLAGS
    3418             :     if (follow_symlinks_specified("chflags", follow_symlinks))
    3419             :         return NULL;
    3420             : #endif
    3421             : 
    3422             :     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
    3423             :         return NULL;
    3424             :     }
    3425             : 
    3426             :     Py_BEGIN_ALLOW_THREADS
    3427             : #ifdef HAVE_LCHFLAGS
    3428             :     if (!follow_symlinks)
    3429             :         result = lchflags(path->narrow, flags);
    3430             :     else
    3431             : #endif
    3432             :         result = chflags(path->narrow, flags);
    3433             :     Py_END_ALLOW_THREADS
    3434             : 
    3435             :     if (result)
    3436             :         return path_error(path);
    3437             : 
    3438             :     Py_RETURN_NONE;
    3439             : }
    3440             : #endif /* HAVE_CHFLAGS */
    3441             : 
    3442             : 
    3443             : #ifdef HAVE_LCHFLAGS
    3444             : /*[clinic input]
    3445             : os.lchflags
    3446             : 
    3447             :     path: path_t
    3448             :     flags: unsigned_long(bitwise=True)
    3449             : 
    3450             : Set file flags.
    3451             : 
    3452             : This function will not follow symbolic links.
    3453             : Equivalent to chflags(path, flags, follow_symlinks=False).
    3454             : [clinic start generated code]*/
    3455             : 
    3456             : static PyObject *
    3457             : os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
    3458             : /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
    3459             : {
    3460             :     int res;
    3461             :     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
    3462             :         return NULL;
    3463             :     }
    3464             :     Py_BEGIN_ALLOW_THREADS
    3465             :     res = lchflags(path->narrow, flags);
    3466             :     Py_END_ALLOW_THREADS
    3467             :     if (res < 0) {
    3468             :         return path_error(path);
    3469             :     }
    3470             :     Py_RETURN_NONE;
    3471             : }
    3472             : #endif /* HAVE_LCHFLAGS */
    3473             : 
    3474             : 
    3475             : #ifdef HAVE_CHROOT
    3476             : /*[clinic input]
    3477             : os.chroot
    3478             :     path: path_t
    3479             : 
    3480             : Change root directory to path.
    3481             : 
    3482             : [clinic start generated code]*/
    3483             : 
    3484             : static PyObject *
    3485           5 : os_chroot_impl(PyObject *module, path_t *path)
    3486             : /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
    3487             : {
    3488             :     int res;
    3489           5 :     Py_BEGIN_ALLOW_THREADS
    3490           5 :     res = chroot(path->narrow);
    3491           5 :     Py_END_ALLOW_THREADS
    3492           5 :     if (res < 0)
    3493           5 :         return path_error(path);
    3494           0 :     Py_RETURN_NONE;
    3495             : }
    3496             : #endif /* HAVE_CHROOT */
    3497             : 
    3498             : 
    3499             : #ifdef HAVE_FSYNC
    3500             : /*[clinic input]
    3501             : os.fsync
    3502             : 
    3503             :     fd: fildes
    3504             : 
    3505             : Force write of fd to disk.
    3506             : [clinic start generated code]*/
    3507             : 
    3508             : static PyObject *
    3509         559 : os_fsync_impl(PyObject *module, int fd)
    3510             : /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
    3511             : {
    3512         559 :     return posix_fildes_fd(fd, fsync);
    3513             : }
    3514             : #endif /* HAVE_FSYNC */
    3515             : 
    3516             : 
    3517             : #ifdef HAVE_SYNC
    3518             : /*[clinic input]
    3519             : os.sync
    3520             : 
    3521             : Force write of everything to disk.
    3522             : [clinic start generated code]*/
    3523             : 
    3524             : static PyObject *
    3525           1 : os_sync_impl(PyObject *module)
    3526             : /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
    3527             : {
    3528           1 :     Py_BEGIN_ALLOW_THREADS
    3529           1 :     sync();
    3530           1 :     Py_END_ALLOW_THREADS
    3531           1 :     Py_RETURN_NONE;
    3532             : }
    3533             : #endif /* HAVE_SYNC */
    3534             : 
    3535             : 
    3536             : #ifdef HAVE_FDATASYNC
    3537             : #ifdef __hpux
    3538             : extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
    3539             : #endif
    3540             : 
    3541             : /*[clinic input]
    3542             : os.fdatasync
    3543             : 
    3544             :     fd: fildes
    3545             : 
    3546             : Force write of fd to disk without forcing update of metadata.
    3547             : [clinic start generated code]*/
    3548             : 
    3549             : static PyObject *
    3550           1 : os_fdatasync_impl(PyObject *module, int fd)
    3551             : /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
    3552             : {
    3553           1 :     return posix_fildes_fd(fd, fdatasync);
    3554             : }
    3555             : #endif /* HAVE_FDATASYNC */
    3556             : 
    3557             : 
    3558             : #ifdef HAVE_CHOWN
    3559             : /*[clinic input]
    3560             : os.chown
    3561             : 
    3562             :     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
    3563             :         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
    3564             : 
    3565             :     uid: uid_t
    3566             : 
    3567             :     gid: gid_t
    3568             : 
    3569             :     *
    3570             : 
    3571             :     dir_fd : dir_fd(requires='fchownat') = None
    3572             :         If not None, it should be a file descriptor open to a directory,
    3573             :         and path should be relative; path will then be relative to that
    3574             :         directory.
    3575             : 
    3576             :     follow_symlinks: bool = True
    3577             :         If False, and the last element of the path is a symbolic link,
    3578             :         stat will examine the symbolic link itself instead of the file
    3579             :         the link points to.
    3580             : 
    3581             : Change the owner and group id of path to the numeric uid and gid.\
    3582             : 
    3583             : path may always be specified as a string.
    3584             : On some platforms, path may also be specified as an open file descriptor.
    3585             :   If this functionality is unavailable, using it raises an exception.
    3586             : If dir_fd is not None, it should be a file descriptor open to a directory,
    3587             :   and path should be relative; path will then be relative to that directory.
    3588             : If follow_symlinks is False, and the last element of the path is a symbolic
    3589             :   link, chown will modify the symbolic link itself instead of the file the
    3590             :   link points to.
    3591             : It is an error to use dir_fd or follow_symlinks when specifying path as
    3592             :   an open file descriptor.
    3593             : dir_fd and follow_symlinks may not be implemented on your platform.
    3594             :   If they are unavailable, using them will raise a NotImplementedError.
    3595             : 
    3596             : [clinic start generated code]*/
    3597             : 
    3598             : static PyObject *
    3599          28 : os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
    3600             :               int dir_fd, int follow_symlinks)
    3601             : /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
    3602             : {
    3603             :     int result;
    3604             : 
    3605             : #if defined(HAVE_FCHOWNAT)
    3606          28 :     int fchownat_unsupported = 0;
    3607             : #endif
    3608             : 
    3609             : #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
    3610             :     if (follow_symlinks_specified("chown", follow_symlinks))
    3611             :         return NULL;
    3612             : #endif
    3613          56 :     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
    3614          28 :         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
    3615           0 :         return NULL;
    3616             : 
    3617          28 :     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
    3618             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    3619           0 :         return NULL;
    3620             :     }
    3621             : 
    3622          28 :     Py_BEGIN_ALLOW_THREADS
    3623             : #ifdef HAVE_FCHOWN
    3624          28 :     if (path->fd != -1)
    3625           0 :         result = fchown(path->fd, uid, gid);
    3626             :     else
    3627             : #endif
    3628             : #ifdef HAVE_LCHOWN
    3629          28 :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    3630           0 :         result = lchown(path->narrow, uid, gid);
    3631             :     else
    3632             : #endif
    3633             : #ifdef HAVE_FCHOWNAT
    3634          28 :     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
    3635           1 :       if (HAVE_FCHOWNAT_RUNTIME) {
    3636           1 :         result = fchownat(dir_fd, path->narrow, uid, gid,
    3637             :                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
    3638             :       } else {
    3639             :          fchownat_unsupported = 1;
    3640             :       }
    3641             :     } else
    3642             : #endif
    3643          27 :         result = chown(path->narrow, uid, gid);
    3644          28 :     Py_END_ALLOW_THREADS
    3645             : 
    3646             : #ifdef HAVE_FCHOWNAT
    3647          28 :     if (fchownat_unsupported) {
    3648             :         /* This would be incorrect if the current platform
    3649             :          * doesn't support lchown.
    3650             :          */
    3651           0 :         argument_unavailable_error(NULL, "dir_fd");
    3652           0 :         return NULL;
    3653             :     }
    3654             : #endif
    3655             : 
    3656          28 :     if (result)
    3657          10 :         return path_error(path);
    3658             : 
    3659          18 :     Py_RETURN_NONE;
    3660             : }
    3661             : #endif /* HAVE_CHOWN */
    3662             : 
    3663             : 
    3664             : #ifdef HAVE_FCHOWN
    3665             : /*[clinic input]
    3666             : os.fchown
    3667             : 
    3668             :     fd: int
    3669             :     uid: uid_t
    3670             :     gid: gid_t
    3671             : 
    3672             : Change the owner and group id of the file specified by file descriptor.
    3673             : 
    3674             : Equivalent to os.chown(fd, uid, gid).
    3675             : 
    3676             : [clinic start generated code]*/
    3677             : 
    3678             : static PyObject *
    3679           7 : os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
    3680             : /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
    3681             : {
    3682             :     int res;
    3683           7 :     int async_err = 0;
    3684             : 
    3685           7 :     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
    3686           0 :         return NULL;
    3687             :     }
    3688             : 
    3689             :     do {
    3690           7 :         Py_BEGIN_ALLOW_THREADS
    3691           7 :         res = fchown(fd, uid, gid);
    3692           7 :         Py_END_ALLOW_THREADS
    3693           7 :     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    3694           7 :     if (res != 0)
    3695           4 :         return (!async_err) ? posix_error() : NULL;
    3696             : 
    3697           3 :     Py_RETURN_NONE;
    3698             : }
    3699             : #endif /* HAVE_FCHOWN */
    3700             : 
    3701             : 
    3702             : #ifdef HAVE_LCHOWN
    3703             : /*[clinic input]
    3704             : os.lchown
    3705             : 
    3706             :     path : path_t
    3707             :     uid: uid_t
    3708             :     gid: gid_t
    3709             : 
    3710             : Change the owner and group id of path to the numeric uid and gid.
    3711             : 
    3712             : This function will not follow symbolic links.
    3713             : Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
    3714             : [clinic start generated code]*/
    3715             : 
    3716             : static PyObject *
    3717          11 : os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
    3718             : /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
    3719             : {
    3720             :     int res;
    3721          11 :     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
    3722           0 :         return NULL;
    3723             :     }
    3724          11 :     Py_BEGIN_ALLOW_THREADS
    3725          11 :     res = lchown(path->narrow, uid, gid);
    3726          11 :     Py_END_ALLOW_THREADS
    3727          11 :     if (res < 0) {
    3728           8 :         return path_error(path);
    3729             :     }
    3730           3 :     Py_RETURN_NONE;
    3731             : }
    3732             : #endif /* HAVE_LCHOWN */
    3733             : 
    3734             : 
    3735             : static PyObject *
    3736       35707 : posix_getcwd(int use_bytes)
    3737             : {
    3738             : #ifdef MS_WINDOWS
    3739             :     wchar_t wbuf[MAXPATHLEN];
    3740             :     wchar_t *wbuf2 = wbuf;
    3741             :     DWORD len;
    3742             : 
    3743             :     Py_BEGIN_ALLOW_THREADS
    3744             :     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
    3745             :     /* If the buffer is large enough, len does not include the
    3746             :        terminating \0. If the buffer is too small, len includes
    3747             :        the space needed for the terminator. */
    3748             :     if (len >= Py_ARRAY_LENGTH(wbuf)) {
    3749             :         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
    3750             :             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
    3751             :         }
    3752             :         else {
    3753             :             wbuf2 = NULL;
    3754             :         }
    3755             :         if (wbuf2) {
    3756             :             len = GetCurrentDirectoryW(len, wbuf2);
    3757             :         }
    3758             :     }
    3759             :     Py_END_ALLOW_THREADS
    3760             : 
    3761             :     if (!wbuf2) {
    3762             :         PyErr_NoMemory();
    3763             :         return NULL;
    3764             :     }
    3765             :     if (!len) {
    3766             :         if (wbuf2 != wbuf)
    3767             :             PyMem_RawFree(wbuf2);
    3768             :         return PyErr_SetFromWindowsErr(0);
    3769             :     }
    3770             : 
    3771             :     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
    3772             :     if (wbuf2 != wbuf) {
    3773             :         PyMem_RawFree(wbuf2);
    3774             :     }
    3775             : 
    3776             :     if (use_bytes) {
    3777             :         if (resobj == NULL) {
    3778             :             return NULL;
    3779             :         }
    3780             :         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
    3781             :     }
    3782             : 
    3783             :     return resobj;
    3784             : #else
    3785       35707 :     const size_t chunk = 1024;
    3786             : 
    3787       35707 :     char *buf = NULL;
    3788       35707 :     char *cwd = NULL;
    3789       35707 :     size_t buflen = 0;
    3790             : 
    3791       35707 :     Py_BEGIN_ALLOW_THREADS
    3792             :     do {
    3793             :         char *newbuf;
    3794       35713 :         if (buflen <= PY_SSIZE_T_MAX - chunk) {
    3795       35713 :             buflen += chunk;
    3796       35713 :             newbuf = PyMem_RawRealloc(buf, buflen);
    3797             :         }
    3798             :         else {
    3799           0 :             newbuf = NULL;
    3800             :         }
    3801       35713 :         if (newbuf == NULL) {
    3802           0 :             PyMem_RawFree(buf);
    3803           0 :             buf = NULL;
    3804           0 :             break;
    3805             :         }
    3806       35713 :         buf = newbuf;
    3807             : 
    3808       35713 :         cwd = getcwd(buf, buflen);
    3809       35713 :     } while (cwd == NULL && errno == ERANGE);
    3810       35707 :     Py_END_ALLOW_THREADS
    3811             : 
    3812       35707 :     if (buf == NULL) {
    3813           0 :         return PyErr_NoMemory();
    3814             :     }
    3815       35707 :     if (cwd == NULL) {
    3816           4 :         PyMem_RawFree(buf);
    3817           4 :         return posix_error();
    3818             :     }
    3819             : 
    3820             :     PyObject *obj;
    3821       35703 :     if (use_bytes) {
    3822          67 :         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
    3823             :     }
    3824             :     else {
    3825       35636 :         obj = PyUnicode_DecodeFSDefault(buf);
    3826             :     }
    3827       35703 :     PyMem_RawFree(buf);
    3828             : 
    3829       35703 :     return obj;
    3830             : #endif   /* !MS_WINDOWS */
    3831             : }
    3832             : 
    3833             : 
    3834             : /*[clinic input]
    3835             : os.getcwd
    3836             : 
    3837             : Return a unicode string representing the current working directory.
    3838             : [clinic start generated code]*/
    3839             : 
    3840             : static PyObject *
    3841       35640 : os_getcwd_impl(PyObject *module)
    3842             : /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
    3843             : {
    3844       35640 :     return posix_getcwd(0);
    3845             : }
    3846             : 
    3847             : 
    3848             : /*[clinic input]
    3849             : os.getcwdb
    3850             : 
    3851             : Return a bytes string representing the current working directory.
    3852             : [clinic start generated code]*/
    3853             : 
    3854             : static PyObject *
    3855          67 : os_getcwdb_impl(PyObject *module)
    3856             : /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
    3857             : {
    3858          67 :     return posix_getcwd(1);
    3859             : }
    3860             : 
    3861             : 
    3862             : #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
    3863             : #define HAVE_LINK 1
    3864             : #endif
    3865             : 
    3866             : #ifdef HAVE_LINK
    3867             : /*[clinic input]
    3868             : 
    3869             : os.link
    3870             : 
    3871             :     src : path_t
    3872             :     dst : path_t
    3873             :     *
    3874             :     src_dir_fd : dir_fd = None
    3875             :     dst_dir_fd : dir_fd = None
    3876             :     follow_symlinks: bool = True
    3877             : 
    3878             : Create a hard link to a file.
    3879             : 
    3880             : If either src_dir_fd or dst_dir_fd is not None, it should be a file
    3881             :   descriptor open to a directory, and the respective path string (src or dst)
    3882             :   should be relative; the path will then be relative to that directory.
    3883             : If follow_symlinks is False, and the last element of src is a symbolic
    3884             :   link, link will create a link to the symbolic link itself instead of the
    3885             :   file the link points to.
    3886             : src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
    3887             :   platform.  If they are unavailable, using them will raise a
    3888             :   NotImplementedError.
    3889             : [clinic start generated code]*/
    3890             : 
    3891             : static PyObject *
    3892         322 : os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
    3893             :              int dst_dir_fd, int follow_symlinks)
    3894             : /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
    3895             : {
    3896             : #ifdef MS_WINDOWS
    3897             :     BOOL result = FALSE;
    3898             : #else
    3899             :     int result;
    3900             : #endif
    3901             : #if defined(HAVE_LINKAT)
    3902         322 :     int linkat_unavailable = 0;
    3903             : #endif
    3904             : 
    3905             : #ifndef HAVE_LINKAT
    3906             :     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
    3907             :         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
    3908             :         return NULL;
    3909             :     }
    3910             : #endif
    3911             : 
    3912             : #ifndef MS_WINDOWS
    3913         322 :     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
    3914           0 :         PyErr_SetString(PyExc_NotImplementedError,
    3915             :                         "link: src and dst must be the same type");
    3916           0 :         return NULL;
    3917             :     }
    3918             : #endif
    3919             : 
    3920         322 :     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
    3921             :                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
    3922             :                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
    3923           0 :         return NULL;
    3924             :     }
    3925             : 
    3926             : #ifdef MS_WINDOWS
    3927             :     Py_BEGIN_ALLOW_THREADS
    3928             :     result = CreateHardLinkW(dst->wide, src->wide, NULL);
    3929             :     Py_END_ALLOW_THREADS
    3930             : 
    3931             :     if (!result)
    3932             :         return path_error2(src, dst);
    3933             : #else
    3934         322 :     Py_BEGIN_ALLOW_THREADS
    3935             : #ifdef HAVE_LINKAT
    3936         322 :     if ((src_dir_fd != DEFAULT_DIR_FD) ||
    3937         321 :         (dst_dir_fd != DEFAULT_DIR_FD) ||
    3938             :         (!follow_symlinks)) {
    3939             : 
    3940           1 :         if (HAVE_LINKAT_RUNTIME) {
    3941             : 
    3942           1 :             result = linkat(src_dir_fd, src->narrow,
    3943             :                 dst_dir_fd, dst->narrow,
    3944             :                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
    3945             : 
    3946             :         }
    3947             : #ifdef __APPLE__
    3948             :         else {
    3949             :             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
    3950             :                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
    3951             :                 result = link(src->narrow, dst->narrow);
    3952             :             } else {
    3953             :                 linkat_unavailable = 1;
    3954             :             }
    3955             :         }
    3956             : #endif
    3957             :     }
    3958             :     else
    3959             : #endif /* HAVE_LINKAT */
    3960         321 :         result = link(src->narrow, dst->narrow);
    3961         322 :     Py_END_ALLOW_THREADS
    3962             : 
    3963             : #ifdef HAVE_LINKAT
    3964         322 :     if (linkat_unavailable) {
    3965             :         /* Either or both dir_fd arguments were specified */
    3966           0 :         if (src_dir_fd  != DEFAULT_DIR_FD) {
    3967           0 :             argument_unavailable_error("link", "src_dir_fd");
    3968             :         } else {
    3969           0 :             argument_unavailable_error("link", "dst_dir_fd");
    3970             :         }
    3971           0 :         return NULL;
    3972             :     }
    3973             : #endif
    3974             : 
    3975         322 :     if (result)
    3976           6 :         return path_error2(src, dst);
    3977             : #endif /* MS_WINDOWS */
    3978             : 
    3979         316 :     Py_RETURN_NONE;
    3980             : }
    3981             : #endif
    3982             : 
    3983             : 
    3984             : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
    3985             : static PyObject *
    3986             : _listdir_windows_no_opendir(path_t *path, PyObject *list)
    3987             : {
    3988             :     PyObject *v;
    3989             :     HANDLE hFindFile = INVALID_HANDLE_VALUE;
    3990             :     BOOL result;
    3991             :     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
    3992             :     /* only claim to have space for MAX_PATH */
    3993             :     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
    3994             :     wchar_t *wnamebuf = NULL;
    3995             : 
    3996             :     WIN32_FIND_DATAW wFileData;
    3997             :     const wchar_t *po_wchars;
    3998             : 
    3999             :     if (!path->wide) { /* Default arg: "." */
    4000             :         po_wchars = L".";
    4001             :         len = 1;
    4002             :     } else {
    4003             :         po_wchars = path->wide;
    4004             :         len = wcslen(path->wide);
    4005             :     }
    4006             :     /* The +5 is so we can append "\\*.*\0" */
    4007             :     wnamebuf = PyMem_New(wchar_t, len + 5);
    4008             :     if (!wnamebuf) {
    4009             :         PyErr_NoMemory();
    4010             :         goto exit;
    4011             :     }
    4012             :     wcscpy(wnamebuf, po_wchars);
    4013             :     if (len > 0) {
    4014             :         wchar_t wch = wnamebuf[len-1];
    4015             :         if (wch != SEP && wch != ALTSEP && wch != L':')
    4016             :             wnamebuf[len++] = SEP;
    4017             :         wcscpy(wnamebuf + len, L"*.*");
    4018             :     }
    4019             :     if ((list = PyList_New(0)) == NULL) {
    4020             :         goto exit;
    4021             :     }
    4022             :     Py_BEGIN_ALLOW_THREADS
    4023             :     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
    4024             :     Py_END_ALLOW_THREADS
    4025             :     if (hFindFile == INVALID_HANDLE_VALUE) {
    4026             :         int error = GetLastError();
    4027             :         if (error == ERROR_FILE_NOT_FOUND)
    4028             :             goto exit;
    4029             :         Py_DECREF(list);
    4030             :         list = path_error(path);
    4031             :         goto exit;
    4032             :     }
    4033             :     do {
    4034             :         /* Skip over . and .. */
    4035             :         if (wcscmp(wFileData.cFileName, L".") != 0 &&
    4036             :             wcscmp(wFileData.cFileName, L"..") != 0) {
    4037             :             v = PyUnicode_FromWideChar(wFileData.cFileName,
    4038             :                                        wcslen(wFileData.cFileName));
    4039             :             if (path->narrow && v) {
    4040             :                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
    4041             :             }
    4042             :             if (v == NULL) {
    4043             :                 Py_DECREF(list);
    4044             :                 list = NULL;
    4045             :                 break;
    4046             :             }
    4047             :             if (PyList_Append(list, v) != 0) {
    4048             :                 Py_DECREF(v);
    4049             :                 Py_DECREF(list);
    4050             :                 list = NULL;
    4051             :                 break;
    4052             :             }
    4053             :             Py_DECREF(v);
    4054             :         }
    4055             :         Py_BEGIN_ALLOW_THREADS
    4056             :         result = FindNextFileW(hFindFile, &wFileData);
    4057             :         Py_END_ALLOW_THREADS
    4058             :         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
    4059             :            it got to the end of the directory. */
    4060             :         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
    4061             :             Py_DECREF(list);
    4062             :             list = path_error(path);
    4063             :             goto exit;
    4064             :         }
    4065             :     } while (result == TRUE);
    4066             : 
    4067             : exit:
    4068             :     if (hFindFile != INVALID_HANDLE_VALUE) {
    4069             :         if (FindClose(hFindFile) == FALSE) {
    4070             :             if (list != NULL) {
    4071             :                 Py_DECREF(list);
    4072             :                 list = path_error(path);
    4073             :             }
    4074             :         }
    4075             :     }
    4076             :     PyMem_Free(wnamebuf);
    4077             : 
    4078             :     return list;
    4079             : }  /* end of _listdir_windows_no_opendir */
    4080             : 
    4081             : #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
    4082             : 
    4083             : static PyObject *
    4084       37287 : _posix_listdir(path_t *path, PyObject *list)
    4085             : {
    4086             :     PyObject *v;
    4087       37287 :     DIR *dirp = NULL;
    4088             :     struct dirent *ep;
    4089             :     int return_str; /* if false, return bytes */
    4090             : #ifdef HAVE_FDOPENDIR
    4091       37287 :     int fd = -1;
    4092             : #endif
    4093             : 
    4094       37287 :     errno = 0;
    4095             : #ifdef HAVE_FDOPENDIR
    4096       37287 :     if (path->fd != -1) {
    4097             :       if (HAVE_FDOPENDIR_RUNTIME) {
    4098             :         /* closedir() closes the FD, so we duplicate it */
    4099          55 :         fd = _Py_dup(path->fd);
    4100          55 :         if (fd == -1)
    4101           0 :             return NULL;
    4102             : 
    4103          55 :         return_str = 1;
    4104             : 
    4105          55 :         Py_BEGIN_ALLOW_THREADS
    4106          55 :         dirp = fdopendir(fd);
    4107          55 :         Py_END_ALLOW_THREADS
    4108             :       } else {
    4109             :         PyErr_SetString(PyExc_TypeError,
    4110             :             "listdir: path should be string, bytes, os.PathLike or None, not int");
    4111             :         return NULL;
    4112             :       }
    4113             :     }
    4114             :     else
    4115             : #endif
    4116             :     {
    4117             :         const char *name;
    4118       37232 :         if (path->narrow) {
    4119       35138 :             name = path->narrow;
    4120             :             /* only return bytes if they specified a bytes-like object */
    4121       35138 :             return_str = !PyObject_CheckBuffer(path->object);
    4122             :         }
    4123             :         else {
    4124        2094 :             name = ".";
    4125        2094 :             return_str = 1;
    4126             :         }
    4127             : 
    4128       37232 :         Py_BEGIN_ALLOW_THREADS
    4129       37232 :         dirp = opendir(name);
    4130       37232 :         Py_END_ALLOW_THREADS
    4131             :     }
    4132             : 
    4133       37287 :     if (dirp == NULL) {
    4134         526 :         list = path_error(path);
    4135             : #ifdef HAVE_FDOPENDIR
    4136         526 :         if (fd != -1) {
    4137           0 :             Py_BEGIN_ALLOW_THREADS
    4138           0 :             close(fd);
    4139           0 :             Py_END_ALLOW_THREADS
    4140             :         }
    4141             : #endif
    4142         526 :         goto exit;
    4143             :     }
    4144       36761 :     if ((list = PyList_New(0)) == NULL) {
    4145           0 :         goto exit;
    4146             :     }
    4147             :     for (;;) {
    4148     2344280 :         errno = 0;
    4149     2344280 :         Py_BEGIN_ALLOW_THREADS
    4150     2344280 :         ep = readdir(dirp);
    4151     2344280 :         Py_END_ALLOW_THREADS
    4152     2344280 :         if (ep == NULL) {
    4153       36761 :             if (errno == 0) {
    4154       36761 :                 break;
    4155             :             } else {
    4156           0 :                 Py_DECREF(list);
    4157           0 :                 list = path_error(path);
    4158           0 :                 goto exit;
    4159             :             }
    4160             :         }
    4161     2307520 :         if (ep->d_name[0] == '.' &&
    4162       81006 :             (NAMLEN(ep) == 1 ||
    4163       44245 :              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
    4164       73522 :             continue;
    4165     2234000 :         if (return_str)
    4166     2233900 :             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
    4167             :         else
    4168          98 :             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
    4169     2234000 :         if (v == NULL) {
    4170           0 :             Py_CLEAR(list);
    4171           0 :             break;
    4172             :         }
    4173     2234000 :         if (PyList_Append(list, v) != 0) {
    4174           0 :             Py_DECREF(v);
    4175           0 :             Py_CLEAR(list);
    4176           0 :             break;
    4177             :         }
    4178     2234000 :         Py_DECREF(v);
    4179             :     }
    4180             : 
    4181       37287 : exit:
    4182       37287 :     if (dirp != NULL) {
    4183       36761 :         Py_BEGIN_ALLOW_THREADS
    4184             : #ifdef HAVE_FDOPENDIR
    4185       36761 :         if (fd > -1)
    4186          55 :             rewinddir(dirp);
    4187             : #endif
    4188       36761 :         closedir(dirp);
    4189       36761 :         Py_END_ALLOW_THREADS
    4190             :     }
    4191             : 
    4192       37287 :     return list;
    4193             : }  /* end of _posix_listdir */
    4194             : #endif  /* which OS */
    4195             : 
    4196             : 
    4197             : /*[clinic input]
    4198             : os.listdir
    4199             : 
    4200             :     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
    4201             : 
    4202             : Return a list containing the names of the files in the directory.
    4203             : 
    4204             : path can be specified as either str, bytes, or a path-like object.  If path is bytes,
    4205             :   the filenames returned will also be bytes; in all other circumstances
    4206             :   the filenames returned will be str.
    4207             : If path is None, uses the path='.'.
    4208             : On some platforms, path may also be specified as an open file descriptor;\
    4209             :   the file descriptor must refer to a directory.
    4210             :   If this functionality is unavailable, using it raises NotImplementedError.
    4211             : 
    4212             : The list is in arbitrary order.  It does not include the special
    4213             : entries '.' and '..' even if they are present in the directory.
    4214             : 
    4215             : 
    4216             : [clinic start generated code]*/
    4217             : 
    4218             : static PyObject *
    4219       37287 : os_listdir_impl(PyObject *module, path_t *path)
    4220             : /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
    4221             : {
    4222       37287 :     if (PySys_Audit("os.listdir", "O",
    4223       37287 :                     path->object ? path->object : Py_None) < 0) {
    4224           0 :         return NULL;
    4225             :     }
    4226             : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
    4227             :     return _listdir_windows_no_opendir(path, NULL);
    4228             : #else
    4229       37287 :     return _posix_listdir(path, NULL);
    4230             : #endif
    4231             : }
    4232             : 
    4233             : #ifdef MS_WINDOWS
    4234             : int
    4235             : _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
    4236             : {
    4237             :     wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
    4238             :     DWORD result;
    4239             : 
    4240             :     result = GetFullPathNameW(path,
    4241             :                               Py_ARRAY_LENGTH(woutbuf), woutbuf,
    4242             :                               NULL);
    4243             :     if (!result) {
    4244             :         return -1;
    4245             :     }
    4246             : 
    4247             :     if (result >= Py_ARRAY_LENGTH(woutbuf)) {
    4248             :         if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
    4249             :             woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
    4250             :         }
    4251             :         else {
    4252             :             woutbufp = NULL;
    4253             :         }
    4254             :         if (!woutbufp) {
    4255             :             *abspath_p = NULL;
    4256             :             return 0;
    4257             :         }
    4258             : 
    4259             :         result = GetFullPathNameW(path, result, woutbufp, NULL);
    4260             :         if (!result) {
    4261             :             PyMem_RawFree(woutbufp);
    4262             :             return -1;
    4263             :         }
    4264             :     }
    4265             : 
    4266             :     if (woutbufp != woutbuf) {
    4267             :         *abspath_p = woutbufp;
    4268             :         return 0;
    4269             :     }
    4270             : 
    4271             :     *abspath_p = _PyMem_RawWcsdup(woutbufp);
    4272             :     return 0;
    4273             : }
    4274             : 
    4275             : 
    4276             : /* A helper function for abspath on win32 */
    4277             : /*[clinic input]
    4278             : os._getfullpathname
    4279             : 
    4280             :     path: path_t
    4281             :     /
    4282             : 
    4283             : [clinic start generated code]*/
    4284             : 
    4285             : static PyObject *
    4286             : os__getfullpathname_impl(PyObject *module, path_t *path)
    4287             : /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
    4288             : {
    4289             :     wchar_t *abspath;
    4290             : 
    4291             :     if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
    4292             :         return win32_error_object("GetFullPathNameW", path->object);
    4293             :     }
    4294             :     if (abspath == NULL) {
    4295             :         return PyErr_NoMemory();
    4296             :     }
    4297             : 
    4298             :     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
    4299             :     PyMem_RawFree(abspath);
    4300             :     if (str == NULL) {
    4301             :         return NULL;
    4302             :     }
    4303             :     if (path->narrow) {
    4304             :         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
    4305             :     }
    4306             :     return str;
    4307             : }
    4308             : 
    4309             : 
    4310             : /*[clinic input]
    4311             : os._getfinalpathname
    4312             : 
    4313             :     path: path_t
    4314             :     /
    4315             : 
    4316             : A helper function for samepath on windows.
    4317             : [clinic start generated code]*/
    4318             : 
    4319             : static PyObject *
    4320             : os__getfinalpathname_impl(PyObject *module, path_t *path)
    4321             : /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
    4322             : {
    4323             :     HANDLE hFile;
    4324             :     wchar_t buf[MAXPATHLEN], *target_path = buf;
    4325             :     int buf_size = Py_ARRAY_LENGTH(buf);
    4326             :     int result_length;
    4327             :     PyObject *result;
    4328             : 
    4329             :     Py_BEGIN_ALLOW_THREADS
    4330             :     hFile = CreateFileW(
    4331             :         path->wide,
    4332             :         0, /* desired access */
    4333             :         0, /* share mode */
    4334             :         NULL, /* security attributes */
    4335             :         OPEN_EXISTING,
    4336             :         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
    4337             :         FILE_FLAG_BACKUP_SEMANTICS,
    4338             :         NULL);
    4339             :     Py_END_ALLOW_THREADS
    4340             : 
    4341             :     if (hFile == INVALID_HANDLE_VALUE) {
    4342             :         return win32_error_object("CreateFileW", path->object);
    4343             :     }
    4344             : 
    4345             :     /* We have a good handle to the target, use it to determine the
    4346             :        target path name. */
    4347             :     while (1) {
    4348             :         Py_BEGIN_ALLOW_THREADS
    4349             :         result_length = GetFinalPathNameByHandleW(hFile, target_path,
    4350             :                                                   buf_size, VOLUME_NAME_DOS);
    4351             :         Py_END_ALLOW_THREADS
    4352             : 
    4353             :         if (!result_length) {
    4354             :             result = win32_error_object("GetFinalPathNameByHandleW",
    4355             :                                          path->object);
    4356             :             goto cleanup;
    4357             :         }
    4358             : 
    4359             :         if (result_length < buf_size) {
    4360             :             break;
    4361             :         }
    4362             : 
    4363             :         wchar_t *tmp;
    4364             :         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
    4365             :                             result_length * sizeof(*tmp));
    4366             :         if (!tmp) {
    4367             :             result = PyErr_NoMemory();
    4368             :             goto cleanup;
    4369             :         }
    4370             : 
    4371             :         buf_size = result_length;
    4372             :         target_path = tmp;
    4373             :     }
    4374             : 
    4375             :     result = PyUnicode_FromWideChar(target_path, result_length);
    4376             :     if (result && path->narrow) {
    4377             :         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
    4378             :     }
    4379             : 
    4380             : cleanup:
    4381             :     if (target_path != buf) {
    4382             :         PyMem_Free(target_path);
    4383             :     }
    4384             :     CloseHandle(hFile);
    4385             :     return result;
    4386             : }
    4387             : 
    4388             : 
    4389             : /*[clinic input]
    4390             : os._getvolumepathname
    4391             : 
    4392             :     path: path_t
    4393             : 
    4394             : A helper function for ismount on Win32.
    4395             : [clinic start generated code]*/
    4396             : 
    4397             : static PyObject *
    4398             : os__getvolumepathname_impl(PyObject *module, path_t *path)
    4399             : /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
    4400             : {
    4401             :     PyObject *result;
    4402             :     wchar_t *mountpath=NULL;
    4403             :     size_t buflen;
    4404             :     BOOL ret;
    4405             : 
    4406             :     /* Volume path should be shorter than entire path */
    4407             :     buflen = Py_MAX(path->length, MAX_PATH);
    4408             : 
    4409             :     if (buflen > PY_DWORD_MAX) {
    4410             :         PyErr_SetString(PyExc_OverflowError, "path too long");
    4411             :         return NULL;
    4412             :     }
    4413             : 
    4414             :     mountpath = PyMem_New(wchar_t, buflen);
    4415             :     if (mountpath == NULL)
    4416             :         return PyErr_NoMemory();
    4417             : 
    4418             :     Py_BEGIN_ALLOW_THREADS
    4419             :     ret = GetVolumePathNameW(path->wide, mountpath,
    4420             :                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
    4421             :     Py_END_ALLOW_THREADS
    4422             : 
    4423             :     if (!ret) {
    4424             :         result = win32_error_object("_getvolumepathname", path->object);
    4425             :         goto exit;
    4426             :     }
    4427             :     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
    4428             :     if (path->narrow)
    4429             :         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
    4430             : 
    4431             : exit:
    4432             :     PyMem_Free(mountpath);
    4433             :     return result;
    4434             : }
    4435             : 
    4436             : 
    4437             : /*[clinic input]
    4438             : os._path_splitroot
    4439             : 
    4440             :     path: path_t
    4441             : 
    4442             : Removes everything after the root on Win32.
    4443             : [clinic start generated code]*/
    4444             : 
    4445             : static PyObject *
    4446             : os__path_splitroot_impl(PyObject *module, path_t *path)
    4447             : /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
    4448             : {
    4449             :     wchar_t *buffer;
    4450             :     wchar_t *end;
    4451             :     PyObject *result = NULL;
    4452             :     HRESULT ret;
    4453             : 
    4454             :     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
    4455             :     if (!buffer) {
    4456             :         return NULL;
    4457             :     }
    4458             :     wcscpy(buffer, path->wide);
    4459             :     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
    4460             :         *p = L'\\';
    4461             :     }
    4462             : 
    4463             :     Py_BEGIN_ALLOW_THREADS
    4464             :     ret = PathCchSkipRoot(buffer, &end);
    4465             :     Py_END_ALLOW_THREADS
    4466             :     if (FAILED(ret)) {
    4467             :         result = Py_BuildValue("sO", "", path->object);
    4468             :     } else if (end != buffer) {
    4469             :         size_t rootLen = (size_t)(end - buffer);
    4470             :         result = Py_BuildValue("NN",
    4471             :             PyUnicode_FromWideChar(path->wide, rootLen),
    4472             :             PyUnicode_FromWideChar(path->wide + rootLen, -1)
    4473             :         );
    4474             :     } else {
    4475             :         result = Py_BuildValue("Os", path->object, "");
    4476             :     }
    4477             :     PyMem_Free(buffer);
    4478             : 
    4479             :     return result;
    4480             : }
    4481             : 
    4482             : 
    4483             : #endif /* MS_WINDOWS */
    4484             : 
    4485             : 
    4486             : /*[clinic input]
    4487             : os._path_normpath
    4488             : 
    4489             :     path: object
    4490             : 
    4491             : Basic path normalization.
    4492             : [clinic start generated code]*/
    4493             : 
    4494             : static PyObject *
    4495      152965 : os__path_normpath_impl(PyObject *module, PyObject *path)
    4496             : /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
    4497             : {
    4498      152965 :     if (!PyUnicode_Check(path)) {
    4499           0 :         PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
    4500           0 :             Py_TYPE(path)->tp_name);
    4501           0 :         return NULL;
    4502             :     }
    4503             :     Py_ssize_t len;
    4504      152965 :     wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
    4505      152965 :     if (!buffer) {
    4506           0 :         return NULL;
    4507             :     }
    4508      152965 :     PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
    4509      152965 :     PyMem_Free(buffer);
    4510      152965 :     return result;
    4511             : }
    4512             : 
    4513             : /*[clinic input]
    4514             : os.mkdir
    4515             : 
    4516             :     path : path_t
    4517             : 
    4518             :     mode: int = 0o777
    4519             : 
    4520             :     *
    4521             : 
    4522             :     dir_fd : dir_fd(requires='mkdirat') = None
    4523             : 
    4524             : # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
    4525             : 
    4526             : Create a directory.
    4527             : 
    4528             : If dir_fd is not None, it should be a file descriptor open to a directory,
    4529             :   and path should be relative; path will then be relative to that directory.
    4530             : dir_fd may not be implemented on your platform.
    4531             :   If it is unavailable, using it will raise a NotImplementedError.
    4532             : 
    4533             : The mode argument is ignored on Windows.
    4534             : [clinic start generated code]*/
    4535             : 
    4536             : static PyObject *
    4537       17676 : os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
    4538             : /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
    4539             : {
    4540             :     int result;
    4541             : #ifdef HAVE_MKDIRAT
    4542       17676 :     int mkdirat_unavailable = 0;
    4543             : #endif
    4544             : 
    4545       17676 :     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
    4546             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    4547           0 :         return NULL;
    4548             :     }
    4549             : 
    4550             : #ifdef MS_WINDOWS
    4551             :     Py_BEGIN_ALLOW_THREADS
    4552             :     result = CreateDirectoryW(path->wide, NULL);
    4553             :     Py_END_ALLOW_THREADS
    4554             : 
    4555             :     if (!result)
    4556             :         return path_error(path);
    4557             : #else
    4558       17676 :     Py_BEGIN_ALLOW_THREADS
    4559             : #if HAVE_MKDIRAT
    4560       17676 :     if (dir_fd != DEFAULT_DIR_FD) {
    4561             :       if (HAVE_MKDIRAT_RUNTIME) {
    4562           1 :         result = mkdirat(dir_fd, path->narrow, mode);
    4563             : 
    4564             :       } else {
    4565             :         mkdirat_unavailable = 1;
    4566             :       }
    4567             :     } else
    4568             : #endif
    4569             : #if defined(__WATCOMC__) && !defined(__QNX__)
    4570             :         result = mkdir(path->narrow);
    4571             : #else
    4572       17675 :         result = mkdir(path->narrow, mode);
    4573             : #endif
    4574       17676 :     Py_END_ALLOW_THREADS
    4575             : 
    4576             : #if HAVE_MKDIRAT
    4577       17676 :     if (mkdirat_unavailable) {
    4578           0 :         argument_unavailable_error(NULL, "dir_fd");
    4579           0 :         return NULL;
    4580             :     }
    4581             : #endif
    4582             : 
    4583       17676 :     if (result < 0)
    4584        7686 :         return path_error(path);
    4585             : #endif /* MS_WINDOWS */
    4586        9990 :     Py_RETURN_NONE;
    4587             : }
    4588             : 
    4589             : 
    4590             : /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
    4591             : #if defined(HAVE_SYS_RESOURCE_H)
    4592             : #include <sys/resource.h>
    4593             : #endif
    4594             : 
    4595             : 
    4596             : #ifdef HAVE_NICE
    4597             : /*[clinic input]
    4598             : os.nice
    4599             : 
    4600             :     increment: int
    4601             :     /
    4602             : 
    4603             : Add increment to the priority of process and return the new priority.
    4604             : [clinic start generated code]*/
    4605             : 
    4606             : static PyObject *
    4607           0 : os_nice_impl(PyObject *module, int increment)
    4608             : /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
    4609             : {
    4610             :     int value;
    4611             : 
    4612             :     /* There are two flavours of 'nice': one that returns the new
    4613             :        priority (as required by almost all standards out there) and the
    4614             :        Linux/FreeBSD one, which returns '0' on success and advices
    4615             :        the use of getpriority() to get the new priority.
    4616             : 
    4617             :        If we are of the nice family that returns the new priority, we
    4618             :        need to clear errno before the call, and check if errno is filled
    4619             :        before calling posix_error() on a returnvalue of -1, because the
    4620             :        -1 may be the actual new priority! */
    4621             : 
    4622           0 :     errno = 0;
    4623           0 :     value = nice(increment);
    4624             : #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
    4625             :     if (value == 0)
    4626             :         value = getpriority(PRIO_PROCESS, 0);
    4627             : #endif
    4628           0 :     if (value == -1 && errno != 0)
    4629             :         /* either nice() or getpriority() returned an error */
    4630           0 :         return posix_error();
    4631           0 :     return PyLong_FromLong((long) value);
    4632             : }
    4633             : #endif /* HAVE_NICE */
    4634             : 
    4635             : 
    4636             : #ifdef HAVE_GETPRIORITY
    4637             : /*[clinic input]
    4638             : os.getpriority
    4639             : 
    4640             :     which: int
    4641             :     who: int
    4642             : 
    4643             : Return program scheduling priority.
    4644             : [clinic start generated code]*/
    4645             : 
    4646             : static PyObject *
    4647           2 : os_getpriority_impl(PyObject *module, int which, int who)
    4648             : /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
    4649             : {
    4650             :     int retval;
    4651             : 
    4652           2 :     errno = 0;
    4653           2 :     retval = getpriority(which, who);
    4654           2 :     if (errno != 0)
    4655           0 :         return posix_error();
    4656           2 :     return PyLong_FromLong((long)retval);
    4657             : }
    4658             : #endif /* HAVE_GETPRIORITY */
    4659             : 
    4660             : 
    4661             : #ifdef HAVE_SETPRIORITY
    4662             : /*[clinic input]
    4663             : os.setpriority
    4664             : 
    4665             :     which: int
    4666             :     who: int
    4667             :     priority: int
    4668             : 
    4669             : Set program scheduling priority.
    4670             : [clinic start generated code]*/
    4671             : 
    4672             : static PyObject *
    4673           2 : os_setpriority_impl(PyObject *module, int which, int who, int priority)
    4674             : /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
    4675             : {
    4676             :     int retval;
    4677             : 
    4678           2 :     retval = setpriority(which, who, priority);
    4679           2 :     if (retval == -1)
    4680           1 :         return posix_error();
    4681           1 :     Py_RETURN_NONE;
    4682             : }
    4683             : #endif /* HAVE_SETPRIORITY */
    4684             : 
    4685             : 
    4686             : static PyObject *
    4687        8476 : internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
    4688             : {
    4689        8476 :     const char *function_name = is_replace ? "replace" : "rename";
    4690             :     int dir_fd_specified;
    4691             : 
    4692             : #ifdef HAVE_RENAMEAT
    4693        8476 :     int renameat_unavailable = 0;
    4694             : #endif
    4695             : 
    4696             : #ifdef MS_WINDOWS
    4697             :     BOOL result;
    4698             :     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
    4699             : #else
    4700             :     int result;
    4701             : #endif
    4702             : 
    4703        8476 :     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
    4704             :                        (dst_dir_fd != DEFAULT_DIR_FD);
    4705             : #ifndef HAVE_RENAMEAT
    4706             :     if (dir_fd_specified) {
    4707             :         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
    4708             :         return NULL;
    4709             :     }
    4710             : #endif
    4711             : 
    4712        8476 :     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
    4713             :                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
    4714             :                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
    4715           0 :         return NULL;
    4716             :     }
    4717             : 
    4718             : #ifdef MS_WINDOWS
    4719             :     Py_BEGIN_ALLOW_THREADS
    4720             :     result = MoveFileExW(src->wide, dst->wide, flags);
    4721             :     Py_END_ALLOW_THREADS
    4722             : 
    4723             :     if (!result)
    4724             :         return path_error2(src, dst);
    4725             : 
    4726             : #else
    4727        8476 :     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
    4728           0 :         PyErr_Format(PyExc_ValueError,
    4729             :                      "%s: src and dst must be the same type", function_name);
    4730           0 :         return NULL;
    4731             :     }
    4732             : 
    4733        8476 :     Py_BEGIN_ALLOW_THREADS
    4734             : #ifdef HAVE_RENAMEAT
    4735        8476 :     if (dir_fd_specified) {
    4736             :         if (HAVE_RENAMEAT_RUNTIME) {
    4737           1 :             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
    4738             :         } else {
    4739             :             renameat_unavailable = 1;
    4740             :         }
    4741             :     } else
    4742             : #endif
    4743        8475 :     result = rename(src->narrow, dst->narrow);
    4744        8476 :     Py_END_ALLOW_THREADS
    4745             : 
    4746             : 
    4747             : #ifdef HAVE_RENAMEAT
    4748        8476 :     if (renameat_unavailable) {
    4749           0 :         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
    4750           0 :         return NULL;
    4751             :     }
    4752             : #endif
    4753             : 
    4754        8476 :     if (result)
    4755         121 :         return path_error2(src, dst);
    4756             : #endif
    4757        8355 :     Py_RETURN_NONE;
    4758             : }
    4759             : 
    4760             : 
    4761             : /*[clinic input]
    4762             : os.rename
    4763             : 
    4764             :     src : path_t
    4765             :     dst : path_t
    4766             :     *
    4767             :     src_dir_fd : dir_fd = None
    4768             :     dst_dir_fd : dir_fd = None
    4769             : 
    4770             : Rename a file or directory.
    4771             : 
    4772             : If either src_dir_fd or dst_dir_fd is not None, it should be a file
    4773             :   descriptor open to a directory, and the respective path string (src or dst)
    4774             :   should be relative; the path will then be relative to that directory.
    4775             : src_dir_fd and dst_dir_fd, may not be implemented on your platform.
    4776             :   If they are unavailable, using them will raise a NotImplementedError.
    4777             : [clinic start generated code]*/
    4778             : 
    4779             : static PyObject *
    4780         931 : os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
    4781             :                int dst_dir_fd)
    4782             : /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
    4783             : {
    4784         931 :     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
    4785             : }
    4786             : 
    4787             : 
    4788             : /*[clinic input]
    4789             : os.replace = os.rename
    4790             : 
    4791             : Rename a file or directory, overwriting the destination.
    4792             : 
    4793             : If either src_dir_fd or dst_dir_fd is not None, it should be a file
    4794             :   descriptor open to a directory, and the respective path string (src or dst)
    4795             :   should be relative; the path will then be relative to that directory.
    4796             : src_dir_fd and dst_dir_fd, may not be implemented on your platform.
    4797             :   If they are unavailable, using them will raise a NotImplementedError.
    4798             : [clinic start generated code]*/
    4799             : 
    4800             : static PyObject *
    4801        7545 : os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
    4802             :                 int dst_dir_fd)
    4803             : /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
    4804             : {
    4805        7545 :     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
    4806             : }
    4807             : 
    4808             : 
    4809             : /*[clinic input]
    4810             : os.rmdir
    4811             : 
    4812             :     path: path_t
    4813             :     *
    4814             :     dir_fd: dir_fd(requires='unlinkat') = None
    4815             : 
    4816             : Remove a directory.
    4817             : 
    4818             : If dir_fd is not None, it should be a file descriptor open to a directory,
    4819             :   and path should be relative; path will then be relative to that directory.
    4820             : dir_fd may not be implemented on your platform.
    4821             :   If it is unavailable, using it will raise a NotImplementedError.
    4822             : [clinic start generated code]*/
    4823             : 
    4824             : static PyObject *
    4825       10658 : os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
    4826             : /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
    4827             : {
    4828             :     int result;
    4829             : #ifdef HAVE_UNLINKAT
    4830       10658 :     int unlinkat_unavailable = 0;
    4831             : #endif
    4832             : 
    4833       10658 :     if (PySys_Audit("os.rmdir", "Oi", path->object,
    4834             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    4835           0 :         return NULL;
    4836             :     }
    4837             : 
    4838       10658 :     Py_BEGIN_ALLOW_THREADS
    4839             : #ifdef MS_WINDOWS
    4840             :     /* Windows, success=1, UNIX, success=0 */
    4841             :     result = !RemoveDirectoryW(path->wide);
    4842             : #else
    4843             : #ifdef HAVE_UNLINKAT
    4844       10658 :     if (dir_fd != DEFAULT_DIR_FD) {
    4845             :       if (HAVE_UNLINKAT_RUNTIME) {
    4846        5809 :         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
    4847             :       } else {
    4848             :         unlinkat_unavailable = 1;
    4849             :         result = -1;
    4850             :       }
    4851             :     } else
    4852             : #endif
    4853        4849 :         result = rmdir(path->narrow);
    4854             : #endif
    4855       10658 :     Py_END_ALLOW_THREADS
    4856             : 
    4857             : #ifdef HAVE_UNLINKAT
    4858       10658 :     if (unlinkat_unavailable) {
    4859           0 :         argument_unavailable_error("rmdir", "dir_fd");
    4860           0 :         return NULL;
    4861             :     }
    4862             : #endif
    4863             : 
    4864       10658 :     if (result)
    4865         409 :         return path_error(path);
    4866             : 
    4867       10249 :     Py_RETURN_NONE;
    4868             : }
    4869             : 
    4870             : 
    4871             : #ifdef HAVE_SYSTEM
    4872             : #ifdef MS_WINDOWS
    4873             : /*[clinic input]
    4874             : os.system -> long
    4875             : 
    4876             :     command: Py_UNICODE
    4877             : 
    4878             : Execute the command in a subshell.
    4879             : [clinic start generated code]*/
    4880             : 
    4881             : static long
    4882             : os_system_impl(PyObject *module, const Py_UNICODE *command)
    4883             : /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
    4884             : {
    4885             :     long result;
    4886             : 
    4887             :     if (PySys_Audit("os.system", "(u)", command) < 0) {
    4888             :         return -1;
    4889             :     }
    4890             : 
    4891             :     Py_BEGIN_ALLOW_THREADS
    4892             :     _Py_BEGIN_SUPPRESS_IPH
    4893             :     result = _wsystem(command);
    4894             :     _Py_END_SUPPRESS_IPH
    4895             :     Py_END_ALLOW_THREADS
    4896             :     return result;
    4897             : }
    4898             : #else /* MS_WINDOWS */
    4899             : /*[clinic input]
    4900             : os.system -> long
    4901             : 
    4902             :     command: FSConverter
    4903             : 
    4904             : Execute the command in a subshell.
    4905             : [clinic start generated code]*/
    4906             : 
    4907             : static long
    4908           5 : os_system_impl(PyObject *module, PyObject *command)
    4909             : /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
    4910             : {
    4911             :     long result;
    4912           5 :     const char *bytes = PyBytes_AsString(command);
    4913             : 
    4914           5 :     if (PySys_Audit("os.system", "(O)", command) < 0) {
    4915           0 :         return -1;
    4916             :     }
    4917             : 
    4918           5 :     Py_BEGIN_ALLOW_THREADS
    4919           5 :     result = system(bytes);
    4920           5 :     Py_END_ALLOW_THREADS
    4921           5 :     return result;
    4922             : }
    4923             : #endif
    4924             : #endif /* HAVE_SYSTEM */
    4925             : 
    4926             : 
    4927             : #ifdef HAVE_UMASK
    4928             : /*[clinic input]
    4929             : os.umask
    4930             : 
    4931             :     mask: int
    4932             :     /
    4933             : 
    4934             : Set the current numeric umask and return the previous umask.
    4935             : [clinic start generated code]*/
    4936             : 
    4937             : static PyObject *
    4938         502 : os_umask_impl(PyObject *module, int mask)
    4939             : /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
    4940             : {
    4941         502 :     int i = (int)umask(mask);
    4942         502 :     if (i < 0)
    4943           0 :         return posix_error();
    4944         502 :     return PyLong_FromLong((long)i);
    4945             : }
    4946             : #endif
    4947             : 
    4948             : #ifdef MS_WINDOWS
    4949             : 
    4950             : /* override the default DeleteFileW behavior so that directory
    4951             : symlinks can be removed with this function, the same as with
    4952             : Unix symlinks */
    4953             : BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
    4954             : {
    4955             :     WIN32_FILE_ATTRIBUTE_DATA info;
    4956             :     WIN32_FIND_DATAW find_data;
    4957             :     HANDLE find_data_handle;
    4958             :     int is_directory = 0;
    4959             :     int is_link = 0;
    4960             : 
    4961             :     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
    4962             :         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
    4963             : 
    4964             :         /* Get WIN32_FIND_DATA structure for the path to determine if
    4965             :            it is a symlink */
    4966             :         if(is_directory &&
    4967             :            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    4968             :             find_data_handle = FindFirstFileW(lpFileName, &find_data);
    4969             : 
    4970             :             if(find_data_handle != INVALID_HANDLE_VALUE) {
    4971             :                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
    4972             :                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
    4973             :                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
    4974             :                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
    4975             :                 FindClose(find_data_handle);
    4976             :             }
    4977             :         }
    4978             :     }
    4979             : 
    4980             :     if (is_directory && is_link)
    4981             :         return RemoveDirectoryW(lpFileName);
    4982             : 
    4983             :     return DeleteFileW(lpFileName);
    4984             : }
    4985             : #endif /* MS_WINDOWS */
    4986             : 
    4987             : 
    4988             : /*[clinic input]
    4989             : os.unlink
    4990             : 
    4991             :     path: path_t
    4992             :     *
    4993             :     dir_fd: dir_fd(requires='unlinkat')=None
    4994             : 
    4995             : Remove a file (same as remove()).
    4996             : 
    4997             : If dir_fd is not None, it should be a file descriptor open to a directory,
    4998             :   and path should be relative; path will then be relative to that directory.
    4999             : dir_fd may not be implemented on your platform.
    5000             :   If it is unavailable, using it will raise a NotImplementedError.
    5001             : 
    5002             : [clinic start generated code]*/
    5003             : 
    5004             : static PyObject *
    5005       51699 : os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
    5006             : /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
    5007             : {
    5008             :     int result;
    5009             : #ifdef HAVE_UNLINKAT
    5010       51699 :     int unlinkat_unavailable = 0;
    5011             : #endif
    5012             : 
    5013       51699 :     if (PySys_Audit("os.remove", "Oi", path->object,
    5014             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    5015           0 :         return NULL;
    5016             :     }
    5017             : 
    5018       51699 :     Py_BEGIN_ALLOW_THREADS
    5019             :     _Py_BEGIN_SUPPRESS_IPH
    5020             : #ifdef MS_WINDOWS
    5021             :     /* Windows, success=1, UNIX, success=0 */
    5022             :     result = !Py_DeleteFileW(path->wide);
    5023             : #else
    5024             : #ifdef HAVE_UNLINKAT
    5025       51699 :     if (dir_fd != DEFAULT_DIR_FD) {
    5026             :       if (HAVE_UNLINKAT_RUNTIME) {
    5027             : 
    5028       33538 :         result = unlinkat(dir_fd, path->narrow, 0);
    5029             :       } else {
    5030             :         unlinkat_unavailable = 1;
    5031             :       }
    5032             :     } else
    5033             : #endif /* HAVE_UNLINKAT */
    5034       18161 :         result = unlink(path->narrow);
    5035             : #endif
    5036             :     _Py_END_SUPPRESS_IPH
    5037       51699 :     Py_END_ALLOW_THREADS
    5038             : 
    5039             : #ifdef HAVE_UNLINKAT
    5040       51699 :     if (unlinkat_unavailable) {
    5041           0 :         argument_unavailable_error(NULL, "dir_fd");
    5042           0 :         return NULL;
    5043             :     }
    5044             : #endif
    5045             : 
    5046       51699 :     if (result)
    5047        7413 :         return path_error(path);
    5048             : 
    5049       44286 :     Py_RETURN_NONE;
    5050             : }
    5051             : 
    5052             : 
    5053             : /*[clinic input]
    5054             : os.remove = os.unlink
    5055             : 
    5056             : Remove a file (same as unlink()).
    5057             : 
    5058             : If dir_fd is not None, it should be a file descriptor open to a directory,
    5059             :   and path should be relative; path will then be relative to that directory.
    5060             : dir_fd may not be implemented on your platform.
    5061             :   If it is unavailable, using it will raise a NotImplementedError.
    5062             : [clinic start generated code]*/
    5063             : 
    5064             : static PyObject *
    5065        1435 : os_remove_impl(PyObject *module, path_t *path, int dir_fd)
    5066             : /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
    5067             : {
    5068        1435 :     return os_unlink_impl(module, path, dir_fd);
    5069             : }
    5070             : 
    5071             : 
    5072             : static PyStructSequence_Field uname_result_fields[] = {
    5073             :     {"sysname",    "operating system name"},
    5074             :     {"nodename",   "name of machine on network (implementation-defined)"},
    5075             :     {"release",    "operating system release"},
    5076             :     {"version",    "operating system version"},
    5077             :     {"machine",    "hardware identifier"},
    5078             :     {NULL}
    5079             : };
    5080             : 
    5081             : PyDoc_STRVAR(uname_result__doc__,
    5082             : "uname_result: Result from os.uname().\n\n\
    5083             : This object may be accessed either as a tuple of\n\
    5084             :   (sysname, nodename, release, version, machine),\n\
    5085             : or via the attributes sysname, nodename, release, version, and machine.\n\
    5086             : \n\
    5087             : See os.uname for more information.");
    5088             : 
    5089             : static PyStructSequence_Desc uname_result_desc = {
    5090             :     MODNAME ".uname_result", /* name */
    5091             :     uname_result__doc__, /* doc */
    5092             :     uname_result_fields,
    5093             :     5
    5094             : };
    5095             : 
    5096             : #ifdef HAVE_UNAME
    5097             : /*[clinic input]
    5098             : os.uname
    5099             : 
    5100             : Return an object identifying the current operating system.
    5101             : 
    5102             : The object behaves like a named tuple with the following fields:
    5103             :   (sysname, nodename, release, version, machine)
    5104             : 
    5105             : [clinic start generated code]*/
    5106             : 
    5107             : static PyObject *
    5108         289 : os_uname_impl(PyObject *module)
    5109             : /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
    5110             : {
    5111             :     struct utsname u;
    5112             :     int res;
    5113             :     PyObject *value;
    5114             : 
    5115         289 :     Py_BEGIN_ALLOW_THREADS
    5116         289 :     res = uname(&u);
    5117         289 :     Py_END_ALLOW_THREADS
    5118         289 :     if (res < 0)
    5119           0 :         return posix_error();
    5120             : 
    5121         289 :     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
    5122         289 :     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
    5123         289 :     if (value == NULL)
    5124           0 :         return NULL;
    5125             : 
    5126             : #define SET(i, field) \
    5127             :     { \
    5128             :     PyObject *o = PyUnicode_DecodeFSDefault(field); \
    5129             :     if (!o) { \
    5130             :         Py_DECREF(value); \
    5131             :         return NULL; \
    5132             :     } \
    5133             :     PyStructSequence_SET_ITEM(value, i, o); \
    5134             :     } \
    5135             : 
    5136         289 :     SET(0, u.sysname);
    5137         289 :     SET(1, u.nodename);
    5138         289 :     SET(2, u.release);
    5139         289 :     SET(3, u.version);
    5140         289 :     SET(4, u.machine);
    5141             : 
    5142             : #undef SET
    5143             : 
    5144         289 :     return value;
    5145             : }
    5146             : #endif /* HAVE_UNAME */
    5147             : 
    5148             : 
    5149             : 
    5150             : typedef struct {
    5151             :     int    now;
    5152             :     time_t atime_s;
    5153             :     long   atime_ns;
    5154             :     time_t mtime_s;
    5155             :     long   mtime_ns;
    5156             : } utime_t;
    5157             : 
    5158             : /*
    5159             :  * these macros assume that "ut" is a pointer to a utime_t
    5160             :  * they also intentionally leak the declaration of a pointer named "time"
    5161             :  */
    5162             : #define UTIME_TO_TIMESPEC \
    5163             :     struct timespec ts[2]; \
    5164             :     struct timespec *time; \
    5165             :     if (ut->now) \
    5166             :         time = NULL; \
    5167             :     else { \
    5168             :         ts[0].tv_sec = ut->atime_s; \
    5169             :         ts[0].tv_nsec = ut->atime_ns; \
    5170             :         ts[1].tv_sec = ut->mtime_s; \
    5171             :         ts[1].tv_nsec = ut->mtime_ns; \
    5172             :         time = ts; \
    5173             :     } \
    5174             : 
    5175             : #define UTIME_TO_TIMEVAL \
    5176             :     struct timeval tv[2]; \
    5177             :     struct timeval *time; \
    5178             :     if (ut->now) \
    5179             :         time = NULL; \
    5180             :     else { \
    5181             :         tv[0].tv_sec = ut->atime_s; \
    5182             :         tv[0].tv_usec = ut->atime_ns / 1000; \
    5183             :         tv[1].tv_sec = ut->mtime_s; \
    5184             :         tv[1].tv_usec = ut->mtime_ns / 1000; \
    5185             :         time = tv; \
    5186             :     } \
    5187             : 
    5188             : #define UTIME_TO_UTIMBUF \
    5189             :     struct utimbuf u; \
    5190             :     struct utimbuf *time; \
    5191             :     if (ut->now) \
    5192             :         time = NULL; \
    5193             :     else { \
    5194             :         u.actime = ut->atime_s; \
    5195             :         u.modtime = ut->mtime_s; \
    5196             :         time = &u; \
    5197             :     }
    5198             : 
    5199             : #define UTIME_TO_TIME_T \
    5200             :     time_t timet[2]; \
    5201             :     time_t *time; \
    5202             :     if (ut->now) \
    5203             :         time = NULL; \
    5204             :     else { \
    5205             :         timet[0] = ut->atime_s; \
    5206             :         timet[1] = ut->mtime_s; \
    5207             :         time = timet; \
    5208             :     } \
    5209             : 
    5210             : 
    5211             : #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
    5212             : 
    5213             : static int
    5214           8 : utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
    5215             : {
    5216             : #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
    5217             :     if (HAVE_UTIMENSAT_RUNTIME) {
    5218             :         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
    5219             :         UTIME_TO_TIMESPEC;
    5220             :         return utimensat(dir_fd, path, time, flags);
    5221             :     }  else {
    5222             :         errno = ENOSYS;
    5223             :         return -1;
    5224             :     }
    5225             : #elif defined(HAVE_UTIMENSAT)
    5226           8 :     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
    5227           8 :     UTIME_TO_TIMESPEC;
    5228           8 :     return utimensat(dir_fd, path, time, flags);
    5229             : #elif defined(HAVE_FUTIMESAT)
    5230             :     UTIME_TO_TIMEVAL;
    5231             :     /*
    5232             :      * follow_symlinks will never be false here;
    5233             :      * we only allow !follow_symlinks and dir_fd together
    5234             :      * if we have utimensat()
    5235             :      */
    5236             :     assert(follow_symlinks);
    5237             :     return futimesat(dir_fd, path, time);
    5238             : #endif
    5239             : }
    5240             : 
    5241             :     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
    5242             : #else
    5243             :     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
    5244             : #endif
    5245             : 
    5246             : #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
    5247             : 
    5248             : static int
    5249           7 : utime_fd(utime_t *ut, int fd)
    5250             : {
    5251             : #ifdef HAVE_FUTIMENS
    5252             : 
    5253             :     if (HAVE_FUTIMENS_RUNTIME) {
    5254             : 
    5255           7 :     UTIME_TO_TIMESPEC;
    5256           7 :     return futimens(fd, time);
    5257             : 
    5258             :     } else
    5259             : #ifndef HAVE_FUTIMES
    5260             :     {
    5261             :         /* Not sure if this can happen */
    5262             :         PyErr_SetString(
    5263             :             PyExc_RuntimeError,
    5264             :             "neither futimens nor futimes are supported"
    5265             :             " on this system");
    5266             :         return -1;
    5267             :     }
    5268             : #endif
    5269             : 
    5270             : #endif
    5271             : #ifdef HAVE_FUTIMES
    5272             :     {
    5273             :     UTIME_TO_TIMEVAL;
    5274             :     return futimes(fd, time);
    5275             :     }
    5276             : #endif
    5277             : }
    5278             : 
    5279             :     #define PATH_UTIME_HAVE_FD 1
    5280             : #else
    5281             :     #define PATH_UTIME_HAVE_FD 0
    5282             : #endif
    5283             : 
    5284             : #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
    5285             : #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
    5286             : #endif
    5287             : 
    5288             : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
    5289             : 
    5290             : static int
    5291          10 : utime_nofollow_symlinks(utime_t *ut, const char *path)
    5292             : {
    5293             : #ifdef HAVE_UTIMENSAT
    5294             :     if (HAVE_UTIMENSAT_RUNTIME) {
    5295          10 :         UTIME_TO_TIMESPEC;
    5296          10 :         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
    5297             :     } else
    5298             : #ifndef HAVE_LUTIMES
    5299             :     {
    5300             :         /* Not sure if this can happen */
    5301             :         PyErr_SetString(
    5302             :             PyExc_RuntimeError,
    5303             :             "neither utimensat nor lutimes are supported"
    5304             :             " on this system");
    5305             :         return -1;
    5306             :     }
    5307             : #endif
    5308             : #endif
    5309             : 
    5310             : #ifdef HAVE_LUTIMES
    5311             :     {
    5312             :     UTIME_TO_TIMEVAL;
    5313             :     return lutimes(path, time);
    5314             :     }
    5315             : #endif
    5316             : }
    5317             : 
    5318             : #endif
    5319             : 
    5320             : #ifndef MS_WINDOWS
    5321             : 
    5322             : static int
    5323       11529 : utime_default(utime_t *ut, const char *path)
    5324             : {
    5325             : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
    5326             :     if (HAVE_UTIMENSAT_RUNTIME) {
    5327             :         UTIME_TO_TIMESPEC;
    5328             :         return utimensat(DEFAULT_DIR_FD, path, time, 0);
    5329             :     } else {
    5330             :         UTIME_TO_TIMEVAL;
    5331             :         return utimes(path, time);
    5332             :     }
    5333             : #elif defined(HAVE_UTIMENSAT)
    5334       11529 :     UTIME_TO_TIMESPEC;
    5335       11529 :     return utimensat(DEFAULT_DIR_FD, path, time, 0);
    5336             : #elif defined(HAVE_UTIMES)
    5337             :     UTIME_TO_TIMEVAL;
    5338             :     return utimes(path, time);
    5339             : #elif defined(HAVE_UTIME_H)
    5340             :     UTIME_TO_UTIMBUF;
    5341             :     return utime(path, time);
    5342             : #else
    5343             :     UTIME_TO_TIME_T;
    5344             :     return utime(path, time);
    5345             : #endif
    5346             : }
    5347             : 
    5348             : #endif
    5349             : 
    5350             : static int
    5351       22323 : split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
    5352             : {
    5353       22323 :     int result = 0;
    5354             :     PyObject *divmod;
    5355       22323 :     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
    5356       22323 :     if (!divmod)
    5357           0 :         goto exit;
    5358       22323 :     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
    5359           3 :         PyErr_Format(PyExc_TypeError,
    5360             :                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
    5361             :                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
    5362           3 :         goto exit;
    5363             :     }
    5364       22320 :     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
    5365       22320 :     if ((*s == -1) && PyErr_Occurred())
    5366           0 :         goto exit;
    5367       22320 :     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
    5368       22320 :     if ((*ns == -1) && PyErr_Occurred())
    5369           0 :         goto exit;
    5370             : 
    5371       22320 :     result = 1;
    5372       22323 : exit:
    5373       22323 :     Py_XDECREF(divmod);
    5374       22323 :     return result;
    5375             : }
    5376             : 
    5377             : 
    5378             : /*[clinic input]
    5379             : os.utime
    5380             : 
    5381             :     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
    5382             :     times: object = None
    5383             :     *
    5384             :     ns: object = NULL
    5385             :     dir_fd: dir_fd(requires='futimensat') = None
    5386             :     follow_symlinks: bool=True
    5387             : 
    5388             : # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
    5389             : 
    5390             : Set the access and modified time of path.
    5391             : 
    5392             : path may always be specified as a string.
    5393             : On some platforms, path may also be specified as an open file descriptor.
    5394             :   If this functionality is unavailable, using it raises an exception.
    5395             : 
    5396             : If times is not None, it must be a tuple (atime, mtime);
    5397             :     atime and mtime should be expressed as float seconds since the epoch.
    5398             : If ns is specified, it must be a tuple (atime_ns, mtime_ns);
    5399             :     atime_ns and mtime_ns should be expressed as integer nanoseconds
    5400             :     since the epoch.
    5401             : If times is None and ns is unspecified, utime uses the current time.
    5402             : Specifying tuples for both times and ns is an error.
    5403             : 
    5404             : If dir_fd is not None, it should be a file descriptor open to a directory,
    5405             :   and path should be relative; path will then be relative to that directory.
    5406             : If follow_symlinks is False, and the last element of the path is a symbolic
    5407             :   link, utime will modify the symbolic link itself instead of the file the
    5408             :   link points to.
    5409             : It is an error to use dir_fd or follow_symlinks when specifying path
    5410             :   as an open file descriptor.
    5411             : dir_fd and follow_symlinks may not be available on your platform.
    5412             :   If they are unavailable, using them will raise a NotImplementedError.
    5413             : 
    5414             : [clinic start generated code]*/
    5415             : 
    5416             : static PyObject *
    5417       11581 : os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
    5418             :               int dir_fd, int follow_symlinks)
    5419             : /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
    5420             : {
    5421             : #ifdef MS_WINDOWS
    5422             :     HANDLE hFile;
    5423             :     FILETIME atime, mtime;
    5424             : #else
    5425             :     int result;
    5426             : #endif
    5427             : 
    5428             :     utime_t utime;
    5429             : 
    5430       11581 :     memset(&utime, 0, sizeof(utime_t));
    5431             : 
    5432       11581 :     if (times != Py_None && ns) {
    5433           4 :         PyErr_SetString(PyExc_ValueError,
    5434             :                      "utime: you may specify either 'times'"
    5435             :                      " or 'ns' but not both");
    5436           4 :         return NULL;
    5437             :     }
    5438             : 
    5439       11577 :     if (times != Py_None) {
    5440             :         time_t a_sec, m_sec;
    5441             :         long a_nsec, m_nsec;
    5442         344 :         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
    5443           4 :             PyErr_SetString(PyExc_TypeError,
    5444             :                          "utime: 'times' must be either"
    5445             :                          " a tuple of two ints or None");
    5446          17 :             return NULL;
    5447             :         }
    5448         340 :         utime.now = 0;
    5449         340 :         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
    5450         332 :                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
    5451         332 :             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
    5452             :                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
    5453          13 :             return NULL;
    5454             :         }
    5455         327 :         utime.atime_s = a_sec;
    5456         327 :         utime.atime_ns = a_nsec;
    5457         327 :         utime.mtime_s = m_sec;
    5458         327 :         utime.mtime_ns = m_nsec;
    5459             :     }
    5460       11233 :     else if (ns) {
    5461       11166 :         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
    5462           3 :             PyErr_SetString(PyExc_TypeError,
    5463             :                          "utime: 'ns' must be a tuple of two ints");
    5464           3 :             return NULL;
    5465             :         }
    5466       11163 :         utime.now = 0;
    5467       11163 :         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
    5468       11160 :                                       &utime.atime_s, &utime.atime_ns) ||
    5469       11160 :             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
    5470             :                                        &utime.mtime_s, &utime.mtime_ns)) {
    5471           3 :             return NULL;
    5472             :         }
    5473             :     }
    5474             :     else {
    5475             :         /* times and ns are both None/unspecified. use "now". */
    5476          67 :         utime.now = 1;
    5477             :     }
    5478             : 
    5479             : #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
    5480             :     if (follow_symlinks_specified("utime", follow_symlinks))
    5481             :         return NULL;
    5482             : #endif
    5483             : 
    5484       23108 :     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
    5485       23108 :         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
    5486       11554 :         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
    5487           0 :         return NULL;
    5488             : 
    5489             : #if !defined(HAVE_UTIMENSAT)
    5490             :     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
    5491             :         PyErr_SetString(PyExc_ValueError,
    5492             :                      "utime: cannot use dir_fd and follow_symlinks "
    5493             :                      "together on this platform");
    5494             :         return NULL;
    5495             :     }
    5496             : #endif
    5497             : 
    5498       11554 :     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
    5499             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    5500           0 :         return NULL;
    5501             :     }
    5502             : 
    5503             : #ifdef MS_WINDOWS
    5504             :     Py_BEGIN_ALLOW_THREADS
    5505             :     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
    5506             :                         NULL, OPEN_EXISTING,
    5507             :                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
    5508             :     Py_END_ALLOW_THREADS
    5509             :     if (hFile == INVALID_HANDLE_VALUE) {
    5510             :         path_error(path);
    5511             :         return NULL;
    5512             :     }
    5513             : 
    5514             :     if (utime.now) {
    5515             :         GetSystemTimeAsFileTime(&mtime);
    5516             :         atime = mtime;
    5517             :     }
    5518             :     else {
    5519             :         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
    5520             :         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
    5521             :     }
    5522             :     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
    5523             :         /* Avoid putting the file name into the error here,
    5524             :            as that may confuse the user into believing that
    5525             :            something is wrong with the file, when it also
    5526             :            could be the time stamp that gives a problem. */
    5527             :         PyErr_SetFromWindowsErr(0);
    5528             :         CloseHandle(hFile);
    5529             :         return NULL;
    5530             :     }
    5531             :     CloseHandle(hFile);
    5532             : #else /* MS_WINDOWS */
    5533       11554 :     Py_BEGIN_ALLOW_THREADS
    5534             : 
    5535             : #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
    5536       11554 :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    5537          10 :         result = utime_nofollow_symlinks(&utime, path->narrow);
    5538             :     else
    5539             : #endif
    5540             : 
    5541             : #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
    5542       11544 :     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
    5543           8 :         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
    5544             : 
    5545             :     } else
    5546             : #endif
    5547             : 
    5548             : #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
    5549       11536 :     if (path->fd != -1)
    5550           7 :         result = utime_fd(&utime, path->fd);
    5551             :     else
    5552             : #endif
    5553             : 
    5554       11529 :     result = utime_default(&utime, path->narrow);
    5555             : 
    5556       11554 :     Py_END_ALLOW_THREADS
    5557             : 
    5558             : #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
    5559             :     /* See utime_dir_fd implementation */
    5560             :     if (result == -1 && errno == ENOSYS) {
    5561             :         argument_unavailable_error(NULL, "dir_fd");
    5562             :         return NULL;
    5563             :     }
    5564             : #endif
    5565             : 
    5566       11554 :     if (result < 0) {
    5567             :         /* see previous comment about not putting filename in error here */
    5568          49 :         posix_error();
    5569          49 :         return NULL;
    5570             :     }
    5571             : 
    5572             : #endif /* MS_WINDOWS */
    5573             : 
    5574       11505 :     Py_RETURN_NONE;
    5575             : }
    5576             : 
    5577             : /* Process operations */
    5578             : 
    5579             : 
    5580             : /*[clinic input]
    5581             : os._exit
    5582             : 
    5583             :     status: int
    5584             : 
    5585             : Exit to the system with specified status, without normal exit processing.
    5586             : [clinic start generated code]*/
    5587             : 
    5588             : static PyObject *
    5589           0 : os__exit_impl(PyObject *module, int status)
    5590             : /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
    5591             : {
    5592           0 :     _exit(status);
    5593             :     return NULL; /* Make gcc -Wall happy */
    5594             : }
    5595             : 
    5596             : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
    5597             : #define EXECV_CHAR wchar_t
    5598             : #else
    5599             : #define EXECV_CHAR char
    5600             : #endif
    5601             : 
    5602             : #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
    5603             : static void
    5604         210 : free_string_array(EXECV_CHAR **array, Py_ssize_t count)
    5605             : {
    5606             :     Py_ssize_t i;
    5607       11103 :     for (i = 0; i < count; i++)
    5608       10893 :         PyMem_Free(array[i]);
    5609         210 :     PyMem_Free(array);
    5610         210 : }
    5611             : 
    5612             : static int
    5613       10893 : fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
    5614             : {
    5615             :     Py_ssize_t size;
    5616             :     PyObject *ub;
    5617       10893 :     int result = 0;
    5618             : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
    5619             :     if (!PyUnicode_FSDecoder(o, &ub))
    5620             :         return 0;
    5621             :     *out = PyUnicode_AsWideCharString(ub, &size);
    5622             :     if (*out)
    5623             :         result = 1;
    5624             : #else
    5625       10893 :     if (!PyUnicode_FSConverter(o, &ub))
    5626           0 :         return 0;
    5627       10893 :     size = PyBytes_GET_SIZE(ub);
    5628       10893 :     *out = PyMem_Malloc(size + 1);
    5629       10893 :     if (*out) {
    5630       10893 :         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
    5631       10893 :         result = 1;
    5632             :     } else
    5633           0 :         PyErr_NoMemory();
    5634             : #endif
    5635       10893 :     Py_DECREF(ub);
    5636       10893 :     return result;
    5637             : }
    5638             : #endif
    5639             : 
    5640             : #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
    5641             : static EXECV_CHAR**
    5642          94 : parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
    5643             : {
    5644             :     Py_ssize_t i, pos, envc;
    5645          94 :     PyObject *keys=NULL, *vals=NULL;
    5646             :     PyObject *key, *val, *key2, *val2, *keyval;
    5647             :     EXECV_CHAR **envlist;
    5648             : 
    5649          94 :     i = PyMapping_Size(env);
    5650          94 :     if (i < 0)
    5651           0 :         return NULL;
    5652          94 :     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
    5653          94 :     if (envlist == NULL) {
    5654           0 :         PyErr_NoMemory();
    5655           0 :         return NULL;
    5656             :     }
    5657          94 :     envc = 0;
    5658          94 :     keys = PyMapping_Keys(env);
    5659          94 :     if (!keys)
    5660           0 :         goto error;
    5661          94 :     vals = PyMapping_Values(env);
    5662          94 :     if (!vals)
    5663           0 :         goto error;
    5664          94 :     if (!PyList_Check(keys) || !PyList_Check(vals)) {
    5665           0 :         PyErr_Format(PyExc_TypeError,
    5666             :                      "env.keys() or env.values() is not a list");
    5667           0 :         goto error;
    5668             :     }
    5669             : 
    5670       10625 :     for (pos = 0; pos < i; pos++) {
    5671       10534 :         key = PyList_GetItem(keys, pos);
    5672       10534 :         val = PyList_GetItem(vals, pos);
    5673       10534 :         if (!key || !val)
    5674           0 :             goto error;
    5675             : 
    5676             : #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
    5677             :         if (!PyUnicode_FSDecoder(key, &key2))
    5678             :             goto error;
    5679             :         if (!PyUnicode_FSDecoder(val, &val2)) {
    5680             :             Py_DECREF(key2);
    5681             :             goto error;
    5682             :         }
    5683             :         /* Search from index 1 because on Windows starting '=' is allowed for
    5684             :            defining hidden environment variables. */
    5685             :         if (PyUnicode_GET_LENGTH(key2) == 0 ||
    5686             :             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
    5687             :         {
    5688             :             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
    5689             :             Py_DECREF(key2);
    5690             :             Py_DECREF(val2);
    5691             :             goto error;
    5692             :         }
    5693             :         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
    5694             : #else
    5695       10534 :         if (!PyUnicode_FSConverter(key, &key2))
    5696           1 :             goto error;
    5697       10533 :         if (!PyUnicode_FSConverter(val, &val2)) {
    5698           1 :             Py_DECREF(key2);
    5699           1 :             goto error;
    5700             :         }
    5701       10532 :         if (PyBytes_GET_SIZE(key2) == 0 ||
    5702       10532 :             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
    5703             :         {
    5704           1 :             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
    5705           1 :             Py_DECREF(key2);
    5706           1 :             Py_DECREF(val2);
    5707           1 :             goto error;
    5708             :         }
    5709       10531 :         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
    5710             :                                              PyBytes_AS_STRING(val2));
    5711             : #endif
    5712       10531 :         Py_DECREF(key2);
    5713       10531 :         Py_DECREF(val2);
    5714       10531 :         if (!keyval)
    5715           0 :             goto error;
    5716             : 
    5717       10531 :         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
    5718           0 :             Py_DECREF(keyval);
    5719           0 :             goto error;
    5720             :         }
    5721             : 
    5722       10531 :         Py_DECREF(keyval);
    5723             :     }
    5724          91 :     Py_DECREF(vals);
    5725          91 :     Py_DECREF(keys);
    5726             : 
    5727          91 :     envlist[envc] = 0;
    5728          91 :     *envc_ptr = envc;
    5729          91 :     return envlist;
    5730             : 
    5731           3 : error:
    5732           3 :     Py_XDECREF(keys);
    5733           3 :     Py_XDECREF(vals);
    5734           3 :     free_string_array(envlist, envc);
    5735           3 :     return NULL;
    5736             : }
    5737             : 
    5738             : static EXECV_CHAR**
    5739         116 : parse_arglist(PyObject* argv, Py_ssize_t *argc)
    5740             : {
    5741             :     int i;
    5742         116 :     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
    5743         116 :     if (argvlist == NULL) {
    5744           0 :         PyErr_NoMemory();
    5745           0 :         return NULL;
    5746             :     }
    5747         478 :     for (i = 0; i < *argc; i++) {
    5748         362 :         PyObject* item = PySequence_ITEM(argv, i);
    5749         362 :         if (item == NULL)
    5750           0 :             goto fail;
    5751         362 :         if (!fsconvert_strdup(item, &argvlist[i])) {
    5752           0 :             Py_DECREF(item);
    5753           0 :             goto fail;
    5754             :         }
    5755         362 :         Py_DECREF(item);
    5756             :     }
    5757         116 :     argvlist[*argc] = NULL;
    5758         116 :     return argvlist;
    5759           0 : fail:
    5760           0 :     *argc = i;
    5761           0 :     free_string_array(argvlist, *argc);
    5762           0 :     return NULL;
    5763             : }
    5764             : 
    5765             : #endif
    5766             : 
    5767             : 
    5768             : #ifdef HAVE_EXECV
    5769             : /*[clinic input]
    5770             : os.execv
    5771             : 
    5772             :     path: path_t
    5773             :         Path of executable file.
    5774             :     argv: object
    5775             :         Tuple or list of strings.
    5776             :     /
    5777             : 
    5778             : Execute an executable path with arguments, replacing current process.
    5779             : [clinic start generated code]*/
    5780             : 
    5781             : static PyObject *
    5782          24 : os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
    5783             : /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
    5784             : {
    5785             :     EXECV_CHAR **argvlist;
    5786             :     Py_ssize_t argc;
    5787             : 
    5788             :     /* execv has two arguments: (path, argv), where
    5789             :        argv is a list or tuple of strings. */
    5790             : 
    5791          24 :     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
    5792           0 :         PyErr_SetString(PyExc_TypeError,
    5793             :                         "execv() arg 2 must be a tuple or list");
    5794           0 :         return NULL;
    5795             :     }
    5796          24 :     argc = PySequence_Size(argv);
    5797          24 :     if (argc < 1) {
    5798           3 :         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
    5799           3 :         return NULL;
    5800             :     }
    5801             : 
    5802          21 :     argvlist = parse_arglist(argv, &argc);
    5803          21 :     if (argvlist == NULL) {
    5804           0 :         return NULL;
    5805             :     }
    5806          21 :     if (!argvlist[0][0]) {
    5807           2 :         PyErr_SetString(PyExc_ValueError,
    5808             :             "execv() arg 2 first element cannot be empty");
    5809           2 :         free_string_array(argvlist, argc);
    5810           2 :         return NULL;
    5811             :     }
    5812             : 
    5813          19 :     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
    5814           0 :         free_string_array(argvlist, argc);
    5815           0 :         return NULL;
    5816             :     }
    5817             : 
    5818             :     _Py_BEGIN_SUPPRESS_IPH
    5819             : #ifdef HAVE_WEXECV
    5820             :     _wexecv(path->wide, argvlist);
    5821             : #else
    5822          19 :     execv(path->narrow, argvlist);
    5823             : #endif
    5824             :     _Py_END_SUPPRESS_IPH
    5825             : 
    5826             :     /* If we get here it's definitely an error */
    5827             : 
    5828          19 :     free_string_array(argvlist, argc);
    5829          19 :     return posix_error();
    5830             : }
    5831             : 
    5832             : 
    5833             : /*[clinic input]
    5834             : os.execve
    5835             : 
    5836             :     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
    5837             :         Path of executable file.
    5838             :     argv: object
    5839             :         Tuple or list of strings.
    5840             :     env: object
    5841             :         Dictionary of strings mapping to strings.
    5842             : 
    5843             : Execute an executable path with arguments, replacing current process.
    5844             : [clinic start generated code]*/
    5845             : 
    5846             : static PyObject *
    5847           5 : os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
    5848             : /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
    5849             : {
    5850           5 :     EXECV_CHAR **argvlist = NULL;
    5851             :     EXECV_CHAR **envlist;
    5852             :     Py_ssize_t argc, envc;
    5853             : 
    5854             :     /* execve has three arguments: (path, argv, env), where
    5855             :        argv is a list or tuple of strings and env is a dictionary
    5856             :        like posix.environ. */
    5857             : 
    5858           5 :     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
    5859           0 :         PyErr_SetString(PyExc_TypeError,
    5860             :                         "execve: argv must be a tuple or list");
    5861           0 :         goto fail_0;
    5862             :     }
    5863           5 :     argc = PySequence_Size(argv);
    5864           5 :     if (argc < 1) {
    5865           1 :         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
    5866           1 :         return NULL;
    5867             :     }
    5868             : 
    5869           4 :     if (!PyMapping_Check(env)) {
    5870           0 :         PyErr_SetString(PyExc_TypeError,
    5871             :                         "execve: environment must be a mapping object");
    5872           0 :         goto fail_0;
    5873             :     }
    5874             : 
    5875           4 :     argvlist = parse_arglist(argv, &argc);
    5876           4 :     if (argvlist == NULL) {
    5877           0 :         goto fail_0;
    5878             :     }
    5879           4 :     if (!argvlist[0][0]) {
    5880           1 :         PyErr_SetString(PyExc_ValueError,
    5881             :             "execve: argv first element cannot be empty");
    5882           1 :         goto fail_0;
    5883             :     }
    5884             : 
    5885           3 :     envlist = parse_envlist(env, &envc);
    5886           3 :     if (envlist == NULL)
    5887           3 :         goto fail_0;
    5888             : 
    5889           0 :     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
    5890           0 :         goto fail_1;
    5891             :     }
    5892             : 
    5893             :     _Py_BEGIN_SUPPRESS_IPH
    5894             : #ifdef HAVE_FEXECVE
    5895           0 :     if (path->fd > -1)
    5896           0 :         fexecve(path->fd, argvlist, envlist);
    5897             :     else
    5898             : #endif
    5899             : #ifdef HAVE_WEXECV
    5900             :         _wexecve(path->wide, argvlist, envlist);
    5901             : #else
    5902           0 :         execve(path->narrow, argvlist, envlist);
    5903             : #endif
    5904             :     _Py_END_SUPPRESS_IPH
    5905             : 
    5906             :     /* If we get here it's definitely an error */
    5907             : 
    5908           0 :     posix_path_error(path);
    5909           0 :   fail_1:
    5910           0 :     free_string_array(envlist, envc);
    5911           4 :   fail_0:
    5912           4 :     if (argvlist)
    5913           4 :         free_string_array(argvlist, argc);
    5914           4 :     return NULL;
    5915             : }
    5916             : 
    5917             : #endif /* HAVE_EXECV */
    5918             : 
    5919             : #ifdef HAVE_POSIX_SPAWN
    5920             : 
    5921             : enum posix_spawn_file_actions_identifier {
    5922             :     POSIX_SPAWN_OPEN,
    5923             :     POSIX_SPAWN_CLOSE,
    5924             :     POSIX_SPAWN_DUP2
    5925             : };
    5926             : 
    5927             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
    5928             : static int
    5929             : convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
    5930             : #endif
    5931             : 
    5932             : static int
    5933          75 : parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
    5934             :                         int resetids, int setsid, PyObject *setsigmask,
    5935             :                         PyObject *setsigdef, PyObject *scheduler,
    5936             :                         posix_spawnattr_t *attrp)
    5937             : {
    5938          75 :     long all_flags = 0;
    5939             : 
    5940          75 :     errno = posix_spawnattr_init(attrp);
    5941          75 :     if (errno) {
    5942           0 :         posix_error();
    5943           0 :         return -1;
    5944             :     }
    5945             : 
    5946          75 :     if (setpgroup) {
    5947           4 :         pid_t pgid = PyLong_AsPid(setpgroup);
    5948           4 :         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
    5949           2 :             goto fail;
    5950             :         }
    5951           2 :         errno = posix_spawnattr_setpgroup(attrp, pgid);
    5952           2 :         if (errno) {
    5953           0 :             posix_error();
    5954           0 :             goto fail;
    5955             :         }
    5956           2 :         all_flags |= POSIX_SPAWN_SETPGROUP;
    5957             :     }
    5958             : 
    5959          73 :     if (resetids) {
    5960           2 :         all_flags |= POSIX_SPAWN_RESETIDS;
    5961             :     }
    5962             : 
    5963          73 :     if (setsid) {
    5964             : #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
    5965             :         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
    5966             : #endif
    5967             : #ifdef POSIX_SPAWN_SETSID
    5968           2 :         all_flags |= POSIX_SPAWN_SETSID;
    5969             : #elif defined(POSIX_SPAWN_SETSID_NP)
    5970             :         all_flags |= POSIX_SPAWN_SETSID_NP;
    5971             : #else
    5972             :         argument_unavailable_error(func_name, "setsid");
    5973             :         return -1;
    5974             : #endif
    5975             : 
    5976             : #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
    5977             :         } else {
    5978             :             argument_unavailable_error(func_name, "setsid");
    5979             :             return -1;
    5980             :         }
    5981             : #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
    5982             : 
    5983             :     }
    5984             : 
    5985             : #ifdef HAVE_SIGSET_T
    5986          73 :    if (setsigmask) {
    5987             :         sigset_t set;
    5988           8 :         if (!_Py_Sigset_Converter(setsigmask, &set)) {
    5989           6 :             goto fail;
    5990             :         }
    5991           2 :         errno = posix_spawnattr_setsigmask(attrp, &set);
    5992           2 :         if (errno) {
    5993           0 :             posix_error();
    5994           0 :             goto fail;
    5995             :         }
    5996           2 :         all_flags |= POSIX_SPAWN_SETSIGMASK;
    5997             :     }
    5998             : 
    5999          67 :     if (setsigdef) {
    6000             :         sigset_t set;
    6001          34 :         if (!_Py_Sigset_Converter(setsigdef, &set)) {
    6002           6 :             goto fail;
    6003             :         }
    6004          28 :         errno = posix_spawnattr_setsigdefault(attrp, &set);
    6005          28 :         if (errno) {
    6006           0 :             posix_error();
    6007           0 :             goto fail;
    6008             :         }
    6009          28 :         all_flags |= POSIX_SPAWN_SETSIGDEF;
    6010             :     }
    6011             : #else
    6012             :     if (setsigmask || setsigdef) {
    6013             :         PyErr_SetString(PyExc_NotImplementedError,
    6014             :                         "sigset is not supported on this platform");
    6015             :         goto fail;
    6016             :     }
    6017             : #endif
    6018             : 
    6019          61 :     if (scheduler) {
    6020             : #ifdef POSIX_SPAWN_SETSCHEDULER
    6021             :         PyObject *py_schedpolicy;
    6022             :         PyObject *schedparam_obj;
    6023             :         struct sched_param schedparam;
    6024             : 
    6025           4 :         if (!PyArg_ParseTuple(scheduler, "OO"
    6026             :                         ";A scheduler tuple must have two elements",
    6027             :                         &py_schedpolicy, &schedparam_obj)) {
    6028           0 :             goto fail;
    6029             :         }
    6030           4 :         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
    6031           0 :             goto fail;
    6032             :         }
    6033           4 :         if (py_schedpolicy != Py_None) {
    6034           2 :             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
    6035             : 
    6036           2 :             if (schedpolicy == -1 && PyErr_Occurred()) {
    6037           0 :                 goto fail;
    6038             :             }
    6039           2 :             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
    6040           2 :             if (errno) {
    6041           0 :                 posix_error();
    6042           0 :                 goto fail;
    6043             :             }
    6044           2 :             all_flags |= POSIX_SPAWN_SETSCHEDULER;
    6045             :         }
    6046           4 :         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
    6047           4 :         if (errno) {
    6048           0 :             posix_error();
    6049           0 :             goto fail;
    6050             :         }
    6051           4 :         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
    6052             : #else
    6053             :         PyErr_SetString(PyExc_NotImplementedError,
    6054             :                 "The scheduler option is not supported in this system.");
    6055             :         goto fail;
    6056             : #endif
    6057             :     }
    6058             : 
    6059          61 :     errno = posix_spawnattr_setflags(attrp, all_flags);
    6060          61 :     if (errno) {
    6061           0 :         posix_error();
    6062           0 :         goto fail;
    6063             :     }
    6064             : 
    6065          61 :     return 0;
    6066             : 
    6067          14 : fail:
    6068          14 :     (void)posix_spawnattr_destroy(attrp);
    6069          14 :     return -1;
    6070             : }
    6071             : 
    6072             : static int
    6073          51 : parse_file_actions(PyObject *file_actions,
    6074             :                    posix_spawn_file_actions_t *file_actionsp,
    6075             :                    PyObject *temp_buffer)
    6076             : {
    6077             :     PyObject *seq;
    6078          51 :     PyObject *file_action = NULL;
    6079             :     PyObject *tag_obj;
    6080             : 
    6081          51 :     seq = PySequence_Fast(file_actions,
    6082             :                           "file_actions must be a sequence or None");
    6083          51 :     if (seq == NULL) {
    6084           0 :         return -1;
    6085             :     }
    6086             : 
    6087          51 :     errno = posix_spawn_file_actions_init(file_actionsp);
    6088          51 :     if (errno) {
    6089           0 :         posix_error();
    6090           0 :         Py_DECREF(seq);
    6091           0 :         return -1;
    6092             :     }
    6093             : 
    6094         172 :     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
    6095         137 :         file_action = PySequence_Fast_GET_ITEM(seq, i);
    6096         137 :         Py_INCREF(file_action);
    6097         137 :         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
    6098           4 :             PyErr_SetString(PyExc_TypeError,
    6099             :                 "Each file_actions element must be a non-empty tuple");
    6100           4 :             goto fail;
    6101             :         }
    6102         133 :         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
    6103         133 :         if (tag == -1 && PyErr_Occurred()) {
    6104           2 :             goto fail;
    6105             :         }
    6106             : 
    6107             :         /* Populate the file_actions object */
    6108         131 :         switch (tag) {
    6109           6 :             case POSIX_SPAWN_OPEN: {
    6110             :                 int fd, oflag;
    6111             :                 PyObject *path;
    6112             :                 unsigned long mode;
    6113           6 :                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
    6114             :                         ";A open file_action tuple must have 5 elements",
    6115             :                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
    6116             :                         &oflag, &mode))
    6117             :                 {
    6118           2 :                     goto fail;
    6119             :                 }
    6120           4 :                 if (PyList_Append(temp_buffer, path)) {
    6121           0 :                     Py_DECREF(path);
    6122           0 :                     goto fail;
    6123             :                 }
    6124           4 :                 errno = posix_spawn_file_actions_addopen(file_actionsp,
    6125           4 :                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
    6126           4 :                 Py_DECREF(path);
    6127           4 :                 if (errno) {
    6128           0 :                     posix_error();
    6129           0 :                     goto fail;
    6130             :                 }
    6131           4 :                 break;
    6132             :             }
    6133          50 :             case POSIX_SPAWN_CLOSE: {
    6134             :                 int fd;
    6135          50 :                 if (!PyArg_ParseTuple(file_action, "Oi"
    6136             :                         ";A close file_action tuple must have 2 elements",
    6137             :                         &tag_obj, &fd))
    6138             :                 {
    6139           6 :                     goto fail;
    6140             :                 }
    6141          44 :                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
    6142          44 :                 if (errno) {
    6143           0 :                     posix_error();
    6144           0 :                     goto fail;
    6145             :                 }
    6146          44 :                 break;
    6147             :             }
    6148          73 :             case POSIX_SPAWN_DUP2: {
    6149             :                 int fd1, fd2;
    6150          73 :                 if (!PyArg_ParseTuple(file_action, "Oii"
    6151             :                         ";A dup2 file_action tuple must have 3 elements",
    6152             :                         &tag_obj, &fd1, &fd2))
    6153             :                 {
    6154           0 :                     goto fail;
    6155             :                 }
    6156          73 :                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
    6157             :                                                          fd1, fd2);
    6158          73 :                 if (errno) {
    6159           0 :                     posix_error();
    6160           0 :                     goto fail;
    6161             :                 }
    6162          73 :                 break;
    6163             :             }
    6164           2 :             default: {
    6165           2 :                 PyErr_SetString(PyExc_TypeError,
    6166             :                                 "Unknown file_actions identifier");
    6167           2 :                 goto fail;
    6168             :             }
    6169             :         }
    6170         121 :         Py_DECREF(file_action);
    6171             :     }
    6172             : 
    6173          35 :     Py_DECREF(seq);
    6174          35 :     return 0;
    6175             : 
    6176          16 : fail:
    6177          16 :     Py_DECREF(seq);
    6178          16 :     Py_DECREF(file_action);
    6179          16 :     (void)posix_spawn_file_actions_destroy(file_actionsp);
    6180          16 :     return -1;
    6181             : }
    6182             : 
    6183             : 
    6184             : static PyObject *
    6185          91 : py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
    6186             :                PyObject *env, PyObject *file_actions,
    6187             :                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
    6188             :                PyObject *setsigdef, PyObject *scheduler)
    6189             : {
    6190          91 :     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
    6191          91 :     EXECV_CHAR **argvlist = NULL;
    6192          91 :     EXECV_CHAR **envlist = NULL;
    6193             :     posix_spawn_file_actions_t file_actions_buf;
    6194          91 :     posix_spawn_file_actions_t *file_actionsp = NULL;
    6195             :     posix_spawnattr_t attr;
    6196          91 :     posix_spawnattr_t *attrp = NULL;
    6197             :     Py_ssize_t argc, envc;
    6198          91 :     PyObject *result = NULL;
    6199          91 :     PyObject *temp_buffer = NULL;
    6200             :     pid_t pid;
    6201             :     int err_code;
    6202             : 
    6203             :     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
    6204             :        argv is a list or tuple of strings and env is a dictionary
    6205             :        like posix.environ. */
    6206             : 
    6207          91 :     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
    6208           0 :         PyErr_Format(PyExc_TypeError,
    6209             :                      "%s: argv must be a tuple or list", func_name);
    6210           0 :         goto exit;
    6211             :     }
    6212          91 :     argc = PySequence_Size(argv);
    6213          91 :     if (argc < 1) {
    6214           0 :         PyErr_Format(PyExc_ValueError,
    6215             :                      "%s: argv must not be empty", func_name);
    6216           0 :         return NULL;
    6217             :     }
    6218             : 
    6219          91 :     if (!PyMapping_Check(env)) {
    6220           0 :         PyErr_Format(PyExc_TypeError,
    6221             :                      "%s: environment must be a mapping object", func_name);
    6222           0 :         goto exit;
    6223             :     }
    6224             : 
    6225          91 :     argvlist = parse_arglist(argv, &argc);
    6226          91 :     if (argvlist == NULL) {
    6227           0 :         goto exit;
    6228             :     }
    6229          91 :     if (!argvlist[0][0]) {
    6230           0 :         PyErr_Format(PyExc_ValueError,
    6231             :                      "%s: argv first element cannot be empty", func_name);
    6232           0 :         goto exit;
    6233             :     }
    6234             : 
    6235          91 :     envlist = parse_envlist(env, &envc);
    6236          91 :     if (envlist == NULL) {
    6237           0 :         goto exit;
    6238             :     }
    6239             : 
    6240          91 :     if (file_actions != NULL && file_actions != Py_None) {
    6241             :         /* There is a bug in old versions of glibc that makes some of the
    6242             :          * helper functions for manipulating file actions not copy the provided
    6243             :          * buffers. The problem is that posix_spawn_file_actions_addopen does not
    6244             :          * copy the value of path for some old versions of glibc (<2.20).
    6245             :          * The use of temp_buffer here is a workaround that keeps the
    6246             :          * python objects that own the buffers alive until posix_spawn gets called.
    6247             :          * Check https://bugs.python.org/issue33630 and
    6248             :          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
    6249          51 :         temp_buffer = PyList_New(0);
    6250          51 :         if (!temp_buffer) {
    6251           0 :             goto exit;
    6252             :         }
    6253          51 :         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
    6254          16 :             goto exit;
    6255             :         }
    6256          35 :         file_actionsp = &file_actions_buf;
    6257             :     }
    6258             : 
    6259          75 :     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
    6260             :                                 setsigmask, setsigdef, scheduler, &attr)) {
    6261          14 :         goto exit;
    6262             :     }
    6263          61 :     attrp = &attr;
    6264             : 
    6265          61 :     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
    6266           0 :         goto exit;
    6267             :     }
    6268             : 
    6269             :     _Py_BEGIN_SUPPRESS_IPH
    6270             : #ifdef HAVE_POSIX_SPAWNP
    6271          61 :     if (use_posix_spawnp) {
    6272          18 :         err_code = posix_spawnp(&pid, path->narrow,
    6273             :                                 file_actionsp, attrp, argvlist, envlist);
    6274             :     }
    6275             :     else
    6276             : #endif /* HAVE_POSIX_SPAWNP */
    6277             :     {
    6278          43 :         err_code = posix_spawn(&pid, path->narrow,
    6279             :                                file_actionsp, attrp, argvlist, envlist);
    6280             :     }
    6281             :     _Py_END_SUPPRESS_IPH
    6282             : 
    6283          61 :     if (err_code) {
    6284           2 :         errno = err_code;
    6285           2 :         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
    6286           2 :         goto exit;
    6287             :     }
    6288             : #ifdef _Py_MEMORY_SANITIZER
    6289             :     __msan_unpoison(&pid, sizeof(pid));
    6290             : #endif
    6291          59 :     result = PyLong_FromPid(pid);
    6292             : 
    6293          91 : exit:
    6294          91 :     if (file_actionsp) {
    6295          35 :         (void)posix_spawn_file_actions_destroy(file_actionsp);
    6296             :     }
    6297          91 :     if (attrp) {
    6298          61 :         (void)posix_spawnattr_destroy(attrp);
    6299             :     }
    6300          91 :     if (envlist) {
    6301          91 :         free_string_array(envlist, envc);
    6302             :     }
    6303          91 :     if (argvlist) {
    6304          91 :         free_string_array(argvlist, argc);
    6305             :     }
    6306          91 :     Py_XDECREF(temp_buffer);
    6307          91 :     return result;
    6308             : }
    6309             : 
    6310             : 
    6311             : /*[clinic input]
    6312             : 
    6313             : os.posix_spawn
    6314             :     path: path_t
    6315             :         Path of executable file.
    6316             :     argv: object
    6317             :         Tuple or list of strings.
    6318             :     env: object
    6319             :         Dictionary of strings mapping to strings.
    6320             :     /
    6321             :     *
    6322             :     file_actions: object(c_default='NULL') = ()
    6323             :         A sequence of file action tuples.
    6324             :     setpgroup: object = NULL
    6325             :         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
    6326             :     resetids: bool(accept={int}) = False
    6327             :         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
    6328             :     setsid: bool(accept={int}) = False
    6329             :         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
    6330             :     setsigmask: object(c_default='NULL') = ()
    6331             :         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
    6332             :     setsigdef: object(c_default='NULL') = ()
    6333             :         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
    6334             :     scheduler: object = NULL
    6335             :         A tuple with the scheduler policy (optional) and parameters.
    6336             : 
    6337             : Execute the program specified by path in a new process.
    6338             : [clinic start generated code]*/
    6339             : 
    6340             : static PyObject *
    6341          58 : os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
    6342             :                     PyObject *env, PyObject *file_actions,
    6343             :                     PyObject *setpgroup, int resetids, int setsid,
    6344             :                     PyObject *setsigmask, PyObject *setsigdef,
    6345             :                     PyObject *scheduler)
    6346             : /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
    6347             : {
    6348          58 :     return py_posix_spawn(0, module, path, argv, env, file_actions,
    6349             :                           setpgroup, resetids, setsid, setsigmask, setsigdef,
    6350             :                           scheduler);
    6351             : }
    6352             :  #endif /* HAVE_POSIX_SPAWN */
    6353             : 
    6354             : 
    6355             : 
    6356             : #ifdef HAVE_POSIX_SPAWNP
    6357             : /*[clinic input]
    6358             : 
    6359             : os.posix_spawnp
    6360             :     path: path_t
    6361             :         Path of executable file.
    6362             :     argv: object
    6363             :         Tuple or list of strings.
    6364             :     env: object
    6365             :         Dictionary of strings mapping to strings.
    6366             :     /
    6367             :     *
    6368             :     file_actions: object(c_default='NULL') = ()
    6369             :         A sequence of file action tuples.
    6370             :     setpgroup: object = NULL
    6371             :         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
    6372             :     resetids: bool(accept={int}) = False
    6373             :         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
    6374             :     setsid: bool(accept={int}) = False
    6375             :         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
    6376             :     setsigmask: object(c_default='NULL') = ()
    6377             :         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
    6378             :     setsigdef: object(c_default='NULL') = ()
    6379             :         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
    6380             :     scheduler: object = NULL
    6381             :         A tuple with the scheduler policy (optional) and parameters.
    6382             : 
    6383             : Execute the program specified by path in a new process.
    6384             : [clinic start generated code]*/
    6385             : 
    6386             : static PyObject *
    6387          33 : os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
    6388             :                      PyObject *env, PyObject *file_actions,
    6389             :                      PyObject *setpgroup, int resetids, int setsid,
    6390             :                      PyObject *setsigmask, PyObject *setsigdef,
    6391             :                      PyObject *scheduler)
    6392             : /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
    6393             : {
    6394          33 :     return py_posix_spawn(1, module, path, argv, env, file_actions,
    6395             :                           setpgroup, resetids, setsid, setsigmask, setsigdef,
    6396             :                           scheduler);
    6397             : }
    6398             : #endif /* HAVE_POSIX_SPAWNP */
    6399             : 
    6400             : #ifdef HAVE_RTPSPAWN
    6401             : static intptr_t
    6402             : _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
    6403             :                const char  *envp[])
    6404             : {
    6405             :      RTP_ID rtpid;
    6406             :      int status;
    6407             :      pid_t res;
    6408             :      int async_err = 0;
    6409             : 
    6410             :      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
    6411             :         uStackSize=0 cannot be used, the default stack size is too small for
    6412             :         Python. */
    6413             :      if (envp) {
    6414             :          rtpid = rtpSpawn(rtpFileName, argv, envp,
    6415             :                           100, 0x1000000, 0, VX_FP_TASK);
    6416             :      }
    6417             :      else {
    6418             :          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
    6419             :                           100, 0x1000000, 0, VX_FP_TASK);
    6420             :      }
    6421             :      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
    6422             :          do {
    6423             :              res = waitpid((pid_t)rtpid, &status, 0);
    6424             :          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    6425             : 
    6426             :          if (res < 0)
    6427             :              return RTP_ID_ERROR;
    6428             :          return ((intptr_t)status);
    6429             :      }
    6430             :      return ((intptr_t)rtpid);
    6431             : }
    6432             : #endif
    6433             : 
    6434             : #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
    6435             : /*[clinic input]
    6436             : os.spawnv
    6437             : 
    6438             :     mode: int
    6439             :         Mode of process creation.
    6440             :     path: path_t
    6441             :         Path of executable file.
    6442             :     argv: object
    6443             :         Tuple or list of strings.
    6444             :     /
    6445             : 
    6446             : Execute the program specified by path in a new process.
    6447             : [clinic start generated code]*/
    6448             : 
    6449             : static PyObject *
    6450             : os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
    6451             : /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
    6452             : {
    6453             :     EXECV_CHAR **argvlist;
    6454             :     int i;
    6455             :     Py_ssize_t argc;
    6456             :     intptr_t spawnval;
    6457             :     PyObject *(*getitem)(PyObject *, Py_ssize_t);
    6458             : 
    6459             :     /* spawnv has three arguments: (mode, path, argv), where
    6460             :        argv is a list or tuple of strings. */
    6461             : 
    6462             :     if (PyList_Check(argv)) {
    6463             :         argc = PyList_Size(argv);
    6464             :         getitem = PyList_GetItem;
    6465             :     }
    6466             :     else if (PyTuple_Check(argv)) {
    6467             :         argc = PyTuple_Size(argv);
    6468             :         getitem = PyTuple_GetItem;
    6469             :     }
    6470             :     else {
    6471             :         PyErr_SetString(PyExc_TypeError,
    6472             :                         "spawnv() arg 2 must be a tuple or list");
    6473             :         return NULL;
    6474             :     }
    6475             :     if (argc == 0) {
    6476             :         PyErr_SetString(PyExc_ValueError,
    6477             :             "spawnv() arg 2 cannot be empty");
    6478             :         return NULL;
    6479             :     }
    6480             : 
    6481             :     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
    6482             :     if (argvlist == NULL) {
    6483             :         return PyErr_NoMemory();
    6484             :     }
    6485             :     for (i = 0; i < argc; i++) {
    6486             :         if (!fsconvert_strdup((*getitem)(argv, i),
    6487             :                               &argvlist[i])) {
    6488             :             free_string_array(argvlist, i);
    6489             :             PyErr_SetString(
    6490             :                 PyExc_TypeError,
    6491             :                 "spawnv() arg 2 must contain only strings");
    6492             :             return NULL;
    6493             :         }
    6494             :         if (i == 0 && !argvlist[0][0]) {
    6495             :             free_string_array(argvlist, i + 1);
    6496             :             PyErr_SetString(
    6497             :                 PyExc_ValueError,
    6498             :                 "spawnv() arg 2 first element cannot be empty");
    6499             :             return NULL;
    6500             :         }
    6501             :     }
    6502             :     argvlist[argc] = NULL;
    6503             : 
    6504             : #if !defined(HAVE_RTPSPAWN)
    6505             :     if (mode == _OLD_P_OVERLAY)
    6506             :         mode = _P_OVERLAY;
    6507             : #endif
    6508             : 
    6509             :     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
    6510             :                     Py_None) < 0) {
    6511             :         free_string_array(argvlist, argc);
    6512             :         return NULL;
    6513             :     }
    6514             : 
    6515             :     Py_BEGIN_ALLOW_THREADS
    6516             :     _Py_BEGIN_SUPPRESS_IPH
    6517             : #ifdef HAVE_WSPAWNV
    6518             :     spawnval = _wspawnv(mode, path->wide, argvlist);
    6519             : #elif defined(HAVE_RTPSPAWN)
    6520             :     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
    6521             : #else
    6522             :     spawnval = _spawnv(mode, path->narrow, argvlist);
    6523             : #endif
    6524             :     _Py_END_SUPPRESS_IPH
    6525             :     Py_END_ALLOW_THREADS
    6526             : 
    6527             :     free_string_array(argvlist, argc);
    6528             : 
    6529             :     if (spawnval == -1)
    6530             :         return posix_error();
    6531             :     else
    6532             :         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
    6533             : }
    6534             : 
    6535             : /*[clinic input]
    6536             : os.spawnve
    6537             : 
    6538             :     mode: int
    6539             :         Mode of process creation.
    6540             :     path: path_t
    6541             :         Path of executable file.
    6542             :     argv: object
    6543             :         Tuple or list of strings.
    6544             :     env: object
    6545             :         Dictionary of strings mapping to strings.
    6546             :     /
    6547             : 
    6548             : Execute the program specified by path in a new process.
    6549             : [clinic start generated code]*/
    6550             : 
    6551             : static PyObject *
    6552             : os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
    6553             :                 PyObject *env)
    6554             : /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
    6555             : {
    6556             :     EXECV_CHAR **argvlist;
    6557             :     EXECV_CHAR **envlist;
    6558             :     PyObject *res = NULL;
    6559             :     Py_ssize_t argc, i, envc;
    6560             :     intptr_t spawnval;
    6561             :     PyObject *(*getitem)(PyObject *, Py_ssize_t);
    6562             :     Py_ssize_t lastarg = 0;
    6563             : 
    6564             :     /* spawnve has four arguments: (mode, path, argv, env), where
    6565             :        argv is a list or tuple of strings and env is a dictionary
    6566             :        like posix.environ. */
    6567             : 
    6568             :     if (PyList_Check(argv)) {
    6569             :         argc = PyList_Size(argv);
    6570             :         getitem = PyList_GetItem;
    6571             :     }
    6572             :     else if (PyTuple_Check(argv)) {
    6573             :         argc = PyTuple_Size(argv);
    6574             :         getitem = PyTuple_GetItem;
    6575             :     }
    6576             :     else {
    6577             :         PyErr_SetString(PyExc_TypeError,
    6578             :                         "spawnve() arg 2 must be a tuple or list");
    6579             :         goto fail_0;
    6580             :     }
    6581             :     if (argc == 0) {
    6582             :         PyErr_SetString(PyExc_ValueError,
    6583             :             "spawnve() arg 2 cannot be empty");
    6584             :         goto fail_0;
    6585             :     }
    6586             :     if (!PyMapping_Check(env)) {
    6587             :         PyErr_SetString(PyExc_TypeError,
    6588             :                         "spawnve() arg 3 must be a mapping object");
    6589             :         goto fail_0;
    6590             :     }
    6591             : 
    6592             :     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
    6593             :     if (argvlist == NULL) {
    6594             :         PyErr_NoMemory();
    6595             :         goto fail_0;
    6596             :     }
    6597             :     for (i = 0; i < argc; i++) {
    6598             :         if (!fsconvert_strdup((*getitem)(argv, i),
    6599             :                               &argvlist[i]))
    6600             :         {
    6601             :             lastarg = i;
    6602             :             goto fail_1;
    6603             :         }
    6604             :         if (i == 0 && !argvlist[0][0]) {
    6605             :             lastarg = i + 1;
    6606             :             PyErr_SetString(
    6607             :                 PyExc_ValueError,
    6608             :                 "spawnv() arg 2 first element cannot be empty");
    6609             :             goto fail_1;
    6610             :         }
    6611             :     }
    6612             :     lastarg = argc;
    6613             :     argvlist[argc] = NULL;
    6614             : 
    6615             :     envlist = parse_envlist(env, &envc);
    6616             :     if (envlist == NULL)
    6617             :         goto fail_1;
    6618             : 
    6619             : #if !defined(HAVE_RTPSPAWN)
    6620             :     if (mode == _OLD_P_OVERLAY)
    6621             :         mode = _P_OVERLAY;
    6622             : #endif
    6623             : 
    6624             :     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
    6625             :         goto fail_2;
    6626             :     }
    6627             : 
    6628             :     Py_BEGIN_ALLOW_THREADS
    6629             :     _Py_BEGIN_SUPPRESS_IPH
    6630             : #ifdef HAVE_WSPAWNV
    6631             :     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
    6632             : #elif defined(HAVE_RTPSPAWN)
    6633             :     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
    6634             :                            (const char **)envlist);
    6635             : #else
    6636             :     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
    6637             : #endif
    6638             :     _Py_END_SUPPRESS_IPH
    6639             :     Py_END_ALLOW_THREADS
    6640             : 
    6641             :     if (spawnval == -1)
    6642             :         (void) posix_error();
    6643             :     else
    6644             :         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
    6645             : 
    6646             :   fail_2:
    6647             :     while (--envc >= 0) {
    6648             :         PyMem_Free(envlist[envc]);
    6649             :     }
    6650             :     PyMem_Free(envlist);
    6651             :   fail_1:
    6652             :     free_string_array(argvlist, lastarg);
    6653             :   fail_0:
    6654             :     return res;
    6655             : }
    6656             : 
    6657             : #endif /* HAVE_SPAWNV */
    6658             : 
    6659             : #ifdef HAVE_FORK
    6660             : 
    6661             : /* Helper function to validate arguments.
    6662             :    Returns 0 on success.  non-zero on failure with a TypeError raised.
    6663             :    If obj is non-NULL it must be callable.  */
    6664             : static int
    6665        9315 : check_null_or_callable(PyObject *obj, const char* obj_name)
    6666             : {
    6667        9315 :     if (obj && !PyCallable_Check(obj)) {
    6668           8 :         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
    6669             :                      obj_name, _PyType_Name(Py_TYPE(obj)));
    6670           8 :         return -1;
    6671             :     }
    6672        9307 :     return 0;
    6673             : }
    6674             : 
    6675             : /*[clinic input]
    6676             : os.register_at_fork
    6677             : 
    6678             :     *
    6679             :     before: object=NULL
    6680             :         A callable to be called in the parent before the fork() syscall.
    6681             :     after_in_child: object=NULL
    6682             :         A callable to be called in the child after fork().
    6683             :     after_in_parent: object=NULL
    6684             :         A callable to be called in the parent after fork().
    6685             : 
    6686             : Register callables to be called when forking a new process.
    6687             : 
    6688             : 'before' callbacks are called in reverse order.
    6689             : 'after_in_child' and 'after_in_parent' callbacks are called in order.
    6690             : 
    6691             : [clinic start generated code]*/
    6692             : 
    6693             : static PyObject *
    6694        3108 : os_register_at_fork_impl(PyObject *module, PyObject *before,
    6695             :                          PyObject *after_in_child, PyObject *after_in_parent)
    6696             : /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
    6697             : {
    6698             :     PyInterpreterState *interp;
    6699             : 
    6700        3108 :     if (!before && !after_in_child && !after_in_parent) {
    6701           0 :         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
    6702           0 :         return NULL;
    6703             :     }
    6704        6213 :     if (check_null_or_callable(before, "before") ||
    6705        6207 :         check_null_or_callable(after_in_child, "after_in_child") ||
    6706        3102 :         check_null_or_callable(after_in_parent, "after_in_parent")) {
    6707           8 :         return NULL;
    6708             :     }
    6709        3100 :     interp = _PyInterpreterState_GET();
    6710             : 
    6711        3100 :     if (register_at_forker(&interp->before_forkers, before)) {
    6712           0 :         return NULL;
    6713             :     }
    6714        3100 :     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
    6715           0 :         return NULL;
    6716             :     }
    6717        3100 :     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
    6718           0 :         return NULL;
    6719             :     }
    6720        3100 :     Py_RETURN_NONE;
    6721             : }
    6722             : #endif /* HAVE_FORK */
    6723             : 
    6724             : 
    6725             : #ifdef HAVE_FORK1
    6726             : /*[clinic input]
    6727             : os.fork1
    6728             : 
    6729             : Fork a child process with a single multiplexed (i.e., not bound) thread.
    6730             : 
    6731             : Return 0 to child process and PID of child to parent process.
    6732             : [clinic start generated code]*/
    6733             : 
    6734             : static PyObject *
    6735             : os_fork1_impl(PyObject *module)
    6736             : /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
    6737             : {
    6738             :     pid_t pid;
    6739             : 
    6740             :     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
    6741             :         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
    6742             :         return NULL;
    6743             :     }
    6744             :     PyOS_BeforeFork();
    6745             :     pid = fork1();
    6746             :     if (pid == 0) {
    6747             :         /* child: this clobbers and resets the import lock. */
    6748             :         PyOS_AfterFork_Child();
    6749             :     } else {
    6750             :         /* parent: release the import lock. */
    6751             :         PyOS_AfterFork_Parent();
    6752             :     }
    6753             :     if (pid == -1)
    6754             :         return posix_error();
    6755             :     return PyLong_FromPid(pid);
    6756             : }
    6757             : #endif /* HAVE_FORK1 */
    6758             : 
    6759             : 
    6760             : #ifdef HAVE_FORK
    6761             : /*[clinic input]
    6762             : os.fork
    6763             : 
    6764             : Fork a child process.
    6765             : 
    6766             : Return 0 to child process and PID of child to parent process.
    6767             : [clinic start generated code]*/
    6768             : 
    6769             : static PyObject *
    6770        1669 : os_fork_impl(PyObject *module)
    6771             : /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
    6772             : {
    6773             :     pid_t pid;
    6774        1669 :     PyInterpreterState *interp = _PyInterpreterState_GET();
    6775        1669 :     if (interp->config._isolated_interpreter) {
    6776           2 :         PyErr_SetString(PyExc_RuntimeError,
    6777             :                         "fork not supported for isolated subinterpreters");
    6778           2 :         return NULL;
    6779             :     }
    6780        1667 :     if (PySys_Audit("os.fork", NULL) < 0) {
    6781           0 :         return NULL;
    6782             :     }
    6783        1667 :     PyOS_BeforeFork();
    6784        1667 :     pid = fork();
    6785        1667 :     if (pid == 0) {
    6786             :         /* child: this clobbers and resets the import lock. */
    6787           8 :         PyOS_AfterFork_Child();
    6788             :     } else {
    6789             :         /* parent: release the import lock. */
    6790        1659 :         PyOS_AfterFork_Parent();
    6791             :     }
    6792        1667 :     if (pid == -1)
    6793           0 :         return posix_error();
    6794        1667 :     return PyLong_FromPid(pid);
    6795             : }
    6796             : #endif /* HAVE_FORK */
    6797             : 
    6798             : 
    6799             : #ifdef HAVE_SCHED_H
    6800             : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
    6801             : /*[clinic input]
    6802             : os.sched_get_priority_max
    6803             : 
    6804             :     policy: int
    6805             : 
    6806             : Get the maximum scheduling priority for policy.
    6807             : [clinic start generated code]*/
    6808             : 
    6809             : static PyObject *
    6810           2 : os_sched_get_priority_max_impl(PyObject *module, int policy)
    6811             : /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
    6812             : {
    6813             :     int max;
    6814             : 
    6815           2 :     max = sched_get_priority_max(policy);
    6816           2 :     if (max < 0)
    6817           1 :         return posix_error();
    6818           1 :     return PyLong_FromLong(max);
    6819             : }
    6820             : 
    6821             : 
    6822             : /*[clinic input]
    6823             : os.sched_get_priority_min
    6824             : 
    6825             :     policy: int
    6826             : 
    6827             : Get the minimum scheduling priority for policy.
    6828             : [clinic start generated code]*/
    6829             : 
    6830             : static PyObject *
    6831           6 : os_sched_get_priority_min_impl(PyObject *module, int policy)
    6832             : /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
    6833             : {
    6834           6 :     int min = sched_get_priority_min(policy);
    6835           6 :     if (min < 0)
    6836           1 :         return posix_error();
    6837           5 :     return PyLong_FromLong(min);
    6838             : }
    6839             : #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
    6840             : 
    6841             : 
    6842             : #ifdef HAVE_SCHED_SETSCHEDULER
    6843             : /*[clinic input]
    6844             : os.sched_getscheduler
    6845             :     pid: pid_t
    6846             :     /
    6847             : 
    6848             : Get the scheduling policy for the process identified by pid.
    6849             : 
    6850             : Passing 0 for pid returns the scheduling policy for the calling process.
    6851             : [clinic start generated code]*/
    6852             : 
    6853             : static PyObject *
    6854          12 : os_sched_getscheduler_impl(PyObject *module, pid_t pid)
    6855             : /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
    6856             : {
    6857             :     int policy;
    6858             : 
    6859          12 :     policy = sched_getscheduler(pid);
    6860          12 :     if (policy < 0)
    6861           1 :         return posix_error();
    6862          11 :     return PyLong_FromLong(policy);
    6863             : }
    6864             : #endif /* HAVE_SCHED_SETSCHEDULER */
    6865             : 
    6866             : 
    6867             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
    6868             : /*[clinic input]
    6869             : class os.sched_param "PyObject *" "SchedParamType"
    6870             : 
    6871             : @classmethod
    6872             : os.sched_param.__new__
    6873             : 
    6874             :     sched_priority: object
    6875             :         A scheduling parameter.
    6876             : 
    6877             : Currently has only one field: sched_priority
    6878             : [clinic start generated code]*/
    6879             : 
    6880             : static PyObject *
    6881           7 : os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
    6882             : /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
    6883             : {
    6884             :     PyObject *res;
    6885             : 
    6886           7 :     res = PyStructSequence_New(type);
    6887           7 :     if (!res)
    6888           0 :         return NULL;
    6889           7 :     Py_INCREF(sched_priority);
    6890           7 :     PyStructSequence_SET_ITEM(res, 0, sched_priority);
    6891           7 :     return res;
    6892             : }
    6893             : 
    6894             : PyDoc_VAR(os_sched_param__doc__);
    6895             : 
    6896             : static PyStructSequence_Field sched_param_fields[] = {
    6897             :     {"sched_priority", "the scheduling priority"},
    6898             :     {0}
    6899             : };
    6900             : 
    6901             : static PyStructSequence_Desc sched_param_desc = {
    6902             :     "sched_param", /* name */
    6903             :     os_sched_param__doc__, /* doc */
    6904             :     sched_param_fields,
    6905             :     1
    6906             : };
    6907             : 
    6908             : static int
    6909          13 : convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
    6910             : {
    6911             :     long priority;
    6912             : 
    6913          13 :     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
    6914           2 :         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
    6915           2 :         return 0;
    6916             :     }
    6917          11 :     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
    6918          11 :     if (priority == -1 && PyErr_Occurred())
    6919           1 :         return 0;
    6920          10 :     if (priority > INT_MAX || priority < INT_MIN) {
    6921           2 :         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
    6922           2 :         return 0;
    6923             :     }
    6924           8 :     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
    6925           8 :     return 1;
    6926             : }
    6927             : #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
    6928             : 
    6929             : 
    6930             : #ifdef HAVE_SCHED_SETSCHEDULER
    6931             : /*[clinic input]
    6932             : os.sched_setscheduler
    6933             : 
    6934             :     pid: pid_t
    6935             :     policy: int
    6936             :     param as param_obj: object
    6937             :     /
    6938             : 
    6939             : Set the scheduling policy for the process identified by pid.
    6940             : 
    6941             : If pid is 0, the calling process is changed.
    6942             : param is an instance of sched_param.
    6943             : [clinic start generated code]*/
    6944             : 
    6945             : static PyObject *
    6946           3 : os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
    6947             :                            PyObject *param_obj)
    6948             : /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
    6949             : {
    6950             :     struct sched_param param;
    6951           3 :     if (!convert_sched_param(module, param_obj, &param)) {
    6952           1 :         return NULL;
    6953             :     }
    6954             : 
    6955             :     /*
    6956             :     ** sched_setscheduler() returns 0 in Linux, but the previous
    6957             :     ** scheduling policy under Solaris/Illumos, and others.
    6958             :     ** On error, -1 is returned in all Operating Systems.
    6959             :     */
    6960           2 :     if (sched_setscheduler(pid, policy, &param) == -1)
    6961           1 :         return posix_error();
    6962           1 :     Py_RETURN_NONE;
    6963             : }
    6964             : #endif  /* HAVE_SCHED_SETSCHEDULER*/
    6965             : 
    6966             : 
    6967             : #ifdef HAVE_SCHED_SETPARAM
    6968             : /*[clinic input]
    6969             : os.sched_getparam
    6970             :     pid: pid_t
    6971             :     /
    6972             : 
    6973             : Returns scheduling parameters for the process identified by pid.
    6974             : 
    6975             : If pid is 0, returns parameters for the calling process.
    6976             : Return value is an instance of sched_param.
    6977             : [clinic start generated code]*/
    6978             : 
    6979             : static PyObject *
    6980           6 : os_sched_getparam_impl(PyObject *module, pid_t pid)
    6981             : /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
    6982             : {
    6983             :     struct sched_param param;
    6984             :     PyObject *result;
    6985             :     PyObject *priority;
    6986             : 
    6987           6 :     if (sched_getparam(pid, &param))
    6988           1 :         return posix_error();
    6989           5 :     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
    6990           5 :     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
    6991           5 :     if (!result)
    6992           0 :         return NULL;
    6993           5 :     priority = PyLong_FromLong(param.sched_priority);
    6994           5 :     if (!priority) {
    6995           0 :         Py_DECREF(result);
    6996           0 :         return NULL;
    6997             :     }
    6998           5 :     PyStructSequence_SET_ITEM(result, 0, priority);
    6999           5 :     return result;
    7000             : }
    7001             : 
    7002             : 
    7003             : /*[clinic input]
    7004             : os.sched_setparam
    7005             :     pid: pid_t
    7006             :     param as param_obj: object
    7007             :     /
    7008             : 
    7009             : Set scheduling parameters for the process identified by pid.
    7010             : 
    7011             : If pid is 0, sets parameters for the calling process.
    7012             : param should be an instance of sched_param.
    7013             : [clinic start generated code]*/
    7014             : 
    7015             : static PyObject *
    7016           6 : os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
    7017             : /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
    7018             : {
    7019             :     struct sched_param param;
    7020           6 :     if (!convert_sched_param(module, param_obj, &param)) {
    7021           4 :         return NULL;
    7022             :     }
    7023             : 
    7024           2 :     if (sched_setparam(pid, &param))
    7025           1 :         return posix_error();
    7026           1 :     Py_RETURN_NONE;
    7027             : }
    7028             : #endif /* HAVE_SCHED_SETPARAM */
    7029             : 
    7030             : 
    7031             : #ifdef HAVE_SCHED_RR_GET_INTERVAL
    7032             : /*[clinic input]
    7033             : os.sched_rr_get_interval -> double
    7034             :     pid: pid_t
    7035             :     /
    7036             : 
    7037             : Return the round-robin quantum for the process identified by pid, in seconds.
    7038             : 
    7039             : Value returned is a float.
    7040             : [clinic start generated code]*/
    7041             : 
    7042             : static double
    7043           1 : os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
    7044             : /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
    7045             : {
    7046             :     struct timespec interval;
    7047           1 :     if (sched_rr_get_interval(pid, &interval)) {
    7048           0 :         posix_error();
    7049           0 :         return -1.0;
    7050             :     }
    7051             : #ifdef _Py_MEMORY_SANITIZER
    7052             :     __msan_unpoison(&interval, sizeof(interval));
    7053             : #endif
    7054           1 :     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
    7055             : }
    7056             : #endif /* HAVE_SCHED_RR_GET_INTERVAL */
    7057             : 
    7058             : 
    7059             : /*[clinic input]
    7060             : os.sched_yield
    7061             : 
    7062             : Voluntarily relinquish the CPU.
    7063             : [clinic start generated code]*/
    7064             : 
    7065             : static PyObject *
    7066           1 : os_sched_yield_impl(PyObject *module)
    7067             : /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
    7068             : {
    7069           1 :     if (sched_yield())
    7070           0 :         return posix_error();
    7071           1 :     Py_RETURN_NONE;
    7072             : }
    7073             : 
    7074             : #ifdef HAVE_SCHED_SETAFFINITY
    7075             : /* The minimum number of CPUs allocated in a cpu_set_t */
    7076             : static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
    7077             : 
    7078             : /*[clinic input]
    7079             : os.sched_setaffinity
    7080             :     pid: pid_t
    7081             :     mask : object
    7082             :     /
    7083             : 
    7084             : Set the CPU affinity of the process identified by pid to mask.
    7085             : 
    7086             : mask should be an iterable of integers identifying CPUs.
    7087             : [clinic start generated code]*/
    7088             : 
    7089             : static PyObject *
    7090           6 : os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
    7091             : /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
    7092             : {
    7093             :     int ncpus;
    7094             :     size_t setsize;
    7095           6 :     cpu_set_t *cpu_set = NULL;
    7096           6 :     PyObject *iterator = NULL, *item;
    7097             : 
    7098           6 :     iterator = PyObject_GetIter(mask);
    7099           6 :     if (iterator == NULL)
    7100           0 :         return NULL;
    7101             : 
    7102           6 :     ncpus = NCPUS_START;
    7103           6 :     setsize = CPU_ALLOC_SIZE(ncpus);
    7104           6 :     cpu_set = CPU_ALLOC(ncpus);
    7105           6 :     if (cpu_set == NULL) {
    7106           0 :         PyErr_NoMemory();
    7107           0 :         goto error;
    7108             :     }
    7109           6 :     CPU_ZERO_S(setsize, cpu_set);
    7110             : 
    7111           9 :     while ((item = PyIter_Next(iterator))) {
    7112             :         long cpu;
    7113           5 :         if (!PyLong_Check(item)) {
    7114           0 :             PyErr_Format(PyExc_TypeError,
    7115             :                         "expected an iterator of ints, "
    7116             :                         "but iterator yielded %R",
    7117             :                         Py_TYPE(item));
    7118           0 :             Py_DECREF(item);
    7119           0 :             goto error;
    7120             :         }
    7121           5 :         cpu = PyLong_AsLong(item);
    7122           5 :         Py_DECREF(item);
    7123           5 :         if (cpu < 0) {
    7124           2 :             if (!PyErr_Occurred())
    7125           1 :                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
    7126           2 :             goto error;
    7127             :         }
    7128           3 :         if (cpu > INT_MAX - 1) {
    7129           0 :             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
    7130           0 :             goto error;
    7131             :         }
    7132           3 :         if (cpu >= ncpus) {
    7133             :             /* Grow CPU mask to fit the CPU number */
    7134           0 :             int newncpus = ncpus;
    7135             :             cpu_set_t *newmask;
    7136             :             size_t newsetsize;
    7137           0 :             while (newncpus <= cpu) {
    7138           0 :                 if (newncpus > INT_MAX / 2)
    7139           0 :                     newncpus = cpu + 1;
    7140             :                 else
    7141           0 :                     newncpus = newncpus * 2;
    7142             :             }
    7143           0 :             newmask = CPU_ALLOC(newncpus);
    7144           0 :             if (newmask == NULL) {
    7145           0 :                 PyErr_NoMemory();
    7146           0 :                 goto error;
    7147             :             }
    7148           0 :             newsetsize = CPU_ALLOC_SIZE(newncpus);
    7149           0 :             CPU_ZERO_S(newsetsize, newmask);
    7150           0 :             memcpy(newmask, cpu_set, setsize);
    7151           0 :             CPU_FREE(cpu_set);
    7152           0 :             setsize = newsetsize;
    7153           0 :             cpu_set = newmask;
    7154           0 :             ncpus = newncpus;
    7155             :         }
    7156           3 :         CPU_SET_S(cpu, setsize, cpu_set);
    7157             :     }
    7158           4 :     if (PyErr_Occurred()) {
    7159           1 :         goto error;
    7160             :     }
    7161           3 :     Py_CLEAR(iterator);
    7162             : 
    7163           3 :     if (sched_setaffinity(pid, setsize, cpu_set)) {
    7164           2 :         posix_error();
    7165           2 :         goto error;
    7166             :     }
    7167           1 :     CPU_FREE(cpu_set);
    7168           1 :     Py_RETURN_NONE;
    7169             : 
    7170           5 : error:
    7171           5 :     if (cpu_set)
    7172           5 :         CPU_FREE(cpu_set);
    7173           5 :     Py_XDECREF(iterator);
    7174           5 :     return NULL;
    7175             : }
    7176             : 
    7177             : 
    7178             : /*[clinic input]
    7179             : os.sched_getaffinity
    7180             :     pid: pid_t
    7181             :     /
    7182             : 
    7183             : Return the affinity of the process identified by pid (or the current process if zero).
    7184             : 
    7185             : The affinity is returned as a set of CPU identifiers.
    7186             : [clinic start generated code]*/
    7187             : 
    7188             : static PyObject *
    7189           4 : os_sched_getaffinity_impl(PyObject *module, pid_t pid)
    7190             : /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
    7191             : {
    7192             :     int cpu, ncpus, count;
    7193             :     size_t setsize;
    7194           4 :     cpu_set_t *mask = NULL;
    7195           4 :     PyObject *res = NULL;
    7196             : 
    7197           4 :     ncpus = NCPUS_START;
    7198             :     while (1) {
    7199           4 :         setsize = CPU_ALLOC_SIZE(ncpus);
    7200           4 :         mask = CPU_ALLOC(ncpus);
    7201           4 :         if (mask == NULL)
    7202           0 :             return PyErr_NoMemory();
    7203           4 :         if (sched_getaffinity(pid, setsize, mask) == 0)
    7204           3 :             break;
    7205           1 :         CPU_FREE(mask);
    7206           1 :         if (errno != EINVAL)
    7207           1 :             return posix_error();
    7208           0 :         if (ncpus > INT_MAX / 2) {
    7209           0 :             PyErr_SetString(PyExc_OverflowError, "could not allocate "
    7210             :                             "a large enough CPU set");
    7211           0 :             return NULL;
    7212             :         }
    7213           0 :         ncpus = ncpus * 2;
    7214             :     }
    7215             : 
    7216           3 :     res = PySet_New(NULL);
    7217           3 :     if (res == NULL)
    7218           0 :         goto error;
    7219           9 :     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
    7220           6 :         if (CPU_ISSET_S(cpu, setsize, mask)) {
    7221           5 :             PyObject *cpu_num = PyLong_FromLong(cpu);
    7222           5 :             --count;
    7223           5 :             if (cpu_num == NULL)
    7224           0 :                 goto error;
    7225           5 :             if (PySet_Add(res, cpu_num)) {
    7226           0 :                 Py_DECREF(cpu_num);
    7227           0 :                 goto error;
    7228             :             }
    7229           5 :             Py_DECREF(cpu_num);
    7230             :         }
    7231             :     }
    7232           3 :     CPU_FREE(mask);
    7233           3 :     return res;
    7234             : 
    7235           0 : error:
    7236           0 :     if (mask)
    7237           0 :         CPU_FREE(mask);
    7238           0 :     Py_XDECREF(res);
    7239           0 :     return NULL;
    7240             : }
    7241             : 
    7242             : #endif /* HAVE_SCHED_SETAFFINITY */
    7243             : 
    7244             : #endif /* HAVE_SCHED_H */
    7245             : 
    7246             : 
    7247             : /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
    7248             : #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
    7249             : #  define DEV_PTY_FILE "/dev/ptc"
    7250             : #  define HAVE_DEV_PTMX
    7251             : #else
    7252             : #  define DEV_PTY_FILE "/dev/ptmx"
    7253             : #endif
    7254             : 
    7255             : #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
    7256             : #ifdef HAVE_PTY_H
    7257             : #include <pty.h>
    7258             : #ifdef HAVE_UTMP_H
    7259             : #include <utmp.h>
    7260             : #endif /* HAVE_UTMP_H */
    7261             : #elif defined(HAVE_LIBUTIL_H)
    7262             : #include <libutil.h>
    7263             : #elif defined(HAVE_UTIL_H)
    7264             : #include <util.h>
    7265             : #endif /* HAVE_PTY_H */
    7266             : #ifdef HAVE_STROPTS_H
    7267             : #include <stropts.h>
    7268             : #endif
    7269             : #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
    7270             : 
    7271             : 
    7272             : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
    7273             : /*[clinic input]
    7274             : os.openpty
    7275             : 
    7276             : Open a pseudo-terminal.
    7277             : 
    7278             : Return a tuple of (master_fd, slave_fd) containing open file descriptors
    7279             : for both the master and slave ends.
    7280             : [clinic start generated code]*/
    7281             : 
    7282             : static PyObject *
    7283          17 : os_openpty_impl(PyObject *module)
    7284             : /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
    7285             : {
    7286          17 :     int master_fd = -1, slave_fd = -1;
    7287             : #ifndef HAVE_OPENPTY
    7288             :     char * slave_name;
    7289             : #endif
    7290             : #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
    7291             :     PyOS_sighandler_t sig_saved;
    7292             : #if defined(__sun) && defined(__SVR4)
    7293             :     extern char *ptsname(int fildes);
    7294             : #endif
    7295             : #endif
    7296             : 
    7297             : #ifdef HAVE_OPENPTY
    7298          17 :     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
    7299           0 :         goto posix_error;
    7300             : 
    7301          17 :     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
    7302           0 :         goto error;
    7303          17 :     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
    7304           0 :         goto error;
    7305             : 
    7306             : #elif defined(HAVE__GETPTY)
    7307             :     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
    7308             :     if (slave_name == NULL)
    7309             :         goto posix_error;
    7310             :     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
    7311             :         goto error;
    7312             : 
    7313             :     slave_fd = _Py_open(slave_name, O_RDWR);
    7314             :     if (slave_fd < 0)
    7315             :         goto error;
    7316             : 
    7317             : #else
    7318             :     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
    7319             :     if (master_fd < 0)
    7320             :         goto posix_error;
    7321             : 
    7322             :     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
    7323             : 
    7324             :     /* change permission of slave */
    7325             :     if (grantpt(master_fd) < 0) {
    7326             :         PyOS_setsig(SIGCHLD, sig_saved);
    7327             :         goto posix_error;
    7328             :     }
    7329             : 
    7330             :     /* unlock slave */
    7331             :     if (unlockpt(master_fd) < 0) {
    7332             :         PyOS_setsig(SIGCHLD, sig_saved);
    7333             :         goto posix_error;
    7334             :     }
    7335             : 
    7336             :     PyOS_setsig(SIGCHLD, sig_saved);
    7337             : 
    7338             :     slave_name = ptsname(master_fd); /* get name of slave */
    7339             :     if (slave_name == NULL)
    7340             :         goto posix_error;
    7341             : 
    7342             :     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
    7343             :     if (slave_fd == -1)
    7344             :         goto error;
    7345             : 
    7346             :     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
    7347             :         goto posix_error;
    7348             : 
    7349             : #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
    7350             :     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
    7351             :     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
    7352             : #ifndef __hpux
    7353             :     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
    7354             : #endif /* __hpux */
    7355             : #endif /* HAVE_CYGWIN */
    7356             : #endif /* HAVE_OPENPTY */
    7357             : 
    7358          17 :     return Py_BuildValue("(ii)", master_fd, slave_fd);
    7359             : 
    7360           0 : posix_error:
    7361           0 :     posix_error();
    7362           0 : error:
    7363           0 :     if (master_fd != -1)
    7364           0 :         close(master_fd);
    7365           0 :     if (slave_fd != -1)
    7366           0 :         close(slave_fd);
    7367           0 :     return NULL;
    7368             : }
    7369             : #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
    7370             : 
    7371             : 
    7372             : #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
    7373             : #define HAVE_FALLBACK_LOGIN_TTY 1
    7374             : #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
    7375             : 
    7376             : #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
    7377             : /*[clinic input]
    7378             : os.login_tty
    7379             : 
    7380             :     fd: fildes
    7381             :     /
    7382             : 
    7383             : Prepare the tty of which fd is a file descriptor for a new login session.
    7384             : 
    7385             : Make the calling process a session leader; make the tty the
    7386             : controlling tty, the stdin, the stdout, and the stderr of the
    7387             : calling process; close fd.
    7388             : [clinic start generated code]*/
    7389             : 
    7390             : static PyObject *
    7391           0 : os_login_tty_impl(PyObject *module, int fd)
    7392             : /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
    7393             : {
    7394             : #ifdef HAVE_LOGIN_TTY
    7395           0 :     if (login_tty(fd) == -1) {
    7396           0 :         return posix_error();
    7397             :     }
    7398             : #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
    7399             :     /* Establish a new session. */
    7400             :     if (setsid() == -1) {
    7401             :         return posix_error();
    7402             :     }
    7403             : 
    7404             :     /* The tty becomes the controlling terminal. */
    7405             :     if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
    7406             :         return posix_error();
    7407             :     }
    7408             : 
    7409             :     /* The tty becomes stdin/stdout/stderr */
    7410             :     if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
    7411             :         return posix_error();
    7412             :     }
    7413             :     if (fd > 2) {
    7414             :         close(fd);
    7415             :     }
    7416             : #endif /* HAVE_LOGIN_TTY */
    7417           0 :     Py_RETURN_NONE;
    7418             : }
    7419             : #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
    7420             : 
    7421             : 
    7422             : #ifdef HAVE_FORKPTY
    7423             : /*[clinic input]
    7424             : os.forkpty
    7425             : 
    7426             : Fork a new process with a new pseudo-terminal as controlling tty.
    7427             : 
    7428             : Returns a tuple of (pid, master_fd).
    7429             : Like fork(), return pid of 0 to the child process,
    7430             : and pid of child to the parent process.
    7431             : To both, return fd of newly opened pseudo-terminal.
    7432             : [clinic start generated code]*/
    7433             : 
    7434             : static PyObject *
    7435           3 : os_forkpty_impl(PyObject *module)
    7436             : /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
    7437             : {
    7438           3 :     int master_fd = -1;
    7439             :     pid_t pid;
    7440             : 
    7441           3 :     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
    7442           0 :         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
    7443           0 :         return NULL;
    7444             :     }
    7445           3 :     if (PySys_Audit("os.forkpty", NULL) < 0) {
    7446           0 :         return NULL;
    7447             :     }
    7448           3 :     PyOS_BeforeFork();
    7449           3 :     pid = forkpty(&master_fd, NULL, NULL, NULL);
    7450           3 :     if (pid == 0) {
    7451             :         /* child: this clobbers and resets the import lock. */
    7452           0 :         PyOS_AfterFork_Child();
    7453             :     } else {
    7454             :         /* parent: release the import lock. */
    7455           3 :         PyOS_AfterFork_Parent();
    7456             :     }
    7457           3 :     if (pid == -1) {
    7458           0 :         return posix_error();
    7459             :     }
    7460           3 :     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
    7461             : }
    7462             : #endif /* HAVE_FORKPTY */
    7463             : 
    7464             : 
    7465             : #ifdef HAVE_GETEGID
    7466             : /*[clinic input]
    7467             : os.getegid
    7468             : 
    7469             : Return the current process's effective group id.
    7470             : [clinic start generated code]*/
    7471             : 
    7472             : static PyObject *
    7473        2273 : os_getegid_impl(PyObject *module)
    7474             : /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
    7475             : {
    7476        2273 :     return _PyLong_FromGid(getegid());
    7477             : }
    7478             : #endif /* HAVE_GETEGID */
    7479             : 
    7480             : 
    7481             : #ifdef HAVE_GETEUID
    7482             : /*[clinic input]
    7483             : os.geteuid
    7484             : 
    7485             : Return the current process's effective user id.
    7486             : [clinic start generated code]*/
    7487             : 
    7488             : static PyObject *
    7489        2504 : os_geteuid_impl(PyObject *module)
    7490             : /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
    7491             : {
    7492        2504 :     return _PyLong_FromUid(geteuid());
    7493             : }
    7494             : #endif /* HAVE_GETEUID */
    7495             : 
    7496             : 
    7497             : #ifdef HAVE_GETGID
    7498             : /*[clinic input]
    7499             : os.getgid
    7500             : 
    7501             : Return the current process's group id.
    7502             : [clinic start generated code]*/
    7503             : 
    7504             : static PyObject *
    7505        2278 : os_getgid_impl(PyObject *module)
    7506             : /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
    7507             : {
    7508        2278 :     return _PyLong_FromGid(getgid());
    7509             : }
    7510             : #endif /* HAVE_GETGID */
    7511             : 
    7512             : 
    7513             : #ifdef HAVE_GETPID
    7514             : /*[clinic input]
    7515             : os.getpid
    7516             : 
    7517             : Return the current process id.
    7518             : [clinic start generated code]*/
    7519             : 
    7520             : static PyObject *
    7521      288533 : os_getpid_impl(PyObject *module)
    7522             : /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
    7523             : {
    7524      288533 :     return PyLong_FromPid(getpid());
    7525             : }
    7526             : #endif /* HAVE_GETPID */
    7527             : 
    7528             : #ifdef NGROUPS_MAX
    7529             : #define MAX_GROUPS NGROUPS_MAX
    7530             : #else
    7531             :     /* defined to be 16 on Solaris7, so this should be a small number */
    7532             : #define MAX_GROUPS 64
    7533             : #endif
    7534             : 
    7535             : #ifdef HAVE_GETGROUPLIST
    7536             : 
    7537             : #ifdef __APPLE__
    7538             : /*[clinic input]
    7539             : os.getgrouplist
    7540             : 
    7541             :     user: str
    7542             :         username to lookup
    7543             :     group as basegid: int
    7544             :         base group id of the user
    7545             :     /
    7546             : 
    7547             : Returns a list of groups to which a user belongs.
    7548             : [clinic start generated code]*/
    7549             : 
    7550             : static PyObject *
    7551             : os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
    7552             : /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
    7553             : #else
    7554             : /*[clinic input]
    7555             : os.getgrouplist
    7556             : 
    7557             :     user: str
    7558             :         username to lookup
    7559             :     group as basegid: gid_t
    7560             :         base group id of the user
    7561             :     /
    7562             : 
    7563             : Returns a list of groups to which a user belongs.
    7564             : [clinic start generated code]*/
    7565             : 
    7566             : static PyObject *
    7567           1 : os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
    7568             : /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
    7569             : #endif
    7570             : {
    7571             :     int i, ngroups;
    7572             :     PyObject *list;
    7573             : #ifdef __APPLE__
    7574             :     int *groups;
    7575             : #else
    7576             :     gid_t *groups;
    7577             : #endif
    7578             : 
    7579             :     /*
    7580             :      * NGROUPS_MAX is defined by POSIX.1 as the maximum
    7581             :      * number of supplimental groups a users can belong to.
    7582             :      * We have to increment it by one because
    7583             :      * getgrouplist() returns both the supplemental groups
    7584             :      * and the primary group, i.e. all of the groups the
    7585             :      * user belongs to.
    7586             :      */
    7587           1 :     ngroups = 1 + MAX_GROUPS;
    7588             : 
    7589           0 :     while (1) {
    7590             : #ifdef __APPLE__
    7591             :         groups = PyMem_New(int, ngroups);
    7592             : #else
    7593           1 :         groups = PyMem_New(gid_t, ngroups);
    7594             : #endif
    7595           1 :         if (groups == NULL) {
    7596           0 :             return PyErr_NoMemory();
    7597             :         }
    7598             : 
    7599           1 :         int old_ngroups = ngroups;
    7600           1 :         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
    7601             :             /* Success */
    7602           1 :             break;
    7603             :         }
    7604             : 
    7605             :         /* getgrouplist() fails if the group list is too small */
    7606           0 :         PyMem_Free(groups);
    7607             : 
    7608           0 :         if (ngroups > old_ngroups) {
    7609             :             /* If the group list is too small, the glibc implementation of
    7610             :                getgrouplist() sets ngroups to the total number of groups and
    7611             :                returns -1. */
    7612             :         }
    7613             :         else {
    7614             :             /* Double the group list size */
    7615           0 :             if (ngroups > INT_MAX / 2) {
    7616           0 :                 return PyErr_NoMemory();
    7617             :             }
    7618           0 :             ngroups *= 2;
    7619             :         }
    7620             : 
    7621             :         /* Retry getgrouplist() with a larger group list */
    7622             :     }
    7623             : 
    7624             : #ifdef _Py_MEMORY_SANITIZER
    7625             :     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
    7626             :     __msan_unpoison(&ngroups, sizeof(ngroups));
    7627             :     __msan_unpoison(groups, ngroups*sizeof(*groups));
    7628             : #endif
    7629             : 
    7630           1 :     list = PyList_New(ngroups);
    7631           1 :     if (list == NULL) {
    7632           0 :         PyMem_Free(groups);
    7633           0 :         return NULL;
    7634             :     }
    7635             : 
    7636           4 :     for (i = 0; i < ngroups; i++) {
    7637             : #ifdef __APPLE__
    7638             :         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
    7639             : #else
    7640           3 :         PyObject *o = _PyLong_FromGid(groups[i]);
    7641             : #endif
    7642           3 :         if (o == NULL) {
    7643           0 :             Py_DECREF(list);
    7644           0 :             PyMem_Free(groups);
    7645           0 :             return NULL;
    7646             :         }
    7647           3 :         PyList_SET_ITEM(list, i, o);
    7648             :     }
    7649             : 
    7650           1 :     PyMem_Free(groups);
    7651             : 
    7652           1 :     return list;
    7653             : }
    7654             : #endif /* HAVE_GETGROUPLIST */
    7655             : 
    7656             : 
    7657             : #ifdef HAVE_GETGROUPS
    7658             : /*[clinic input]
    7659             : os.getgroups
    7660             : 
    7661             : Return list of supplemental group IDs for the process.
    7662             : [clinic start generated code]*/
    7663             : 
    7664             : static PyObject *
    7665           6 : os_getgroups_impl(PyObject *module)
    7666             : /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
    7667             : {
    7668             :     // Call getgroups with length 0 to get the actual number of groups
    7669           6 :     int n = getgroups(0, NULL);
    7670           6 :     if (n < 0) {
    7671           0 :         return posix_error();
    7672             :     }
    7673             : 
    7674           6 :     if (n == 0) {
    7675           0 :         return PyList_New(0);
    7676             :     }
    7677             : 
    7678           6 :     gid_t *grouplist = PyMem_New(gid_t, n);
    7679           6 :     if (grouplist == NULL) {
    7680           0 :         return PyErr_NoMemory();
    7681             :     }
    7682             : 
    7683           6 :     n = getgroups(n, grouplist);
    7684           6 :     if (n == -1) {
    7685           0 :         PyMem_Free(grouplist);
    7686           0 :         return posix_error();
    7687             :     }
    7688             : 
    7689           6 :     PyObject *result = PyList_New(n);
    7690           6 :     if (result == NULL) {
    7691           0 :         goto error;
    7692             :     }
    7693             : 
    7694          24 :     for (int i = 0; i < n; ++i) {
    7695          18 :         PyObject *group = _PyLong_FromGid(grouplist[i]);
    7696          18 :         if (group == NULL) {
    7697           0 :             goto error;
    7698             :         }
    7699          18 :         PyList_SET_ITEM(result, i, group);
    7700             :     }
    7701           6 :     PyMem_Free(grouplist);
    7702             : 
    7703           6 :     return result;
    7704             : 
    7705           0 : error:
    7706           0 :     PyMem_Free(grouplist);
    7707           0 :     Py_XDECREF(result);
    7708           0 :     return NULL;
    7709             : }
    7710             : #endif /* HAVE_GETGROUPS */
    7711             : 
    7712             : #ifdef HAVE_INITGROUPS
    7713             : #ifdef __APPLE__
    7714             : /*[clinic input]
    7715             : os.initgroups
    7716             : 
    7717             :     username as oname: FSConverter
    7718             :     gid: int
    7719             :     /
    7720             : 
    7721             : Initialize the group access list.
    7722             : 
    7723             : Call the system initgroups() to initialize the group access list with all of
    7724             : the groups of which the specified username is a member, plus the specified
    7725             : group id.
    7726             : [clinic start generated code]*/
    7727             : 
    7728             : static PyObject *
    7729             : os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
    7730             : /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
    7731             : #else
    7732             : /*[clinic input]
    7733             : os.initgroups
    7734             : 
    7735             :     username as oname: FSConverter
    7736             :     gid: gid_t
    7737             :     /
    7738             : 
    7739             : Initialize the group access list.
    7740             : 
    7741             : Call the system initgroups() to initialize the group access list with all of
    7742             : the groups of which the specified username is a member, plus the specified
    7743             : group id.
    7744             : [clinic start generated code]*/
    7745             : 
    7746             : static PyObject *
    7747           1 : os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
    7748             : /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
    7749             : #endif
    7750             : {
    7751           1 :     const char *username = PyBytes_AS_STRING(oname);
    7752             : 
    7753           1 :     if (initgroups(username, gid) == -1)
    7754           1 :         return PyErr_SetFromErrno(PyExc_OSError);
    7755             : 
    7756           0 :     Py_RETURN_NONE;
    7757             : }
    7758             : #endif /* HAVE_INITGROUPS */
    7759             : 
    7760             : 
    7761             : #ifdef HAVE_GETPGID
    7762             : /*[clinic input]
    7763             : os.getpgid
    7764             : 
    7765             :     pid: pid_t
    7766             : 
    7767             : Call the system call getpgid(), and return the result.
    7768             : [clinic start generated code]*/
    7769             : 
    7770             : static PyObject *
    7771           2 : os_getpgid_impl(PyObject *module, pid_t pid)
    7772             : /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
    7773             : {
    7774           2 :     pid_t pgid = getpgid(pid);
    7775           2 :     if (pgid < 0)
    7776           0 :         return posix_error();
    7777           2 :     return PyLong_FromPid(pgid);
    7778             : }
    7779             : #endif /* HAVE_GETPGID */
    7780             : 
    7781             : 
    7782             : #ifdef HAVE_GETPGRP
    7783             : /*[clinic input]
    7784             : os.getpgrp
    7785             : 
    7786             : Return the current process group id.
    7787             : [clinic start generated code]*/
    7788             : 
    7789             : static PyObject *
    7790           3 : os_getpgrp_impl(PyObject *module)
    7791             : /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
    7792             : {
    7793             : #ifdef GETPGRP_HAVE_ARG
    7794             :     return PyLong_FromPid(getpgrp(0));
    7795             : #else /* GETPGRP_HAVE_ARG */
    7796           3 :     return PyLong_FromPid(getpgrp());
    7797             : #endif /* GETPGRP_HAVE_ARG */
    7798             : }
    7799             : #endif /* HAVE_GETPGRP */
    7800             : 
    7801             : 
    7802             : #ifdef HAVE_SETPGRP
    7803             : /*[clinic input]
    7804             : os.setpgrp
    7805             : 
    7806             : Make the current process the leader of its process group.
    7807             : [clinic start generated code]*/
    7808             : 
    7809             : static PyObject *
    7810           0 : os_setpgrp_impl(PyObject *module)
    7811             : /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
    7812             : {
    7813             : #ifdef SETPGRP_HAVE_ARG
    7814             :     if (setpgrp(0, 0) < 0)
    7815             : #else /* SETPGRP_HAVE_ARG */
    7816           0 :     if (setpgrp() < 0)
    7817             : #endif /* SETPGRP_HAVE_ARG */
    7818           0 :         return posix_error();
    7819           0 :     Py_RETURN_NONE;
    7820             : }
    7821             : #endif /* HAVE_SETPGRP */
    7822             : 
    7823             : #ifdef HAVE_GETPPID
    7824             : 
    7825             : #ifdef MS_WINDOWS
    7826             : #include <tlhelp32.h>
    7827             : 
    7828             : static PyObject*
    7829             : win32_getppid()
    7830             : {
    7831             :     HANDLE snapshot;
    7832             :     pid_t mypid;
    7833             :     PyObject* result = NULL;
    7834             :     BOOL have_record;
    7835             :     PROCESSENTRY32 pe;
    7836             : 
    7837             :     mypid = getpid(); /* This function never fails */
    7838             : 
    7839             :     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    7840             :     if (snapshot == INVALID_HANDLE_VALUE)
    7841             :         return PyErr_SetFromWindowsErr(GetLastError());
    7842             : 
    7843             :     pe.dwSize = sizeof(pe);
    7844             :     have_record = Process32First(snapshot, &pe);
    7845             :     while (have_record) {
    7846             :         if (mypid == (pid_t)pe.th32ProcessID) {
    7847             :             /* We could cache the ulong value in a static variable. */
    7848             :             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
    7849             :             break;
    7850             :         }
    7851             : 
    7852             :         have_record = Process32Next(snapshot, &pe);
    7853             :     }
    7854             : 
    7855             :     /* If our loop exits and our pid was not found (result will be NULL)
    7856             :      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
    7857             :      * error anyway, so let's raise it. */
    7858             :     if (!result)
    7859             :         result = PyErr_SetFromWindowsErr(GetLastError());
    7860             : 
    7861             :     CloseHandle(snapshot);
    7862             : 
    7863             :     return result;
    7864             : }
    7865             : #endif /*MS_WINDOWS*/
    7866             : 
    7867             : 
    7868             : /*[clinic input]
    7869             : os.getppid
    7870             : 
    7871             : Return the parent's process id.
    7872             : 
    7873             : If the parent process has already exited, Windows machines will still
    7874             : return its id; others systems will return the id of the 'init' process (1).
    7875             : [clinic start generated code]*/
    7876             : 
    7877             : static PyObject *
    7878           7 : os_getppid_impl(PyObject *module)
    7879             : /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
    7880             : {
    7881             : #ifdef MS_WINDOWS
    7882             :     return win32_getppid();
    7883             : #else
    7884           7 :     return PyLong_FromPid(getppid());
    7885             : #endif
    7886             : }
    7887             : #endif /* HAVE_GETPPID */
    7888             : 
    7889             : 
    7890             : #ifdef HAVE_GETLOGIN
    7891             : /*[clinic input]
    7892             : os.getlogin
    7893             : 
    7894             : Return the actual login name.
    7895             : [clinic start generated code]*/
    7896             : 
    7897             : static PyObject *
    7898           0 : os_getlogin_impl(PyObject *module)
    7899             : /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
    7900             : {
    7901           0 :     PyObject *result = NULL;
    7902             : #ifdef MS_WINDOWS
    7903             :     wchar_t user_name[UNLEN + 1];
    7904             :     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
    7905             : 
    7906             :     if (GetUserNameW(user_name, &num_chars)) {
    7907             :         /* num_chars is the number of unicode chars plus null terminator */
    7908             :         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
    7909             :     }
    7910             :     else
    7911             :         result = PyErr_SetFromWindowsErr(GetLastError());
    7912             : #else
    7913             :     char *name;
    7914           0 :     int old_errno = errno;
    7915             : 
    7916           0 :     errno = 0;
    7917           0 :     name = getlogin();
    7918           0 :     if (name == NULL) {
    7919           0 :         if (errno)
    7920           0 :             posix_error();
    7921             :         else
    7922           0 :             PyErr_SetString(PyExc_OSError, "unable to determine login name");
    7923             :     }
    7924             :     else
    7925           0 :         result = PyUnicode_DecodeFSDefault(name);
    7926           0 :     errno = old_errno;
    7927             : #endif
    7928           0 :     return result;
    7929             : }
    7930             : #endif /* HAVE_GETLOGIN */
    7931             : 
    7932             : 
    7933             : #ifdef HAVE_GETUID
    7934             : /*[clinic input]
    7935             : os.getuid
    7936             : 
    7937             : Return the current process's user id.
    7938             : [clinic start generated code]*/
    7939             : 
    7940             : static PyObject *
    7941        2319 : os_getuid_impl(PyObject *module)
    7942             : /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
    7943             : {
    7944        2319 :     return _PyLong_FromUid(getuid());
    7945             : }
    7946             : #endif /* HAVE_GETUID */
    7947             : 
    7948             : 
    7949             : #ifdef MS_WINDOWS
    7950             : #define HAVE_KILL
    7951             : #endif /* MS_WINDOWS */
    7952             : 
    7953             : #ifdef HAVE_KILL
    7954             : /*[clinic input]
    7955             : os.kill
    7956             : 
    7957             :     pid: pid_t
    7958             :     signal: Py_ssize_t
    7959             :     /
    7960             : 
    7961             : Kill a process with a signal.
    7962             : [clinic start generated code]*/
    7963             : 
    7964             : static PyObject *
    7965       15912 : os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
    7966             : /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
    7967             : {
    7968       15912 :     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
    7969           0 :         return NULL;
    7970             :     }
    7971             : #ifndef MS_WINDOWS
    7972       15912 :     if (kill(pid, (int)signal) == -1) {
    7973          11 :         return posix_error();
    7974             :     }
    7975             : 
    7976             :     // Check immediately if the signal was sent to the current process.
    7977             :     // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
    7978             :     // is cheap.
    7979       15901 :     if (PyErr_CheckSignals()) {
    7980          95 :         return NULL;
    7981             :     }
    7982             : 
    7983       15806 :     Py_RETURN_NONE;
    7984             : #else /* !MS_WINDOWS */
    7985             :     PyObject *result;
    7986             :     DWORD sig = (DWORD)signal;
    7987             :     DWORD err;
    7988             :     HANDLE handle;
    7989             : 
    7990             :     /* Console processes which share a common console can be sent CTRL+C or
    7991             :        CTRL+BREAK events, provided they handle said events. */
    7992             :     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
    7993             :         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
    7994             :             err = GetLastError();
    7995             :             PyErr_SetFromWindowsErr(err);
    7996             :         }
    7997             :         else
    7998             :             Py_RETURN_NONE;
    7999             :     }
    8000             : 
    8001             :     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
    8002             :        attempt to open and terminate the process. */
    8003             :     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
    8004             :     if (handle == NULL) {
    8005             :         err = GetLastError();
    8006             :         return PyErr_SetFromWindowsErr(err);
    8007             :     }
    8008             : 
    8009             :     if (TerminateProcess(handle, sig) == 0) {
    8010             :         err = GetLastError();
    8011             :         result = PyErr_SetFromWindowsErr(err);
    8012             :     } else {
    8013             :         Py_INCREF(Py_None);
    8014             :         result = Py_None;
    8015             :     }
    8016             : 
    8017             :     CloseHandle(handle);
    8018             :     return result;
    8019             : #endif /* !MS_WINDOWS */
    8020             : }
    8021             : #endif /* HAVE_KILL */
    8022             : 
    8023             : 
    8024             : #ifdef HAVE_KILLPG
    8025             : /*[clinic input]
    8026             : os.killpg
    8027             : 
    8028             :     pgid: pid_t
    8029             :     signal: int
    8030             :     /
    8031             : 
    8032             : Kill a process group with a signal.
    8033             : [clinic start generated code]*/
    8034             : 
    8035             : static PyObject *
    8036           1 : os_killpg_impl(PyObject *module, pid_t pgid, int signal)
    8037             : /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
    8038             : {
    8039           1 :     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
    8040           0 :         return NULL;
    8041             :     }
    8042             :     /* XXX some man pages make the `pgid` parameter an int, others
    8043             :        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
    8044             :        take the same type. Moreover, pid_t is always at least as wide as
    8045             :        int (else compilation of this module fails), which is safe. */
    8046           1 :     if (killpg(pgid, signal) == -1)
    8047           0 :         return posix_error();
    8048           1 :     Py_RETURN_NONE;
    8049             : }
    8050             : #endif /* HAVE_KILLPG */
    8051             : 
    8052             : 
    8053             : #ifdef HAVE_PLOCK
    8054             : #ifdef HAVE_SYS_LOCK_H
    8055             : #include <sys/lock.h>
    8056             : #endif
    8057             : 
    8058             : /*[clinic input]
    8059             : os.plock
    8060             :     op: int
    8061             :     /
    8062             : 
    8063             : Lock program segments into memory.");
    8064             : [clinic start generated code]*/
    8065             : 
    8066             : static PyObject *
    8067             : os_plock_impl(PyObject *module, int op)
    8068             : /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
    8069             : {
    8070             :     if (plock(op) == -1)
    8071             :         return posix_error();
    8072             :     Py_RETURN_NONE;
    8073             : }
    8074             : #endif /* HAVE_PLOCK */
    8075             : 
    8076             : 
    8077             : #ifdef HAVE_SETUID
    8078             : /*[clinic input]
    8079             : os.setuid
    8080             : 
    8081             :     uid: uid_t
    8082             :     /
    8083             : 
    8084             : Set the current process's user id.
    8085             : [clinic start generated code]*/
    8086             : 
    8087             : static PyObject *
    8088           1 : os_setuid_impl(PyObject *module, uid_t uid)
    8089             : /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
    8090             : {
    8091           1 :     if (setuid(uid) < 0)
    8092           1 :         return posix_error();
    8093           0 :     Py_RETURN_NONE;
    8094             : }
    8095             : #endif /* HAVE_SETUID */
    8096             : 
    8097             : 
    8098             : #ifdef HAVE_SETEUID
    8099             : /*[clinic input]
    8100             : os.seteuid
    8101             : 
    8102             :     euid: uid_t
    8103             :     /
    8104             : 
    8105             : Set the current process's effective user id.
    8106             : [clinic start generated code]*/
    8107             : 
    8108             : static PyObject *
    8109           1 : os_seteuid_impl(PyObject *module, uid_t euid)
    8110             : /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
    8111             : {
    8112           1 :     if (seteuid(euid) < 0)
    8113           1 :         return posix_error();
    8114           0 :     Py_RETURN_NONE;
    8115             : }
    8116             : #endif /* HAVE_SETEUID */
    8117             : 
    8118             : 
    8119             : #ifdef HAVE_SETEGID
    8120             : /*[clinic input]
    8121             : os.setegid
    8122             : 
    8123             :     egid: gid_t
    8124             :     /
    8125             : 
    8126             : Set the current process's effective group id.
    8127             : [clinic start generated code]*/
    8128             : 
    8129             : static PyObject *
    8130           1 : os_setegid_impl(PyObject *module, gid_t egid)
    8131             : /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
    8132             : {
    8133           1 :     if (setegid(egid) < 0)
    8134           1 :         return posix_error();
    8135           0 :     Py_RETURN_NONE;
    8136             : }
    8137             : #endif /* HAVE_SETEGID */
    8138             : 
    8139             : 
    8140             : #ifdef HAVE_SETREUID
    8141             : /*[clinic input]
    8142             : os.setreuid
    8143             : 
    8144             :     ruid: uid_t
    8145             :     euid: uid_t
    8146             :     /
    8147             : 
    8148             : Set the current process's real and effective user ids.
    8149             : [clinic start generated code]*/
    8150             : 
    8151             : static PyObject *
    8152           2 : os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
    8153             : /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
    8154             : {
    8155           2 :     if (setreuid(ruid, euid) < 0) {
    8156           1 :         return posix_error();
    8157             :     } else {
    8158           1 :         Py_RETURN_NONE;
    8159             :     }
    8160             : }
    8161             : #endif /* HAVE_SETREUID */
    8162             : 
    8163             : 
    8164             : #ifdef HAVE_SETREGID
    8165             : /*[clinic input]
    8166             : os.setregid
    8167             : 
    8168             :     rgid: gid_t
    8169             :     egid: gid_t
    8170             :     /
    8171             : 
    8172             : Set the current process's real and effective group ids.
    8173             : [clinic start generated code]*/
    8174             : 
    8175             : static PyObject *
    8176           2 : os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
    8177             : /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
    8178             : {
    8179           2 :     if (setregid(rgid, egid) < 0)
    8180           1 :         return posix_error();
    8181           1 :     Py_RETURN_NONE;
    8182             : }
    8183             : #endif /* HAVE_SETREGID */
    8184             : 
    8185             : 
    8186             : #ifdef HAVE_SETGID
    8187             : /*[clinic input]
    8188             : os.setgid
    8189             :     gid: gid_t
    8190             :     /
    8191             : 
    8192             : Set the current process's group id.
    8193             : [clinic start generated code]*/
    8194             : 
    8195             : static PyObject *
    8196           1 : os_setgid_impl(PyObject *module, gid_t gid)
    8197             : /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
    8198             : {
    8199           1 :     if (setgid(gid) < 0)
    8200           1 :         return posix_error();
    8201           0 :     Py_RETURN_NONE;
    8202             : }
    8203             : #endif /* HAVE_SETGID */
    8204             : 
    8205             : 
    8206             : #ifdef HAVE_SETGROUPS
    8207             : /*[clinic input]
    8208             : os.setgroups
    8209             : 
    8210             :     groups: object
    8211             :     /
    8212             : 
    8213             : Set the groups of the current process to list.
    8214             : [clinic start generated code]*/
    8215             : 
    8216             : static PyObject *
    8217           0 : os_setgroups(PyObject *module, PyObject *groups)
    8218             : /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
    8219             : {
    8220           0 :     if (!PySequence_Check(groups)) {
    8221           0 :         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
    8222           0 :         return NULL;
    8223             :     }
    8224           0 :     Py_ssize_t len = PySequence_Size(groups);
    8225           0 :     if (len < 0) {
    8226           0 :         return NULL;
    8227             :     }
    8228           0 :     if (len > MAX_GROUPS) {
    8229           0 :         PyErr_SetString(PyExc_ValueError, "too many groups");
    8230           0 :         return NULL;
    8231             :     }
    8232             : 
    8233           0 :     gid_t *grouplist = PyMem_New(gid_t, len);
    8234           0 :     for (Py_ssize_t i = 0; i < len; i++) {
    8235             :         PyObject *elem;
    8236           0 :         elem = PySequence_GetItem(groups, i);
    8237           0 :         if (!elem) {
    8238           0 :             PyMem_Free(grouplist);
    8239           0 :             return NULL;
    8240             :         }
    8241           0 :         if (!PyLong_Check(elem)) {
    8242           0 :             PyErr_SetString(PyExc_TypeError,
    8243             :                             "groups must be integers");
    8244           0 :             Py_DECREF(elem);
    8245           0 :             PyMem_Free(grouplist);
    8246           0 :             return NULL;
    8247             :         } else {
    8248           0 :             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
    8249           0 :                 Py_DECREF(elem);
    8250           0 :                 PyMem_Free(grouplist);
    8251           0 :                 return NULL;
    8252             :             }
    8253             :         }
    8254           0 :         Py_DECREF(elem);
    8255             :     }
    8256             : 
    8257           0 :     if (setgroups(len, grouplist) < 0) {
    8258           0 :         PyMem_Free(grouplist);
    8259           0 :         return posix_error();
    8260             :     }
    8261           0 :     PyMem_Free(grouplist);
    8262           0 :     Py_RETURN_NONE;
    8263             : }
    8264             : #endif /* HAVE_SETGROUPS */
    8265             : 
    8266             : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
    8267             : static PyObject *
    8268          23 : wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
    8269             : {
    8270             :     PyObject *result;
    8271             :     PyObject *struct_rusage;
    8272             : 
    8273          23 :     if (pid == -1)
    8274           0 :         return posix_error();
    8275             : 
    8276             :     // If wait succeeded but no child was ready to report status, ru will not
    8277             :     // have been populated.
    8278          23 :     if (pid == 0) {
    8279          17 :         memset(ru, 0, sizeof(*ru));
    8280             :     }
    8281             : 
    8282          23 :     struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage");
    8283          23 :     if (struct_rusage == NULL)
    8284           0 :         return NULL;
    8285             : 
    8286             :     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
    8287          23 :     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
    8288          23 :     Py_DECREF(struct_rusage);
    8289          23 :     if (!result)
    8290           0 :         return NULL;
    8291             : 
    8292             : #ifndef doubletime
    8293             : #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
    8294             : #endif
    8295             : 
    8296          23 :     PyStructSequence_SET_ITEM(result, 0,
    8297             :                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
    8298          23 :     PyStructSequence_SET_ITEM(result, 1,
    8299             :                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
    8300             : #define SET_INT(result, index, value)\
    8301             :         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
    8302          23 :     SET_INT(result, 2, ru->ru_maxrss);
    8303          23 :     SET_INT(result, 3, ru->ru_ixrss);
    8304          23 :     SET_INT(result, 4, ru->ru_idrss);
    8305          23 :     SET_INT(result, 5, ru->ru_isrss);
    8306          23 :     SET_INT(result, 6, ru->ru_minflt);
    8307          23 :     SET_INT(result, 7, ru->ru_majflt);
    8308          23 :     SET_INT(result, 8, ru->ru_nswap);
    8309          23 :     SET_INT(result, 9, ru->ru_inblock);
    8310          23 :     SET_INT(result, 10, ru->ru_oublock);
    8311          23 :     SET_INT(result, 11, ru->ru_msgsnd);
    8312          23 :     SET_INT(result, 12, ru->ru_msgrcv);
    8313          23 :     SET_INT(result, 13, ru->ru_nsignals);
    8314          23 :     SET_INT(result, 14, ru->ru_nvcsw);
    8315          23 :     SET_INT(result, 15, ru->ru_nivcsw);
    8316             : #undef SET_INT
    8317             : 
    8318          23 :     if (PyErr_Occurred()) {
    8319           0 :         Py_DECREF(result);
    8320           0 :         return NULL;
    8321             :     }
    8322             : 
    8323          23 :     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
    8324             : }
    8325             : #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
    8326             : 
    8327             : 
    8328             : #ifdef HAVE_WAIT3
    8329             : /*[clinic input]
    8330             : os.wait3
    8331             : 
    8332             :     options: int
    8333             : Wait for completion of a child process.
    8334             : 
    8335             : Returns a tuple of information about the child process:
    8336             :   (pid, status, rusage)
    8337             : [clinic start generated code]*/
    8338             : 
    8339             : static PyObject *
    8340          13 : os_wait3_impl(PyObject *module, int options)
    8341             : /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
    8342             : {
    8343             :     pid_t pid;
    8344             :     struct rusage ru;
    8345          13 :     int async_err = 0;
    8346             :     WAIT_TYPE status;
    8347          13 :     WAIT_STATUS_INT(status) = 0;
    8348             : 
    8349             :     do {
    8350          25 :         Py_BEGIN_ALLOW_THREADS
    8351          25 :         pid = wait3(&status, options, &ru);
    8352          25 :         Py_END_ALLOW_THREADS
    8353          25 :     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    8354          13 :     if (pid < 0)
    8355           0 :         return (!async_err) ? posix_error() : NULL;
    8356             : 
    8357          13 :     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
    8358             : }
    8359             : #endif /* HAVE_WAIT3 */
    8360             : 
    8361             : 
    8362             : #ifdef HAVE_WAIT4
    8363             : /*[clinic input]
    8364             : 
    8365             : os.wait4
    8366             : 
    8367             :     pid: pid_t
    8368             :     options: int
    8369             : 
    8370             : Wait for completion of a specific child process.
    8371             : 
    8372             : Returns a tuple of information about the child process:
    8373             :   (pid, status, rusage)
    8374             : [clinic start generated code]*/
    8375             : 
    8376             : static PyObject *
    8377          10 : os_wait4_impl(PyObject *module, pid_t pid, int options)
    8378             : /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
    8379             : {
    8380             :     pid_t res;
    8381             :     struct rusage ru;
    8382          10 :     int async_err = 0;
    8383             :     WAIT_TYPE status;
    8384          10 :     WAIT_STATUS_INT(status) = 0;
    8385             : 
    8386             :     do {
    8387          18 :         Py_BEGIN_ALLOW_THREADS
    8388          18 :         res = wait4(pid, &status, options, &ru);
    8389          18 :         Py_END_ALLOW_THREADS
    8390          18 :     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    8391          10 :     if (res < 0)
    8392           0 :         return (!async_err) ? posix_error() : NULL;
    8393             : 
    8394          10 :     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
    8395             : }
    8396             : #endif /* HAVE_WAIT4 */
    8397             : 
    8398             : 
    8399             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
    8400             : /*[clinic input]
    8401             : os.waitid
    8402             : 
    8403             :     idtype: idtype_t
    8404             :         Must be one of be P_PID, P_PGID or P_ALL.
    8405             :     id: id_t
    8406             :         The id to wait on.
    8407             :     options: int
    8408             :         Constructed from the ORing of one or more of WEXITED, WSTOPPED
    8409             :         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
    8410             :     /
    8411             : 
    8412             : Returns the result of waiting for a process or processes.
    8413             : 
    8414             : Returns either waitid_result or None if WNOHANG is specified and there are
    8415             : no children in a waitable state.
    8416             : [clinic start generated code]*/
    8417             : 
    8418             : static PyObject *
    8419           1 : os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
    8420             : /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
    8421             : {
    8422             :     PyObject *result;
    8423             :     int res;
    8424           1 :     int async_err = 0;
    8425             :     siginfo_t si;
    8426           1 :     si.si_pid = 0;
    8427             : 
    8428             :     do {
    8429           1 :         Py_BEGIN_ALLOW_THREADS
    8430           1 :         res = waitid(idtype, id, &si, options);
    8431           1 :         Py_END_ALLOW_THREADS
    8432           1 :     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    8433           1 :     if (res < 0)
    8434           0 :         return (!async_err) ? posix_error() : NULL;
    8435             : 
    8436           1 :     if (si.si_pid == 0)
    8437           0 :         Py_RETURN_NONE;
    8438             : 
    8439           1 :     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
    8440           1 :     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
    8441           1 :     if (!result)
    8442           0 :         return NULL;
    8443             : 
    8444           1 :     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
    8445           1 :     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
    8446           1 :     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
    8447           1 :     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
    8448           1 :     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
    8449           1 :     if (PyErr_Occurred()) {
    8450           0 :         Py_DECREF(result);
    8451           0 :         return NULL;
    8452             :     }
    8453             : 
    8454           1 :     return result;
    8455             : }
    8456             : #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
    8457             : 
    8458             : 
    8459             : #if defined(HAVE_WAITPID)
    8460             : /*[clinic input]
    8461             : os.waitpid
    8462             :     pid: pid_t
    8463             :     options: int
    8464             :     /
    8465             : 
    8466             : Wait for completion of a given child process.
    8467             : 
    8468             : Returns a tuple of information regarding the child process:
    8469             :     (pid, status)
    8470             : 
    8471             : The options argument is ignored on Windows.
    8472             : [clinic start generated code]*/
    8473             : 
    8474             : static PyObject *
    8475       81369 : os_waitpid_impl(PyObject *module, pid_t pid, int options)
    8476             : /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
    8477             : {
    8478             :     pid_t res;
    8479       81369 :     int async_err = 0;
    8480             :     WAIT_TYPE status;
    8481       81369 :     WAIT_STATUS_INT(status) = 0;
    8482             : 
    8483             :     do {
    8484       81405 :         Py_BEGIN_ALLOW_THREADS
    8485       81405 :         res = waitpid(pid, &status, options);
    8486       81405 :         Py_END_ALLOW_THREADS
    8487       81405 :     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    8488       81369 :     if (res < 0)
    8489        3639 :         return (!async_err) ? posix_error() : NULL;
    8490             : 
    8491       77730 :     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
    8492             : }
    8493             : #elif defined(HAVE_CWAIT)
    8494             : /* MS C has a variant of waitpid() that's usable for most purposes. */
    8495             : /*[clinic input]
    8496             : os.waitpid
    8497             :     pid: intptr_t
    8498             :     options: int
    8499             :     /
    8500             : 
    8501             : Wait for completion of a given process.
    8502             : 
    8503             : Returns a tuple of information regarding the process:
    8504             :     (pid, status << 8)
    8505             : 
    8506             : The options argument is ignored on Windows.
    8507             : [clinic start generated code]*/
    8508             : 
    8509             : static PyObject *
    8510             : os_waitpid_impl(PyObject *module, intptr_t pid, int options)
    8511             : /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
    8512             : {
    8513             :     int status;
    8514             :     intptr_t res;
    8515             :     int async_err = 0;
    8516             : 
    8517             :     do {
    8518             :         Py_BEGIN_ALLOW_THREADS
    8519             :         _Py_BEGIN_SUPPRESS_IPH
    8520             :         res = _cwait(&status, pid, options);
    8521             :         _Py_END_SUPPRESS_IPH
    8522             :         Py_END_ALLOW_THREADS
    8523             :     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    8524             :     if (res < 0)
    8525             :         return (!async_err) ? posix_error() : NULL;
    8526             : 
    8527             :     unsigned long long ustatus = (unsigned int)status;
    8528             : 
    8529             :     /* shift the status left a byte so this is more like the POSIX waitpid */
    8530             :     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
    8531             : }
    8532             : #endif
    8533             : 
    8534             : 
    8535             : #ifdef HAVE_WAIT
    8536             : /*[clinic input]
    8537             : os.wait
    8538             : 
    8539             : Wait for completion of a child process.
    8540             : 
    8541             : Returns a tuple of information about the child process:
    8542             :     (pid, status)
    8543             : [clinic start generated code]*/
    8544             : 
    8545             : static PyObject *
    8546           4 : os_wait_impl(PyObject *module)
    8547             : /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
    8548             : {
    8549             :     pid_t pid;
    8550           4 :     int async_err = 0;
    8551             :     WAIT_TYPE status;
    8552           4 :     WAIT_STATUS_INT(status) = 0;
    8553             : 
    8554             :     do {
    8555          15 :         Py_BEGIN_ALLOW_THREADS
    8556          15 :         pid = wait(&status);
    8557          15 :         Py_END_ALLOW_THREADS
    8558          15 :     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    8559           4 :     if (pid < 0)
    8560           0 :         return (!async_err) ? posix_error() : NULL;
    8561             : 
    8562           4 :     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
    8563             : }
    8564             : #endif /* HAVE_WAIT */
    8565             : 
    8566             : #if defined(__linux__) && defined(__NR_pidfd_open)
    8567             : /*[clinic input]
    8568             : os.pidfd_open
    8569             :   pid: pid_t
    8570             :   flags: unsigned_int = 0
    8571             : 
    8572             : Return a file descriptor referring to the process *pid*.
    8573             : 
    8574             : The descriptor can be used to perform process management without races and
    8575             : signals.
    8576             : [clinic start generated code]*/
    8577             : 
    8578             : static PyObject *
    8579          26 : os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
    8580             : /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
    8581             : {
    8582          26 :     int fd = syscall(__NR_pidfd_open, pid, flags);
    8583          26 :     if (fd < 0) {
    8584           1 :         return posix_error();
    8585             :     }
    8586          25 :     return PyLong_FromLong(fd);
    8587             : }
    8588             : #endif
    8589             : 
    8590             : 
    8591             : #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
    8592             : /*[clinic input]
    8593             : os.readlink
    8594             : 
    8595             :     path: path_t
    8596             :     *
    8597             :     dir_fd: dir_fd(requires='readlinkat') = None
    8598             : 
    8599             : Return a string representing the path to which the symbolic link points.
    8600             : 
    8601             : If dir_fd is not None, it should be a file descriptor open to a directory,
    8602             : and path should be relative; path will then be relative to that directory.
    8603             : 
    8604             : dir_fd may not be implemented on your platform.  If it is unavailable,
    8605             : using it will raise a NotImplementedError.
    8606             : [clinic start generated code]*/
    8607             : 
    8608             : static PyObject *
    8609         327 : os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
    8610             : /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
    8611             : {
    8612             : #if defined(HAVE_READLINK)
    8613             :     char buffer[MAXPATHLEN+1];
    8614             :     ssize_t length;
    8615             : #ifdef HAVE_READLINKAT
    8616         327 :     int readlinkat_unavailable = 0;
    8617             : #endif
    8618             : 
    8619         327 :     Py_BEGIN_ALLOW_THREADS
    8620             : #ifdef HAVE_READLINKAT
    8621         327 :     if (dir_fd != DEFAULT_DIR_FD) {
    8622             :         if (HAVE_READLINKAT_RUNTIME) {
    8623           1 :             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
    8624             :         } else {
    8625             :             readlinkat_unavailable = 1;
    8626             :         }
    8627             :     } else
    8628             : #endif
    8629         326 :         length = readlink(path->narrow, buffer, MAXPATHLEN);
    8630         327 :     Py_END_ALLOW_THREADS
    8631             : 
    8632             : #ifdef HAVE_READLINKAT
    8633         327 :     if (readlinkat_unavailable) {
    8634           0 :         argument_unavailable_error(NULL, "dir_fd");
    8635           0 :         return NULL;
    8636             :     }
    8637             : #endif
    8638             : 
    8639         327 :     if (length < 0) {
    8640          11 :         return path_error(path);
    8641             :     }
    8642         316 :     buffer[length] = '\0';
    8643             : 
    8644         316 :     if (PyUnicode_Check(path->object))
    8645         314 :         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
    8646             :     else
    8647           2 :         return PyBytes_FromStringAndSize(buffer, length);
    8648             : #elif defined(MS_WINDOWS)
    8649             :     DWORD n_bytes_returned;
    8650             :     DWORD io_result = 0;
    8651             :     HANDLE reparse_point_handle;
    8652             :     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    8653             :     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
    8654             :     PyObject *result = NULL;
    8655             : 
    8656             :     /* First get a handle to the reparse point */
    8657             :     Py_BEGIN_ALLOW_THREADS
    8658             :     reparse_point_handle = CreateFileW(
    8659             :         path->wide,
    8660             :         0,
    8661             :         0,
    8662             :         0,
    8663             :         OPEN_EXISTING,
    8664             :         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
    8665             :         0);
    8666             :     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
    8667             :         /* New call DeviceIoControl to read the reparse point */
    8668             :         io_result = DeviceIoControl(
    8669             :             reparse_point_handle,
    8670             :             FSCTL_GET_REPARSE_POINT,
    8671             :             0, 0, /* in buffer */
    8672             :             target_buffer, sizeof(target_buffer),
    8673             :             &n_bytes_returned,
    8674             :             0 /* we're not using OVERLAPPED_IO */
    8675             :             );
    8676             :         CloseHandle(reparse_point_handle);
    8677             :     }
    8678             :     Py_END_ALLOW_THREADS
    8679             : 
    8680             :     if (io_result == 0) {
    8681             :         return path_error(path);
    8682             :     }
    8683             : 
    8684             :     wchar_t *name = NULL;
    8685             :     Py_ssize_t nameLen = 0;
    8686             :     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
    8687             :     {
    8688             :         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
    8689             :                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
    8690             :         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
    8691             :     }
    8692             :     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
    8693             :     {
    8694             :         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
    8695             :                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
    8696             :         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
    8697             :     }
    8698             :     else
    8699             :     {
    8700             :         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
    8701             :     }
    8702             :     if (name) {
    8703             :         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
    8704             :             /* Our buffer is mutable, so this is okay */
    8705             :             name[1] = L'\\';
    8706             :         }
    8707             :         result = PyUnicode_FromWideChar(name, nameLen);
    8708             :         if (result && path->narrow) {
    8709             :             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
    8710             :         }
    8711             :     }
    8712             :     return result;
    8713             : #endif
    8714             : }
    8715             : #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
    8716             : 
    8717             : #if defined(MS_WINDOWS)
    8718             : 
    8719             : /* Remove the last portion of the path - return 0 on success */
    8720             : static int
    8721             : _dirnameW(WCHAR *path)
    8722             : {
    8723             :     WCHAR *ptr;
    8724             :     size_t length = wcsnlen_s(path, MAX_PATH);
    8725             :     if (length == MAX_PATH) {
    8726             :         return -1;
    8727             :     }
    8728             : 
    8729             :     /* walk the path from the end until a backslash is encountered */
    8730             :     for(ptr = path + length; ptr != path; ptr--) {
    8731             :         if (*ptr == L'\\' || *ptr == L'/') {
    8732             :             break;
    8733             :         }
    8734             :     }
    8735             :     *ptr = 0;
    8736             :     return 0;
    8737             : }
    8738             : 
    8739             : #endif
    8740             : 
    8741             : #ifdef HAVE_SYMLINK
    8742             : 
    8743             : #if defined(MS_WINDOWS)
    8744             : 
    8745             : /* Is this path absolute? */
    8746             : static int
    8747             : _is_absW(const WCHAR *path)
    8748             : {
    8749             :     return path[0] == L'\\' || path[0] == L'/' ||
    8750             :         (path[0] && path[1] == L':');
    8751             : }
    8752             : 
    8753             : /* join root and rest with a backslash - return 0 on success */
    8754             : static int
    8755             : _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
    8756             : {
    8757             :     if (_is_absW(rest)) {
    8758             :         return wcscpy_s(dest_path, MAX_PATH, rest);
    8759             :     }
    8760             : 
    8761             :     if (wcscpy_s(dest_path, MAX_PATH, root)) {
    8762             :         return -1;
    8763             :     }
    8764             : 
    8765             :     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
    8766             :         return -1;
    8767             :     }
    8768             : 
    8769             :     return wcscat_s(dest_path, MAX_PATH, rest);
    8770             : }
    8771             : 
    8772             : /* Return True if the path at src relative to dest is a directory */
    8773             : static int
    8774             : _check_dirW(LPCWSTR src, LPCWSTR dest)
    8775             : {
    8776             :     WIN32_FILE_ATTRIBUTE_DATA src_info;
    8777             :     WCHAR dest_parent[MAX_PATH];
    8778             :     WCHAR src_resolved[MAX_PATH] = L"";
    8779             : 
    8780             :     /* dest_parent = os.path.dirname(dest) */
    8781             :     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
    8782             :         _dirnameW(dest_parent)) {
    8783             :         return 0;
    8784             :     }
    8785             :     /* src_resolved = os.path.join(dest_parent, src) */
    8786             :     if (_joinW(src_resolved, dest_parent, src)) {
    8787             :         return 0;
    8788             :     }
    8789             :     return (
    8790             :         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
    8791             :         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
    8792             :     );
    8793             : }
    8794             : #endif
    8795             : 
    8796             : 
    8797             : /*[clinic input]
    8798             : os.symlink
    8799             :     src: path_t
    8800             :     dst: path_t
    8801             :     target_is_directory: bool = False
    8802             :     *
    8803             :     dir_fd: dir_fd(requires='symlinkat')=None
    8804             : 
    8805             : # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
    8806             : 
    8807             : Create a symbolic link pointing to src named dst.
    8808             : 
    8809             : target_is_directory is required on Windows if the target is to be
    8810             :   interpreted as a directory.  (On Windows, symlink requires
    8811             :   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
    8812             :   target_is_directory is ignored on non-Windows platforms.
    8813             : 
    8814             : If dir_fd is not None, it should be a file descriptor open to a directory,
    8815             :   and path should be relative; path will then be relative to that directory.
    8816             : dir_fd may not be implemented on your platform.
    8817             :   If it is unavailable, using it will raise a NotImplementedError.
    8818             : 
    8819             : [clinic start generated code]*/
    8820             : 
    8821             : static PyObject *
    8822        1309 : os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
    8823             :                 int target_is_directory, int dir_fd)
    8824             : /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
    8825             : {
    8826             : #ifdef MS_WINDOWS
    8827             :     DWORD result;
    8828             :     DWORD flags = 0;
    8829             : 
    8830             :     /* Assumed true, set to false if detected to not be available. */
    8831             :     static int windows_has_symlink_unprivileged_flag = TRUE;
    8832             : #else
    8833             :     int result;
    8834             : #ifdef HAVE_SYMLINKAT
    8835        1309 :     int symlinkat_unavailable = 0;
    8836             : #endif
    8837             : #endif
    8838             : 
    8839        1309 :     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
    8840             :                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
    8841           0 :         return NULL;
    8842             :     }
    8843             : 
    8844             : #ifdef MS_WINDOWS
    8845             : 
    8846             :     if (windows_has_symlink_unprivileged_flag) {
    8847             :         /* Allow non-admin symlinks if system allows it. */
    8848             :         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
    8849             :     }
    8850             : 
    8851             :     Py_BEGIN_ALLOW_THREADS
    8852             :     _Py_BEGIN_SUPPRESS_IPH
    8853             :     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
    8854             :     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
    8855             :         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
    8856             :     }
    8857             : 
    8858             :     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
    8859             :     _Py_END_SUPPRESS_IPH
    8860             :     Py_END_ALLOW_THREADS
    8861             : 
    8862             :     if (windows_has_symlink_unprivileged_flag && !result &&
    8863             :         ERROR_INVALID_PARAMETER == GetLastError()) {
    8864             : 
    8865             :         Py_BEGIN_ALLOW_THREADS
    8866             :         _Py_BEGIN_SUPPRESS_IPH
    8867             :         /* This error might be caused by
    8868             :         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
    8869             :         Try again, and update windows_has_symlink_unprivileged_flag if we
    8870             :         are successful this time.
    8871             : 
    8872             :         NOTE: There is a risk of a race condition here if there are other
    8873             :         conditions than the flag causing ERROR_INVALID_PARAMETER, and
    8874             :         another process (or thread) changes that condition in between our
    8875             :         calls to CreateSymbolicLink.
    8876             :         */
    8877             :         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
    8878             :         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
    8879             :         _Py_END_SUPPRESS_IPH
    8880             :         Py_END_ALLOW_THREADS
    8881             : 
    8882             :         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
    8883             :             windows_has_symlink_unprivileged_flag = FALSE;
    8884             :         }
    8885             :     }
    8886             : 
    8887             :     if (!result)
    8888             :         return path_error2(src, dst);
    8889             : 
    8890             : #else
    8891             : 
    8892        1309 :     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
    8893           0 :         PyErr_SetString(PyExc_ValueError,
    8894             :             "symlink: src and dst must be the same type");
    8895           0 :         return NULL;
    8896             :     }
    8897             : 
    8898        1309 :     Py_BEGIN_ALLOW_THREADS
    8899             : #ifdef HAVE_SYMLINKAT
    8900        1309 :     if (dir_fd != DEFAULT_DIR_FD) {
    8901             :         if (HAVE_SYMLINKAT_RUNTIME) {
    8902           1 :             result = symlinkat(src->narrow, dir_fd, dst->narrow);
    8903             :         } else {
    8904             :             symlinkat_unavailable = 1;
    8905             :         }
    8906             :     } else
    8907             : #endif
    8908        1308 :         result = symlink(src->narrow, dst->narrow);
    8909        1309 :     Py_END_ALLOW_THREADS
    8910             : 
    8911             : #ifdef HAVE_SYMLINKAT
    8912        1309 :     if (symlinkat_unavailable) {
    8913           0 :           argument_unavailable_error(NULL, "dir_fd");
    8914           0 :           return NULL;
    8915             :     }
    8916             : #endif
    8917             : 
    8918        1309 :     if (result)
    8919           0 :         return path_error2(src, dst);
    8920             : #endif
    8921             : 
    8922        1309 :     Py_RETURN_NONE;
    8923             : }
    8924             : #endif /* HAVE_SYMLINK */
    8925             : 
    8926             : 
    8927             : 
    8928             : 
    8929             : static PyStructSequence_Field times_result_fields[] = {
    8930             :     {"user",    "user time"},
    8931             :     {"system",   "system time"},
    8932             :     {"children_user",    "user time of children"},
    8933             :     {"children_system",    "system time of children"},
    8934             :     {"elapsed",    "elapsed time since an arbitrary point in the past"},
    8935             :     {NULL}
    8936             : };
    8937             : 
    8938             : PyDoc_STRVAR(times_result__doc__,
    8939             : "times_result: Result from os.times().\n\n\
    8940             : This object may be accessed either as a tuple of\n\
    8941             :   (user, system, children_user, children_system, elapsed),\n\
    8942             : or via the attributes user, system, children_user, children_system,\n\
    8943             : and elapsed.\n\
    8944             : \n\
    8945             : See os.times for more information.");
    8946             : 
    8947             : static PyStructSequence_Desc times_result_desc = {
    8948             :     "times_result", /* name */
    8949             :     times_result__doc__, /* doc */
    8950             :     times_result_fields,
    8951             :     5
    8952             : };
    8953             : 
    8954             : #ifdef MS_WINDOWS
    8955             : #define HAVE_TIMES  /* mandatory, for the method table */
    8956             : #endif
    8957             : 
    8958             : #ifdef HAVE_TIMES
    8959             : 
    8960             : static PyObject *
    8961           2 : build_times_result(PyObject *module, double user, double system,
    8962             :     double children_user, double children_system,
    8963             :     double elapsed)
    8964             : {
    8965           2 :     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
    8966           2 :     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
    8967           2 :     if (value == NULL)
    8968           0 :         return NULL;
    8969             : 
    8970             : #define SET(i, field) \
    8971             :     { \
    8972             :     PyObject *o = PyFloat_FromDouble(field); \
    8973             :     if (!o) { \
    8974             :         Py_DECREF(value); \
    8975             :         return NULL; \
    8976             :     } \
    8977             :     PyStructSequence_SET_ITEM(value, i, o); \
    8978             :     } \
    8979             : 
    8980           2 :     SET(0, user);
    8981           2 :     SET(1, system);
    8982           2 :     SET(2, children_user);
    8983           2 :     SET(3, children_system);
    8984           2 :     SET(4, elapsed);
    8985             : 
    8986             : #undef SET
    8987             : 
    8988           2 :     return value;
    8989             : }
    8990             : 
    8991             : 
    8992             : #ifndef MS_WINDOWS
    8993             : #define NEED_TICKS_PER_SECOND
    8994             : static long ticks_per_second = -1;
    8995             : #endif /* MS_WINDOWS */
    8996             : 
    8997             : /*[clinic input]
    8998             : os.times
    8999             : 
    9000             : Return a collection containing process timing information.
    9001             : 
    9002             : The object returned behaves like a named tuple with these fields:
    9003             :   (utime, stime, cutime, cstime, elapsed_time)
    9004             : All fields are floating point numbers.
    9005             : [clinic start generated code]*/
    9006             : 
    9007             : static PyObject *
    9008           2 : os_times_impl(PyObject *module)
    9009             : /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
    9010             : #ifdef MS_WINDOWS
    9011             : {
    9012             :     FILETIME create, exit, kernel, user;
    9013             :     HANDLE hProc;
    9014             :     hProc = GetCurrentProcess();
    9015             :     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
    9016             :     /* The fields of a FILETIME structure are the hi and lo part
    9017             :        of a 64-bit value expressed in 100 nanosecond units.
    9018             :        1e7 is one second in such units; 1e-7 the inverse.
    9019             :        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
    9020             :     */
    9021             :     return build_times_result(module,
    9022             :         (double)(user.dwHighDateTime*429.4967296 +
    9023             :                  user.dwLowDateTime*1e-7),
    9024             :         (double)(kernel.dwHighDateTime*429.4967296 +
    9025             :                  kernel.dwLowDateTime*1e-7),
    9026             :         (double)0,
    9027             :         (double)0,
    9028             :         (double)0);
    9029             : }
    9030             : #else /* MS_WINDOWS */
    9031             : {
    9032             : 
    9033             : 
    9034             :     struct tms t;
    9035             :     clock_t c;
    9036           2 :     errno = 0;
    9037           2 :     c = times(&t);
    9038           2 :     if (c == (clock_t) -1)
    9039           0 :         return posix_error();
    9040           2 :     return build_times_result(module,
    9041           2 :                          (double)t.tms_utime / ticks_per_second,
    9042           2 :                          (double)t.tms_stime / ticks_per_second,
    9043           2 :                          (double)t.tms_cutime / ticks_per_second,
    9044           2 :                          (double)t.tms_cstime / ticks_per_second,
    9045           2 :                          (double)c / ticks_per_second);
    9046             : }
    9047             : #endif /* MS_WINDOWS */
    9048             : #endif /* HAVE_TIMES */
    9049             : 
    9050             : 
    9051             : #ifdef HAVE_GETSID
    9052             : /*[clinic input]
    9053             : os.getsid
    9054             : 
    9055             :     pid: pid_t
    9056             :     /
    9057             : 
    9058             : Call the system call getsid(pid) and return the result.
    9059             : [clinic start generated code]*/
    9060             : 
    9061             : static PyObject *
    9062           6 : os_getsid_impl(PyObject *module, pid_t pid)
    9063             : /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
    9064             : {
    9065             :     int sid;
    9066           6 :     sid = getsid(pid);
    9067           6 :     if (sid < 0)
    9068           0 :         return posix_error();
    9069           6 :     return PyLong_FromLong((long)sid);
    9070             : }
    9071             : #endif /* HAVE_GETSID */
    9072             : 
    9073             : 
    9074             : #ifdef HAVE_SETSID
    9075             : /*[clinic input]
    9076             : os.setsid
    9077             : 
    9078             : Call the system call setsid().
    9079             : [clinic start generated code]*/
    9080             : 
    9081             : static PyObject *
    9082           0 : os_setsid_impl(PyObject *module)
    9083             : /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
    9084             : {
    9085           0 :     if (setsid() < 0)
    9086           0 :         return posix_error();
    9087           0 :     Py_RETURN_NONE;
    9088             : }
    9089             : #endif /* HAVE_SETSID */
    9090             : 
    9091             : 
    9092             : #ifdef HAVE_SETPGID
    9093             : /*[clinic input]
    9094             : os.setpgid
    9095             : 
    9096             :     pid: pid_t
    9097             :     pgrp: pid_t
    9098             :     /
    9099             : 
    9100             : Call the system call setpgid(pid, pgrp).
    9101             : [clinic start generated code]*/
    9102             : 
    9103             : static PyObject *
    9104           0 : os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
    9105             : /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
    9106             : {
    9107           0 :     if (setpgid(pid, pgrp) < 0)
    9108           0 :         return posix_error();
    9109           0 :     Py_RETURN_NONE;
    9110             : }
    9111             : #endif /* HAVE_SETPGID */
    9112             : 
    9113             : 
    9114             : #ifdef HAVE_TCGETPGRP
    9115             : /*[clinic input]
    9116             : os.tcgetpgrp
    9117             : 
    9118             :     fd: int
    9119             :     /
    9120             : 
    9121             : Return the process group associated with the terminal specified by fd.
    9122             : [clinic start generated code]*/
    9123             : 
    9124             : static PyObject *
    9125           1 : os_tcgetpgrp_impl(PyObject *module, int fd)
    9126             : /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
    9127             : {
    9128           1 :     pid_t pgid = tcgetpgrp(fd);
    9129           1 :     if (pgid < 0)
    9130           1 :         return posix_error();
    9131           0 :     return PyLong_FromPid(pgid);
    9132             : }
    9133             : #endif /* HAVE_TCGETPGRP */
    9134             : 
    9135             : 
    9136             : #ifdef HAVE_TCSETPGRP
    9137             : /*[clinic input]
    9138             : os.tcsetpgrp
    9139             : 
    9140             :     fd: int
    9141             :     pgid: pid_t
    9142             :     /
    9143             : 
    9144             : Set the process group associated with the terminal specified by fd.
    9145             : [clinic start generated code]*/
    9146             : 
    9147             : static PyObject *
    9148           1 : os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
    9149             : /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
    9150             : {
    9151           1 :     if (tcsetpgrp(fd, pgid) < 0)
    9152           1 :         return posix_error();
    9153           0 :     Py_RETURN_NONE;
    9154             : }
    9155             : #endif /* HAVE_TCSETPGRP */
    9156             : 
    9157             : /* Functions acting on file descriptors */
    9158             : 
    9159             : #ifdef O_CLOEXEC
    9160             : extern int _Py_open_cloexec_works;
    9161             : #endif
    9162             : 
    9163             : 
    9164             : /*[clinic input]
    9165             : os.open -> int
    9166             :     path: path_t
    9167             :     flags: int
    9168             :     mode: int = 0o777
    9169             :     *
    9170             :     dir_fd: dir_fd(requires='openat') = None
    9171             : 
    9172             : # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
    9173             : 
    9174             : Open a file for low level IO.  Returns a file descriptor (integer).
    9175             : 
    9176             : If dir_fd is not None, it should be a file descriptor open to a directory,
    9177             :   and path should be relative; path will then be relative to that directory.
    9178             : dir_fd may not be implemented on your platform.
    9179             :   If it is unavailable, using it will raise a NotImplementedError.
    9180             : [clinic start generated code]*/
    9181             : 
    9182             : static int
    9183       32305 : os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
    9184             : /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
    9185             : {
    9186             :     int fd;
    9187       32305 :     int async_err = 0;
    9188             : #ifdef HAVE_OPENAT
    9189       32305 :     int openat_unavailable = 0;
    9190             : #endif
    9191             : 
    9192             : #ifdef O_CLOEXEC
    9193       32305 :     int *atomic_flag_works = &_Py_open_cloexec_works;
    9194             : #elif !defined(MS_WINDOWS)
    9195             :     int *atomic_flag_works = NULL;
    9196             : #endif
    9197             : 
    9198             : #ifdef MS_WINDOWS
    9199             :     flags |= O_NOINHERIT;
    9200             : #elif defined(O_CLOEXEC)
    9201       32305 :     flags |= O_CLOEXEC;
    9202             : #endif
    9203             : 
    9204       32305 :     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
    9205           0 :         return -1;
    9206             :     }
    9207             : 
    9208             :     _Py_BEGIN_SUPPRESS_IPH
    9209             :     do {
    9210       32311 :         Py_BEGIN_ALLOW_THREADS
    9211             : #ifdef MS_WINDOWS
    9212             :         fd = _wopen(path->wide, flags, mode);
    9213             : #else
    9214             : #ifdef HAVE_OPENAT
    9215       32311 :         if (dir_fd != DEFAULT_DIR_FD) {
    9216             :             if (HAVE_OPENAT_RUNTIME) {
    9217       10126 :                 fd = openat(dir_fd, path->narrow, flags, mode);
    9218             : 
    9219             :             } else {
    9220             :                 openat_unavailable = 1;
    9221             :                 fd = -1;
    9222             :             }
    9223             :         } else
    9224             : #endif /* HAVE_OPENAT */
    9225       22185 :             fd = open(path->narrow, flags, mode);
    9226             : #endif /* !MS_WINDOWS */
    9227       32311 :         Py_END_ALLOW_THREADS
    9228       32311 :     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    9229             :     _Py_END_SUPPRESS_IPH
    9230             : 
    9231             : #ifdef HAVE_OPENAT
    9232       32305 :     if (openat_unavailable) {
    9233           0 :         argument_unavailable_error(NULL, "dir_fd");
    9234           0 :         return -1;
    9235             :     }
    9236             : #endif
    9237             : 
    9238       32305 :     if (fd < 0) {
    9239         734 :         if (!async_err)
    9240         734 :             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
    9241         734 :         return -1;
    9242             :     }
    9243             : 
    9244             : #ifndef MS_WINDOWS
    9245       31571 :     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
    9246           0 :         close(fd);
    9247           0 :         return -1;
    9248             :     }
    9249             : #endif
    9250             : 
    9251       31571 :     return fd;
    9252             : }
    9253             : 
    9254             : 
    9255             : /*[clinic input]
    9256             : os.close
    9257             : 
    9258             :     fd: int
    9259             : 
    9260             : Close a file descriptor.
    9261             : [clinic start generated code]*/
    9262             : 
    9263             : static PyObject *
    9264       61929 : os_close_impl(PyObject *module, int fd)
    9265             : /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
    9266             : {
    9267             :     int res;
    9268             :     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
    9269             :      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
    9270             :      * for more details.
    9271             :      */
    9272       61929 :     Py_BEGIN_ALLOW_THREADS
    9273             :     _Py_BEGIN_SUPPRESS_IPH
    9274       61929 :     res = close(fd);
    9275             :     _Py_END_SUPPRESS_IPH
    9276       61929 :     Py_END_ALLOW_THREADS
    9277       61929 :     if (res < 0)
    9278          25 :         return posix_error();
    9279       61904 :     Py_RETURN_NONE;
    9280             : }
    9281             : 
    9282             : /*[clinic input]
    9283             : os.closerange
    9284             : 
    9285             :     fd_low: int
    9286             :     fd_high: int
    9287             :     /
    9288             : 
    9289             : Closes all file descriptors in [fd_low, fd_high), ignoring errors.
    9290             : [clinic start generated code]*/
    9291             : 
    9292             : static PyObject *
    9293           2 : os_closerange_impl(PyObject *module, int fd_low, int fd_high)
    9294             : /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
    9295             : {
    9296           2 :     Py_BEGIN_ALLOW_THREADS
    9297           2 :     _Py_closerange(fd_low, fd_high - 1);
    9298           2 :     Py_END_ALLOW_THREADS
    9299           2 :     Py_RETURN_NONE;
    9300             : }
    9301             : 
    9302             : 
    9303             : /*[clinic input]
    9304             : os.dup -> int
    9305             : 
    9306             :     fd: int
    9307             :     /
    9308             : 
    9309             : Return a duplicate of a file descriptor.
    9310             : [clinic start generated code]*/
    9311             : 
    9312             : static int
    9313        1434 : os_dup_impl(PyObject *module, int fd)
    9314             : /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
    9315             : {
    9316        1434 :     return _Py_dup(fd);
    9317             : }
    9318             : 
    9319             : 
    9320             : /*[clinic input]
    9321             : os.dup2 -> int
    9322             :     fd: int
    9323             :     fd2: int
    9324             :     inheritable: bool=True
    9325             : 
    9326             : Duplicate file descriptor.
    9327             : [clinic start generated code]*/
    9328             : 
    9329             : static int
    9330         411 : os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
    9331             : /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
    9332             : {
    9333         411 :     int res = 0;
    9334             : #if defined(HAVE_DUP3) && \
    9335             :     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
    9336             :     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
    9337             :     static int dup3_works = -1;
    9338             : #endif
    9339             : 
    9340         411 :     if (fd < 0 || fd2 < 0) {
    9341           0 :         posix_error();
    9342           0 :         return -1;
    9343             :     }
    9344             : 
    9345             :     /* dup2() can fail with EINTR if the target FD is already open, because it
    9346             :      * then has to be closed. See os_close_impl() for why we don't handle EINTR
    9347             :      * upon close(), and therefore below.
    9348             :      */
    9349             : #ifdef MS_WINDOWS
    9350             :     Py_BEGIN_ALLOW_THREADS
    9351             :     _Py_BEGIN_SUPPRESS_IPH
    9352             :     res = dup2(fd, fd2);
    9353             :     _Py_END_SUPPRESS_IPH
    9354             :     Py_END_ALLOW_THREADS
    9355             :     if (res < 0) {
    9356             :         posix_error();
    9357             :         return -1;
    9358             :     }
    9359             :     res = fd2; // msvcrt dup2 returns 0 on success.
    9360             : 
    9361             :     /* Character files like console cannot be make non-inheritable */
    9362             :     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
    9363             :         close(fd2);
    9364             :         return -1;
    9365             :     }
    9366             : 
    9367             : #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
    9368             :     Py_BEGIN_ALLOW_THREADS
    9369             :     if (!inheritable)
    9370             :         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
    9371             :     else
    9372             :         res = dup2(fd, fd2);
    9373             :     Py_END_ALLOW_THREADS
    9374             :     if (res < 0) {
    9375             :         posix_error();
    9376             :         return -1;
    9377             :     }
    9378             : 
    9379             : #else
    9380             : 
    9381             : #ifdef HAVE_DUP3
    9382         411 :     if (!inheritable && dup3_works != 0) {
    9383           1 :         Py_BEGIN_ALLOW_THREADS
    9384           1 :         res = dup3(fd, fd2, O_CLOEXEC);
    9385           1 :         Py_END_ALLOW_THREADS
    9386           1 :         if (res < 0) {
    9387           0 :             if (dup3_works == -1)
    9388           0 :                 dup3_works = (errno != ENOSYS);
    9389           0 :             if (dup3_works) {
    9390           0 :                 posix_error();
    9391           0 :                 return -1;
    9392             :             }
    9393             :         }
    9394             :     }
    9395             : 
    9396         411 :     if (inheritable || dup3_works == 0)
    9397             :     {
    9398             : #endif
    9399         410 :         Py_BEGIN_ALLOW_THREADS
    9400         410 :         res = dup2(fd, fd2);
    9401         410 :         Py_END_ALLOW_THREADS
    9402         410 :         if (res < 0) {
    9403           1 :             posix_error();
    9404           1 :             return -1;
    9405             :         }
    9406             : 
    9407         409 :         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
    9408           0 :             close(fd2);
    9409           0 :             return -1;
    9410             :         }
    9411             : #ifdef HAVE_DUP3
    9412             :     }
    9413             : #endif
    9414             : 
    9415             : #endif
    9416             : 
    9417         410 :     return res;
    9418             : }
    9419             : 
    9420             : 
    9421             : #ifdef HAVE_LOCKF
    9422             : /*[clinic input]
    9423             : os.lockf
    9424             : 
    9425             :     fd: int
    9426             :         An open file descriptor.
    9427             :     command: int
    9428             :         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
    9429             :     length: Py_off_t
    9430             :         The number of bytes to lock, starting at the current position.
    9431             :     /
    9432             : 
    9433             : Apply, test or remove a POSIX lock on an open file descriptor.
    9434             : 
    9435             : [clinic start generated code]*/
    9436             : 
    9437             : static PyObject *
    9438           2 : os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
    9439             : /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
    9440             : {
    9441             :     int res;
    9442             : 
    9443           2 :     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
    9444           0 :         return NULL;
    9445             :     }
    9446             : 
    9447           2 :     Py_BEGIN_ALLOW_THREADS
    9448           2 :     res = lockf(fd, command, length);
    9449           2 :     Py_END_ALLOW_THREADS
    9450             : 
    9451           2 :     if (res < 0)
    9452           0 :         return posix_error();
    9453             : 
    9454           2 :     Py_RETURN_NONE;
    9455             : }
    9456             : #endif /* HAVE_LOCKF */
    9457             : 
    9458             : 
    9459             : /*[clinic input]
    9460             : os.lseek -> Py_off_t
    9461             : 
    9462             :     fd: int
    9463             :     position: Py_off_t
    9464             :     how: int
    9465             :     /
    9466             : 
    9467             : Set the position of a file descriptor.  Return the new position.
    9468             : 
    9469             : Return the new cursor position in number of bytes
    9470             : relative to the beginning of the file.
    9471             : [clinic start generated code]*/
    9472             : 
    9473             : static Py_off_t
    9474        8399 : os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
    9475             : /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
    9476             : {
    9477             :     Py_off_t result;
    9478             : 
    9479             : #ifdef SEEK_SET
    9480             :     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
    9481        8399 :     switch (how) {
    9482        2044 :         case 0: how = SEEK_SET; break;
    9483        6258 :         case 1: how = SEEK_CUR; break;
    9484          85 :         case 2: how = SEEK_END; break;
    9485             :     }
    9486             : #endif /* SEEK_END */
    9487             : 
    9488        8399 :     Py_BEGIN_ALLOW_THREADS
    9489             :     _Py_BEGIN_SUPPRESS_IPH
    9490             : #ifdef MS_WINDOWS
    9491             :     result = _lseeki64(fd, position, how);
    9492             : #else
    9493        8399 :     result = lseek(fd, position, how);
    9494             : #endif
    9495             :     _Py_END_SUPPRESS_IPH
    9496        8399 :     Py_END_ALLOW_THREADS
    9497        8399 :     if (result < 0)
    9498          37 :         posix_error();
    9499             : 
    9500        8399 :     return result;
    9501             : }
    9502             : 
    9503             : 
    9504             : /*[clinic input]
    9505             : os.read
    9506             :     fd: int
    9507             :     length: Py_ssize_t
    9508             :     /
    9509             : 
    9510             : Read from a file descriptor.  Returns a bytes object.
    9511             : [clinic start generated code]*/
    9512             : 
    9513             : static PyObject *
    9514      178712 : os_read_impl(PyObject *module, int fd, Py_ssize_t length)
    9515             : /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
    9516             : {
    9517             :     Py_ssize_t n;
    9518             :     PyObject *buffer;
    9519             : 
    9520      178712 :     if (length < 0) {
    9521           0 :         errno = EINVAL;
    9522           0 :         return posix_error();
    9523             :     }
    9524             : 
    9525      178712 :     length = Py_MIN(length, _PY_READ_MAX);
    9526             : 
    9527      178712 :     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
    9528      178712 :     if (buffer == NULL)
    9529           0 :         return NULL;
    9530             : 
    9531      178712 :     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
    9532      178710 :     if (n == -1) {
    9533          30 :         Py_DECREF(buffer);
    9534          30 :         return NULL;
    9535             :     }
    9536             : 
    9537      178680 :     if (n != length)
    9538       36880 :         _PyBytes_Resize(&buffer, n);
    9539             : 
    9540      178680 :     return buffer;
    9541             : }
    9542             : 
    9543             : #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
    9544             :                                 || defined(__APPLE__))) \
    9545             :     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
    9546             :     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
    9547             : static int
    9548           9 : iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
    9549             : {
    9550             :     Py_ssize_t i, j;
    9551             : 
    9552           9 :     *iov = PyMem_New(struct iovec, cnt);
    9553           9 :     if (*iov == NULL) {
    9554           0 :         PyErr_NoMemory();
    9555           0 :         return -1;
    9556             :     }
    9557             : 
    9558           9 :     *buf = PyMem_New(Py_buffer, cnt);
    9559           9 :     if (*buf == NULL) {
    9560           0 :         PyMem_Free(*iov);
    9561           0 :         PyErr_NoMemory();
    9562           0 :         return -1;
    9563             :     }
    9564             : 
    9565          26 :     for (i = 0; i < cnt; i++) {
    9566          17 :         PyObject *item = PySequence_GetItem(seq, i);
    9567          17 :         if (item == NULL)
    9568           0 :             goto fail;
    9569          17 :         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
    9570           0 :             Py_DECREF(item);
    9571           0 :             goto fail;
    9572             :         }
    9573          17 :         Py_DECREF(item);
    9574          17 :         (*iov)[i].iov_base = (*buf)[i].buf;
    9575          17 :         (*iov)[i].iov_len = (*buf)[i].len;
    9576             :     }
    9577           9 :     return 0;
    9578             : 
    9579           0 : fail:
    9580           0 :     PyMem_Free(*iov);
    9581           0 :     for (j = 0; j < i; j++) {
    9582           0 :         PyBuffer_Release(&(*buf)[j]);
    9583             :     }
    9584           0 :     PyMem_Free(*buf);
    9585           0 :     return -1;
    9586             : }
    9587             : 
    9588             : static void
    9589           9 : iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
    9590             : {
    9591             :     int i;
    9592           9 :     PyMem_Free(iov);
    9593          26 :     for (i = 0; i < cnt; i++) {
    9594          17 :         PyBuffer_Release(&buf[i]);
    9595             :     }
    9596           9 :     PyMem_Free(buf);
    9597           9 : }
    9598             : #endif
    9599             : 
    9600             : 
    9601             : #ifdef HAVE_READV
    9602             : /*[clinic input]
    9603             : os.readv -> Py_ssize_t
    9604             : 
    9605             :     fd: int
    9606             :     buffers: object
    9607             :     /
    9608             : 
    9609             : Read from a file descriptor fd into an iterable of buffers.
    9610             : 
    9611             : The buffers should be mutable buffers accepting bytes.
    9612             : readv will transfer data into each buffer until it is full
    9613             : and then move on to the next buffer in the sequence to hold
    9614             : the rest of the data.
    9615             : 
    9616             : readv returns the total number of bytes read,
    9617             : which may be less than the total capacity of all the buffers.
    9618             : [clinic start generated code]*/
    9619             : 
    9620             : static Py_ssize_t
    9621           3 : os_readv_impl(PyObject *module, int fd, PyObject *buffers)
    9622             : /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
    9623             : {
    9624             :     Py_ssize_t cnt, n;
    9625           3 :     int async_err = 0;
    9626             :     struct iovec *iov;
    9627             :     Py_buffer *buf;
    9628             : 
    9629           3 :     if (!PySequence_Check(buffers)) {
    9630           0 :         PyErr_SetString(PyExc_TypeError,
    9631             :             "readv() arg 2 must be a sequence");
    9632           0 :         return -1;
    9633             :     }
    9634             : 
    9635           3 :     cnt = PySequence_Size(buffers);
    9636           3 :     if (cnt < 0)
    9637           0 :         return -1;
    9638             : 
    9639           3 :     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
    9640           0 :         return -1;
    9641             : 
    9642             :     do {
    9643           3 :         Py_BEGIN_ALLOW_THREADS
    9644           3 :         n = readv(fd, iov, cnt);
    9645           3 :         Py_END_ALLOW_THREADS
    9646           3 :     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    9647             : 
    9648           3 :     iov_cleanup(iov, buf, cnt);
    9649           3 :     if (n < 0) {
    9650           1 :         if (!async_err)
    9651           1 :             posix_error();
    9652           1 :         return -1;
    9653             :     }
    9654             : 
    9655           2 :     return n;
    9656             : }
    9657             : #endif /* HAVE_READV */
    9658             : 
    9659             : 
    9660             : #ifdef HAVE_PREAD
    9661             : /*[clinic input]
    9662             : os.pread
    9663             : 
    9664             :     fd: int
    9665             :     length: Py_ssize_t
    9666             :     offset: Py_off_t
    9667             :     /
    9668             : 
    9669             : Read a number of bytes from a file descriptor starting at a particular offset.
    9670             : 
    9671             : Read length bytes from file descriptor fd, starting at offset bytes from
    9672             : the beginning of the file.  The file offset remains unchanged.
    9673             : [clinic start generated code]*/
    9674             : 
    9675             : static PyObject *
    9676           1 : os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
    9677             : /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
    9678             : {
    9679             :     Py_ssize_t n;
    9680           1 :     int async_err = 0;
    9681             :     PyObject *buffer;
    9682             : 
    9683           1 :     if (length < 0) {
    9684           0 :         errno = EINVAL;
    9685           0 :         return posix_error();
    9686             :     }
    9687           1 :     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
    9688           1 :     if (buffer == NULL)
    9689           0 :         return NULL;
    9690             : 
    9691             :     do {
    9692           1 :         Py_BEGIN_ALLOW_THREADS
    9693             :         _Py_BEGIN_SUPPRESS_IPH
    9694           1 :         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
    9695             :         _Py_END_SUPPRESS_IPH
    9696           1 :         Py_END_ALLOW_THREADS
    9697           1 :     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    9698             : 
    9699           1 :     if (n < 0) {
    9700           0 :         Py_DECREF(buffer);
    9701           0 :         return (!async_err) ? posix_error() : NULL;
    9702             :     }
    9703           1 :     if (n != length)
    9704           0 :         _PyBytes_Resize(&buffer, n);
    9705           1 :     return buffer;
    9706             : }
    9707             : #endif /* HAVE_PREAD */
    9708             : 
    9709             : #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
    9710             : /*[clinic input]
    9711             : os.preadv -> Py_ssize_t
    9712             : 
    9713             :     fd: int
    9714             :     buffers: object
    9715             :     offset: Py_off_t
    9716             :     flags: int = 0
    9717             :     /
    9718             : 
    9719             : Reads from a file descriptor into a number of mutable bytes-like objects.
    9720             : 
    9721             : Combines the functionality of readv() and pread(). As readv(), it will
    9722             : transfer data into each buffer until it is full and then move on to the next
    9723             : buffer in the sequence to hold the rest of the data. Its fourth argument,
    9724             : specifies the file offset at which the input operation is to be performed. It
    9725             : will return the total number of bytes read (which can be less than the total
    9726             : capacity of all the objects).
    9727             : 
    9728             : The flags argument contains a bitwise OR of zero or more of the following flags:
    9729             : 
    9730             : - RWF_HIPRI
    9731             : - RWF_NOWAIT
    9732             : 
    9733             : Using non-zero flags requires Linux 4.6 or newer.
    9734             : [clinic start generated code]*/
    9735             : 
    9736             : static Py_ssize_t
    9737           2 : os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
    9738             :                int flags)
    9739             : /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
    9740             : {
    9741             :     Py_ssize_t cnt, n;
    9742           2 :     int async_err = 0;
    9743             :     struct iovec *iov;
    9744             :     Py_buffer *buf;
    9745             : 
    9746           2 :     if (!PySequence_Check(buffers)) {
    9747           0 :         PyErr_SetString(PyExc_TypeError,
    9748             :             "preadv2() arg 2 must be a sequence");
    9749           0 :         return -1;
    9750             :     }
    9751             : 
    9752           2 :     cnt = PySequence_Size(buffers);
    9753           2 :     if (cnt < 0) {
    9754           0 :         return -1;
    9755             :     }
    9756             : 
    9757             : #ifndef HAVE_PREADV2
    9758             :     if(flags != 0) {
    9759             :         argument_unavailable_error("preadv2", "flags");
    9760             :         return -1;
    9761             :     }
    9762             : #endif
    9763             : 
    9764           2 :     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
    9765           0 :         return -1;
    9766             :     }
    9767             : #ifdef HAVE_PREADV2
    9768             :     do {
    9769           2 :         Py_BEGIN_ALLOW_THREADS
    9770             :         _Py_BEGIN_SUPPRESS_IPH
    9771           2 :         n = preadv2(fd, iov, cnt, offset, flags);
    9772             :         _Py_END_SUPPRESS_IPH
    9773           2 :         Py_END_ALLOW_THREADS
    9774           2 :     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    9775             : #else
    9776             :     do {
    9777             : #ifdef __APPLE__
    9778             : /* This entire function will be removed from the module dict when the API
    9779             :  * is not available.
    9780             :  */
    9781             : #pragma clang diagnostic push
    9782             : #pragma clang diagnostic ignored "-Wunguarded-availability"
    9783             : #pragma clang diagnostic ignored "-Wunguarded-availability-new"
    9784             : #endif
    9785             :         Py_BEGIN_ALLOW_THREADS
    9786             :         _Py_BEGIN_SUPPRESS_IPH
    9787             :         n = preadv(fd, iov, cnt, offset);
    9788             :         _Py_END_SUPPRESS_IPH
    9789             :         Py_END_ALLOW_THREADS
    9790             :     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    9791             : 
    9792             : #ifdef __APPLE__
    9793             : #pragma clang diagnostic pop
    9794             : #endif
    9795             : 
    9796             : #endif
    9797             : 
    9798           2 :     iov_cleanup(iov, buf, cnt);
    9799           2 :     if (n < 0) {
    9800           0 :         if (!async_err) {
    9801           0 :             posix_error();
    9802             :         }
    9803           0 :         return -1;
    9804             :     }
    9805             : 
    9806           2 :     return n;
    9807             : }
    9808             : #endif /* HAVE_PREADV */
    9809             : 
    9810             : 
    9811             : /*[clinic input]
    9812             : os.write -> Py_ssize_t
    9813             : 
    9814             :     fd: int
    9815             :     data: Py_buffer
    9816             :     /
    9817             : 
    9818             : Write a bytes object to a file descriptor.
    9819             : [clinic start generated code]*/
    9820             : 
    9821             : static Py_ssize_t
    9822       83228 : os_write_impl(PyObject *module, int fd, Py_buffer *data)
    9823             : /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
    9824             : {
    9825       83228 :     return _Py_write(fd, data->buf, data->len);
    9826             : }
    9827             : 
    9828             : #ifdef HAVE_SENDFILE
    9829             : #ifdef __APPLE__
    9830             : /*[clinic input]
    9831             : os.sendfile
    9832             : 
    9833             :     out_fd: int
    9834             :     in_fd: int
    9835             :     offset: Py_off_t
    9836             :     count as sbytes: Py_off_t
    9837             :     headers: object(c_default="NULL") = ()
    9838             :     trailers: object(c_default="NULL") = ()
    9839             :     flags: int = 0
    9840             : 
    9841             : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
    9842             : [clinic start generated code]*/
    9843             : 
    9844             : static PyObject *
    9845             : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
    9846             :                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
    9847             :                  int flags)
    9848             : /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
    9849             : #elif defined(__FreeBSD__) || defined(__DragonFly__)
    9850             : /*[clinic input]
    9851             : os.sendfile
    9852             : 
    9853             :     out_fd: int
    9854             :     in_fd: int
    9855             :     offset: Py_off_t
    9856             :     count: Py_ssize_t
    9857             :     headers: object(c_default="NULL") = ()
    9858             :     trailers: object(c_default="NULL") = ()
    9859             :     flags: int = 0
    9860             : 
    9861             : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
    9862             : [clinic start generated code]*/
    9863             : 
    9864             : static PyObject *
    9865             : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
    9866             :                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
    9867             :                  int flags)
    9868             : /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
    9869             : #else
    9870             : /*[clinic input]
    9871             : os.sendfile
    9872             : 
    9873             :     out_fd: int
    9874             :     in_fd: int
    9875             :     offset as offobj: object
    9876             :     count: Py_ssize_t
    9877             : 
    9878             : Copy count bytes from file descriptor in_fd to file descriptor out_fd.
    9879             : [clinic start generated code]*/
    9880             : 
    9881             : static PyObject *
    9882       21997 : os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
    9883             :                  Py_ssize_t count)
    9884             : /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
    9885             : #endif
    9886             : {
    9887             :     Py_ssize_t ret;
    9888       21997 :     int async_err = 0;
    9889             : 
    9890             : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
    9891             : #ifndef __APPLE__
    9892             :     off_t sbytes;
    9893             : #endif
    9894             :     Py_buffer *hbuf, *tbuf;
    9895             :     struct sf_hdtr sf;
    9896             : 
    9897             :     sf.headers = NULL;
    9898             :     sf.trailers = NULL;
    9899             : 
    9900             :     if (headers != NULL) {
    9901             :         if (!PySequence_Check(headers)) {
    9902             :             PyErr_SetString(PyExc_TypeError,
    9903             :                 "sendfile() headers must be a sequence");
    9904             :             return NULL;
    9905             :         } else {
    9906             :             Py_ssize_t i = PySequence_Size(headers);
    9907             :             if (i < 0)
    9908             :                 return NULL;
    9909             :             if (i > INT_MAX) {
    9910             :                 PyErr_SetString(PyExc_OverflowError,
    9911             :                     "sendfile() header is too large");
    9912             :                 return NULL;
    9913             :             }
    9914             :             if (i > 0) {
    9915             :                 sf.hdr_cnt = (int)i;
    9916             :                 if (iov_setup(&(sf.headers), &hbuf,
    9917             :                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
    9918             :                     return NULL;
    9919             : #ifdef __APPLE__
    9920             :                 for (i = 0; i < sf.hdr_cnt; i++) {
    9921             :                     Py_ssize_t blen = sf.headers[i].iov_len;
    9922             : # define OFF_T_MAX 0x7fffffffffffffff
    9923             :                     if (sbytes >= OFF_T_MAX - blen) {
    9924             :                         PyErr_SetString(PyExc_OverflowError,
    9925             :                             "sendfile() header is too large");
    9926             :                         return NULL;
    9927             :                     }
    9928             :                     sbytes += blen;
    9929             :                 }
    9930             : #endif
    9931             :             }
    9932             :         }
    9933             :     }
    9934             :     if (trailers != NULL) {
    9935             :         if (!PySequence_Check(trailers)) {
    9936             :             PyErr_SetString(PyExc_TypeError,
    9937             :                 "sendfile() trailers must be a sequence");
    9938             :             return NULL;
    9939             :         } else {
    9940             :             Py_ssize_t i = PySequence_Size(trailers);
    9941             :             if (i < 0)
    9942             :                 return NULL;
    9943             :             if (i > INT_MAX) {
    9944             :                 PyErr_SetString(PyExc_OverflowError,
    9945             :                     "sendfile() trailer is too large");
    9946             :                 return NULL;
    9947             :             }
    9948             :             if (i > 0) {
    9949             :                 sf.trl_cnt = (int)i;
    9950             :                 if (iov_setup(&(sf.trailers), &tbuf,
    9951             :                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
    9952             :                     return NULL;
    9953             :             }
    9954             :         }
    9955             :     }
    9956             : 
    9957             :     _Py_BEGIN_SUPPRESS_IPH
    9958             :     do {
    9959             :         Py_BEGIN_ALLOW_THREADS
    9960             : #ifdef __APPLE__
    9961             :         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
    9962             : #else
    9963             :         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
    9964             : #endif
    9965             :         Py_END_ALLOW_THREADS
    9966             :     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
    9967             :     _Py_END_SUPPRESS_IPH
    9968             : 
    9969             :     if (sf.headers != NULL)
    9970             :         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
    9971             :     if (sf.trailers != NULL)
    9972             :         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
    9973             : 
    9974             :     if (ret < 0) {
    9975             :         if ((errno == EAGAIN) || (errno == EBUSY)) {
    9976             :             if (sbytes != 0) {
    9977             :                 // some data has been sent
    9978             :                 goto done;
    9979             :             }
    9980             :             else {
    9981             :                 // no data has been sent; upper application is supposed
    9982             :                 // to retry on EAGAIN or EBUSY
    9983             :                 return posix_error();
    9984             :             }
    9985             :         }
    9986             :         return (!async_err) ? posix_error() : NULL;
    9987             :     }
    9988             :     goto done;
    9989             : 
    9990             : done:
    9991             :     #if !defined(HAVE_LARGEFILE_SUPPORT)
    9992             :         return Py_BuildValue("l", sbytes);
    9993             :     #else
    9994             :         return Py_BuildValue("L", sbytes);
    9995             :     #endif
    9996             : 
    9997             : #else
    9998             : #ifdef __linux__
    9999       21997 :     if (offobj == Py_None) {
   10000             :         do {
   10001           0 :             Py_BEGIN_ALLOW_THREADS
   10002           0 :             ret = sendfile(out_fd, in_fd, NULL, count);
   10003           0 :             Py_END_ALLOW_THREADS
   10004           0 :         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10005           0 :         if (ret < 0)
   10006           0 :             return (!async_err) ? posix_error() : NULL;
   10007           0 :         return Py_BuildValue("n", ret);
   10008             :     }
   10009             : #endif
   10010             :     off_t offset;
   10011       21997 :     if (!Py_off_t_converter(offobj, &offset))
   10012           0 :         return NULL;
   10013             : 
   10014             : #if defined(__sun) && defined(__SVR4)
   10015             :     // On Solaris, sendfile raises EINVAL rather than returning 0
   10016             :     // when the offset is equal or bigger than the in_fd size.
   10017             :     struct stat st;
   10018             : 
   10019             :     do {
   10020             :         Py_BEGIN_ALLOW_THREADS
   10021             :         ret = fstat(in_fd, &st);
   10022             :         Py_END_ALLOW_THREADS
   10023             :     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10024             :     if (ret < 0)
   10025             :         return (!async_err) ? posix_error() : NULL;
   10026             : 
   10027             :     if (offset >= st.st_size) {
   10028             :         return Py_BuildValue("i", 0);
   10029             :     }
   10030             : 
   10031             :     // On illumos specifically sendfile() may perform a partial write but
   10032             :     // return -1/an error (in one confirmed case the destination socket
   10033             :     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
   10034             :     // code to check if the offset parameter was modified by sendfile().
   10035             :     //
   10036             :     // We need this variable to track said change.
   10037             :     off_t original_offset = offset;
   10038             : #endif
   10039             : 
   10040             :     do {
   10041       21997 :         Py_BEGIN_ALLOW_THREADS
   10042       21997 :         ret = sendfile(out_fd, in_fd, &offset, count);
   10043             : #if defined(__sun) && defined(__SVR4)
   10044             :         // This handles illumos-specific sendfile() partial write behavior,
   10045             :         // see a comment above for more details.
   10046             :         if (ret < 0 && offset != original_offset) {
   10047             :             ret = offset - original_offset;
   10048             :         }
   10049             : #endif
   10050       21997 :         Py_END_ALLOW_THREADS
   10051       21997 :     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10052       21997 :     if (ret < 0)
   10053           6 :         return (!async_err) ? posix_error() : NULL;
   10054       21991 :     return Py_BuildValue("n", ret);
   10055             : #endif
   10056             : }
   10057             : #endif /* HAVE_SENDFILE */
   10058             : 
   10059             : 
   10060             : #if defined(__APPLE__)
   10061             : /*[clinic input]
   10062             : os._fcopyfile
   10063             : 
   10064             :     in_fd: int
   10065             :     out_fd: int
   10066             :     flags: int
   10067             :     /
   10068             : 
   10069             : Efficiently copy content or metadata of 2 regular file descriptors (macOS).
   10070             : [clinic start generated code]*/
   10071             : 
   10072             : static PyObject *
   10073             : os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
   10074             : /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
   10075             : {
   10076             :     int ret;
   10077             : 
   10078             :     Py_BEGIN_ALLOW_THREADS
   10079             :     ret = fcopyfile(in_fd, out_fd, NULL, flags);
   10080             :     Py_END_ALLOW_THREADS
   10081             :     if (ret < 0)
   10082             :         return posix_error();
   10083             :     Py_RETURN_NONE;
   10084             : }
   10085             : #endif
   10086             : 
   10087             : 
   10088             : /*[clinic input]
   10089             : os.fstat
   10090             : 
   10091             :     fd : int
   10092             : 
   10093             : Perform a stat system call on the given file descriptor.
   10094             : 
   10095             : Like stat(), but for an open file descriptor.
   10096             : Equivalent to os.stat(fd).
   10097             : [clinic start generated code]*/
   10098             : 
   10099             : static PyObject *
   10100     1079470 : os_fstat_impl(PyObject *module, int fd)
   10101             : /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
   10102             : {
   10103             :     STRUCT_STAT st;
   10104             :     int res;
   10105     1079470 :     int async_err = 0;
   10106             : 
   10107             :     do {
   10108     1079470 :         Py_BEGIN_ALLOW_THREADS
   10109     1079470 :         res = FSTAT(fd, &st);
   10110     1079470 :         Py_END_ALLOW_THREADS
   10111     1079470 :     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10112     1079470 :     if (res != 0) {
   10113             : #ifdef MS_WINDOWS
   10114             :         return PyErr_SetFromWindowsErr(0);
   10115             : #else
   10116     1048800 :         return (!async_err) ? posix_error() : NULL;
   10117             : #endif
   10118             :     }
   10119             : 
   10120       30667 :     return _pystat_fromstructstat(module, &st);
   10121             : }
   10122             : 
   10123             : 
   10124             : /*[clinic input]
   10125             : os.isatty -> bool
   10126             :     fd: int
   10127             :     /
   10128             : 
   10129             : Return True if the fd is connected to a terminal.
   10130             : 
   10131             : Return True if the file descriptor is an open file descriptor
   10132             : connected to the slave end of a terminal.
   10133             : [clinic start generated code]*/
   10134             : 
   10135             : static int
   10136        3604 : os_isatty_impl(PyObject *module, int fd)
   10137             : /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
   10138             : {
   10139             :     int return_value;
   10140        3604 :     Py_BEGIN_ALLOW_THREADS
   10141             :     _Py_BEGIN_SUPPRESS_IPH
   10142        3604 :     return_value = isatty(fd);
   10143             :     _Py_END_SUPPRESS_IPH
   10144        3604 :     Py_END_ALLOW_THREADS
   10145        3604 :     return return_value;
   10146             : }
   10147             : 
   10148             : 
   10149             : #ifdef HAVE_PIPE
   10150             : /*[clinic input]
   10151             : os.pipe
   10152             : 
   10153             : Create a pipe.
   10154             : 
   10155             : Returns a tuple of two file descriptors:
   10156             :   (read_fd, write_fd)
   10157             : [clinic start generated code]*/
   10158             : 
   10159             : static PyObject *
   10160       21079 : os_pipe_impl(PyObject *module)
   10161             : /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
   10162             : {
   10163             :     int fds[2];
   10164             : #ifdef MS_WINDOWS
   10165             :     HANDLE read, write;
   10166             :     SECURITY_ATTRIBUTES attr;
   10167             :     BOOL ok;
   10168             : #else
   10169             :     int res;
   10170             : #endif
   10171             : 
   10172             : #ifdef MS_WINDOWS
   10173             :     attr.nLength = sizeof(attr);
   10174             :     attr.lpSecurityDescriptor = NULL;
   10175             :     attr.bInheritHandle = FALSE;
   10176             : 
   10177             :     Py_BEGIN_ALLOW_THREADS
   10178             :     ok = CreatePipe(&read, &write, &attr, 0);
   10179             :     if (ok) {
   10180             :         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
   10181             :         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
   10182             :         if (fds[0] == -1 || fds[1] == -1) {
   10183             :             CloseHandle(read);
   10184             :             CloseHandle(write);
   10185             :             ok = 0;
   10186             :         }
   10187             :     }
   10188             :     Py_END_ALLOW_THREADS
   10189             : 
   10190             :     if (!ok)
   10191             :         return PyErr_SetFromWindowsErr(0);
   10192             : #else
   10193             : 
   10194             : #ifdef HAVE_PIPE2
   10195       21079 :     Py_BEGIN_ALLOW_THREADS
   10196       21079 :     res = pipe2(fds, O_CLOEXEC);
   10197       21079 :     Py_END_ALLOW_THREADS
   10198             : 
   10199       21079 :     if (res != 0 && errno == ENOSYS)
   10200             :     {
   10201             : #endif
   10202           0 :         Py_BEGIN_ALLOW_THREADS
   10203           0 :         res = pipe(fds);
   10204           0 :         Py_END_ALLOW_THREADS
   10205             : 
   10206           0 :         if (res == 0) {
   10207           0 :             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
   10208           0 :                 close(fds[0]);
   10209           0 :                 close(fds[1]);
   10210           0 :                 return NULL;
   10211             :             }
   10212           0 :             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
   10213           0 :                 close(fds[0]);
   10214           0 :                 close(fds[1]);
   10215           0 :                 return NULL;
   10216             :             }
   10217             :         }
   10218             : #ifdef HAVE_PIPE2
   10219             :     }
   10220             : #endif
   10221             : 
   10222       21079 :     if (res != 0)
   10223           0 :         return PyErr_SetFromErrno(PyExc_OSError);
   10224             : #endif /* !MS_WINDOWS */
   10225       21079 :     return Py_BuildValue("(ii)", fds[0], fds[1]);
   10226             : }
   10227             : #endif  /* HAVE_PIPE */
   10228             : 
   10229             : 
   10230             : #ifdef HAVE_PIPE2
   10231             : /*[clinic input]
   10232             : os.pipe2
   10233             : 
   10234             :     flags: int
   10235             :     /
   10236             : 
   10237             : Create a pipe with flags set atomically.
   10238             : 
   10239             : Returns a tuple of two file descriptors:
   10240             :   (read_fd, write_fd)
   10241             : 
   10242             : flags can be constructed by ORing together one or more of these values:
   10243             : O_NONBLOCK, O_CLOEXEC.
   10244             : [clinic start generated code]*/
   10245             : 
   10246             : static PyObject *
   10247           2 : os_pipe2_impl(PyObject *module, int flags)
   10248             : /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
   10249             : {
   10250             :     int fds[2];
   10251             :     int res;
   10252             : 
   10253           2 :     res = pipe2(fds, flags);
   10254           2 :     if (res != 0)
   10255           0 :         return posix_error();
   10256           2 :     return Py_BuildValue("(ii)", fds[0], fds[1]);
   10257             : }
   10258             : #endif /* HAVE_PIPE2 */
   10259             : 
   10260             : 
   10261             : #ifdef HAVE_WRITEV
   10262             : /*[clinic input]
   10263             : os.writev -> Py_ssize_t
   10264             :     fd: int
   10265             :     buffers: object
   10266             :     /
   10267             : 
   10268             : Iterate over buffers, and write the contents of each to a file descriptor.
   10269             : 
   10270             : Returns the total number of bytes written.
   10271             : buffers must be a sequence of bytes-like objects.
   10272             : [clinic start generated code]*/
   10273             : 
   10274             : static Py_ssize_t
   10275           3 : os_writev_impl(PyObject *module, int fd, PyObject *buffers)
   10276             : /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
   10277             : {
   10278             :     Py_ssize_t cnt;
   10279             :     Py_ssize_t result;
   10280           3 :     int async_err = 0;
   10281             :     struct iovec *iov;
   10282             :     Py_buffer *buf;
   10283             : 
   10284           3 :     if (!PySequence_Check(buffers)) {
   10285           0 :         PyErr_SetString(PyExc_TypeError,
   10286             :             "writev() arg 2 must be a sequence");
   10287           0 :         return -1;
   10288             :     }
   10289           3 :     cnt = PySequence_Size(buffers);
   10290           3 :     if (cnt < 0)
   10291           0 :         return -1;
   10292             : 
   10293           3 :     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
   10294           0 :         return -1;
   10295             :     }
   10296             : 
   10297             :     do {
   10298           3 :         Py_BEGIN_ALLOW_THREADS
   10299           3 :         result = writev(fd, iov, cnt);
   10300           3 :         Py_END_ALLOW_THREADS
   10301           3 :     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10302             : 
   10303           3 :     iov_cleanup(iov, buf, cnt);
   10304           3 :     if (result < 0 && !async_err)
   10305           1 :         posix_error();
   10306             : 
   10307           3 :     return result;
   10308             : }
   10309             : #endif /* HAVE_WRITEV */
   10310             : 
   10311             : 
   10312             : #ifdef HAVE_PWRITE
   10313             : /*[clinic input]
   10314             : os.pwrite -> Py_ssize_t
   10315             : 
   10316             :     fd: int
   10317             :     buffer: Py_buffer
   10318             :     offset: Py_off_t
   10319             :     /
   10320             : 
   10321             : Write bytes to a file descriptor starting at a particular offset.
   10322             : 
   10323             : Write buffer to fd, starting at offset bytes from the beginning of
   10324             : the file.  Returns the number of bytes writte.  Does not change the
   10325             : current file offset.
   10326             : [clinic start generated code]*/
   10327             : 
   10328             : static Py_ssize_t
   10329           1 : os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
   10330             : /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
   10331             : {
   10332             :     Py_ssize_t size;
   10333           1 :     int async_err = 0;
   10334             : 
   10335             :     do {
   10336           1 :         Py_BEGIN_ALLOW_THREADS
   10337             :         _Py_BEGIN_SUPPRESS_IPH
   10338           1 :         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
   10339             :         _Py_END_SUPPRESS_IPH
   10340           1 :         Py_END_ALLOW_THREADS
   10341           1 :     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10342             : 
   10343           1 :     if (size < 0 && !async_err)
   10344           0 :         posix_error();
   10345           1 :     return size;
   10346             : }
   10347             : #endif /* HAVE_PWRITE */
   10348             : 
   10349             : #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
   10350             : /*[clinic input]
   10351             : os.pwritev -> Py_ssize_t
   10352             : 
   10353             :     fd: int
   10354             :     buffers: object
   10355             :     offset: Py_off_t
   10356             :     flags: int = 0
   10357             :     /
   10358             : 
   10359             : Writes the contents of bytes-like objects to a file descriptor at a given offset.
   10360             : 
   10361             : Combines the functionality of writev() and pwrite(). All buffers must be a sequence
   10362             : of bytes-like objects. Buffers are processed in array order. Entire contents of first
   10363             : buffer is written before proceeding to second, and so on. The operating system may
   10364             : set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
   10365             : This function writes the contents of each object to the file descriptor and returns
   10366             : the total number of bytes written.
   10367             : 
   10368             : The flags argument contains a bitwise OR of zero or more of the following flags:
   10369             : 
   10370             : - RWF_DSYNC
   10371             : - RWF_SYNC
   10372             : - RWF_APPEND
   10373             : 
   10374             : Using non-zero flags requires Linux 4.7 or newer.
   10375             : [clinic start generated code]*/
   10376             : 
   10377             : static Py_ssize_t
   10378           1 : os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
   10379             :                 int flags)
   10380             : /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
   10381             : {
   10382             :     Py_ssize_t cnt;
   10383             :     Py_ssize_t result;
   10384           1 :     int async_err = 0;
   10385             :     struct iovec *iov;
   10386             :     Py_buffer *buf;
   10387             : 
   10388           1 :     if (!PySequence_Check(buffers)) {
   10389           0 :         PyErr_SetString(PyExc_TypeError,
   10390             :             "pwritev() arg 2 must be a sequence");
   10391           0 :         return -1;
   10392             :     }
   10393             : 
   10394           1 :     cnt = PySequence_Size(buffers);
   10395           1 :     if (cnt < 0) {
   10396           0 :         return -1;
   10397             :     }
   10398             : 
   10399             : #ifndef HAVE_PWRITEV2
   10400             :     if(flags != 0) {
   10401             :         argument_unavailable_error("pwritev2", "flags");
   10402             :         return -1;
   10403             :     }
   10404             : #endif
   10405             : 
   10406           1 :     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
   10407           0 :         return -1;
   10408             :     }
   10409             : #ifdef HAVE_PWRITEV2
   10410             :     do {
   10411           1 :         Py_BEGIN_ALLOW_THREADS
   10412             :         _Py_BEGIN_SUPPRESS_IPH
   10413           1 :         result = pwritev2(fd, iov, cnt, offset, flags);
   10414             :         _Py_END_SUPPRESS_IPH
   10415           1 :         Py_END_ALLOW_THREADS
   10416           1 :     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10417             : #else
   10418             : 
   10419             : #ifdef __APPLE__
   10420             : /* This entire function will be removed from the module dict when the API
   10421             :  * is not available.
   10422             :  */
   10423             : #pragma clang diagnostic push
   10424             : #pragma clang diagnostic ignored "-Wunguarded-availability"
   10425             : #pragma clang diagnostic ignored "-Wunguarded-availability-new"
   10426             : #endif
   10427             :     do {
   10428             :         Py_BEGIN_ALLOW_THREADS
   10429             :         _Py_BEGIN_SUPPRESS_IPH
   10430             :         result = pwritev(fd, iov, cnt, offset);
   10431             :         _Py_END_SUPPRESS_IPH
   10432             :         Py_END_ALLOW_THREADS
   10433             :     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10434             : 
   10435             : #ifdef __APPLE__
   10436             : #pragma clang diagnostic pop
   10437             : #endif
   10438             : 
   10439             : #endif
   10440             : 
   10441           1 :     iov_cleanup(iov, buf, cnt);
   10442           1 :     if (result < 0) {
   10443           0 :         if (!async_err) {
   10444           0 :             posix_error();
   10445             :         }
   10446           0 :         return -1;
   10447             :     }
   10448             : 
   10449           1 :     return result;
   10450             : }
   10451             : #endif /* HAVE_PWRITEV */
   10452             : 
   10453             : #ifdef HAVE_COPY_FILE_RANGE
   10454             : /*[clinic input]
   10455             : 
   10456             : os.copy_file_range
   10457             :     src: int
   10458             :         Source file descriptor.
   10459             :     dst: int
   10460             :         Destination file descriptor.
   10461             :     count: Py_ssize_t
   10462             :         Number of bytes to copy.
   10463             :     offset_src: object = None
   10464             :         Starting offset in src.
   10465             :     offset_dst: object = None
   10466             :         Starting offset in dst.
   10467             : 
   10468             : Copy count bytes from one file descriptor to another.
   10469             : 
   10470             : If offset_src is None, then src is read from the current position;
   10471             : respectively for offset_dst.
   10472             : [clinic start generated code]*/
   10473             : 
   10474             : static PyObject *
   10475           3 : os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
   10476             :                         PyObject *offset_src, PyObject *offset_dst)
   10477             : /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
   10478             : {
   10479             :     off_t offset_src_val, offset_dst_val;
   10480           3 :     off_t *p_offset_src = NULL;
   10481           3 :     off_t *p_offset_dst = NULL;
   10482             :     Py_ssize_t ret;
   10483           3 :     int async_err = 0;
   10484             :     /* The flags argument is provided to allow
   10485             :      * for future extensions and currently must be to 0. */
   10486           3 :     int flags = 0;
   10487             : 
   10488             : 
   10489           3 :     if (count < 0) {
   10490           1 :         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
   10491           1 :         return NULL;
   10492             :     }
   10493             : 
   10494           2 :     if (offset_src != Py_None) {
   10495           1 :         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
   10496           0 :             return NULL;
   10497             :         }
   10498           1 :         p_offset_src = &offset_src_val;
   10499             :     }
   10500             : 
   10501           2 :     if (offset_dst != Py_None) {
   10502           1 :         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
   10503           0 :             return NULL;
   10504             :         }
   10505           1 :         p_offset_dst = &offset_dst_val;
   10506             :     }
   10507             : 
   10508             :     do {
   10509           2 :         Py_BEGIN_ALLOW_THREADS
   10510           2 :         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
   10511           2 :         Py_END_ALLOW_THREADS
   10512           2 :     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10513             : 
   10514           2 :     if (ret < 0) {
   10515           0 :         return (!async_err) ? posix_error() : NULL;
   10516             :     }
   10517             : 
   10518           2 :     return PyLong_FromSsize_t(ret);
   10519             : }
   10520             : #endif /* HAVE_COPY_FILE_RANGE*/
   10521             : 
   10522             : #if (defined(HAVE_SPLICE) && !defined(_AIX))
   10523             : /*[clinic input]
   10524             : 
   10525             : os.splice
   10526             :     src: int
   10527             :         Source file descriptor.
   10528             :     dst: int
   10529             :         Destination file descriptor.
   10530             :     count: Py_ssize_t
   10531             :         Number of bytes to copy.
   10532             :     offset_src: object = None
   10533             :         Starting offset in src.
   10534             :     offset_dst: object = None
   10535             :         Starting offset in dst.
   10536             :     flags: unsigned_int = 0
   10537             :         Flags to modify the semantics of the call.
   10538             : 
   10539             : Transfer count bytes from one pipe to a descriptor or vice versa.
   10540             : 
   10541             : If offset_src is None, then src is read from the current position;
   10542             : respectively for offset_dst. The offset associated to the file
   10543             : descriptor that refers to a pipe must be None.
   10544             : [clinic start generated code]*/
   10545             : 
   10546             : static PyObject *
   10547           4 : os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
   10548             :                PyObject *offset_src, PyObject *offset_dst,
   10549             :                unsigned int flags)
   10550             : /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
   10551             : {
   10552             :     off_t offset_src_val, offset_dst_val;
   10553           4 :     off_t *p_offset_src = NULL;
   10554           4 :     off_t *p_offset_dst = NULL;
   10555             :     Py_ssize_t ret;
   10556           4 :     int async_err = 0;
   10557             : 
   10558           4 :     if (count < 0) {
   10559           1 :         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
   10560           1 :         return NULL;
   10561             :     }
   10562             : 
   10563           3 :     if (offset_src != Py_None) {
   10564           1 :         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
   10565           0 :             return NULL;
   10566             :         }
   10567           1 :         p_offset_src = &offset_src_val;
   10568             :     }
   10569             : 
   10570           3 :     if (offset_dst != Py_None) {
   10571           1 :         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
   10572           0 :             return NULL;
   10573             :         }
   10574           1 :         p_offset_dst = &offset_dst_val;
   10575             :     }
   10576             : 
   10577             :     do {
   10578           3 :         Py_BEGIN_ALLOW_THREADS
   10579           3 :         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
   10580           3 :         Py_END_ALLOW_THREADS
   10581           3 :     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
   10582             : 
   10583           3 :     if (ret < 0) {
   10584           0 :         return (!async_err) ? posix_error() : NULL;
   10585             :     }
   10586             : 
   10587           3 :     return PyLong_FromSsize_t(ret);
   10588             : }
   10589             : #endif /* HAVE_SPLICE*/
   10590             : 
   10591             : #ifdef HAVE_MKFIFO
   10592             : /*[clinic input]
   10593             : os.mkfifo
   10594             : 
   10595             :     path: path_t
   10596             :     mode: int=0o666
   10597             :     *
   10598             :     dir_fd: dir_fd(requires='mkfifoat')=None
   10599             : 
   10600             : Create a "fifo" (a POSIX named pipe).
   10601             : 
   10602             : If dir_fd is not None, it should be a file descriptor open to a directory,
   10603             :   and path should be relative; path will then be relative to that directory.
   10604             : dir_fd may not be implemented on your platform.
   10605             :   If it is unavailable, using it will raise a NotImplementedError.
   10606             : [clinic start generated code]*/
   10607             : 
   10608             : static PyObject *
   10609          10 : os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
   10610             : /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
   10611             : {
   10612             :     int result;
   10613          10 :     int async_err = 0;
   10614             : 
   10615             :     do {
   10616          10 :         Py_BEGIN_ALLOW_THREADS
   10617             : #ifdef HAVE_MKFIFOAT
   10618          10 :         if (dir_fd != DEFAULT_DIR_FD)
   10619           1 :             result = mkfifoat(dir_fd, path->narrow, mode);
   10620             :         else
   10621             : #endif
   10622           9 :             result = mkfifo(path->narrow, mode);
   10623          10 :         Py_END_ALLOW_THREADS
   10624           0 :     } while (result != 0 && errno == EINTR &&
   10625          10 :              !(async_err = PyErr_CheckSignals()));
   10626          10 :     if (result != 0)
   10627           0 :         return (!async_err) ? posix_error() : NULL;
   10628             : 
   10629          10 :     Py_RETURN_NONE;
   10630             : }
   10631             : #endif /* HAVE_MKFIFO */
   10632             : 
   10633             : 
   10634             : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
   10635             : /*[clinic input]
   10636             : os.mknod
   10637             : 
   10638             :     path: path_t
   10639             :     mode: int=0o600
   10640             :     device: dev_t=0
   10641             :     *
   10642             :     dir_fd: dir_fd(requires='mknodat')=None
   10643             : 
   10644             : Create a node in the file system.
   10645             : 
   10646             : Create a node in the file system (file, device special file or named pipe)
   10647             : at path.  mode specifies both the permissions to use and the
   10648             : type of node to be created, being combined (bitwise OR) with one of
   10649             : S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
   10650             : device defines the newly created device special file (probably using
   10651             : os.makedev()).  Otherwise device is ignored.
   10652             : 
   10653             : If dir_fd is not None, it should be a file descriptor open to a directory,
   10654             :   and path should be relative; path will then be relative to that directory.
   10655             : dir_fd may not be implemented on your platform.
   10656             :   If it is unavailable, using it will raise a NotImplementedError.
   10657             : [clinic start generated code]*/
   10658             : 
   10659             : static PyObject *
   10660           3 : os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
   10661             :               int dir_fd)
   10662             : /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
   10663             : {
   10664             :     int result;
   10665           3 :     int async_err = 0;
   10666             : 
   10667             :     do {
   10668           3 :         Py_BEGIN_ALLOW_THREADS
   10669             : #ifdef HAVE_MKNODAT
   10670           3 :         if (dir_fd != DEFAULT_DIR_FD)
   10671           1 :             result = mknodat(dir_fd, path->narrow, mode, device);
   10672             :         else
   10673             : #endif
   10674           2 :             result = mknod(path->narrow, mode, device);
   10675           3 :         Py_END_ALLOW_THREADS
   10676           0 :     } while (result != 0 && errno == EINTR &&
   10677           3 :              !(async_err = PyErr_CheckSignals()));
   10678           3 :     if (result != 0)
   10679           0 :         return (!async_err) ? posix_error() : NULL;
   10680             : 
   10681           3 :     Py_RETURN_NONE;
   10682             : }
   10683             : #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
   10684             : 
   10685             : 
   10686             : #ifdef HAVE_DEVICE_MACROS
   10687             : /*[clinic input]
   10688             : os.major -> unsigned_int
   10689             : 
   10690             :     device: dev_t
   10691             :     /
   10692             : 
   10693             : Extracts a device major number from a raw device number.
   10694             : [clinic start generated code]*/
   10695             : 
   10696             : static unsigned int
   10697           2 : os_major_impl(PyObject *module, dev_t device)
   10698             : /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
   10699             : {
   10700           2 :     return major(device);
   10701             : }
   10702             : 
   10703             : 
   10704             : /*[clinic input]
   10705             : os.minor -> unsigned_int
   10706             : 
   10707             :     device: dev_t
   10708             :     /
   10709             : 
   10710             : Extracts a device minor number from a raw device number.
   10711             : [clinic start generated code]*/
   10712             : 
   10713             : static unsigned int
   10714           2 : os_minor_impl(PyObject *module, dev_t device)
   10715             : /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
   10716             : {
   10717           2 :     return minor(device);
   10718             : }
   10719             : 
   10720             : 
   10721             : /*[clinic input]
   10722             : os.makedev -> dev_t
   10723             : 
   10724             :     major: int
   10725             :     minor: int
   10726             :     /
   10727             : 
   10728             : Composes a raw device number from the major and minor device numbers.
   10729             : [clinic start generated code]*/
   10730             : 
   10731             : static dev_t
   10732           1 : os_makedev_impl(PyObject *module, int major, int minor)
   10733             : /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
   10734             : {
   10735           1 :     return makedev(major, minor);
   10736             : }
   10737             : #endif /* HAVE_DEVICE_MACROS */
   10738             : 
   10739             : 
   10740             : #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
   10741             : /*[clinic input]
   10742             : os.ftruncate
   10743             : 
   10744             :     fd: int
   10745             :     length: Py_off_t
   10746             :     /
   10747             : 
   10748             : Truncate a file, specified by file descriptor, to a specific length.
   10749             : [clinic start generated code]*/
   10750             : 
   10751             : static PyObject *
   10752         297 : os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
   10753             : /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
   10754             : {
   10755             :     int result;
   10756         297 :     int async_err = 0;
   10757             : 
   10758         297 :     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
   10759           0 :         return NULL;
   10760             :     }
   10761             : 
   10762             :     do {
   10763         297 :         Py_BEGIN_ALLOW_THREADS
   10764             :         _Py_BEGIN_SUPPRESS_IPH
   10765             : #ifdef MS_WINDOWS
   10766             :         result = _chsize_s(fd, length);
   10767             : #else
   10768         297 :         result = ftruncate(fd, length);
   10769             : #endif
   10770             :         _Py_END_SUPPRESS_IPH
   10771         297 :         Py_END_ALLOW_THREADS
   10772           4 :     } while (result != 0 && errno == EINTR &&
   10773         297 :              !(async_err = PyErr_CheckSignals()));
   10774         297 :     if (result != 0)
   10775           4 :         return (!async_err) ? posix_error() : NULL;
   10776         293 :     Py_RETURN_NONE;
   10777             : }
   10778             : #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
   10779             : 
   10780             : 
   10781             : #if defined HAVE_TRUNCATE || defined MS_WINDOWS
   10782             : /*[clinic input]
   10783             : os.truncate
   10784             :     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
   10785             :     length: Py_off_t
   10786             : 
   10787             : Truncate a file, specified by path, to a specific length.
   10788             : 
   10789             : On some platforms, path may also be specified as an open file descriptor.
   10790             :   If this functionality is unavailable, using it raises an exception.
   10791             : [clinic start generated code]*/
   10792             : 
   10793             : static PyObject *
   10794           7 : os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
   10795             : /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
   10796             : {
   10797             :     int result;
   10798             : #ifdef MS_WINDOWS
   10799             :     int fd;
   10800             : #endif
   10801             : 
   10802           7 :     if (path->fd != -1)
   10803           1 :         return os_ftruncate_impl(module, path->fd, length);
   10804             : 
   10805           6 :     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
   10806           0 :         return NULL;
   10807             :     }
   10808             : 
   10809           6 :     Py_BEGIN_ALLOW_THREADS
   10810             :     _Py_BEGIN_SUPPRESS_IPH
   10811             : #ifdef MS_WINDOWS
   10812             :     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
   10813             :     if (fd < 0)
   10814             :         result = -1;
   10815             :     else {
   10816             :         result = _chsize_s(fd, length);
   10817             :         close(fd);
   10818             :         if (result < 0)
   10819             :             errno = result;
   10820             :     }
   10821             : #else
   10822           6 :     result = truncate(path->narrow, length);
   10823             : #endif
   10824             :     _Py_END_SUPPRESS_IPH
   10825           6 :     Py_END_ALLOW_THREADS
   10826           6 :     if (result < 0)
   10827           5 :         return posix_path_error(path);
   10828             : 
   10829           1 :     Py_RETURN_NONE;
   10830             : }
   10831             : #endif /* HAVE_TRUNCATE || MS_WINDOWS */
   10832             : 
   10833             : 
   10834             : /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
   10835             :    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
   10836             :    defined, which is the case in Python on AIX. AIX bug report:
   10837             :    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
   10838             : #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
   10839             : #  define POSIX_FADVISE_AIX_BUG
   10840             : #endif
   10841             : 
   10842             : 
   10843             : #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
   10844             : /*[clinic input]
   10845             : os.posix_fallocate
   10846             : 
   10847             :     fd: int
   10848             :     offset: Py_off_t
   10849             :     length: Py_off_t
   10850             :     /
   10851             : 
   10852             : Ensure a file has allocated at least a particular number of bytes on disk.
   10853             : 
   10854             : Ensure that the file specified by fd encompasses a range of bytes
   10855             : starting at offset bytes from the beginning and continuing for length bytes.
   10856             : [clinic start generated code]*/
   10857             : 
   10858             : static PyObject *
   10859           2 : os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
   10860             :                         Py_off_t length)
   10861             : /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
   10862             : {
   10863             :     int result;
   10864           2 :     int async_err = 0;
   10865             : 
   10866             :     do {
   10867           2 :         Py_BEGIN_ALLOW_THREADS
   10868           2 :         result = posix_fallocate(fd, offset, length);
   10869           2 :         Py_END_ALLOW_THREADS
   10870           2 :     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
   10871             : 
   10872           2 :     if (result == 0)
   10873           1 :         Py_RETURN_NONE;
   10874             : 
   10875           1 :     if (async_err)
   10876           0 :         return NULL;
   10877             : 
   10878           1 :     errno = result;
   10879           1 :     return posix_error();
   10880             : }
   10881             : #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
   10882             : 
   10883             : 
   10884             : #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
   10885             : /*[clinic input]
   10886             : os.posix_fadvise
   10887             : 
   10888             :     fd: int
   10889             :     offset: Py_off_t
   10890             :     length: Py_off_t
   10891             :     advice: int
   10892             :     /
   10893             : 
   10894             : Announce an intention to access data in a specific pattern.
   10895             : 
   10896             : Announce an intention to access data in a specific pattern, thus allowing
   10897             : the kernel to make optimizations.
   10898             : The advice applies to the region of the file specified by fd starting at
   10899             : offset and continuing for length bytes.
   10900             : advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
   10901             : POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
   10902             : POSIX_FADV_DONTNEED.
   10903             : [clinic start generated code]*/
   10904             : 
   10905             : static PyObject *
   10906           2 : os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
   10907             :                       Py_off_t length, int advice)
   10908             : /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
   10909             : {
   10910             :     int result;
   10911           2 :     int async_err = 0;
   10912             : 
   10913             :     do {
   10914           2 :         Py_BEGIN_ALLOW_THREADS
   10915           2 :         result = posix_fadvise(fd, offset, length, advice);
   10916           2 :         Py_END_ALLOW_THREADS
   10917           2 :     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
   10918             : 
   10919           2 :     if (result == 0)
   10920           1 :         Py_RETURN_NONE;
   10921             : 
   10922           1 :     if (async_err)
   10923           0 :         return NULL;
   10924             : 
   10925           1 :     errno = result;
   10926           1 :     return posix_error();
   10927             : }
   10928             : #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
   10929             : 
   10930             : 
   10931             : #ifdef MS_WINDOWS
   10932             : static PyObject*
   10933             : win32_putenv(PyObject *name, PyObject *value)
   10934             : {
   10935             :     /* Search from index 1 because on Windows starting '=' is allowed for
   10936             :        defining hidden environment variables. */
   10937             :     if (PyUnicode_GET_LENGTH(name) == 0 ||
   10938             :         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
   10939             :     {
   10940             :         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
   10941             :         return NULL;
   10942             :     }
   10943             :     PyObject *unicode;
   10944             :     if (value != NULL) {
   10945             :         unicode = PyUnicode_FromFormat("%U=%U", name, value);
   10946             :     }
   10947             :     else {
   10948             :         unicode = PyUnicode_FromFormat("%U=", name);
   10949             :     }
   10950             :     if (unicode == NULL) {
   10951             :         return NULL;
   10952             :     }
   10953             : 
   10954             :     Py_ssize_t size;
   10955             :     /* PyUnicode_AsWideCharString() rejects embedded null characters */
   10956             :     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
   10957             :     Py_DECREF(unicode);
   10958             : 
   10959             :     if (env == NULL) {
   10960             :         return NULL;
   10961             :     }
   10962             :     if (size > _MAX_ENV) {
   10963             :         PyErr_Format(PyExc_ValueError,
   10964             :                      "the environment variable is longer than %u characters",
   10965             :                      _MAX_ENV);
   10966             :         PyMem_Free(env);
   10967             :         return NULL;
   10968             :     }
   10969             : 
   10970             :     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
   10971             :        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
   10972             :        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
   10973             : 
   10974             :        Prefer _wputenv() to be compatible with C libraries using CRT
   10975             :        variables and CRT functions using these variables (ex: getenv()). */
   10976             :     int err = _wputenv(env);
   10977             :     PyMem_Free(env);
   10978             : 
   10979             :     if (err) {
   10980             :         posix_error();
   10981             :         return NULL;
   10982             :     }
   10983             : 
   10984             :     Py_RETURN_NONE;
   10985             : }
   10986             : #endif
   10987             : 
   10988             : 
   10989             : #ifdef MS_WINDOWS
   10990             : /*[clinic input]
   10991             : os.putenv
   10992             : 
   10993             :     name: unicode
   10994             :     value: unicode
   10995             :     /
   10996             : 
   10997             : Change or add an environment variable.
   10998             : [clinic start generated code]*/
   10999             : 
   11000             : static PyObject *
   11001             : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
   11002             : /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
   11003             : {
   11004             :     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
   11005             :         return NULL;
   11006             :     }
   11007             :     return win32_putenv(name, value);
   11008             : }
   11009             : #else
   11010             : /*[clinic input]
   11011             : os.putenv
   11012             : 
   11013             :     name: FSConverter
   11014             :     value: FSConverter
   11015             :     /
   11016             : 
   11017             : Change or add an environment variable.
   11018             : [clinic start generated code]*/
   11019             : 
   11020             : static PyObject *
   11021       13698 : os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
   11022             : /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
   11023             : {
   11024       13698 :     const char *name_string = PyBytes_AS_STRING(name);
   11025       13698 :     const char *value_string = PyBytes_AS_STRING(value);
   11026             : 
   11027       13698 :     if (strchr(name_string, '=') != NULL) {
   11028           5 :         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
   11029           5 :         return NULL;
   11030             :     }
   11031             : 
   11032       13693 :     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
   11033           0 :         return NULL;
   11034             :     }
   11035             : 
   11036       13693 :     if (setenv(name_string, value_string, 1)) {
   11037           1 :         return posix_error();
   11038             :     }
   11039       13692 :     Py_RETURN_NONE;
   11040             : }
   11041             : #endif  /* !defined(MS_WINDOWS) */
   11042             : 
   11043             : 
   11044             : #ifdef MS_WINDOWS
   11045             : /*[clinic input]
   11046             : os.unsetenv
   11047             :     name: unicode
   11048             :     /
   11049             : 
   11050             : Delete an environment variable.
   11051             : [clinic start generated code]*/
   11052             : 
   11053             : static PyObject *
   11054             : os_unsetenv_impl(PyObject *module, PyObject *name)
   11055             : /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
   11056             : {
   11057             :     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
   11058             :         return NULL;
   11059             :     }
   11060             :     return win32_putenv(name, NULL);
   11061             : }
   11062             : #else
   11063             : /*[clinic input]
   11064             : os.unsetenv
   11065             :     name: FSConverter
   11066             :     /
   11067             : 
   11068             : Delete an environment variable.
   11069             : [clinic start generated code]*/
   11070             : 
   11071             : static PyObject *
   11072       13313 : os_unsetenv_impl(PyObject *module, PyObject *name)
   11073             : /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
   11074             : {
   11075       13313 :     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
   11076           0 :         return NULL;
   11077             :     }
   11078             : #ifdef HAVE_BROKEN_UNSETENV
   11079             :     unsetenv(PyBytes_AS_STRING(name));
   11080             : #else
   11081       13313 :     int err = unsetenv(PyBytes_AS_STRING(name));
   11082       13313 :     if (err) {
   11083           4 :         return posix_error();
   11084             :     }
   11085             : #endif
   11086             : 
   11087       13309 :     Py_RETURN_NONE;
   11088             : }
   11089             : #endif /* !MS_WINDOWS */
   11090             : 
   11091             : 
   11092             : /*[clinic input]
   11093             : os.strerror
   11094             : 
   11095             :     code: int
   11096             :     /
   11097             : 
   11098             : Translate an error code to a message string.
   11099             : [clinic start generated code]*/
   11100             : 
   11101             : static PyObject *
   11102        2095 : os_strerror_impl(PyObject *module, int code)
   11103             : /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
   11104             : {
   11105        2095 :     char *message = strerror(code);
   11106        2095 :     if (message == NULL) {
   11107           0 :         PyErr_SetString(PyExc_ValueError,
   11108             :                         "strerror() argument out of range");
   11109           0 :         return NULL;
   11110             :     }
   11111        2095 :     return PyUnicode_DecodeLocale(message, "surrogateescape");
   11112             : }
   11113             : 
   11114             : 
   11115             : #ifdef HAVE_SYS_WAIT_H
   11116             : #ifdef WCOREDUMP
   11117             : /*[clinic input]
   11118             : os.WCOREDUMP -> bool
   11119             : 
   11120             :     status: int
   11121             :     /
   11122             : 
   11123             : Return True if the process returning status was dumped to a core file.
   11124             : [clinic start generated code]*/
   11125             : 
   11126             : static int
   11127           0 : os_WCOREDUMP_impl(PyObject *module, int status)
   11128             : /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
   11129             : {
   11130             :     WAIT_TYPE wait_status;
   11131           0 :     WAIT_STATUS_INT(wait_status) = status;
   11132           0 :     return WCOREDUMP(wait_status);
   11133             : }
   11134             : #endif /* WCOREDUMP */
   11135             : 
   11136             : 
   11137             : #ifdef WIFCONTINUED
   11138             : /*[clinic input]
   11139             : os.WIFCONTINUED -> bool
   11140             : 
   11141             :     status: int
   11142             : 
   11143             : Return True if a particular process was continued from a job control stop.
   11144             : 
   11145             : Return True if the process returning status was continued from a
   11146             : job control stop.
   11147             : [clinic start generated code]*/
   11148             : 
   11149             : static int
   11150           0 : os_WIFCONTINUED_impl(PyObject *module, int status)
   11151             : /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
   11152             : {
   11153             :     WAIT_TYPE wait_status;
   11154           0 :     WAIT_STATUS_INT(wait_status) = status;
   11155           0 :     return WIFCONTINUED(wait_status);
   11156             : }
   11157             : #endif /* WIFCONTINUED */
   11158             : 
   11159             : 
   11160             : #ifdef WIFSTOPPED
   11161             : /*[clinic input]
   11162             : os.WIFSTOPPED -> bool
   11163             : 
   11164             :     status: int
   11165             : 
   11166             : Return True if the process returning status was stopped.
   11167             : [clinic start generated code]*/
   11168             : 
   11169             : static int
   11170        4943 : os_WIFSTOPPED_impl(PyObject *module, int status)
   11171             : /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
   11172             : {
   11173             :     WAIT_TYPE wait_status;
   11174        4943 :     WAIT_STATUS_INT(wait_status) = status;
   11175        4943 :     return WIFSTOPPED(wait_status);
   11176             : }
   11177             : #endif /* WIFSTOPPED */
   11178             : 
   11179             : 
   11180             : #ifdef WIFSIGNALED
   11181             : /*[clinic input]
   11182             : os.WIFSIGNALED -> bool
   11183             : 
   11184             :     status: int
   11185             : 
   11186             : Return True if the process returning status was terminated by a signal.
   11187             : [clinic start generated code]*/
   11188             : 
   11189             : static int
   11190           0 : os_WIFSIGNALED_impl(PyObject *module, int status)
   11191             : /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
   11192             : {
   11193             :     WAIT_TYPE wait_status;
   11194           0 :     WAIT_STATUS_INT(wait_status) = status;
   11195           0 :     return WIFSIGNALED(wait_status);
   11196             : }
   11197             : #endif /* WIFSIGNALED */
   11198             : 
   11199             : 
   11200             : #ifdef WIFEXITED
   11201             : /*[clinic input]
   11202             : os.WIFEXITED -> bool
   11203             : 
   11204             :     status: int
   11205             : 
   11206             : Return True if the process returning status exited via the exit() system call.
   11207             : [clinic start generated code]*/
   11208             : 
   11209             : static int
   11210           0 : os_WIFEXITED_impl(PyObject *module, int status)
   11211             : /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
   11212             : {
   11213             :     WAIT_TYPE wait_status;
   11214           0 :     WAIT_STATUS_INT(wait_status) = status;
   11215           0 :     return WIFEXITED(wait_status);
   11216             : }
   11217             : #endif /* WIFEXITED */
   11218             : 
   11219             : 
   11220             : #ifdef WEXITSTATUS
   11221             : /*[clinic input]
   11222             : os.WEXITSTATUS -> int
   11223             : 
   11224             :     status: int
   11225             : 
   11226             : Return the process return code from status.
   11227             : [clinic start generated code]*/
   11228             : 
   11229             : static int
   11230           0 : os_WEXITSTATUS_impl(PyObject *module, int status)
   11231             : /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
   11232             : {
   11233             :     WAIT_TYPE wait_status;
   11234           0 :     WAIT_STATUS_INT(wait_status) = status;
   11235           0 :     return WEXITSTATUS(wait_status);
   11236             : }
   11237             : #endif /* WEXITSTATUS */
   11238             : 
   11239             : 
   11240             : #ifdef WTERMSIG
   11241             : /*[clinic input]
   11242             : os.WTERMSIG -> int
   11243             : 
   11244             :     status: int
   11245             : 
   11246             : Return the signal that terminated the process that provided the status value.
   11247             : [clinic start generated code]*/
   11248             : 
   11249             : static int
   11250           0 : os_WTERMSIG_impl(PyObject *module, int status)
   11251             : /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
   11252             : {
   11253             :     WAIT_TYPE wait_status;
   11254           0 :     WAIT_STATUS_INT(wait_status) = status;
   11255           0 :     return WTERMSIG(wait_status);
   11256             : }
   11257             : #endif /* WTERMSIG */
   11258             : 
   11259             : 
   11260             : #ifdef WSTOPSIG
   11261             : /*[clinic input]
   11262             : os.WSTOPSIG -> int
   11263             : 
   11264             :     status: int
   11265             : 
   11266             : Return the signal that stopped the process that provided the status value.
   11267             : [clinic start generated code]*/
   11268             : 
   11269             : static int
   11270           1 : os_WSTOPSIG_impl(PyObject *module, int status)
   11271             : /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
   11272             : {
   11273             :     WAIT_TYPE wait_status;
   11274           1 :     WAIT_STATUS_INT(wait_status) = status;
   11275           1 :     return WSTOPSIG(wait_status);
   11276             : }
   11277             : #endif /* WSTOPSIG */
   11278             : #endif /* HAVE_SYS_WAIT_H */
   11279             : 
   11280             : 
   11281             : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
   11282             : #ifdef _SCO_DS
   11283             : /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
   11284             :    needed definitions in sys/statvfs.h */
   11285             : #define _SVID3
   11286             : #endif
   11287             : #include <sys/statvfs.h>
   11288             : 
   11289             : static PyObject*
   11290         135 : _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
   11291         135 :     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
   11292         135 :     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
   11293         135 :     if (v == NULL)
   11294           0 :         return NULL;
   11295             : 
   11296             : #if !defined(HAVE_LARGEFILE_SUPPORT)
   11297         135 :     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
   11298         135 :     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
   11299         135 :     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
   11300         135 :     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
   11301         135 :     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
   11302         135 :     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
   11303         135 :     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
   11304         135 :     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
   11305         135 :     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
   11306         135 :     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
   11307             : #else
   11308             :     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
   11309             :     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
   11310             :     PyStructSequence_SET_ITEM(v, 2,
   11311             :                               PyLong_FromLongLong((long long) st.f_blocks));
   11312             :     PyStructSequence_SET_ITEM(v, 3,
   11313             :                               PyLong_FromLongLong((long long) st.f_bfree));
   11314             :     PyStructSequence_SET_ITEM(v, 4,
   11315             :                               PyLong_FromLongLong((long long) st.f_bavail));
   11316             :     PyStructSequence_SET_ITEM(v, 5,
   11317             :                               PyLong_FromLongLong((long long) st.f_files));
   11318             :     PyStructSequence_SET_ITEM(v, 6,
   11319             :                               PyLong_FromLongLong((long long) st.f_ffree));
   11320             :     PyStructSequence_SET_ITEM(v, 7,
   11321             :                               PyLong_FromLongLong((long long) st.f_favail));
   11322             :     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
   11323             :     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
   11324             : #endif
   11325             : /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
   11326             :  * (issue #32390). */
   11327             : #if defined(_AIX) && defined(_ALL_SOURCE)
   11328             :     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
   11329             : #else
   11330         135 :     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
   11331             : #endif
   11332         135 :     if (PyErr_Occurred()) {
   11333           0 :         Py_DECREF(v);
   11334           0 :         return NULL;
   11335             :     }
   11336             : 
   11337         135 :     return v;
   11338             : }
   11339             : 
   11340             : 
   11341             : /*[clinic input]
   11342             : os.fstatvfs
   11343             :     fd: int
   11344             :     /
   11345             : 
   11346             : Perform an fstatvfs system call on the given fd.
   11347             : 
   11348             : Equivalent to statvfs(fd).
   11349             : [clinic start generated code]*/
   11350             : 
   11351             : static PyObject *
   11352           2 : os_fstatvfs_impl(PyObject *module, int fd)
   11353             : /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
   11354             : {
   11355             :     int result;
   11356           2 :     int async_err = 0;
   11357             :     struct statvfs st;
   11358             : 
   11359             :     do {
   11360           2 :         Py_BEGIN_ALLOW_THREADS
   11361           2 :         result = fstatvfs(fd, &st);
   11362           2 :         Py_END_ALLOW_THREADS
   11363           1 :     } while (result != 0 && errno == EINTR &&
   11364           2 :              !(async_err = PyErr_CheckSignals()));
   11365           2 :     if (result != 0)
   11366           1 :         return (!async_err) ? posix_error() : NULL;
   11367             : 
   11368           1 :     return _pystatvfs_fromstructstatvfs(module, st);
   11369             : }
   11370             : #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
   11371             : 
   11372             : 
   11373             : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
   11374             : #include <sys/statvfs.h>
   11375             : /*[clinic input]
   11376             : os.statvfs
   11377             : 
   11378             :     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
   11379             : 
   11380             : Perform a statvfs system call on the given path.
   11381             : 
   11382             : path may always be specified as a string.
   11383             : On some platforms, path may also be specified as an open file descriptor.
   11384             :   If this functionality is unavailable, using it raises an exception.
   11385             : [clinic start generated code]*/
   11386             : 
   11387             : static PyObject *
   11388         134 : os_statvfs_impl(PyObject *module, path_t *path)
   11389             : /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
   11390             : {
   11391             :     int result;
   11392             :     struct statvfs st;
   11393             : 
   11394         134 :     Py_BEGIN_ALLOW_THREADS
   11395             : #ifdef HAVE_FSTATVFS
   11396         134 :     if (path->fd != -1) {
   11397           1 :         result = fstatvfs(path->fd, &st);
   11398             :     }
   11399             :     else
   11400             : #endif
   11401         133 :         result = statvfs(path->narrow, &st);
   11402         134 :     Py_END_ALLOW_THREADS
   11403             : 
   11404         134 :     if (result) {
   11405           0 :         return path_error(path);
   11406             :     }
   11407             : 
   11408         134 :     return _pystatvfs_fromstructstatvfs(module, st);
   11409             : }
   11410             : #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
   11411             : 
   11412             : 
   11413             : #ifdef MS_WINDOWS
   11414             : /*[clinic input]
   11415             : os._getdiskusage
   11416             : 
   11417             :     path: path_t
   11418             : 
   11419             : Return disk usage statistics about the given path as a (total, free) tuple.
   11420             : [clinic start generated code]*/
   11421             : 
   11422             : static PyObject *
   11423             : os__getdiskusage_impl(PyObject *module, path_t *path)
   11424             : /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
   11425             : {
   11426             :     BOOL retval;
   11427             :     ULARGE_INTEGER _, total, free;
   11428             :     DWORD err = 0;
   11429             : 
   11430             :     Py_BEGIN_ALLOW_THREADS
   11431             :     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
   11432             :     Py_END_ALLOW_THREADS
   11433             :     if (retval == 0) {
   11434             :         if (GetLastError() == ERROR_DIRECTORY) {
   11435             :             wchar_t *dir_path = NULL;
   11436             : 
   11437             :             dir_path = PyMem_New(wchar_t, path->length + 1);
   11438             :             if (dir_path == NULL) {
   11439             :                 return PyErr_NoMemory();
   11440             :             }
   11441             : 
   11442             :             wcscpy_s(dir_path, path->length + 1, path->wide);
   11443             : 
   11444             :             if (_dirnameW(dir_path) != -1) {
   11445             :                 Py_BEGIN_ALLOW_THREADS
   11446             :                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
   11447             :                 Py_END_ALLOW_THREADS
   11448             :             }
   11449             :             /* Record the last error in case it's modified by PyMem_Free. */
   11450             :             err = GetLastError();
   11451             :             PyMem_Free(dir_path);
   11452             :             if (retval) {
   11453             :                 goto success;
   11454             :             }
   11455             :         }
   11456             :         return PyErr_SetFromWindowsErr(err);
   11457             :     }
   11458             : 
   11459             : success:
   11460             :     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
   11461             : }
   11462             : #endif /* MS_WINDOWS */
   11463             : 
   11464             : 
   11465             : /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
   11466             :  * It maps strings representing configuration variable names to
   11467             :  * integer values, allowing those functions to be called with the
   11468             :  * magic names instead of polluting the module's namespace with tons of
   11469             :  * rarely-used constants.  There are three separate tables that use
   11470             :  * these definitions.
   11471             :  *
   11472             :  * This code is always included, even if none of the interfaces that
   11473             :  * need it are included.  The #if hackery needed to avoid it would be
   11474             :  * sufficiently pervasive that it's not worth the loss of readability.
   11475             :  */
   11476             : struct constdef {
   11477             :     const char *name;
   11478             :     int value;
   11479             : };
   11480             : 
   11481             : static int
   11482        2741 : conv_confname(PyObject *arg, int *valuep, struct constdef *table,
   11483             :               size_t tablesize)
   11484             : {
   11485        2741 :     if (PyLong_Check(arg)) {
   11486           0 :         int value = _PyLong_AsInt(arg);
   11487           0 :         if (value == -1 && PyErr_Occurred())
   11488           0 :             return 0;
   11489           0 :         *valuep = value;
   11490           0 :         return 1;
   11491             :     }
   11492             :     else {
   11493             :         /* look up the value in the table using a binary search */
   11494        2741 :         size_t lo = 0;
   11495             :         size_t mid;
   11496        2741 :         size_t hi = tablesize;
   11497             :         int cmp;
   11498             :         const char *confname;
   11499        2741 :         if (!PyUnicode_Check(arg)) {
   11500           0 :             PyErr_SetString(PyExc_TypeError,
   11501             :                 "configuration names must be strings or integers");
   11502           0 :             return 0;
   11503             :         }
   11504        2741 :         confname = PyUnicode_AsUTF8(arg);
   11505        2741 :         if (confname == NULL)
   11506           0 :             return 0;
   11507       14505 :         while (lo < hi) {
   11508       14504 :             mid = (lo + hi) / 2;
   11509       14504 :             cmp = strcmp(confname, table[mid].name);
   11510       14504 :             if (cmp < 0)
   11511        8731 :                 hi = mid;
   11512        5773 :             else if (cmp > 0)
   11513        3033 :                 lo = mid + 1;
   11514             :             else {
   11515        2740 :                 *valuep = table[mid].value;
   11516        2740 :                 return 1;
   11517             :             }
   11518             :         }
   11519           1 :         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
   11520           1 :         return 0;
   11521             :     }
   11522             : }
   11523             : 
   11524             : 
   11525             : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
   11526             : static struct constdef  posix_constants_pathconf[] = {
   11527             : #ifdef _PC_ABI_AIO_XFER_MAX
   11528             :     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
   11529             : #endif
   11530             : #ifdef _PC_ABI_ASYNC_IO
   11531             :     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
   11532             : #endif
   11533             : #ifdef _PC_ASYNC_IO
   11534             :     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
   11535             : #endif
   11536             : #ifdef _PC_CHOWN_RESTRICTED
   11537             :     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
   11538             : #endif
   11539             : #ifdef _PC_FILESIZEBITS
   11540             :     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
   11541             : #endif
   11542             : #ifdef _PC_LAST
   11543             :     {"PC_LAST", _PC_LAST},
   11544             : #endif
   11545             : #ifdef _PC_LINK_MAX
   11546             :     {"PC_LINK_MAX",     _PC_LINK_MAX},
   11547             : #endif
   11548             : #ifdef _PC_MAX_CANON
   11549             :     {"PC_MAX_CANON",    _PC_MAX_CANON},
   11550             : #endif
   11551             : #ifdef _PC_MAX_INPUT
   11552             :     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
   11553             : #endif
   11554             : #ifdef _PC_NAME_MAX
   11555             :     {"PC_NAME_MAX",     _PC_NAME_MAX},
   11556             : #endif
   11557             : #ifdef _PC_NO_TRUNC
   11558             :     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
   11559             : #endif
   11560             : #ifdef _PC_PATH_MAX
   11561             :     {"PC_PATH_MAX",     _PC_PATH_MAX},
   11562             : #endif
   11563             : #ifdef _PC_PIPE_BUF
   11564             :     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
   11565             : #endif
   11566             : #ifdef _PC_PRIO_IO
   11567             :     {"PC_PRIO_IO",      _PC_PRIO_IO},
   11568             : #endif
   11569             : #ifdef _PC_SOCK_MAXBUF
   11570             :     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
   11571             : #endif
   11572             : #ifdef _PC_SYNC_IO
   11573             :     {"PC_SYNC_IO",      _PC_SYNC_IO},
   11574             : #endif
   11575             : #ifdef _PC_VDISABLE
   11576             :     {"PC_VDISABLE",     _PC_VDISABLE},
   11577             : #endif
   11578             : #ifdef _PC_ACL_ENABLED
   11579             :     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
   11580             : #endif
   11581             : #ifdef _PC_MIN_HOLE_SIZE
   11582             :     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
   11583             : #endif
   11584             : #ifdef _PC_ALLOC_SIZE_MIN
   11585             :     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
   11586             : #endif
   11587             : #ifdef _PC_REC_INCR_XFER_SIZE
   11588             :     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
   11589             : #endif
   11590             : #ifdef _PC_REC_MAX_XFER_SIZE
   11591             :     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
   11592             : #endif
   11593             : #ifdef _PC_REC_MIN_XFER_SIZE
   11594             :     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
   11595             : #endif
   11596             : #ifdef _PC_REC_XFER_ALIGN
   11597             :     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
   11598             : #endif
   11599             : #ifdef _PC_SYMLINK_MAX
   11600             :     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
   11601             : #endif
   11602             : #ifdef _PC_XATTR_ENABLED
   11603             :     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
   11604             : #endif
   11605             : #ifdef _PC_XATTR_EXISTS
   11606             :     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
   11607             : #endif
   11608             : #ifdef _PC_TIMESTAMP_RESOLUTION
   11609             :     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
   11610             : #endif
   11611             : };
   11612             : 
   11613             : static int
   11614           2 : conv_path_confname(PyObject *arg, int *valuep)
   11615             : {
   11616           2 :     return conv_confname(arg, valuep, posix_constants_pathconf,
   11617             :                          sizeof(posix_constants_pathconf)
   11618             :                            / sizeof(struct constdef));
   11619             : }
   11620             : #endif
   11621             : 
   11622             : 
   11623             : #ifdef HAVE_FPATHCONF
   11624             : /*[clinic input]
   11625             : os.fpathconf -> long
   11626             : 
   11627             :     fd: fildes
   11628             :     name: path_confname
   11629             :     /
   11630             : 
   11631             : Return the configuration limit name for the file descriptor fd.
   11632             : 
   11633             : If there is no limit, return -1.
   11634             : [clinic start generated code]*/
   11635             : 
   11636             : static long
   11637           1 : os_fpathconf_impl(PyObject *module, int fd, int name)
   11638             : /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
   11639             : {
   11640             :     long limit;
   11641             : 
   11642           1 :     errno = 0;
   11643           1 :     limit = fpathconf(fd, name);
   11644           1 :     if (limit == -1 && errno != 0)
   11645           1 :         posix_error();
   11646             : 
   11647           1 :     return limit;
   11648             : }
   11649             : #endif /* HAVE_FPATHCONF */
   11650             : 
   11651             : 
   11652             : #ifdef HAVE_PATHCONF
   11653             : /*[clinic input]
   11654             : os.pathconf -> long
   11655             :     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
   11656             :     name: path_confname
   11657             : 
   11658             : Return the configuration limit name for the file or directory path.
   11659             : 
   11660             : If there is no limit, return -1.
   11661             : On some platforms, path may also be specified as an open file descriptor.
   11662             :   If this functionality is unavailable, using it raises an exception.
   11663             : [clinic start generated code]*/
   11664             : 
   11665             : static long
   11666           1 : os_pathconf_impl(PyObject *module, path_t *path, int name)
   11667             : /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
   11668             : {
   11669             :     long limit;
   11670             : 
   11671           1 :     errno = 0;
   11672             : #ifdef HAVE_FPATHCONF
   11673           1 :     if (path->fd != -1)
   11674           1 :         limit = fpathconf(path->fd, name);
   11675             :     else
   11676             : #endif
   11677           0 :         limit = pathconf(path->narrow, name);
   11678           1 :     if (limit == -1 && errno != 0) {
   11679           1 :         if (errno == EINVAL)
   11680             :             /* could be a path or name problem */
   11681           0 :             posix_error();
   11682             :         else
   11683           1 :             path_error(path);
   11684             :     }
   11685             : 
   11686           1 :     return limit;
   11687             : }
   11688             : #endif /* HAVE_PATHCONF */
   11689             : 
   11690             : #ifdef HAVE_CONFSTR
   11691             : static struct constdef posix_constants_confstr[] = {
   11692             : #ifdef _CS_ARCHITECTURE
   11693             :     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
   11694             : #endif
   11695             : #ifdef _CS_GNU_LIBC_VERSION
   11696             :     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
   11697             : #endif
   11698             : #ifdef _CS_GNU_LIBPTHREAD_VERSION
   11699             :     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
   11700             : #endif
   11701             : #ifdef _CS_HOSTNAME
   11702             :     {"CS_HOSTNAME",     _CS_HOSTNAME},
   11703             : #endif
   11704             : #ifdef _CS_HW_PROVIDER
   11705             :     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
   11706             : #endif
   11707             : #ifdef _CS_HW_SERIAL
   11708             :     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
   11709             : #endif
   11710             : #ifdef _CS_INITTAB_NAME
   11711             :     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
   11712             : #endif
   11713             : #ifdef _CS_LFS64_CFLAGS
   11714             :     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
   11715             : #endif
   11716             : #ifdef _CS_LFS64_LDFLAGS
   11717             :     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
   11718             : #endif
   11719             : #ifdef _CS_LFS64_LIBS
   11720             :     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
   11721             : #endif
   11722             : #ifdef _CS_LFS64_LINTFLAGS
   11723             :     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
   11724             : #endif
   11725             : #ifdef _CS_LFS_CFLAGS
   11726             :     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
   11727             : #endif
   11728             : #ifdef _CS_LFS_LDFLAGS
   11729             :     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
   11730             : #endif
   11731             : #ifdef _CS_LFS_LIBS
   11732             :     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
   11733             : #endif
   11734             : #ifdef _CS_LFS_LINTFLAGS
   11735             :     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
   11736             : #endif
   11737             : #ifdef _CS_MACHINE
   11738             :     {"CS_MACHINE",      _CS_MACHINE},
   11739             : #endif
   11740             : #ifdef _CS_PATH
   11741             :     {"CS_PATH", _CS_PATH},
   11742             : #endif
   11743             : #ifdef _CS_RELEASE
   11744             :     {"CS_RELEASE",      _CS_RELEASE},
   11745             : #endif
   11746             : #ifdef _CS_SRPC_DOMAIN
   11747             :     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
   11748             : #endif
   11749             : #ifdef _CS_SYSNAME
   11750             :     {"CS_SYSNAME",      _CS_SYSNAME},
   11751             : #endif
   11752             : #ifdef _CS_VERSION
   11753             :     {"CS_VERSION",      _CS_VERSION},
   11754             : #endif
   11755             : #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
   11756             :     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
   11757             : #endif
   11758             : #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
   11759             :     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
   11760             : #endif
   11761             : #ifdef _CS_XBS5_ILP32_OFF32_LIBS
   11762             :     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
   11763             : #endif
   11764             : #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
   11765             :     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
   11766             : #endif
   11767             : #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
   11768             :     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
   11769             : #endif
   11770             : #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
   11771             :     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
   11772             : #endif
   11773             : #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
   11774             :     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
   11775             : #endif
   11776             : #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
   11777             :     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
   11778             : #endif
   11779             : #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
   11780             :     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
   11781             : #endif
   11782             : #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
   11783             :     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
   11784             : #endif
   11785             : #ifdef _CS_XBS5_LP64_OFF64_LIBS
   11786             :     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
   11787             : #endif
   11788             : #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
   11789             :     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
   11790             : #endif
   11791             : #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
   11792             :     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
   11793             : #endif
   11794             : #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
   11795             :     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
   11796             : #endif
   11797             : #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
   11798             :     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
   11799             : #endif
   11800             : #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
   11801             :     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
   11802             : #endif
   11803             : #ifdef _MIPS_CS_AVAIL_PROCESSORS
   11804             :     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
   11805             : #endif
   11806             : #ifdef _MIPS_CS_BASE
   11807             :     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
   11808             : #endif
   11809             : #ifdef _MIPS_CS_HOSTID
   11810             :     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
   11811             : #endif
   11812             : #ifdef _MIPS_CS_HW_NAME
   11813             :     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
   11814             : #endif
   11815             : #ifdef _MIPS_CS_NUM_PROCESSORS
   11816             :     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
   11817             : #endif
   11818             : #ifdef _MIPS_CS_OSREL_MAJ
   11819             :     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
   11820             : #endif
   11821             : #ifdef _MIPS_CS_OSREL_MIN
   11822             :     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
   11823             : #endif
   11824             : #ifdef _MIPS_CS_OSREL_PATCH
   11825             :     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
   11826             : #endif
   11827             : #ifdef _MIPS_CS_OS_NAME
   11828             :     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
   11829             : #endif
   11830             : #ifdef _MIPS_CS_OS_PROVIDER
   11831             :     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
   11832             : #endif
   11833             : #ifdef _MIPS_CS_PROCESSORS
   11834             :     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
   11835             : #endif
   11836             : #ifdef _MIPS_CS_SERIAL
   11837             :     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
   11838             : #endif
   11839             : #ifdef _MIPS_CS_VENDOR
   11840             :     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
   11841             : #endif
   11842             : };
   11843             : 
   11844             : static int
   11845        1227 : conv_confstr_confname(PyObject *arg, int *valuep)
   11846             : {
   11847        1227 :     return conv_confname(arg, valuep, posix_constants_confstr,
   11848             :                          sizeof(posix_constants_confstr)
   11849             :                            / sizeof(struct constdef));
   11850             : }
   11851             : 
   11852             : 
   11853             : /*[clinic input]
   11854             : os.confstr
   11855             : 
   11856             :     name: confstr_confname
   11857             :     /
   11858             : 
   11859             : Return a string-valued system configuration variable.
   11860             : [clinic start generated code]*/
   11861             : 
   11862             : static PyObject *
   11863        1226 : os_confstr_impl(PyObject *module, int name)
   11864             : /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
   11865             : {
   11866        1226 :     PyObject *result = NULL;
   11867             :     char buffer[255];
   11868             :     size_t len;
   11869             : 
   11870        1226 :     errno = 0;
   11871        1226 :     len = confstr(name, buffer, sizeof(buffer));
   11872        1226 :     if (len == 0) {
   11873           0 :         if (errno) {
   11874           0 :             posix_error();
   11875           0 :             return NULL;
   11876             :         }
   11877             :         else {
   11878           0 :             Py_RETURN_NONE;
   11879             :         }
   11880             :     }
   11881             : 
   11882        1226 :     if (len >= sizeof(buffer)) {
   11883             :         size_t len2;
   11884           0 :         char *buf = PyMem_Malloc(len);
   11885           0 :         if (buf == NULL)
   11886           0 :             return PyErr_NoMemory();
   11887           0 :         len2 = confstr(name, buf, len);
   11888           0 :         assert(len == len2);
   11889           0 :         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
   11890           0 :         PyMem_Free(buf);
   11891             :     }
   11892             :     else
   11893        1226 :         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
   11894        1226 :     return result;
   11895             : }
   11896             : #endif /* HAVE_CONFSTR */
   11897             : 
   11898             : 
   11899             : #ifdef HAVE_SYSCONF
   11900             : static struct constdef posix_constants_sysconf[] = {
   11901             : #ifdef _SC_2_CHAR_TERM
   11902             :     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
   11903             : #endif
   11904             : #ifdef _SC_2_C_BIND
   11905             :     {"SC_2_C_BIND",     _SC_2_C_BIND},
   11906             : #endif
   11907             : #ifdef _SC_2_C_DEV
   11908             :     {"SC_2_C_DEV",      _SC_2_C_DEV},
   11909             : #endif
   11910             : #ifdef _SC_2_C_VERSION
   11911             :     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
   11912             : #endif
   11913             : #ifdef _SC_2_FORT_DEV
   11914             :     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
   11915             : #endif
   11916             : #ifdef _SC_2_FORT_RUN
   11917             :     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
   11918             : #endif
   11919             : #ifdef _SC_2_LOCALEDEF
   11920             :     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
   11921             : #endif
   11922             : #ifdef _SC_2_SW_DEV
   11923             :     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
   11924             : #endif
   11925             : #ifdef _SC_2_UPE
   11926             :     {"SC_2_UPE",        _SC_2_UPE},
   11927             : #endif
   11928             : #ifdef _SC_2_VERSION
   11929             :     {"SC_2_VERSION",    _SC_2_VERSION},
   11930             : #endif
   11931             : #ifdef _SC_ABI_ASYNCHRONOUS_IO
   11932             :     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
   11933             : #endif
   11934             : #ifdef _SC_ACL
   11935             :     {"SC_ACL",  _SC_ACL},
   11936             : #endif
   11937             : #ifdef _SC_AIO_LISTIO_MAX
   11938             :     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
   11939             : #endif
   11940             : #ifdef _SC_AIO_MAX
   11941             :     {"SC_AIO_MAX",      _SC_AIO_MAX},
   11942             : #endif
   11943             : #ifdef _SC_AIO_PRIO_DELTA_MAX
   11944             :     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
   11945             : #endif
   11946             : #ifdef _SC_ARG_MAX
   11947             :     {"SC_ARG_MAX",      _SC_ARG_MAX},
   11948             : #endif
   11949             : #ifdef _SC_ASYNCHRONOUS_IO
   11950             :     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
   11951             : #endif
   11952             : #ifdef _SC_ATEXIT_MAX
   11953             :     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
   11954             : #endif
   11955             : #ifdef _SC_AUDIT
   11956             :     {"SC_AUDIT",        _SC_AUDIT},
   11957             : #endif
   11958             : #ifdef _SC_AVPHYS_PAGES
   11959             :     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
   11960             : #endif
   11961             : #ifdef _SC_BC_BASE_MAX
   11962             :     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
   11963             : #endif
   11964             : #ifdef _SC_BC_DIM_MAX
   11965             :     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
   11966             : #endif
   11967             : #ifdef _SC_BC_SCALE_MAX
   11968             :     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
   11969             : #endif
   11970             : #ifdef _SC_BC_STRING_MAX
   11971             :     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
   11972             : #endif
   11973             : #ifdef _SC_CAP
   11974             :     {"SC_CAP",  _SC_CAP},
   11975             : #endif
   11976             : #ifdef _SC_CHARCLASS_NAME_MAX
   11977             :     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
   11978             : #endif
   11979             : #ifdef _SC_CHAR_BIT
   11980             :     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
   11981             : #endif
   11982             : #ifdef _SC_CHAR_MAX
   11983             :     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
   11984             : #endif
   11985             : #ifdef _SC_CHAR_MIN
   11986             :     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
   11987             : #endif
   11988             : #ifdef _SC_CHILD_MAX
   11989             :     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
   11990             : #endif
   11991             : #ifdef _SC_CLK_TCK
   11992             :     {"SC_CLK_TCK",      _SC_CLK_TCK},
   11993             : #endif
   11994             : #ifdef _SC_COHER_BLKSZ
   11995             :     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
   11996             : #endif
   11997             : #ifdef _SC_COLL_WEIGHTS_MAX
   11998             :     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
   11999             : #endif
   12000             : #ifdef _SC_DCACHE_ASSOC
   12001             :     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
   12002             : #endif
   12003             : #ifdef _SC_DCACHE_BLKSZ
   12004             :     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
   12005             : #endif
   12006             : #ifdef _SC_DCACHE_LINESZ
   12007             :     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
   12008             : #endif
   12009             : #ifdef _SC_DCACHE_SZ
   12010             :     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
   12011             : #endif
   12012             : #ifdef _SC_DCACHE_TBLKSZ
   12013             :     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
   12014             : #endif
   12015             : #ifdef _SC_DELAYTIMER_MAX
   12016             :     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
   12017             : #endif
   12018             : #ifdef _SC_EQUIV_CLASS_MAX
   12019             :     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
   12020             : #endif
   12021             : #ifdef _SC_EXPR_NEST_MAX
   12022             :     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
   12023             : #endif
   12024             : #ifdef _SC_FSYNC
   12025             :     {"SC_FSYNC",        _SC_FSYNC},
   12026             : #endif
   12027             : #ifdef _SC_GETGR_R_SIZE_MAX
   12028             :     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
   12029             : #endif
   12030             : #ifdef _SC_GETPW_R_SIZE_MAX
   12031             :     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
   12032             : #endif
   12033             : #ifdef _SC_ICACHE_ASSOC
   12034             :     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
   12035             : #endif
   12036             : #ifdef _SC_ICACHE_BLKSZ
   12037             :     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
   12038             : #endif
   12039             : #ifdef _SC_ICACHE_LINESZ
   12040             :     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
   12041             : #endif
   12042             : #ifdef _SC_ICACHE_SZ
   12043             :     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
   12044             : #endif
   12045             : #ifdef _SC_INF
   12046             :     {"SC_INF",  _SC_INF},
   12047             : #endif
   12048             : #ifdef _SC_INT_MAX
   12049             :     {"SC_INT_MAX",      _SC_INT_MAX},
   12050             : #endif
   12051             : #ifdef _SC_INT_MIN
   12052             :     {"SC_INT_MIN",      _SC_INT_MIN},
   12053             : #endif
   12054             : #ifdef _SC_IOV_MAX
   12055             :     {"SC_IOV_MAX",      _SC_IOV_MAX},
   12056             : #endif
   12057             : #ifdef _SC_IP_SECOPTS
   12058             :     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
   12059             : #endif
   12060             : #ifdef _SC_JOB_CONTROL
   12061             :     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
   12062             : #endif
   12063             : #ifdef _SC_KERN_POINTERS
   12064             :     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
   12065             : #endif
   12066             : #ifdef _SC_KERN_SIM
   12067             :     {"SC_KERN_SIM",     _SC_KERN_SIM},
   12068             : #endif
   12069             : #ifdef _SC_LINE_MAX
   12070             :     {"SC_LINE_MAX",     _SC_LINE_MAX},
   12071             : #endif
   12072             : #ifdef _SC_LOGIN_NAME_MAX
   12073             :     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
   12074             : #endif
   12075             : #ifdef _SC_LOGNAME_MAX
   12076             :     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
   12077             : #endif
   12078             : #ifdef _SC_LONG_BIT
   12079             :     {"SC_LONG_BIT",     _SC_LONG_BIT},
   12080             : #endif
   12081             : #ifdef _SC_MAC
   12082             :     {"SC_MAC",  _SC_MAC},
   12083             : #endif
   12084             : #ifdef _SC_MAPPED_FILES
   12085             :     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
   12086             : #endif
   12087             : #ifdef _SC_MAXPID
   12088             :     {"SC_MAXPID",       _SC_MAXPID},
   12089             : #endif
   12090             : #ifdef _SC_MB_LEN_MAX
   12091             :     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
   12092             : #endif
   12093             : #ifdef _SC_MEMLOCK
   12094             :     {"SC_MEMLOCK",      _SC_MEMLOCK},
   12095             : #endif
   12096             : #ifdef _SC_MEMLOCK_RANGE
   12097             :     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
   12098             : #endif
   12099             : #ifdef _SC_MEMORY_PROTECTION
   12100             :     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
   12101             : #endif
   12102             : #ifdef _SC_MESSAGE_PASSING
   12103             :     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
   12104             : #endif
   12105             : #ifdef _SC_MMAP_FIXED_ALIGNMENT
   12106             :     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
   12107             : #endif
   12108             : #ifdef _SC_MQ_OPEN_MAX
   12109             :     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
   12110             : #endif
   12111             : #ifdef _SC_MQ_PRIO_MAX
   12112             :     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
   12113             : #endif
   12114             : #ifdef _SC_NACLS_MAX
   12115             :     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
   12116             : #endif
   12117             : #ifdef _SC_NGROUPS_MAX
   12118             :     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
   12119             : #endif
   12120             : #ifdef _SC_NL_ARGMAX
   12121             :     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
   12122             : #endif
   12123             : #ifdef _SC_NL_LANGMAX
   12124             :     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
   12125             : #endif
   12126             : #ifdef _SC_NL_MSGMAX
   12127             :     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
   12128             : #endif
   12129             : #ifdef _SC_NL_NMAX
   12130             :     {"SC_NL_NMAX",      _SC_NL_NMAX},
   12131             : #endif
   12132             : #ifdef _SC_NL_SETMAX
   12133             :     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
   12134             : #endif
   12135             : #ifdef _SC_NL_TEXTMAX
   12136             :     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
   12137             : #endif
   12138             : #ifdef _SC_NPROCESSORS_CONF
   12139             :     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
   12140             : #endif
   12141             : #ifdef _SC_NPROCESSORS_ONLN
   12142             :     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
   12143             : #endif
   12144             : #ifdef _SC_NPROC_CONF
   12145             :     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
   12146             : #endif
   12147             : #ifdef _SC_NPROC_ONLN
   12148             :     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
   12149             : #endif
   12150             : #ifdef _SC_NZERO
   12151             :     {"SC_NZERO",        _SC_NZERO},
   12152             : #endif
   12153             : #ifdef _SC_OPEN_MAX
   12154             :     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
   12155             : #endif
   12156             : #ifdef _SC_PAGESIZE
   12157             :     {"SC_PAGESIZE",     _SC_PAGESIZE},
   12158             : #endif
   12159             : #ifdef _SC_PAGE_SIZE
   12160             :     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
   12161             : #endif
   12162             : #ifdef _SC_AIX_REALMEM
   12163             :     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
   12164             : #endif
   12165             : #ifdef _SC_PASS_MAX
   12166             :     {"SC_PASS_MAX",     _SC_PASS_MAX},
   12167             : #endif
   12168             : #ifdef _SC_PHYS_PAGES
   12169             :     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
   12170             : #endif
   12171             : #ifdef _SC_PII
   12172             :     {"SC_PII",  _SC_PII},
   12173             : #endif
   12174             : #ifdef _SC_PII_INTERNET
   12175             :     {"SC_PII_INTERNET", _SC_PII_INTERNET},
   12176             : #endif
   12177             : #ifdef _SC_PII_INTERNET_DGRAM
   12178             :     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
   12179             : #endif
   12180             : #ifdef _SC_PII_INTERNET_STREAM
   12181             :     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
   12182             : #endif
   12183             : #ifdef _SC_PII_OSI
   12184             :     {"SC_PII_OSI",      _SC_PII_OSI},
   12185             : #endif
   12186             : #ifdef _SC_PII_OSI_CLTS
   12187             :     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
   12188             : #endif
   12189             : #ifdef _SC_PII_OSI_COTS
   12190             :     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
   12191             : #endif
   12192             : #ifdef _SC_PII_OSI_M
   12193             :     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
   12194             : #endif
   12195             : #ifdef _SC_PII_SOCKET
   12196             :     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
   12197             : #endif
   12198             : #ifdef _SC_PII_XTI
   12199             :     {"SC_PII_XTI",      _SC_PII_XTI},
   12200             : #endif
   12201             : #ifdef _SC_POLL
   12202             :     {"SC_POLL", _SC_POLL},
   12203             : #endif
   12204             : #ifdef _SC_PRIORITIZED_IO
   12205             :     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
   12206             : #endif
   12207             : #ifdef _SC_PRIORITY_SCHEDULING
   12208             :     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
   12209             : #endif
   12210             : #ifdef _SC_REALTIME_SIGNALS
   12211             :     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
   12212             : #endif
   12213             : #ifdef _SC_RE_DUP_MAX
   12214             :     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
   12215             : #endif
   12216             : #ifdef _SC_RTSIG_MAX
   12217             :     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
   12218             : #endif
   12219             : #ifdef _SC_SAVED_IDS
   12220             :     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
   12221             : #endif
   12222             : #ifdef _SC_SCHAR_MAX
   12223             :     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
   12224             : #endif
   12225             : #ifdef _SC_SCHAR_MIN
   12226             :     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
   12227             : #endif
   12228             : #ifdef _SC_SELECT
   12229             :     {"SC_SELECT",       _SC_SELECT},
   12230             : #endif
   12231             : #ifdef _SC_SEMAPHORES
   12232             :     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
   12233             : #endif
   12234             : #ifdef _SC_SEM_NSEMS_MAX
   12235             :     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
   12236             : #endif
   12237             : #ifdef _SC_SEM_VALUE_MAX
   12238             :     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
   12239             : #endif
   12240             : #ifdef _SC_SHARED_MEMORY_OBJECTS
   12241             :     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
   12242             : #endif
   12243             : #ifdef _SC_SHRT_MAX
   12244             :     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
   12245             : #endif
   12246             : #ifdef _SC_SHRT_MIN
   12247             :     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
   12248             : #endif
   12249             : #ifdef _SC_SIGQUEUE_MAX
   12250             :     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
   12251             : #endif
   12252             : #ifdef _SC_SIGRT_MAX
   12253             :     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
   12254             : #endif
   12255             : #ifdef _SC_SIGRT_MIN
   12256             :     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
   12257             : #endif
   12258             : #ifdef _SC_SOFTPOWER
   12259             :     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
   12260             : #endif
   12261             : #ifdef _SC_SPLIT_CACHE
   12262             :     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
   12263             : #endif
   12264             : #ifdef _SC_SSIZE_MAX
   12265             :     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
   12266             : #endif
   12267             : #ifdef _SC_STACK_PROT
   12268             :     {"SC_STACK_PROT",   _SC_STACK_PROT},
   12269             : #endif
   12270             : #ifdef _SC_STREAM_MAX
   12271             :     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
   12272             : #endif
   12273             : #ifdef _SC_SYNCHRONIZED_IO
   12274             :     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
   12275             : #endif
   12276             : #ifdef _SC_THREADS
   12277             :     {"SC_THREADS",      _SC_THREADS},
   12278             : #endif
   12279             : #ifdef _SC_THREAD_ATTR_STACKADDR
   12280             :     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
   12281             : #endif
   12282             : #ifdef _SC_THREAD_ATTR_STACKSIZE
   12283             :     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
   12284             : #endif
   12285             : #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
   12286             :     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
   12287             : #endif
   12288             : #ifdef _SC_THREAD_KEYS_MAX
   12289             :     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
   12290             : #endif
   12291             : #ifdef _SC_THREAD_PRIORITY_SCHEDULING
   12292             :     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
   12293             : #endif
   12294             : #ifdef _SC_THREAD_PRIO_INHERIT
   12295             :     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
   12296             : #endif
   12297             : #ifdef _SC_THREAD_PRIO_PROTECT
   12298             :     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
   12299             : #endif
   12300             : #ifdef _SC_THREAD_PROCESS_SHARED
   12301             :     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
   12302             : #endif
   12303             : #ifdef _SC_THREAD_SAFE_FUNCTIONS
   12304             :     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
   12305             : #endif
   12306             : #ifdef _SC_THREAD_STACK_MIN
   12307             :     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
   12308             : #endif
   12309             : #ifdef _SC_THREAD_THREADS_MAX
   12310             :     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
   12311             : #endif
   12312             : #ifdef _SC_TIMERS
   12313             :     {"SC_TIMERS",       _SC_TIMERS},
   12314             : #endif
   12315             : #ifdef _SC_TIMER_MAX
   12316             :     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
   12317             : #endif
   12318             : #ifdef _SC_TTY_NAME_MAX
   12319             :     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
   12320             : #endif
   12321             : #ifdef _SC_TZNAME_MAX
   12322             :     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
   12323             : #endif
   12324             : #ifdef _SC_T_IOV_MAX
   12325             :     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
   12326             : #endif
   12327             : #ifdef _SC_UCHAR_MAX
   12328             :     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
   12329             : #endif
   12330             : #ifdef _SC_UINT_MAX
   12331             :     {"SC_UINT_MAX",     _SC_UINT_MAX},
   12332             : #endif
   12333             : #ifdef _SC_UIO_MAXIOV
   12334             :     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
   12335             : #endif
   12336             : #ifdef _SC_ULONG_MAX
   12337             :     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
   12338             : #endif
   12339             : #ifdef _SC_USHRT_MAX
   12340             :     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
   12341             : #endif
   12342             : #ifdef _SC_VERSION
   12343             :     {"SC_VERSION",      _SC_VERSION},
   12344             : #endif
   12345             : #ifdef _SC_WORD_BIT
   12346             :     {"SC_WORD_BIT",     _SC_WORD_BIT},
   12347             : #endif
   12348             : #ifdef _SC_XBS5_ILP32_OFF32
   12349             :     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
   12350             : #endif
   12351             : #ifdef _SC_XBS5_ILP32_OFFBIG
   12352             :     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
   12353             : #endif
   12354             : #ifdef _SC_XBS5_LP64_OFF64
   12355             :     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
   12356             : #endif
   12357             : #ifdef _SC_XBS5_LPBIG_OFFBIG
   12358             :     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
   12359             : #endif
   12360             : #ifdef _SC_XOPEN_CRYPT
   12361             :     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
   12362             : #endif
   12363             : #ifdef _SC_XOPEN_ENH_I18N
   12364             :     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
   12365             : #endif
   12366             : #ifdef _SC_XOPEN_LEGACY
   12367             :     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
   12368             : #endif
   12369             : #ifdef _SC_XOPEN_REALTIME
   12370             :     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
   12371             : #endif
   12372             : #ifdef _SC_XOPEN_REALTIME_THREADS
   12373             :     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
   12374             : #endif
   12375             : #ifdef _SC_XOPEN_SHM
   12376             :     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
   12377             : #endif
   12378             : #ifdef _SC_XOPEN_UNIX
   12379             :     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
   12380             : #endif
   12381             : #ifdef _SC_XOPEN_VERSION
   12382             :     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
   12383             : #endif
   12384             : #ifdef _SC_XOPEN_XCU_VERSION
   12385             :     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
   12386             : #endif
   12387             : #ifdef _SC_XOPEN_XPG2
   12388             :     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
   12389             : #endif
   12390             : #ifdef _SC_XOPEN_XPG3
   12391             :     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
   12392             : #endif
   12393             : #ifdef _SC_XOPEN_XPG4
   12394             :     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
   12395             : #endif
   12396             : #ifdef _SC_MINSIGSTKSZ
   12397             :     {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
   12398             : #endif
   12399             : };
   12400             : 
   12401             : static int
   12402        1512 : conv_sysconf_confname(PyObject *arg, int *valuep)
   12403             : {
   12404        1512 :     return conv_confname(arg, valuep, posix_constants_sysconf,
   12405             :                          sizeof(posix_constants_sysconf)
   12406             :                            / sizeof(struct constdef));
   12407             : }
   12408             : 
   12409             : 
   12410             : /*[clinic input]
   12411             : os.sysconf -> long
   12412             :     name: sysconf_confname
   12413             :     /
   12414             : 
   12415             : Return an integer-valued system configuration variable.
   12416             : [clinic start generated code]*/
   12417             : 
   12418             : static long
   12419        1512 : os_sysconf_impl(PyObject *module, int name)
   12420             : /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
   12421             : {
   12422             :     long value;
   12423             : 
   12424        1512 :     errno = 0;
   12425        1512 :     value = sysconf(name);
   12426        1512 :     if (value == -1 && errno != 0)
   12427           0 :         posix_error();
   12428        1512 :     return value;
   12429             : }
   12430             : #endif /* HAVE_SYSCONF */
   12431             : 
   12432             : 
   12433             : /* This code is used to ensure that the tables of configuration value names
   12434             :  * are in sorted order as required by conv_confname(), and also to build
   12435             :  * the exported dictionaries that are used to publish information about the
   12436             :  * names available on the host platform.
   12437             :  *
   12438             :  * Sorting the table at runtime ensures that the table is properly ordered
   12439             :  * when used, even for platforms we're not able to test on.  It also makes
   12440             :  * it easier to add additional entries to the tables.
   12441             :  */
   12442             : 
   12443             : static int
   12444     1773480 : cmp_constdefs(const void *v1,  const void *v2)
   12445             : {
   12446     1773480 :     const struct constdef *c1 =
   12447             :     (const struct constdef *) v1;
   12448     1773480 :     const struct constdef *c2 =
   12449             :     (const struct constdef *) v2;
   12450             : 
   12451     1773480 :     return strcmp(c1->name, c2->name);
   12452             : }
   12453             : 
   12454             : static int
   12455        9390 : setup_confname_table(struct constdef *table, size_t tablesize,
   12456             :                      const char *tablename, PyObject *module)
   12457             : {
   12458        9390 :     PyObject *d = NULL;
   12459             :     size_t i;
   12460             : 
   12461        9390 :     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
   12462        9390 :     d = PyDict_New();
   12463        9390 :     if (d == NULL)
   12464           0 :         return -1;
   12465             : 
   12466      575920 :     for (i=0; i < tablesize; ++i) {
   12467      566530 :         PyObject *o = PyLong_FromLong(table[i].value);
   12468      566530 :         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
   12469           0 :             Py_XDECREF(o);
   12470           0 :             Py_DECREF(d);
   12471           0 :             return -1;
   12472             :         }
   12473      566530 :         Py_DECREF(o);
   12474             :     }
   12475        9390 :     return PyModule_AddObject(module, tablename, d);
   12476             : }
   12477             : 
   12478             : /* Return -1 on failure, 0 on success. */
   12479             : static int
   12480        3130 : setup_confname_tables(PyObject *module)
   12481             : {
   12482             : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
   12483        3130 :     if (setup_confname_table(posix_constants_pathconf,
   12484             :                              sizeof(posix_constants_pathconf)
   12485             :                                / sizeof(struct constdef),
   12486             :                              "pathconf_names", module))
   12487           0 :         return -1;
   12488             : #endif
   12489             : #ifdef HAVE_CONFSTR
   12490        3130 :     if (setup_confname_table(posix_constants_confstr,
   12491             :                              sizeof(posix_constants_confstr)
   12492             :                                / sizeof(struct constdef),
   12493             :                              "confstr_names", module))
   12494           0 :         return -1;
   12495             : #endif
   12496             : #ifdef HAVE_SYSCONF
   12497        3130 :     if (setup_confname_table(posix_constants_sysconf,
   12498             :                              sizeof(posix_constants_sysconf)
   12499             :                                / sizeof(struct constdef),
   12500             :                              "sysconf_names", module))
   12501           0 :         return -1;
   12502             : #endif
   12503        3130 :     return 0;
   12504             : }
   12505             : 
   12506             : 
   12507             : /*[clinic input]
   12508             : os.abort
   12509             : 
   12510             : Abort the interpreter immediately.
   12511             : 
   12512             : This function 'dumps core' or otherwise fails in the hardest way possible
   12513             : on the hosting operating system.  This function never returns.
   12514             : [clinic start generated code]*/
   12515             : 
   12516             : static PyObject *
   12517           0 : os_abort_impl(PyObject *module)
   12518             : /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
   12519             : {
   12520           0 :     abort();
   12521             :     /*NOTREACHED*/
   12522             : #ifndef __clang__
   12523             :     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
   12524             :        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
   12525             :        is smarter and emits a warning on the return. */
   12526             :     Py_FatalError("abort() called from Python code didn't abort!");
   12527             :     return NULL;
   12528             : #endif
   12529             : }
   12530             : 
   12531             : #ifdef MS_WINDOWS
   12532             : /* Grab ShellExecute dynamically from shell32 */
   12533             : static int has_ShellExecute = -1;
   12534             : static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
   12535             :                                               LPCWSTR, INT);
   12536             : static int
   12537             : check_ShellExecute()
   12538             : {
   12539             :     HINSTANCE hShell32;
   12540             : 
   12541             :     /* only recheck */
   12542             :     if (-1 == has_ShellExecute) {
   12543             :         Py_BEGIN_ALLOW_THREADS
   12544             :         /* Security note: this call is not vulnerable to "DLL hijacking".
   12545             :            SHELL32 is part of "KnownDLLs" and so Windows always load
   12546             :            the system SHELL32.DLL, even if there is another SHELL32.DLL
   12547             :            in the DLL search path. */
   12548             :         hShell32 = LoadLibraryW(L"SHELL32");
   12549             :         if (hShell32) {
   12550             :             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
   12551             :                                             "ShellExecuteW");
   12552             :             has_ShellExecute = Py_ShellExecuteW != NULL;
   12553             :         } else {
   12554             :             has_ShellExecute = 0;
   12555             :         }
   12556             :         Py_END_ALLOW_THREADS
   12557             :     }
   12558             :     return has_ShellExecute;
   12559             : }
   12560             : 
   12561             : 
   12562             : /*[clinic input]
   12563             : os.startfile
   12564             :     filepath: path_t
   12565             :     operation: Py_UNICODE = NULL
   12566             :     arguments: Py_UNICODE = NULL
   12567             :     cwd: path_t(nullable=True) = None
   12568             :     show_cmd: int = 1
   12569             : 
   12570             : Start a file with its associated application.
   12571             : 
   12572             : When "operation" is not specified or "open", this acts like
   12573             : double-clicking the file in Explorer, or giving the file name as an
   12574             : argument to the DOS "start" command: the file is opened with whatever
   12575             : application (if any) its extension is associated.
   12576             : When another "operation" is given, it specifies what should be done with
   12577             : the file.  A typical operation is "print".
   12578             : 
   12579             : "arguments" is passed to the application, but should be omitted if the
   12580             : file is a document.
   12581             : 
   12582             : "cwd" is the working directory for the operation. If "filepath" is
   12583             : relative, it will be resolved against this directory. This argument
   12584             : should usually be an absolute path.
   12585             : 
   12586             : "show_cmd" can be used to override the recommended visibility option.
   12587             : See the Windows ShellExecute documentation for values.
   12588             : 
   12589             : startfile returns as soon as the associated application is launched.
   12590             : There is no option to wait for the application to close, and no way
   12591             : to retrieve the application's exit status.
   12592             : 
   12593             : The filepath is relative to the current directory.  If you want to use
   12594             : an absolute path, make sure the first character is not a slash ("/");
   12595             : the underlying Win32 ShellExecute function doesn't work if it is.
   12596             : [clinic start generated code]*/
   12597             : 
   12598             : static PyObject *
   12599             : os_startfile_impl(PyObject *module, path_t *filepath,
   12600             :                   const Py_UNICODE *operation, const Py_UNICODE *arguments,
   12601             :                   path_t *cwd, int show_cmd)
   12602             : /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
   12603             : {
   12604             :     HINSTANCE rc;
   12605             : 
   12606             :     if(!check_ShellExecute()) {
   12607             :         /* If the OS doesn't have ShellExecute, return a
   12608             :            NotImplementedError. */
   12609             :         return PyErr_Format(PyExc_NotImplementedError,
   12610             :             "startfile not available on this platform");
   12611             :     }
   12612             : 
   12613             :     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
   12614             :         return NULL;
   12615             :     }
   12616             :     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
   12617             :                     arguments, cwd->object ? cwd->object : Py_None,
   12618             :                     show_cmd) < 0) {
   12619             :         return NULL;
   12620             :     }
   12621             : 
   12622             :     Py_BEGIN_ALLOW_THREADS
   12623             :     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
   12624             :                           arguments, cwd->wide, show_cmd);
   12625             :     Py_END_ALLOW_THREADS
   12626             : 
   12627             :     if (rc <= (HINSTANCE)32) {
   12628             :         win32_error_object("startfile", filepath->object);
   12629             :         return NULL;
   12630             :     }
   12631             :     Py_RETURN_NONE;
   12632             : }
   12633             : #endif /* MS_WINDOWS */
   12634             : 
   12635             : 
   12636             : #ifdef HAVE_GETLOADAVG
   12637             : /*[clinic input]
   12638             : os.getloadavg
   12639             : 
   12640             : Return average recent system load information.
   12641             : 
   12642             : Return the number of processes in the system run queue averaged over
   12643             : the last 1, 5, and 15 minutes as a tuple of three floats.
   12644             : Raises OSError if the load average was unobtainable.
   12645             : [clinic start generated code]*/
   12646             : 
   12647             : static PyObject *
   12648         707 : os_getloadavg_impl(PyObject *module)
   12649             : /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
   12650             : {
   12651             :     double loadavg[3];
   12652         707 :     if (getloadavg(loadavg, 3)!=3) {
   12653           0 :         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
   12654           0 :         return NULL;
   12655             :     } else
   12656         707 :         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
   12657             : }
   12658             : #endif /* HAVE_GETLOADAVG */
   12659             : 
   12660             : 
   12661             : /*[clinic input]
   12662             : os.device_encoding
   12663             :     fd: int
   12664             : 
   12665             : Return a string describing the encoding of a terminal's file descriptor.
   12666             : 
   12667             : The file descriptor must be attached to a terminal.
   12668             : If the device is not a terminal, return None.
   12669             : [clinic start generated code]*/
   12670             : 
   12671             : static PyObject *
   12672           1 : os_device_encoding_impl(PyObject *module, int fd)
   12673             : /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
   12674             : {
   12675           1 :     return _Py_device_encoding(fd);
   12676             : }
   12677             : 
   12678             : 
   12679             : #ifdef HAVE_SETRESUID
   12680             : /*[clinic input]
   12681             : os.setresuid
   12682             : 
   12683             :     ruid: uid_t
   12684             :     euid: uid_t
   12685             :     suid: uid_t
   12686             :     /
   12687             : 
   12688             : Set the current process's real, effective, and saved user ids.
   12689             : [clinic start generated code]*/
   12690             : 
   12691             : static PyObject *
   12692           3 : os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
   12693             : /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
   12694             : {
   12695           3 :     if (setresuid(ruid, euid, suid) < 0)
   12696           1 :         return posix_error();
   12697           2 :     Py_RETURN_NONE;
   12698             : }
   12699             : #endif /* HAVE_SETRESUID */
   12700             : 
   12701             : 
   12702             : #ifdef HAVE_SETRESGID
   12703             : /*[clinic input]
   12704             : os.setresgid
   12705             : 
   12706             :     rgid: gid_t
   12707             :     egid: gid_t
   12708             :     sgid: gid_t
   12709             :     /
   12710             : 
   12711             : Set the current process's real, effective, and saved group ids.
   12712             : [clinic start generated code]*/
   12713             : 
   12714             : static PyObject *
   12715           3 : os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
   12716             : /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
   12717             : {
   12718           3 :     if (setresgid(rgid, egid, sgid) < 0)
   12719           1 :         return posix_error();
   12720           2 :     Py_RETURN_NONE;
   12721             : }
   12722             : #endif /* HAVE_SETRESGID */
   12723             : 
   12724             : 
   12725             : #ifdef HAVE_GETRESUID
   12726             : /*[clinic input]
   12727             : os.getresuid
   12728             : 
   12729             : Return a tuple of the current process's real, effective, and saved user ids.
   12730             : [clinic start generated code]*/
   12731             : 
   12732             : static PyObject *
   12733           3 : os_getresuid_impl(PyObject *module)
   12734             : /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
   12735             : {
   12736             :     uid_t ruid, euid, suid;
   12737           3 :     if (getresuid(&ruid, &euid, &suid) < 0)
   12738           0 :         return posix_error();
   12739           3 :     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
   12740             :                                   _PyLong_FromUid(euid),
   12741             :                                   _PyLong_FromUid(suid));
   12742             : }
   12743             : #endif /* HAVE_GETRESUID */
   12744             : 
   12745             : 
   12746             : #ifdef HAVE_GETRESGID
   12747             : /*[clinic input]
   12748             : os.getresgid
   12749             : 
   12750             : Return a tuple of the current process's real, effective, and saved group ids.
   12751             : [clinic start generated code]*/
   12752             : 
   12753             : static PyObject *
   12754           3 : os_getresgid_impl(PyObject *module)
   12755             : /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
   12756             : {
   12757             :     gid_t rgid, egid, sgid;
   12758           3 :     if (getresgid(&rgid, &egid, &sgid) < 0)
   12759           0 :         return posix_error();
   12760           3 :     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
   12761             :                                   _PyLong_FromGid(egid),
   12762             :                                   _PyLong_FromGid(sgid));
   12763             : }
   12764             : #endif /* HAVE_GETRESGID */
   12765             : 
   12766             : 
   12767             : #ifdef USE_XATTRS
   12768             : /*[clinic input]
   12769             : os.getxattr
   12770             : 
   12771             :     path: path_t(allow_fd=True)
   12772             :     attribute: path_t
   12773             :     *
   12774             :     follow_symlinks: bool = True
   12775             : 
   12776             : Return the value of extended attribute attribute on path.
   12777             : 
   12778             : path may be either a string, a path-like object, or an open file descriptor.
   12779             : If follow_symlinks is False, and the last element of the path is a symbolic
   12780             :   link, getxattr will examine the symbolic link itself instead of the file
   12781             :   the link points to.
   12782             : 
   12783             : [clinic start generated code]*/
   12784             : 
   12785             : static PyObject *
   12786          41 : os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
   12787             :                  int follow_symlinks)
   12788             : /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
   12789             : {
   12790             :     Py_ssize_t i;
   12791          41 :     PyObject *buffer = NULL;
   12792             : 
   12793          41 :     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
   12794           0 :         return NULL;
   12795             : 
   12796          41 :     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
   12797           0 :         return NULL;
   12798             :     }
   12799             : 
   12800          41 :     for (i = 0; ; i++) {
   12801             :         void *ptr;
   12802             :         ssize_t result;
   12803             :         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
   12804          47 :         Py_ssize_t buffer_size = buffer_sizes[i];
   12805          47 :         if (!buffer_size) {
   12806           0 :             path_error(path);
   12807           0 :             return NULL;
   12808             :         }
   12809          47 :         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
   12810          47 :         if (!buffer)
   12811           0 :             return NULL;
   12812          47 :         ptr = PyBytes_AS_STRING(buffer);
   12813             : 
   12814          47 :         Py_BEGIN_ALLOW_THREADS;
   12815          47 :         if (path->fd >= 0)
   12816          14 :             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
   12817          33 :         else if (follow_symlinks)
   12818          19 :             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
   12819             :         else
   12820          14 :             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
   12821          47 :         Py_END_ALLOW_THREADS;
   12822             : 
   12823          47 :         if (result < 0) {
   12824          23 :             Py_DECREF(buffer);
   12825          23 :             if (errno == ERANGE)
   12826           6 :                 continue;
   12827          17 :             path_error(path);
   12828          17 :             return NULL;
   12829             :         }
   12830             : 
   12831          24 :         if (result != buffer_size) {
   12832             :             /* Can only shrink. */
   12833          24 :             _PyBytes_Resize(&buffer, result);
   12834             :         }
   12835          24 :         break;
   12836             :     }
   12837             : 
   12838          24 :     return buffer;
   12839             : }
   12840             : 
   12841             : 
   12842             : /*[clinic input]
   12843             : os.setxattr
   12844             : 
   12845             :     path: path_t(allow_fd=True)
   12846             :     attribute: path_t
   12847             :     value: Py_buffer
   12848             :     flags: int = 0
   12849             :     *
   12850             :     follow_symlinks: bool = True
   12851             : 
   12852             : Set extended attribute attribute on path to value.
   12853             : 
   12854             : path may be either a string, a path-like object,  or an open file descriptor.
   12855             : If follow_symlinks is False, and the last element of the path is a symbolic
   12856             :   link, setxattr will modify the symbolic link itself instead of the file
   12857             :   the link points to.
   12858             : 
   12859             : [clinic start generated code]*/
   12860             : 
   12861             : static PyObject *
   12862         647 : os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
   12863             :                  Py_buffer *value, int flags, int follow_symlinks)
   12864             : /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
   12865             : {
   12866             :     ssize_t result;
   12867             : 
   12868         647 :     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
   12869           0 :         return NULL;
   12870             : 
   12871         647 :     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
   12872             :                     value->buf, value->len, flags) < 0) {
   12873           0 :         return NULL;
   12874             :     }
   12875             : 
   12876         647 :     Py_BEGIN_ALLOW_THREADS;
   12877         647 :     if (path->fd > -1)
   12878         216 :         result = fsetxattr(path->fd, attribute->narrow,
   12879         216 :                            value->buf, value->len, flags);
   12880         431 :     else if (follow_symlinks)
   12881         219 :         result = setxattr(path->narrow, attribute->narrow,
   12882         219 :                            value->buf, value->len, flags);
   12883             :     else
   12884         212 :         result = lsetxattr(path->narrow, attribute->narrow,
   12885         212 :                            value->buf, value->len, flags);
   12886         647 :     Py_END_ALLOW_THREADS;
   12887             : 
   12888         647 :     if (result) {
   12889          19 :         path_error(path);
   12890          19 :         return NULL;
   12891             :     }
   12892             : 
   12893         628 :     Py_RETURN_NONE;
   12894             : }
   12895             : 
   12896             : 
   12897             : /*[clinic input]
   12898             : os.removexattr
   12899             : 
   12900             :     path: path_t(allow_fd=True)
   12901             :     attribute: path_t
   12902             :     *
   12903             :     follow_symlinks: bool = True
   12904             : 
   12905             : Remove extended attribute attribute on path.
   12906             : 
   12907             : path may be either a string, a path-like object, or an open file descriptor.
   12908             : If follow_symlinks is False, and the last element of the path is a symbolic
   12909             :   link, removexattr will modify the symbolic link itself instead of the file
   12910             :   the link points to.
   12911             : 
   12912             : [clinic start generated code]*/
   12913             : 
   12914             : static PyObject *
   12915          17 : os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
   12916             :                     int follow_symlinks)
   12917             : /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
   12918             : {
   12919             :     ssize_t result;
   12920             : 
   12921          17 :     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
   12922           0 :         return NULL;
   12923             : 
   12924          17 :     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
   12925           0 :         return NULL;
   12926             :     }
   12927             : 
   12928          17 :     Py_BEGIN_ALLOW_THREADS;
   12929          17 :     if (path->fd > -1)
   12930           4 :         result = fremovexattr(path->fd, attribute->narrow);
   12931          13 :     else if (follow_symlinks)
   12932           9 :         result = removexattr(path->narrow, attribute->narrow);
   12933             :     else
   12934           4 :         result = lremovexattr(path->narrow, attribute->narrow);
   12935          17 :     Py_END_ALLOW_THREADS;
   12936             : 
   12937          17 :     if (result) {
   12938           5 :         return path_error(path);
   12939             :     }
   12940             : 
   12941          12 :     Py_RETURN_NONE;
   12942             : }
   12943             : 
   12944             : 
   12945             : /*[clinic input]
   12946             : os.listxattr
   12947             : 
   12948             :     path: path_t(allow_fd=True, nullable=True) = None
   12949             :     *
   12950             :     follow_symlinks: bool = True
   12951             : 
   12952             : Return a list of extended attributes on path.
   12953             : 
   12954             : path may be either None, a string, a path-like object, or an open file descriptor.
   12955             : if path is None, listxattr will examine the current directory.
   12956             : If follow_symlinks is False, and the last element of the path is a symbolic
   12957             :   link, listxattr will examine the symbolic link itself instead of the file
   12958             :   the link points to.
   12959             : [clinic start generated code]*/
   12960             : 
   12961             : static PyObject *
   12962       11189 : os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
   12963             : /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
   12964             : {
   12965             :     Py_ssize_t i;
   12966       11189 :     PyObject *result = NULL;
   12967             :     const char *name;
   12968       11189 :     char *buffer = NULL;
   12969             : 
   12970       11189 :     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
   12971           0 :         goto exit;
   12972             : 
   12973       11189 :     if (PySys_Audit("os.listxattr", "(O)",
   12974       11189 :                     path->object ? path->object : Py_None) < 0) {
   12975           0 :         return NULL;
   12976             :     }
   12977             : 
   12978       11189 :     name = path->narrow ? path->narrow : ".";
   12979             : 
   12980       11189 :     for (i = 0; ; i++) {
   12981             :         const char *start, *trace, *end;
   12982             :         ssize_t length;
   12983             :         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
   12984       11195 :         Py_ssize_t buffer_size = buffer_sizes[i];
   12985       11195 :         if (!buffer_size) {
   12986             :             /* ERANGE */
   12987           0 :             path_error(path);
   12988           0 :             break;
   12989             :         }
   12990       11195 :         buffer = PyMem_Malloc(buffer_size);
   12991       11195 :         if (!buffer) {
   12992           0 :             PyErr_NoMemory();
   12993           0 :             break;
   12994             :         }
   12995             : 
   12996       11195 :         Py_BEGIN_ALLOW_THREADS;
   12997       11195 :         if (path->fd > -1)
   12998          12 :             length = flistxattr(path->fd, buffer, buffer_size);
   12999       11183 :         else if (follow_symlinks)
   13000       11178 :             length = listxattr(name, buffer, buffer_size);
   13001             :         else
   13002           5 :             length = llistxattr(name, buffer, buffer_size);
   13003       11195 :         Py_END_ALLOW_THREADS;
   13004             : 
   13005       11195 :         if (length < 0) {
   13006          11 :             if (errno == ERANGE) {
   13007           6 :                 PyMem_Free(buffer);
   13008           6 :                 buffer = NULL;
   13009           6 :                 continue;
   13010             :             }
   13011           5 :             path_error(path);
   13012           5 :             break;
   13013             :         }
   13014             : 
   13015       11184 :         result = PyList_New(0);
   13016       11184 :         if (!result) {
   13017           0 :             goto exit;
   13018             :         }
   13019             : 
   13020       11184 :         end = buffer + length;
   13021       18576 :         for (trace = start = buffer; trace != end; trace++) {
   13022        7392 :             if (!*trace) {
   13023             :                 int error;
   13024         624 :                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
   13025             :                                                                  trace - start);
   13026         624 :                 if (!attribute) {
   13027           0 :                     Py_DECREF(result);
   13028           0 :                     result = NULL;
   13029           0 :                     goto exit;
   13030             :                 }
   13031         624 :                 error = PyList_Append(result, attribute);
   13032         624 :                 Py_DECREF(attribute);
   13033         624 :                 if (error) {
   13034           0 :                     Py_DECREF(result);
   13035           0 :                     result = NULL;
   13036           0 :                     goto exit;
   13037             :                 }
   13038         624 :                 start = trace + 1;
   13039             :             }
   13040             :         }
   13041       11184 :     break;
   13042             :     }
   13043       11189 : exit:
   13044       11189 :     if (buffer)
   13045       11189 :         PyMem_Free(buffer);
   13046       11189 :     return result;
   13047             : }
   13048             : #endif /* USE_XATTRS */
   13049             : 
   13050             : 
   13051             : /*[clinic input]
   13052             : os.urandom
   13053             : 
   13054             :     size: Py_ssize_t
   13055             :     /
   13056             : 
   13057             : Return a bytes object containing random bytes suitable for cryptographic use.
   13058             : [clinic start generated code]*/
   13059             : 
   13060             : static PyObject *
   13061      168921 : os_urandom_impl(PyObject *module, Py_ssize_t size)
   13062             : /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
   13063             : {
   13064             :     PyObject *bytes;
   13065             :     int result;
   13066             : 
   13067      168921 :     if (size < 0)
   13068           1 :         return PyErr_Format(PyExc_ValueError,
   13069             :                             "negative argument not allowed");
   13070      168920 :     bytes = PyBytes_FromStringAndSize(NULL, size);
   13071      168920 :     if (bytes == NULL)
   13072           0 :         return NULL;
   13073             : 
   13074      168920 :     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
   13075      168920 :     if (result == -1) {
   13076           0 :         Py_DECREF(bytes);
   13077           0 :         return NULL;
   13078             :     }
   13079      168920 :     return bytes;
   13080             : }
   13081             : 
   13082             : #ifdef HAVE_MEMFD_CREATE
   13083             : /*[clinic input]
   13084             : os.memfd_create
   13085             : 
   13086             :     name: FSConverter
   13087             :     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
   13088             : 
   13089             : [clinic start generated code]*/
   13090             : 
   13091             : static PyObject *
   13092           2 : os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
   13093             : /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
   13094             : {
   13095             :     int fd;
   13096           2 :     const char *bytes = PyBytes_AS_STRING(name);
   13097           2 :     Py_BEGIN_ALLOW_THREADS
   13098           2 :     fd = memfd_create(bytes, flags);
   13099           2 :     Py_END_ALLOW_THREADS
   13100           2 :     if (fd == -1) {
   13101           0 :         return PyErr_SetFromErrno(PyExc_OSError);
   13102             :     }
   13103           2 :     return PyLong_FromLong(fd);
   13104             : }
   13105             : #endif
   13106             : 
   13107             : #ifdef HAVE_EVENTFD
   13108             : /*[clinic input]
   13109             : os.eventfd
   13110             : 
   13111             :     initval: unsigned_int
   13112             :     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
   13113             : 
   13114             : Creates and returns an event notification file descriptor.
   13115             : [clinic start generated code]*/
   13116             : 
   13117             : static PyObject *
   13118           3 : os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
   13119             : /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
   13120             : 
   13121             : {
   13122             :     /* initval is limited to uint32_t, internal counter is uint64_t */
   13123             :     int fd;
   13124           3 :     Py_BEGIN_ALLOW_THREADS
   13125           3 :     fd = eventfd(initval, flags);
   13126           3 :     Py_END_ALLOW_THREADS
   13127           3 :     if (fd == -1) {
   13128           0 :         return PyErr_SetFromErrno(PyExc_OSError);
   13129             :     }
   13130           3 :     return PyLong_FromLong(fd);
   13131             : }
   13132             : 
   13133             : /*[clinic input]
   13134             : os.eventfd_read
   13135             : 
   13136             :     fd: fildes
   13137             : 
   13138             : Read eventfd value
   13139             : [clinic start generated code]*/
   13140             : 
   13141             : static PyObject *
   13142           8 : os_eventfd_read_impl(PyObject *module, int fd)
   13143             : /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
   13144             : {
   13145             :     eventfd_t value;
   13146             :     int result;
   13147           8 :     Py_BEGIN_ALLOW_THREADS
   13148           8 :     result = eventfd_read(fd, &value);
   13149           8 :     Py_END_ALLOW_THREADS
   13150           8 :     if (result == -1) {
   13151           2 :         return PyErr_SetFromErrno(PyExc_OSError);
   13152             :     }
   13153           6 :     return PyLong_FromUnsignedLongLong(value);
   13154             : }
   13155             : 
   13156             : /*[clinic input]
   13157             : os.eventfd_write
   13158             : 
   13159             :     fd: fildes
   13160             :     value: unsigned_long_long
   13161             : 
   13162             : Write eventfd value.
   13163             : [clinic start generated code]*/
   13164             : 
   13165             : static PyObject *
   13166           5 : os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
   13167             : /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
   13168             : {
   13169             :     int result;
   13170           5 :     Py_BEGIN_ALLOW_THREADS
   13171           5 :     result = eventfd_write(fd, value);
   13172           5 :     Py_END_ALLOW_THREADS
   13173           5 :     if (result == -1) {
   13174           0 :         return PyErr_SetFromErrno(PyExc_OSError);
   13175             :     }
   13176           5 :     Py_RETURN_NONE;
   13177             : }
   13178             : #endif  /* HAVE_EVENTFD */
   13179             : 
   13180             : /* Terminal size querying */
   13181             : 
   13182             : PyDoc_STRVAR(TerminalSize_docstring,
   13183             :     "A tuple of (columns, lines) for holding terminal window size");
   13184             : 
   13185             : static PyStructSequence_Field TerminalSize_fields[] = {
   13186             :     {"columns", "width of the terminal window in characters"},
   13187             :     {"lines", "height of the terminal window in characters"},
   13188             :     {NULL, NULL}
   13189             : };
   13190             : 
   13191             : static PyStructSequence_Desc TerminalSize_desc = {
   13192             :     "os.terminal_size",
   13193             :     TerminalSize_docstring,
   13194             :     TerminalSize_fields,
   13195             :     2,
   13196             : };
   13197             : 
   13198             : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
   13199             : /*[clinic input]
   13200             : os.get_terminal_size
   13201             : 
   13202             :     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
   13203             :     /
   13204             : 
   13205             : Return the size of the terminal window as (columns, lines).
   13206             : 
   13207             : The optional argument fd (default standard output) specifies
   13208             : which file descriptor should be queried.
   13209             : 
   13210             : If the file descriptor is not connected to a terminal, an OSError
   13211             : is thrown.
   13212             : 
   13213             : This function will only be defined if an implementation is
   13214             : available for this system.
   13215             : 
   13216             : shutil.get_terminal_size is the high-level function which should
   13217             : normally be used, os.get_terminal_size is the low-level implementation.
   13218             : [clinic start generated code]*/
   13219             : 
   13220             : static PyObject *
   13221       10553 : os_get_terminal_size_impl(PyObject *module, int fd)
   13222             : /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
   13223             : {
   13224             :     int columns, lines;
   13225             :     PyObject *termsize;
   13226             : 
   13227             :     /* Under some conditions stdout may not be connected and
   13228             :      * fileno(stdout) may point to an invalid file descriptor. For example
   13229             :      * GUI apps don't have valid standard streams by default.
   13230             :      *
   13231             :      * If this happens, and the optional fd argument is not present,
   13232             :      * the ioctl below will fail returning EBADF. This is what we want.
   13233             :      */
   13234             : 
   13235             : #ifdef TERMSIZE_USE_IOCTL
   13236             :     {
   13237             :         struct winsize w;
   13238       10553 :         if (ioctl(fd, TIOCGWINSZ, &w))
   13239       10553 :             return PyErr_SetFromErrno(PyExc_OSError);
   13240           0 :         columns = w.ws_col;
   13241           0 :         lines = w.ws_row;
   13242             :     }
   13243             : #endif /* TERMSIZE_USE_IOCTL */
   13244             : 
   13245             : #ifdef TERMSIZE_USE_CONIO
   13246             :     {
   13247             :         DWORD nhandle;
   13248             :         HANDLE handle;
   13249             :         CONSOLE_SCREEN_BUFFER_INFO csbi;
   13250             :         switch (fd) {
   13251             :         case 0: nhandle = STD_INPUT_HANDLE;
   13252             :             break;
   13253             :         case 1: nhandle = STD_OUTPUT_HANDLE;
   13254             :             break;
   13255             :         case 2: nhandle = STD_ERROR_HANDLE;
   13256             :             break;
   13257             :         default:
   13258             :             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
   13259             :         }
   13260             :         handle = GetStdHandle(nhandle);
   13261             :         if (handle == NULL)
   13262             :             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
   13263             :         if (handle == INVALID_HANDLE_VALUE)
   13264             :             return PyErr_SetFromWindowsErr(0);
   13265             : 
   13266             :         if (!GetConsoleScreenBufferInfo(handle, &csbi))
   13267             :             return PyErr_SetFromWindowsErr(0);
   13268             : 
   13269             :         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
   13270             :         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
   13271             :     }
   13272             : #endif /* TERMSIZE_USE_CONIO */
   13273             : 
   13274           0 :     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
   13275           0 :     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
   13276           0 :     if (termsize == NULL)
   13277           0 :         return NULL;
   13278           0 :     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
   13279           0 :     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
   13280           0 :     if (PyErr_Occurred()) {
   13281           0 :         Py_DECREF(termsize);
   13282           0 :         return NULL;
   13283             :     }
   13284           0 :     return termsize;
   13285             : }
   13286             : #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
   13287             : 
   13288             : 
   13289             : /*[clinic input]
   13290             : os.cpu_count
   13291             : 
   13292             : Return the number of CPUs in the system; return None if indeterminable.
   13293             : 
   13294             : This number is not equivalent to the number of CPUs the current process can
   13295             : use.  The number of usable CPUs can be obtained with
   13296             : ``len(os.sched_getaffinity(0))``
   13297             : [clinic start generated code]*/
   13298             : 
   13299             : static PyObject *
   13300         110 : os_cpu_count_impl(PyObject *module)
   13301             : /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
   13302             : {
   13303         110 :     int ncpu = 0;
   13304             : #ifdef MS_WINDOWS
   13305             :     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
   13306             : #elif defined(__hpux)
   13307             :     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
   13308             : #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
   13309         110 :     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
   13310             : #elif defined(__VXWORKS__)
   13311             :     ncpu = _Py_popcount32(vxCpuEnabledGet());
   13312             : #elif defined(__DragonFly__) || \
   13313             :       defined(__OpenBSD__)   || \
   13314             :       defined(__FreeBSD__)   || \
   13315             :       defined(__NetBSD__)    || \
   13316             :       defined(__APPLE__)
   13317             :     int mib[2];
   13318             :     size_t len = sizeof(ncpu);
   13319             :     mib[0] = CTL_HW;
   13320             :     mib[1] = HW_NCPU;
   13321             :     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
   13322             :         ncpu = 0;
   13323             : #endif
   13324         110 :     if (ncpu >= 1)
   13325         110 :         return PyLong_FromLong(ncpu);
   13326             :     else
   13327           0 :         Py_RETURN_NONE;
   13328             : }
   13329             : 
   13330             : 
   13331             : /*[clinic input]
   13332             : os.get_inheritable -> bool
   13333             : 
   13334             :     fd: int
   13335             :     /
   13336             : 
   13337             : Get the close-on-exe flag of the specified file descriptor.
   13338             : [clinic start generated code]*/
   13339             : 
   13340             : static int
   13341         130 : os_get_inheritable_impl(PyObject *module, int fd)
   13342             : /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
   13343             : {
   13344             :     int return_value;
   13345             :     _Py_BEGIN_SUPPRESS_IPH
   13346         130 :     return_value = _Py_get_inheritable(fd);
   13347             :     _Py_END_SUPPRESS_IPH
   13348         130 :     return return_value;
   13349             : }
   13350             : 
   13351             : 
   13352             : /*[clinic input]
   13353             : os.set_inheritable
   13354             :     fd: int
   13355             :     inheritable: int
   13356             :     /
   13357             : 
   13358             : Set the inheritable flag of the specified file descriptor.
   13359             : [clinic start generated code]*/
   13360             : 
   13361             : static PyObject *
   13362          61 : os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
   13363             : /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
   13364             : {
   13365             :     int result;
   13366             : 
   13367             :     _Py_BEGIN_SUPPRESS_IPH
   13368          61 :     result = _Py_set_inheritable(fd, inheritable, NULL);
   13369             :     _Py_END_SUPPRESS_IPH
   13370          61 :     if (result < 0)
   13371           3 :         return NULL;
   13372          58 :     Py_RETURN_NONE;
   13373             : }
   13374             : 
   13375             : 
   13376             : #ifdef MS_WINDOWS
   13377             : /*[clinic input]
   13378             : os.get_handle_inheritable -> bool
   13379             :     handle: intptr_t
   13380             :     /
   13381             : 
   13382             : Get the close-on-exe flag of the specified file descriptor.
   13383             : [clinic start generated code]*/
   13384             : 
   13385             : static int
   13386             : os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
   13387             : /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
   13388             : {
   13389             :     DWORD flags;
   13390             : 
   13391             :     if (!GetHandleInformation((HANDLE)handle, &flags)) {
   13392             :         PyErr_SetFromWindowsErr(0);
   13393             :         return -1;
   13394             :     }
   13395             : 
   13396             :     return flags & HANDLE_FLAG_INHERIT;
   13397             : }
   13398             : 
   13399             : 
   13400             : /*[clinic input]
   13401             : os.set_handle_inheritable
   13402             :     handle: intptr_t
   13403             :     inheritable: bool
   13404             :     /
   13405             : 
   13406             : Set the inheritable flag of the specified handle.
   13407             : [clinic start generated code]*/
   13408             : 
   13409             : static PyObject *
   13410             : os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
   13411             :                                int inheritable)
   13412             : /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
   13413             : {
   13414             :     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
   13415             :     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
   13416             :         PyErr_SetFromWindowsErr(0);
   13417             :         return NULL;
   13418             :     }
   13419             :     Py_RETURN_NONE;
   13420             : }
   13421             : #endif /* MS_WINDOWS */
   13422             : 
   13423             : #ifndef MS_WINDOWS
   13424             : /*[clinic input]
   13425             : os.get_blocking -> bool
   13426             :     fd: int
   13427             :     /
   13428             : 
   13429             : Get the blocking mode of the file descriptor.
   13430             : 
   13431             : Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
   13432             : [clinic start generated code]*/
   13433             : 
   13434             : static int
   13435           7 : os_get_blocking_impl(PyObject *module, int fd)
   13436             : /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
   13437             : {
   13438             :     int blocking;
   13439             : 
   13440             :     _Py_BEGIN_SUPPRESS_IPH
   13441           7 :     blocking = _Py_get_blocking(fd);
   13442             :     _Py_END_SUPPRESS_IPH
   13443           7 :     return blocking;
   13444             : }
   13445             : 
   13446             : /*[clinic input]
   13447             : os.set_blocking
   13448             :     fd: int
   13449             :     blocking: bool(accept={int})
   13450             :     /
   13451             : 
   13452             : Set the blocking mode of the specified file descriptor.
   13453             : 
   13454             : Set the O_NONBLOCK flag if blocking is False,
   13455             : clear the O_NONBLOCK flag otherwise.
   13456             : [clinic start generated code]*/
   13457             : 
   13458             : static PyObject *
   13459         327 : os_set_blocking_impl(PyObject *module, int fd, int blocking)
   13460             : /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
   13461             : {
   13462             :     int result;
   13463             : 
   13464             :     _Py_BEGIN_SUPPRESS_IPH
   13465         327 :     result = _Py_set_blocking(fd, blocking);
   13466             :     _Py_END_SUPPRESS_IPH
   13467         327 :     if (result < 0)
   13468           1 :         return NULL;
   13469         326 :     Py_RETURN_NONE;
   13470             : }
   13471             : #endif   /* !MS_WINDOWS */
   13472             : 
   13473             : 
   13474             : /*[clinic input]
   13475             : class os.DirEntry "DirEntry *" "DirEntryType"
   13476             : [clinic start generated code]*/
   13477             : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
   13478             : 
   13479             : typedef struct {
   13480             :     PyObject_HEAD
   13481             :     PyObject *name;
   13482             :     PyObject *path;
   13483             :     PyObject *stat;
   13484             :     PyObject *lstat;
   13485             : #ifdef MS_WINDOWS
   13486             :     struct _Py_stat_struct win32_lstat;
   13487             :     uint64_t win32_file_index;
   13488             :     int got_file_index;
   13489             : #else /* POSIX */
   13490             : #ifdef HAVE_DIRENT_D_TYPE
   13491             :     unsigned char d_type;
   13492             : #endif
   13493             :     ino_t d_ino;
   13494             :     int dir_fd;
   13495             : #endif
   13496             : } DirEntry;
   13497             : 
   13498             : static void
   13499      110745 : DirEntry_dealloc(DirEntry *entry)
   13500             : {
   13501      110745 :     PyTypeObject *tp = Py_TYPE(entry);
   13502      110745 :     Py_XDECREF(entry->name);
   13503      110745 :     Py_XDECREF(entry->path);
   13504      110745 :     Py_XDECREF(entry->stat);
   13505      110745 :     Py_XDECREF(entry->lstat);
   13506      110745 :     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
   13507      110745 :     free_func(entry);
   13508      110745 :     Py_DECREF(tp);
   13509      110745 : }
   13510             : 
   13511             : /* Forward reference */
   13512             : static int
   13513             : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
   13514             :                    int follow_symlinks, unsigned short mode_bits);
   13515             : 
   13516             : /*[clinic input]
   13517             : os.DirEntry.is_symlink -> bool
   13518             :     defining_class: defining_class
   13519             :     /
   13520             : 
   13521             : Return True if the entry is a symbolic link; cached per entry.
   13522             : [clinic start generated code]*/
   13523             : 
   13524             : static int
   13525       38764 : os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
   13526             : /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
   13527             : {
   13528             : #ifdef MS_WINDOWS
   13529             :     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
   13530             : #elif defined(HAVE_DIRENT_D_TYPE)
   13531             :     /* POSIX */
   13532       38764 :     if (self->d_type != DT_UNKNOWN)
   13533       38764 :         return self->d_type == DT_LNK;
   13534             :     else
   13535           0 :         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
   13536             : #else
   13537             :     /* POSIX without d_type */
   13538             :     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
   13539             : #endif
   13540             : }
   13541             : 
   13542             : static PyObject *
   13543       20174 : DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
   13544             : {
   13545             :     int result;
   13546             :     STRUCT_STAT st;
   13547             :     PyObject *ub;
   13548             : 
   13549             : #ifdef MS_WINDOWS
   13550             :     if (!PyUnicode_FSDecoder(self->path, &ub))
   13551             :         return NULL;
   13552             :     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
   13553             :     Py_DECREF(ub);
   13554             : #else /* POSIX */
   13555       20174 :     if (!PyUnicode_FSConverter(self->path, &ub))
   13556           0 :         return NULL;
   13557       20174 :     const char *path = PyBytes_AS_STRING(ub);
   13558       20174 :     if (self->dir_fd != DEFAULT_DIR_FD) {
   13559             : #ifdef HAVE_FSTATAT
   13560             :       if (HAVE_FSTATAT_RUNTIME) {
   13561        8257 :         Py_BEGIN_ALLOW_THREADS
   13562        8257 :         result = fstatat(self->dir_fd, path, &st,
   13563             :                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
   13564        8257 :         Py_END_ALLOW_THREADS
   13565             :       } else
   13566             : 
   13567             : #endif /* HAVE_FSTATAT */
   13568             :       {
   13569             :         Py_DECREF(ub);
   13570             :         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
   13571             :         return NULL;
   13572             :       }
   13573             :     }
   13574             :     else
   13575             : #endif
   13576             :     {
   13577       11917 :         Py_BEGIN_ALLOW_THREADS
   13578       11917 :         if (follow_symlinks) {
   13579         794 :             result = STAT(path, &st);
   13580             :         }
   13581             :         else {
   13582       11123 :             result = LSTAT(path, &st);
   13583             :         }
   13584       11917 :         Py_END_ALLOW_THREADS
   13585             :     }
   13586             : #if defined(MS_WINDOWS)
   13587             :     PyMem_Free(path);
   13588             : #else
   13589       20174 :     Py_DECREF(ub);
   13590             : #endif
   13591             : 
   13592       20174 :     if (result != 0)
   13593        2183 :         return path_object_error(self->path);
   13594             : 
   13595       17991 :     return _pystat_fromstructstat(module, &st);
   13596             : }
   13597             : 
   13598             : static PyObject *
   13599       17059 : DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
   13600             : {
   13601       17059 :     if (!self->lstat) {
   13602       17055 :         PyObject *module = PyType_GetModule(defining_class);
   13603             : #ifdef MS_WINDOWS
   13604             :         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
   13605             : #else /* POSIX */
   13606       17055 :         self->lstat = DirEntry_fetch_stat(module, self, 0);
   13607             : #endif
   13608             :     }
   13609       17059 :     Py_XINCREF(self->lstat);
   13610       17059 :     return self->lstat;
   13611             : }
   13612             : 
   13613             : /*[clinic input]
   13614             : os.DirEntry.stat
   13615             :     defining_class: defining_class
   13616             :     /
   13617             :     *
   13618             :     follow_symlinks: bool = True
   13619             : 
   13620             : Return stat_result object for the entry; cached per entry.
   13621             : [clinic start generated code]*/
   13622             : 
   13623             : static PyObject *
   13624       40818 : os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
   13625             :                       int follow_symlinks)
   13626             : /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
   13627             : {
   13628       40818 :     if (!follow_symlinks) {
   13629        5943 :         return DirEntry_get_lstat(defining_class, self);
   13630             :     }
   13631             : 
   13632       34875 :     if (!self->stat) {
   13633       14235 :         int result = os_DirEntry_is_symlink_impl(self, defining_class);
   13634       14235 :         if (result == -1) {
   13635           0 :             return NULL;
   13636             :         }
   13637       14235 :         if (result) {
   13638        3119 :             PyObject *module = PyType_GetModule(defining_class);
   13639        3119 :             self->stat = DirEntry_fetch_stat(module, self, 1);
   13640             :         }
   13641             :         else {
   13642       11116 :             self->stat = DirEntry_get_lstat(defining_class, self);
   13643             :         }
   13644             :     }
   13645             : 
   13646       34875 :     Py_XINCREF(self->stat);
   13647       34875 :     return self->stat;
   13648             : }
   13649             : 
   13650             : /* Set exception and return -1 on error, 0 for False, 1 for True */
   13651             : static int
   13652      103445 : DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
   13653             :                    int follow_symlinks, unsigned short mode_bits)
   13654             : {
   13655      103445 :     PyObject *stat = NULL;
   13656      103445 :     PyObject *st_mode = NULL;
   13657             :     long mode;
   13658             :     int result;
   13659             : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
   13660             :     int is_symlink;
   13661             :     int need_stat;
   13662             : #endif
   13663             : #ifdef MS_WINDOWS
   13664             :     unsigned long dir_bits;
   13665             : #endif
   13666             : 
   13667             : #ifdef MS_WINDOWS
   13668             :     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
   13669             :     need_stat = follow_symlinks && is_symlink;
   13670             : #elif defined(HAVE_DIRENT_D_TYPE)
   13671      103445 :     is_symlink = self->d_type == DT_LNK;
   13672      103445 :     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
   13673             : #endif
   13674             : 
   13675             : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
   13676      103445 :     if (need_stat) {
   13677             : #endif
   13678        3117 :         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
   13679        3117 :         if (!stat) {
   13680        2166 :             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
   13681             :                 /* If file doesn't exist (anymore), then return False
   13682             :                    (i.e., say it's not a file/directory) */
   13683         982 :                 PyErr_Clear();
   13684         982 :                 return 0;
   13685             :             }
   13686        1184 :             goto error;
   13687             :         }
   13688         951 :         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
   13689         951 :         st_mode = PyObject_GetAttr(stat, state->st_mode);
   13690         951 :         if (!st_mode)
   13691           0 :             goto error;
   13692             : 
   13693         951 :         mode = PyLong_AsLong(st_mode);
   13694         951 :         if (mode == -1 && PyErr_Occurred())
   13695           0 :             goto error;
   13696         951 :         Py_CLEAR(st_mode);
   13697         951 :         Py_CLEAR(stat);
   13698         951 :         result = (mode & S_IFMT) == mode_bits;
   13699             : #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
   13700             :     }
   13701      100328 :     else if (is_symlink) {
   13702        1199 :         assert(mode_bits != S_IFLNK);
   13703        1199 :         result = 0;
   13704             :     }
   13705             :     else {
   13706       99129 :         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
   13707             : #ifdef MS_WINDOWS
   13708             :         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
   13709             :         if (mode_bits == S_IFDIR)
   13710             :             result = dir_bits != 0;
   13711             :         else
   13712             :             result = dir_bits == 0;
   13713             : #else /* POSIX */
   13714       99129 :         if (mode_bits == S_IFDIR)
   13715       99122 :             result = self->d_type == DT_DIR;
   13716             :         else
   13717           7 :             result = self->d_type == DT_REG;
   13718             : #endif
   13719             :     }
   13720             : #endif
   13721             : 
   13722      101279 :     return result;
   13723             : 
   13724        1184 : error:
   13725        1184 :     Py_XDECREF(st_mode);
   13726        1184 :     Py_XDECREF(stat);
   13727        1184 :     return -1;
   13728             : }
   13729             : 
   13730             : /*[clinic input]
   13731             : os.DirEntry.is_dir -> bool
   13732             :     defining_class: defining_class
   13733             :     /
   13734             :     *
   13735             :     follow_symlinks: bool = True
   13736             : 
   13737             : Return True if the entry is a directory; cached per entry.
   13738             : [clinic start generated code]*/
   13739             : 
   13740             : static int
   13741      103432 : os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
   13742             :                         int follow_symlinks)
   13743             : /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
   13744             : {
   13745      103432 :     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
   13746             : }
   13747             : 
   13748             : /*[clinic input]
   13749             : os.DirEntry.is_file -> bool
   13750             :     defining_class: defining_class
   13751             :     /
   13752             :     *
   13753             :     follow_symlinks: bool = True
   13754             : 
   13755             : Return True if the entry is a file; cached per entry.
   13756             : [clinic start generated code]*/
   13757             : 
   13758             : static int
   13759          13 : os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
   13760             :                          int follow_symlinks)
   13761             : /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
   13762             : {
   13763          13 :     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
   13764             : }
   13765             : 
   13766             : /*[clinic input]
   13767             : os.DirEntry.inode
   13768             : 
   13769             : Return inode of the entry; cached per entry.
   13770             : [clinic start generated code]*/
   13771             : 
   13772             : static PyObject *
   13773           8 : os_DirEntry_inode_impl(DirEntry *self)
   13774             : /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
   13775             : {
   13776             : #ifdef MS_WINDOWS
   13777             :     if (!self->got_file_index) {
   13778             :         PyObject *unicode;
   13779             :         STRUCT_STAT stat;
   13780             :         int result;
   13781             : 
   13782             :         if (!PyUnicode_FSDecoder(self->path, &unicode))
   13783             :             return NULL;
   13784             :         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
   13785             :         Py_DECREF(unicode);
   13786             :         result = LSTAT(path, &stat);
   13787             :         PyMem_Free(path);
   13788             : 
   13789             :         if (result != 0)
   13790             :             return path_object_error(self->path);
   13791             : 
   13792             :         self->win32_file_index = stat.st_ino;
   13793             :         self->got_file_index = 1;
   13794             :     }
   13795             :     static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
   13796             :                   "DirEntry.win32_file_index is larger than unsigned long long");
   13797             :     return PyLong_FromUnsignedLongLong(self->win32_file_index);
   13798             : #else /* POSIX */
   13799             :     static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
   13800             :                   "DirEntry.d_ino is larger than unsigned long long");
   13801           8 :     return PyLong_FromUnsignedLongLong(self->d_ino);
   13802             : #endif
   13803             : }
   13804             : 
   13805             : static PyObject *
   13806           1 : DirEntry_repr(DirEntry *self)
   13807             : {
   13808           1 :     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
   13809             : }
   13810             : 
   13811             : /*[clinic input]
   13812             : os.DirEntry.__fspath__
   13813             : 
   13814             : Returns the path for the entry.
   13815             : [clinic start generated code]*/
   13816             : 
   13817             : static PyObject *
   13818       33273 : os_DirEntry___fspath___impl(DirEntry *self)
   13819             : /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
   13820             : {
   13821       33273 :     Py_INCREF(self->path);
   13822       33273 :     return self->path;
   13823             : }
   13824             : 
   13825             : static PyMemberDef DirEntry_members[] = {
   13826             :     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
   13827             :      "the entry's base filename, relative to scandir() \"path\" argument"},
   13828             :     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
   13829             :      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
   13830             :     {NULL}
   13831             : };
   13832             : 
   13833             : #include "clinic/posixmodule.c.h"
   13834             : 
   13835             : static PyMethodDef DirEntry_methods[] = {
   13836             :     OS_DIRENTRY_IS_DIR_METHODDEF
   13837             :     OS_DIRENTRY_IS_FILE_METHODDEF
   13838             :     OS_DIRENTRY_IS_SYMLINK_METHODDEF
   13839             :     OS_DIRENTRY_STAT_METHODDEF
   13840             :     OS_DIRENTRY_INODE_METHODDEF
   13841             :     OS_DIRENTRY___FSPATH___METHODDEF
   13842             :     {"__class_getitem__",       Py_GenericAlias,
   13843             :     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
   13844             :     {NULL}
   13845             : };
   13846             : 
   13847             : static PyType_Slot DirEntryType_slots[] = {
   13848             :     {Py_tp_dealloc, DirEntry_dealloc},
   13849             :     {Py_tp_repr, DirEntry_repr},
   13850             :     {Py_tp_methods, DirEntry_methods},
   13851             :     {Py_tp_members, DirEntry_members},
   13852             :     {0, 0},
   13853             : };
   13854             : 
   13855             : static PyType_Spec DirEntryType_spec = {
   13856             :     MODNAME ".DirEntry",
   13857             :     sizeof(DirEntry),
   13858             :     0,
   13859             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
   13860             :     DirEntryType_slots
   13861             : };
   13862             : 
   13863             : 
   13864             : #ifdef MS_WINDOWS
   13865             : 
   13866             : static wchar_t *
   13867             : join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
   13868             : {
   13869             :     Py_ssize_t path_len;
   13870             :     Py_ssize_t size;
   13871             :     wchar_t *result;
   13872             :     wchar_t ch;
   13873             : 
   13874             :     if (!path_wide) { /* Default arg: "." */
   13875             :         path_wide = L".";
   13876             :         path_len = 1;
   13877             :     }
   13878             :     else {
   13879             :         path_len = wcslen(path_wide);
   13880             :     }
   13881             : 
   13882             :     /* The +1's are for the path separator and the NUL */
   13883             :     size = path_len + 1 + wcslen(filename) + 1;
   13884             :     result = PyMem_New(wchar_t, size);
   13885             :     if (!result) {
   13886             :         PyErr_NoMemory();
   13887             :         return NULL;
   13888             :     }
   13889             :     wcscpy(result, path_wide);
   13890             :     if (path_len > 0) {
   13891             :         ch = result[path_len - 1];
   13892             :         if (ch != SEP && ch != ALTSEP && ch != L':')
   13893             :             result[path_len++] = SEP;
   13894             :         wcscpy(result + path_len, filename);
   13895             :     }
   13896             :     return result;
   13897             : }
   13898             : 
   13899             : static PyObject *
   13900             : DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
   13901             : {
   13902             :     DirEntry *entry;
   13903             :     BY_HANDLE_FILE_INFORMATION file_info;
   13904             :     ULONG reparse_tag;
   13905             :     wchar_t *joined_path;
   13906             : 
   13907             :     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
   13908             :     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
   13909             :     if (!entry)
   13910             :         return NULL;
   13911             :     entry->name = NULL;
   13912             :     entry->path = NULL;
   13913             :     entry->stat = NULL;
   13914             :     entry->lstat = NULL;
   13915             :     entry->got_file_index = 0;
   13916             : 
   13917             :     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
   13918             :     if (!entry->name)
   13919             :         goto error;
   13920             :     if (path->narrow) {
   13921             :         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
   13922             :         if (!entry->name)
   13923             :             goto error;
   13924             :     }
   13925             : 
   13926             :     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
   13927             :     if (!joined_path)
   13928             :         goto error;
   13929             : 
   13930             :     entry->path = PyUnicode_FromWideChar(joined_path, -1);
   13931             :     PyMem_Free(joined_path);
   13932             :     if (!entry->path)
   13933             :         goto error;
   13934             :     if (path->narrow) {
   13935             :         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
   13936             :         if (!entry->path)
   13937             :             goto error;
   13938             :     }
   13939             : 
   13940             :     find_data_to_file_info(dataW, &file_info, &reparse_tag);
   13941             :     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
   13942             : 
   13943             :     return (PyObject *)entry;
   13944             : 
   13945             : error:
   13946             :     Py_DECREF(entry);
   13947             :     return NULL;
   13948             : }
   13949             : 
   13950             : #else /* POSIX */
   13951             : 
   13952             : static char *
   13953       62160 : join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
   13954             : {
   13955             :     Py_ssize_t path_len;
   13956             :     Py_ssize_t size;
   13957             :     char *result;
   13958             : 
   13959       62160 :     if (!path_narrow) { /* Default arg: "." */
   13960           1 :         path_narrow = ".";
   13961           1 :         path_len = 1;
   13962             :     }
   13963             :     else {
   13964       62159 :         path_len = strlen(path_narrow);
   13965             :     }
   13966             : 
   13967       62160 :     if (filename_len == -1)
   13968           0 :         filename_len = strlen(filename);
   13969             : 
   13970             :     /* The +1's are for the path separator and the NUL */
   13971       62160 :     size = path_len + 1 + filename_len + 1;
   13972       62160 :     result = PyMem_New(char, size);
   13973       62160 :     if (!result) {
   13974           0 :         PyErr_NoMemory();
   13975           0 :         return NULL;
   13976             :     }
   13977       62160 :     strcpy(result, path_narrow);
   13978       62160 :     if (path_len > 0 && result[path_len - 1] != '/')
   13979       62070 :         result[path_len++] = '/';
   13980       62160 :     strcpy(result + path_len, filename);
   13981       62160 :     return result;
   13982             : }
   13983             : 
   13984             : static PyObject *
   13985      110745 : DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
   13986             :                          Py_ssize_t name_len, ino_t d_ino
   13987             : #ifdef HAVE_DIRENT_D_TYPE
   13988             :                          , unsigned char d_type
   13989             : #endif
   13990             :                          )
   13991             : {
   13992             :     DirEntry *entry;
   13993             :     char *joined_path;
   13994             : 
   13995      110745 :     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
   13996      110745 :     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
   13997      110745 :     if (!entry)
   13998           0 :         return NULL;
   13999      110745 :     entry->name = NULL;
   14000      110745 :     entry->path = NULL;
   14001      110745 :     entry->stat = NULL;
   14002      110745 :     entry->lstat = NULL;
   14003             : 
   14004      110745 :     if (path->fd != -1) {
   14005       48585 :         entry->dir_fd = path->fd;
   14006       48585 :         joined_path = NULL;
   14007             :     }
   14008             :     else {
   14009       62160 :         entry->dir_fd = DEFAULT_DIR_FD;
   14010       62160 :         joined_path = join_path_filename(path->narrow, name, name_len);
   14011       62160 :         if (!joined_path)
   14012           0 :             goto error;
   14013             :     }
   14014             : 
   14015      110745 :     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
   14016      102396 :         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
   14017      102396 :         if (joined_path)
   14018       53811 :             entry->path = PyUnicode_DecodeFSDefault(joined_path);
   14019             :     }
   14020             :     else {
   14021        8349 :         entry->name = PyBytes_FromStringAndSize(name, name_len);
   14022        8349 :         if (joined_path)
   14023        8349 :             entry->path = PyBytes_FromString(joined_path);
   14024             :     }
   14025      110745 :     PyMem_Free(joined_path);
   14026      110745 :     if (!entry->name)
   14027           0 :         goto error;
   14028             : 
   14029      110745 :     if (path->fd != -1) {
   14030       48585 :         entry->path = entry->name;
   14031       48585 :         Py_INCREF(entry->path);
   14032             :     }
   14033       62160 :     else if (!entry->path)
   14034           0 :         goto error;
   14035             : 
   14036             : #ifdef HAVE_DIRENT_D_TYPE
   14037      110745 :     entry->d_type = d_type;
   14038             : #endif
   14039      110745 :     entry->d_ino = d_ino;
   14040             : 
   14041      110745 :     return (PyObject *)entry;
   14042             : 
   14043           0 : error:
   14044           0 :     Py_XDECREF(entry);
   14045           0 :     return NULL;
   14046             : }
   14047             : 
   14048             : #endif
   14049             : 
   14050             : 
   14051             : typedef struct {
   14052             :     PyObject_HEAD
   14053             :     path_t path;
   14054             : #ifdef MS_WINDOWS
   14055             :     HANDLE handle;
   14056             :     WIN32_FIND_DATAW file_data;
   14057             :     int first_time;
   14058             : #else /* POSIX */
   14059             :     DIR *dirp;
   14060             : #endif
   14061             : #ifdef HAVE_FDOPENDIR
   14062             :     int fd;
   14063             : #endif
   14064             : } ScandirIterator;
   14065             : 
   14066             : #ifdef MS_WINDOWS
   14067             : 
   14068             : static int
   14069             : ScandirIterator_is_closed(ScandirIterator *iterator)
   14070             : {
   14071             :     return iterator->handle == INVALID_HANDLE_VALUE;
   14072             : }
   14073             : 
   14074             : static void
   14075             : ScandirIterator_closedir(ScandirIterator *iterator)
   14076             : {
   14077             :     HANDLE handle = iterator->handle;
   14078             : 
   14079             :     if (handle == INVALID_HANDLE_VALUE)
   14080             :         return;
   14081             : 
   14082             :     iterator->handle = INVALID_HANDLE_VALUE;
   14083             :     Py_BEGIN_ALLOW_THREADS
   14084             :     FindClose(handle);
   14085             :     Py_END_ALLOW_THREADS
   14086             : }
   14087             : 
   14088             : static PyObject *
   14089             : ScandirIterator_iternext(ScandirIterator *iterator)
   14090             : {
   14091             :     WIN32_FIND_DATAW *file_data = &iterator->file_data;
   14092             :     BOOL success;
   14093             :     PyObject *entry;
   14094             : 
   14095             :     /* Happens if the iterator is iterated twice, or closed explicitly */
   14096             :     if (iterator->handle == INVALID_HANDLE_VALUE)
   14097             :         return NULL;
   14098             : 
   14099             :     while (1) {
   14100             :         if (!iterator->first_time) {
   14101             :             Py_BEGIN_ALLOW_THREADS
   14102             :             success = FindNextFileW(iterator->handle, file_data);
   14103             :             Py_END_ALLOW_THREADS
   14104             :             if (!success) {
   14105             :                 /* Error or no more files */
   14106             :                 if (GetLastError() != ERROR_NO_MORE_FILES)
   14107             :                     path_error(&iterator->path);
   14108             :                 break;
   14109             :             }
   14110             :         }
   14111             :         iterator->first_time = 0;
   14112             : 
   14113             :         /* Skip over . and .. */
   14114             :         if (wcscmp(file_data->cFileName, L".") != 0 &&
   14115             :             wcscmp(file_data->cFileName, L"..") != 0)
   14116             :         {
   14117             :             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
   14118             :             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
   14119             :             if (!entry)
   14120             :                 break;
   14121             :             return entry;
   14122             :         }
   14123             : 
   14124             :         /* Loop till we get a non-dot directory or finish iterating */
   14125             :     }
   14126             : 
   14127             :     /* Error or no more files */
   14128             :     ScandirIterator_closedir(iterator);
   14129             :     return NULL;
   14130             : }
   14131             : 
   14132             : #else /* POSIX */
   14133             : 
   14134             : static int
   14135       48335 : ScandirIterator_is_closed(ScandirIterator *iterator)
   14136             : {
   14137       48335 :     return !iterator->dirp;
   14138             : }
   14139             : 
   14140             : static void
   14141       92470 : ScandirIterator_closedir(ScandirIterator *iterator)
   14142             : {
   14143       92470 :     DIR *dirp = iterator->dirp;
   14144             : 
   14145       92470 :     if (!dirp)
   14146       44592 :         return;
   14147             : 
   14148       47878 :     iterator->dirp = NULL;
   14149       47878 :     Py_BEGIN_ALLOW_THREADS
   14150             : #ifdef HAVE_FDOPENDIR
   14151       47878 :     if (iterator->path.fd != -1)
   14152       13280 :         rewinddir(dirp);
   14153             : #endif
   14154       47878 :     closedir(dirp);
   14155       47878 :     Py_END_ALLOW_THREADS
   14156       47878 :     return;
   14157             : }
   14158             : 
   14159             : static PyObject *
   14160      158617 : ScandirIterator_iternext(ScandirIterator *iterator)
   14161             : {
   14162             :     struct dirent *direntp;
   14163             :     Py_ssize_t name_len;
   14164             :     int is_dot;
   14165             :     PyObject *entry;
   14166             : 
   14167             :     /* Happens if the iterator is iterated twice, or closed explicitly */
   14168      158617 :     if (!iterator->dirp)
   14169           1 :         return NULL;
   14170             : 
   14171             :     while (1) {
   14172      254368 :         errno = 0;
   14173      254368 :         Py_BEGIN_ALLOW_THREADS
   14174      254368 :         direntp = readdir(iterator->dirp);
   14175      254368 :         Py_END_ALLOW_THREADS
   14176             : 
   14177      254368 :         if (!direntp) {
   14178             :             /* Error or no more files */
   14179       47871 :             if (errno != 0)
   14180           0 :                 path_error(&iterator->path);
   14181       47871 :             break;
   14182             :         }
   14183             : 
   14184             :         /* Skip over . and .. */
   14185      206497 :         name_len = NAMLEN(direntp);
   14186      255377 :         is_dot = direntp->d_name[0] == '.' &&
   14187       48880 :                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
   14188      206497 :         if (!is_dot) {
   14189      110745 :             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
   14190      110745 :             entry = DirEntry_from_posix_info(module,
   14191      110745 :                                              &iterator->path, direntp->d_name,
   14192             :                                              name_len, direntp->d_ino
   14193             : #ifdef HAVE_DIRENT_D_TYPE
   14194      110745 :                                              , direntp->d_type
   14195             : #endif
   14196             :                                             );
   14197      110745 :             if (!entry)
   14198           0 :                 break;
   14199      110745 :             return entry;
   14200             :         }
   14201             : 
   14202             :         /* Loop till we get a non-dot directory or finish iterating */
   14203             :     }
   14204             : 
   14205             :     /* Error or no more files */
   14206       47871 :     ScandirIterator_closedir(iterator);
   14207       47871 :     return NULL;
   14208             : }
   14209             : 
   14210             : #endif
   14211             : 
   14212             : static PyObject *
   14213           5 : ScandirIterator_close(ScandirIterator *self, PyObject *args)
   14214             : {
   14215           5 :     ScandirIterator_closedir(self);
   14216           5 :     Py_RETURN_NONE;
   14217             : }
   14218             : 
   14219             : static PyObject *
   14220       44593 : ScandirIterator_enter(PyObject *self, PyObject *args)
   14221             : {
   14222       44593 :     Py_INCREF(self);
   14223       44593 :     return self;
   14224             : }
   14225             : 
   14226             : static PyObject *
   14227       44593 : ScandirIterator_exit(ScandirIterator *self, PyObject *args)
   14228             : {
   14229       44593 :     ScandirIterator_closedir(self);
   14230       44593 :     Py_RETURN_NONE;
   14231             : }
   14232             : 
   14233             : static void
   14234       48335 : ScandirIterator_finalize(ScandirIterator *iterator)
   14235             : {
   14236             :     PyObject *error_type, *error_value, *error_traceback;
   14237             : 
   14238             :     /* Save the current exception, if any. */
   14239       48335 :     PyErr_Fetch(&error_type, &error_value, &error_traceback);
   14240             : 
   14241       48335 :     if (!ScandirIterator_is_closed(iterator)) {
   14242           1 :         ScandirIterator_closedir(iterator);
   14243             : 
   14244           1 :         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
   14245             :                                   "unclosed scandir iterator %R", iterator)) {
   14246             :             /* Spurious errors can appear at shutdown */
   14247           0 :             if (PyErr_ExceptionMatches(PyExc_Warning)) {
   14248           0 :                 PyErr_WriteUnraisable((PyObject *) iterator);
   14249             :             }
   14250             :         }
   14251             :     }
   14252             : 
   14253       48335 :     path_cleanup(&iterator->path);
   14254             : 
   14255             :     /* Restore the saved exception. */
   14256       48335 :     PyErr_Restore(error_type, error_value, error_traceback);
   14257       48335 : }
   14258             : 
   14259             : static void
   14260       48335 : ScandirIterator_dealloc(ScandirIterator *iterator)
   14261             : {
   14262       48335 :     PyTypeObject *tp = Py_TYPE(iterator);
   14263       48335 :     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
   14264           1 :         return;
   14265             : 
   14266       48334 :     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
   14267       48334 :     free_func(iterator);
   14268       48334 :     Py_DECREF(tp);
   14269             : }
   14270             : 
   14271             : static PyMethodDef ScandirIterator_methods[] = {
   14272             :     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
   14273             :     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
   14274             :     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
   14275             :     {NULL}
   14276             : };
   14277             : 
   14278             : static PyType_Slot ScandirIteratorType_slots[] = {
   14279             :     {Py_tp_dealloc, ScandirIterator_dealloc},
   14280             :     {Py_tp_finalize, ScandirIterator_finalize},
   14281             :     {Py_tp_iter, PyObject_SelfIter},
   14282             :     {Py_tp_iternext, ScandirIterator_iternext},
   14283             :     {Py_tp_methods, ScandirIterator_methods},
   14284             :     {0, 0},
   14285             : };
   14286             : 
   14287             : static PyType_Spec ScandirIteratorType_spec = {
   14288             :     MODNAME ".ScandirIterator",
   14289             :     sizeof(ScandirIterator),
   14290             :     0,
   14291             :     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
   14292             :     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
   14293             :     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
   14294             :         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
   14295             :     ScandirIteratorType_slots
   14296             : };
   14297             : 
   14298             : /*[clinic input]
   14299             : os.scandir
   14300             : 
   14301             :     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
   14302             : 
   14303             : Return an iterator of DirEntry objects for given path.
   14304             : 
   14305             : path can be specified as either str, bytes, or a path-like object.  If path
   14306             : is bytes, the names of yielded DirEntry objects will also be bytes; in
   14307             : all other circumstances they will be str.
   14308             : 
   14309             : If path is None, uses the path='.'.
   14310             : [clinic start generated code]*/
   14311             : 
   14312             : static PyObject *
   14313       48334 : os_scandir_impl(PyObject *module, path_t *path)
   14314             : /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
   14315             : {
   14316             :     ScandirIterator *iterator;
   14317             : #ifdef MS_WINDOWS
   14318             :     wchar_t *path_strW;
   14319             : #else
   14320             :     const char *path_str;
   14321             : #ifdef HAVE_FDOPENDIR
   14322       48334 :     int fd = -1;
   14323             : #endif
   14324             : #endif
   14325             : 
   14326       48334 :     if (PySys_Audit("os.scandir", "O",
   14327       48334 :                     path->object ? path->object : Py_None) < 0) {
   14328           0 :         return NULL;
   14329             :     }
   14330             : 
   14331       48334 :     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
   14332       48334 :     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
   14333       48334 :     if (!iterator)
   14334           0 :         return NULL;
   14335             : 
   14336             : #ifdef MS_WINDOWS
   14337             :     iterator->handle = INVALID_HANDLE_VALUE;
   14338             : #else
   14339       48334 :     iterator->dirp = NULL;
   14340             : #endif
   14341             : 
   14342             :     /* Move the ownership to iterator->path */
   14343       48334 :     memcpy(&iterator->path, path, sizeof(path_t));
   14344       48334 :     memset(path, 0, sizeof(path_t));
   14345             : 
   14346             : #ifdef MS_WINDOWS
   14347             :     iterator->first_time = 1;
   14348             : 
   14349             :     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
   14350             :     if (!path_strW)
   14351             :         goto error;
   14352             : 
   14353             :     Py_BEGIN_ALLOW_THREADS
   14354             :     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
   14355             :     Py_END_ALLOW_THREADS
   14356             : 
   14357             :     PyMem_Free(path_strW);
   14358             : 
   14359             :     if (iterator->handle == INVALID_HANDLE_VALUE) {
   14360             :         path_error(&iterator->path);
   14361             :         goto error;
   14362             :     }
   14363             : #else /* POSIX */
   14364       48334 :     errno = 0;
   14365             : #ifdef HAVE_FDOPENDIR
   14366       48334 :     if (iterator->path.fd != -1) {
   14367             :       if (HAVE_FDOPENDIR_RUNTIME) {
   14368             :         /* closedir() closes the FD, so we duplicate it */
   14369       13284 :         fd = _Py_dup(iterator->path.fd);
   14370       13284 :         if (fd == -1)
   14371           0 :             goto error;
   14372             : 
   14373       13284 :         Py_BEGIN_ALLOW_THREADS
   14374       13284 :         iterator->dirp = fdopendir(fd);
   14375       13284 :         Py_END_ALLOW_THREADS
   14376             :       } else {
   14377             :         PyErr_SetString(PyExc_TypeError,
   14378             :             "scandir: path should be string, bytes, os.PathLike or None, not int");
   14379             :         return NULL;
   14380             :       }
   14381             :     }
   14382             :     else
   14383             : #endif
   14384             :     {
   14385       35050 :         if (iterator->path.narrow)
   14386       35049 :             path_str = iterator->path.narrow;
   14387             :         else
   14388           1 :             path_str = ".";
   14389             : 
   14390       35050 :         Py_BEGIN_ALLOW_THREADS
   14391       35050 :         iterator->dirp = opendir(path_str);
   14392       35050 :         Py_END_ALLOW_THREADS
   14393             :     }
   14394             : 
   14395       48334 :     if (!iterator->dirp) {
   14396         456 :         path_error(&iterator->path);
   14397             : #ifdef HAVE_FDOPENDIR
   14398         456 :         if (fd != -1) {
   14399           4 :             Py_BEGIN_ALLOW_THREADS
   14400           4 :             close(fd);
   14401           4 :             Py_END_ALLOW_THREADS
   14402             :         }
   14403             : #endif
   14404         456 :         goto error;
   14405             :     }
   14406             : #endif
   14407             : 
   14408       47878 :     return (PyObject *)iterator;
   14409             : 
   14410         456 : error:
   14411         456 :     Py_DECREF(iterator);
   14412         456 :     return NULL;
   14413             : }
   14414             : 
   14415             : /*
   14416             :     Return the file system path representation of the object.
   14417             : 
   14418             :     If the object is str or bytes, then allow it to pass through with
   14419             :     an incremented refcount. If the object defines __fspath__(), then
   14420             :     return the result of that method. All other types raise a TypeError.
   14421             : */
   14422             : PyObject *
   14423     6097820 : PyOS_FSPath(PyObject *path)
   14424             : {
   14425             :     /* For error message reasons, this function is manually inlined in
   14426             :        path_converter(). */
   14427     6097820 :     PyObject *func = NULL;
   14428     6097820 :     PyObject *path_repr = NULL;
   14429             : 
   14430     6097820 :     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
   14431     6072390 :         Py_INCREF(path);
   14432     6072390 :         return path;
   14433             :     }
   14434             : 
   14435       25427 :     func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
   14436       25427 :     if (NULL == func) {
   14437          90 :         return PyErr_Format(PyExc_TypeError,
   14438             :                             "expected str, bytes or os.PathLike object, "
   14439             :                             "not %.200s",
   14440             :                             _PyType_Name(Py_TYPE(path)));
   14441             :     }
   14442             : 
   14443       25337 :     path_repr = _PyObject_CallNoArgs(func);
   14444       25337 :     Py_DECREF(func);
   14445       25337 :     if (NULL == path_repr) {
   14446           4 :         return NULL;
   14447             :     }
   14448             : 
   14449       25333 :     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
   14450           5 :         PyErr_Format(PyExc_TypeError,
   14451             :                      "expected %.200s.__fspath__() to return str or bytes, "
   14452             :                      "not %.200s", _PyType_Name(Py_TYPE(path)),
   14453             :                      _PyType_Name(Py_TYPE(path_repr)));
   14454           5 :         Py_DECREF(path_repr);
   14455           5 :         return NULL;
   14456             :     }
   14457             : 
   14458       25328 :     return path_repr;
   14459             : }
   14460             : 
   14461             : /*[clinic input]
   14462             : os.fspath
   14463             : 
   14464             :     path: object
   14465             : 
   14466             : Return the file system path representation of the object.
   14467             : 
   14468             : If the object is str or bytes, then allow it to pass through as-is. If the
   14469             : object defines __fspath__(), then return the result of that method. All other
   14470             : types raise a TypeError.
   14471             : [clinic start generated code]*/
   14472             : 
   14473             : static PyObject *
   14474     3622600 : os_fspath_impl(PyObject *module, PyObject *path)
   14475             : /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
   14476             : {
   14477     3622600 :     return PyOS_FSPath(path);
   14478             : }
   14479             : 
   14480             : #ifdef HAVE_GETRANDOM_SYSCALL
   14481             : /*[clinic input]
   14482             : os.getrandom
   14483             : 
   14484             :     size: Py_ssize_t
   14485             :     flags: int=0
   14486             : 
   14487             : Obtain a series of random bytes.
   14488             : [clinic start generated code]*/
   14489             : 
   14490             : static PyObject *
   14491           6 : os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
   14492             : /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
   14493             : {
   14494             :     PyObject *bytes;
   14495             :     Py_ssize_t n;
   14496             : 
   14497           6 :     if (size < 0) {
   14498           0 :         errno = EINVAL;
   14499           0 :         return posix_error();
   14500             :     }
   14501             : 
   14502           6 :     bytes = PyBytes_FromStringAndSize(NULL, size);
   14503           6 :     if (bytes == NULL) {
   14504           0 :         PyErr_NoMemory();
   14505           0 :         return NULL;
   14506             :     }
   14507             : 
   14508             :     while (1) {
   14509           6 :         n = syscall(SYS_getrandom,
   14510             :                     PyBytes_AS_STRING(bytes),
   14511             :                     PyBytes_GET_SIZE(bytes),
   14512             :                     flags);
   14513           6 :         if (n < 0 && errno == EINTR) {
   14514           0 :             if (PyErr_CheckSignals() < 0) {
   14515           0 :                 goto error;
   14516             :             }
   14517             : 
   14518             :             /* getrandom() was interrupted by a signal: retry */
   14519           0 :             continue;
   14520             :         }
   14521           6 :         break;
   14522             :     }
   14523             : 
   14524           6 :     if (n < 0) {
   14525           0 :         PyErr_SetFromErrno(PyExc_OSError);
   14526           0 :         goto error;
   14527             :     }
   14528             : 
   14529           6 :     if (n != size) {
   14530           0 :         _PyBytes_Resize(&bytes, n);
   14531             :     }
   14532             : 
   14533           6 :     return bytes;
   14534             : 
   14535           0 : error:
   14536           0 :     Py_DECREF(bytes);
   14537           0 :     return NULL;
   14538             : }
   14539             : #endif   /* HAVE_GETRANDOM_SYSCALL */
   14540             : 
   14541             : #ifdef MS_WINDOWS
   14542             : /* bpo-36085: Helper functions for managing DLL search directories
   14543             :  * on win32
   14544             :  */
   14545             : 
   14546             : typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
   14547             : typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
   14548             : 
   14549             : /*[clinic input]
   14550             : os._add_dll_directory
   14551             : 
   14552             :     path: path_t
   14553             : 
   14554             : Add a path to the DLL search path.
   14555             : 
   14556             : This search path is used when resolving dependencies for imported
   14557             : extension modules (the module itself is resolved through sys.path),
   14558             : and also by ctypes.
   14559             : 
   14560             : Returns an opaque value that may be passed to os.remove_dll_directory
   14561             : to remove this directory from the search path.
   14562             : [clinic start generated code]*/
   14563             : 
   14564             : static PyObject *
   14565             : os__add_dll_directory_impl(PyObject *module, path_t *path)
   14566             : /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
   14567             : {
   14568             :     HMODULE hKernel32;
   14569             :     PAddDllDirectory AddDllDirectory;
   14570             :     DLL_DIRECTORY_COOKIE cookie = 0;
   14571             :     DWORD err = 0;
   14572             : 
   14573             :     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
   14574             :         return NULL;
   14575             :     }
   14576             : 
   14577             :     /* For Windows 7, we have to load this. As this will be a fairly
   14578             :        infrequent operation, just do it each time. Kernel32 is always
   14579             :        loaded. */
   14580             :     Py_BEGIN_ALLOW_THREADS
   14581             :     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
   14582             :         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
   14583             :             hKernel32, "AddDllDirectory")) ||
   14584             :         !(cookie = (*AddDllDirectory)(path->wide))) {
   14585             :         err = GetLastError();
   14586             :     }
   14587             :     Py_END_ALLOW_THREADS
   14588             : 
   14589             :     if (err) {
   14590             :         return win32_error_object_err("add_dll_directory",
   14591             :                                       path->object, err);
   14592             :     }
   14593             : 
   14594             :     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
   14595             : }
   14596             : 
   14597             : /*[clinic input]
   14598             : os._remove_dll_directory
   14599             : 
   14600             :     cookie: object
   14601             : 
   14602             : Removes a path from the DLL search path.
   14603             : 
   14604             : The parameter is an opaque value that was returned from
   14605             : os.add_dll_directory. You can only remove directories that you added
   14606             : yourself.
   14607             : [clinic start generated code]*/
   14608             : 
   14609             : static PyObject *
   14610             : os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
   14611             : /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
   14612             : {
   14613             :     HMODULE hKernel32;
   14614             :     PRemoveDllDirectory RemoveDllDirectory;
   14615             :     DLL_DIRECTORY_COOKIE cookieValue;
   14616             :     DWORD err = 0;
   14617             : 
   14618             :     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
   14619             :         PyErr_SetString(PyExc_TypeError,
   14620             :             "Provided cookie was not returned from os.add_dll_directory");
   14621             :         return NULL;
   14622             :     }
   14623             : 
   14624             :     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
   14625             :         cookie, "DLL directory cookie");
   14626             : 
   14627             :     /* For Windows 7, we have to load this. As this will be a fairly
   14628             :        infrequent operation, just do it each time. Kernel32 is always
   14629             :        loaded. */
   14630             :     Py_BEGIN_ALLOW_THREADS
   14631             :     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
   14632             :         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
   14633             :             hKernel32, "RemoveDllDirectory")) ||
   14634             :         !(*RemoveDllDirectory)(cookieValue)) {
   14635             :         err = GetLastError();
   14636             :     }
   14637             :     Py_END_ALLOW_THREADS
   14638             : 
   14639             :     if (err) {
   14640             :         return win32_error_object_err("remove_dll_directory",
   14641             :                                       NULL, err);
   14642             :     }
   14643             : 
   14644             :     if (PyCapsule_SetName(cookie, NULL)) {
   14645             :         return NULL;
   14646             :     }
   14647             : 
   14648             :     Py_RETURN_NONE;
   14649             : }
   14650             : 
   14651             : #endif
   14652             : 
   14653             : 
   14654             : /* Only check if WIFEXITED is available: expect that it comes
   14655             :    with WEXITSTATUS, WIFSIGNALED, etc.
   14656             : 
   14657             :    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
   14658             :    subprocess can safely call it during late Python finalization without
   14659             :    risking that used os attributes were set to None by finalize_modules(). */
   14660             : #if defined(WIFEXITED) || defined(MS_WINDOWS)
   14661             : /*[clinic input]
   14662             : os.waitstatus_to_exitcode
   14663             : 
   14664             :     status as status_obj: object
   14665             : 
   14666             : Convert a wait status to an exit code.
   14667             : 
   14668             : On Unix:
   14669             : 
   14670             : * If WIFEXITED(status) is true, return WEXITSTATUS(status).
   14671             : * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
   14672             : * Otherwise, raise a ValueError.
   14673             : 
   14674             : On Windows, return status shifted right by 8 bits.
   14675             : 
   14676             : On Unix, if the process is being traced or if waitpid() was called with
   14677             : WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
   14678             : This function must not be called if WIFSTOPPED(status) is true.
   14679             : [clinic start generated code]*/
   14680             : 
   14681             : static PyObject *
   14682        7294 : os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
   14683             : /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
   14684             : {
   14685             : #ifndef MS_WINDOWS
   14686        7294 :     int status = _PyLong_AsInt(status_obj);
   14687        7294 :     if (status == -1 && PyErr_Occurred()) {
   14688           1 :         return NULL;
   14689             :     }
   14690             : 
   14691             :     WAIT_TYPE wait_status;
   14692        7293 :     WAIT_STATUS_INT(wait_status) = status;
   14693             :     int exitcode;
   14694        7293 :     if (WIFEXITED(wait_status)) {
   14695        6774 :         exitcode = WEXITSTATUS(wait_status);
   14696             :         /* Sanity check to provide warranty on the function behavior.
   14697             :            It should not occur in practice */
   14698        6774 :         if (exitcode < 0) {
   14699           0 :             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
   14700           0 :             return NULL;
   14701             :         }
   14702             :     }
   14703         519 :     else if (WIFSIGNALED(wait_status)) {
   14704         519 :         int signum = WTERMSIG(wait_status);
   14705             :         /* Sanity check to provide warranty on the function behavior.
   14706             :            It should not occurs in practice */
   14707         519 :         if (signum <= 0) {
   14708           0 :             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
   14709           0 :             return NULL;
   14710             :         }
   14711         519 :         exitcode = -signum;
   14712           0 :     } else if (WIFSTOPPED(wait_status)) {
   14713             :         /* Status only received if the process is being traced
   14714             :            or if waitpid() was called with WUNTRACED option. */
   14715           0 :         int signum = WSTOPSIG(wait_status);
   14716           0 :         PyErr_Format(PyExc_ValueError,
   14717             :                      "process stopped by delivery of signal %i",
   14718             :                      signum);
   14719           0 :         return NULL;
   14720             :     }
   14721             :     else {
   14722           0 :         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
   14723           0 :         return NULL;
   14724             :     }
   14725        7293 :     return PyLong_FromLong(exitcode);
   14726             : #else
   14727             :     /* Windows implementation: see os.waitpid() implementation
   14728             :        which uses _cwait(). */
   14729             :     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
   14730             :     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
   14731             :         return NULL;
   14732             :     }
   14733             : 
   14734             :     unsigned long long exitcode = (status >> 8);
   14735             :     /* ExitProcess() accepts an UINT type:
   14736             :        reject exit code which doesn't fit in an UINT */
   14737             :     if (exitcode > UINT_MAX) {
   14738             :         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
   14739             :         return NULL;
   14740             :     }
   14741             :     return PyLong_FromUnsignedLong((unsigned long)exitcode);
   14742             : #endif
   14743             : }
   14744             : #endif
   14745             : 
   14746             : 
   14747             : static PyMethodDef posix_methods[] = {
   14748             : 
   14749             :     OS_STAT_METHODDEF
   14750             :     OS_ACCESS_METHODDEF
   14751             :     OS_TTYNAME_METHODDEF
   14752             :     OS_CHDIR_METHODDEF
   14753             :     OS_CHFLAGS_METHODDEF
   14754             :     OS_CHMOD_METHODDEF
   14755             :     OS_FCHMOD_METHODDEF
   14756             :     OS_LCHMOD_METHODDEF
   14757             :     OS_CHOWN_METHODDEF
   14758             :     OS_FCHOWN_METHODDEF
   14759             :     OS_LCHOWN_METHODDEF
   14760             :     OS_LCHFLAGS_METHODDEF
   14761             :     OS_CHROOT_METHODDEF
   14762             :     OS_CTERMID_METHODDEF
   14763             :     OS_GETCWD_METHODDEF
   14764             :     OS_GETCWDB_METHODDEF
   14765             :     OS_LINK_METHODDEF
   14766             :     OS_LISTDIR_METHODDEF
   14767             :     OS_LSTAT_METHODDEF
   14768             :     OS_MKDIR_METHODDEF
   14769             :     OS_NICE_METHODDEF
   14770             :     OS_GETPRIORITY_METHODDEF
   14771             :     OS_SETPRIORITY_METHODDEF
   14772             :     OS_POSIX_SPAWN_METHODDEF
   14773             :     OS_POSIX_SPAWNP_METHODDEF
   14774             :     OS_READLINK_METHODDEF
   14775             :     OS_COPY_FILE_RANGE_METHODDEF
   14776             :     OS_SPLICE_METHODDEF
   14777             :     OS_RENAME_METHODDEF
   14778             :     OS_REPLACE_METHODDEF
   14779             :     OS_RMDIR_METHODDEF
   14780             :     OS_SYMLINK_METHODDEF
   14781             :     OS_SYSTEM_METHODDEF
   14782             :     OS_UMASK_METHODDEF
   14783             :     OS_UNAME_METHODDEF
   14784             :     OS_UNLINK_METHODDEF
   14785             :     OS_REMOVE_METHODDEF
   14786             :     OS_UTIME_METHODDEF
   14787             :     OS_TIMES_METHODDEF
   14788             :     OS__EXIT_METHODDEF
   14789             :     OS__FCOPYFILE_METHODDEF
   14790             :     OS_EXECV_METHODDEF
   14791             :     OS_EXECVE_METHODDEF
   14792             :     OS_SPAWNV_METHODDEF
   14793             :     OS_SPAWNVE_METHODDEF
   14794             :     OS_FORK1_METHODDEF
   14795             :     OS_FORK_METHODDEF
   14796             :     OS_REGISTER_AT_FORK_METHODDEF
   14797             :     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
   14798             :     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
   14799             :     OS_SCHED_GETPARAM_METHODDEF
   14800             :     OS_SCHED_GETSCHEDULER_METHODDEF
   14801             :     OS_SCHED_RR_GET_INTERVAL_METHODDEF
   14802             :     OS_SCHED_SETPARAM_METHODDEF
   14803             :     OS_SCHED_SETSCHEDULER_METHODDEF
   14804             :     OS_SCHED_YIELD_METHODDEF
   14805             :     OS_SCHED_SETAFFINITY_METHODDEF
   14806             :     OS_SCHED_GETAFFINITY_METHODDEF
   14807             :     OS_OPENPTY_METHODDEF
   14808             :     OS_LOGIN_TTY_METHODDEF
   14809             :     OS_FORKPTY_METHODDEF
   14810             :     OS_GETEGID_METHODDEF
   14811             :     OS_GETEUID_METHODDEF
   14812             :     OS_GETGID_METHODDEF
   14813             :     OS_GETGROUPLIST_METHODDEF
   14814             :     OS_GETGROUPS_METHODDEF
   14815             :     OS_GETPID_METHODDEF
   14816             :     OS_GETPGRP_METHODDEF
   14817             :     OS_GETPPID_METHODDEF
   14818             :     OS_GETUID_METHODDEF
   14819             :     OS_GETLOGIN_METHODDEF
   14820             :     OS_KILL_METHODDEF
   14821             :     OS_KILLPG_METHODDEF
   14822             :     OS_PLOCK_METHODDEF
   14823             :     OS_STARTFILE_METHODDEF
   14824             :     OS_SETUID_METHODDEF
   14825             :     OS_SETEUID_METHODDEF
   14826             :     OS_SETREUID_METHODDEF
   14827             :     OS_SETGID_METHODDEF
   14828             :     OS_SETEGID_METHODDEF
   14829             :     OS_SETREGID_METHODDEF
   14830             :     OS_SETGROUPS_METHODDEF
   14831             :     OS_INITGROUPS_METHODDEF
   14832             :     OS_GETPGID_METHODDEF
   14833             :     OS_SETPGRP_METHODDEF
   14834             :     OS_WAIT_METHODDEF
   14835             :     OS_WAIT3_METHODDEF
   14836             :     OS_WAIT4_METHODDEF
   14837             :     OS_WAITID_METHODDEF
   14838             :     OS_WAITPID_METHODDEF
   14839             :     OS_PIDFD_OPEN_METHODDEF
   14840             :     OS_GETSID_METHODDEF
   14841             :     OS_SETSID_METHODDEF
   14842             :     OS_SETPGID_METHODDEF
   14843             :     OS_TCGETPGRP_METHODDEF
   14844             :     OS_TCSETPGRP_METHODDEF
   14845             :     OS_OPEN_METHODDEF
   14846             :     OS_CLOSE_METHODDEF
   14847             :     OS_CLOSERANGE_METHODDEF
   14848             :     OS_DEVICE_ENCODING_METHODDEF
   14849             :     OS_DUP_METHODDEF
   14850             :     OS_DUP2_METHODDEF
   14851             :     OS_LOCKF_METHODDEF
   14852             :     OS_LSEEK_METHODDEF
   14853             :     OS_READ_METHODDEF
   14854             :     OS_READV_METHODDEF
   14855             :     OS_PREAD_METHODDEF
   14856             :     OS_PREADV_METHODDEF
   14857             :     OS_WRITE_METHODDEF
   14858             :     OS_WRITEV_METHODDEF
   14859             :     OS_PWRITE_METHODDEF
   14860             :     OS_PWRITEV_METHODDEF
   14861             :     OS_SENDFILE_METHODDEF
   14862             :     OS_FSTAT_METHODDEF
   14863             :     OS_ISATTY_METHODDEF
   14864             :     OS_PIPE_METHODDEF
   14865             :     OS_PIPE2_METHODDEF
   14866             :     OS_MKFIFO_METHODDEF
   14867             :     OS_MKNOD_METHODDEF
   14868             :     OS_MAJOR_METHODDEF
   14869             :     OS_MINOR_METHODDEF
   14870             :     OS_MAKEDEV_METHODDEF
   14871             :     OS_FTRUNCATE_METHODDEF
   14872             :     OS_TRUNCATE_METHODDEF
   14873             :     OS_POSIX_FALLOCATE_METHODDEF
   14874             :     OS_POSIX_FADVISE_METHODDEF
   14875             :     OS_PUTENV_METHODDEF
   14876             :     OS_UNSETENV_METHODDEF
   14877             :     OS_STRERROR_METHODDEF
   14878             :     OS_FCHDIR_METHODDEF
   14879             :     OS_FSYNC_METHODDEF
   14880             :     OS_SYNC_METHODDEF
   14881             :     OS_FDATASYNC_METHODDEF
   14882             :     OS_WCOREDUMP_METHODDEF
   14883             :     OS_WIFCONTINUED_METHODDEF
   14884             :     OS_WIFSTOPPED_METHODDEF
   14885             :     OS_WIFSIGNALED_METHODDEF
   14886             :     OS_WIFEXITED_METHODDEF
   14887             :     OS_WEXITSTATUS_METHODDEF
   14888             :     OS_WTERMSIG_METHODDEF
   14889             :     OS_WSTOPSIG_METHODDEF
   14890             :     OS_FSTATVFS_METHODDEF
   14891             :     OS_STATVFS_METHODDEF
   14892             :     OS_CONFSTR_METHODDEF
   14893             :     OS_SYSCONF_METHODDEF
   14894             :     OS_FPATHCONF_METHODDEF
   14895             :     OS_PATHCONF_METHODDEF
   14896             :     OS_ABORT_METHODDEF
   14897             :     OS__GETFULLPATHNAME_METHODDEF
   14898             :     OS__GETDISKUSAGE_METHODDEF
   14899             :     OS__GETFINALPATHNAME_METHODDEF
   14900             :     OS__GETVOLUMEPATHNAME_METHODDEF
   14901             :     OS__PATH_SPLITROOT_METHODDEF
   14902             :     OS__PATH_NORMPATH_METHODDEF
   14903             :     OS_GETLOADAVG_METHODDEF
   14904             :     OS_URANDOM_METHODDEF
   14905             :     OS_SETRESUID_METHODDEF
   14906             :     OS_SETRESGID_METHODDEF
   14907             :     OS_GETRESUID_METHODDEF
   14908             :     OS_GETRESGID_METHODDEF
   14909             : 
   14910             :     OS_GETXATTR_METHODDEF
   14911             :     OS_SETXATTR_METHODDEF
   14912             :     OS_REMOVEXATTR_METHODDEF
   14913             :     OS_LISTXATTR_METHODDEF
   14914             : 
   14915             :     OS_GET_TERMINAL_SIZE_METHODDEF
   14916             :     OS_CPU_COUNT_METHODDEF
   14917             :     OS_GET_INHERITABLE_METHODDEF
   14918             :     OS_SET_INHERITABLE_METHODDEF
   14919             :     OS_GET_HANDLE_INHERITABLE_METHODDEF
   14920             :     OS_SET_HANDLE_INHERITABLE_METHODDEF
   14921             :     OS_GET_BLOCKING_METHODDEF
   14922             :     OS_SET_BLOCKING_METHODDEF
   14923             :     OS_SCANDIR_METHODDEF
   14924             :     OS_FSPATH_METHODDEF
   14925             :     OS_GETRANDOM_METHODDEF
   14926             :     OS_MEMFD_CREATE_METHODDEF
   14927             :     OS_EVENTFD_METHODDEF
   14928             :     OS_EVENTFD_READ_METHODDEF
   14929             :     OS_EVENTFD_WRITE_METHODDEF
   14930             :     OS__ADD_DLL_DIRECTORY_METHODDEF
   14931             :     OS__REMOVE_DLL_DIRECTORY_METHODDEF
   14932             :     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
   14933             :     {NULL,              NULL}            /* Sentinel */
   14934             : };
   14935             : 
   14936             : static int
   14937        3130 : all_ins(PyObject *m)
   14938             : {
   14939             : #ifdef F_OK
   14940        3130 :     if (PyModule_AddIntMacro(m, F_OK)) return -1;
   14941             : #endif
   14942             : #ifdef R_OK
   14943        3130 :     if (PyModule_AddIntMacro(m, R_OK)) return -1;
   14944             : #endif
   14945             : #ifdef W_OK
   14946        3130 :     if (PyModule_AddIntMacro(m, W_OK)) return -1;
   14947             : #endif
   14948             : #ifdef X_OK
   14949        3130 :     if (PyModule_AddIntMacro(m, X_OK)) return -1;
   14950             : #endif
   14951             : #ifdef NGROUPS_MAX
   14952        3130 :     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
   14953             : #endif
   14954             : #ifdef TMP_MAX
   14955        3130 :     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
   14956             : #endif
   14957             : #ifdef WCONTINUED
   14958        3130 :     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
   14959             : #endif
   14960             : #ifdef WNOHANG
   14961        3130 :     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
   14962             : #endif
   14963             : #ifdef WUNTRACED
   14964        3130 :     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
   14965             : #endif
   14966             : #ifdef O_RDONLY
   14967        3130 :     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
   14968             : #endif
   14969             : #ifdef O_WRONLY
   14970        3130 :     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
   14971             : #endif
   14972             : #ifdef O_RDWR
   14973        3130 :     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
   14974             : #endif
   14975             : #ifdef O_NDELAY
   14976        3130 :     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
   14977             : #endif
   14978             : #ifdef O_NONBLOCK
   14979        3130 :     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
   14980             : #endif
   14981             : #ifdef O_APPEND
   14982        3130 :     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
   14983             : #endif
   14984             : #ifdef O_DSYNC
   14985        3130 :     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
   14986             : #endif
   14987             : #ifdef O_RSYNC
   14988        3130 :     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
   14989             : #endif
   14990             : #ifdef O_SYNC
   14991        3130 :     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
   14992             : #endif
   14993             : #ifdef O_NOCTTY
   14994        3130 :     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
   14995             : #endif
   14996             : #ifdef O_CREAT
   14997        3130 :     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
   14998             : #endif
   14999             : #ifdef O_EXCL
   15000        3130 :     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
   15001             : #endif
   15002             : #ifdef O_TRUNC
   15003        3130 :     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
   15004             : #endif
   15005             : #ifdef O_BINARY
   15006             :     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
   15007             : #endif
   15008             : #ifdef O_TEXT
   15009             :     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
   15010             : #endif
   15011             : #ifdef O_XATTR
   15012             :     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
   15013             : #endif
   15014             : #ifdef O_LARGEFILE
   15015        3130 :     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
   15016             : #endif
   15017             : #ifndef __GNU__
   15018             : #ifdef O_SHLOCK
   15019             :     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
   15020             : #endif
   15021             : #ifdef O_EXLOCK
   15022             :     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
   15023             : #endif
   15024             : #endif
   15025             : #ifdef O_EXEC
   15026             :     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
   15027             : #endif
   15028             : #ifdef O_SEARCH
   15029             :     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
   15030             : #endif
   15031             : #ifdef O_PATH
   15032        3130 :     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
   15033             : #endif
   15034             : #ifdef O_TTY_INIT
   15035             :     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
   15036             : #endif
   15037             : #ifdef O_TMPFILE
   15038        3130 :     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
   15039             : #endif
   15040             : #ifdef PRIO_PROCESS
   15041        3130 :     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
   15042             : #endif
   15043             : #ifdef PRIO_PGRP
   15044        3130 :     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
   15045             : #endif
   15046             : #ifdef PRIO_USER
   15047        3130 :     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
   15048             : #endif
   15049             : #ifdef O_CLOEXEC
   15050        3130 :     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
   15051             : #endif
   15052             : #ifdef O_ACCMODE
   15053        3130 :     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
   15054             : #endif
   15055             : #ifdef O_EVTONLY
   15056             :     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
   15057             : #endif
   15058             : #ifdef O_FSYNC
   15059        3130 :     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
   15060             : #endif
   15061             : #ifdef O_SYMLINK
   15062             :     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
   15063             : #endif
   15064             : 
   15065             : #ifdef SEEK_HOLE
   15066        3130 :     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
   15067             : #endif
   15068             : #ifdef SEEK_DATA
   15069        3130 :     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
   15070             : #endif
   15071             : 
   15072             : /* MS Windows */
   15073             : #ifdef O_NOINHERIT
   15074             :     /* Don't inherit in child processes. */
   15075             :     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
   15076             : #endif
   15077             : #ifdef _O_SHORT_LIVED
   15078             :     /* Optimize for short life (keep in memory). */
   15079             :     /* MS forgot to define this one with a non-underscore form too. */
   15080             :     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
   15081             : #endif
   15082             : #ifdef O_TEMPORARY
   15083             :     /* Automatically delete when last handle is closed. */
   15084             :     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
   15085             : #endif
   15086             : #ifdef O_RANDOM
   15087             :     /* Optimize for random access. */
   15088             :     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
   15089             : #endif
   15090             : #ifdef O_SEQUENTIAL
   15091             :     /* Optimize for sequential access. */
   15092             :     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
   15093             : #endif
   15094             : 
   15095             : /* GNU extensions. */
   15096             : #ifdef O_ASYNC
   15097             :     /* Send a SIGIO signal whenever input or output
   15098             :        becomes available on file descriptor */
   15099        3130 :     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
   15100             : #endif
   15101             : #ifdef O_DIRECT
   15102             :     /* Direct disk access. */
   15103        3130 :     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
   15104             : #endif
   15105             : #ifdef O_DIRECTORY
   15106             :     /* Must be a directory.      */
   15107        3130 :     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
   15108             : #endif
   15109             : #ifdef O_NOFOLLOW
   15110             :     /* Do not follow links.      */
   15111        3130 :     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
   15112             : #endif
   15113             : #ifdef O_NOFOLLOW_ANY
   15114             :     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
   15115             : #endif
   15116             : #ifdef O_NOLINKS
   15117             :     /* Fails if link count of the named file is greater than 1 */
   15118             :     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
   15119             : #endif
   15120             : #ifdef O_NOATIME
   15121             :     /* Do not update the access time. */
   15122        3130 :     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
   15123             : #endif
   15124             : 
   15125             :     /* These come from sysexits.h */
   15126             : #ifdef EX_OK
   15127        3130 :     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
   15128             : #endif /* EX_OK */
   15129             : #ifdef EX_USAGE
   15130        3130 :     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
   15131             : #endif /* EX_USAGE */
   15132             : #ifdef EX_DATAERR
   15133        3130 :     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
   15134             : #endif /* EX_DATAERR */
   15135             : #ifdef EX_NOINPUT
   15136        3130 :     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
   15137             : #endif /* EX_NOINPUT */
   15138             : #ifdef EX_NOUSER
   15139        3130 :     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
   15140             : #endif /* EX_NOUSER */
   15141             : #ifdef EX_NOHOST
   15142        3130 :     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
   15143             : #endif /* EX_NOHOST */
   15144             : #ifdef EX_UNAVAILABLE
   15145        3130 :     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
   15146             : #endif /* EX_UNAVAILABLE */
   15147             : #ifdef EX_SOFTWARE
   15148        3130 :     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
   15149             : #endif /* EX_SOFTWARE */
   15150             : #ifdef EX_OSERR
   15151        3130 :     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
   15152             : #endif /* EX_OSERR */
   15153             : #ifdef EX_OSFILE
   15154        3130 :     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
   15155             : #endif /* EX_OSFILE */
   15156             : #ifdef EX_CANTCREAT
   15157        3130 :     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
   15158             : #endif /* EX_CANTCREAT */
   15159             : #ifdef EX_IOERR
   15160        3130 :     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
   15161             : #endif /* EX_IOERR */
   15162             : #ifdef EX_TEMPFAIL
   15163        3130 :     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
   15164             : #endif /* EX_TEMPFAIL */
   15165             : #ifdef EX_PROTOCOL
   15166        3130 :     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
   15167             : #endif /* EX_PROTOCOL */
   15168             : #ifdef EX_NOPERM
   15169        3130 :     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
   15170             : #endif /* EX_NOPERM */
   15171             : #ifdef EX_CONFIG
   15172        3130 :     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
   15173             : #endif /* EX_CONFIG */
   15174             : #ifdef EX_NOTFOUND
   15175             :     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
   15176             : #endif /* EX_NOTFOUND */
   15177             : 
   15178             :     /* statvfs */
   15179             : #ifdef ST_RDONLY
   15180        3130 :     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
   15181             : #endif /* ST_RDONLY */
   15182             : #ifdef ST_NOSUID
   15183        3130 :     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
   15184             : #endif /* ST_NOSUID */
   15185             : 
   15186             :        /* GNU extensions */
   15187             : #ifdef ST_NODEV
   15188        3130 :     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
   15189             : #endif /* ST_NODEV */
   15190             : #ifdef ST_NOEXEC
   15191        3130 :     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
   15192             : #endif /* ST_NOEXEC */
   15193             : #ifdef ST_SYNCHRONOUS
   15194        3130 :     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
   15195             : #endif /* ST_SYNCHRONOUS */
   15196             : #ifdef ST_MANDLOCK
   15197        3130 :     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
   15198             : #endif /* ST_MANDLOCK */
   15199             : #ifdef ST_WRITE
   15200        3130 :     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
   15201             : #endif /* ST_WRITE */
   15202             : #ifdef ST_APPEND
   15203        3130 :     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
   15204             : #endif /* ST_APPEND */
   15205             : #ifdef ST_NOATIME
   15206        3130 :     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
   15207             : #endif /* ST_NOATIME */
   15208             : #ifdef ST_NODIRATIME
   15209        3130 :     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
   15210             : #endif /* ST_NODIRATIME */
   15211             : #ifdef ST_RELATIME
   15212        3130 :     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
   15213             : #endif /* ST_RELATIME */
   15214             : 
   15215             :     /* FreeBSD sendfile() constants */
   15216             : #ifdef SF_NODISKIO
   15217             :     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
   15218             : #endif
   15219             :     /* is obsolete since the 11.x release */
   15220             : #ifdef SF_MNOWAIT
   15221             :     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
   15222             : #endif
   15223             : #ifdef SF_SYNC
   15224             :     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
   15225             : #endif
   15226             : #ifdef SF_NOCACHE
   15227             :     if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
   15228             : #endif
   15229             : 
   15230             :     /* constants for posix_fadvise */
   15231             : #ifdef POSIX_FADV_NORMAL
   15232        3130 :     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
   15233             : #endif
   15234             : #ifdef POSIX_FADV_SEQUENTIAL
   15235        3130 :     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
   15236             : #endif
   15237             : #ifdef POSIX_FADV_RANDOM
   15238        3130 :     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
   15239             : #endif
   15240             : #ifdef POSIX_FADV_NOREUSE
   15241        3130 :     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
   15242             : #endif
   15243             : #ifdef POSIX_FADV_WILLNEED
   15244        3130 :     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
   15245             : #endif
   15246             : #ifdef POSIX_FADV_DONTNEED
   15247        3130 :     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
   15248             : #endif
   15249             : 
   15250             :     /* constants for waitid */
   15251             : #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
   15252        3130 :     if (PyModule_AddIntMacro(m, P_PID)) return -1;
   15253        3130 :     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
   15254        3130 :     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
   15255             : #ifdef P_PIDFD
   15256        3130 :     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
   15257             : #endif
   15258             : #ifdef PIDFD_NONBLOCK
   15259             :     if (PyModule_AddIntMacro(m, PIDFD_NONBLOCK)) return -1;
   15260             : #endif
   15261             : #endif
   15262             : #ifdef WEXITED
   15263        3130 :     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
   15264             : #endif
   15265             : #ifdef WNOWAIT
   15266        3130 :     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
   15267             : #endif
   15268             : #ifdef WSTOPPED
   15269        3130 :     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
   15270             : #endif
   15271             : #ifdef CLD_EXITED
   15272        3130 :     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
   15273             : #endif
   15274             : #ifdef CLD_KILLED
   15275        3130 :     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
   15276             : #endif
   15277             : #ifdef CLD_DUMPED
   15278        3130 :     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
   15279             : #endif
   15280             : #ifdef CLD_TRAPPED
   15281        3130 :     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
   15282             : #endif
   15283             : #ifdef CLD_STOPPED
   15284        3130 :     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
   15285             : #endif
   15286             : #ifdef CLD_CONTINUED
   15287        3130 :     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
   15288             : #endif
   15289             : 
   15290             :     /* constants for lockf */
   15291             : #ifdef F_LOCK
   15292        3130 :     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
   15293             : #endif
   15294             : #ifdef F_TLOCK
   15295        3130 :     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
   15296             : #endif
   15297             : #ifdef F_ULOCK
   15298        3130 :     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
   15299             : #endif
   15300             : #ifdef F_TEST
   15301        3130 :     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
   15302             : #endif
   15303             : 
   15304             : #ifdef RWF_DSYNC
   15305        3130 :     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
   15306             : #endif
   15307             : #ifdef RWF_HIPRI
   15308        3130 :     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
   15309             : #endif
   15310             : #ifdef RWF_SYNC
   15311        3130 :     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
   15312             : #endif
   15313             : #ifdef RWF_NOWAIT
   15314        3130 :     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
   15315             : #endif
   15316             : #ifdef RWF_APPEND
   15317        3130 :     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
   15318             : #endif
   15319             : 
   15320             : /* constants for splice */
   15321             : #if defined(HAVE_SPLICE) && defined(__linux__)
   15322        3130 :     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
   15323        3130 :     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
   15324        3130 :     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
   15325             : #endif
   15326             : 
   15327             : /* constants for posix_spawn */
   15328             : #ifdef HAVE_POSIX_SPAWN
   15329        3130 :     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
   15330        3130 :     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
   15331        3130 :     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
   15332             : #endif
   15333             : 
   15334             : #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
   15335             :     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
   15336             :     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
   15337             :     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
   15338             : #endif
   15339             : #ifdef HAVE_SPAWNV
   15340             :     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
   15341             :     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
   15342             : #endif
   15343             : 
   15344             : #ifdef HAVE_SCHED_H
   15345             : #ifdef SCHED_OTHER
   15346        3130 :     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
   15347             : #endif
   15348             : #ifdef SCHED_FIFO
   15349        3130 :     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
   15350             : #endif
   15351             : #ifdef SCHED_RR
   15352        3130 :     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
   15353             : #endif
   15354             : #ifdef SCHED_SPORADIC
   15355             :     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
   15356             : #endif
   15357             : #ifdef SCHED_BATCH
   15358        3130 :     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
   15359             : #endif
   15360             : #ifdef SCHED_IDLE
   15361        3130 :     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
   15362             : #endif
   15363             : #ifdef SCHED_RESET_ON_FORK
   15364        3130 :     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
   15365             : #endif
   15366             : #ifdef SCHED_SYS
   15367             :     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
   15368             : #endif
   15369             : #ifdef SCHED_IA
   15370             :     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
   15371             : #endif
   15372             : #ifdef SCHED_FSS
   15373             :     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
   15374             : #endif
   15375             : #ifdef SCHED_FX
   15376             :     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
   15377             : #endif
   15378             : #endif
   15379             : 
   15380             : #ifdef USE_XATTRS
   15381        3130 :     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
   15382        3130 :     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
   15383        3130 :     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
   15384             : #endif
   15385             : 
   15386             : #if HAVE_DECL_RTLD_LAZY
   15387        3130 :     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
   15388             : #endif
   15389             : #if HAVE_DECL_RTLD_NOW
   15390        3130 :     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
   15391             : #endif
   15392             : #if HAVE_DECL_RTLD_GLOBAL
   15393        3130 :     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
   15394             : #endif
   15395             : #if HAVE_DECL_RTLD_LOCAL
   15396        3130 :     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
   15397             : #endif
   15398             : #if HAVE_DECL_RTLD_NODELETE
   15399        3130 :     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
   15400             : #endif
   15401             : #if HAVE_DECL_RTLD_NOLOAD
   15402        3130 :     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
   15403             : #endif
   15404             : #if HAVE_DECL_RTLD_DEEPBIND
   15405        3130 :     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
   15406             : #endif
   15407             : #if HAVE_DECL_RTLD_MEMBER
   15408             :     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
   15409             : #endif
   15410             : 
   15411             : #ifdef HAVE_GETRANDOM_SYSCALL
   15412        3130 :     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
   15413        3130 :     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
   15414             : #endif
   15415             : #ifdef HAVE_MEMFD_CREATE
   15416        3130 :     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
   15417        3130 :     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
   15418             : #ifdef MFD_HUGETLB
   15419        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
   15420             : #endif
   15421             : #ifdef MFD_HUGE_SHIFT
   15422        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
   15423             : #endif
   15424             : #ifdef MFD_HUGE_MASK
   15425        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
   15426             : #endif
   15427             : #ifdef MFD_HUGE_64KB
   15428        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
   15429             : #endif
   15430             : #ifdef MFD_HUGE_512KB
   15431        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
   15432             : #endif
   15433             : #ifdef MFD_HUGE_1MB
   15434        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
   15435             : #endif
   15436             : #ifdef MFD_HUGE_2MB
   15437        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
   15438             : #endif
   15439             : #ifdef MFD_HUGE_8MB
   15440        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
   15441             : #endif
   15442             : #ifdef MFD_HUGE_16MB
   15443        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
   15444             : #endif
   15445             : #ifdef MFD_HUGE_32MB
   15446        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
   15447             : #endif
   15448             : #ifdef MFD_HUGE_256MB
   15449        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
   15450             : #endif
   15451             : #ifdef MFD_HUGE_512MB
   15452        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
   15453             : #endif
   15454             : #ifdef MFD_HUGE_1GB
   15455        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
   15456             : #endif
   15457             : #ifdef MFD_HUGE_2GB
   15458        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
   15459             : #endif
   15460             : #ifdef MFD_HUGE_16GB
   15461        3130 :     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
   15462             : #endif
   15463             : #endif /* HAVE_MEMFD_CREATE */
   15464             : 
   15465             : #ifdef HAVE_EVENTFD
   15466        3130 :     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
   15467        3130 :     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
   15468        3130 :     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
   15469             : #endif
   15470             : 
   15471             : #if defined(__APPLE__)
   15472             :     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
   15473             :     if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
   15474             :     if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
   15475             :     if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
   15476             : #endif
   15477             : 
   15478             : #ifdef MS_WINDOWS
   15479             :     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
   15480             :     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
   15481             :     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
   15482             :     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
   15483             :     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
   15484             : #endif
   15485             : 
   15486        3130 :     return 0;
   15487             : }
   15488             : 
   15489             : 
   15490             : 
   15491             : #define PROBE(name, test) \
   15492             :    static int name(void)  \
   15493             :    {                      \
   15494             :       if (test) {        \
   15495             :           return 1;       \
   15496             :       } else {            \
   15497             :           return 0;       \
   15498             :       }                   \
   15499             :    }
   15500             : 
   15501             : #ifdef HAVE_FSTATAT
   15502        3130 : PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
   15503             : #endif
   15504             : 
   15505             : #ifdef HAVE_FACCESSAT
   15506        3130 : PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
   15507             : #endif
   15508             : 
   15509             : #ifdef HAVE_FCHMODAT
   15510        3130 : PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
   15511             : #endif
   15512             : 
   15513             : #ifdef HAVE_FCHOWNAT
   15514        3130 : PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
   15515             : #endif
   15516             : 
   15517             : #ifdef HAVE_LINKAT
   15518        3130 : PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
   15519             : #endif
   15520             : 
   15521             : #ifdef HAVE_FDOPENDIR
   15522        3130 : PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
   15523             : #endif
   15524             : 
   15525             : #ifdef HAVE_MKDIRAT
   15526        3130 : PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
   15527             : #endif
   15528             : 
   15529             : #ifdef HAVE_RENAMEAT
   15530        3130 : PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
   15531             : #endif
   15532             : 
   15533             : #ifdef HAVE_UNLINKAT
   15534        3130 : PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
   15535             : #endif
   15536             : 
   15537             : #ifdef HAVE_OPENAT
   15538        3130 : PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
   15539             : #endif
   15540             : 
   15541             : #ifdef HAVE_READLINKAT
   15542        3130 : PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
   15543             : #endif
   15544             : 
   15545             : #ifdef HAVE_SYMLINKAT
   15546        3130 : PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
   15547             : #endif
   15548             : 
   15549             : #ifdef HAVE_FUTIMENS
   15550        3130 : PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
   15551             : #endif
   15552             : 
   15553             : #ifdef HAVE_UTIMENSAT
   15554        3130 : PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
   15555             : #endif
   15556             : 
   15557             : 
   15558             : 
   15559             : 
   15560             : static const struct have_function {
   15561             :     const char * const label;
   15562             :     int (*probe)(void);
   15563             : } have_functions[] = {
   15564             : 
   15565             : #ifdef HAVE_EVENTFD
   15566             :     {"HAVE_EVENTFD", NULL},
   15567             : #endif
   15568             : 
   15569             : #ifdef HAVE_FACCESSAT
   15570             :     { "HAVE_FACCESSAT", probe_faccessat },
   15571             : #endif
   15572             : 
   15573             : #ifdef HAVE_FCHDIR
   15574             :     { "HAVE_FCHDIR", NULL },
   15575             : #endif
   15576             : 
   15577             : #ifdef HAVE_FCHMOD
   15578             :     { "HAVE_FCHMOD", NULL },
   15579             : #endif
   15580             : 
   15581             : #ifdef HAVE_FCHMODAT
   15582             :     { "HAVE_FCHMODAT", probe_fchmodat },
   15583             : #endif
   15584             : 
   15585             : #ifdef HAVE_FCHOWN
   15586             :     { "HAVE_FCHOWN", NULL },
   15587             : #endif
   15588             : 
   15589             : #ifdef HAVE_FCHOWNAT
   15590             :     { "HAVE_FCHOWNAT", probe_fchownat },
   15591             : #endif
   15592             : 
   15593             : #ifdef HAVE_FEXECVE
   15594             :     { "HAVE_FEXECVE", NULL },
   15595             : #endif
   15596             : 
   15597             : #ifdef HAVE_FDOPENDIR
   15598             :     { "HAVE_FDOPENDIR", probe_fdopendir },
   15599             : #endif
   15600             : 
   15601             : #ifdef HAVE_FPATHCONF
   15602             :     { "HAVE_FPATHCONF", NULL },
   15603             : #endif
   15604             : 
   15605             : #ifdef HAVE_FSTATAT
   15606             :     { "HAVE_FSTATAT", probe_fstatat },
   15607             : #endif
   15608             : 
   15609             : #ifdef HAVE_FSTATVFS
   15610             :     { "HAVE_FSTATVFS", NULL },
   15611             : #endif
   15612             : 
   15613             : #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
   15614             :     { "HAVE_FTRUNCATE", NULL },
   15615             : #endif
   15616             : 
   15617             : #ifdef HAVE_FUTIMENS
   15618             :     { "HAVE_FUTIMENS", probe_futimens },
   15619             : #endif
   15620             : 
   15621             : #ifdef HAVE_FUTIMES
   15622             :     { "HAVE_FUTIMES", NULL },
   15623             : #endif
   15624             : 
   15625             : #ifdef HAVE_FUTIMESAT
   15626             :     { "HAVE_FUTIMESAT", NULL },
   15627             : #endif
   15628             : 
   15629             : #ifdef HAVE_LINKAT
   15630             :     { "HAVE_LINKAT", probe_linkat },
   15631             : #endif
   15632             : 
   15633             : #ifdef HAVE_LCHFLAGS
   15634             :     { "HAVE_LCHFLAGS", NULL },
   15635             : #endif
   15636             : 
   15637             : #ifdef HAVE_LCHMOD
   15638             :     { "HAVE_LCHMOD", NULL },
   15639             : #endif
   15640             : 
   15641             : #ifdef HAVE_LCHOWN
   15642             :     { "HAVE_LCHOWN", NULL },
   15643             : #endif
   15644             : 
   15645             : #ifdef HAVE_LSTAT
   15646             :     { "HAVE_LSTAT", NULL },
   15647             : #endif
   15648             : 
   15649             : #ifdef HAVE_LUTIMES
   15650             :     { "HAVE_LUTIMES", NULL },
   15651             : #endif
   15652             : 
   15653             : #ifdef HAVE_MEMFD_CREATE
   15654             :     { "HAVE_MEMFD_CREATE", NULL },
   15655             : #endif
   15656             : 
   15657             : #ifdef HAVE_MKDIRAT
   15658             :     { "HAVE_MKDIRAT", probe_mkdirat },
   15659             : #endif
   15660             : 
   15661             : #ifdef HAVE_MKFIFOAT
   15662             :     { "HAVE_MKFIFOAT", NULL },
   15663             : #endif
   15664             : 
   15665             : #ifdef HAVE_MKNODAT
   15666             :     { "HAVE_MKNODAT", NULL },
   15667             : #endif
   15668             : 
   15669             : #ifdef HAVE_OPENAT
   15670             :     { "HAVE_OPENAT", probe_openat },
   15671             : #endif
   15672             : 
   15673             : #ifdef HAVE_READLINKAT
   15674             :     { "HAVE_READLINKAT", probe_readlinkat },
   15675             : #endif
   15676             : 
   15677             : #ifdef HAVE_RENAMEAT
   15678             :     { "HAVE_RENAMEAT", probe_renameat },
   15679             : #endif
   15680             : 
   15681             : #ifdef HAVE_SYMLINKAT
   15682             :     { "HAVE_SYMLINKAT", probe_symlinkat },
   15683             : #endif
   15684             : 
   15685             : #ifdef HAVE_UNLINKAT
   15686             :     { "HAVE_UNLINKAT", probe_unlinkat },
   15687             : #endif
   15688             : 
   15689             : #ifdef HAVE_UTIMENSAT
   15690             :     { "HAVE_UTIMENSAT", probe_utimensat },
   15691             : #endif
   15692             : 
   15693             : #ifdef MS_WINDOWS
   15694             :     { "MS_WINDOWS", NULL },
   15695             : #endif
   15696             : 
   15697             :     { NULL, NULL }
   15698             : };
   15699             : 
   15700             : 
   15701             : static int
   15702        3130 : posixmodule_exec(PyObject *m)
   15703             : {
   15704        3130 :     _posixstate *state = get_posix_state(m);
   15705             : 
   15706             : #if defined(HAVE_PWRITEV)
   15707             :     if (HAVE_PWRITEV_RUNTIME) {} else {
   15708             :         PyObject* dct = PyModule_GetDict(m);
   15709             : 
   15710             :         if (dct == NULL) {
   15711             :             return -1;
   15712             :         }
   15713             : 
   15714             :         if (PyDict_DelItemString(dct, "pwritev") == -1) {
   15715             :             PyErr_Clear();
   15716             :         }
   15717             :         if (PyDict_DelItemString(dct, "preadv") == -1) {
   15718             :             PyErr_Clear();
   15719             :         }
   15720             :     }
   15721             : #endif
   15722             : 
   15723             :     /* Initialize environ dictionary */
   15724        3130 :     PyObject *v = convertenviron();
   15725        3130 :     Py_XINCREF(v);
   15726        3130 :     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
   15727           0 :         return -1;
   15728        3130 :     Py_DECREF(v);
   15729             : 
   15730        3130 :     if (all_ins(m))
   15731           0 :         return -1;
   15732             : 
   15733        3130 :     if (setup_confname_tables(m))
   15734           0 :         return -1;
   15735             : 
   15736        3130 :     Py_INCREF(PyExc_OSError);
   15737        3130 :     PyModule_AddObject(m, "error", PyExc_OSError);
   15738             : 
   15739             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
   15740        3130 :     waitid_result_desc.name = MODNAME ".waitid_result";
   15741        3130 :     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
   15742        3130 :     if (WaitidResultType == NULL) {
   15743           0 :         return -1;
   15744             :     }
   15745        3130 :     Py_INCREF(WaitidResultType);
   15746        3130 :     PyModule_AddObject(m, "waitid_result", WaitidResultType);
   15747        3130 :     state->WaitidResultType = WaitidResultType;
   15748             : #endif
   15749             : 
   15750        3130 :     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
   15751        3130 :     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
   15752        3130 :     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
   15753        3130 :     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
   15754        3130 :     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
   15755        3130 :     if (StatResultType == NULL) {
   15756           0 :         return -1;
   15757             :     }
   15758        3130 :     Py_INCREF(StatResultType);
   15759        3130 :     PyModule_AddObject(m, "stat_result", StatResultType);
   15760        3130 :     state->StatResultType = StatResultType;
   15761        3130 :     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
   15762        3130 :     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
   15763             : 
   15764        3130 :     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
   15765        3130 :     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
   15766        3130 :     if (StatVFSResultType == NULL) {
   15767           0 :         return -1;
   15768             :     }
   15769        3130 :     Py_INCREF(StatVFSResultType);
   15770        3130 :     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
   15771        3130 :     state->StatVFSResultType = StatVFSResultType;
   15772             : #ifdef NEED_TICKS_PER_SECOND
   15773             : #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
   15774        3130 :     ticks_per_second = sysconf(_SC_CLK_TCK);
   15775             : #  elif defined(HZ)
   15776             :     ticks_per_second = HZ;
   15777             : #  else
   15778             :     ticks_per_second = 60; /* magic fallback value; may be bogus */
   15779             : #  endif
   15780             : #endif
   15781             : 
   15782             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
   15783        3130 :     sched_param_desc.name = MODNAME ".sched_param";
   15784        3130 :     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
   15785        3130 :     if (SchedParamType == NULL) {
   15786           0 :         return -1;
   15787             :     }
   15788        3130 :     Py_INCREF(SchedParamType);
   15789        3130 :     PyModule_AddObject(m, "sched_param", SchedParamType);
   15790        3130 :     state->SchedParamType = SchedParamType;
   15791        3130 :     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
   15792             : #endif
   15793             : 
   15794             :     /* initialize TerminalSize_info */
   15795        3130 :     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
   15796        3130 :     if (TerminalSizeType == NULL) {
   15797           0 :         return -1;
   15798             :     }
   15799        3130 :     Py_INCREF(TerminalSizeType);
   15800        3130 :     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
   15801        3130 :     state->TerminalSizeType = TerminalSizeType;
   15802             : 
   15803             :     /* initialize scandir types */
   15804        3130 :     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
   15805        3130 :     if (ScandirIteratorType == NULL) {
   15806           0 :         return -1;
   15807             :     }
   15808        3130 :     state->ScandirIteratorType = ScandirIteratorType;
   15809             : 
   15810        3130 :     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
   15811        3130 :     if (DirEntryType == NULL) {
   15812           0 :         return -1;
   15813             :     }
   15814        3130 :     Py_INCREF(DirEntryType);
   15815        3130 :     PyModule_AddObject(m, "DirEntry", DirEntryType);
   15816        3130 :     state->DirEntryType = DirEntryType;
   15817             : 
   15818        3130 :     times_result_desc.name = MODNAME ".times_result";
   15819        3130 :     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
   15820        3130 :     if (TimesResultType == NULL) {
   15821           0 :         return -1;
   15822             :     }
   15823        3130 :     Py_INCREF(TimesResultType);
   15824        3130 :     PyModule_AddObject(m, "times_result", TimesResultType);
   15825        3130 :     state->TimesResultType = TimesResultType;
   15826             : 
   15827        3130 :     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
   15828        3130 :     if (UnameResultType == NULL) {
   15829           0 :         return -1;
   15830             :     }
   15831        3130 :     Py_INCREF(UnameResultType);
   15832        3130 :     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
   15833        3130 :     state->UnameResultType = (PyObject *)UnameResultType;
   15834             : 
   15835        3130 :     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
   15836           0 :         return -1;
   15837             : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
   15838        3130 :     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
   15839        3130 :     if (state->struct_rusage == NULL)
   15840           0 :         return -1;
   15841             : #endif
   15842        3130 :     state->st_mode = PyUnicode_InternFromString("st_mode");
   15843        3130 :     if (state->st_mode == NULL)
   15844           0 :         return -1;
   15845             : 
   15846             :     /* suppress "function not used" warnings */
   15847             :     {
   15848             :     int ignored;
   15849        3130 :     fd_specified("", -1);
   15850        3130 :     follow_symlinks_specified("", 1);
   15851        3130 :     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
   15852        3130 :     dir_fd_converter(Py_None, &ignored);
   15853        3130 :     dir_fd_unavailable(Py_None, &ignored);
   15854             :     }
   15855             : 
   15856             :     /*
   15857             :      * provide list of locally available functions
   15858             :      * so os.py can populate support_* lists
   15859             :      */
   15860        3130 :     PyObject *list = PyList_New(0);
   15861        3130 :     if (!list) {
   15862           0 :         return -1;
   15863             :     }
   15864       97030 :     for (const struct have_function *trace = have_functions; trace->label; trace++) {
   15865             :         PyObject *unicode;
   15866       93900 :         if (trace->probe && !trace->probe()) continue;
   15867       93900 :         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
   15868       93900 :         if (!unicode)
   15869           0 :             return -1;
   15870       93900 :         if (PyList_Append(list, unicode))
   15871           0 :             return -1;
   15872       93900 :         Py_DECREF(unicode);
   15873             :     }
   15874             : 
   15875        3130 :     PyModule_AddObject(m, "_have_functions", list);
   15876             : 
   15877        3130 :     return 0;
   15878             : }
   15879             : 
   15880             : 
   15881             : static PyModuleDef_Slot posixmodile_slots[] = {
   15882             :     {Py_mod_exec, posixmodule_exec},
   15883             :     {0, NULL}
   15884             : };
   15885             : 
   15886             : static struct PyModuleDef posixmodule = {
   15887             :     PyModuleDef_HEAD_INIT,
   15888             :     .m_name = MODNAME,
   15889             :     .m_doc = posix__doc__,
   15890             :     .m_size = sizeof(_posixstate),
   15891             :     .m_methods = posix_methods,
   15892             :     .m_slots = posixmodile_slots,
   15893             :     .m_traverse = _posix_traverse,
   15894             :     .m_clear = _posix_clear,
   15895             :     .m_free = _posix_free,
   15896             : };
   15897             : 
   15898             : PyMODINIT_FUNC
   15899        3130 : INITFUNC(void)
   15900             : {
   15901        3130 :     return PyModuleDef_Init(&posixmodule);
   15902             : }
   15903             : 
   15904             : #ifdef __cplusplus
   15905             : }
   15906             : #endif

Generated by: LCOV version 1.14