LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules - posixmodule.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 411 2492 16.5 %
Date: 2012-12-17 Functions: 34 194 17.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /* POSIX module implementation */
       3             : 
       4             : /* This file is also used for Windows NT/MS-Win and OS/2.  In that case the
       5             :    module actually calls itself 'nt' or 'os2', not 'posix', and a few
       6             :    functions are either unimplemented or implemented differently.  The source
       7             :    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
       8             :    of the compiler used.  Different compilers define their own feature
       9             :    test macro, e.g. '__BORLANDC__' or '_MSC_VER'.  For OS/2, the compiler
      10             :    independent macro PYOS_OS2 should be defined.  On OS/2 the default
      11             :    compiler is assumed to be IBM's VisualAge C++ (VACPP).  PYCC_GCC is used
      12             :    as the compiler specific macro for the EMX port of gcc to OS/2. */
      13             : 
      14             : #ifdef __APPLE__
      15             :    /*
      16             :     * Step 1 of support for weak-linking a number of symbols existing on
      17             :     * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
      18             :     * at the end of this file for more information.
      19             :     */
      20             : #  pragma weak lchown
      21             : #  pragma weak statvfs
      22             : #  pragma weak fstatvfs
      23             : 
      24             : #endif /* __APPLE__ */
      25             : 
      26             : #define PY_SSIZE_T_CLEAN
      27             : 
      28             : #include "Python.h"
      29             : 
      30             : #if defined(__VMS)
      31             : #    error "PEP 11: VMS is now unsupported, code will be removed in Python 3.4"
      32             : #    include <unixio.h>
      33             : #endif /* defined(__VMS) */
      34             : 
      35             : #ifdef __cplusplus
      36             : extern "C" {
      37             : #endif
      38             : 
      39             : PyDoc_STRVAR(posix__doc__,
      40             : "This module provides access to operating system functionality that is\n\
      41             : standardized by the C Standard and the POSIX standard (a thinly\n\
      42             : disguised Unix interface).  Refer to the library manual and\n\
      43             : corresponding Unix manual entries for more information on calls.");
      44             : 
      45             : 
      46             : #if defined(PYOS_OS2)
      47             : #error "PEP 11: OS/2 is now unsupported, code will be removed in Python 3.4"
      48             : #define  INCL_DOS
      49             : #define  INCL_DOSERRORS
      50             : #define  INCL_DOSPROCESS
      51             : #define  INCL_NOPMAPI
      52             : #include <os2.h>
      53             : #if defined(PYCC_GCC)
      54             : #include <ctype.h>
      55             : #include <io.h>
      56             : #include <stdio.h>
      57             : #include <process.h>
      58             : #endif
      59             : #include "osdefs.h"
      60             : #endif
      61             : 
      62             : #ifdef HAVE_SYS_UIO_H
      63             : #include <sys/uio.h>
      64             : #endif
      65             : 
      66             : #ifdef HAVE_SYS_TYPES_H
      67             : #include <sys/types.h>
      68             : #endif /* HAVE_SYS_TYPES_H */
      69             : 
      70             : #ifdef HAVE_SYS_STAT_H
      71             : #include <sys/stat.h>
      72             : #endif /* HAVE_SYS_STAT_H */
      73             : 
      74             : #ifdef HAVE_SYS_WAIT_H
      75             : #include <sys/wait.h>           /* For WNOHANG */
      76             : #endif
      77             : 
      78             : #ifdef HAVE_SIGNAL_H
      79             : #include <signal.h>
      80             : #endif
      81             : 
      82             : #ifdef HAVE_FCNTL_H
      83             : #include <fcntl.h>
      84             : #endif /* HAVE_FCNTL_H */
      85             : 
      86             : #ifdef HAVE_GRP_H
      87             : #include <grp.h>
      88             : #endif
      89             : 
      90             : #ifdef HAVE_SYSEXITS_H
      91             : #include <sysexits.h>
      92             : #endif /* HAVE_SYSEXITS_H */
      93             : 
      94             : #ifdef HAVE_SYS_LOADAVG_H
      95             : #include <sys/loadavg.h>
      96             : #endif
      97             : 
      98             : #ifdef HAVE_LANGINFO_H
      99             : #include <langinfo.h>
     100             : #endif
     101             : 
     102             : #ifdef HAVE_SYS_SENDFILE_H
     103             : #include <sys/sendfile.h>
     104             : #endif
     105             : 
     106             : #ifdef HAVE_SCHED_H
     107             : #include <sched.h>
     108             : #endif
     109             : 
     110             : #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
     111             : #undef HAVE_SCHED_SETAFFINITY
     112             : #endif
     113             : 
     114             : #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__)
     115             : #define USE_XATTRS
     116             : #endif
     117             : 
     118             : #ifdef USE_XATTRS
     119             : #include <sys/xattr.h>
     120             : #endif
     121             : 
     122             : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
     123             : #ifdef HAVE_SYS_SOCKET_H
     124             : #include <sys/socket.h>
     125             : #endif
     126             : #endif
     127             : 
     128             : #ifdef HAVE_DLFCN_H
     129             : #include <dlfcn.h>
     130             : #endif
     131             : 
     132             : #if defined(MS_WINDOWS)
     133             : #  define TERMSIZE_USE_CONIO
     134             : #elif defined(HAVE_SYS_IOCTL_H)
     135             : #  include <sys/ioctl.h>
     136             : #  if defined(HAVE_TERMIOS_H)
     137             : #    include <termios.h>
     138             : #  endif
     139             : #  if defined(TIOCGWINSZ)
     140             : #    define TERMSIZE_USE_IOCTL
     141             : #  endif
     142             : #endif /* MS_WINDOWS */
     143             : 
     144             : /* Various compilers have only certain posix functions */
     145             : /* XXX Gosh I wish these were all moved into pyconfig.h */
     146             : #if defined(PYCC_VACPP) && defined(PYOS_OS2)
     147             : #include <process.h>
     148             : #else
     149             : #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
     150             : #define HAVE_GETCWD     1
     151             : #define HAVE_OPENDIR    1
     152             : #define HAVE_SYSTEM     1
     153             : #if defined(__OS2__)
     154             : #define HAVE_EXECV      1
     155             : #define HAVE_WAIT       1
     156             : #endif
     157             : #include <process.h>
     158             : #else
     159             : #ifdef __BORLANDC__             /* Borland compiler */
     160             : #define HAVE_EXECV      1
     161             : #define HAVE_GETCWD     1
     162             : #define HAVE_OPENDIR    1
     163             : #define HAVE_PIPE       1
     164             : #define HAVE_SYSTEM     1
     165             : #define HAVE_WAIT       1
     166             : #else
     167             : #ifdef _MSC_VER         /* Microsoft compiler */
     168             : #define HAVE_GETCWD     1
     169             : #define HAVE_GETPPID    1
     170             : #define HAVE_GETLOGIN   1
     171             : #define HAVE_SPAWNV     1
     172             : #define HAVE_EXECV      1
     173             : #define HAVE_PIPE       1
     174             : #define HAVE_SYSTEM     1
     175             : #define HAVE_CWAIT      1
     176             : #define HAVE_FSYNC      1
     177             : #define fsync _commit
     178             : #else
     179             : #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
     180             : /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
     181             : #else                   /* all other compilers */
     182             : /* Unix functions that the configure script doesn't check for */
     183             : #define HAVE_EXECV      1
     184             : #define HAVE_FORK       1
     185             : #if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
     186             : #define HAVE_FORK1      1
     187             : #endif
     188             : #define HAVE_GETCWD     1
     189             : #define HAVE_GETEGID    1
     190             : #define HAVE_GETEUID    1
     191             : #define HAVE_GETGID     1
     192             : #define HAVE_GETPPID    1
     193             : #define HAVE_GETUID     1
     194             : #define HAVE_KILL       1
     195             : #define HAVE_OPENDIR    1
     196             : #define HAVE_PIPE       1
     197             : #define HAVE_SYSTEM     1
     198             : #define HAVE_WAIT       1
     199             : #define HAVE_TTYNAME    1
     200             : #endif  /* PYOS_OS2 && PYCC_GCC && __VMS */
     201             : #endif  /* _MSC_VER */
     202             : #endif  /* __BORLANDC__ */
     203             : #endif  /* ! __WATCOMC__ || __QNX__ */
     204             : #endif /* ! __IBMC__ */
     205             : 
     206             : 
     207             : 
     208             : 
     209             : #ifndef _MSC_VER
     210             : 
     211             : #if defined(__sgi)&&_COMPILER_VERSION>=700
     212             : /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
     213             :    (default) */
     214             : extern char        *ctermid_r(char *);
     215             : #endif
     216             : 
     217             : #ifndef HAVE_UNISTD_H
     218             : #if defined(PYCC_VACPP)
     219             : extern int mkdir(char *);
     220             : #else
     221             : #if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
     222             : extern int mkdir(const char *);
     223             : #else
     224             : extern int mkdir(const char *, mode_t);
     225             : #endif
     226             : #endif
     227             : #if defined(__IBMC__) || defined(__IBMCPP__)
     228             : extern int chdir(char *);
     229             : extern int rmdir(char *);
     230             : #else
     231             : extern int chdir(const char *);
     232             : extern int rmdir(const char *);
     233             : #endif
     234             : #ifdef __BORLANDC__
     235             : extern int chmod(const char *, int);
     236             : #else
     237             : extern int chmod(const char *, mode_t);
     238             : #endif
     239             : /*#ifdef HAVE_FCHMOD
     240             : extern int fchmod(int, mode_t);
     241             : #endif*/
     242             : /*#ifdef HAVE_LCHMOD
     243             : extern int lchmod(const char *, mode_t);
     244             : #endif*/
     245             : extern int chown(const char *, uid_t, gid_t);
     246             : extern char *getcwd(char *, int);
     247             : extern char *strerror(int);
     248             : extern int link(const char *, const char *);
     249             : extern int rename(const char *, const char *);
     250             : extern int stat(const char *, struct stat *);
     251             : extern int unlink(const char *);
     252             : #ifdef HAVE_SYMLINK
     253             : extern int symlink(const char *, const char *);
     254             : #endif /* HAVE_SYMLINK */
     255             : #ifdef HAVE_LSTAT
     256             : extern int lstat(const char *, struct stat *);
     257             : #endif /* HAVE_LSTAT */
     258             : #endif /* !HAVE_UNISTD_H */
     259             : 
     260             : #endif /* !_MSC_VER */
     261             : 
     262             : #ifdef HAVE_UTIME_H
     263             : #include <utime.h>
     264             : #endif /* HAVE_UTIME_H */
     265             : 
     266             : #ifdef HAVE_SYS_UTIME_H
     267             : #include <sys/utime.h>
     268             : #define HAVE_UTIME_H /* pretend we do for the rest of this file */
     269             : #endif /* HAVE_SYS_UTIME_H */
     270             : 
     271             : #ifdef HAVE_SYS_TIMES_H
     272             : #include <sys/times.h>
     273             : #endif /* HAVE_SYS_TIMES_H */
     274             : 
     275             : #ifdef HAVE_SYS_PARAM_H
     276             : #include <sys/param.h>
     277             : #endif /* HAVE_SYS_PARAM_H */
     278             : 
     279             : #ifdef HAVE_SYS_UTSNAME_H
     280             : #include <sys/utsname.h>
     281             : #endif /* HAVE_SYS_UTSNAME_H */
     282             : 
     283             : #ifdef HAVE_DIRENT_H
     284             : #include <dirent.h>
     285             : #define NAMLEN(dirent) strlen((dirent)->d_name)
     286             : #else
     287             : #if defined(__WATCOMC__) && !defined(__QNX__)
     288             : #include <direct.h>
     289             : #define NAMLEN(dirent) strlen((dirent)->d_name)
     290             : #else
     291             : #define dirent direct
     292             : #define NAMLEN(dirent) (dirent)->d_namlen
     293             : #endif
     294             : #ifdef HAVE_SYS_NDIR_H
     295             : #include <sys/ndir.h>
     296             : #endif
     297             : #ifdef HAVE_SYS_DIR_H
     298             : #include <sys/dir.h>
     299             : #endif
     300             : #ifdef HAVE_NDIR_H
     301             : #include <ndir.h>
     302             : #endif
     303             : #endif
     304             : 
     305             : #ifdef _MSC_VER
     306             : #ifdef HAVE_DIRECT_H
     307             : #include <direct.h>
     308             : #endif
     309             : #ifdef HAVE_IO_H
     310             : #include <io.h>
     311             : #endif
     312             : #ifdef HAVE_PROCESS_H
     313             : #include <process.h>
     314             : #endif
     315             : #ifndef VOLUME_NAME_DOS
     316             : #define VOLUME_NAME_DOS 0x0
     317             : #endif
     318             : #ifndef VOLUME_NAME_NT
     319             : #define VOLUME_NAME_NT  0x2
     320             : #endif
     321             : #ifndef IO_REPARSE_TAG_SYMLINK
     322             : #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
     323             : #endif
     324             : #include "osdefs.h"
     325             : #include <malloc.h>
     326             : #include <windows.h>
     327             : #include <shellapi.h>   /* for ShellExecute() */
     328             : #include <lmcons.h>     /* for UNLEN */
     329             : #ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */
     330             : #define HAVE_SYMLINK
     331             : static int win32_can_symlink = 0;
     332             : #endif
     333             : #endif /* _MSC_VER */
     334             : 
     335             : #if defined(PYCC_VACPP) && defined(PYOS_OS2)
     336             : #include <io.h>
     337             : #endif /* OS2 */
     338             : 
     339             : #ifndef MAXPATHLEN
     340             : #if defined(PATH_MAX) && PATH_MAX > 1024
     341             : #define MAXPATHLEN PATH_MAX
     342             : #else
     343             : #define MAXPATHLEN 1024
     344             : #endif
     345             : #endif /* MAXPATHLEN */
     346             : 
     347             : #ifdef UNION_WAIT
     348             : /* Emulate some macros on systems that have a union instead of macros */
     349             : 
     350             : #ifndef WIFEXITED
     351             : #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
     352             : #endif
     353             : 
     354             : #ifndef WEXITSTATUS
     355             : #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
     356             : #endif
     357             : 
     358             : #ifndef WTERMSIG
     359             : #define WTERMSIG(u_wait) ((u_wait).w_termsig)
     360             : #endif
     361             : 
     362             : #define WAIT_TYPE union wait
     363             : #define WAIT_STATUS_INT(s) (s.w_status)
     364             : 
     365             : #else /* !UNION_WAIT */
     366             : #define WAIT_TYPE int
     367             : #define WAIT_STATUS_INT(s) (s)
     368             : #endif /* UNION_WAIT */
     369             : 
     370             : /* Don't use the "_r" form if we don't need it (also, won't have a
     371             :    prototype for it, at least on Solaris -- maybe others as well?). */
     372             : #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
     373             : #define USE_CTERMID_R
     374             : #endif
     375             : 
     376             : /* choose the appropriate stat and fstat functions and return structs */
     377             : #undef STAT
     378             : #undef FSTAT
     379             : #undef STRUCT_STAT
     380             : #if defined(MS_WIN64) || defined(MS_WINDOWS)
     381             : #       define STAT win32_stat
     382             : #       define LSTAT win32_lstat
     383             : #       define FSTAT win32_fstat
     384             : #       define STRUCT_STAT struct win32_stat
     385             : #else
     386             : #       define STAT stat
     387             : #       define LSTAT lstat
     388             : #       define FSTAT fstat
     389             : #       define STRUCT_STAT struct stat
     390             : #endif
     391             : 
     392             : #if defined(MAJOR_IN_MKDEV)
     393             : #include <sys/mkdev.h>
     394             : #else
     395             : #if defined(MAJOR_IN_SYSMACROS)
     396             : #include <sys/sysmacros.h>
     397             : #endif
     398             : #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
     399             : #include <sys/mkdev.h>
     400             : #endif
     401             : #endif
     402             : 
     403             : 
     404             : #ifdef MS_WINDOWS
     405             : static int
     406             : win32_warn_bytes_api()
     407             : {
     408             :     return PyErr_WarnEx(PyExc_DeprecationWarning,
     409             :         "The Windows bytes API has been deprecated, "
     410             :         "use Unicode filenames instead",
     411             :         1);
     412             : }
     413             : #endif
     414             : 
     415             : 
     416             : #ifdef AT_FDCWD
     417             : #define DEFAULT_DIR_FD AT_FDCWD
     418             : #else
     419             : #define DEFAULT_DIR_FD (-100)
     420             : #endif
     421             : 
     422             : static int
     423           2 : _fd_converter(PyObject *o, int *p, int default_value) {
     424             :     long long_value;
     425           2 :     if (o == Py_None) {
     426           2 :         *p = default_value;
     427           2 :         return 1;
     428             :     }
     429           0 :     if (PyFloat_Check(o)) {
     430           0 :         PyErr_SetString(PyExc_TypeError,
     431             :                         "integer argument expected, got float" );
     432           0 :         return 0;
     433             :     }
     434           0 :     long_value = PyLong_AsLong(o);
     435           0 :     if (long_value == -1 && PyErr_Occurred())
     436           0 :         return 0;
     437             :     if (long_value > INT_MAX) {
     438             :         PyErr_SetString(PyExc_OverflowError,
     439             :                         "signed integer is greater than maximum");
     440             :         return 0;
     441             :     }
     442             :     if (long_value < INT_MIN) {
     443             :         PyErr_SetString(PyExc_OverflowError,
     444             :                         "signed integer is less than minimum");
     445             :         return 0;
     446             :     }
     447           0 :     *p = (int)long_value;
     448           0 :     return 1;
     449             : }
     450             : 
     451             : static int
     452           1 : dir_fd_converter(PyObject *o, void *p) {
     453           1 :     return _fd_converter(o, (int *)p, DEFAULT_DIR_FD);
     454             : }
     455             : 
     456             : 
     457             : 
     458             : /*
     459             :  * A PyArg_ParseTuple "converter" function
     460             :  * that handles filesystem paths in the manner
     461             :  * preferred by the os module.
     462             :  *
     463             :  * path_converter accepts (Unicode) strings and their
     464             :  * subclasses, and bytes and their subclasses.  What
     465             :  * it does with the argument depends on the platform:
     466             :  *
     467             :  *   * On Windows, if we get a (Unicode) string we
     468             :  *     extract the wchar_t * and return it; if we get
     469             :  *     bytes we extract the char * and return that.
     470             :  *
     471             :  *   * On all other platforms, strings are encoded
     472             :  *     to bytes using PyUnicode_FSConverter, then we
     473             :  *     extract the char * from the bytes object and
     474             :  *     return that.
     475             :  *
     476             :  * path_converter also optionally accepts signed
     477             :  * integers (representing open file descriptors) instead
     478             :  * of path strings.
     479             :  *
     480             :  * Input fields:
     481             :  *   path.nullable
     482             :  *     If nonzero, the path is permitted to be None.
     483             :  *   path.allow_fd
     484             :  *     If nonzero, the path is permitted to be a file handle
     485             :  *     (a signed int) instead of a string.
     486             :  *   path.function_name
     487             :  *     If non-NULL, path_converter will use that as the name
     488             :  *     of the function in error messages.
     489             :  *     (If path.argument_name is NULL it omits the function name.)
     490             :  *   path.argument_name
     491             :  *     If non-NULL, path_converter will use that as the name
     492             :  *     of the parameter in error messages.
     493             :  *     (If path.argument_name is NULL it uses "path".)
     494             :  *
     495             :  * Output fields:
     496             :  *   path.wide
     497             :  *     Points to the path if it was expressed as Unicode
     498             :  *     and was not encoded.  (Only used on Windows.)
     499             :  *   path.narrow
     500             :  *     Points to the path if it was expressed as bytes,
     501             :  *     or it was Unicode and was encoded to bytes.
     502             :  *   path.fd
     503             :  *     Contains a file descriptor if path.accept_fd was true
     504             :  *     and the caller provided a signed integer instead of any
     505             :  *     sort of string.
     506             :  *
     507             :  *     WARNING: if your "path" parameter is optional, and is
     508             :  *     unspecified, path_converter will never get called.
     509             :  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
     510             :  *     yourself!
     511             :  *   path.length
     512             :  *     The length of the path in characters, if specified as
     513             :  *     a string.
     514             :  *   path.object
     515             :  *     The original object passed in.
     516             :  *   path.cleanup
     517             :  *     For internal use only.  May point to a temporary object.
     518             :  *     (Pay no attention to the man behind the curtain.)
     519             :  *
     520             :  *   At most one of path.wide or path.narrow will be non-NULL.
     521             :  *   If path was None and path.nullable was set,
     522             :  *     or if path was an integer and path.allow_fd was set,
     523             :  *     both path.wide and path.narrow will be NULL
     524             :  *     and path.length will be 0.
     525             :  *
     526             :  *   path_converter takes care to not write to the path_t
     527             :  *   unless it's successful.  However it must reset the
     528             :  *   "cleanup" field each time it's called.
     529             :  *
     530             :  * Use as follows:
     531             :  *      path_t path;
     532             :  *      memset(&path, 0, sizeof(path));
     533             :  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
     534             :  *      // ... use values from path ...
     535             :  *      path_cleanup(&path);
     536             :  *
     537             :  * (Note that if PyArg_Parse fails you don't need to call
     538             :  * path_cleanup().  However it is safe to do so.)
     539             :  */
     540             : typedef struct {
     541             :     char *function_name;
     542             :     char *argument_name;
     543             :     int nullable;
     544             :     int allow_fd;
     545             :     wchar_t *wide;
     546             :     char *narrow;
     547             :     int fd;
     548             :     Py_ssize_t length;
     549             :     PyObject *object;
     550             :     PyObject *cleanup;
     551             : } path_t;
     552             : 
     553             : static void
     554         360 : path_cleanup(path_t *path) {
     555         360 :     if (path->cleanup) {
     556         360 :         Py_DECREF(path->cleanup);
     557         360 :         path->cleanup = NULL;
     558             :     }
     559         360 : }
     560             : 
     561             : static int
     562         360 : path_converter(PyObject *o, void *p) {
     563         360 :     path_t *path = (path_t *)p;
     564             :     PyObject *unicode, *bytes;
     565             :     Py_ssize_t length;
     566             :     char *narrow;
     567             : 
     568             : #define FORMAT_EXCEPTION(exc, fmt) \
     569             :     PyErr_Format(exc, "%s%s" fmt, \
     570             :         path->function_name ? path->function_name : "", \
     571             :         path->function_name ? ": "                : "", \
     572             :         path->argument_name ? path->argument_name : "path")
     573             : 
     574             :     /* Py_CLEANUP_SUPPORTED support */
     575         360 :     if (o == NULL) {
     576           0 :         path_cleanup(path);
     577           0 :         return 1;
     578             :     }
     579             : 
     580             :     /* ensure it's always safe to call path_cleanup() */
     581         360 :     path->cleanup = NULL;
     582             : 
     583         360 :     if (o == Py_None) {
     584           0 :         if (!path->nullable) {
     585           0 :             FORMAT_EXCEPTION(PyExc_TypeError,
     586             :                              "can't specify None for %s argument");
     587           0 :             return 0;
     588             :         }
     589           0 :         path->wide = NULL;
     590           0 :         path->narrow = NULL;
     591           0 :         path->length = 0;
     592           0 :         path->object = o;
     593           0 :         path->fd = -1;
     594           0 :         return 1;
     595             :     }
     596             : 
     597         360 :     unicode = PyUnicode_FromObject(o);
     598         360 :     if (unicode) {
     599             : #ifdef MS_WINDOWS
     600             :         wchar_t *wide;
     601             :         length = PyUnicode_GET_SIZE(unicode);
     602             :         if (length > 32767) {
     603             :             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
     604             :             Py_DECREF(unicode);
     605             :             return 0;
     606             :         }
     607             : 
     608             :         wide = PyUnicode_AsUnicode(unicode);
     609             :         if (!wide) {
     610             :             Py_DECREF(unicode);
     611             :             return 0;
     612             :         }
     613             : 
     614             :         path->wide = wide;
     615             :         path->narrow = NULL;
     616             :         path->length = length;
     617             :         path->object = o;
     618             :         path->fd = -1;
     619             :         path->cleanup = unicode;
     620             :         return Py_CLEANUP_SUPPORTED;
     621             : #else
     622         358 :         int converted = PyUnicode_FSConverter(unicode, &bytes);
     623         358 :         Py_DECREF(unicode);
     624         358 :         if (!converted)
     625           0 :             bytes = NULL;
     626             : #endif
     627             :     }
     628             :     else {
     629           2 :         PyErr_Clear();
     630           2 :         bytes = PyBytes_FromObject(o);
     631           2 :         if (!bytes) {
     632           0 :             PyErr_Clear();
     633           0 :             if (path->allow_fd) {
     634             :                 int fd;
     635             :                 /*
     636             :                  * note: _fd_converter always permits None.
     637             :                  * but we've already done our None check.
     638             :                  * so o cannot be None at this point.
     639             :                  */
     640           0 :                 int result = _fd_converter(o, &fd, -1);
     641           0 :                 if (result) {
     642           0 :                     path->wide = NULL;
     643           0 :                     path->narrow = NULL;
     644           0 :                     path->length = 0;
     645           0 :                     path->object = o;
     646           0 :                     path->fd = fd;
     647           0 :                     return result;
     648             :                 }
     649             :             }
     650             :         }
     651             :     }
     652             : 
     653         360 :     if (!bytes) {
     654           0 :         if (!PyErr_Occurred())
     655           0 :             FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter");
     656           0 :         return 0;
     657             :     }
     658             : 
     659             : #ifdef MS_WINDOWS
     660             :     if (win32_warn_bytes_api()) {
     661             :         Py_DECREF(bytes);
     662             :         return 0;
     663             :     }
     664             : #endif
     665             : 
     666         360 :     length = PyBytes_GET_SIZE(bytes);
     667             : #ifdef MS_WINDOWS
     668             :     if (length > MAX_PATH) {
     669             :         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
     670             :         Py_DECREF(bytes);
     671             :         return 0;
     672             :     }
     673             : #endif
     674             : 
     675         360 :     narrow = PyBytes_AS_STRING(bytes);
     676         360 :     if (length != strlen(narrow)) {
     677           0 :         FORMAT_EXCEPTION(PyExc_ValueError, "embedded NUL character in %s");
     678           0 :         Py_DECREF(bytes);
     679           0 :         return 0;
     680             :     }
     681             : 
     682         360 :     path->wide = NULL;
     683         360 :     path->narrow = narrow;
     684         360 :     path->length = length;
     685         360 :     path->object = o;
     686         360 :     path->fd = -1;
     687         360 :     path->cleanup = bytes;
     688         360 :     return Py_CLEANUP_SUPPORTED;
     689             : }
     690             : 
     691             : static void
     692           0 : argument_unavailable_error(char *function_name, char *argument_name) {
     693           0 :     PyErr_Format(PyExc_NotImplementedError,
     694             :         "%s%s%s unavailable on this platform",
     695             :         (function_name != NULL) ? function_name : "",
     696             :         (function_name != NULL) ? ": ": "",
     697             :         argument_name);
     698           0 : }
     699             : 
     700             : static int
     701           1 : dir_fd_unavailable(PyObject *o, void *p) {
     702           1 :     int *dir_fd = (int *)p;
     703           1 :     int return_value = _fd_converter(o, dir_fd, DEFAULT_DIR_FD);
     704           1 :     if (!return_value)
     705           0 :         return 0;
     706           1 :     if (*dir_fd == DEFAULT_DIR_FD)
     707           1 :         return 1;
     708           0 :     argument_unavailable_error(NULL, "dir_fd");
     709           0 :     return 0;
     710             : }
     711             : 
     712             : static int
     713           1 : fd_specified(char *function_name, int fd) {
     714           1 :     if (fd == -1)
     715           1 :         return 0;
     716             : 
     717           0 :     argument_unavailable_error(function_name, "fd");
     718           0 :     return 1;
     719             : }
     720             : 
     721             : static int
     722           1 : follow_symlinks_specified(char *function_name, int follow_symlinks) {
     723           1 :     if (follow_symlinks)
     724           1 :         return 0;
     725             : 
     726           0 :     argument_unavailable_error(function_name, "follow_symlinks");
     727           0 :     return 1;
     728             : }
     729             : 
     730             : static int
     731         347 : path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) {
     732         347 :     if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) {
     733           0 :         PyErr_Format(PyExc_ValueError,
     734             :                      "%s: can't specify dir_fd without matching path",
     735             :                      function_name);
     736           0 :         return 1;
     737             :     }
     738         347 :     return 0;
     739             : }
     740             : 
     741             : static int
     742         347 : dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) {
     743         347 :     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
     744           0 :         PyErr_Format(PyExc_ValueError,
     745             :                      "%s: can't specify both dir_fd and fd",
     746             :                      function_name);
     747           0 :         return 1;
     748             :     }
     749         347 :     return 0;
     750             : }
     751             : 
     752             : static int
     753         347 : fd_and_follow_symlinks_invalid(char *function_name, int fd,
     754             :                                int follow_symlinks) {
     755         347 :     if ((fd > 0) && (!follow_symlinks)) {
     756           0 :         PyErr_Format(PyExc_ValueError,
     757             :                      "%s: cannot use fd and follow_symlinks together",
     758             :                      function_name);
     759           0 :         return 1;
     760             :     }
     761         347 :     return 0;
     762             : }
     763             : 
     764             : static int
     765           1 : dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd,
     766             :                                    int follow_symlinks) {
     767           1 :     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
     768           0 :         PyErr_Format(PyExc_ValueError,
     769             :                      "%s: cannot use dir_fd and follow_symlinks together",
     770             :                      function_name);
     771           0 :         return 1;
     772             :     }
     773           1 :     return 0;
     774             : }
     775             : 
     776             : /* A helper used by a number of POSIX-only functions */
     777             : #ifndef MS_WINDOWS
     778             : static int
     779           0 : _parse_off_t(PyObject* arg, void* addr)
     780             : {
     781             : #if !defined(HAVE_LARGEFILE_SUPPORT)
     782             :     *((off_t*)addr) = PyLong_AsLong(arg);
     783             : #else
     784           0 :     *((off_t*)addr) = PyLong_AsLongLong(arg);
     785             : #endif
     786           0 :     if (PyErr_Occurred())
     787           0 :         return 0;
     788           0 :     return 1;
     789             : }
     790             : #endif
     791             : 
     792             : #if defined _MSC_VER && _MSC_VER >= 1400
     793             : /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
     794             :  * valid and throw an assertion if it isn't.
     795             :  * Normally, an invalid fd is likely to be a C program error and therefore
     796             :  * an assertion can be useful, but it does contradict the POSIX standard
     797             :  * which for write(2) states:
     798             :  *    "Otherwise, -1 shall be returned and errno set to indicate the error."
     799             :  *    "[EBADF] The fildes argument is not a valid file descriptor open for
     800             :  *     writing."
     801             :  * Furthermore, python allows the user to enter any old integer
     802             :  * as a fd and should merely raise a python exception on error.
     803             :  * The Microsoft CRT doesn't provide an official way to check for the
     804             :  * validity of a file descriptor, but we can emulate its internal behaviour
     805             :  * by using the exported __pinfo data member and knowledge of the
     806             :  * internal structures involved.
     807             :  * The structures below must be updated for each version of visual studio
     808             :  * according to the file internal.h in the CRT source, until MS comes
     809             :  * up with a less hacky way to do this.
     810             :  * (all of this is to avoid globally modifying the CRT behaviour using
     811             :  * _set_invalid_parameter_handler() and _CrtSetReportMode())
     812             :  */
     813             : /* The actual size of the structure is determined at runtime.
     814             :  * Only the first items must be present.
     815             :  */
     816             : typedef struct {
     817             :     intptr_t osfhnd;
     818             :     char osfile;
     819             : } my_ioinfo;
     820             : 
     821             : extern __declspec(dllimport) char * __pioinfo[];
     822             : #define IOINFO_L2E 5
     823             : #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
     824             : #define IOINFO_ARRAYS 64
     825             : #define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
     826             : #define FOPEN 0x01
     827             : #define _NO_CONSOLE_FILENO (intptr_t)-2
     828             : 
     829             : /* This function emulates what the windows CRT does to validate file handles */
     830             : int
     831             : _PyVerify_fd(int fd)
     832             : {
     833             :     const int i1 = fd >> IOINFO_L2E;
     834             :     const int i2 = fd & ((1 << IOINFO_L2E) - 1);
     835             : 
     836             :     static size_t sizeof_ioinfo = 0;
     837             : 
     838             :     /* Determine the actual size of the ioinfo structure,
     839             :      * as used by the CRT loaded in memory
     840             :      */
     841             :     if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
     842             :         sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
     843             :     }
     844             :     if (sizeof_ioinfo == 0) {
     845             :         /* This should not happen... */
     846             :         goto fail;
     847             :     }
     848             : 
     849             :     /* See that it isn't a special CLEAR fileno */
     850             :     if (fd != _NO_CONSOLE_FILENO) {
     851             :         /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that.  Instead
     852             :          * we check pointer validity and other info
     853             :          */
     854             :         if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
     855             :             /* finally, check that the file is open */
     856             :             my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
     857             :             if (info->osfile & FOPEN) {
     858             :                 return 1;
     859             :             }
     860             :         }
     861             :     }
     862             :   fail:
     863             :     errno = EBADF;
     864             :     return 0;
     865             : }
     866             : 
     867             : /* the special case of checking dup2.  The target fd must be in a sensible range */
     868             : static int
     869             : _PyVerify_fd_dup2(int fd1, int fd2)
     870             : {
     871             :     if (!_PyVerify_fd(fd1))
     872             :         return 0;
     873             :     if (fd2 == _NO_CONSOLE_FILENO)
     874             :         return 0;
     875             :     if ((unsigned)fd2 < _NHANDLE_)
     876             :         return 1;
     877             :     else
     878             :         return 0;
     879             : }
     880             : #else
     881             : /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
     882             : #define _PyVerify_fd_dup2(A, B) (1)
     883             : #endif
     884             : 
     885             : #ifdef MS_WINDOWS
     886             : /* The following structure was copied from
     887             :    http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
     888             :    include doesn't seem to be present in the Windows SDK (at least as included
     889             :    with Visual Studio Express). */
     890             : typedef struct _REPARSE_DATA_BUFFER {
     891             :     ULONG ReparseTag;
     892             :     USHORT ReparseDataLength;
     893             :     USHORT Reserved;
     894             :     union {
     895             :         struct {
     896             :             USHORT SubstituteNameOffset;
     897             :             USHORT SubstituteNameLength;
     898             :             USHORT PrintNameOffset;
     899             :             USHORT PrintNameLength;
     900             :             ULONG Flags;
     901             :             WCHAR PathBuffer[1];
     902             :         } SymbolicLinkReparseBuffer;
     903             : 
     904             :         struct {
     905             :             USHORT SubstituteNameOffset;
     906             :             USHORT  SubstituteNameLength;
     907             :             USHORT  PrintNameOffset;
     908             :             USHORT  PrintNameLength;
     909             :             WCHAR  PathBuffer[1];
     910             :         } MountPointReparseBuffer;
     911             : 
     912             :         struct {
     913             :             UCHAR  DataBuffer[1];
     914             :         } GenericReparseBuffer;
     915             :     };
     916             : } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
     917             : 
     918             : #define REPARSE_DATA_BUFFER_HEADER_SIZE  FIELD_OFFSET(REPARSE_DATA_BUFFER,\
     919             :                                                       GenericReparseBuffer)
     920             : #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE  ( 16 * 1024 )
     921             : 
     922             : static int
     923             : win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
     924             : {
     925             :     char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
     926             :     REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
     927             :     DWORD n_bytes_returned;
     928             : 
     929             :     if (0 == DeviceIoControl(
     930             :         reparse_point_handle,
     931             :         FSCTL_GET_REPARSE_POINT,
     932             :         NULL, 0, /* in buffer */
     933             :         target_buffer, sizeof(target_buffer),
     934             :         &n_bytes_returned,
     935             :         NULL)) /* we're not using OVERLAPPED_IO */
     936             :         return FALSE;
     937             : 
     938             :     if (reparse_tag)
     939             :         *reparse_tag = rdb->ReparseTag;
     940             : 
     941             :     return TRUE;
     942             : }
     943             : 
     944             : #endif /* MS_WINDOWS */
     945             : 
     946             : /* Return a dictionary corresponding to the POSIX environment table */
     947             : #ifdef WITH_NEXT_FRAMEWORK
     948             : /* On Darwin/MacOSX a shared library or framework has no access to
     949             : ** environ directly, we must obtain it with _NSGetEnviron().
     950             : */
     951             : #include <crt_externs.h>
     952             : static char **environ;
     953             : #elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
     954             : extern char **environ;
     955             : #endif /* !_MSC_VER */
     956             : 
     957             : static PyObject *
     958           1 : convertenviron(void)
     959             : {
     960             :     PyObject *d;
     961             : #ifdef MS_WINDOWS
     962             :     wchar_t **e;
     963             : #else
     964             :     char **e;
     965             : #endif
     966             : #if defined(PYOS_OS2)
     967             :     APIRET rc;
     968             :     char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
     969             : #endif
     970             : 
     971           1 :     d = PyDict_New();
     972           1 :     if (d == NULL)
     973           0 :         return NULL;
     974             : #ifdef WITH_NEXT_FRAMEWORK
     975             :     if (environ == NULL)
     976             :         environ = *_NSGetEnviron();
     977             : #endif
     978             : #ifdef MS_WINDOWS
     979             :     /* _wenviron must be initialized in this way if the program is started
     980             :        through main() instead of wmain(). */
     981             :     _wgetenv(L"");
     982             :     if (_wenviron == NULL)
     983             :         return d;
     984             :     /* This part ignores errors */
     985             :     for (e = _wenviron; *e != NULL; e++) {
     986             :         PyObject *k;
     987             :         PyObject *v;
     988             :         wchar_t *p = wcschr(*e, L'=');
     989             :         if (p == NULL)
     990             :             continue;
     991             :         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
     992             :         if (k == NULL) {
     993             :             PyErr_Clear();
     994             :             continue;
     995             :         }
     996             :         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
     997             :         if (v == NULL) {
     998             :             PyErr_Clear();
     999             :             Py_DECREF(k);
    1000             :             continue;
    1001             :         }
    1002             :         if (PyDict_GetItem(d, k) == NULL) {
    1003             :             if (PyDict_SetItem(d, k, v) != 0)
    1004             :                 PyErr_Clear();
    1005             :         }
    1006             :         Py_DECREF(k);
    1007             :         Py_DECREF(v);
    1008             :     }
    1009             : #else
    1010           1 :     if (environ == NULL)
    1011           0 :         return d;
    1012             :     /* This part ignores errors */
    1013         747 :     for (e = environ; *e != NULL; e++) {
    1014             :         PyObject *k;
    1015             :         PyObject *v;
    1016         746 :         char *p = strchr(*e, '=');
    1017         746 :         if (p == NULL)
    1018           0 :             continue;
    1019         746 :         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
    1020         746 :         if (k == NULL) {
    1021           0 :             PyErr_Clear();
    1022           0 :             continue;
    1023             :         }
    1024         746 :         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
    1025         746 :         if (v == NULL) {
    1026           0 :             PyErr_Clear();
    1027           0 :             Py_DECREF(k);
    1028           0 :             continue;
    1029             :         }
    1030         746 :         if (PyDict_GetItem(d, k) == NULL) {
    1031         746 :             if (PyDict_SetItem(d, k, v) != 0)
    1032           0 :                 PyErr_Clear();
    1033             :         }
    1034         746 :         Py_DECREF(k);
    1035         746 :         Py_DECREF(v);
    1036             :     }
    1037             : #endif
    1038             : #if defined(PYOS_OS2)
    1039             :     rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
    1040             :     if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
    1041             :         PyObject *v = PyBytes_FromString(buffer);
    1042             :         PyDict_SetItemString(d, "BEGINLIBPATH", v);
    1043             :         Py_DECREF(v);
    1044             :     }
    1045             :     rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
    1046             :     if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
    1047             :         PyObject *v = PyBytes_FromString(buffer);
    1048             :         PyDict_SetItemString(d, "ENDLIBPATH", v);
    1049             :         Py_DECREF(v);
    1050             :     }
    1051             : #endif
    1052           1 :     return d;
    1053             : }
    1054             : 
    1055             : /* Set a POSIX-specific error from errno, and return NULL */
    1056             : 
    1057             : static PyObject *
    1058           0 : posix_error(void)
    1059             : {
    1060           0 :     return PyErr_SetFromErrno(PyExc_OSError);
    1061             : }
    1062             : static PyObject *
    1063          23 : posix_error_with_filename(char* name)
    1064             : {
    1065          23 :     return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
    1066             : }
    1067             : 
    1068             : 
    1069             : static PyObject *
    1070           0 : posix_error_with_allocated_filename(PyObject* name)
    1071             : {
    1072             :     PyObject *name_str, *rc;
    1073           0 :     name_str = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AsString(name),
    1074             :                                                 PyBytes_GET_SIZE(name));
    1075           0 :     Py_DECREF(name);
    1076           0 :     rc = PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
    1077             :                                               name_str);
    1078           0 :     Py_XDECREF(name_str);
    1079           0 :     return rc;
    1080             : }
    1081             : 
    1082             : #ifdef MS_WINDOWS
    1083             : static PyObject *
    1084             : win32_error(char* function, const char* filename)
    1085             : {
    1086             :     /* XXX We should pass the function name along in the future.
    1087             :        (winreg.c also wants to pass the function name.)
    1088             :        This would however require an additional param to the
    1089             :        Windows error object, which is non-trivial.
    1090             :     */
    1091             :     errno = GetLastError();
    1092             :     if (filename)
    1093             :         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
    1094             :     else
    1095             :         return PyErr_SetFromWindowsErr(errno);
    1096             : }
    1097             : 
    1098             : static PyObject *
    1099             : win32_error_unicode(char* function, wchar_t* filename)
    1100             : {
    1101             :     /* XXX - see win32_error for comments on 'function' */
    1102             :     errno = GetLastError();
    1103             :     if (filename)
    1104             :         return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
    1105             :     else
    1106             :         return PyErr_SetFromWindowsErr(errno);
    1107             : }
    1108             : 
    1109             : static PyObject *
    1110             : win32_error_object(char* function, PyObject* filename)
    1111             : {
    1112             :     /* XXX - see win32_error for comments on 'function' */
    1113             :     errno = GetLastError();
    1114             :     if (filename)
    1115             :         return PyErr_SetExcFromWindowsErrWithFilenameObject(
    1116             :                     PyExc_WindowsError,
    1117             :                     errno,
    1118             :                     filename);
    1119             :     else
    1120             :         return PyErr_SetFromWindowsErr(errno);
    1121             : }
    1122             : 
    1123             : #endif /* MS_WINDOWS */
    1124             : 
    1125             : /*
    1126             :  * Some functions return Win32 errors, others only ever use posix_error
    1127             :  * (this is for backwards compatibility with exceptions)
    1128             :  */
    1129             : static PyObject *
    1130          23 : path_posix_error(char *function_name, path_t *path)
    1131             : {
    1132          23 :     if (path->narrow)
    1133          23 :         return posix_error_with_filename(path->narrow);
    1134           0 :     return posix_error();
    1135             : }
    1136             : 
    1137             : static PyObject *
    1138          23 : path_error(char *function_name, path_t *path)
    1139             : {
    1140             : #ifdef MS_WINDOWS
    1141             :     if (path->narrow)
    1142             :         return win32_error(function_name, path->narrow);
    1143             :     if (path->wide)
    1144             :         return win32_error_unicode(function_name, path->wide);
    1145             :     return win32_error(function_name, NULL);
    1146             : #else
    1147          23 :     return path_posix_error(function_name, path);
    1148             : #endif
    1149             : }
    1150             : 
    1151             : #if defined(PYOS_OS2)
    1152             : /**********************************************************************
    1153             :  *         Helper Function to Trim and Format OS/2 Messages
    1154             :  **********************************************************************/
    1155             : static void
    1156             : os2_formatmsg(char *msgbuf, int msglen, char *reason)
    1157             : {
    1158             :     msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
    1159             : 
    1160             :     if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
    1161             :         char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
    1162             : 
    1163             :         while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
    1164             :             *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
    1165             :     }
    1166             : 
    1167             :     /* Add Optional Reason Text */
    1168             :     if (reason) {
    1169             :         strcat(msgbuf, " : ");
    1170             :         strcat(msgbuf, reason);
    1171             :     }
    1172             : }
    1173             : 
    1174             : /**********************************************************************
    1175             :  *             Decode an OS/2 Operating System Error Code
    1176             :  *
    1177             :  * A convenience function to lookup an OS/2 error code and return a
    1178             :  * text message we can use to raise a Python exception.
    1179             :  *
    1180             :  * Notes:
    1181             :  *   The messages for errors returned from the OS/2 kernel reside in
    1182             :  *   the file OSO001.MSG in the \OS2 directory hierarchy.
    1183             :  *
    1184             :  **********************************************************************/
    1185             : static char *
    1186             : os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
    1187             : {
    1188             :     APIRET rc;
    1189             :     ULONG  msglen;
    1190             : 
    1191             :     /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
    1192             :     Py_BEGIN_ALLOW_THREADS
    1193             :     rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
    1194             :                        errorcode, "oso001.msg", &msglen);
    1195             :     Py_END_ALLOW_THREADS
    1196             : 
    1197             :     if (rc == NO_ERROR)
    1198             :         os2_formatmsg(msgbuf, msglen, reason);
    1199             :     else
    1200             :         PyOS_snprintf(msgbuf, msgbuflen,
    1201             :                       "unknown OS error #%d", errorcode);
    1202             : 
    1203             :     return msgbuf;
    1204             : }
    1205             : 
    1206             : /* Set an OS/2-specific error and return NULL.  OS/2 kernel
    1207             :    errors are not in a global variable e.g. 'errno' nor are
    1208             :    they congruent with posix error numbers. */
    1209             : 
    1210             : static PyObject *
    1211             : os2_error(int code)
    1212             : {
    1213             :     char text[1024];
    1214             :     PyObject *v;
    1215             : 
    1216             :     os2_strerror(text, sizeof(text), code, "");
    1217             : 
    1218             :     v = Py_BuildValue("(is)", code, text);
    1219             :     if (v != NULL) {
    1220             :         PyErr_SetObject(PyExc_OSError, v);
    1221             :         Py_DECREF(v);
    1222             :     }
    1223             :     return NULL; /* Signal to Python that an Exception is Pending */
    1224             : }
    1225             : 
    1226             : #endif /* OS2 */
    1227             : 
    1228             : /* POSIX generic methods */
    1229             : 
    1230             : static PyObject *
    1231           0 : posix_fildes(PyObject *fdobj, int (*func)(int))
    1232             : {
    1233             :     int fd;
    1234             :     int res;
    1235           0 :     fd = PyObject_AsFileDescriptor(fdobj);
    1236           0 :     if (fd < 0)
    1237           0 :         return NULL;
    1238             :     if (!_PyVerify_fd(fd))
    1239             :         return posix_error();
    1240           0 :     Py_BEGIN_ALLOW_THREADS
    1241           0 :     res = (*func)(fd);
    1242           0 :     Py_END_ALLOW_THREADS
    1243           0 :     if (res < 0)
    1244           0 :         return posix_error();
    1245           0 :     Py_INCREF(Py_None);
    1246           0 :     return Py_None;
    1247             : }
    1248             : 
    1249             : static PyObject *
    1250           0 : posix_1str(PyObject *args, char *format, int (*func)(const char*))
    1251             : {
    1252           0 :     PyObject *opath1 = NULL;
    1253             :     char *path1;
    1254             :     int res;
    1255           0 :     if (!PyArg_ParseTuple(args, format,
    1256             :                           PyUnicode_FSConverter, &opath1))
    1257           0 :         return NULL;
    1258           0 :     path1 = PyBytes_AsString(opath1);
    1259           0 :     Py_BEGIN_ALLOW_THREADS
    1260           0 :     res = (*func)(path1);
    1261           0 :     Py_END_ALLOW_THREADS
    1262           0 :     if (res < 0)
    1263           0 :         return posix_error_with_allocated_filename(opath1);
    1264           0 :     Py_DECREF(opath1);
    1265           0 :     Py_INCREF(Py_None);
    1266           0 :     return Py_None;
    1267             : }
    1268             : 
    1269             : 
    1270             : #ifdef MS_WINDOWS
    1271             : static PyObject*
    1272             : win32_1str(PyObject* args, char* func,
    1273             :            char* format, BOOL (__stdcall *funcA)(LPCSTR),
    1274             :            char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
    1275             : {
    1276             :     PyObject *uni;
    1277             :     const char *ansi;
    1278             :     BOOL result;
    1279             : 
    1280             :     if (PyArg_ParseTuple(args, wformat, &uni))
    1281             :     {
    1282             :         wchar_t *wstr = PyUnicode_AsUnicode(uni);
    1283             :         if (wstr == NULL)
    1284             :             return NULL;
    1285             :         Py_BEGIN_ALLOW_THREADS
    1286             :         result = funcW(wstr);
    1287             :         Py_END_ALLOW_THREADS
    1288             :         if (!result)
    1289             :             return win32_error_object(func, uni);
    1290             :         Py_INCREF(Py_None);
    1291             :         return Py_None;
    1292             :     }
    1293             :     PyErr_Clear();
    1294             : 
    1295             :     if (!PyArg_ParseTuple(args, format, &ansi))
    1296             :         return NULL;
    1297             :     if (win32_warn_bytes_api())
    1298             :         return NULL;
    1299             :     Py_BEGIN_ALLOW_THREADS
    1300             :     result = funcA(ansi);
    1301             :     Py_END_ALLOW_THREADS
    1302             :     if (!result)
    1303             :         return win32_error(func, ansi);
    1304             :     Py_INCREF(Py_None);
    1305             :     return Py_None;
    1306             : 
    1307             : }
    1308             : 
    1309             : /* This is a reimplementation of the C library's chdir function,
    1310             :    but one that produces Win32 errors instead of DOS error codes.
    1311             :    chdir is essentially a wrapper around SetCurrentDirectory; however,
    1312             :    it also needs to set "magic" environment variables indicating
    1313             :    the per-drive current directory, which are of the form =<drive>: */
    1314             : static BOOL __stdcall
    1315             : win32_chdir(LPCSTR path)
    1316             : {
    1317             :     char new_path[MAX_PATH+1];
    1318             :     int result;
    1319             :     char env[4] = "=x:";
    1320             : 
    1321             :     if(!SetCurrentDirectoryA(path))
    1322             :         return FALSE;
    1323             :     result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
    1324             :     if (!result)
    1325             :         return FALSE;
    1326             :     /* In the ANSI API, there should not be any paths longer
    1327             :        than MAX_PATH. */
    1328             :     assert(result <= MAX_PATH+1);
    1329             :     if (strncmp(new_path, "\\\\", 2) == 0 ||
    1330             :         strncmp(new_path, "//", 2) == 0)
    1331             :         /* UNC path, nothing to do. */
    1332             :         return TRUE;
    1333             :     env[1] = new_path[0];
    1334             :     return SetEnvironmentVariableA(env, new_path);
    1335             : }
    1336             : 
    1337             : /* The Unicode version differs from the ANSI version
    1338             :    since the current directory might exceed MAX_PATH characters */
    1339             : static BOOL __stdcall
    1340             : win32_wchdir(LPCWSTR path)
    1341             : {
    1342             :     wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
    1343             :     int result;
    1344             :     wchar_t env[4] = L"=x:";
    1345             : 
    1346             :     if(!SetCurrentDirectoryW(path))
    1347             :         return FALSE;
    1348             :     result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
    1349             :     if (!result)
    1350             :         return FALSE;
    1351             :     if (result > MAX_PATH+1) {
    1352             :         new_path = malloc(result * sizeof(wchar_t));
    1353             :         if (!new_path) {
    1354             :             SetLastError(ERROR_OUTOFMEMORY);
    1355             :             return FALSE;
    1356             :         }
    1357             :         result = GetCurrentDirectoryW(result, new_path);
    1358             :         if (!result) {
    1359             :             free(new_path);
    1360             :             return FALSE;
    1361             :         }
    1362             :     }
    1363             :     if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
    1364             :         wcsncmp(new_path, L"//", 2) == 0)
    1365             :         /* UNC path, nothing to do. */
    1366             :         return TRUE;
    1367             :     env[1] = new_path[0];
    1368             :     result = SetEnvironmentVariableW(env, new_path);
    1369             :     if (new_path != _new_path)
    1370             :         free(new_path);
    1371             :     return result;
    1372             : }
    1373             : #endif
    1374             : 
    1375             : #ifdef MS_WINDOWS
    1376             : /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
    1377             :    - time stamps are restricted to second resolution
    1378             :    - file modification times suffer from forth-and-back conversions between
    1379             :      UTC and local time
    1380             :    Therefore, we implement our own stat, based on the Win32 API directly.
    1381             : */
    1382             : #define HAVE_STAT_NSEC 1
    1383             : 
    1384             : struct win32_stat{
    1385             :     int st_dev;
    1386             :     __int64 st_ino;
    1387             :     unsigned short st_mode;
    1388             :     int st_nlink;
    1389             :     int st_uid;
    1390             :     int st_gid;
    1391             :     int st_rdev;
    1392             :     __int64 st_size;
    1393             :     time_t st_atime;
    1394             :     int st_atime_nsec;
    1395             :     time_t st_mtime;
    1396             :     int st_mtime_nsec;
    1397             :     time_t st_ctime;
    1398             :     int st_ctime_nsec;
    1399             : };
    1400             : 
    1401             : static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
    1402             : 
    1403             : static void
    1404             : FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
    1405             : {
    1406             :     /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
    1407             :     /* Cannot simply cast and dereference in_ptr,
    1408             :        since it might not be aligned properly */
    1409             :     __int64 in;
    1410             :     memcpy(&in, in_ptr, sizeof(in));
    1411             :     *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
    1412             :     *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
    1413             : }
    1414             : 
    1415             : static void
    1416             : time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
    1417             : {
    1418             :     /* XXX endianness */
    1419             :     __int64 out;
    1420             :     out = time_in + secs_between_epochs;
    1421             :     out = out * 10000000 + nsec_in / 100;
    1422             :     memcpy(out_ptr, &out, sizeof(out));
    1423             : }
    1424             : 
    1425             : /* Below, we *know* that ugo+r is 0444 */
    1426             : #if _S_IREAD != 0400
    1427             : #error Unsupported C library
    1428             : #endif
    1429             : static int
    1430             : attributes_to_mode(DWORD attr)
    1431             : {
    1432             :     int m = 0;
    1433             :     if (attr & FILE_ATTRIBUTE_DIRECTORY)
    1434             :         m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
    1435             :     else
    1436             :         m |= _S_IFREG;
    1437             :     if (attr & FILE_ATTRIBUTE_READONLY)
    1438             :         m |= 0444;
    1439             :     else
    1440             :         m |= 0666;
    1441             :     return m;
    1442             : }
    1443             : 
    1444             : static int
    1445             : attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct win32_stat *result)
    1446             : {
    1447             :     memset(result, 0, sizeof(*result));
    1448             :     result->st_mode = attributes_to_mode(info->dwFileAttributes);
    1449             :     result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
    1450             :     FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
    1451             :     FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
    1452             :     FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
    1453             :     result->st_nlink = info->nNumberOfLinks;
    1454             :     result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
    1455             :     if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
    1456             :         /* first clear the S_IFMT bits */
    1457             :         result->st_mode ^= (result->st_mode & 0170000);
    1458             :         /* now set the bits that make this a symlink */
    1459             :         result->st_mode |= 0120000;
    1460             :     }
    1461             : 
    1462             :     return 0;
    1463             : }
    1464             : 
    1465             : static BOOL
    1466             : attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
    1467             : {
    1468             :     HANDLE hFindFile;
    1469             :     WIN32_FIND_DATAA FileData;
    1470             :     hFindFile = FindFirstFileA(pszFile, &FileData);
    1471             :     if (hFindFile == INVALID_HANDLE_VALUE)
    1472             :         return FALSE;
    1473             :     FindClose(hFindFile);
    1474             :     memset(info, 0, sizeof(*info));
    1475             :     *reparse_tag = 0;
    1476             :     info->dwFileAttributes = FileData.dwFileAttributes;
    1477             :     info->ftCreationTime   = FileData.ftCreationTime;
    1478             :     info->ftLastAccessTime = FileData.ftLastAccessTime;
    1479             :     info->ftLastWriteTime  = FileData.ftLastWriteTime;
    1480             :     info->nFileSizeHigh    = FileData.nFileSizeHigh;
    1481             :     info->nFileSizeLow     = FileData.nFileSizeLow;
    1482             : /*  info->nNumberOfLinks   = 1; */
    1483             :     if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
    1484             :         *reparse_tag = FileData.dwReserved0;
    1485             :     return TRUE;
    1486             : }
    1487             : 
    1488             : static BOOL
    1489             : attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
    1490             : {
    1491             :     HANDLE hFindFile;
    1492             :     WIN32_FIND_DATAW FileData;
    1493             :     hFindFile = FindFirstFileW(pszFile, &FileData);
    1494             :     if (hFindFile == INVALID_HANDLE_VALUE)
    1495             :         return FALSE;
    1496             :     FindClose(hFindFile);
    1497             :     memset(info, 0, sizeof(*info));
    1498             :     *reparse_tag = 0;
    1499             :     info->dwFileAttributes = FileData.dwFileAttributes;
    1500             :     info->ftCreationTime   = FileData.ftCreationTime;
    1501             :     info->ftLastAccessTime = FileData.ftLastAccessTime;
    1502             :     info->ftLastWriteTime  = FileData.ftLastWriteTime;
    1503             :     info->nFileSizeHigh    = FileData.nFileSizeHigh;
    1504             :     info->nFileSizeLow     = FileData.nFileSizeLow;
    1505             : /*  info->nNumberOfLinks   = 1; */
    1506             :     if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
    1507             :         *reparse_tag = FileData.dwReserved0;
    1508             :     return TRUE;
    1509             : }
    1510             : 
    1511             : /* Grab GetFinalPathNameByHandle dynamically from kernel32 */
    1512             : static int has_GetFinalPathNameByHandle = 0;
    1513             : static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
    1514             :                                                       DWORD);
    1515             : static int
    1516             : check_GetFinalPathNameByHandle()
    1517             : {
    1518             :     HINSTANCE hKernel32;
    1519             :     DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
    1520             :                                                    DWORD);
    1521             : 
    1522             :     /* only recheck */
    1523             :     if (!has_GetFinalPathNameByHandle)
    1524             :     {
    1525             :         hKernel32 = GetModuleHandleW(L"KERNEL32");
    1526             :         *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
    1527             :                                                 "GetFinalPathNameByHandleA");
    1528             :         *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
    1529             :                                                 "GetFinalPathNameByHandleW");
    1530             :         has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
    1531             :                                        Py_GetFinalPathNameByHandleW;
    1532             :     }
    1533             :     return has_GetFinalPathNameByHandle;
    1534             : }
    1535             : 
    1536             : static BOOL
    1537             : get_target_path(HANDLE hdl, wchar_t **target_path)
    1538             : {
    1539             :     int buf_size, result_length;
    1540             :     wchar_t *buf;
    1541             : 
    1542             :     /* We have a good handle to the target, use it to determine
    1543             :        the target path name (then we'll call lstat on it). */
    1544             :     buf_size = Py_GetFinalPathNameByHandleW(hdl, 0, 0,
    1545             :                                             VOLUME_NAME_DOS);
    1546             :     if(!buf_size)
    1547             :         return FALSE;
    1548             : 
    1549             :     buf = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
    1550             :     if (!buf) {
    1551             :         SetLastError(ERROR_OUTOFMEMORY);
    1552             :         return FALSE;
    1553             :     }
    1554             : 
    1555             :     result_length = Py_GetFinalPathNameByHandleW(hdl,
    1556             :                        buf, buf_size, VOLUME_NAME_DOS);
    1557             : 
    1558             :     if(!result_length) {
    1559             :         free(buf);
    1560             :         return FALSE;
    1561             :     }
    1562             : 
    1563             :     if(!CloseHandle(hdl)) {
    1564             :         free(buf);
    1565             :         return FALSE;
    1566             :     }
    1567             : 
    1568             :     buf[result_length] = 0;
    1569             : 
    1570             :     *target_path = buf;
    1571             :     return TRUE;
    1572             : }
    1573             : 
    1574             : static int
    1575             : win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
    1576             :                    BOOL traverse);
    1577             : static int
    1578             : win32_xstat_impl(const char *path, struct win32_stat *result,
    1579             :                  BOOL traverse)
    1580             : {
    1581             :     int code;
    1582             :     HANDLE hFile, hFile2;
    1583             :     BY_HANDLE_FILE_INFORMATION info;
    1584             :     ULONG reparse_tag = 0;
    1585             :     wchar_t *target_path;
    1586             :     const char *dot;
    1587             : 
    1588             :     if(!check_GetFinalPathNameByHandle()) {
    1589             :         /* If the OS doesn't have GetFinalPathNameByHandle, don't
    1590             :            traverse reparse point. */
    1591             :         traverse = FALSE;
    1592             :     }
    1593             : 
    1594             :     hFile = CreateFileA(
    1595             :         path,
    1596             :         FILE_READ_ATTRIBUTES, /* desired access */
    1597             :         0, /* share mode */
    1598             :         NULL, /* security attributes */
    1599             :         OPEN_EXISTING,
    1600             :         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
    1601             :         /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
    1602             :            Because of this, calls like GetFinalPathNameByHandle will return
    1603             :            the symlink path agin and not the actual final path. */
    1604             :         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
    1605             :             FILE_FLAG_OPEN_REPARSE_POINT,
    1606             :         NULL);
    1607             : 
    1608             :     if (hFile == INVALID_HANDLE_VALUE) {
    1609             :         /* Either the target doesn't exist, or we don't have access to
    1610             :            get a handle to it. If the former, we need to return an error.
    1611             :            If the latter, we can use attributes_from_dir. */
    1612             :         if (GetLastError() != ERROR_SHARING_VIOLATION)
    1613             :             return -1;
    1614             :         /* Could not get attributes on open file. Fall back to
    1615             :            reading the directory. */
    1616             :         if (!attributes_from_dir(path, &info, &reparse_tag))
    1617             :             /* Very strange. This should not fail now */
    1618             :             return -1;
    1619             :         if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    1620             :             if (traverse) {
    1621             :                 /* Should traverse, but could not open reparse point handle */
    1622             :                 SetLastError(ERROR_SHARING_VIOLATION);
    1623             :                 return -1;
    1624             :             }
    1625             :         }
    1626             :     } else {
    1627             :         if (!GetFileInformationByHandle(hFile, &info)) {
    1628             :             CloseHandle(hFile);
    1629             :             return -1;
    1630             :         }
    1631             :         if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    1632             :             if (!win32_get_reparse_tag(hFile, &reparse_tag))
    1633             :                 return -1;
    1634             : 
    1635             :             /* Close the outer open file handle now that we're about to
    1636             :                reopen it with different flags. */
    1637             :             if (!CloseHandle(hFile))
    1638             :                 return -1;
    1639             : 
    1640             :             if (traverse) {
    1641             :                 /* In order to call GetFinalPathNameByHandle we need to open
    1642             :                    the file without the reparse handling flag set. */
    1643             :                 hFile2 = CreateFileA(
    1644             :                            path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
    1645             :                            NULL, OPEN_EXISTING,
    1646             :                            FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
    1647             :                            NULL);
    1648             :                 if (hFile2 == INVALID_HANDLE_VALUE)
    1649             :                     return -1;
    1650             : 
    1651             :                 if (!get_target_path(hFile2, &target_path))
    1652             :                     return -1;
    1653             : 
    1654             :                 code = win32_xstat_impl_w(target_path, result, FALSE);
    1655             :                 free(target_path);
    1656             :                 return code;
    1657             :             }
    1658             :         } else
    1659             :             CloseHandle(hFile);
    1660             :     }
    1661             :     attribute_data_to_stat(&info, reparse_tag, result);
    1662             : 
    1663             :     /* Set S_IEXEC if it is an .exe, .bat, ... */
    1664             :     dot = strrchr(path, '.');
    1665             :     if (dot) {
    1666             :         if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
    1667             :             stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
    1668             :             result->st_mode |= 0111;
    1669             :     }
    1670             :     return 0;
    1671             : }
    1672             : 
    1673             : static int
    1674             : win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
    1675             :                    BOOL traverse)
    1676             : {
    1677             :     int code;
    1678             :     HANDLE hFile, hFile2;
    1679             :     BY_HANDLE_FILE_INFORMATION info;
    1680             :     ULONG reparse_tag = 0;
    1681             :     wchar_t *target_path;
    1682             :     const wchar_t *dot;
    1683             : 
    1684             :     if(!check_GetFinalPathNameByHandle()) {
    1685             :         /* If the OS doesn't have GetFinalPathNameByHandle, don't
    1686             :            traverse reparse point. */
    1687             :         traverse = FALSE;
    1688             :     }
    1689             : 
    1690             :     hFile = CreateFileW(
    1691             :         path,
    1692             :         FILE_READ_ATTRIBUTES, /* desired access */
    1693             :         0, /* share mode */
    1694             :         NULL, /* security attributes */
    1695             :         OPEN_EXISTING,
    1696             :         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
    1697             :         /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
    1698             :            Because of this, calls like GetFinalPathNameByHandle will return
    1699             :            the symlink path agin and not the actual final path. */
    1700             :         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
    1701             :             FILE_FLAG_OPEN_REPARSE_POINT,
    1702             :         NULL);
    1703             : 
    1704             :     if (hFile == INVALID_HANDLE_VALUE) {
    1705             :         /* Either the target doesn't exist, or we don't have access to
    1706             :            get a handle to it. If the former, we need to return an error.
    1707             :            If the latter, we can use attributes_from_dir. */
    1708             :         if (GetLastError() != ERROR_SHARING_VIOLATION)
    1709             :             return -1;
    1710             :         /* Could not get attributes on open file. Fall back to
    1711             :            reading the directory. */
    1712             :         if (!attributes_from_dir_w(path, &info, &reparse_tag))
    1713             :             /* Very strange. This should not fail now */
    1714             :             return -1;
    1715             :         if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    1716             :             if (traverse) {
    1717             :                 /* Should traverse, but could not open reparse point handle */
    1718             :                 SetLastError(ERROR_SHARING_VIOLATION);
    1719             :                 return -1;
    1720             :             }
    1721             :         }
    1722             :     } else {
    1723             :         if (!GetFileInformationByHandle(hFile, &info)) {
    1724             :             CloseHandle(hFile);
    1725             :             return -1;
    1726             :         }
    1727             :         if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    1728             :             if (!win32_get_reparse_tag(hFile, &reparse_tag))
    1729             :                 return -1;
    1730             : 
    1731             :             /* Close the outer open file handle now that we're about to
    1732             :                reopen it with different flags. */
    1733             :             if (!CloseHandle(hFile))
    1734             :                 return -1;
    1735             : 
    1736             :             if (traverse) {
    1737             :                 /* In order to call GetFinalPathNameByHandle we need to open
    1738             :                    the file without the reparse handling flag set. */
    1739             :                 hFile2 = CreateFileW(
    1740             :                            path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
    1741             :                            NULL, OPEN_EXISTING,
    1742             :                            FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
    1743             :                            NULL);
    1744             :                 if (hFile2 == INVALID_HANDLE_VALUE)
    1745             :                     return -1;
    1746             : 
    1747             :                 if (!get_target_path(hFile2, &target_path))
    1748             :                     return -1;
    1749             : 
    1750             :                 code = win32_xstat_impl_w(target_path, result, FALSE);
    1751             :                 free(target_path);
    1752             :                 return code;
    1753             :             }
    1754             :         } else
    1755             :             CloseHandle(hFile);
    1756             :     }
    1757             :     attribute_data_to_stat(&info, reparse_tag, result);
    1758             : 
    1759             :     /* Set S_IEXEC if it is an .exe, .bat, ... */
    1760             :     dot = wcsrchr(path, '.');
    1761             :     if (dot) {
    1762             :         if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
    1763             :             _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
    1764             :             result->st_mode |= 0111;
    1765             :     }
    1766             :     return 0;
    1767             : }
    1768             : 
    1769             : static int
    1770             : win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
    1771             : {
    1772             :     /* Protocol violation: we explicitly clear errno, instead of
    1773             :        setting it to a POSIX error. Callers should use GetLastError. */
    1774             :     int code = win32_xstat_impl(path, result, traverse);
    1775             :     errno = 0;
    1776             :     return code;
    1777             : }
    1778             : 
    1779             : static int
    1780             : win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
    1781             : {
    1782             :     /* Protocol violation: we explicitly clear errno, instead of
    1783             :        setting it to a POSIX error. Callers should use GetLastError. */
    1784             :     int code = win32_xstat_impl_w(path, result, traverse);
    1785             :     errno = 0;
    1786             :     return code;
    1787             : }
    1788             : /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
    1789             : 
    1790             :    In Posix, stat automatically traverses symlinks and returns the stat
    1791             :    structure for the target.  In Windows, the equivalent GetFileAttributes by
    1792             :    default does not traverse symlinks and instead returns attributes for
    1793             :    the symlink.
    1794             : 
    1795             :    Therefore, win32_lstat will get the attributes traditionally, and
    1796             :    win32_stat will first explicitly resolve the symlink target and then will
    1797             :    call win32_lstat on that result.
    1798             : 
    1799             :    The _w represent Unicode equivalents of the aforementioned ANSI functions. */
    1800             : 
    1801             : static int
    1802             : win32_lstat(const char* path, struct win32_stat *result)
    1803             : {
    1804             :     return win32_xstat(path, result, FALSE);
    1805             : }
    1806             : 
    1807             : static int
    1808             : win32_lstat_w(const wchar_t* path, struct win32_stat *result)
    1809             : {
    1810             :     return win32_xstat_w(path, result, FALSE);
    1811             : }
    1812             : 
    1813             : static int
    1814             : win32_stat(const char* path, struct win32_stat *result)
    1815             : {
    1816             :     return win32_xstat(path, result, TRUE);
    1817             : }
    1818             : 
    1819             : static int
    1820             : win32_stat_w(const wchar_t* path, struct win32_stat *result)
    1821             : {
    1822             :     return win32_xstat_w(path, result, TRUE);
    1823             : }
    1824             : 
    1825             : static int
    1826             : win32_fstat(int file_number, struct win32_stat *result)
    1827             : {
    1828             :     BY_HANDLE_FILE_INFORMATION info;
    1829             :     HANDLE h;
    1830             :     int type;
    1831             : 
    1832             :     if (!_PyVerify_fd(file_number))
    1833             :         h = INVALID_HANDLE_VALUE;
    1834             :     else
    1835             :         h = (HANDLE)_get_osfhandle(file_number);
    1836             : 
    1837             :     /* Protocol violation: we explicitly clear errno, instead of
    1838             :        setting it to a POSIX error. Callers should use GetLastError. */
    1839             :     errno = 0;
    1840             : 
    1841             :     if (h == INVALID_HANDLE_VALUE) {
    1842             :         /* This is really a C library error (invalid file handle).
    1843             :            We set the Win32 error to the closes one matching. */
    1844             :         SetLastError(ERROR_INVALID_HANDLE);
    1845             :         return -1;
    1846             :     }
    1847             :     memset(result, 0, sizeof(*result));
    1848             : 
    1849             :     type = GetFileType(h);
    1850             :     if (type == FILE_TYPE_UNKNOWN) {
    1851             :         DWORD error = GetLastError();
    1852             :         if (error != 0) {
    1853             :             return -1;
    1854             :         }
    1855             :         /* else: valid but unknown file */
    1856             :     }
    1857             : 
    1858             :     if (type != FILE_TYPE_DISK) {
    1859             :         if (type == FILE_TYPE_CHAR)
    1860             :             result->st_mode = _S_IFCHR;
    1861             :         else if (type == FILE_TYPE_PIPE)
    1862             :             result->st_mode = _S_IFIFO;
    1863             :         return 0;
    1864             :     }
    1865             : 
    1866             :     if (!GetFileInformationByHandle(h, &info)) {
    1867             :         return -1;
    1868             :     }
    1869             : 
    1870             :     attribute_data_to_stat(&info, 0, result);
    1871             :     /* specific to fstat() */
    1872             :     result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
    1873             :     return 0;
    1874             : }
    1875             : 
    1876             : #endif /* MS_WINDOWS */
    1877             : 
    1878             : PyDoc_STRVAR(stat_result__doc__,
    1879             : "stat_result: Result from stat, fstat, or lstat.\n\n\
    1880             : This object may be accessed either as a tuple of\n\
    1881             :   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
    1882             : or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
    1883             : \n\
    1884             : Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
    1885             : or st_flags, they are available as attributes only.\n\
    1886             : \n\
    1887             : See os.stat for more information.");
    1888             : 
    1889             : static PyStructSequence_Field stat_result_fields[] = {
    1890             :     {"st_mode",    "protection bits"},
    1891             :     {"st_ino",     "inode"},
    1892             :     {"st_dev",     "device"},
    1893             :     {"st_nlink",   "number of hard links"},
    1894             :     {"st_uid",     "user ID of owner"},
    1895             :     {"st_gid",     "group ID of owner"},
    1896             :     {"st_size",    "total size, in bytes"},
    1897             :     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
    1898             :     {NULL,   "integer time of last access"},
    1899             :     {NULL,   "integer time of last modification"},
    1900             :     {NULL,   "integer time of last change"},
    1901             :     {"st_atime",   "time of last access"},
    1902             :     {"st_mtime",   "time of last modification"},
    1903             :     {"st_ctime",   "time of last change"},
    1904             :     {"st_atime_ns",   "time of last access in nanoseconds"},
    1905             :     {"st_mtime_ns",   "time of last modification in nanoseconds"},
    1906             :     {"st_ctime_ns",   "time of last change in nanoseconds"},
    1907             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    1908             :     {"st_blksize", "blocksize for filesystem I/O"},
    1909             : #endif
    1910             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    1911             :     {"st_blocks",  "number of blocks allocated"},
    1912             : #endif
    1913             : #ifdef HAVE_STRUCT_STAT_ST_RDEV
    1914             :     {"st_rdev",    "device type (if inode device)"},
    1915             : #endif
    1916             : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
    1917             :     {"st_flags",   "user defined flags for file"},
    1918             : #endif
    1919             : #ifdef HAVE_STRUCT_STAT_ST_GEN
    1920             :     {"st_gen",    "generation number"},
    1921             : #endif
    1922             : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
    1923             :     {"st_birthtime",   "time of creation"},
    1924             : #endif
    1925             :     {0}
    1926             : };
    1927             : 
    1928             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    1929             : #define ST_BLKSIZE_IDX 16
    1930             : #else
    1931             : #define ST_BLKSIZE_IDX 15
    1932             : #endif
    1933             : 
    1934             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    1935             : #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
    1936             : #else
    1937             : #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
    1938             : #endif
    1939             : 
    1940             : #ifdef HAVE_STRUCT_STAT_ST_RDEV
    1941             : #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
    1942             : #else
    1943             : #define ST_RDEV_IDX ST_BLOCKS_IDX
    1944             : #endif
    1945             : 
    1946             : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
    1947             : #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
    1948             : #else
    1949             : #define ST_FLAGS_IDX ST_RDEV_IDX
    1950             : #endif
    1951             : 
    1952             : #ifdef HAVE_STRUCT_STAT_ST_GEN
    1953             : #define ST_GEN_IDX (ST_FLAGS_IDX+1)
    1954             : #else
    1955             : #define ST_GEN_IDX ST_FLAGS_IDX
    1956             : #endif
    1957             : 
    1958             : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
    1959             : #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
    1960             : #else
    1961             : #define ST_BIRTHTIME_IDX ST_GEN_IDX
    1962             : #endif
    1963             : 
    1964             : static PyStructSequence_Desc stat_result_desc = {
    1965             :     "stat_result", /* name */
    1966             :     stat_result__doc__, /* doc */
    1967             :     stat_result_fields,
    1968             :     10
    1969             : };
    1970             : 
    1971             : PyDoc_STRVAR(statvfs_result__doc__,
    1972             : "statvfs_result: Result from statvfs or fstatvfs.\n\n\
    1973             : This object may be accessed either as a tuple of\n\
    1974             :   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
    1975             : or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
    1976             : \n\
    1977             : See os.statvfs for more information.");
    1978             : 
    1979             : static PyStructSequence_Field statvfs_result_fields[] = {
    1980             :     {"f_bsize",  },
    1981             :     {"f_frsize", },
    1982             :     {"f_blocks", },
    1983             :     {"f_bfree",  },
    1984             :     {"f_bavail", },
    1985             :     {"f_files",  },
    1986             :     {"f_ffree",  },
    1987             :     {"f_favail", },
    1988             :     {"f_flag",   },
    1989             :     {"f_namemax",},
    1990             :     {0}
    1991             : };
    1992             : 
    1993             : static PyStructSequence_Desc statvfs_result_desc = {
    1994             :     "statvfs_result", /* name */
    1995             :     statvfs_result__doc__, /* doc */
    1996             :     statvfs_result_fields,
    1997             :     10
    1998             : };
    1999             : 
    2000             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
    2001             : PyDoc_STRVAR(waitid_result__doc__,
    2002             : "waitid_result: Result from waitid.\n\n\
    2003             : This object may be accessed either as a tuple of\n\
    2004             :   (si_pid, si_uid, si_signo, si_status, si_code),\n\
    2005             : or via the attributes si_pid, si_uid, and so on.\n\
    2006             : \n\
    2007             : See os.waitid for more information.");
    2008             : 
    2009             : static PyStructSequence_Field waitid_result_fields[] = {
    2010             :     {"si_pid",  },
    2011             :     {"si_uid", },
    2012             :     {"si_signo", },
    2013             :     {"si_status",  },
    2014             :     {"si_code", },
    2015             :     {0}
    2016             : };
    2017             : 
    2018             : static PyStructSequence_Desc waitid_result_desc = {
    2019             :     "waitid_result", /* name */
    2020             :     waitid_result__doc__, /* doc */
    2021             :     waitid_result_fields,
    2022             :     5
    2023             : };
    2024             : static PyTypeObject WaitidResultType;
    2025             : #endif
    2026             : 
    2027             : static int initialized;
    2028             : static PyTypeObject StatResultType;
    2029             : static PyTypeObject StatVFSResultType;
    2030             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
    2031             : static PyTypeObject SchedParamType;
    2032             : #endif
    2033             : static newfunc structseq_new;
    2034             : 
    2035             : static PyObject *
    2036           0 : statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    2037             : {
    2038             :     PyStructSequence *result;
    2039             :     int i;
    2040             : 
    2041           0 :     result = (PyStructSequence*)structseq_new(type, args, kwds);
    2042           0 :     if (!result)
    2043           0 :         return NULL;
    2044             :     /* If we have been initialized from a tuple,
    2045             :        st_?time might be set to None. Initialize it
    2046             :        from the int slots.  */
    2047           0 :     for (i = 7; i <= 9; i++) {
    2048           0 :         if (result->ob_item[i+3] == Py_None) {
    2049           0 :             Py_DECREF(Py_None);
    2050           0 :             Py_INCREF(result->ob_item[i]);
    2051           0 :             result->ob_item[i+3] = result->ob_item[i];
    2052             :         }
    2053             :     }
    2054           0 :     return (PyObject*)result;
    2055             : }
    2056             : 
    2057             : 
    2058             : 
    2059             : /* If true, st_?time is float. */
    2060             : static int _stat_float_times = 1;
    2061             : 
    2062             : PyDoc_STRVAR(stat_float_times__doc__,
    2063             : "stat_float_times([newval]) -> oldval\n\n\
    2064             : Determine whether os.[lf]stat represents time stamps as float objects.\n\
    2065             : If newval is True, future calls to stat() return floats, if it is False,\n\
    2066             : future calls return ints. \n\
    2067             : If newval is omitted, return the current setting.\n");
    2068             : 
    2069             : static PyObject*
    2070           0 : stat_float_times(PyObject* self, PyObject *args)
    2071             : {
    2072           0 :     int newval = -1;
    2073           0 :     if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
    2074           0 :         return NULL;
    2075           0 :     if (PyErr_WarnEx(PyExc_DeprecationWarning,
    2076             :                      "stat_float_times() is deprecated",
    2077             :                      1))
    2078           0 :         return NULL;
    2079           0 :     if (newval == -1)
    2080             :         /* Return old value */
    2081           0 :         return PyBool_FromLong(_stat_float_times);
    2082           0 :     _stat_float_times = newval;
    2083           0 :     Py_INCREF(Py_None);
    2084           0 :     return Py_None;
    2085             : }
    2086             : 
    2087             : static PyObject *billion = NULL;
    2088             : 
    2089             : static void
    2090         972 : fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
    2091             : {
    2092         972 :     PyObject *s = _PyLong_FromTime_t(sec);
    2093         972 :     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
    2094         972 :     PyObject *s_in_ns = NULL;
    2095         972 :     PyObject *ns_total = NULL;
    2096         972 :     PyObject *float_s = NULL;
    2097             : 
    2098         972 :     if (!(s && ns_fractional))
    2099             :         goto exit;
    2100             : 
    2101         972 :     s_in_ns = PyNumber_Multiply(s, billion);
    2102         972 :     if (!s_in_ns)
    2103           0 :         goto exit;
    2104             : 
    2105         972 :     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
    2106         972 :     if (!ns_total)
    2107           0 :         goto exit;
    2108             : 
    2109         972 :     if (_stat_float_times) {
    2110         972 :         float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
    2111         972 :         if (!float_s)
    2112           0 :             goto exit;
    2113             :     }
    2114             :     else {
    2115           0 :         float_s = s;
    2116           0 :         Py_INCREF(float_s);
    2117             :     }
    2118             : 
    2119         972 :     PyStructSequence_SET_ITEM(v, index, s);
    2120         972 :     PyStructSequence_SET_ITEM(v, index+3, float_s);
    2121         972 :     PyStructSequence_SET_ITEM(v, index+6, ns_total);
    2122         972 :     s = NULL;
    2123         972 :     float_s = NULL;
    2124         972 :     ns_total = NULL;
    2125             : exit:
    2126         972 :     Py_XDECREF(s);
    2127         972 :     Py_XDECREF(ns_fractional);
    2128         972 :     Py_XDECREF(s_in_ns);
    2129         972 :     Py_XDECREF(ns_total);
    2130         972 :     Py_XDECREF(float_s);
    2131         972 : }
    2132             : 
    2133             : /* pack a system stat C structure into the Python stat tuple
    2134             :    (used by posix_stat() and posix_fstat()) */
    2135             : static PyObject*
    2136         324 : _pystat_fromstructstat(STRUCT_STAT *st)
    2137             : {
    2138             :     unsigned long ansec, mnsec, cnsec;
    2139         324 :     PyObject *v = PyStructSequence_New(&StatResultType);
    2140         324 :     if (v == NULL)
    2141           0 :         return NULL;
    2142             : 
    2143         324 :     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
    2144             : #ifdef HAVE_LARGEFILE_SUPPORT
    2145         324 :     PyStructSequence_SET_ITEM(v, 1,
    2146             :                               PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
    2147             : #else
    2148             :     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
    2149             : #endif
    2150             : #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
    2151         324 :     PyStructSequence_SET_ITEM(v, 2,
    2152             :                               PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
    2153             : #else
    2154             :     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long)st->st_dev));
    2155             : #endif
    2156         324 :     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
    2157         324 :     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long)st->st_uid));
    2158         324 :     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long)st->st_gid));
    2159             : #ifdef HAVE_LARGEFILE_SUPPORT
    2160         324 :     PyStructSequence_SET_ITEM(v, 6,
    2161             :                               PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
    2162             : #else
    2163             :     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
    2164             : #endif
    2165             : 
    2166             : #if defined(HAVE_STAT_TV_NSEC)
    2167         324 :     ansec = st->st_atim.tv_nsec;
    2168         324 :     mnsec = st->st_mtim.tv_nsec;
    2169         324 :     cnsec = st->st_ctim.tv_nsec;
    2170             : #elif defined(HAVE_STAT_TV_NSEC2)
    2171             :     ansec = st->st_atimespec.tv_nsec;
    2172             :     mnsec = st->st_mtimespec.tv_nsec;
    2173             :     cnsec = st->st_ctimespec.tv_nsec;
    2174             : #elif defined(HAVE_STAT_NSEC)
    2175             :     ansec = st->st_atime_nsec;
    2176             :     mnsec = st->st_mtime_nsec;
    2177             :     cnsec = st->st_ctime_nsec;
    2178             : #else
    2179             :     ansec = mnsec = cnsec = 0;
    2180             : #endif
    2181         324 :     fill_time(v, 7, st->st_atime, ansec);
    2182         324 :     fill_time(v, 8, st->st_mtime, mnsec);
    2183         324 :     fill_time(v, 9, st->st_ctime, cnsec);
    2184             : 
    2185             : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    2186         324 :     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
    2187             :                               PyLong_FromLong((long)st->st_blksize));
    2188             : #endif
    2189             : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    2190         324 :     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
    2191             :                               PyLong_FromLong((long)st->st_blocks));
    2192             : #endif
    2193             : #ifdef HAVE_STRUCT_STAT_ST_RDEV
    2194         324 :     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
    2195             :                               PyLong_FromLong((long)st->st_rdev));
    2196             : #endif
    2197             : #ifdef HAVE_STRUCT_STAT_ST_GEN
    2198             :     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
    2199             :                               PyLong_FromLong((long)st->st_gen));
    2200             : #endif
    2201             : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
    2202             :     {
    2203             :       PyObject *val;
    2204             :       unsigned long bsec,bnsec;
    2205             :       bsec = (long)st->st_birthtime;
    2206             : #ifdef HAVE_STAT_TV_NSEC2
    2207             :       bnsec = st->st_birthtimespec.tv_nsec;
    2208             : #else
    2209             :       bnsec = 0;
    2210             : #endif
    2211             :       if (_stat_float_times) {
    2212             :         val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
    2213             :       } else {
    2214             :         val = PyLong_FromLong((long)bsec);
    2215             :       }
    2216             :       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
    2217             :                                 val);
    2218             :     }
    2219             : #endif
    2220             : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
    2221             :     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
    2222             :                               PyLong_FromLong((long)st->st_flags));
    2223             : #endif
    2224             : 
    2225         324 :     if (PyErr_Occurred()) {
    2226           0 :         Py_DECREF(v);
    2227           0 :         return NULL;
    2228             :     }
    2229             : 
    2230         324 :     return v;
    2231             : }
    2232             : 
    2233             : /* POSIX methods */
    2234             : 
    2235             : 
    2236             : static PyObject *
    2237         347 : posix_do_stat(char *function_name, path_t *path,
    2238             :               int dir_fd, int follow_symlinks)
    2239             : {
    2240             :     STRUCT_STAT st;
    2241             :     int result;
    2242             : 
    2243             : #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
    2244             :     if (follow_symlinks_specified(function_name, follow_symlinks))
    2245             :         return NULL;
    2246             : #endif
    2247             : 
    2248         694 :     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
    2249         694 :         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
    2250         347 :         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
    2251           0 :         return NULL;
    2252             : 
    2253         347 :     Py_BEGIN_ALLOW_THREADS
    2254         347 :     if (path->fd != -1)
    2255           0 :         result = FSTAT(path->fd, &st);
    2256             :     else
    2257             : #ifdef MS_WINDOWS
    2258             :     if (path->wide) {
    2259             :         if (follow_symlinks)
    2260             :             result = win32_stat_w(path->wide, &st);
    2261             :         else
    2262             :             result = win32_lstat_w(path->wide, &st);
    2263             :     }
    2264             :     else
    2265             : #endif
    2266             : #if defined(HAVE_LSTAT) || defined(MS_WINDOWS)
    2267         347 :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    2268          22 :         result = LSTAT(path->narrow, &st);
    2269             :     else
    2270             : #endif
    2271             : #ifdef HAVE_FSTATAT
    2272         325 :     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
    2273           0 :         result = fstatat(dir_fd, path->narrow, &st,
    2274             :                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
    2275             :     else
    2276             : #endif
    2277         325 :         result = STAT(path->narrow, &st);
    2278         347 :     Py_END_ALLOW_THREADS
    2279             : 
    2280         347 :     if (result != 0)
    2281          23 :         return path_error("stat", path);
    2282             : 
    2283         324 :     return _pystat_fromstructstat(&st);
    2284             : }
    2285             : 
    2286             : PyDoc_STRVAR(posix_stat__doc__,
    2287             : "stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result\n\n\
    2288             : Perform a stat system call on the given path.\n\
    2289             : \n\
    2290             : path may be specified as either a string or as an open file descriptor.\n\
    2291             : \n\
    2292             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    2293             :   and path should be relative; path will then be relative to that directory.\n\
    2294             :   dir_fd may not be supported on your platform; if it is unavailable, using\n\
    2295             :   it will raise a NotImplementedError.\n\
    2296             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
    2297             :   link, stat will examine the symbolic link itself instead of the file the\n\
    2298             :   link points to.\n\
    2299             : It is an error to use dir_fd or follow_symlinks when specifying path as\n\
    2300             :   an open file descriptor.");
    2301             : 
    2302             : static PyObject *
    2303         325 : posix_stat(PyObject *self, PyObject *args, PyObject *kwargs)
    2304             : {
    2305             :     static char *keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
    2306             :     path_t path;
    2307         325 :     int dir_fd = DEFAULT_DIR_FD;
    2308         325 :     int follow_symlinks = 1;
    2309             :     PyObject *return_value;
    2310             : 
    2311         325 :     memset(&path, 0, sizeof(path));
    2312         325 :     path.allow_fd = 1;
    2313         325 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", keywords,
    2314             :         path_converter, &path,
    2315             : #ifdef HAVE_FSTATAT
    2316             :         dir_fd_converter, &dir_fd,
    2317             : #else
    2318             :         dir_fd_unavailable, &dir_fd,
    2319             : #endif
    2320             :         &follow_symlinks))
    2321           0 :         return NULL;
    2322         325 :     return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
    2323         325 :     path_cleanup(&path);
    2324         325 :     return return_value;
    2325             : }
    2326             : 
    2327             : PyDoc_STRVAR(posix_lstat__doc__,
    2328             : "lstat(path, *, dir_fd=None) -> stat result\n\n\
    2329             : Like stat(), but do not follow symbolic links.\n\
    2330             : Equivalent to stat(path, follow_symlinks=False).");
    2331             : 
    2332             : static PyObject *
    2333          22 : posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs)
    2334             : {
    2335             :     static char *keywords[] = {"path", "dir_fd", NULL};
    2336             :     path_t path;
    2337          22 :     int dir_fd = DEFAULT_DIR_FD;
    2338          22 :     int follow_symlinks = 0;
    2339             :     PyObject *return_value;
    2340             : 
    2341          22 :     memset(&path, 0, sizeof(path));
    2342          22 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", keywords,
    2343             :         path_converter, &path,
    2344             : #ifdef HAVE_FSTATAT
    2345             :         dir_fd_converter, &dir_fd
    2346             : #else
    2347             :         dir_fd_unavailable, &dir_fd
    2348             : #endif
    2349             :         ))
    2350           0 :         return NULL;
    2351          22 :     return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
    2352          22 :     path_cleanup(&path);
    2353          22 :     return return_value;
    2354             : }
    2355             : 
    2356             : PyDoc_STRVAR(posix_access__doc__,
    2357             : "access(path, mode, *, dir_fd=None, effective_ids=False,\
    2358             :  follow_symlinks=True)\n\n\
    2359             : Use the real uid/gid to test for access to a path.  Returns True if granted,\n\
    2360             : False otherwise.\n\
    2361             : \n\
    2362             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    2363             :   and path should be relative; path will then be relative to that directory.\n\
    2364             : If effective_ids is True, access will use the effective uid/gid instead of\n\
    2365             :   the real uid/gid.\n\
    2366             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
    2367             :   link, access will examine the symbolic link itself instead of the file the\n\
    2368             :   link points to.\n\
    2369             : dir_fd, effective_ids, and follow_symlinks may not be implemented\n\
    2370             :   on your platform.  If they are unavailable, using them will raise a\n\
    2371             :   NotImplementedError.\n\
    2372             : \n\
    2373             : Note that most operations will use the effective uid/gid, therefore this\n\
    2374             :   routine can be used in a suid/sgid environment to test if the invoking user\n\
    2375             :   has the specified access to the path.\n\
    2376             : The mode argument can be F_OK to test existence, or the inclusive-OR\n\
    2377             :   of R_OK, W_OK, and X_OK.");
    2378             : 
    2379             : static PyObject *
    2380           2 : posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
    2381             : {
    2382             :     static char *keywords[] = {"path", "mode", "dir_fd", "effective_ids",
    2383             :                                 "follow_symlinks", NULL};
    2384             :     path_t path;
    2385             :     int mode;
    2386           2 :     int dir_fd = DEFAULT_DIR_FD;
    2387           2 :     int effective_ids = 0;
    2388           2 :     int follow_symlinks = 1;
    2389           2 :     PyObject *return_value = NULL;
    2390             : 
    2391             : #ifdef MS_WINDOWS
    2392             :     DWORD attr;
    2393             : #else
    2394             :     int result;
    2395             : #endif
    2396             : 
    2397           2 :     memset(&path, 0, sizeof(path));
    2398           2 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&pp:access", keywords,
    2399             :         path_converter, &path, &mode,
    2400             : #ifdef HAVE_FACCESSAT
    2401             :         dir_fd_converter, &dir_fd,
    2402             : #else
    2403             :         dir_fd_unavailable, &dir_fd,
    2404             : #endif
    2405             :         &effective_ids, &follow_symlinks))
    2406           0 :         return NULL;
    2407             : 
    2408             : #ifndef HAVE_FACCESSAT
    2409             :     if (follow_symlinks_specified("access", follow_symlinks))
    2410             :         goto exit;
    2411             : 
    2412             :     if (effective_ids) {
    2413             :         argument_unavailable_error("access", "effective_ids");
    2414             :         goto exit;
    2415             :     }
    2416             : #endif
    2417             : 
    2418             : #ifdef MS_WINDOWS
    2419             :     Py_BEGIN_ALLOW_THREADS
    2420             :     if (path.wide != NULL)
    2421             :         attr = GetFileAttributesW(path.wide);
    2422             :     else
    2423             :         attr = GetFileAttributesA(path.narrow);
    2424             :     Py_END_ALLOW_THREADS
    2425             : 
    2426             :     /*
    2427             :      * Access is possible if
    2428             :      *   * we didn't get a -1, and
    2429             :      *     * write access wasn't requested,
    2430             :      *     * or the file isn't read-only,
    2431             :      *     * or it's a directory.
    2432             :      * (Directories cannot be read-only on Windows.)
    2433             :     */
    2434             :     return_value = PyBool_FromLong(
    2435             :         (attr != 0xFFFFFFFF) &&
    2436             :             (!(mode & 2) ||
    2437             :             !(attr & FILE_ATTRIBUTE_READONLY) ||
    2438             :             (attr & FILE_ATTRIBUTE_DIRECTORY)));
    2439             : #else
    2440             : 
    2441           2 :     Py_BEGIN_ALLOW_THREADS
    2442             : #ifdef HAVE_FACCESSAT
    2443           2 :     if ((dir_fd != DEFAULT_DIR_FD) ||
    2444           2 :         effective_ids ||
    2445           2 :         !follow_symlinks) {
    2446           0 :         int flags = 0;
    2447           0 :         if (!follow_symlinks)
    2448           0 :             flags |= AT_SYMLINK_NOFOLLOW;
    2449           0 :         if (effective_ids)
    2450           0 :             flags |= AT_EACCESS;
    2451           0 :         result = faccessat(dir_fd, path.narrow, mode, flags);
    2452             :     }
    2453             :     else
    2454             : #endif
    2455           2 :         result = access(path.narrow, mode);
    2456           2 :     Py_END_ALLOW_THREADS
    2457           2 :     return_value = PyBool_FromLong(!result);
    2458             : #endif
    2459             : 
    2460             : #ifndef HAVE_FACCESSAT
    2461             : exit:
    2462             : #endif
    2463           2 :     path_cleanup(&path);
    2464           2 :     return return_value;
    2465             : }
    2466             : 
    2467             : #ifndef F_OK
    2468             : #define F_OK 0
    2469             : #endif
    2470             : #ifndef R_OK
    2471             : #define R_OK 4
    2472             : #endif
    2473             : #ifndef W_OK
    2474             : #define W_OK 2
    2475             : #endif
    2476             : #ifndef X_OK
    2477             : #define X_OK 1
    2478             : #endif
    2479             : 
    2480             : #ifdef HAVE_TTYNAME
    2481             : PyDoc_STRVAR(posix_ttyname__doc__,
    2482             : "ttyname(fd) -> string\n\n\
    2483             : Return the name of the terminal device connected to 'fd'.");
    2484             : 
    2485             : static PyObject *
    2486           0 : posix_ttyname(PyObject *self, PyObject *args)
    2487             : {
    2488             :     int id;
    2489             :     char *ret;
    2490             : 
    2491           0 :     if (!PyArg_ParseTuple(args, "i:ttyname", &id))
    2492           0 :         return NULL;
    2493             : 
    2494             : #if defined(__VMS)
    2495             :     /* file descriptor 0 only, the default input device (stdin) */
    2496             :     if (id == 0) {
    2497             :         ret = ttyname();
    2498             :     }
    2499             :     else {
    2500             :         ret = NULL;
    2501             :     }
    2502             : #else
    2503           0 :     ret = ttyname(id);
    2504             : #endif
    2505           0 :     if (ret == NULL)
    2506           0 :         return posix_error();
    2507           0 :     return PyUnicode_DecodeFSDefault(ret);
    2508             : }
    2509             : #endif
    2510             : 
    2511             : #ifdef HAVE_CTERMID
    2512             : PyDoc_STRVAR(posix_ctermid__doc__,
    2513             : "ctermid() -> string\n\n\
    2514             : Return the name of the controlling terminal for this process.");
    2515             : 
    2516             : static PyObject *
    2517           0 : posix_ctermid(PyObject *self, PyObject *noargs)
    2518             : {
    2519             :     char *ret;
    2520             :     char buffer[L_ctermid];
    2521             : 
    2522             : #ifdef USE_CTERMID_R
    2523             :     ret = ctermid_r(buffer);
    2524             : #else
    2525           0 :     ret = ctermid(buffer);
    2526             : #endif
    2527           0 :     if (ret == NULL)
    2528           0 :         return posix_error();
    2529           0 :     return PyUnicode_DecodeFSDefault(buffer);
    2530             : }
    2531             : #endif
    2532             : 
    2533             : PyDoc_STRVAR(posix_chdir__doc__,
    2534             : "chdir(path)\n\n\
    2535             : Change the current working directory to the specified path.\n\
    2536             : \n\
    2537             : path may always be specified as a string.\n\
    2538             : On some platforms, path may also be specified as an open file descriptor.\n\
    2539             :   If this functionality is unavailable, using it raises an exception.");
    2540             : 
    2541             : static PyObject *
    2542           0 : posix_chdir(PyObject *self, PyObject *args, PyObject *kwargs)
    2543             : {
    2544             :     path_t path;
    2545             :     int result;
    2546           0 :     PyObject *return_value = NULL;
    2547             :     static char *keywords[] = {"path", NULL};
    2548             : 
    2549           0 :     memset(&path, 0, sizeof(path));
    2550             : #ifdef HAVE_FCHDIR
    2551           0 :     path.allow_fd = 1;
    2552             : #endif
    2553           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", keywords,
    2554             :         path_converter, &path
    2555             :         ))
    2556           0 :         return NULL;
    2557             : 
    2558           0 :     Py_BEGIN_ALLOW_THREADS
    2559             : #ifdef MS_WINDOWS
    2560             :     if (path.wide)
    2561             :         result = win32_wchdir(path.wide);
    2562             :     else
    2563             :         result = win32_chdir(path.narrow);
    2564             :         result = !result; /* on unix, success = 0, on windows, success = !0 */
    2565             : #elif defined(PYOS_OS2) && defined(PYCC_GCC)
    2566             :     result = _chdir2(path.narrow);
    2567             : #else
    2568             : #ifdef HAVE_FCHDIR
    2569           0 :     if (path.fd != -1)
    2570           0 :         result = fchdir(path.fd);
    2571             :     else
    2572             : #endif
    2573           0 :         result = chdir(path.narrow);
    2574             : #endif
    2575           0 :     Py_END_ALLOW_THREADS
    2576             : 
    2577           0 :     if (result) {
    2578           0 :         return_value = path_error("chdir", &path);
    2579           0 :         goto exit;
    2580             :     }
    2581             : 
    2582           0 :     return_value = Py_None;
    2583           0 :     Py_INCREF(Py_None);
    2584             : 
    2585             : exit:
    2586           0 :     path_cleanup(&path);
    2587           0 :     return return_value;
    2588             : }
    2589             : 
    2590             : #ifdef HAVE_FCHDIR
    2591             : PyDoc_STRVAR(posix_fchdir__doc__,
    2592             : "fchdir(fd)\n\n\
    2593             : Change to the directory of the given file descriptor.  fd must be\n\
    2594             : opened on a directory, not a file.  Equivalent to os.chdir(fd).");
    2595             : 
    2596             : static PyObject *
    2597           0 : posix_fchdir(PyObject *self, PyObject *fdobj)
    2598             : {
    2599           0 :     return posix_fildes(fdobj, fchdir);
    2600             : }
    2601             : #endif /* HAVE_FCHDIR */
    2602             : 
    2603             : 
    2604             : PyDoc_STRVAR(posix_chmod__doc__,
    2605             : "chmod(path, mode, *, dir_fd=None, follow_symlinks=True)\n\n\
    2606             : Change the access permissions of a file.\n\
    2607             : \n\
    2608             : path may always be specified as a string.\n\
    2609             : On some platforms, path may also be specified as an open file descriptor.\n\
    2610             :   If this functionality is unavailable, using it raises an exception.\n\
    2611             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    2612             :   and path should be relative; path will then be relative to that directory.\n\
    2613             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
    2614             :   link, chmod will modify the symbolic link itself instead of the file the\n\
    2615             :   link points to.\n\
    2616             : It is an error to use dir_fd or follow_symlinks when specifying path as\n\
    2617             :   an open file descriptor.\n\
    2618             : dir_fd and follow_symlinks may not be implemented on your platform.\n\
    2619             :   If they are unavailable, using them will raise a NotImplementedError.");
    2620             : 
    2621             : static PyObject *
    2622           0 : posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
    2623             : {
    2624             :     path_t path;
    2625             :     int mode;
    2626           0 :     int dir_fd = DEFAULT_DIR_FD;
    2627           0 :     int follow_symlinks = 1;
    2628             :     int result;
    2629           0 :     PyObject *return_value = NULL;
    2630             :     static char *keywords[] = {"path", "mode", "dir_fd",
    2631             :                                "follow_symlinks", NULL};
    2632             : 
    2633             : #ifdef MS_WINDOWS
    2634             :     DWORD attr;
    2635             : #endif
    2636             : 
    2637             : #ifdef HAVE_FCHMODAT
    2638           0 :     int fchmodat_nofollow_unsupported = 0;
    2639             : #endif
    2640             : 
    2641           0 :     memset(&path, 0, sizeof(path));
    2642             : #ifdef HAVE_FCHMOD
    2643           0 :     path.allow_fd = 1;
    2644             : #endif
    2645           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", keywords,
    2646             :         path_converter, &path,
    2647             :         &mode,
    2648             : #ifdef HAVE_FCHMODAT
    2649             :         dir_fd_converter, &dir_fd,
    2650             : #else
    2651             :         dir_fd_unavailable, &dir_fd,
    2652             : #endif
    2653             :         &follow_symlinks))
    2654           0 :         return NULL;
    2655             : 
    2656             : #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
    2657             :     if (follow_symlinks_specified("chmod", follow_symlinks))
    2658             :         goto exit;
    2659             : #endif
    2660             : 
    2661             : #ifdef MS_WINDOWS
    2662             :     Py_BEGIN_ALLOW_THREADS
    2663             :     if (path.wide)
    2664             :         attr = GetFileAttributesW(path.wide);
    2665             :     else
    2666             :         attr = GetFileAttributesA(path.narrow);
    2667             :     if (attr == 0xFFFFFFFF)
    2668             :         result = 0;
    2669             :     else {
    2670             :         if (mode & _S_IWRITE)
    2671             :             attr &= ~FILE_ATTRIBUTE_READONLY;
    2672             :         else
    2673             :             attr |= FILE_ATTRIBUTE_READONLY;
    2674             :         if (path.wide)
    2675             :             result = SetFileAttributesW(path.wide, attr);
    2676             :         else
    2677             :             result = SetFileAttributesA(path.narrow, attr);
    2678             :     }
    2679             :     Py_END_ALLOW_THREADS
    2680             : 
    2681             :     if (!result) {
    2682             :         return_value = win32_error_object("chmod", path.object);
    2683             :         goto exit;
    2684             :     }
    2685             : #else /* MS_WINDOWS */
    2686           0 :     Py_BEGIN_ALLOW_THREADS
    2687             : #ifdef HAVE_FCHMOD
    2688           0 :     if (path.fd != -1)
    2689           0 :         result = fchmod(path.fd, mode);
    2690             :     else
    2691             : #endif
    2692             : #ifdef HAVE_LCHMOD
    2693             :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    2694             :         result = lchmod(path.narrow, mode);
    2695             :     else
    2696             : #endif
    2697             : #ifdef HAVE_FCHMODAT
    2698           0 :     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
    2699             :         /*
    2700             :          * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
    2701             :          * The documentation specifically shows how to use it,
    2702             :          * and then says it isn't implemented yet.
    2703             :          * (true on linux with glibc 2.15, and openindiana 3.x)
    2704             :          *
    2705             :          * Once it is supported, os.chmod will automatically
    2706             :          * support dir_fd and follow_symlinks=False.  (Hopefully.)
    2707             :          * Until then, we need to be careful what exception we raise.
    2708             :          */
    2709           0 :         result = fchmodat(dir_fd, path.narrow, mode,
    2710           0 :                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
    2711             :         /*
    2712             :          * But wait!  We can't throw the exception without allowing threads,
    2713             :          * and we can't do that in this nested scope.  (Macro trickery, sigh.)
    2714             :          */
    2715           0 :         fchmodat_nofollow_unsupported =
    2716           0 :                          result &&
    2717           0 :                          ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
    2718           0 :                          !follow_symlinks;
    2719             :     }
    2720             :     else
    2721             : #endif
    2722           0 :         result = chmod(path.narrow, mode);
    2723           0 :     Py_END_ALLOW_THREADS
    2724             : 
    2725           0 :     if (result) {
    2726             : #ifdef HAVE_FCHMODAT
    2727           0 :         if (fchmodat_nofollow_unsupported) {
    2728           0 :             if (dir_fd != DEFAULT_DIR_FD)
    2729           0 :                 dir_fd_and_follow_symlinks_invalid("chmod",
    2730             :                                                    dir_fd, follow_symlinks);
    2731             :             else
    2732           0 :                 follow_symlinks_specified("chmod", follow_symlinks);
    2733             :         }
    2734             :         else
    2735             : #endif
    2736           0 :             return_value = path_error("chmod", &path);
    2737           0 :         goto exit;
    2738             :     }
    2739             : #endif
    2740             : 
    2741           0 :     Py_INCREF(Py_None);
    2742           0 :     return_value = Py_None;
    2743             : exit:
    2744           0 :     path_cleanup(&path);
    2745           0 :     return return_value;
    2746             : }
    2747             : 
    2748             : 
    2749             : #ifdef HAVE_FCHMOD
    2750             : PyDoc_STRVAR(posix_fchmod__doc__,
    2751             : "fchmod(fd, mode)\n\n\
    2752             : Change the access permissions of the file given by file\n\
    2753             : descriptor fd.  Equivalent to os.chmod(fd, mode).");
    2754             : 
    2755             : static PyObject *
    2756           0 : posix_fchmod(PyObject *self, PyObject *args)
    2757             : {
    2758             :     int fd, mode, res;
    2759           0 :     if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
    2760           0 :         return NULL;
    2761           0 :     Py_BEGIN_ALLOW_THREADS
    2762           0 :     res = fchmod(fd, mode);
    2763           0 :     Py_END_ALLOW_THREADS
    2764           0 :     if (res < 0)
    2765           0 :         return posix_error();
    2766           0 :     Py_RETURN_NONE;
    2767             : }
    2768             : #endif /* HAVE_FCHMOD */
    2769             : 
    2770             : #ifdef HAVE_LCHMOD
    2771             : PyDoc_STRVAR(posix_lchmod__doc__,
    2772             : "lchmod(path, mode)\n\n\
    2773             : Change the access permissions of a file. If path is a symlink, this\n\
    2774             : affects the link itself rather than the target.\n\
    2775             : Equivalent to chmod(path, mode, follow_symlinks=False).");
    2776             : 
    2777             : static PyObject *
    2778             : posix_lchmod(PyObject *self, PyObject *args)
    2779             : {
    2780             :     PyObject *opath;
    2781             :     char *path;
    2782             :     int i;
    2783             :     int res;
    2784             :     if (!PyArg_ParseTuple(args, "O&i:lchmod", PyUnicode_FSConverter,
    2785             :                           &opath, &i))
    2786             :         return NULL;
    2787             :     path = PyBytes_AsString(opath);
    2788             :     Py_BEGIN_ALLOW_THREADS
    2789             :     res = lchmod(path, i);
    2790             :     Py_END_ALLOW_THREADS
    2791             :     if (res < 0)
    2792             :         return posix_error_with_allocated_filename(opath);
    2793             :     Py_DECREF(opath);
    2794             :     Py_RETURN_NONE;
    2795             : }
    2796             : #endif /* HAVE_LCHMOD */
    2797             : 
    2798             : 
    2799             : #ifdef HAVE_CHFLAGS
    2800             : PyDoc_STRVAR(posix_chflags__doc__,
    2801             : "chflags(path, flags, *, follow_symlinks=True)\n\n\
    2802             : Set file flags.\n\
    2803             : \n\
    2804             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
    2805             :   link, chflags will change flags on the symbolic link itself instead of the\n\
    2806             :   file the link points to.\n\
    2807             : follow_symlinks may not be implemented on your platform.  If it is\n\
    2808             : unavailable, using it will raise a NotImplementedError.");
    2809             : 
    2810             : static PyObject *
    2811             : posix_chflags(PyObject *self, PyObject *args, PyObject *kwargs)
    2812             : {
    2813             :     path_t path;
    2814             :     unsigned long flags;
    2815             :     int follow_symlinks = 1;
    2816             :     int result;
    2817             :     PyObject *return_value;
    2818             :     static char *keywords[] = {"path", "flags", "follow_symlinks", NULL};
    2819             : 
    2820             :     memset(&path, 0, sizeof(path));
    2821             :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|$i:chflags", keywords,
    2822             :                           path_converter, &path,
    2823             :                           &flags, &follow_symlinks))
    2824             :         return NULL;
    2825             : 
    2826             : #ifndef HAVE_LCHFLAGS
    2827             :     if (follow_symlinks_specified("chflags", follow_symlinks))
    2828             :         goto exit;
    2829             : #endif
    2830             : 
    2831             :     Py_BEGIN_ALLOW_THREADS
    2832             : #ifdef HAVE_LCHFLAGS
    2833             :     if (!follow_symlinks)
    2834             :         result = lchflags(path.narrow, flags);
    2835             :     else
    2836             : #endif
    2837             :         result = chflags(path.narrow, flags);
    2838             :     Py_END_ALLOW_THREADS
    2839             : 
    2840             :     if (result) {
    2841             :         return_value = path_posix_error("chflags", &path);
    2842             :         goto exit;
    2843             :     }
    2844             : 
    2845             :     return_value = Py_None;
    2846             :     Py_INCREF(Py_None);
    2847             : 
    2848             : exit:
    2849             :     path_cleanup(&path);
    2850             :     return return_value;
    2851             : }
    2852             : #endif /* HAVE_CHFLAGS */
    2853             : 
    2854             : #ifdef HAVE_LCHFLAGS
    2855             : PyDoc_STRVAR(posix_lchflags__doc__,
    2856             : "lchflags(path, flags)\n\n\
    2857             : Set file flags.\n\
    2858             : This function will not follow symbolic links.\n\
    2859             : Equivalent to chflags(path, flags, follow_symlinks=False).");
    2860             : 
    2861             : static PyObject *
    2862             : posix_lchflags(PyObject *self, PyObject *args)
    2863             : {
    2864             :     PyObject *opath;
    2865             :     char *path;
    2866             :     unsigned long flags;
    2867             :     int res;
    2868             :     if (!PyArg_ParseTuple(args, "O&k:lchflags",
    2869             :                           PyUnicode_FSConverter, &opath, &flags))
    2870             :         return NULL;
    2871             :     path = PyBytes_AsString(opath);
    2872             :     Py_BEGIN_ALLOW_THREADS
    2873             :     res = lchflags(path, flags);
    2874             :     Py_END_ALLOW_THREADS
    2875             :     if (res < 0)
    2876             :         return posix_error_with_allocated_filename(opath);
    2877             :     Py_DECREF(opath);
    2878             :     Py_INCREF(Py_None);
    2879             :     return Py_None;
    2880             : }
    2881             : #endif /* HAVE_LCHFLAGS */
    2882             : 
    2883             : #ifdef HAVE_CHROOT
    2884             : PyDoc_STRVAR(posix_chroot__doc__,
    2885             : "chroot(path)\n\n\
    2886             : Change root directory to path.");
    2887             : 
    2888             : static PyObject *
    2889           0 : posix_chroot(PyObject *self, PyObject *args)
    2890             : {
    2891           0 :     return posix_1str(args, "O&:chroot", chroot);
    2892             : }
    2893             : #endif
    2894             : 
    2895             : #ifdef HAVE_FSYNC
    2896             : PyDoc_STRVAR(posix_fsync__doc__,
    2897             : "fsync(fildes)\n\n\
    2898             : force write of file with filedescriptor to disk.");
    2899             : 
    2900             : static PyObject *
    2901           0 : posix_fsync(PyObject *self, PyObject *fdobj)
    2902             : {
    2903           0 :     return posix_fildes(fdobj, fsync);
    2904             : }
    2905             : #endif /* HAVE_FSYNC */
    2906             : 
    2907             : #ifdef HAVE_SYNC
    2908             : PyDoc_STRVAR(posix_sync__doc__,
    2909             : "sync()\n\n\
    2910             : Force write of everything to disk.");
    2911             : 
    2912             : static PyObject *
    2913           0 : posix_sync(PyObject *self, PyObject *noargs)
    2914             : {
    2915           0 :     Py_BEGIN_ALLOW_THREADS
    2916           0 :     sync();
    2917           0 :     Py_END_ALLOW_THREADS
    2918           0 :     Py_RETURN_NONE;
    2919             : }
    2920             : #endif
    2921             : 
    2922             : #ifdef HAVE_FDATASYNC
    2923             : 
    2924             : #ifdef __hpux
    2925             : extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
    2926             : #endif
    2927             : 
    2928             : PyDoc_STRVAR(posix_fdatasync__doc__,
    2929             : "fdatasync(fildes)\n\n\
    2930             : force write of file with filedescriptor to disk.\n\
    2931             :  does not force update of metadata.");
    2932             : 
    2933             : static PyObject *
    2934           0 : posix_fdatasync(PyObject *self, PyObject *fdobj)
    2935             : {
    2936           0 :     return posix_fildes(fdobj, fdatasync);
    2937             : }
    2938             : #endif /* HAVE_FDATASYNC */
    2939             : 
    2940             : 
    2941             : #ifdef HAVE_CHOWN
    2942             : PyDoc_STRVAR(posix_chown__doc__,
    2943             : "chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n\n\
    2944             : Change the owner and group id of path to the numeric uid and gid.\n\
    2945             : \n\
    2946             : path may always be specified as a string.\n\
    2947             : On some platforms, path may also be specified as an open file descriptor.\n\
    2948             :   If this functionality is unavailable, using it raises an exception.\n\
    2949             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    2950             :   and path should be relative; path will then be relative to that directory.\n\
    2951             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
    2952             :   link, chown will modify the symbolic link itself instead of the file the\n\
    2953             :   link points to.\n\
    2954             : It is an error to use dir_fd or follow_symlinks when specifying path as\n\
    2955             :   an open file descriptor.\n\
    2956             : dir_fd and follow_symlinks may not be implemented on your platform.\n\
    2957             :   If they are unavailable, using them will raise a NotImplementedError.");
    2958             : 
    2959             : static PyObject *
    2960           0 : posix_chown(PyObject *self, PyObject *args, PyObject *kwargs)
    2961             : {
    2962             :     path_t path;
    2963             :     long uid_l, gid_l;
    2964             :     uid_t uid;
    2965             :     gid_t gid;
    2966           0 :     int dir_fd = DEFAULT_DIR_FD;
    2967           0 :     int follow_symlinks = 1;
    2968             :     int result;
    2969           0 :     PyObject *return_value = NULL;
    2970             :     static char *keywords[] = {"path", "uid", "gid", "dir_fd",
    2971             :                                "follow_symlinks", NULL};
    2972             : 
    2973           0 :     memset(&path, 0, sizeof(path));
    2974             : #ifdef HAVE_FCHOWN
    2975           0 :     path.allow_fd = 1;
    2976             : #endif
    2977           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&ll|$O&p:chown", keywords,
    2978             :                                      path_converter, &path,
    2979             :                                      &uid_l, &gid_l,
    2980             : #ifdef HAVE_FCHOWNAT
    2981             :                                      dir_fd_converter, &dir_fd,
    2982             : #else
    2983             :                                      dir_fd_unavailable, &dir_fd,
    2984             : #endif
    2985             :                                      &follow_symlinks))
    2986           0 :         return NULL;
    2987             : 
    2988             : #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
    2989             :     if (follow_symlinks_specified("chown", follow_symlinks))
    2990             :         goto exit;
    2991             : #endif
    2992           0 :     if (dir_fd_and_fd_invalid("chown", dir_fd, path.fd) ||
    2993           0 :         fd_and_follow_symlinks_invalid("chown", path.fd, follow_symlinks))
    2994             :         goto exit;
    2995             : 
    2996             : #ifdef __APPLE__
    2997             :     /*
    2998             :      * This is for Mac OS X 10.3, which doesn't have lchown.
    2999             :      * (But we still have an lchown symbol because of weak-linking.)
    3000             :      * It doesn't have fchownat either.  So there's no possibility
    3001             :      * of a graceful failover.
    3002             :      */
    3003             :     if ((!follow_symlinks) && (lchown == NULL)) {
    3004             :         follow_symlinks_specified("chown", follow_symlinks);
    3005             :         goto exit;
    3006             :     }
    3007             : #endif
    3008             : 
    3009           0 :     Py_BEGIN_ALLOW_THREADS
    3010           0 :     uid = (uid_t)uid_l;
    3011           0 :     gid = (uid_t)gid_l;
    3012             : #ifdef HAVE_FCHOWN
    3013           0 :     if (path.fd != -1)
    3014           0 :         result = fchown(path.fd, uid, gid);
    3015             :     else
    3016             : #endif
    3017             : #ifdef HAVE_LCHOWN
    3018           0 :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    3019           0 :         result = lchown(path.narrow, uid, gid);
    3020             :     else
    3021             : #endif
    3022             : #ifdef HAVE_FCHOWNAT
    3023           0 :     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
    3024           0 :         result = fchownat(dir_fd, path.narrow, uid, gid,
    3025           0 :                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
    3026             :     else
    3027             : #endif
    3028           0 :         result = chown(path.narrow, uid, gid);
    3029           0 :     Py_END_ALLOW_THREADS
    3030             : 
    3031           0 :     if (result) {
    3032           0 :         return_value = path_posix_error("chown", &path);
    3033           0 :         goto exit;
    3034             :     }
    3035             : 
    3036           0 :     return_value = Py_None;
    3037           0 :     Py_INCREF(Py_None);
    3038             : 
    3039             : exit:
    3040           0 :     path_cleanup(&path);
    3041           0 :     return return_value;
    3042             : }
    3043             : #endif /* HAVE_CHOWN */
    3044             : 
    3045             : #ifdef HAVE_FCHOWN
    3046             : PyDoc_STRVAR(posix_fchown__doc__,
    3047             : "fchown(fd, uid, gid)\n\n\
    3048             : Change the owner and group id of the file given by file descriptor\n\
    3049             : fd to the numeric uid and gid.  Equivalent to os.chown(fd, uid, gid).");
    3050             : 
    3051             : static PyObject *
    3052           0 : posix_fchown(PyObject *self, PyObject *args)
    3053             : {
    3054             :     int fd;
    3055             :     long uid, gid;
    3056             :     int res;
    3057           0 :     if (!PyArg_ParseTuple(args, "ill:fchown", &fd, &uid, &gid))
    3058           0 :         return NULL;
    3059           0 :     Py_BEGIN_ALLOW_THREADS
    3060           0 :     res = fchown(fd, (uid_t) uid, (gid_t) gid);
    3061           0 :     Py_END_ALLOW_THREADS
    3062           0 :     if (res < 0)
    3063           0 :         return posix_error();
    3064           0 :     Py_RETURN_NONE;
    3065             : }
    3066             : #endif /* HAVE_FCHOWN */
    3067             : 
    3068             : #ifdef HAVE_LCHOWN
    3069             : PyDoc_STRVAR(posix_lchown__doc__,
    3070             : "lchown(path, uid, gid)\n\n\
    3071             : Change the owner and group id of path to the numeric uid and gid.\n\
    3072             : This function will not follow symbolic links.\n\
    3073             : Equivalent to os.chown(path, uid, gid, follow_symlinks=False).");
    3074             : 
    3075             : static PyObject *
    3076           0 : posix_lchown(PyObject *self, PyObject *args)
    3077             : {
    3078             :     PyObject *opath;
    3079             :     char *path;
    3080             :     long uid, gid;
    3081             :     int res;
    3082           0 :     if (!PyArg_ParseTuple(args, "O&ll:lchown",
    3083             :                           PyUnicode_FSConverter, &opath,
    3084             :                           &uid, &gid))
    3085           0 :         return NULL;
    3086           0 :     path = PyBytes_AsString(opath);
    3087           0 :     Py_BEGIN_ALLOW_THREADS
    3088           0 :     res = lchown(path, (uid_t) uid, (gid_t) gid);
    3089           0 :     Py_END_ALLOW_THREADS
    3090           0 :     if (res < 0)
    3091           0 :         return posix_error_with_allocated_filename(opath);
    3092           0 :     Py_DECREF(opath);
    3093           0 :     Py_INCREF(Py_None);
    3094           0 :     return Py_None;
    3095             : }
    3096             : #endif /* HAVE_LCHOWN */
    3097             : 
    3098             : 
    3099             : #ifdef HAVE_GETCWD
    3100             : static PyObject *
    3101           2 : posix_getcwd(int use_bytes)
    3102             : {
    3103             :     char buf[1026];
    3104             :     char *res;
    3105             : 
    3106             : #ifdef MS_WINDOWS
    3107             :     if (!use_bytes) {
    3108             :         wchar_t wbuf[1026];
    3109             :         wchar_t *wbuf2 = wbuf;
    3110             :         PyObject *resobj;
    3111             :         DWORD len;
    3112             :         Py_BEGIN_ALLOW_THREADS
    3113             :         len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
    3114             :         /* If the buffer is large enough, len does not include the
    3115             :            terminating \0. If the buffer is too small, len includes
    3116             :            the space needed for the terminator. */
    3117             :         if (len >= sizeof wbuf/ sizeof wbuf[0]) {
    3118             :             wbuf2 = malloc(len * sizeof(wchar_t));
    3119             :             if (wbuf2)
    3120             :                 len = GetCurrentDirectoryW(len, wbuf2);
    3121             :         }
    3122             :         Py_END_ALLOW_THREADS
    3123             :         if (!wbuf2) {
    3124             :             PyErr_NoMemory();
    3125             :             return NULL;
    3126             :         }
    3127             :         if (!len) {
    3128             :             if (wbuf2 != wbuf) free(wbuf2);
    3129             :             return win32_error("getcwdu", NULL);
    3130             :         }
    3131             :         resobj = PyUnicode_FromWideChar(wbuf2, len);
    3132             :         if (wbuf2 != wbuf) free(wbuf2);
    3133             :         return resobj;
    3134             :     }
    3135             : 
    3136             :     if (win32_warn_bytes_api())
    3137             :         return NULL;
    3138             : #endif
    3139             : 
    3140           2 :     Py_BEGIN_ALLOW_THREADS
    3141             : #if defined(PYOS_OS2) && defined(PYCC_GCC)
    3142             :     res = _getcwd2(buf, sizeof buf);
    3143             : #else
    3144           2 :     res = getcwd(buf, sizeof buf);
    3145             : #endif
    3146           2 :     Py_END_ALLOW_THREADS
    3147           2 :     if (res == NULL)
    3148           0 :         return posix_error();
    3149           2 :     if (use_bytes)
    3150           0 :         return PyBytes_FromStringAndSize(buf, strlen(buf));
    3151           2 :     return PyUnicode_DecodeFSDefault(buf);
    3152             : }
    3153             : 
    3154             : PyDoc_STRVAR(posix_getcwd__doc__,
    3155             : "getcwd() -> path\n\n\
    3156             : Return a unicode string representing the current working directory.");
    3157             : 
    3158             : static PyObject *
    3159           2 : posix_getcwd_unicode(PyObject *self)
    3160             : {
    3161           2 :     return posix_getcwd(0);
    3162             : }
    3163             : 
    3164             : PyDoc_STRVAR(posix_getcwdb__doc__,
    3165             : "getcwdb() -> path\n\n\
    3166             : Return a bytes string representing the current working directory.");
    3167             : 
    3168             : static PyObject *
    3169           0 : posix_getcwd_bytes(PyObject *self)
    3170             : {
    3171           0 :     return posix_getcwd(1);
    3172             : }
    3173             : #endif
    3174             : 
    3175             : #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
    3176             : #define HAVE_LINK 1
    3177             : #endif
    3178             : 
    3179             : #ifdef HAVE_LINK
    3180             : PyDoc_STRVAR(posix_link__doc__,
    3181             : "link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True)\n\n\
    3182             : Create a hard link to a file.\n\
    3183             : \n\
    3184             : If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
    3185             :   descriptor open to a directory, and the respective path string (src or dst)\n\
    3186             :   should be relative; the path will then be relative to that directory.\n\
    3187             : If follow_symlinks is False, and the last element of src is a symbolic\n\
    3188             :   link, link will create a link to the symbolic link itself instead of the\n\
    3189             :   file the link points to.\n\
    3190             : src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n\
    3191             :   platform.  If they are unavailable, using them will raise a\n\
    3192             :   NotImplementedError.");
    3193             : 
    3194             : static PyObject *
    3195           0 : posix_link(PyObject *self, PyObject *args, PyObject *kwargs)
    3196             : {
    3197             :     path_t src, dst;
    3198           0 :     int src_dir_fd = DEFAULT_DIR_FD;
    3199           0 :     int dst_dir_fd = DEFAULT_DIR_FD;
    3200           0 :     int follow_symlinks = 1;
    3201           0 :     PyObject *return_value = NULL;
    3202             :     static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd",
    3203             :                                "follow_symlinks", NULL};
    3204             : #ifdef MS_WINDOWS
    3205             :     BOOL result;
    3206             : #else
    3207             :     int result;
    3208             : #endif
    3209             : 
    3210           0 :     memset(&src, 0, sizeof(src));
    3211           0 :     memset(&dst, 0, sizeof(dst));
    3212           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|O&O&p:link", keywords,
    3213             :             path_converter, &src,
    3214             :             path_converter, &dst,
    3215             :             dir_fd_converter, &src_dir_fd,
    3216             :             dir_fd_converter, &dst_dir_fd,
    3217             :             &follow_symlinks))
    3218           0 :         return NULL;
    3219             : 
    3220             : #ifndef HAVE_LINKAT
    3221             :     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
    3222             :         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
    3223             :         goto exit;
    3224             :     }
    3225             : #endif
    3226             : 
    3227           0 :     if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
    3228           0 :         PyErr_SetString(PyExc_NotImplementedError,
    3229             :                         "link: src and dst must be the same type");
    3230           0 :         goto exit;
    3231             :     }
    3232             : 
    3233             : #ifdef MS_WINDOWS
    3234             :     Py_BEGIN_ALLOW_THREADS
    3235             :     if (src.wide)
    3236             :         result = CreateHardLinkW(dst.wide, src.wide, NULL);
    3237             :     else
    3238             :         result = CreateHardLinkA(dst.narrow, src.narrow, NULL);
    3239             :     Py_END_ALLOW_THREADS
    3240             : 
    3241             :     if (!result) {
    3242             :         return_value = win32_error_object("link", dst.object);
    3243             :         goto exit;
    3244             :     }
    3245             : #else
    3246           0 :     Py_BEGIN_ALLOW_THREADS
    3247             : #ifdef HAVE_LINKAT
    3248           0 :     if ((src_dir_fd != DEFAULT_DIR_FD) ||
    3249           0 :         (dst_dir_fd != DEFAULT_DIR_FD) ||
    3250           0 :         (!follow_symlinks))
    3251           0 :         result = linkat(src_dir_fd, src.narrow,
    3252           0 :             dst_dir_fd, dst.narrow,
    3253           0 :             follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
    3254             :     else
    3255             : #endif
    3256           0 :         result = link(src.narrow, dst.narrow);
    3257           0 :     Py_END_ALLOW_THREADS
    3258             : 
    3259           0 :     if (result) {
    3260           0 :         return_value = path_error("link", &dst);
    3261           0 :         goto exit;
    3262             :     }
    3263             : #endif
    3264             : 
    3265           0 :     return_value = Py_None;
    3266           0 :     Py_INCREF(Py_None);
    3267             : 
    3268             : exit:
    3269           0 :     path_cleanup(&src);
    3270           0 :     path_cleanup(&dst);
    3271           0 :     return return_value;
    3272             : }
    3273             : #endif
    3274             : 
    3275             : 
    3276             : 
    3277             : PyDoc_STRVAR(posix_listdir__doc__,
    3278             : "listdir(path='.') -> list_of_filenames\n\n\
    3279             : Return a list containing the names of the files in the directory.\n\
    3280             : The list is in arbitrary order.  It does not include the special\n\
    3281             : entries '.' and '..' even if they are present in the directory.\n\
    3282             : \n\
    3283             : path can be specified as either str or bytes.  If path is bytes,\n\
    3284             :   the filenames returned will also be bytes; in all other circumstances\n\
    3285             :   the filenames returned will be str.\n\
    3286             : On some platforms, path may also be specified as an open file descriptor;\n\
    3287             :   the file descriptor must refer to a directory.\n\
    3288             :   If this functionality is unavailable, using it raises NotImplementedError.");
    3289             : 
    3290             : static PyObject *
    3291          11 : posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
    3292             : {
    3293             :     path_t path;
    3294          11 :     PyObject *list = NULL;
    3295             :     static char *keywords[] = {"path", NULL};
    3296          11 :     int fd = -1;
    3297             : 
    3298             : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
    3299             :     PyObject *v;
    3300             :     HANDLE hFindFile = INVALID_HANDLE_VALUE;
    3301             :     BOOL result;
    3302             :     WIN32_FIND_DATA FileData;
    3303             :     char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
    3304             :     char *bufptr = namebuf;
    3305             :     /* only claim to have space for MAX_PATH */
    3306             :     Py_ssize_t len = sizeof(namebuf)-5;
    3307             :     PyObject *po = NULL;
    3308             :     wchar_t *wnamebuf = NULL;
    3309             : #elif defined(PYOS_OS2)
    3310             : #ifndef MAX_PATH
    3311             : #define MAX_PATH    CCHMAXPATH
    3312             : #endif
    3313             :     char *pt;
    3314             :     PyObject *v;
    3315             :     char namebuf[MAX_PATH+5];
    3316             :     HDIR  hdir = 1;
    3317             :     ULONG srchcnt = 1;
    3318             :     FILEFINDBUF3   ep;
    3319             :     APIRET rc;
    3320             : #else
    3321             :     PyObject *v;
    3322          11 :     DIR *dirp = NULL;
    3323             :     struct dirent *ep;
    3324             :     int return_str; /* if false, return bytes */
    3325             : #endif
    3326             : 
    3327          11 :     memset(&path, 0, sizeof(path));
    3328          11 :     path.nullable = 1;
    3329             : #ifdef HAVE_FDOPENDIR
    3330          11 :     path.allow_fd = 1;
    3331          11 :     path.fd = -1;
    3332             : #endif
    3333          11 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", keywords,
    3334             :         path_converter, &path
    3335             :         ))
    3336           0 :         return NULL;
    3337             : 
    3338             :     /* XXX Should redo this putting the (now four) versions of opendir
    3339             :        in separate files instead of having them all here... */
    3340             : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
    3341             :     if (!path.narrow) {
    3342             :         WIN32_FIND_DATAW wFileData;
    3343             :         wchar_t *po_wchars;
    3344             : 
    3345             :         if (!path.wide) { /* Default arg: "." */
    3346             :             po_wchars = L".";
    3347             :             len = 1;
    3348             :         } else {
    3349             :             po_wchars = path.wide;
    3350             :             len = wcslen(path.wide);
    3351             :         }
    3352             :         /* The +5 is so we can append "\\*.*\0" */
    3353             :         wnamebuf = malloc((len + 5) * sizeof(wchar_t));
    3354             :         if (!wnamebuf) {
    3355             :             PyErr_NoMemory();
    3356             :             goto exit;
    3357             :         }
    3358             :         wcscpy(wnamebuf, po_wchars);
    3359             :         if (len > 0) {
    3360             :             wchar_t wch = wnamebuf[len-1];
    3361             :             if (wch != L'/' && wch != L'\\' && wch != L':')
    3362             :                 wnamebuf[len++] = L'\\';
    3363             :             wcscpy(wnamebuf + len, L"*.*");
    3364             :         }
    3365             :         if ((list = PyList_New(0)) == NULL) {
    3366             :             goto exit;
    3367             :         }
    3368             :         Py_BEGIN_ALLOW_THREADS
    3369             :         hFindFile = FindFirstFileW(wnamebuf, &wFileData);
    3370             :         Py_END_ALLOW_THREADS
    3371             :         if (hFindFile == INVALID_HANDLE_VALUE) {
    3372             :             int error = GetLastError();
    3373             :             if (error == ERROR_FILE_NOT_FOUND)
    3374             :                 goto exit;
    3375             :             Py_DECREF(list);
    3376             :             list = NULL;
    3377             :             win32_error_unicode("FindFirstFileW", wnamebuf);
    3378             :             goto exit;
    3379             :         }
    3380             :         do {
    3381             :             /* Skip over . and .. */
    3382             :             if (wcscmp(wFileData.cFileName, L".") != 0 &&
    3383             :                 wcscmp(wFileData.cFileName, L"..") != 0) {
    3384             :                 v = PyUnicode_FromWideChar(wFileData.cFileName,
    3385             :                                            wcslen(wFileData.cFileName));
    3386             :                 if (v == NULL) {
    3387             :                     Py_DECREF(list);
    3388             :                     list = NULL;
    3389             :                     break;
    3390             :                 }
    3391             :                 if (PyList_Append(list, v) != 0) {
    3392             :                     Py_DECREF(v);
    3393             :                     Py_DECREF(list);
    3394             :                     list = NULL;
    3395             :                     break;
    3396             :                 }
    3397             :                 Py_DECREF(v);
    3398             :             }
    3399             :             Py_BEGIN_ALLOW_THREADS
    3400             :             result = FindNextFileW(hFindFile, &wFileData);
    3401             :             Py_END_ALLOW_THREADS
    3402             :             /* FindNextFile sets error to ERROR_NO_MORE_FILES if
    3403             :                it got to the end of the directory. */
    3404             :             if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
    3405             :                 Py_DECREF(list);
    3406             :                 list = win32_error_unicode("FindNextFileW", wnamebuf);
    3407             :                 goto exit;
    3408             :             }
    3409             :         } while (result == TRUE);
    3410             : 
    3411             :         goto exit;
    3412             :     }
    3413             :     strcpy(namebuf, path.narrow);
    3414             :     len = path.length;
    3415             :     if (len > 0) {
    3416             :         char ch = namebuf[len-1];
    3417             :         if (ch != SEP && ch != ALTSEP && ch != ':')
    3418             :             namebuf[len++] = '/';
    3419             :         strcpy(namebuf + len, "*.*");
    3420             :     }
    3421             : 
    3422             :     if ((list = PyList_New(0)) == NULL)
    3423             :         return NULL;
    3424             : 
    3425             :     Py_BEGIN_ALLOW_THREADS
    3426             :     hFindFile = FindFirstFile(namebuf, &FileData);
    3427             :     Py_END_ALLOW_THREADS
    3428             :     if (hFindFile == INVALID_HANDLE_VALUE) {
    3429             :         int error = GetLastError();
    3430             :         if (error == ERROR_FILE_NOT_FOUND)
    3431             :             goto exit;
    3432             :         Py_DECREF(list);
    3433             :         list = win32_error("FindFirstFile", namebuf);
    3434             :         goto exit;
    3435             :     }
    3436             :     do {
    3437             :         /* Skip over . and .. */
    3438             :         if (strcmp(FileData.cFileName, ".") != 0 &&
    3439             :             strcmp(FileData.cFileName, "..") != 0) {
    3440             :             v = PyBytes_FromString(FileData.cFileName);
    3441             :             if (v == NULL) {
    3442             :                 Py_DECREF(list);
    3443             :                 list = NULL;
    3444             :                 break;
    3445             :             }
    3446             :             if (PyList_Append(list, v) != 0) {
    3447             :                 Py_DECREF(v);
    3448             :                 Py_DECREF(list);
    3449             :                 list = NULL;
    3450             :                 break;
    3451             :             }
    3452             :             Py_DECREF(v);
    3453             :         }
    3454             :         Py_BEGIN_ALLOW_THREADS
    3455             :         result = FindNextFile(hFindFile, &FileData);
    3456             :         Py_END_ALLOW_THREADS
    3457             :         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
    3458             :            it got to the end of the directory. */
    3459             :         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
    3460             :             Py_DECREF(list);
    3461             :             list = win32_error("FindNextFile", namebuf);
    3462             :             goto exit;
    3463             :         }
    3464             :     } while (result == TRUE);
    3465             : 
    3466             : exit:
    3467             :     if (hFindFile != INVALID_HANDLE_VALUE) {
    3468             :         if (FindClose(hFindFile) == FALSE) {
    3469             :             if (list != NULL) {
    3470             :                 Py_DECREF(list);
    3471             :                 list = win32_error_object("FindClose", path.object);
    3472             :             }
    3473             :         }
    3474             :     }
    3475             :     if (wnamebuf)
    3476             :         free(wnamebuf);
    3477             :     path_cleanup(&path);
    3478             : 
    3479             :     return list;
    3480             : 
    3481             : #elif defined(PYOS_OS2)
    3482             :     if (path.length >= MAX_PATH) {
    3483             :         PyErr_SetString(PyExc_ValueError, "path too long");
    3484             :         goto exit;
    3485             :     }
    3486             :     strcpy(namebuf, path.narrow);
    3487             :     for (pt = namebuf; *pt; pt++)
    3488             :         if (*pt == ALTSEP)
    3489             :             *pt = SEP;
    3490             :     if (namebuf[len-1] != SEP)
    3491             :         namebuf[len++] = SEP;
    3492             :     strcpy(namebuf + len, "*.*");
    3493             : 
    3494             :     if ((list = PyList_New(0)) == NULL) {
    3495             :         goto exit;
    3496             :     }
    3497             : 
    3498             :     rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
    3499             :                       &hdir,           /* Handle to Use While Search Directory */
    3500             :                       FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
    3501             :                       &ep, sizeof(ep), /* Structure to Receive Directory Entry */
    3502             :                       &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
    3503             :                       FIL_STANDARD);   /* Format of Entry (EAs or Not) */
    3504             : 
    3505             :     if (rc != NO_ERROR) {
    3506             :         errno = ENOENT;
    3507             :         Py_DECREF(list);
    3508             :         list = posix_error_with_filename(path.narrow);
    3509             :         goto exit;
    3510             :     }
    3511             : 
    3512             :     if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
    3513             :         do {
    3514             :             if (ep.achName[0] == '.'
    3515             :             && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
    3516             :                 continue; /* Skip Over "." and ".." Names */
    3517             : 
    3518             :             strcpy(namebuf, ep.achName);
    3519             : 
    3520             :             /* Leave Case of Name Alone -- In Native Form */
    3521             :             /* (Removed Forced Lowercasing Code) */
    3522             : 
    3523             :             v = PyBytes_FromString(namebuf);
    3524             :             if (v == NULL) {
    3525             :                 Py_DECREF(list);
    3526             :                 list = NULL;
    3527             :                 break;
    3528             :             }
    3529             :             if (PyList_Append(list, v) != 0) {
    3530             :                 Py_DECREF(v);
    3531             :                 Py_DECREF(list);
    3532             :                 list = NULL;
    3533             :                 break;
    3534             :             }
    3535             :             Py_DECREF(v);
    3536             :         } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
    3537             :     }
    3538             : 
    3539             : exit:
    3540             :     path_cleanup(&path);
    3541             : 
    3542             :     return list;
    3543             : #else
    3544             : 
    3545          11 :     errno = 0;
    3546             : #ifdef HAVE_FDOPENDIR
    3547          11 :     if (path.fd != -1) {
    3548             :         /* closedir() closes the FD, so we duplicate it */
    3549           0 :         Py_BEGIN_ALLOW_THREADS
    3550           0 :         fd = dup(path.fd);
    3551           0 :         Py_END_ALLOW_THREADS
    3552             : 
    3553           0 :         if (fd == -1) {
    3554           0 :             list = posix_error();
    3555           0 :             goto exit;
    3556             :         }
    3557             : 
    3558           0 :         return_str = 1;
    3559             : 
    3560           0 :         Py_BEGIN_ALLOW_THREADS
    3561           0 :         dirp = fdopendir(fd);
    3562           0 :         Py_END_ALLOW_THREADS
    3563             :     }
    3564             :     else
    3565             : #endif
    3566             :     {
    3567             :         char *name;
    3568          11 :         if (path.narrow) {
    3569          11 :             name = path.narrow;
    3570             :             /* only return bytes if they specified a bytes object */
    3571          11 :             return_str = !(PyBytes_Check(path.object));
    3572             :         }
    3573             :         else {
    3574           0 :             name = ".";
    3575           0 :             return_str = 1;
    3576             :         }
    3577             : 
    3578          11 :         Py_BEGIN_ALLOW_THREADS
    3579          11 :         dirp = opendir(name);
    3580          11 :         Py_END_ALLOW_THREADS
    3581             :     }
    3582             : 
    3583          11 :     if (dirp == NULL) {
    3584           0 :         list = path_error("listdir", &path);
    3585           0 :         goto exit;
    3586             :     }
    3587          11 :     if ((list = PyList_New(0)) == NULL) {
    3588           0 :         goto exit;
    3589             :     }
    3590             :     for (;;) {
    3591         942 :         errno = 0;
    3592         942 :         Py_BEGIN_ALLOW_THREADS
    3593         942 :         ep = readdir(dirp);
    3594         942 :         Py_END_ALLOW_THREADS
    3595         942 :         if (ep == NULL) {
    3596          11 :             if (errno == 0) {
    3597          11 :                 break;
    3598             :             } else {
    3599           0 :                 Py_DECREF(list);
    3600           0 :                 list = path_error("listdir", &path);
    3601           0 :                 goto exit;
    3602             :             }
    3603             :         }
    3604         954 :         if (ep->d_name[0] == '.' &&
    3605          35 :             (NAMLEN(ep) == 1 ||
    3606          23 :              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
    3607          22 :             continue;
    3608         909 :         if (return_str)
    3609         909 :             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
    3610             :         else
    3611           0 :             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
    3612         909 :         if (v == NULL) {
    3613           0 :             Py_CLEAR(list);
    3614           0 :             break;
    3615             :         }
    3616         909 :         if (PyList_Append(list, v) != 0) {
    3617           0 :             Py_DECREF(v);
    3618           0 :             Py_CLEAR(list);
    3619           0 :             break;
    3620             :         }
    3621         909 :         Py_DECREF(v);
    3622         931 :     }
    3623             : 
    3624             : exit:
    3625          11 :     if (dirp != NULL) {
    3626          11 :         Py_BEGIN_ALLOW_THREADS
    3627          11 :         if (fd > -1)
    3628           0 :             rewinddir(dirp);
    3629          11 :         closedir(dirp);
    3630          11 :         Py_END_ALLOW_THREADS
    3631             :     }
    3632             : 
    3633          11 :     path_cleanup(&path);
    3634             : 
    3635          11 :     return list;
    3636             : 
    3637             : #endif /* which OS */
    3638             : }  /* end of posix_listdir */
    3639             : 
    3640             : #ifdef MS_WINDOWS
    3641             : /* A helper function for abspath on win32 */
    3642             : static PyObject *
    3643             : posix__getfullpathname(PyObject *self, PyObject *args)
    3644             : {
    3645             :     const char *path;
    3646             :     char outbuf[MAX_PATH*2];
    3647             :     char *temp;
    3648             :     PyObject *po;
    3649             : 
    3650             :     if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po))
    3651             :     {
    3652             :         wchar_t *wpath;
    3653             :         wchar_t woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
    3654             :         wchar_t *wtemp;
    3655             :         DWORD result;
    3656             :         PyObject *v;
    3657             : 
    3658             :         wpath = PyUnicode_AsUnicode(po);
    3659             :         if (wpath == NULL)
    3660             :             return NULL;
    3661             :         result = GetFullPathNameW(wpath,
    3662             :                                   Py_ARRAY_LENGTH(woutbuf),
    3663             :                                   woutbuf, &wtemp);
    3664             :         if (result > Py_ARRAY_LENGTH(woutbuf)) {
    3665             :             woutbufp = malloc(result * sizeof(wchar_t));
    3666             :             if (!woutbufp)
    3667             :                 return PyErr_NoMemory();
    3668             :             result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
    3669             :         }
    3670             :         if (result)
    3671             :             v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
    3672             :         else
    3673             :             v = win32_error_object("GetFullPathNameW", po);
    3674             :         if (woutbufp != woutbuf)
    3675             :             free(woutbufp);
    3676             :         return v;
    3677             :     }
    3678             :     /* Drop the argument parsing error as narrow strings
    3679             :        are also valid. */
    3680             :     PyErr_Clear();
    3681             : 
    3682             :     if (!PyArg_ParseTuple (args, "y:_getfullpathname",
    3683             :                            &path))
    3684             :         return NULL;
    3685             :     if (win32_warn_bytes_api())
    3686             :         return NULL;
    3687             :     if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf),
    3688             :                          outbuf, &temp)) {
    3689             :         win32_error("GetFullPathName", path);
    3690             :         return NULL;
    3691             :     }
    3692             :     if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
    3693             :         return PyUnicode_Decode(outbuf, strlen(outbuf),
    3694             :                                 Py_FileSystemDefaultEncoding, NULL);
    3695             :     }
    3696             :     return PyBytes_FromString(outbuf);
    3697             : } /* end of posix__getfullpathname */
    3698             : 
    3699             : 
    3700             : 
    3701             : /* A helper function for samepath on windows */
    3702             : static PyObject *
    3703             : posix__getfinalpathname(PyObject *self, PyObject *args)
    3704             : {
    3705             :     HANDLE hFile;
    3706             :     int buf_size;
    3707             :     wchar_t *target_path;
    3708             :     int result_length;
    3709             :     PyObject *po, *result;
    3710             :     wchar_t *path;
    3711             : 
    3712             :     if (!PyArg_ParseTuple(args, "U|:_getfinalpathname", &po))
    3713             :         return NULL;
    3714             :     path = PyUnicode_AsUnicode(po);
    3715             :     if (path == NULL)
    3716             :         return NULL;
    3717             : 
    3718             :     if(!check_GetFinalPathNameByHandle()) {
    3719             :         /* If the OS doesn't have GetFinalPathNameByHandle, return a
    3720             :            NotImplementedError. */
    3721             :         return PyErr_Format(PyExc_NotImplementedError,
    3722             :             "GetFinalPathNameByHandle not available on this platform");
    3723             :     }
    3724             : 
    3725             :     hFile = CreateFileW(
    3726             :         path,
    3727             :         0, /* desired access */
    3728             :         0, /* share mode */
    3729             :         NULL, /* security attributes */
    3730             :         OPEN_EXISTING,
    3731             :         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
    3732             :         FILE_FLAG_BACKUP_SEMANTICS,
    3733             :         NULL);
    3734             : 
    3735             :     if(hFile == INVALID_HANDLE_VALUE)
    3736             :         return win32_error_object("CreateFileW", po);
    3737             : 
    3738             :     /* We have a good handle to the target, use it to determine the
    3739             :        target path name. */
    3740             :     buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
    3741             : 
    3742             :     if(!buf_size)
    3743             :         return win32_error_object("GetFinalPathNameByHandle", po);
    3744             : 
    3745             :     target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
    3746             :     if(!target_path)
    3747             :         return PyErr_NoMemory();
    3748             : 
    3749             :     result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
    3750             :                                                  buf_size, VOLUME_NAME_DOS);
    3751             :     if(!result_length)
    3752             :         return win32_error_object("GetFinalPathNamyByHandle", po);
    3753             : 
    3754             :     if(!CloseHandle(hFile))
    3755             :         return win32_error_object("CloseHandle", po);
    3756             : 
    3757             :     target_path[result_length] = 0;
    3758             :     result = PyUnicode_FromWideChar(target_path, result_length);
    3759             :     free(target_path);
    3760             :     return result;
    3761             : 
    3762             : } /* end of posix__getfinalpathname */
    3763             : 
    3764             : static PyObject *
    3765             : posix__getfileinformation(PyObject *self, PyObject *args)
    3766             : {
    3767             :     HANDLE hFile;
    3768             :     BY_HANDLE_FILE_INFORMATION info;
    3769             :     int fd;
    3770             : 
    3771             :     if (!PyArg_ParseTuple(args, "i:_getfileinformation", &fd))
    3772             :         return NULL;
    3773             : 
    3774             :     if (!_PyVerify_fd(fd))
    3775             :         return posix_error();
    3776             : 
    3777             :     hFile = (HANDLE)_get_osfhandle(fd);
    3778             :     if (hFile == INVALID_HANDLE_VALUE)
    3779             :         return posix_error();
    3780             : 
    3781             :     if (!GetFileInformationByHandle(hFile, &info))
    3782             :         return win32_error("_getfileinformation", NULL);
    3783             : 
    3784             :     return Py_BuildValue("iii", info.dwVolumeSerialNumber,
    3785             :                                 info.nFileIndexHigh,
    3786             :                                 info.nFileIndexLow);
    3787             : }
    3788             : 
    3789             : PyDoc_STRVAR(posix__isdir__doc__,
    3790             : "Return true if the pathname refers to an existing directory.");
    3791             : 
    3792             : static PyObject *
    3793             : posix__isdir(PyObject *self, PyObject *args)
    3794             : {
    3795             :     const char *path;
    3796             :     PyObject *po;
    3797             :     DWORD attributes;
    3798             : 
    3799             :     if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
    3800             :         wchar_t *wpath = PyUnicode_AsUnicode(po);
    3801             :         if (wpath == NULL)
    3802             :             return NULL;
    3803             : 
    3804             :         attributes = GetFileAttributesW(wpath);
    3805             :         if (attributes == INVALID_FILE_ATTRIBUTES)
    3806             :             Py_RETURN_FALSE;
    3807             :         goto check;
    3808             :     }
    3809             :     /* Drop the argument parsing error as narrow strings
    3810             :        are also valid. */
    3811             :     PyErr_Clear();
    3812             : 
    3813             :     if (!PyArg_ParseTuple(args, "y:_isdir", &path))
    3814             :         return NULL;
    3815             :     if (win32_warn_bytes_api())
    3816             :         return NULL;
    3817             :     attributes = GetFileAttributesA(path);
    3818             :     if (attributes == INVALID_FILE_ATTRIBUTES)
    3819             :         Py_RETURN_FALSE;
    3820             : 
    3821             : check:
    3822             :     if (attributes & FILE_ATTRIBUTE_DIRECTORY)
    3823             :         Py_RETURN_TRUE;
    3824             :     else
    3825             :         Py_RETURN_FALSE;
    3826             : }
    3827             : #endif /* MS_WINDOWS */
    3828             : 
    3829             : PyDoc_STRVAR(posix_mkdir__doc__,
    3830             : "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
    3831             : Create a directory.\n\
    3832             : \n\
    3833             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    3834             :   and path should be relative; path will then be relative to that directory.\n\
    3835             : dir_fd may not be implemented on your platform.\n\
    3836             :   If it is unavailable, using it will raise a NotImplementedError.\n\
    3837             : \n\
    3838             : The mode argument is ignored on Windows.");
    3839             : 
    3840             : static PyObject *
    3841           0 : posix_mkdir(PyObject *self, PyObject *args, PyObject *kwargs)
    3842             : {
    3843             :     path_t path;
    3844           0 :     int mode = 0777;
    3845           0 :     int dir_fd = DEFAULT_DIR_FD;
    3846             :     static char *keywords[] = {"path", "mode", "dir_fd", NULL};
    3847           0 :     PyObject *return_value = NULL;
    3848             :     int result;
    3849             : 
    3850           0 :     memset(&path, 0, sizeof(path));
    3851           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", keywords,
    3852             :         path_converter, &path, &mode,
    3853             : #ifdef HAVE_MKDIRAT
    3854             :         dir_fd_converter, &dir_fd
    3855             : #else
    3856             :         dir_fd_unavailable, &dir_fd
    3857             : #endif
    3858             :         ))
    3859           0 :         return NULL;
    3860             : 
    3861             : #ifdef MS_WINDOWS
    3862             :     Py_BEGIN_ALLOW_THREADS
    3863             :     if (path.wide)
    3864             :         result = CreateDirectoryW(path.wide, NULL);
    3865             :     else
    3866             :         result = CreateDirectoryA(path.narrow, NULL);
    3867             :     Py_END_ALLOW_THREADS
    3868             : 
    3869             :     if (!result) {
    3870             :         return_value = win32_error_object("mkdir", path.object);
    3871             :         goto exit;
    3872             :     }
    3873             : #else
    3874           0 :     Py_BEGIN_ALLOW_THREADS
    3875             : #if HAVE_MKDIRAT
    3876           0 :     if (dir_fd != DEFAULT_DIR_FD)
    3877           0 :         result = mkdirat(dir_fd, path.narrow, mode);
    3878             :     else
    3879             : #endif
    3880             : #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
    3881             :         result = mkdir(path.narrow);
    3882             : #else
    3883           0 :         result = mkdir(path.narrow, mode);
    3884             : #endif
    3885           0 :     Py_END_ALLOW_THREADS
    3886           0 :     if (result < 0) {
    3887           0 :         return_value = path_error("mkdir", &path);
    3888           0 :         goto exit;
    3889             :     }
    3890             : #endif
    3891           0 :     return_value = Py_None;
    3892           0 :     Py_INCREF(Py_None);
    3893             : exit:
    3894           0 :     path_cleanup(&path);
    3895           0 :     return return_value;
    3896             : }
    3897             : 
    3898             : 
    3899             : /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
    3900             : #if defined(HAVE_SYS_RESOURCE_H)
    3901             : #include <sys/resource.h>
    3902             : #endif
    3903             : 
    3904             : 
    3905             : #ifdef HAVE_NICE
    3906             : PyDoc_STRVAR(posix_nice__doc__,
    3907             : "nice(inc) -> new_priority\n\n\
    3908             : Decrease the priority of process by inc and return the new priority.");
    3909             : 
    3910             : static PyObject *
    3911           0 : posix_nice(PyObject *self, PyObject *args)
    3912             : {
    3913             :     int increment, value;
    3914             : 
    3915           0 :     if (!PyArg_ParseTuple(args, "i:nice", &increment))
    3916           0 :         return NULL;
    3917             : 
    3918             :     /* There are two flavours of 'nice': one that returns the new
    3919             :        priority (as required by almost all standards out there) and the
    3920             :        Linux/FreeBSD/BSDI one, which returns '0' on success and advices
    3921             :        the use of getpriority() to get the new priority.
    3922             : 
    3923             :        If we are of the nice family that returns the new priority, we
    3924             :        need to clear errno before the call, and check if errno is filled
    3925             :        before calling posix_error() on a returnvalue of -1, because the
    3926             :        -1 may be the actual new priority! */
    3927             : 
    3928           0 :     errno = 0;
    3929           0 :     value = nice(increment);
    3930             : #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
    3931             :     if (value == 0)
    3932             :         value = getpriority(PRIO_PROCESS, 0);
    3933             : #endif
    3934           0 :     if (value == -1 && errno != 0)
    3935             :         /* either nice() or getpriority() returned an error */
    3936           0 :         return posix_error();
    3937           0 :     return PyLong_FromLong((long) value);
    3938             : }
    3939             : #endif /* HAVE_NICE */
    3940             : 
    3941             : 
    3942             : #ifdef HAVE_GETPRIORITY
    3943             : PyDoc_STRVAR(posix_getpriority__doc__,
    3944             : "getpriority(which, who) -> current_priority\n\n\
    3945             : Get program scheduling priority.");
    3946             : 
    3947             : static PyObject *
    3948           0 : posix_getpriority(PyObject *self, PyObject *args)
    3949             : {
    3950             :     int which, who, retval;
    3951             : 
    3952           0 :     if (!PyArg_ParseTuple(args, "ii", &which, &who))
    3953           0 :         return NULL;
    3954           0 :     errno = 0;
    3955           0 :     retval = getpriority(which, who);
    3956           0 :     if (errno != 0)
    3957           0 :         return posix_error();
    3958           0 :     return PyLong_FromLong((long)retval);
    3959             : }
    3960             : #endif /* HAVE_GETPRIORITY */
    3961             : 
    3962             : 
    3963             : #ifdef HAVE_SETPRIORITY
    3964             : PyDoc_STRVAR(posix_setpriority__doc__,
    3965             : "setpriority(which, who, prio) -> None\n\n\
    3966             : Set program scheduling priority.");
    3967             : 
    3968             : static PyObject *
    3969           0 : posix_setpriority(PyObject *self, PyObject *args)
    3970             : {
    3971             :     int which, who, prio, retval;
    3972             : 
    3973           0 :     if (!PyArg_ParseTuple(args, "iii", &which, &who, &prio))
    3974           0 :         return NULL;
    3975           0 :     retval = setpriority(which, who, prio);
    3976           0 :     if (retval == -1)
    3977           0 :         return posix_error();
    3978           0 :     Py_RETURN_NONE;
    3979             : }
    3980             : #endif /* HAVE_SETPRIORITY */
    3981             : 
    3982             : 
    3983             : static PyObject *
    3984           0 : internal_rename(PyObject *args, PyObject *kwargs, int is_replace)
    3985             : {
    3986           0 :     char *function_name = is_replace ? "replace" : "rename";
    3987             :     path_t src;
    3988             :     path_t dst;
    3989           0 :     int src_dir_fd = DEFAULT_DIR_FD;
    3990           0 :     int dst_dir_fd = DEFAULT_DIR_FD;
    3991             :     int dir_fd_specified;
    3992           0 :     PyObject *return_value = NULL;
    3993             :     char format[24];
    3994             :     static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
    3995             : 
    3996             : #ifdef MS_WINDOWS
    3997             :     BOOL result;
    3998             :     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
    3999             : #else
    4000             :     int result;
    4001             : #endif
    4002             : 
    4003           0 :     memset(&src, 0, sizeof(src));
    4004           0 :     memset(&dst, 0, sizeof(dst));
    4005           0 :     strcpy(format, "O&O&|$O&O&:");
    4006           0 :     strcat(format, function_name);
    4007           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, keywords,
    4008             :         path_converter, &src,
    4009             :         path_converter, &dst,
    4010             :         dir_fd_converter, &src_dir_fd,
    4011             :         dir_fd_converter, &dst_dir_fd))
    4012           0 :         return NULL;
    4013             : 
    4014           0 :     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
    4015           0 :                        (dst_dir_fd != DEFAULT_DIR_FD);
    4016             : #ifndef HAVE_RENAMEAT
    4017             :     if (dir_fd_specified) {
    4018             :         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
    4019             :         goto exit;
    4020             :     }
    4021             : #endif
    4022             : 
    4023           0 :     if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
    4024           0 :         PyErr_Format(PyExc_ValueError,
    4025             :                      "%s: src and dst must be the same type", function_name);
    4026           0 :         goto exit;
    4027             :     }
    4028             : 
    4029             : #ifdef MS_WINDOWS
    4030             :     Py_BEGIN_ALLOW_THREADS
    4031             :     if (src.wide)
    4032             :         result = MoveFileExW(src.wide, dst.wide, flags);
    4033             :     else
    4034             :         result = MoveFileExA(src.narrow, dst.narrow, flags);
    4035             :     Py_END_ALLOW_THREADS
    4036             : 
    4037             :     if (!result) {
    4038             :         return_value = win32_error_object(function_name, dst.object);
    4039             :         goto exit;
    4040             :     }
    4041             : 
    4042             : #else
    4043           0 :     Py_BEGIN_ALLOW_THREADS
    4044             : #ifdef HAVE_RENAMEAT
    4045           0 :     if (dir_fd_specified)
    4046           0 :         result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow);
    4047             :     else
    4048             : #endif
    4049           0 :         result = rename(src.narrow, dst.narrow);
    4050           0 :     Py_END_ALLOW_THREADS
    4051             : 
    4052           0 :     if (result) {
    4053           0 :         return_value = path_error(function_name, &dst);
    4054           0 :         goto exit;
    4055             :     }
    4056             : #endif
    4057             : 
    4058           0 :     Py_INCREF(Py_None);
    4059           0 :     return_value = Py_None;
    4060             : exit:
    4061           0 :     path_cleanup(&src);
    4062           0 :     path_cleanup(&dst);
    4063           0 :     return return_value;
    4064             : }
    4065             : 
    4066             : PyDoc_STRVAR(posix_rename__doc__,
    4067             : "rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
    4068             : Rename a file or directory.\n\
    4069             : \n\
    4070             : If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
    4071             :   descriptor open to a directory, and the respective path string (src or dst)\n\
    4072             :   should be relative; the path will then be relative to that directory.\n\
    4073             : src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
    4074             :   If they are unavailable, using them will raise a NotImplementedError.");
    4075             : 
    4076             : static PyObject *
    4077           0 : posix_rename(PyObject *self, PyObject *args, PyObject *kwargs)
    4078             : {
    4079           0 :     return internal_rename(args, kwargs, 0);
    4080             : }
    4081             : 
    4082             : PyDoc_STRVAR(posix_replace__doc__,
    4083             : "replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
    4084             : Rename a file or directory, overwriting the destination.\n\
    4085             : \n\
    4086             : If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
    4087             :   descriptor open to a directory, and the respective path string (src or dst)\n\
    4088             :   should be relative; the path will then be relative to that directory.\n\
    4089             : src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
    4090             :   If they are unavailable, using them will raise a NotImplementedError.");
    4091             : 
    4092             : static PyObject *
    4093           0 : posix_replace(PyObject *self, PyObject *args, PyObject *kwargs)
    4094             : {
    4095           0 :     return internal_rename(args, kwargs, 1);
    4096             : }
    4097             : 
    4098             : PyDoc_STRVAR(posix_rmdir__doc__,
    4099             : "rmdir(path, *, dir_fd=None)\n\n\
    4100             : Remove a directory.\n\
    4101             : \n\
    4102             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    4103             :   and path should be relative; path will then be relative to that directory.\n\
    4104             : dir_fd may not be implemented on your platform.\n\
    4105             :   If it is unavailable, using it will raise a NotImplementedError.");
    4106             : 
    4107             : static PyObject *
    4108           0 : posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs)
    4109             : {
    4110             :     path_t path;
    4111           0 :     int dir_fd = DEFAULT_DIR_FD;
    4112             :     static char *keywords[] = {"path", "dir_fd", NULL};
    4113             :     int result;
    4114           0 :     PyObject *return_value = NULL;
    4115             : 
    4116           0 :     memset(&path, 0, sizeof(path));
    4117           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords,
    4118             :             path_converter, &path,
    4119             : #ifdef HAVE_UNLINKAT
    4120             :             dir_fd_converter, &dir_fd
    4121             : #else
    4122             :             dir_fd_unavailable, &dir_fd
    4123             : #endif
    4124             :             ))
    4125           0 :         return NULL;
    4126             : 
    4127           0 :     Py_BEGIN_ALLOW_THREADS
    4128             : #ifdef MS_WINDOWS
    4129             :     if (path.wide)
    4130             :         result = RemoveDirectoryW(path.wide);
    4131             :     else
    4132             :         result = RemoveDirectoryA(path.narrow);
    4133             :     result = !result; /* Windows, success=1, UNIX, success=0 */
    4134             : #else
    4135             : #ifdef HAVE_UNLINKAT
    4136           0 :     if (dir_fd != DEFAULT_DIR_FD)
    4137           0 :         result = unlinkat(dir_fd, path.narrow, AT_REMOVEDIR);
    4138             :     else
    4139             : #endif
    4140           0 :         result = rmdir(path.narrow);
    4141             : #endif
    4142           0 :     Py_END_ALLOW_THREADS
    4143             : 
    4144           0 :     if (result) {
    4145           0 :         return_value = path_error("rmdir", &path);
    4146           0 :         goto exit;
    4147             :     }
    4148             : 
    4149           0 :     return_value = Py_None;
    4150           0 :     Py_INCREF(Py_None);
    4151             : 
    4152             : exit:
    4153           0 :     path_cleanup(&path);
    4154           0 :     return return_value;
    4155             : }
    4156             : 
    4157             : 
    4158             : #ifdef HAVE_SYSTEM
    4159             : PyDoc_STRVAR(posix_system__doc__,
    4160             : "system(command) -> exit_status\n\n\
    4161             : Execute the command (a string) in a subshell.");
    4162             : 
    4163             : static PyObject *
    4164           0 : posix_system(PyObject *self, PyObject *args)
    4165             : {
    4166             :     long sts;
    4167             : #ifdef MS_WINDOWS
    4168             :     wchar_t *command;
    4169             :     if (!PyArg_ParseTuple(args, "u:system", &command))
    4170             :         return NULL;
    4171             : 
    4172             :     Py_BEGIN_ALLOW_THREADS
    4173             :     sts = _wsystem(command);
    4174             :     Py_END_ALLOW_THREADS
    4175             : #else
    4176             :     PyObject *command_obj;
    4177             :     char *command;
    4178           0 :     if (!PyArg_ParseTuple(args, "O&:system",
    4179             :                           PyUnicode_FSConverter, &command_obj))
    4180           0 :         return NULL;
    4181             : 
    4182           0 :     command = PyBytes_AsString(command_obj);
    4183           0 :     Py_BEGIN_ALLOW_THREADS
    4184           0 :     sts = system(command);
    4185           0 :     Py_END_ALLOW_THREADS
    4186           0 :     Py_DECREF(command_obj);
    4187             : #endif
    4188           0 :     return PyLong_FromLong(sts);
    4189             : }
    4190             : #endif
    4191             : 
    4192             : 
    4193             : PyDoc_STRVAR(posix_umask__doc__,
    4194             : "umask(new_mask) -> old_mask\n\n\
    4195             : Set the current numeric umask and return the previous umask.");
    4196             : 
    4197             : static PyObject *
    4198           0 : posix_umask(PyObject *self, PyObject *args)
    4199             : {
    4200             :     int i;
    4201           0 :     if (!PyArg_ParseTuple(args, "i:umask", &i))
    4202           0 :         return NULL;
    4203           0 :     i = (int)umask(i);
    4204           0 :     if (i < 0)
    4205           0 :         return posix_error();
    4206           0 :     return PyLong_FromLong((long)i);
    4207             : }
    4208             : 
    4209             : #ifdef MS_WINDOWS
    4210             : 
    4211             : /* override the default DeleteFileW behavior so that directory
    4212             : symlinks can be removed with this function, the same as with
    4213             : Unix symlinks */
    4214             : BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
    4215             : {
    4216             :     WIN32_FILE_ATTRIBUTE_DATA info;
    4217             :     WIN32_FIND_DATAW find_data;
    4218             :     HANDLE find_data_handle;
    4219             :     int is_directory = 0;
    4220             :     int is_link = 0;
    4221             : 
    4222             :     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
    4223             :         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
    4224             : 
    4225             :         /* Get WIN32_FIND_DATA structure for the path to determine if
    4226             :            it is a symlink */
    4227             :         if(is_directory &&
    4228             :            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
    4229             :             find_data_handle = FindFirstFileW(lpFileName, &find_data);
    4230             : 
    4231             :             if(find_data_handle != INVALID_HANDLE_VALUE) {
    4232             :                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
    4233             :                 FindClose(find_data_handle);
    4234             :             }
    4235             :         }
    4236             :     }
    4237             : 
    4238             :     if (is_directory && is_link)
    4239             :         return RemoveDirectoryW(lpFileName);
    4240             : 
    4241             :     return DeleteFileW(lpFileName);
    4242             : }
    4243             : #endif /* MS_WINDOWS */
    4244             : 
    4245             : PyDoc_STRVAR(posix_unlink__doc__,
    4246             : "unlink(path, *, dir_fd=None)\n\n\
    4247             : Remove a file (same as remove()).\n\
    4248             : \n\
    4249             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    4250             :   and path should be relative; path will then be relative to that directory.\n\
    4251             : dir_fd may not be implemented on your platform.\n\
    4252             :   If it is unavailable, using it will raise a NotImplementedError.");
    4253             : 
    4254             : PyDoc_STRVAR(posix_remove__doc__,
    4255             : "remove(path, *, dir_fd=None)\n\n\
    4256             : Remove a file (same as unlink()).\n\
    4257             : \n\
    4258             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    4259             :   and path should be relative; path will then be relative to that directory.\n\
    4260             : dir_fd may not be implemented on your platform.\n\
    4261             :   If it is unavailable, using it will raise a NotImplementedError.");
    4262             : 
    4263             : static PyObject *
    4264           0 : posix_unlink(PyObject *self, PyObject *args, PyObject *kwargs)
    4265             : {
    4266             :     path_t path;
    4267           0 :     int dir_fd = DEFAULT_DIR_FD;
    4268             :     static char *keywords[] = {"path", "dir_fd", NULL};
    4269             :     int result;
    4270           0 :     PyObject *return_value = NULL;
    4271             : 
    4272           0 :     memset(&path, 0, sizeof(path));
    4273           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:unlink", keywords,
    4274             :             path_converter, &path,
    4275             : #ifdef HAVE_UNLINKAT
    4276             :             dir_fd_converter, &dir_fd
    4277             : #else
    4278             :             dir_fd_unavailable, &dir_fd
    4279             : #endif
    4280             :             ))
    4281           0 :         return NULL;
    4282             : 
    4283           0 :     Py_BEGIN_ALLOW_THREADS
    4284             : #ifdef MS_WINDOWS
    4285             :     if (path.wide)
    4286             :         result = Py_DeleteFileW(path.wide);
    4287             :     else
    4288             :         result = DeleteFileA(path.narrow);
    4289             :     result = !result; /* Windows, success=1, UNIX, success=0 */
    4290             : #else
    4291             : #ifdef HAVE_UNLINKAT
    4292           0 :     if (dir_fd != DEFAULT_DIR_FD)
    4293           0 :         result = unlinkat(dir_fd, path.narrow, 0);
    4294             :     else
    4295             : #endif /* HAVE_UNLINKAT */
    4296           0 :         result = unlink(path.narrow);
    4297             : #endif
    4298           0 :     Py_END_ALLOW_THREADS
    4299             : 
    4300           0 :     if (result) {
    4301           0 :         return_value = path_error("unlink", &path);
    4302           0 :         goto exit;
    4303             :     }
    4304             : 
    4305           0 :     return_value = Py_None;
    4306           0 :     Py_INCREF(Py_None);
    4307             : 
    4308             : exit:
    4309           0 :     path_cleanup(&path);
    4310           0 :     return return_value;
    4311             : }
    4312             : 
    4313             : 
    4314             : PyDoc_STRVAR(posix_uname__doc__,
    4315             : "uname() -> uname_result\n\n\
    4316             : Return an object identifying the current operating system.\n\
    4317             : The object behaves like a named tuple with the following fields:\n\
    4318             :   (sysname, nodename, release, version, machine)");
    4319             : 
    4320             : static PyStructSequence_Field uname_result_fields[] = {
    4321             :     {"sysname",    "operating system name"},
    4322             :     {"nodename",   "name of machine on network (implementation-defined)"},
    4323             :     {"release",    "operating system release"},
    4324             :     {"version",    "operating system version"},
    4325             :     {"machine",    "hardware identifier"},
    4326             :     {NULL}
    4327             : };
    4328             : 
    4329             : PyDoc_STRVAR(uname_result__doc__,
    4330             : "uname_result: Result from os.uname().\n\n\
    4331             : This object may be accessed either as a tuple of\n\
    4332             :   (sysname, nodename, release, version, machine),\n\
    4333             : or via the attributes sysname, nodename, release, version, and machine.\n\
    4334             : \n\
    4335             : See os.uname for more information.");
    4336             : 
    4337             : static PyStructSequence_Desc uname_result_desc = {
    4338             :     "uname_result", /* name */
    4339             :     uname_result__doc__, /* doc */
    4340             :     uname_result_fields,
    4341             :     5
    4342             : };
    4343             : 
    4344             : static PyTypeObject UnameResultType;
    4345             : 
    4346             : 
    4347             : #ifdef HAVE_UNAME
    4348             : static PyObject *
    4349           0 : posix_uname(PyObject *self, PyObject *noargs)
    4350             : {
    4351             :     struct utsname u;
    4352             :     int res;
    4353             :     PyObject *value;
    4354             : 
    4355           0 :     Py_BEGIN_ALLOW_THREADS
    4356           0 :     res = uname(&u);
    4357           0 :     Py_END_ALLOW_THREADS
    4358           0 :     if (res < 0)
    4359           0 :         return posix_error();
    4360             : 
    4361           0 :     value = PyStructSequence_New(&UnameResultType);
    4362           0 :     if (value == NULL)
    4363           0 :         return NULL;
    4364             : 
    4365             : #define SET(i, field) \
    4366             :     { \
    4367             :     PyObject *o = PyUnicode_DecodeASCII(field, strlen(field), NULL); \
    4368             :     if (!o) { \
    4369             :         Py_DECREF(value); \
    4370             :         return NULL; \
    4371             :     } \
    4372             :     PyStructSequence_SET_ITEM(value, i, o); \
    4373             :     } \
    4374             : 
    4375           0 :     SET(0, u.sysname);
    4376           0 :     SET(1, u.nodename);
    4377           0 :     SET(2, u.release);
    4378           0 :     SET(3, u.version);
    4379           0 :     SET(4, u.machine);
    4380             : 
    4381             : #undef SET
    4382             : 
    4383           0 :     return value;
    4384             : }
    4385             : #endif /* HAVE_UNAME */
    4386             : 
    4387             : 
    4388             : PyDoc_STRVAR(posix_utime__doc__,
    4389             : "utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\
    4390             : Set the access and modified time of path.\n\
    4391             : \n\
    4392             : path may always be specified as a string.\n\
    4393             : On some platforms, path may also be specified as an open file descriptor.\n\
    4394             :   If this functionality is unavailable, using it raises an exception.\n\
    4395             : \n\
    4396             : If times is not None, it must be a tuple (atime, mtime);\n\
    4397             :     atime and mtime should be expressed as float seconds since the epoch.\n\
    4398             : If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n\
    4399             :     atime_ns and mtime_ns should be expressed as integer nanoseconds\n\
    4400             :     since the epoch.\n\
    4401             : If both times and ns are None, utime uses the current time.\n\
    4402             : Specifying tuples for both times and ns is an error.\n\
    4403             : \n\
    4404             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    4405             :   and path should be relative; path will then be relative to that directory.\n\
    4406             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
    4407             :   link, utime will modify the symbolic link itself instead of the file the\n\
    4408             :   link points to.\n\
    4409             : It is an error to use dir_fd or follow_symlinks when specifying path\n\
    4410             :   as an open file descriptor.\n\
    4411             : dir_fd and follow_symlinks may not be available on your platform.\n\
    4412             :   If they are unavailable, using them will raise a NotImplementedError.");
    4413             : 
    4414             : typedef struct {
    4415             :     int    now;
    4416             :     time_t atime_s;
    4417             :     long   atime_ns;
    4418             :     time_t mtime_s;
    4419             :     long   mtime_ns;
    4420             : } utime_t;
    4421             : 
    4422             : /*
    4423             :  * these macros assume that "utime" is a pointer to a utime_t
    4424             :  * they also intentionally leak the declaration of a pointer named "time"
    4425             :  */
    4426             : #define UTIME_TO_TIMESPEC \
    4427             :     struct timespec ts[2]; \
    4428             :     struct timespec *time; \
    4429             :     if (utime->now) \
    4430             :         time = NULL; \
    4431             :     else { \
    4432             :         ts[0].tv_sec = utime->atime_s; \
    4433             :         ts[0].tv_nsec = utime->atime_ns; \
    4434             :         ts[1].tv_sec = utime->mtime_s; \
    4435             :         ts[1].tv_nsec = utime->mtime_ns; \
    4436             :         time = ts; \
    4437             :     } \
    4438             : 
    4439             : #define UTIME_TO_TIMEVAL \
    4440             :     struct timeval tv[2]; \
    4441             :     struct timeval *time; \
    4442             :     if (utime->now) \
    4443             :         time = NULL; \
    4444             :     else { \
    4445             :         tv[0].tv_sec = utime->atime_s; \
    4446             :         tv[0].tv_usec = utime->atime_ns / 1000; \
    4447             :         tv[1].tv_sec = utime->mtime_s; \
    4448             :         tv[1].tv_usec = utime->mtime_ns / 1000; \
    4449             :         time = tv; \
    4450             :     } \
    4451             : 
    4452             : #define UTIME_TO_UTIMBUF \
    4453             :     struct utimbuf u[2]; \
    4454             :     struct utimbuf *time; \
    4455             :     if (utime->now) \
    4456             :         time = NULL; \
    4457             :     else { \
    4458             :         u.actime = utime->atime_s; \
    4459             :         u.modtime = utime->mtime_s; \
    4460             :         time = u; \
    4461             :     }
    4462             : 
    4463             : #define UTIME_TO_TIME_T \
    4464             :     time_t timet[2]; \
    4465             :     struct timet time; \
    4466             :     if (utime->now) \
    4467             :         time = NULL; \
    4468             :     else { \
    4469             :         timet[0] = utime->atime_s; \
    4470             :         timet[1] = utime->mtime_s; \
    4471             :         time = &timet; \
    4472             :     } \
    4473             : 
    4474             : 
    4475             : #define UTIME_HAVE_DIR_FD (defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT))
    4476             : 
    4477             : #if UTIME_HAVE_DIR_FD
    4478             : 
    4479             : static int
    4480           0 : utime_dir_fd(utime_t *utime, int dir_fd, char *path, int follow_symlinks)
    4481             : {
    4482             : #ifdef HAVE_UTIMENSAT
    4483           0 :     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
    4484           0 :     UTIME_TO_TIMESPEC;
    4485           0 :     return utimensat(dir_fd, path, time, flags);
    4486             : #elif defined(HAVE_FUTIMESAT)
    4487             :     UTIME_TO_TIMEVAL;
    4488             :     /*
    4489             :      * follow_symlinks will never be false here;
    4490             :      * we only allow !follow_symlinks and dir_fd together
    4491             :      * if we have utimensat()
    4492             :      */
    4493             :     assert(follow_symlinks);
    4494             :     return futimesat(dir_fd, path, time);
    4495             : #endif
    4496             : }
    4497             : 
    4498             : #endif
    4499             : 
    4500             : #define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS))
    4501             : 
    4502             : #if UTIME_HAVE_FD
    4503             : 
    4504             : static int
    4505           0 : utime_fd(utime_t *utime, int fd)
    4506             : {
    4507             : #ifdef HAVE_FUTIMENS
    4508           0 :     UTIME_TO_TIMESPEC;
    4509           0 :     return futimens(fd, time);
    4510             : #else
    4511             :     UTIME_TO_TIMEVAL;
    4512             :     return futimes(fd, time);
    4513             : #endif
    4514             : }
    4515             : 
    4516             : #endif
    4517             : 
    4518             : 
    4519             : #define UTIME_HAVE_NOFOLLOW_SYMLINKS \
    4520             :         (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES))
    4521             : 
    4522             : #if UTIME_HAVE_NOFOLLOW_SYMLINKS
    4523             : 
    4524             : static int
    4525           0 : utime_nofollow_symlinks(utime_t *utime, char *path)
    4526             : {
    4527             : #ifdef HAVE_UTIMENSAT
    4528           0 :     UTIME_TO_TIMESPEC;
    4529           0 :     return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
    4530             : #else
    4531             :     UTIME_TO_TIMEVAL;
    4532             :     return lutimes(path, time);
    4533             : #endif
    4534             : }
    4535             : 
    4536             : #endif
    4537             : 
    4538             : #ifndef MS_WINDOWS
    4539             : 
    4540             : static int
    4541           0 : utime_default(utime_t *utime, char *path)
    4542             : {
    4543             : #ifdef HAVE_UTIMENSAT
    4544           0 :     UTIME_TO_TIMESPEC;
    4545           0 :     return utimensat(DEFAULT_DIR_FD, path, time, 0);
    4546             : #elif defined(HAVE_UTIMES)
    4547             :     UTIME_TO_TIMEVAL;
    4548             :     return utimes(path, time);
    4549             : #elif defined(HAVE_UTIME_H)
    4550             :     UTIME_TO_UTIMBUF;
    4551             :     return utime(path, time);
    4552             : #else
    4553             :     UTIME_TO_TIME_T;
    4554             :     return utime(path, time);
    4555             : #endif
    4556             : }
    4557             : 
    4558             : #endif
    4559             : 
    4560             : static int
    4561           0 : split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
    4562             : {
    4563           0 :     int result = 0;
    4564             :     PyObject *divmod;
    4565           0 :     divmod = PyNumber_Divmod(py_long, billion);
    4566           0 :     if (!divmod)
    4567           0 :         goto exit;
    4568           0 :     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
    4569           0 :     if ((*s == -1) && PyErr_Occurred())
    4570           0 :         goto exit;
    4571           0 :     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
    4572           0 :     if ((*ns == -1) && PyErr_Occurred())
    4573           0 :         goto exit;
    4574             : 
    4575           0 :     result = 1;
    4576             : exit:
    4577           0 :     Py_XDECREF(divmod);
    4578           0 :     return result;
    4579             : }
    4580             : 
    4581             : static PyObject *
    4582           0 : posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
    4583             : {
    4584             :     path_t path;
    4585           0 :     PyObject *times = NULL;
    4586           0 :     PyObject *ns = NULL;
    4587           0 :     int dir_fd = DEFAULT_DIR_FD;
    4588           0 :     int follow_symlinks = 1;
    4589           0 :     char *keywords[] = {"path", "times", "ns", "dir_fd",
    4590             :                         "follow_symlinks", NULL};
    4591             : 
    4592             :     utime_t utime;
    4593             : 
    4594             : #ifdef MS_WINDOWS
    4595             :     HANDLE hFile;
    4596             :     FILETIME atime, mtime;
    4597             : #else
    4598             :     int result;
    4599             : #endif
    4600             : 
    4601           0 :     PyObject *return_value = NULL;
    4602             : 
    4603           0 :     memset(&path, 0, sizeof(path));
    4604             : #if UTIME_HAVE_FD
    4605           0 :     path.allow_fd = 1;
    4606             : #endif
    4607           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
    4608             :             "O&|O$OO&p:utime", keywords,
    4609             :             path_converter, &path,
    4610             :             &times, &ns,
    4611             : #if UTIME_HAVE_DIR_FD
    4612             :             dir_fd_converter, &dir_fd,
    4613             : #else
    4614             :             dir_fd_unavailable, &dir_fd,
    4615             : #endif
    4616             :             &follow_symlinks
    4617             :             ))
    4618           0 :         return NULL;
    4619             : 
    4620           0 :     if (times && (times != Py_None) && ns) {
    4621           0 :         PyErr_SetString(PyExc_ValueError,
    4622             :                      "utime: you may specify either 'times'"
    4623             :                      " or 'ns' but not both");
    4624           0 :         goto exit;
    4625             :     }
    4626             : 
    4627           0 :     if (times && (times != Py_None)) {
    4628           0 :         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
    4629           0 :             PyErr_SetString(PyExc_TypeError,
    4630             :                          "utime: 'times' must be either"
    4631             :                          " a tuple of two ints or None");
    4632           0 :             goto exit;
    4633             :         }
    4634           0 :         utime.now = 0;
    4635           0 :         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
    4636           0 :                                      &utime.atime_s, &utime.atime_ns) == -1 ||
    4637           0 :             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
    4638             :                                      &utime.mtime_s, &utime.mtime_ns) == -1) {
    4639             :             goto exit;
    4640             :         }
    4641             :     }
    4642           0 :     else if (ns) {
    4643           0 :         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
    4644           0 :             PyErr_SetString(PyExc_TypeError,
    4645             :                          "utime: 'ns' must be a tuple of two ints");
    4646           0 :             goto exit;
    4647             :         }
    4648           0 :         utime.now = 0;
    4649           0 :         if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
    4650           0 :                                       &utime.atime_s, &utime.atime_ns) ||
    4651           0 :             !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
    4652             :                                        &utime.mtime_s, &utime.mtime_ns)) {
    4653             :             goto exit;
    4654             :         }
    4655             :     }
    4656             :     else {
    4657             :         /* times and ns are both None/unspecified. use "now". */
    4658           0 :         utime.now = 1;
    4659             :     }
    4660             : 
    4661             : #if !UTIME_HAVE_NOFOLLOW_SYMLINKS
    4662             :     if (follow_symlinks_specified("utime", follow_symlinks))
    4663             :         goto exit;
    4664             : #endif
    4665             : 
    4666           0 :     if (path_and_dir_fd_invalid("utime", &path, dir_fd) ||
    4667           0 :         dir_fd_and_fd_invalid("utime", dir_fd, path.fd) ||
    4668           0 :         fd_and_follow_symlinks_invalid("utime", path.fd, follow_symlinks))
    4669             :         goto exit;
    4670             : 
    4671             : #if !defined(HAVE_UTIMENSAT)
    4672             :     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
    4673             :         PyErr_SetString(PyExc_ValueError,
    4674             :                      "utime: cannot use dir_fd and follow_symlinks "
    4675             :                      "together on this platform");
    4676             :         goto exit;
    4677             :     }
    4678             : #endif
    4679             : 
    4680             : #ifdef MS_WINDOWS
    4681             :     Py_BEGIN_ALLOW_THREADS
    4682             :     if (path.wide)
    4683             :         hFile = CreateFileW(path.wide, FILE_WRITE_ATTRIBUTES, 0,
    4684             :                             NULL, OPEN_EXISTING,
    4685             :                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
    4686             :     else
    4687             :         hFile = CreateFileA(path.narrow, FILE_WRITE_ATTRIBUTES, 0,
    4688             :                             NULL, OPEN_EXISTING,
    4689             :                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
    4690             :     Py_END_ALLOW_THREADS
    4691             :     if (hFile == INVALID_HANDLE_VALUE) {
    4692             :         win32_error_object("utime", path.object);
    4693             :         goto exit;
    4694             :     }
    4695             : 
    4696             :     if (utime.now) {
    4697             :         SYSTEMTIME now;
    4698             :         GetSystemTime(&now);
    4699             :         if (!SystemTimeToFileTime(&now, &mtime) ||
    4700             :             !SystemTimeToFileTime(&now, &atime)) {
    4701             :             win32_error("utime", NULL);
    4702             :             goto exit;
    4703             :         }
    4704             :     }
    4705             :     else {
    4706             :         time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
    4707             :         time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
    4708             :     }
    4709             :     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
    4710             :         /* Avoid putting the file name into the error here,
    4711             :            as that may confuse the user into believing that
    4712             :            something is wrong with the file, when it also
    4713             :            could be the time stamp that gives a problem. */
    4714             :         win32_error("utime", NULL);
    4715             :         goto exit;
    4716             :     }
    4717             : #else /* MS_WINDOWS */
    4718           0 :     Py_BEGIN_ALLOW_THREADS
    4719             : 
    4720             : #if UTIME_HAVE_NOFOLLOW_SYMLINKS
    4721           0 :     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
    4722           0 :         result = utime_nofollow_symlinks(&utime, path.narrow);
    4723             :     else
    4724             : #endif
    4725             : 
    4726             : #if UTIME_HAVE_DIR_FD
    4727           0 :     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
    4728           0 :         result = utime_dir_fd(&utime, dir_fd, path.narrow, follow_symlinks);
    4729             :     else
    4730             : #endif
    4731             : 
    4732             : #if UTIME_HAVE_FD
    4733           0 :     if (path.fd != -1)
    4734           0 :         result = utime_fd(&utime, path.fd);
    4735             :     else
    4736             : #endif
    4737             : 
    4738           0 :     result = utime_default(&utime, path.narrow);
    4739             : 
    4740           0 :     Py_END_ALLOW_THREADS
    4741             : 
    4742           0 :     if (result < 0) {
    4743             :         /* see previous comment about not putting filename in error here */
    4744           0 :         return_value = posix_error();
    4745           0 :         goto exit;
    4746             :     }
    4747             : 
    4748             : #endif /* MS_WINDOWS */
    4749             : 
    4750           0 :     Py_INCREF(Py_None);
    4751           0 :     return_value = Py_None;
    4752             : 
    4753             : exit:
    4754           0 :     path_cleanup(&path);
    4755             : #ifdef MS_WINDOWS
    4756             :     if (hFile != INVALID_HANDLE_VALUE)
    4757             :         CloseHandle(hFile);
    4758             : #endif
    4759           0 :     return return_value;
    4760             : }
    4761             : 
    4762             : /* Process operations */
    4763             : 
    4764             : PyDoc_STRVAR(posix__exit__doc__,
    4765             : "_exit(status)\n\n\
    4766             : Exit to the system with specified status, without normal exit processing.");
    4767             : 
    4768             : static PyObject *
    4769           0 : posix__exit(PyObject *self, PyObject *args)
    4770             : {
    4771             :     int sts;
    4772           0 :     if (!PyArg_ParseTuple(args, "i:_exit", &sts))
    4773           0 :         return NULL;
    4774           0 :     _exit(sts);
    4775             :     return NULL; /* Make gcc -Wall happy */
    4776             : }
    4777             : 
    4778             : #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
    4779             : static void
    4780           0 : free_string_array(char **array, Py_ssize_t count)
    4781             : {
    4782             :     Py_ssize_t i;
    4783           0 :     for (i = 0; i < count; i++)
    4784           0 :         PyMem_Free(array[i]);
    4785           0 :     PyMem_DEL(array);
    4786           0 : }
    4787             : 
    4788             : static
    4789           0 : int fsconvert_strdup(PyObject *o, char**out)
    4790             : {
    4791             :     PyObject *bytes;
    4792             :     Py_ssize_t size;
    4793           0 :     if (!PyUnicode_FSConverter(o, &bytes))
    4794           0 :         return 0;
    4795           0 :     size = PyBytes_GET_SIZE(bytes);
    4796           0 :     *out = PyMem_Malloc(size+1);
    4797           0 :     if (!*out)
    4798           0 :         return 0;
    4799           0 :     memcpy(*out, PyBytes_AsString(bytes), size+1);
    4800           0 :     Py_DECREF(bytes);
    4801           0 :     return 1;
    4802             : }
    4803             : #endif
    4804             : 
    4805             : #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE)
    4806             : static char**
    4807           0 : parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
    4808             : {
    4809             :     char **envlist;
    4810             :     Py_ssize_t i, pos, envc;
    4811           0 :     PyObject *keys=NULL, *vals=NULL;
    4812             :     PyObject *key, *val, *key2, *val2;
    4813             :     char *p, *k, *v;
    4814             :     size_t len;
    4815             : 
    4816           0 :     i = PyMapping_Size(env);
    4817           0 :     if (i < 0)
    4818           0 :         return NULL;
    4819           0 :     envlist = PyMem_NEW(char *, i + 1);
    4820           0 :     if (envlist == NULL) {
    4821           0 :         PyErr_NoMemory();
    4822           0 :         return NULL;
    4823             :     }
    4824           0 :     envc = 0;
    4825           0 :     keys = PyMapping_Keys(env);
    4826           0 :     vals = PyMapping_Values(env);
    4827           0 :     if (!keys || !vals)
    4828             :         goto error;
    4829           0 :     if (!PyList_Check(keys) || !PyList_Check(vals)) {
    4830           0 :         PyErr_Format(PyExc_TypeError,
    4831             :                      "env.keys() or env.values() is not a list");
    4832           0 :         goto error;
    4833             :     }
    4834             : 
    4835           0 :     for (pos = 0; pos < i; pos++) {
    4836           0 :         key = PyList_GetItem(keys, pos);
    4837           0 :         val = PyList_GetItem(vals, pos);
    4838           0 :         if (!key || !val)
    4839             :             goto error;
    4840             : 
    4841           0 :         if (PyUnicode_FSConverter(key, &key2) == 0)
    4842           0 :             goto error;
    4843           0 :         if (PyUnicode_FSConverter(val, &val2) == 0) {
    4844           0 :             Py_DECREF(key2);
    4845           0 :             goto error;
    4846             :         }
    4847             : 
    4848             : #if defined(PYOS_OS2)
    4849             :         /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
    4850             :         if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
    4851             : #endif
    4852           0 :         k = PyBytes_AsString(key2);
    4853           0 :         v = PyBytes_AsString(val2);
    4854           0 :         len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2;
    4855             : 
    4856           0 :         p = PyMem_NEW(char, len);
    4857           0 :         if (p == NULL) {
    4858           0 :             PyErr_NoMemory();
    4859           0 :             Py_DECREF(key2);
    4860           0 :             Py_DECREF(val2);
    4861           0 :             goto error;
    4862             :         }
    4863           0 :         PyOS_snprintf(p, len, "%s=%s", k, v);
    4864           0 :         envlist[envc++] = p;
    4865           0 :         Py_DECREF(key2);
    4866           0 :         Py_DECREF(val2);
    4867             : #if defined(PYOS_OS2)
    4868             :         }
    4869             : #endif
    4870             :     }
    4871           0 :     Py_DECREF(vals);
    4872           0 :     Py_DECREF(keys);
    4873             : 
    4874           0 :     envlist[envc] = 0;
    4875           0 :     *envc_ptr = envc;
    4876           0 :     return envlist;
    4877             : 
    4878             : error:
    4879           0 :     Py_XDECREF(keys);
    4880           0 :     Py_XDECREF(vals);
    4881           0 :     while (--envc >= 0)
    4882           0 :         PyMem_DEL(envlist[envc]);
    4883           0 :     PyMem_DEL(envlist);
    4884           0 :     return NULL;
    4885             : }
    4886             : 
    4887             : static char**
    4888           0 : parse_arglist(PyObject* argv, Py_ssize_t *argc)
    4889             : {
    4890             :     int i;
    4891           0 :     char **argvlist = PyMem_NEW(char *, *argc+1);
    4892           0 :     if (argvlist == NULL) {
    4893           0 :         PyErr_NoMemory();
    4894           0 :         return NULL;
    4895             :     }
    4896           0 :     for (i = 0; i < *argc; i++) {
    4897           0 :         PyObject* item = PySequence_ITEM(argv, i);
    4898           0 :         if (item == NULL)
    4899           0 :             goto fail;
    4900           0 :         if (!fsconvert_strdup(item, &argvlist[i])) {
    4901           0 :             Py_DECREF(item);
    4902           0 :             goto fail;
    4903             :         }
    4904           0 :         Py_DECREF(item);
    4905             :     }
    4906           0 :     argvlist[*argc] = NULL;
    4907           0 :     return argvlist;
    4908             : fail:
    4909           0 :     *argc = i;
    4910           0 :     free_string_array(argvlist, *argc);
    4911           0 :     return NULL;
    4912             : }
    4913             : #endif
    4914             : 
    4915             : #ifdef HAVE_EXECV
    4916             : PyDoc_STRVAR(posix_execv__doc__,
    4917             : "execv(path, args)\n\n\
    4918             : Execute an executable path with arguments, replacing current process.\n\
    4919             : \n\
    4920             :     path: path of executable file\n\
    4921             :     args: tuple or list of strings");
    4922             : 
    4923             : static PyObject *
    4924           0 : posix_execv(PyObject *self, PyObject *args)
    4925             : {
    4926             :     PyObject *opath;
    4927             :     char *path;
    4928             :     PyObject *argv;
    4929             :     char **argvlist;
    4930             :     Py_ssize_t argc;
    4931             : 
    4932             :     /* execv has two arguments: (path, argv), where
    4933             :        argv is a list or tuple of strings. */
    4934             : 
    4935           0 :     if (!PyArg_ParseTuple(args, "O&O:execv",
    4936             :                           PyUnicode_FSConverter,
    4937             :                           &opath, &argv))
    4938           0 :         return NULL;
    4939           0 :     path = PyBytes_AsString(opath);
    4940           0 :     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
    4941           0 :         PyErr_SetString(PyExc_TypeError,
    4942             :                         "execv() arg 2 must be a tuple or list");
    4943           0 :         Py_DECREF(opath);
    4944           0 :         return NULL;
    4945             :     }
    4946           0 :     argc = PySequence_Size(argv);
    4947           0 :     if (argc < 1) {
    4948           0 :         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
    4949           0 :         Py_DECREF(opath);
    4950           0 :         return NULL;
    4951             :     }
    4952             : 
    4953           0 :     argvlist = parse_arglist(argv, &argc);
    4954           0 :     if (argvlist == NULL) {
    4955           0 :         Py_DECREF(opath);
    4956           0 :         return NULL;
    4957             :     }
    4958             : 
    4959           0 :     execv(path, argvlist);
    4960             : 
    4961             :     /* If we get here it's definitely an error */
    4962             : 
    4963           0 :     free_string_array(argvlist, argc);
    4964           0 :     Py_DECREF(opath);
    4965           0 :     return posix_error();
    4966             : }
    4967             : 
    4968             : PyDoc_STRVAR(posix_execve__doc__,
    4969             : "execve(path, args, env)\n\n\
    4970             : Execute a path with arguments and environment, replacing current process.\n\
    4971             : \n\
    4972             :     path: path of executable file\n\
    4973             :     args: tuple or list of arguments\n\
    4974             :     env: dictionary of strings mapping to strings\n\
    4975             : \n\
    4976             : On some platforms, you may specify an open file descriptor for path;\n\
    4977             :   execve will execute the program the file descriptor is open to.\n\
    4978             :   If this functionality is unavailable, using it raises NotImplementedError.");
    4979             : 
    4980             : static PyObject *
    4981           0 : posix_execve(PyObject *self, PyObject *args, PyObject *kwargs)
    4982             : {
    4983             :     path_t path;
    4984             :     PyObject *argv, *env;
    4985           0 :     char **argvlist = NULL;
    4986             :     char **envlist;
    4987             :     Py_ssize_t argc, envc;
    4988             :     static char *keywords[] = {"path", "argv", "environment", NULL};
    4989             : 
    4990             :     /* execve has three arguments: (path, argv, env), where
    4991             :        argv is a list or tuple of strings and env is a dictionary
    4992             :        like posix.environ. */
    4993             : 
    4994           0 :     memset(&path, 0, sizeof(path));
    4995             : #ifdef HAVE_FEXECVE
    4996           0 :     path.allow_fd = 1;
    4997             : #endif
    4998           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&OO:execve", keywords,
    4999             :                           path_converter, &path,
    5000             :                           &argv, &env
    5001             :                           ))
    5002           0 :         return NULL;
    5003             : 
    5004           0 :     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
    5005           0 :         PyErr_SetString(PyExc_TypeError,
    5006             :                         "execve: argv must be a tuple or list");
    5007           0 :         goto fail;
    5008             :     }
    5009           0 :     argc = PySequence_Size(argv);
    5010           0 :     if (!PyMapping_Check(env)) {
    5011           0 :         PyErr_SetString(PyExc_TypeError,
    5012             :                         "execve: environment must be a mapping object");
    5013           0 :         goto fail;
    5014             :     }
    5015             : 
    5016           0 :     argvlist = parse_arglist(argv, &argc);
    5017           0 :     if (argvlist == NULL) {
    5018           0 :         goto fail;
    5019             :     }
    5020             : 
    5021           0 :     envlist = parse_envlist(env, &envc);
    5022           0 :     if (envlist == NULL)
    5023           0 :         goto fail;
    5024             : 
    5025             : #ifdef HAVE_FEXECVE
    5026           0 :     if (path.fd > -1)
    5027           0 :         fexecve(path.fd, argvlist, envlist);
    5028             :     else
    5029             : #endif
    5030           0 :         execve(path.narrow, argvlist, envlist);
    5031             : 
    5032             :     /* If we get here it's definitely an error */
    5033             : 
    5034           0 :     path_posix_error("execve", &path);
    5035             : 
    5036           0 :     while (--envc >= 0)
    5037           0 :         PyMem_DEL(envlist[envc]);
    5038           0 :     PyMem_DEL(envlist);
    5039             :   fail:
    5040           0 :     if (argvlist)
    5041           0 :         free_string_array(argvlist, argc);
    5042           0 :     path_cleanup(&path);
    5043           0 :     return NULL;
    5044             : }
    5045             : #endif /* HAVE_EXECV */
    5046             : 
    5047             : 
    5048             : #ifdef HAVE_SPAWNV
    5049             : PyDoc_STRVAR(posix_spawnv__doc__,
    5050             : "spawnv(mode, path, args)\n\n\
    5051             : Execute the program 'path' in a new process.\n\
    5052             : \n\
    5053             :     mode: mode of process creation\n\
    5054             :     path: path of executable file\n\
    5055             :     args: tuple or list of strings");
    5056             : 
    5057             : static PyObject *
    5058             : posix_spawnv(PyObject *self, PyObject *args)
    5059             : {
    5060             :     PyObject *opath;
    5061             :     char *path;
    5062             :     PyObject *argv;
    5063             :     char **argvlist;
    5064             :     int mode, i;
    5065             :     Py_ssize_t argc;
    5066             :     Py_intptr_t spawnval;
    5067             :     PyObject *(*getitem)(PyObject *, Py_ssize_t);
    5068             : 
    5069             :     /* spawnv has three arguments: (mode, path, argv), where
    5070             :        argv is a list or tuple of strings. */
    5071             : 
    5072             :     if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode,
    5073             :                           PyUnicode_FSConverter,
    5074             :                           &opath, &argv))
    5075             :         return NULL;
    5076             :     path = PyBytes_AsString(opath);
    5077             :     if (PyList_Check(argv)) {
    5078             :         argc = PyList_Size(argv);
    5079             :         getitem = PyList_GetItem;
    5080             :     }
    5081             :     else if (PyTuple_Check(argv)) {
    5082             :         argc = PyTuple_Size(argv);
    5083             :         getitem = PyTuple_GetItem;
    5084             :     }
    5085             :     else {
    5086             :         PyErr_SetString(PyExc_TypeError,
    5087             :                         "spawnv() arg 2 must be a tuple or list");
    5088             :         Py_DECREF(opath);
    5089             :         return NULL;
    5090             :     }
    5091             : 
    5092             :     argvlist = PyMem_NEW(char *, argc+1);
    5093             :     if (argvlist == NULL) {
    5094             :         Py_DECREF(opath);
    5095             :         return PyErr_NoMemory();
    5096             :     }
    5097             :     for (i = 0; i < argc; i++) {
    5098             :         if (!fsconvert_strdup((*getitem)(argv, i),
    5099             :                               &argvlist[i])) {
    5100             :             free_string_array(argvlist, i);
    5101             :             PyErr_SetString(
    5102             :                 PyExc_TypeError,
    5103             :                 "spawnv() arg 2 must contain only strings");
    5104             :             Py_DECREF(opath);
    5105             :             return NULL;
    5106             :         }
    5107             :     }
    5108             :     argvlist[argc] = NULL;
    5109             : 
    5110             : #if defined(PYOS_OS2) && defined(PYCC_GCC)
    5111             :     Py_BEGIN_ALLOW_THREADS
    5112             :     spawnval = spawnv(mode, path, argvlist);
    5113             :     Py_END_ALLOW_THREADS
    5114             : #else
    5115             :     if (mode == _OLD_P_OVERLAY)
    5116             :         mode = _P_OVERLAY;
    5117             : 
    5118             :     Py_BEGIN_ALLOW_THREADS
    5119             :     spawnval = _spawnv(mode, path, argvlist);
    5120             :     Py_END_ALLOW_THREADS
    5121             : #endif
    5122             : 
    5123             :     free_string_array(argvlist, argc);
    5124             :     Py_DECREF(opath);
    5125             : 
    5126             :     if (spawnval == -1)
    5127             :         return posix_error();
    5128             :     else
    5129             : #if SIZEOF_LONG == SIZEOF_VOID_P
    5130             :         return Py_BuildValue("l", (long) spawnval);
    5131             : #else
    5132             :         return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
    5133             : #endif
    5134             : }
    5135             : 
    5136             : 
    5137             : PyDoc_STRVAR(posix_spawnve__doc__,
    5138             : "spawnve(mode, path, args, env)\n\n\
    5139             : Execute the program 'path' in a new process.\n\
    5140             : \n\
    5141             :     mode: mode of process creation\n\
    5142             :     path: path of executable file\n\
    5143             :     args: tuple or list of arguments\n\
    5144             :     env: dictionary of strings mapping to strings");
    5145             : 
    5146             : static PyObject *
    5147             : posix_spawnve(PyObject *self, PyObject *args)
    5148             : {
    5149             :     PyObject *opath;
    5150             :     char *path;
    5151             :     PyObject *argv, *env;
    5152             :     char **argvlist;
    5153             :     char **envlist;
    5154             :     PyObject *res = NULL;
    5155             :     int mode;
    5156             :     Py_ssize_t argc, i, envc;
    5157             :     Py_intptr_t spawnval;
    5158             :     PyObject *(*getitem)(PyObject *, Py_ssize_t);
    5159             :     Py_ssize_t lastarg = 0;
    5160             : 
    5161             :     /* spawnve has four arguments: (mode, path, argv, env), where
    5162             :        argv is a list or tuple of strings and env is a dictionary
    5163             :        like posix.environ. */
    5164             : 
    5165             :     if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode,
    5166             :                           PyUnicode_FSConverter,
    5167             :                           &opath, &argv, &env))
    5168             :         return NULL;
    5169             :     path = PyBytes_AsString(opath);
    5170             :     if (PyList_Check(argv)) {
    5171             :         argc = PyList_Size(argv);
    5172             :         getitem = PyList_GetItem;
    5173             :     }
    5174             :     else if (PyTuple_Check(argv)) {
    5175             :         argc = PyTuple_Size(argv);
    5176             :         getitem = PyTuple_GetItem;
    5177             :     }
    5178             :     else {
    5179             :         PyErr_SetString(PyExc_TypeError,
    5180             :                         "spawnve() arg 2 must be a tuple or list");
    5181             :         goto fail_0;
    5182             :     }
    5183             :     if (!PyMapping_Check(env)) {
    5184             :         PyErr_SetString(PyExc_TypeError,
    5185             :                         "spawnve() arg 3 must be a mapping object");
    5186             :         goto fail_0;
    5187             :     }
    5188             : 
    5189             :     argvlist = PyMem_NEW(char *, argc+1);
    5190             :     if (argvlist == NULL) {
    5191             :         PyErr_NoMemory();
    5192             :         goto fail_0;
    5193             :     }
    5194             :     for (i = 0; i < argc; i++) {
    5195             :         if (!fsconvert_strdup((*getitem)(argv, i),
    5196             :                               &argvlist[i]))
    5197             :         {
    5198             :             lastarg = i;
    5199             :             goto fail_1;
    5200             :         }
    5201             :     }
    5202             :     lastarg = argc;
    5203             :     argvlist[argc] = NULL;
    5204             : 
    5205             :     envlist = parse_envlist(env, &envc);
    5206             :     if (envlist == NULL)
    5207             :         goto fail_1;
    5208             : 
    5209             : #if defined(PYOS_OS2) && defined(PYCC_GCC)
    5210             :     Py_BEGIN_ALLOW_THREADS
    5211             :     spawnval = spawnve(mode, path, argvlist, envlist);
    5212             :     Py_END_ALLOW_THREADS
    5213             : #else
    5214             :     if (mode == _OLD_P_OVERLAY)
    5215             :         mode = _P_OVERLAY;
    5216             : 
    5217             :     Py_BEGIN_ALLOW_THREADS
    5218             :     spawnval = _spawnve(mode, path, argvlist, envlist);
    5219             :     Py_END_ALLOW_THREADS
    5220             : #endif
    5221             : 
    5222             :     if (spawnval == -1)
    5223             :         (void) posix_error();
    5224             :     else
    5225             : #if SIZEOF_LONG == SIZEOF_VOID_P
    5226             :         res = Py_BuildValue("l", (long) spawnval);
    5227             : #else
    5228             :         res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
    5229             : #endif
    5230             : 
    5231             :     while (--envc >= 0)
    5232             :         PyMem_DEL(envlist[envc]);
    5233             :     PyMem_DEL(envlist);
    5234             :   fail_1:
    5235             :     free_string_array(argvlist, lastarg);
    5236             :   fail_0:
    5237             :     Py_DECREF(opath);
    5238             :     return res;
    5239             : }
    5240             : 
    5241             : /* OS/2 supports spawnvp & spawnvpe natively */
    5242             : #if defined(PYOS_OS2)
    5243             : PyDoc_STRVAR(posix_spawnvp__doc__,
    5244             : "spawnvp(mode, file, args)\n\n\
    5245             : Execute the program 'file' in a new process, using the environment\n\
    5246             : search path to find the file.\n\
    5247             : \n\
    5248             :     mode: mode of process creation\n\
    5249             :     file: executable file name\n\
    5250             :     args: tuple or list of strings");
    5251             : 
    5252             : static PyObject *
    5253             : posix_spawnvp(PyObject *self, PyObject *args)
    5254             : {
    5255             :     PyObject *opath;
    5256             :     char *path;
    5257             :     PyObject *argv;
    5258             :     char **argvlist;
    5259             :     int mode, i, argc;
    5260             :     Py_intptr_t spawnval;
    5261             :     PyObject *(*getitem)(PyObject *, Py_ssize_t);
    5262             : 
    5263             :     /* spawnvp has three arguments: (mode, path, argv), where
    5264             :        argv is a list or tuple of strings. */
    5265             : 
    5266             :     if (!PyArg_ParseTuple(args, "iO&O:spawnvp", &mode,
    5267             :                           PyUnicode_FSConverter,
    5268             :                           &opath, &argv))
    5269             :         return NULL;
    5270             :     path = PyBytes_AsString(opath);
    5271             :     if (PyList_Check(argv)) {
    5272             :         argc = PyList_Size(argv);
    5273             :         getitem = PyList_GetItem;
    5274             :     }
    5275             :     else if (PyTuple_Check(argv)) {
    5276             :         argc = PyTuple_Size(argv);
    5277             :         getitem = PyTuple_GetItem;
    5278             :     }
    5279             :     else {
    5280             :         PyErr_SetString(PyExc_TypeError,
    5281             :                         "spawnvp() arg 2 must be a tuple or list");
    5282             :         Py_DECREF(opath);
    5283             :         return NULL;
    5284             :     }
    5285             : 
    5286             :     argvlist = PyMem_NEW(char *, argc+1);
    5287             :     if (argvlist == NULL) {
    5288             :         Py_DECREF(opath);
    5289             :         return PyErr_NoMemory();
    5290             :     }
    5291             :     for (i = 0; i < argc; i++) {
    5292             :         if (!fsconvert_strdup((*getitem)(argv, i),
    5293             :                               &argvlist[i])) {
    5294             :             free_string_array(argvlist, i);
    5295             :             PyErr_SetString(
    5296             :                 PyExc_TypeError,
    5297             :                 "spawnvp() arg 2 must contain only strings");
    5298             :             Py_DECREF(opath);
    5299             :             return NULL;
    5300             :         }
    5301             :     }
    5302             :     argvlist[argc] = NULL;
    5303             : 
    5304             :     Py_BEGIN_ALLOW_THREADS
    5305             : #if defined(PYCC_GCC)
    5306             :     spawnval = spawnvp(mode, path, argvlist);
    5307             : #else
    5308             :     spawnval = _spawnvp(mode, path, argvlist);
    5309             : #endif
    5310             :     Py_END_ALLOW_THREADS
    5311             : 
    5312             :     free_string_array(argvlist, argc);
    5313             :     Py_DECREF(opath);
    5314             : 
    5315             :     if (spawnval == -1)
    5316             :         return posix_error();
    5317             :     else
    5318             :         return Py_BuildValue("l", (long) spawnval);
    5319             : }
    5320             : 
    5321             : 
    5322             : PyDoc_STRVAR(posix_spawnvpe__doc__,
    5323             : "spawnvpe(mode, file, args, env)\n\n\
    5324             : Execute the program 'file' in a new process, using the environment\n\
    5325             : search path to find the file.\n\
    5326             : \n\
    5327             :     mode: mode of process creation\n\
    5328             :     file: executable file name\n\
    5329             :     args: tuple or list of arguments\n\
    5330             :     env: dictionary of strings mapping to strings");
    5331             : 
    5332             : static PyObject *
    5333             : posix_spawnvpe(PyObject *self, PyObject *args)
    5334             : {
    5335             :     PyObject *opath;
    5336             :     char *path;
    5337             :     PyObject *argv, *env;
    5338             :     char **argvlist;
    5339             :     char **envlist;
    5340             :     PyObject *res=NULL;
    5341             :     int mode;
    5342             :     Py_ssize_t argc, i, envc;
    5343             :     Py_intptr_t spawnval;
    5344             :     PyObject *(*getitem)(PyObject *, Py_ssize_t);
    5345             :     int lastarg = 0;
    5346             : 
    5347             :     /* spawnvpe has four arguments: (mode, path, argv, env), where
    5348             :        argv is a list or tuple of strings and env is a dictionary
    5349             :        like posix.environ. */
    5350             : 
    5351             :     if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
    5352             :                           PyUnicode_FSConverter,
    5353             :                           &opath, &argv, &env))
    5354             :         return NULL;
    5355             :     path = PyBytes_AsString(opath);
    5356             :     if (PyList_Check(argv)) {
    5357             :         argc = PyList_Size(argv);
    5358             :         getitem = PyList_GetItem;
    5359             :     }
    5360             :     else if (PyTuple_Check(argv)) {
    5361             :         argc = PyTuple_Size(argv);
    5362             :         getitem = PyTuple_GetItem;
    5363             :     }
    5364             :     else {
    5365             :         PyErr_SetString(PyExc_TypeError,
    5366             :                         "spawnvpe() arg 2 must be a tuple or list");
    5367             :         goto fail_0;
    5368             :     }
    5369             :     if (!PyMapping_Check(env)) {
    5370             :         PyErr_SetString(PyExc_TypeError,
    5371             :                         "spawnvpe() arg 3 must be a mapping object");
    5372             :         goto fail_0;
    5373             :     }
    5374             : 
    5375             :     argvlist = PyMem_NEW(char *, argc+1);
    5376             :     if (argvlist == NULL) {
    5377             :         PyErr_NoMemory();
    5378             :         goto fail_0;
    5379             :     }
    5380             :     for (i = 0; i < argc; i++) {
    5381             :         if (!fsconvert_strdup((*getitem)(argv, i),
    5382             :                               &argvlist[i]))
    5383             :         {
    5384             :             lastarg = i;
    5385             :             goto fail_1;
    5386             :         }
    5387             :     }
    5388             :     lastarg = argc;
    5389             :     argvlist[argc] = NULL;
    5390             : 
    5391             :     envlist = parse_envlist(env, &envc);
    5392             :     if (envlist == NULL)
    5393             :         goto fail_1;
    5394             : 
    5395             :     Py_BEGIN_ALLOW_THREADS
    5396             : #if defined(PYCC_GCC)
    5397             :     spawnval = spawnvpe(mode, path, argvlist, envlist);
    5398             : #else
    5399             :     spawnval = _spawnvpe(mode, path, argvlist, envlist);
    5400             : #endif
    5401             :     Py_END_ALLOW_THREADS
    5402             : 
    5403             :     if (spawnval == -1)
    5404             :         (void) posix_error();
    5405             :     else
    5406             :         res = Py_BuildValue("l", (long) spawnval);
    5407             : 
    5408             :     while (--envc >= 0)
    5409             :         PyMem_DEL(envlist[envc]);
    5410             :     PyMem_DEL(envlist);
    5411             :   fail_1:
    5412             :     free_string_array(argvlist, lastarg);
    5413             :   fail_0:
    5414             :     Py_DECREF(opath);
    5415             :     return res;
    5416             : }
    5417             : #endif /* PYOS_OS2 */
    5418             : #endif /* HAVE_SPAWNV */
    5419             : 
    5420             : 
    5421             : #ifdef HAVE_FORK1
    5422             : PyDoc_STRVAR(posix_fork1__doc__,
    5423             : "fork1() -> pid\n\n\
    5424             : Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
    5425             : \n\
    5426             : Return 0 to child process and PID of child to parent process.");
    5427             : 
    5428             : static PyObject *
    5429             : posix_fork1(PyObject *self, PyObject *noargs)
    5430             : {
    5431             :     pid_t pid;
    5432             :     int result = 0;
    5433             :     _PyImport_AcquireLock();
    5434             :     pid = fork1();
    5435             :     if (pid == 0) {
    5436             :         /* child: this clobbers and resets the import lock. */
    5437             :         PyOS_AfterFork();
    5438             :     } else {
    5439             :         /* parent: release the import lock. */
    5440             :         result = _PyImport_ReleaseLock();
    5441             :     }
    5442             :     if (pid == -1)
    5443             :         return posix_error();
    5444             :     if (result < 0) {
    5445             :         /* Don't clobber the OSError if the fork failed. */
    5446             :         PyErr_SetString(PyExc_RuntimeError,
    5447             :                         "not holding the import lock");
    5448             :         return NULL;
    5449             :     }
    5450             :     return PyLong_FromPid(pid);
    5451             : }
    5452             : #endif
    5453             : 
    5454             : 
    5455             : #ifdef HAVE_FORK
    5456             : PyDoc_STRVAR(posix_fork__doc__,
    5457             : "fork() -> pid\n\n\
    5458             : Fork a child process.\n\
    5459             : Return 0 to child process and PID of child to parent process.");
    5460             : 
    5461             : static PyObject *
    5462           0 : posix_fork(PyObject *self, PyObject *noargs)
    5463             : {
    5464             :     pid_t pid;
    5465           0 :     int result = 0;
    5466           0 :     _PyImport_AcquireLock();
    5467           0 :     pid = fork();
    5468           0 :     if (pid == 0) {
    5469             :         /* child: this clobbers and resets the import lock. */
    5470           0 :         PyOS_AfterFork();
    5471             :     } else {
    5472             :         /* parent: release the import lock. */
    5473           0 :         result = _PyImport_ReleaseLock();
    5474             :     }
    5475           0 :     if (pid == -1)
    5476           0 :         return posix_error();
    5477           0 :     if (result < 0) {
    5478             :         /* Don't clobber the OSError if the fork failed. */
    5479           0 :         PyErr_SetString(PyExc_RuntimeError,
    5480             :                         "not holding the import lock");
    5481           0 :         return NULL;
    5482             :     }
    5483           0 :     return PyLong_FromPid(pid);
    5484             : }
    5485             : #endif
    5486             : 
    5487             : #ifdef HAVE_SCHED_H
    5488             : 
    5489             : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
    5490             : 
    5491             : PyDoc_STRVAR(posix_sched_get_priority_max__doc__,
    5492             : "sched_get_priority_max(policy)\n\n\
    5493             : Get the maximum scheduling priority for *policy*.");
    5494             : 
    5495             : static PyObject *
    5496           0 : posix_sched_get_priority_max(PyObject *self, PyObject *args)
    5497             : {
    5498             :     int policy, max;
    5499             : 
    5500           0 :     if (!PyArg_ParseTuple(args, "i:sched_get_priority_max", &policy))
    5501           0 :         return NULL;
    5502           0 :     max = sched_get_priority_max(policy);
    5503           0 :     if (max < 0)
    5504           0 :         return posix_error();
    5505           0 :     return PyLong_FromLong(max);
    5506             : }
    5507             : 
    5508             : PyDoc_STRVAR(posix_sched_get_priority_min__doc__,
    5509             : "sched_get_priority_min(policy)\n\n\
    5510             : Get the minimum scheduling priority for *policy*.");
    5511             : 
    5512             : static PyObject *
    5513           0 : posix_sched_get_priority_min(PyObject *self, PyObject *args)
    5514             : {
    5515             :     int policy, min;
    5516             : 
    5517           0 :     if (!PyArg_ParseTuple(args, "i:sched_get_priority_min", &policy))
    5518           0 :         return NULL;
    5519           0 :     min = sched_get_priority_min(policy);
    5520           0 :     if (min < 0)
    5521           0 :         return posix_error();
    5522           0 :     return PyLong_FromLong(min);
    5523             : }
    5524             : 
    5525             : #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
    5526             : 
    5527             : #ifdef HAVE_SCHED_SETSCHEDULER
    5528             : 
    5529             : PyDoc_STRVAR(posix_sched_getscheduler__doc__,
    5530             : "sched_getscheduler(pid)\n\n\
    5531             : Get the scheduling policy for the process with a PID of *pid*.\n\
    5532             : Passing a PID of 0 returns the scheduling policy for the calling process.");
    5533             : 
    5534             : static PyObject *
    5535           0 : posix_sched_getscheduler(PyObject *self, PyObject *args)
    5536             : {
    5537             :     pid_t pid;
    5538             :     int policy;
    5539             : 
    5540           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getscheduler", &pid))
    5541           0 :         return NULL;
    5542           0 :     policy = sched_getscheduler(pid);
    5543           0 :     if (policy < 0)
    5544           0 :         return posix_error();
    5545           0 :     return PyLong_FromLong(policy);
    5546             : }
    5547             : 
    5548             : #endif
    5549             : 
    5550             : #if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM)
    5551             : 
    5552             : static PyObject *
    5553           0 : sched_param_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    5554             : {
    5555             :     PyObject *res, *priority;
    5556             :     static char *kwlist[] = {"sched_priority", NULL};
    5557             : 
    5558           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:sched_param", kwlist, &priority))
    5559           0 :         return NULL;
    5560           0 :     res = PyStructSequence_New(type);
    5561           0 :     if (!res)
    5562           0 :         return NULL;
    5563           0 :     Py_INCREF(priority);
    5564           0 :     PyStructSequence_SET_ITEM(res, 0, priority);
    5565           0 :     return res;
    5566             : }
    5567             : 
    5568             : PyDoc_STRVAR(sched_param__doc__,
    5569             : "sched_param(sched_priority): A scheduling parameter.\n\n\
    5570             : Current has only one field: sched_priority");
    5571             : 
    5572             : static PyStructSequence_Field sched_param_fields[] = {
    5573             :     {"sched_priority", "the scheduling priority"},
    5574             :     {0}
    5575             : };
    5576             : 
    5577             : static PyStructSequence_Desc sched_param_desc = {
    5578             :     "sched_param", /* name */
    5579             :     sched_param__doc__, /* doc */
    5580             :     sched_param_fields,
    5581             :     1
    5582             : };
    5583             : 
    5584             : static int
    5585           0 : convert_sched_param(PyObject *param, struct sched_param *res)
    5586             : {
    5587             :     long priority;
    5588             : 
    5589           0 :     if (Py_TYPE(param) != &SchedParamType) {
    5590           0 :         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
    5591           0 :         return 0;
    5592             :     }
    5593           0 :     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
    5594           0 :     if (priority == -1 && PyErr_Occurred())
    5595           0 :         return 0;
    5596             :     if (priority > INT_MAX || priority < INT_MIN) {
    5597             :         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
    5598             :         return 0;
    5599             :     }
    5600           0 :     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
    5601           0 :     return 1;
    5602             : }
    5603             : 
    5604             : #endif
    5605             : 
    5606             : #ifdef HAVE_SCHED_SETSCHEDULER
    5607             : 
    5608             : PyDoc_STRVAR(posix_sched_setscheduler__doc__,
    5609             : "sched_setscheduler(pid, policy, param)\n\n\
    5610             : Set the scheduling policy, *policy*, for *pid*.\n\
    5611             : If *pid* is 0, the calling process is changed.\n\
    5612             : *param* is an instance of sched_param.");
    5613             : 
    5614             : static PyObject *
    5615           0 : posix_sched_setscheduler(PyObject *self, PyObject *args)
    5616             : {
    5617             :     pid_t pid;
    5618             :     int policy;
    5619             :     struct sched_param param;
    5620             : 
    5621           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "iO&:sched_setscheduler",
    5622             :                           &pid, &policy, &convert_sched_param, &param))
    5623           0 :         return NULL;
    5624             : 
    5625             :     /*
    5626             :     ** sched_setscheduler() returns 0 in Linux, but the previous
    5627             :     ** scheduling policy under Solaris/Illumos, and others.
    5628             :     ** On error, -1 is returned in all Operating Systems.
    5629             :     */
    5630           0 :     if (sched_setscheduler(pid, policy, &param) == -1)
    5631           0 :         return posix_error();
    5632           0 :     Py_RETURN_NONE;
    5633             : }
    5634             : 
    5635             : #endif
    5636             : 
    5637             : #ifdef HAVE_SCHED_SETPARAM
    5638             : 
    5639             : PyDoc_STRVAR(posix_sched_getparam__doc__,
    5640             : "sched_getparam(pid) -> sched_param\n\n\
    5641             : Returns scheduling parameters for the process with *pid* as an instance of the\n\
    5642             : sched_param class. A PID of 0 means the calling process.");
    5643             : 
    5644             : static PyObject *
    5645           0 : posix_sched_getparam(PyObject *self, PyObject *args)
    5646             : {
    5647             :     pid_t pid;
    5648             :     struct sched_param param;
    5649             :     PyObject *res, *priority;
    5650             : 
    5651           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getparam", &pid))
    5652           0 :         return NULL;
    5653           0 :     if (sched_getparam(pid, &param))
    5654           0 :         return posix_error();
    5655           0 :     res = PyStructSequence_New(&SchedParamType);
    5656           0 :     if (!res)
    5657           0 :         return NULL;
    5658           0 :     priority = PyLong_FromLong(param.sched_priority);
    5659           0 :     if (!priority) {
    5660           0 :         Py_DECREF(res);
    5661           0 :         return NULL;
    5662             :     }
    5663           0 :     PyStructSequence_SET_ITEM(res, 0, priority);
    5664           0 :     return res;
    5665             : }
    5666             : 
    5667             : PyDoc_STRVAR(posix_sched_setparam__doc__,
    5668             : "sched_setparam(pid, param)\n\n\
    5669             : Set scheduling parameters for a process with PID *pid*.\n\
    5670             : A PID of 0 means the calling process.");
    5671             : 
    5672             : static PyObject *
    5673           0 : posix_sched_setparam(PyObject *self, PyObject *args)
    5674             : {
    5675             :     pid_t pid;
    5676             :     struct sched_param param;
    5677             : 
    5678           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O&:sched_setparam",
    5679             :                           &pid, &convert_sched_param, &param))
    5680           0 :         return NULL;
    5681           0 :     if (sched_setparam(pid, &param))
    5682           0 :         return posix_error();
    5683           0 :     Py_RETURN_NONE;
    5684             : }
    5685             : 
    5686             : #endif
    5687             : 
    5688             : #ifdef HAVE_SCHED_RR_GET_INTERVAL
    5689             : 
    5690             : PyDoc_STRVAR(posix_sched_rr_get_interval__doc__,
    5691             : "sched_rr_get_interval(pid) -> float\n\n\
    5692             : Return the round-robin quantum for the process with PID *pid* in seconds.");
    5693             : 
    5694             : static PyObject *
    5695           0 : posix_sched_rr_get_interval(PyObject *self, PyObject *args)
    5696             : {
    5697             :     pid_t pid;
    5698             :     struct timespec interval;
    5699             : 
    5700           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_rr_get_interval", &pid))
    5701           0 :         return NULL;
    5702           0 :     if (sched_rr_get_interval(pid, &interval))
    5703           0 :         return posix_error();
    5704           0 :     return PyFloat_FromDouble((double)interval.tv_sec + 1e-9*interval.tv_nsec);
    5705             : }
    5706             : 
    5707             : #endif
    5708             : 
    5709             : PyDoc_STRVAR(posix_sched_yield__doc__,
    5710             : "sched_yield()\n\n\
    5711             : Voluntarily relinquish the CPU.");
    5712             : 
    5713             : static PyObject *
    5714           0 : posix_sched_yield(PyObject *self, PyObject *noargs)
    5715             : {
    5716           0 :     if (sched_yield())
    5717           0 :         return posix_error();
    5718           0 :     Py_RETURN_NONE;
    5719             : }
    5720             : 
    5721             : #ifdef HAVE_SCHED_SETAFFINITY
    5722             : 
    5723             : /* The minimum number of CPUs allocated in a cpu_set_t */
    5724             : static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
    5725             : 
    5726             : PyDoc_STRVAR(posix_sched_setaffinity__doc__,
    5727             : "sched_setaffinity(pid, cpu_set)\n\n\
    5728             : Set the affinity of the process with PID *pid* to *cpu_set*.");
    5729             : 
    5730             : static PyObject *
    5731           0 : posix_sched_setaffinity(PyObject *self, PyObject *args)
    5732             : {
    5733             :     pid_t pid;
    5734             :     int ncpus;
    5735             :     size_t setsize;
    5736           0 :     cpu_set_t *mask = NULL;
    5737           0 :     PyObject *iterable, *iterator = NULL, *item;
    5738             : 
    5739           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity",
    5740             :                           &pid, &iterable))
    5741           0 :         return NULL;
    5742             : 
    5743           0 :     iterator = PyObject_GetIter(iterable);
    5744           0 :     if (iterator == NULL)
    5745           0 :         return NULL;
    5746             : 
    5747           0 :     ncpus = NCPUS_START;
    5748           0 :     setsize = CPU_ALLOC_SIZE(ncpus);
    5749           0 :     mask = CPU_ALLOC(ncpus);
    5750           0 :     if (mask == NULL) {
    5751           0 :         PyErr_NoMemory();
    5752           0 :         goto error;
    5753             :     }
    5754           0 :     CPU_ZERO_S(setsize, mask);
    5755             : 
    5756           0 :     while ((item = PyIter_Next(iterator))) {
    5757             :         long cpu;
    5758           0 :         if (!PyLong_Check(item)) {
    5759           0 :             PyErr_Format(PyExc_TypeError,
    5760             :                         "expected an iterator of ints, "
    5761             :                         "but iterator yielded %R",
    5762             :                         Py_TYPE(item));
    5763           0 :             Py_DECREF(item);
    5764           0 :             goto error;
    5765             :         }
    5766           0 :         cpu = PyLong_AsLong(item);
    5767           0 :         Py_DECREF(item);
    5768           0 :         if (cpu < 0) {
    5769           0 :             if (!PyErr_Occurred())
    5770           0 :                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
    5771           0 :             goto error;
    5772             :         }
    5773           0 :         if (cpu > INT_MAX - 1) {
    5774           0 :             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
    5775           0 :             goto error;
    5776             :         }
    5777           0 :         if (cpu >= ncpus) {
    5778             :             /* Grow CPU mask to fit the CPU number */
    5779           0 :             int newncpus = ncpus;
    5780             :             cpu_set_t *newmask;
    5781             :             size_t newsetsize;
    5782           0 :             while (newncpus <= cpu) {
    5783           0 :                 if (newncpus > INT_MAX / 2)
    5784           0 :                     newncpus = cpu + 1;
    5785             :                 else
    5786           0 :                     newncpus = newncpus * 2;
    5787             :             }
    5788           0 :             newmask = CPU_ALLOC(newncpus);
    5789           0 :             if (newmask == NULL) {
    5790           0 :                 PyErr_NoMemory();
    5791           0 :                 goto error;
    5792             :             }
    5793           0 :             newsetsize = CPU_ALLOC_SIZE(newncpus);
    5794           0 :             CPU_ZERO_S(newsetsize, newmask);
    5795           0 :             memcpy(newmask, mask, setsize);
    5796           0 :             CPU_FREE(mask);
    5797           0 :             setsize = newsetsize;
    5798           0 :             mask = newmask;
    5799           0 :             ncpus = newncpus;
    5800             :         }
    5801           0 :         CPU_SET_S(cpu, setsize, mask);
    5802             :     }
    5803           0 :     Py_CLEAR(iterator);
    5804             : 
    5805           0 :     if (sched_setaffinity(pid, setsize, mask)) {
    5806           0 :         posix_error();
    5807           0 :         goto error;
    5808             :     }
    5809           0 :     CPU_FREE(mask);
    5810           0 :     Py_RETURN_NONE;
    5811             : 
    5812             : error:
    5813           0 :     if (mask)
    5814           0 :         CPU_FREE(mask);
    5815           0 :     Py_XDECREF(iterator);
    5816           0 :     return NULL;
    5817             : }
    5818             : 
    5819             : PyDoc_STRVAR(posix_sched_getaffinity__doc__,
    5820             : "sched_getaffinity(pid, ncpus) -> cpu_set\n\n\
    5821             : Return the affinity of the process with PID *pid*.\n\
    5822             : The returned cpu_set will be of size *ncpus*.");
    5823             : 
    5824             : static PyObject *
    5825           0 : posix_sched_getaffinity(PyObject *self, PyObject *args)
    5826             : {
    5827             :     pid_t pid;
    5828             :     int cpu, ncpus, count;
    5829             :     size_t setsize;
    5830           0 :     cpu_set_t *mask = NULL;
    5831           0 :     PyObject *res = NULL;
    5832             : 
    5833           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity",
    5834             :                           &pid))
    5835           0 :         return NULL;
    5836             : 
    5837           0 :     ncpus = NCPUS_START;
    5838             :     while (1) {
    5839           0 :         setsize = CPU_ALLOC_SIZE(ncpus);
    5840           0 :         mask = CPU_ALLOC(ncpus);
    5841           0 :         if (mask == NULL)
    5842           0 :             return PyErr_NoMemory();
    5843           0 :         if (sched_getaffinity(pid, setsize, mask) == 0)
    5844           0 :             break;
    5845           0 :         CPU_FREE(mask);
    5846           0 :         if (errno != EINVAL)
    5847           0 :             return posix_error();
    5848           0 :         if (ncpus > INT_MAX / 2) {
    5849           0 :             PyErr_SetString(PyExc_OverflowError, "could not allocate "
    5850             :                             "a large enough CPU set");
    5851           0 :             return NULL;
    5852             :         }
    5853           0 :         ncpus = ncpus * 2;
    5854           0 :     }
    5855             : 
    5856           0 :     res = PySet_New(NULL);
    5857           0 :     if (res == NULL)
    5858           0 :         goto error;
    5859           0 :     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
    5860           0 :         if (CPU_ISSET_S(cpu, setsize, mask)) {
    5861           0 :             PyObject *cpu_num = PyLong_FromLong(cpu);
    5862           0 :             --count;
    5863           0 :             if (cpu_num == NULL)
    5864           0 :                 goto error;
    5865           0 :             if (PySet_Add(res, cpu_num)) {
    5866           0 :                 Py_DECREF(cpu_num);
    5867           0 :                 goto error;
    5868             :             }
    5869           0 :             Py_DECREF(cpu_num);
    5870             :         }
    5871             :     }
    5872           0 :     CPU_FREE(mask);
    5873           0 :     return res;
    5874             : 
    5875             : error:
    5876           0 :     if (mask)
    5877           0 :         CPU_FREE(mask);
    5878           0 :     Py_XDECREF(res);
    5879           0 :     return NULL;
    5880             : }
    5881             : 
    5882             : #endif /* HAVE_SCHED_SETAFFINITY */
    5883             : 
    5884             : #endif /* HAVE_SCHED_H */
    5885             : 
    5886             : /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
    5887             : /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
    5888             : #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
    5889             : #define DEV_PTY_FILE "/dev/ptc"
    5890             : #define HAVE_DEV_PTMX
    5891             : #else
    5892             : #define DEV_PTY_FILE "/dev/ptmx"
    5893             : #endif
    5894             : 
    5895             : #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
    5896             : #ifdef HAVE_PTY_H
    5897             : #include <pty.h>
    5898             : #else
    5899             : #ifdef HAVE_LIBUTIL_H
    5900             : #include <libutil.h>
    5901             : #else
    5902             : #ifdef HAVE_UTIL_H
    5903             : #include <util.h>
    5904             : #endif /* HAVE_UTIL_H */
    5905             : #endif /* HAVE_LIBUTIL_H */
    5906             : #endif /* HAVE_PTY_H */
    5907             : #ifdef HAVE_STROPTS_H
    5908             : #include <stropts.h>
    5909             : #endif
    5910             : #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
    5911             : 
    5912             : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
    5913             : PyDoc_STRVAR(posix_openpty__doc__,
    5914             : "openpty() -> (master_fd, slave_fd)\n\n\
    5915             : Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
    5916             : 
    5917             : static PyObject *
    5918           0 : posix_openpty(PyObject *self, PyObject *noargs)
    5919             : {
    5920             :     int master_fd, slave_fd;
    5921             : #ifndef HAVE_OPENPTY
    5922             :     char * slave_name;
    5923             : #endif
    5924             : #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
    5925             :     PyOS_sighandler_t sig_saved;
    5926             : #ifdef sun
    5927             :     extern char *ptsname(int fildes);
    5928             : #endif
    5929             : #endif
    5930             : 
    5931             : #ifdef HAVE_OPENPTY
    5932           0 :     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
    5933           0 :         return posix_error();
    5934             : #elif defined(HAVE__GETPTY)
    5935             :     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
    5936             :     if (slave_name == NULL)
    5937             :         return posix_error();
    5938             : 
    5939             :     slave_fd = open(slave_name, O_RDWR);
    5940             :     if (slave_fd < 0)
    5941             :         return posix_error();
    5942             : #else
    5943             :     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
    5944             :     if (master_fd < 0)
    5945             :         return posix_error();
    5946             :     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
    5947             :     /* change permission of slave */
    5948             :     if (grantpt(master_fd) < 0) {
    5949             :         PyOS_setsig(SIGCHLD, sig_saved);
    5950             :         return posix_error();
    5951             :     }
    5952             :     /* unlock slave */
    5953             :     if (unlockpt(master_fd) < 0) {
    5954             :         PyOS_setsig(SIGCHLD, sig_saved);
    5955             :         return posix_error();
    5956             :     }
    5957             :     PyOS_setsig(SIGCHLD, sig_saved);
    5958             :     slave_name = ptsname(master_fd); /* get name of slave */
    5959             :     if (slave_name == NULL)
    5960             :         return posix_error();
    5961             :     slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
    5962             :     if (slave_fd < 0)
    5963             :         return posix_error();
    5964             : #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
    5965             :     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
    5966             :     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
    5967             : #ifndef __hpux
    5968             :     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
    5969             : #endif /* __hpux */
    5970             : #endif /* HAVE_CYGWIN */
    5971             : #endif /* HAVE_OPENPTY */
    5972             : 
    5973           0 :     return Py_BuildValue("(ii)", master_fd, slave_fd);
    5974             : 
    5975             : }
    5976             : #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
    5977             : 
    5978             : #ifdef HAVE_FORKPTY
    5979             : PyDoc_STRVAR(posix_forkpty__doc__,
    5980             : "forkpty() -> (pid, master_fd)\n\n\
    5981             : Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
    5982             : Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
    5983             : To both, return fd of newly opened pseudo-terminal.\n");
    5984             : 
    5985             : static PyObject *
    5986           0 : posix_forkpty(PyObject *self, PyObject *noargs)
    5987             : {
    5988           0 :     int master_fd = -1, result = 0;
    5989             :     pid_t pid;
    5990             : 
    5991           0 :     _PyImport_AcquireLock();
    5992           0 :     pid = forkpty(&master_fd, NULL, NULL, NULL);
    5993           0 :     if (pid == 0) {
    5994             :         /* child: this clobbers and resets the import lock. */
    5995           0 :         PyOS_AfterFork();
    5996             :     } else {
    5997             :         /* parent: release the import lock. */
    5998           0 :         result = _PyImport_ReleaseLock();
    5999             :     }
    6000           0 :     if (pid == -1)
    6001           0 :         return posix_error();
    6002           0 :     if (result < 0) {
    6003             :         /* Don't clobber the OSError if the fork failed. */
    6004           0 :         PyErr_SetString(PyExc_RuntimeError,
    6005             :                         "not holding the import lock");
    6006           0 :         return NULL;
    6007             :     }
    6008           0 :     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
    6009             : }
    6010             : #endif
    6011             : 
    6012             : 
    6013             : #ifdef HAVE_GETEGID
    6014             : PyDoc_STRVAR(posix_getegid__doc__,
    6015             : "getegid() -> egid\n\n\
    6016             : Return the current process's effective group id.");
    6017             : 
    6018             : static PyObject *
    6019           1 : posix_getegid(PyObject *self, PyObject *noargs)
    6020             : {
    6021           1 :     return PyLong_FromLong((long)getegid());
    6022             : }
    6023             : #endif
    6024             : 
    6025             : 
    6026             : #ifdef HAVE_GETEUID
    6027             : PyDoc_STRVAR(posix_geteuid__doc__,
    6028             : "geteuid() -> euid\n\n\
    6029             : Return the current process's effective user id.");
    6030             : 
    6031             : static PyObject *
    6032           1 : posix_geteuid(PyObject *self, PyObject *noargs)
    6033             : {
    6034           1 :     return PyLong_FromLong((long)geteuid());
    6035             : }
    6036             : #endif
    6037             : 
    6038             : 
    6039             : #ifdef HAVE_GETGID
    6040             : PyDoc_STRVAR(posix_getgid__doc__,
    6041             : "getgid() -> gid\n\n\
    6042             : Return the current process's group id.");
    6043             : 
    6044             : static PyObject *
    6045           1 : posix_getgid(PyObject *self, PyObject *noargs)
    6046             : {
    6047           1 :     return PyLong_FromLong((long)getgid());
    6048             : }
    6049             : #endif
    6050             : 
    6051             : 
    6052             : PyDoc_STRVAR(posix_getpid__doc__,
    6053             : "getpid() -> pid\n\n\
    6054             : Return the current process id");
    6055             : 
    6056             : static PyObject *
    6057           0 : posix_getpid(PyObject *self, PyObject *noargs)
    6058             : {
    6059           0 :     return PyLong_FromPid(getpid());
    6060             : }
    6061             : 
    6062             : #ifdef HAVE_GETGROUPLIST
    6063             : PyDoc_STRVAR(posix_getgrouplist__doc__,
    6064             : "getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
    6065             : Returns a list of groups to which a user belongs.\n\n\
    6066             :     user: username to lookup\n\
    6067             :     group: base group id of the user");
    6068             : 
    6069             : static PyObject *
    6070           0 : posix_getgrouplist(PyObject *self, PyObject *args)
    6071             : {
    6072             : #ifdef NGROUPS_MAX
    6073             : #define MAX_GROUPS NGROUPS_MAX
    6074             : #else
    6075             :     /* defined to be 16 on Solaris7, so this should be a small number */
    6076             : #define MAX_GROUPS 64
    6077             : #endif
    6078             : 
    6079             :     const char *user;
    6080             :     int i, ngroups;
    6081             :     PyObject *list;
    6082             : #ifdef __APPLE__
    6083             :     int *groups, basegid;
    6084             : #else
    6085             :     gid_t *groups, basegid;
    6086             : #endif
    6087           0 :     ngroups = MAX_GROUPS;
    6088             : 
    6089           0 :     if (!PyArg_ParseTuple(args, "si", &user, &basegid))
    6090           0 :         return NULL;
    6091             : 
    6092             : #ifdef __APPLE__
    6093             :     groups = PyMem_Malloc(ngroups * sizeof(int));
    6094             : #else
    6095           0 :     groups = PyMem_Malloc(ngroups * sizeof(gid_t));
    6096             : #endif
    6097           0 :     if (groups == NULL)
    6098           0 :         return PyErr_NoMemory();
    6099             : 
    6100           0 :     if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
    6101           0 :         PyMem_Del(groups);
    6102           0 :         return posix_error();
    6103             :     }
    6104             : 
    6105           0 :     list = PyList_New(ngroups);
    6106           0 :     if (list == NULL) {
    6107           0 :         PyMem_Del(groups);
    6108           0 :         return NULL;
    6109             :     }
    6110             : 
    6111           0 :     for (i = 0; i < ngroups; i++) {
    6112           0 :         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
    6113           0 :         if (o == NULL) {
    6114           0 :             Py_DECREF(list);
    6115           0 :             PyMem_Del(groups);
    6116           0 :             return NULL;
    6117             :         }
    6118           0 :         PyList_SET_ITEM(list, i, o);
    6119             :     }
    6120             : 
    6121           0 :     PyMem_Del(groups);
    6122             : 
    6123           0 :     return list;
    6124             : }
    6125             : #endif
    6126             : 
    6127             : #ifdef HAVE_GETGROUPS
    6128             : PyDoc_STRVAR(posix_getgroups__doc__,
    6129             : "getgroups() -> list of group IDs\n\n\
    6130             : Return list of supplemental group IDs for the process.");
    6131             : 
    6132             : static PyObject *
    6133           0 : posix_getgroups(PyObject *self, PyObject *noargs)
    6134             : {
    6135           0 :     PyObject *result = NULL;
    6136             : 
    6137             : #ifdef NGROUPS_MAX
    6138             : #define MAX_GROUPS NGROUPS_MAX
    6139             : #else
    6140             :     /* defined to be 16 on Solaris7, so this should be a small number */
    6141             : #define MAX_GROUPS 64
    6142             : #endif
    6143             :     gid_t grouplist[MAX_GROUPS];
    6144             : 
    6145             :     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
    6146             :      * This is a helper variable to store the intermediate result when
    6147             :      * that happens.
    6148             :      *
    6149             :      * To keep the code readable the OSX behaviour is unconditional,
    6150             :      * according to the POSIX spec this should be safe on all unix-y
    6151             :      * systems.
    6152             :      */
    6153           0 :     gid_t* alt_grouplist = grouplist;
    6154             :     int n;
    6155             : 
    6156           0 :     n = getgroups(MAX_GROUPS, grouplist);
    6157           0 :     if (n < 0) {
    6158           0 :         if (errno == EINVAL) {
    6159           0 :             n = getgroups(0, NULL);
    6160           0 :             if (n == -1) {
    6161           0 :                 return posix_error();
    6162             :             }
    6163           0 :             if (n == 0) {
    6164             :                 /* Avoid malloc(0) */
    6165           0 :                 alt_grouplist = grouplist;
    6166             :             } else {
    6167           0 :                 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
    6168           0 :                 if (alt_grouplist == NULL) {
    6169           0 :                     errno = EINVAL;
    6170           0 :                     return posix_error();
    6171             :                 }
    6172           0 :                 n = getgroups(n, alt_grouplist);
    6173           0 :                 if (n == -1) {
    6174           0 :                     PyMem_Free(alt_grouplist);
    6175           0 :                     return posix_error();
    6176             :                 }
    6177             :             }
    6178             :         } else {
    6179           0 :             return posix_error();
    6180             :         }
    6181             :     }
    6182           0 :     result = PyList_New(n);
    6183           0 :     if (result != NULL) {
    6184             :         int i;
    6185           0 :         for (i = 0; i < n; ++i) {
    6186           0 :             PyObject *o = PyLong_FromLong((long)alt_grouplist[i]);
    6187           0 :             if (o == NULL) {
    6188           0 :                 Py_DECREF(result);
    6189           0 :                 result = NULL;
    6190           0 :                 break;
    6191             :             }
    6192           0 :             PyList_SET_ITEM(result, i, o);
    6193             :         }
    6194             :     }
    6195             : 
    6196           0 :     if (alt_grouplist != grouplist) {
    6197           0 :         PyMem_Free(alt_grouplist);
    6198             :     }
    6199             : 
    6200           0 :     return result;
    6201             : }
    6202             : #endif
    6203             : 
    6204             : #ifdef HAVE_INITGROUPS
    6205             : PyDoc_STRVAR(posix_initgroups__doc__,
    6206             : "initgroups(username, gid) -> None\n\n\
    6207             : Call the system initgroups() to initialize the group access list with all of\n\
    6208             : the groups of which the specified username is a member, plus the specified\n\
    6209             : group id.");
    6210             : 
    6211             : static PyObject *
    6212           0 : posix_initgroups(PyObject *self, PyObject *args)
    6213             : {
    6214             :     PyObject *oname;
    6215             :     char *username;
    6216             :     int res;
    6217             :     long gid;
    6218             : 
    6219           0 :     if (!PyArg_ParseTuple(args, "O&l:initgroups",
    6220             :                           PyUnicode_FSConverter, &oname, &gid))
    6221           0 :         return NULL;
    6222           0 :     username = PyBytes_AS_STRING(oname);
    6223             : 
    6224           0 :     res = initgroups(username, (gid_t) gid);
    6225           0 :     Py_DECREF(oname);
    6226           0 :     if (res == -1)
    6227           0 :         return PyErr_SetFromErrno(PyExc_OSError);
    6228             : 
    6229           0 :     Py_INCREF(Py_None);
    6230           0 :     return Py_None;
    6231             : }
    6232             : #endif
    6233             : 
    6234             : #ifdef HAVE_GETPGID
    6235             : PyDoc_STRVAR(posix_getpgid__doc__,
    6236             : "getpgid(pid) -> pgid\n\n\
    6237             : Call the system call getpgid().");
    6238             : 
    6239             : static PyObject *
    6240           0 : posix_getpgid(PyObject *self, PyObject *args)
    6241             : {
    6242             :     pid_t pid, pgid;
    6243           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getpgid", &pid))
    6244           0 :         return NULL;
    6245           0 :     pgid = getpgid(pid);
    6246           0 :     if (pgid < 0)
    6247           0 :         return posix_error();
    6248           0 :     return PyLong_FromPid(pgid);
    6249             : }
    6250             : #endif /* HAVE_GETPGID */
    6251             : 
    6252             : 
    6253             : #ifdef HAVE_GETPGRP
    6254             : PyDoc_STRVAR(posix_getpgrp__doc__,
    6255             : "getpgrp() -> pgrp\n\n\
    6256             : Return the current process group id.");
    6257             : 
    6258             : static PyObject *
    6259           0 : posix_getpgrp(PyObject *self, PyObject *noargs)
    6260             : {
    6261             : #ifdef GETPGRP_HAVE_ARG
    6262             :     return PyLong_FromPid(getpgrp(0));
    6263             : #else /* GETPGRP_HAVE_ARG */
    6264           0 :     return PyLong_FromPid(getpgrp());
    6265             : #endif /* GETPGRP_HAVE_ARG */
    6266             : }
    6267             : #endif /* HAVE_GETPGRP */
    6268             : 
    6269             : 
    6270             : #ifdef HAVE_SETPGRP
    6271             : PyDoc_STRVAR(posix_setpgrp__doc__,
    6272             : "setpgrp()\n\n\
    6273             : Make this process the process group leader.");
    6274             : 
    6275             : static PyObject *
    6276           0 : posix_setpgrp(PyObject *self, PyObject *noargs)
    6277             : {
    6278             : #ifdef SETPGRP_HAVE_ARG
    6279             :     if (setpgrp(0, 0) < 0)
    6280             : #else /* SETPGRP_HAVE_ARG */
    6281           0 :     if (setpgrp() < 0)
    6282             : #endif /* SETPGRP_HAVE_ARG */
    6283           0 :         return posix_error();
    6284           0 :     Py_INCREF(Py_None);
    6285           0 :     return Py_None;
    6286             : }
    6287             : 
    6288             : #endif /* HAVE_SETPGRP */
    6289             : 
    6290             : #ifdef HAVE_GETPPID
    6291             : 
    6292             : #ifdef MS_WINDOWS
    6293             : #include <tlhelp32.h>
    6294             : 
    6295             : static PyObject*
    6296             : win32_getppid()
    6297             : {
    6298             :     HANDLE snapshot;
    6299             :     pid_t mypid;
    6300             :     PyObject* result = NULL;
    6301             :     BOOL have_record;
    6302             :     PROCESSENTRY32 pe;
    6303             : 
    6304             :     mypid = getpid(); /* This function never fails */
    6305             : 
    6306             :     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    6307             :     if (snapshot == INVALID_HANDLE_VALUE)
    6308             :         return PyErr_SetFromWindowsErr(GetLastError());
    6309             : 
    6310             :     pe.dwSize = sizeof(pe);
    6311             :     have_record = Process32First(snapshot, &pe);
    6312             :     while (have_record) {
    6313             :         if (mypid == (pid_t)pe.th32ProcessID) {
    6314             :             /* We could cache the ulong value in a static variable. */
    6315             :             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
    6316             :             break;
    6317             :         }
    6318             : 
    6319             :         have_record = Process32Next(snapshot, &pe);
    6320             :     }
    6321             : 
    6322             :     /* If our loop exits and our pid was not found (result will be NULL)
    6323             :      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
    6324             :      * error anyway, so let's raise it. */
    6325             :     if (!result)
    6326             :         result = PyErr_SetFromWindowsErr(GetLastError());
    6327             : 
    6328             :     CloseHandle(snapshot);
    6329             : 
    6330             :     return result;
    6331             : }
    6332             : #endif /*MS_WINDOWS*/
    6333             : 
    6334             : PyDoc_STRVAR(posix_getppid__doc__,
    6335             : "getppid() -> ppid\n\n\
    6336             : Return the parent's process id.  If the parent process has already exited,\n\
    6337             : Windows machines will still return its id; others systems will return the id\n\
    6338             : of the 'init' process (1).");
    6339             : 
    6340             : static PyObject *
    6341           0 : posix_getppid(PyObject *self, PyObject *noargs)
    6342             : {
    6343             : #ifdef MS_WINDOWS
    6344             :     return win32_getppid();
    6345             : #else
    6346           0 :     return PyLong_FromPid(getppid());
    6347             : #endif
    6348             : }
    6349             : #endif /* HAVE_GETPPID */
    6350             : 
    6351             : 
    6352             : #ifdef HAVE_GETLOGIN
    6353             : PyDoc_STRVAR(posix_getlogin__doc__,
    6354             : "getlogin() -> string\n\n\
    6355             : Return the actual login name.");
    6356             : 
    6357             : static PyObject *
    6358           0 : posix_getlogin(PyObject *self, PyObject *noargs)
    6359             : {
    6360           0 :     PyObject *result = NULL;
    6361             : #ifdef MS_WINDOWS
    6362             :     wchar_t user_name[UNLEN + 1];
    6363             :     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
    6364             : 
    6365             :     if (GetUserNameW(user_name, &num_chars)) {
    6366             :         /* num_chars is the number of unicode chars plus null terminator */
    6367             :         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
    6368             :     }
    6369             :     else
    6370             :         result = PyErr_SetFromWindowsErr(GetLastError());
    6371             : #else
    6372             :     char *name;
    6373           0 :     int old_errno = errno;
    6374             : 
    6375           0 :     errno = 0;
    6376           0 :     name = getlogin();
    6377           0 :     if (name == NULL) {
    6378           0 :         if (errno)
    6379           0 :             posix_error();
    6380             :         else
    6381           0 :             PyErr_SetString(PyExc_OSError, "unable to determine login name");
    6382             :     }
    6383             :     else
    6384           0 :         result = PyUnicode_DecodeFSDefault(name);
    6385           0 :     errno = old_errno;
    6386             : #endif
    6387           0 :     return result;
    6388             : }
    6389             : #endif /* HAVE_GETLOGIN */
    6390             : 
    6391             : #ifdef HAVE_GETUID
    6392             : PyDoc_STRVAR(posix_getuid__doc__,
    6393             : "getuid() -> uid\n\n\
    6394             : Return the current process's user id.");
    6395             : 
    6396             : static PyObject *
    6397           1 : posix_getuid(PyObject *self, PyObject *noargs)
    6398             : {
    6399           1 :     return PyLong_FromLong((long)getuid());
    6400             : }
    6401             : #endif
    6402             : 
    6403             : 
    6404             : #ifdef HAVE_KILL
    6405             : PyDoc_STRVAR(posix_kill__doc__,
    6406             : "kill(pid, sig)\n\n\
    6407             : Kill a process with a signal.");
    6408             : 
    6409             : static PyObject *
    6410           0 : posix_kill(PyObject *self, PyObject *args)
    6411             : {
    6412             :     pid_t pid;
    6413             :     int sig;
    6414           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:kill", &pid, &sig))
    6415           0 :         return NULL;
    6416             : #if defined(PYOS_OS2) && !defined(PYCC_GCC)
    6417             :     if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
    6418             :         APIRET rc;
    6419             :         if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
    6420             :             return os2_error(rc);
    6421             : 
    6422             :     } else if (sig == XCPT_SIGNAL_KILLPROC) {
    6423             :         APIRET rc;
    6424             :         if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
    6425             :             return os2_error(rc);
    6426             : 
    6427             :     } else
    6428             :         return NULL; /* Unrecognized Signal Requested */
    6429             : #else
    6430           0 :     if (kill(pid, sig) == -1)
    6431           0 :         return posix_error();
    6432             : #endif
    6433           0 :     Py_INCREF(Py_None);
    6434           0 :     return Py_None;
    6435             : }
    6436             : #endif
    6437             : 
    6438             : #ifdef HAVE_KILLPG
    6439             : PyDoc_STRVAR(posix_killpg__doc__,
    6440             : "killpg(pgid, sig)\n\n\
    6441             : Kill a process group with a signal.");
    6442             : 
    6443             : static PyObject *
    6444           0 : posix_killpg(PyObject *self, PyObject *args)
    6445             : {
    6446             :     int sig;
    6447             :     pid_t pgid;
    6448             :     /* XXX some man pages make the `pgid` parameter an int, others
    6449             :        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
    6450             :        take the same type. Moreover, pid_t is always at least as wide as
    6451             :        int (else compilation of this module fails), which is safe. */
    6452           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:killpg", &pgid, &sig))
    6453           0 :         return NULL;
    6454           0 :     if (killpg(pgid, sig) == -1)
    6455           0 :         return posix_error();
    6456           0 :     Py_INCREF(Py_None);
    6457           0 :     return Py_None;
    6458             : }
    6459             : #endif
    6460             : 
    6461             : #ifdef MS_WINDOWS
    6462             : PyDoc_STRVAR(win32_kill__doc__,
    6463             : "kill(pid, sig)\n\n\
    6464             : Kill a process with a signal.");
    6465             : 
    6466             : static PyObject *
    6467             : win32_kill(PyObject *self, PyObject *args)
    6468             : {
    6469             :     PyObject *result;
    6470             :     DWORD pid, sig, err;
    6471             :     HANDLE handle;
    6472             : 
    6473             :     if (!PyArg_ParseTuple(args, "kk:kill", &pid, &sig))
    6474             :         return NULL;
    6475             : 
    6476             :     /* Console processes which share a common console can be sent CTRL+C or
    6477             :        CTRL+BREAK events, provided they handle said events. */
    6478             :     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
    6479             :         if (GenerateConsoleCtrlEvent(sig, pid) == 0) {
    6480             :             err = GetLastError();
    6481             :             PyErr_SetFromWindowsErr(err);
    6482             :         }
    6483             :         else
    6484             :             Py_RETURN_NONE;
    6485             :     }
    6486             : 
    6487             :     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
    6488             :        attempt to open and terminate the process. */
    6489             :     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    6490             :     if (handle == NULL) {
    6491             :         err = GetLastError();
    6492             :         return PyErr_SetFromWindowsErr(err);
    6493             :     }
    6494             : 
    6495             :     if (TerminateProcess(handle, sig) == 0) {
    6496             :         err = GetLastError();
    6497             :         result = PyErr_SetFromWindowsErr(err);
    6498             :     } else {
    6499             :         Py_INCREF(Py_None);
    6500             :         result = Py_None;
    6501             :     }
    6502             : 
    6503             :     CloseHandle(handle);
    6504             :     return result;
    6505             : }
    6506             : #endif /* MS_WINDOWS */
    6507             : 
    6508             : #ifdef HAVE_PLOCK
    6509             : 
    6510             : #ifdef HAVE_SYS_LOCK_H
    6511             : #include <sys/lock.h>
    6512             : #endif
    6513             : 
    6514             : PyDoc_STRVAR(posix_plock__doc__,
    6515             : "plock(op)\n\n\
    6516             : Lock program segments into memory.");
    6517             : 
    6518             : static PyObject *
    6519             : posix_plock(PyObject *self, PyObject *args)
    6520             : {
    6521             :     int op;
    6522             :     if (!PyArg_ParseTuple(args, "i:plock", &op))
    6523             :         return NULL;
    6524             :     if (plock(op) == -1)
    6525             :         return posix_error();
    6526             :     Py_INCREF(Py_None);
    6527             :     return Py_None;
    6528             : }
    6529             : #endif
    6530             : 
    6531             : #ifdef HAVE_SETUID
    6532             : PyDoc_STRVAR(posix_setuid__doc__,
    6533             : "setuid(uid)\n\n\
    6534             : Set the current process's user id.");
    6535             : 
    6536             : static PyObject *
    6537           0 : posix_setuid(PyObject *self, PyObject *args)
    6538             : {
    6539             :     long uid_arg;
    6540             :     uid_t uid;
    6541           0 :     if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
    6542           0 :         return NULL;
    6543           0 :     uid = uid_arg;
    6544           0 :     if (uid != uid_arg) {
    6545           0 :         PyErr_SetString(PyExc_OverflowError, "user id too big");
    6546           0 :         return NULL;
    6547             :     }
    6548           0 :     if (setuid(uid) < 0)
    6549           0 :         return posix_error();
    6550           0 :     Py_INCREF(Py_None);
    6551           0 :     return Py_None;
    6552             : }
    6553             : #endif /* HAVE_SETUID */
    6554             : 
    6555             : 
    6556             : #ifdef HAVE_SETEUID
    6557             : PyDoc_STRVAR(posix_seteuid__doc__,
    6558             : "seteuid(uid)\n\n\
    6559             : Set the current process's effective user id.");
    6560             : 
    6561             : static PyObject *
    6562           0 : posix_seteuid (PyObject *self, PyObject *args)
    6563             : {
    6564             :     long euid_arg;
    6565             :     uid_t euid;
    6566           0 :     if (!PyArg_ParseTuple(args, "l", &euid_arg))
    6567           0 :         return NULL;
    6568           0 :     euid = euid_arg;
    6569           0 :     if (euid != euid_arg) {
    6570           0 :         PyErr_SetString(PyExc_OverflowError, "user id too big");
    6571           0 :         return NULL;
    6572             :     }
    6573           0 :     if (seteuid(euid) < 0) {
    6574           0 :         return posix_error();
    6575             :     } else {
    6576           0 :         Py_INCREF(Py_None);
    6577           0 :         return Py_None;
    6578             :     }
    6579             : }
    6580             : #endif /* HAVE_SETEUID */
    6581             : 
    6582             : #ifdef HAVE_SETEGID
    6583             : PyDoc_STRVAR(posix_setegid__doc__,
    6584             : "setegid(gid)\n\n\
    6585             : Set the current process's effective group id.");
    6586             : 
    6587             : static PyObject *
    6588           0 : posix_setegid (PyObject *self, PyObject *args)
    6589             : {
    6590             :     long egid_arg;
    6591             :     gid_t egid;
    6592           0 :     if (!PyArg_ParseTuple(args, "l", &egid_arg))
    6593           0 :         return NULL;
    6594           0 :     egid = egid_arg;
    6595           0 :     if (egid != egid_arg) {
    6596           0 :         PyErr_SetString(PyExc_OverflowError, "group id too big");
    6597           0 :         return NULL;
    6598             :     }
    6599           0 :     if (setegid(egid) < 0) {
    6600           0 :         return posix_error();
    6601             :     } else {
    6602           0 :         Py_INCREF(Py_None);
    6603           0 :         return Py_None;
    6604             :     }
    6605             : }
    6606             : #endif /* HAVE_SETEGID */
    6607             : 
    6608             : #ifdef HAVE_SETREUID
    6609             : PyDoc_STRVAR(posix_setreuid__doc__,
    6610             : "setreuid(ruid, euid)\n\n\
    6611             : Set the current process's real and effective user ids.");
    6612             : 
    6613             : static PyObject *
    6614           0 : posix_setreuid (PyObject *self, PyObject *args)
    6615             : {
    6616             :     long ruid_arg, euid_arg;
    6617             :     uid_t ruid, euid;
    6618           0 :     if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
    6619           0 :         return NULL;
    6620           0 :     if (ruid_arg == -1)
    6621           0 :         ruid = (uid_t)-1;  /* let the compiler choose how -1 fits */
    6622             :     else
    6623           0 :         ruid = ruid_arg;  /* otherwise, assign from our long */
    6624           0 :     if (euid_arg == -1)
    6625           0 :         euid = (uid_t)-1;
    6626             :     else
    6627           0 :         euid = euid_arg;
    6628           0 :     if ((euid_arg != -1 && euid != euid_arg) ||
    6629           0 :         (ruid_arg != -1 && ruid != ruid_arg)) {
    6630           0 :         PyErr_SetString(PyExc_OverflowError, "user id too big");
    6631           0 :         return NULL;
    6632             :     }
    6633           0 :     if (setreuid(ruid, euid) < 0) {
    6634           0 :         return posix_error();
    6635             :     } else {
    6636           0 :         Py_INCREF(Py_None);
    6637           0 :         return Py_None;
    6638             :     }
    6639             : }
    6640             : #endif /* HAVE_SETREUID */
    6641             : 
    6642             : #ifdef HAVE_SETREGID
    6643             : PyDoc_STRVAR(posix_setregid__doc__,
    6644             : "setregid(rgid, egid)\n\n\
    6645             : Set the current process's real and effective group ids.");
    6646             : 
    6647             : static PyObject *
    6648           0 : posix_setregid (PyObject *self, PyObject *args)
    6649             : {
    6650             :     long rgid_arg, egid_arg;
    6651             :     gid_t rgid, egid;
    6652           0 :     if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
    6653           0 :         return NULL;
    6654           0 :     if (rgid_arg == -1)
    6655           0 :         rgid = (gid_t)-1;  /* let the compiler choose how -1 fits */
    6656             :     else
    6657           0 :         rgid = rgid_arg;  /* otherwise, assign from our long */
    6658           0 :     if (egid_arg == -1)
    6659           0 :         egid = (gid_t)-1;
    6660             :     else
    6661           0 :         egid = egid_arg;
    6662           0 :     if ((egid_arg != -1 && egid != egid_arg) ||
    6663           0 :         (rgid_arg != -1 && rgid != rgid_arg)) {
    6664           0 :         PyErr_SetString(PyExc_OverflowError, "group id too big");
    6665           0 :         return NULL;
    6666             :     }
    6667           0 :     if (setregid(rgid, egid) < 0) {
    6668           0 :         return posix_error();
    6669             :     } else {
    6670           0 :         Py_INCREF(Py_None);
    6671           0 :         return Py_None;
    6672             :     }
    6673             : }
    6674             : #endif /* HAVE_SETREGID */
    6675             : 
    6676             : #ifdef HAVE_SETGID
    6677             : PyDoc_STRVAR(posix_setgid__doc__,
    6678             : "setgid(gid)\n\n\
    6679             : Set the current process's group id.");
    6680             : 
    6681             : static PyObject *
    6682           0 : posix_setgid(PyObject *self, PyObject *args)
    6683             : {
    6684             :     long gid_arg;
    6685             :     gid_t gid;
    6686           0 :     if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
    6687           0 :         return NULL;
    6688           0 :     gid = gid_arg;
    6689           0 :     if (gid != gid_arg) {
    6690           0 :         PyErr_SetString(PyExc_OverflowError, "group id too big");
    6691           0 :         return NULL;
    6692             :     }
    6693           0 :     if (setgid(gid) < 0)
    6694           0 :         return posix_error();
    6695           0 :     Py_INCREF(Py_None);
    6696           0 :     return Py_None;
    6697             : }
    6698             : #endif /* HAVE_SETGID */
    6699             : 
    6700             : #ifdef HAVE_SETGROUPS
    6701             : PyDoc_STRVAR(posix_setgroups__doc__,
    6702             : "setgroups(list)\n\n\
    6703             : Set the groups of the current process to list.");
    6704             : 
    6705             : static PyObject *
    6706           0 : posix_setgroups(PyObject *self, PyObject *groups)
    6707             : {
    6708             :     int i, len;
    6709             :     gid_t grouplist[MAX_GROUPS];
    6710             : 
    6711           0 :     if (!PySequence_Check(groups)) {
    6712           0 :         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
    6713           0 :         return NULL;
    6714             :     }
    6715           0 :     len = PySequence_Size(groups);
    6716           0 :     if (len > MAX_GROUPS) {
    6717           0 :         PyErr_SetString(PyExc_ValueError, "too many groups");
    6718           0 :         return NULL;
    6719             :     }
    6720           0 :     for(i = 0; i < len; i++) {
    6721             :         PyObject *elem;
    6722           0 :         elem = PySequence_GetItem(groups, i);
    6723           0 :         if (!elem)
    6724           0 :             return NULL;
    6725           0 :         if (!PyLong_Check(elem)) {
    6726           0 :             PyErr_SetString(PyExc_TypeError,
    6727             :                             "groups must be integers");
    6728           0 :             Py_DECREF(elem);
    6729           0 :             return NULL;
    6730             :         } else {
    6731           0 :             unsigned long x = PyLong_AsUnsignedLong(elem);
    6732           0 :             if (PyErr_Occurred()) {
    6733           0 :                 PyErr_SetString(PyExc_TypeError,
    6734             :                                 "group id too big");
    6735           0 :                 Py_DECREF(elem);
    6736           0 :                 return NULL;
    6737             :             }
    6738           0 :             grouplist[i] = x;
    6739             :             /* read back the value to see if it fitted in gid_t */
    6740           0 :             if (grouplist[i] != x) {
    6741           0 :                 PyErr_SetString(PyExc_TypeError,
    6742             :                                 "group id too big");
    6743           0 :                 Py_DECREF(elem);
    6744           0 :                 return NULL;
    6745             :             }
    6746             :         }
    6747           0 :         Py_DECREF(elem);
    6748             :     }
    6749             : 
    6750           0 :     if (setgroups(len, grouplist) < 0)
    6751           0 :         return posix_error();
    6752           0 :     Py_INCREF(Py_None);
    6753           0 :     return Py_None;
    6754             : }
    6755             : #endif /* HAVE_SETGROUPS */
    6756             : 
    6757             : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
    6758             : static PyObject *
    6759           0 : wait_helper(pid_t pid, int status, struct rusage *ru)
    6760             : {
    6761             :     PyObject *result;
    6762             :     static PyObject *struct_rusage;
    6763             :     _Py_IDENTIFIER(struct_rusage);
    6764             : 
    6765           0 :     if (pid == -1)
    6766           0 :         return posix_error();
    6767             : 
    6768           0 :     if (struct_rusage == NULL) {
    6769           0 :         PyObject *m = PyImport_ImportModuleNoBlock("resource");
    6770           0 :         if (m == NULL)
    6771           0 :             return NULL;
    6772           0 :         struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
    6773           0 :         Py_DECREF(m);
    6774           0 :         if (struct_rusage == NULL)
    6775           0 :             return NULL;
    6776             :     }
    6777             : 
    6778             :     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
    6779           0 :     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
    6780           0 :     if (!result)
    6781           0 :         return NULL;
    6782             : 
    6783             : #ifndef doubletime
    6784             : #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
    6785             : #endif
    6786             : 
    6787           0 :     PyStructSequence_SET_ITEM(result, 0,
    6788             :                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
    6789           0 :     PyStructSequence_SET_ITEM(result, 1,
    6790             :                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
    6791             : #define SET_INT(result, index, value)\
    6792             :         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
    6793           0 :     SET_INT(result, 2, ru->ru_maxrss);
    6794           0 :     SET_INT(result, 3, ru->ru_ixrss);
    6795           0 :     SET_INT(result, 4, ru->ru_idrss);
    6796           0 :     SET_INT(result, 5, ru->ru_isrss);
    6797           0 :     SET_INT(result, 6, ru->ru_minflt);
    6798           0 :     SET_INT(result, 7, ru->ru_majflt);
    6799           0 :     SET_INT(result, 8, ru->ru_nswap);
    6800           0 :     SET_INT(result, 9, ru->ru_inblock);
    6801           0 :     SET_INT(result, 10, ru->ru_oublock);
    6802           0 :     SET_INT(result, 11, ru->ru_msgsnd);
    6803           0 :     SET_INT(result, 12, ru->ru_msgrcv);
    6804           0 :     SET_INT(result, 13, ru->ru_nsignals);
    6805           0 :     SET_INT(result, 14, ru->ru_nvcsw);
    6806           0 :     SET_INT(result, 15, ru->ru_nivcsw);
    6807             : #undef SET_INT
    6808             : 
    6809           0 :     if (PyErr_Occurred()) {
    6810           0 :         Py_DECREF(result);
    6811           0 :         return NULL;
    6812             :     }
    6813             : 
    6814           0 :     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
    6815             : }
    6816             : #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
    6817             : 
    6818             : #ifdef HAVE_WAIT3
    6819             : PyDoc_STRVAR(posix_wait3__doc__,
    6820             : "wait3(options) -> (pid, status, rusage)\n\n\
    6821             : Wait for completion of a child process.");
    6822             : 
    6823             : static PyObject *
    6824           0 : posix_wait3(PyObject *self, PyObject *args)
    6825             : {
    6826             :     pid_t pid;
    6827             :     int options;
    6828             :     struct rusage ru;
    6829             :     WAIT_TYPE status;
    6830           0 :     WAIT_STATUS_INT(status) = 0;
    6831             : 
    6832           0 :     if (!PyArg_ParseTuple(args, "i:wait3", &options))
    6833           0 :         return NULL;
    6834             : 
    6835           0 :     Py_BEGIN_ALLOW_THREADS
    6836           0 :     pid = wait3(&status, options, &ru);
    6837           0 :     Py_END_ALLOW_THREADS
    6838             : 
    6839           0 :     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
    6840             : }
    6841             : #endif /* HAVE_WAIT3 */
    6842             : 
    6843             : #ifdef HAVE_WAIT4
    6844             : PyDoc_STRVAR(posix_wait4__doc__,
    6845             : "wait4(pid, options) -> (pid, status, rusage)\n\n\
    6846             : Wait for completion of a given child process.");
    6847             : 
    6848             : static PyObject *
    6849           0 : posix_wait4(PyObject *self, PyObject *args)
    6850             : {
    6851             :     pid_t pid;
    6852             :     int options;
    6853             :     struct rusage ru;
    6854             :     WAIT_TYPE status;
    6855           0 :     WAIT_STATUS_INT(status) = 0;
    6856             : 
    6857           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
    6858           0 :         return NULL;
    6859             : 
    6860           0 :     Py_BEGIN_ALLOW_THREADS
    6861           0 :     pid = wait4(pid, &status, options, &ru);
    6862           0 :     Py_END_ALLOW_THREADS
    6863             : 
    6864           0 :     return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
    6865             : }
    6866             : #endif /* HAVE_WAIT4 */
    6867             : 
    6868             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
    6869             : PyDoc_STRVAR(posix_waitid__doc__,
    6870             : "waitid(idtype, id, options) -> waitid_result\n\n\
    6871             : Wait for the completion of one or more child processes.\n\n\
    6872             : idtype can be P_PID, P_PGID or P_ALL.\n\
    6873             : id specifies the pid to wait on.\n\
    6874             : options is constructed from the ORing of one or more of WEXITED, WSTOPPED\n\
    6875             : or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n\
    6876             : Returns either waitid_result or None if WNOHANG is specified and there are\n\
    6877             : no children in a waitable state.");
    6878             : 
    6879             : static PyObject *
    6880           0 : posix_waitid(PyObject *self, PyObject *args)
    6881             : {
    6882             :     PyObject *result;
    6883             :     idtype_t idtype;
    6884             :     id_t id;
    6885             :     int options, res;
    6886             :     siginfo_t si;
    6887           0 :     si.si_pid = 0;
    6888           0 :     if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID "i:waitid", &idtype, &id, &options))
    6889           0 :         return NULL;
    6890           0 :     Py_BEGIN_ALLOW_THREADS
    6891           0 :     res = waitid(idtype, id, &si, options);
    6892           0 :     Py_END_ALLOW_THREADS
    6893           0 :     if (res == -1)
    6894           0 :         return posix_error();
    6895             : 
    6896           0 :     if (si.si_pid == 0)
    6897           0 :         Py_RETURN_NONE;
    6898             : 
    6899           0 :     result = PyStructSequence_New(&WaitidResultType);
    6900           0 :     if (!result)
    6901           0 :         return NULL;
    6902             : 
    6903           0 :     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
    6904           0 :     PyStructSequence_SET_ITEM(result, 1, PyLong_FromPid(si.si_uid));
    6905           0 :     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
    6906           0 :     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
    6907           0 :     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
    6908           0 :     if (PyErr_Occurred()) {
    6909           0 :         Py_DECREF(result);
    6910           0 :         return NULL;
    6911             :     }
    6912             : 
    6913           0 :     return result;
    6914             : }
    6915             : #endif
    6916             : 
    6917             : #ifdef HAVE_WAITPID
    6918             : PyDoc_STRVAR(posix_waitpid__doc__,
    6919             : "waitpid(pid, options) -> (pid, status)\n\n\
    6920             : Wait for completion of a given child process.");
    6921             : 
    6922             : static PyObject *
    6923           0 : posix_waitpid(PyObject *self, PyObject *args)
    6924             : {
    6925             :     pid_t pid;
    6926             :     int options;
    6927             :     WAIT_TYPE status;
    6928           0 :     WAIT_STATUS_INT(status) = 0;
    6929             : 
    6930           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
    6931           0 :         return NULL;
    6932           0 :     Py_BEGIN_ALLOW_THREADS
    6933           0 :     pid = waitpid(pid, &status, options);
    6934           0 :     Py_END_ALLOW_THREADS
    6935           0 :     if (pid == -1)
    6936           0 :         return posix_error();
    6937             : 
    6938           0 :     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
    6939             : }
    6940             : 
    6941             : #elif defined(HAVE_CWAIT)
    6942             : 
    6943             : /* MS C has a variant of waitpid() that's usable for most purposes. */
    6944             : PyDoc_STRVAR(posix_waitpid__doc__,
    6945             : "waitpid(pid, options) -> (pid, status << 8)\n\n"
    6946             : "Wait for completion of a given process.  options is ignored on Windows.");
    6947             : 
    6948             : static PyObject *
    6949             : posix_waitpid(PyObject *self, PyObject *args)
    6950             : {
    6951             :     Py_intptr_t pid;
    6952             :     int status, options;
    6953             : 
    6954             :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
    6955             :         return NULL;
    6956             :     Py_BEGIN_ALLOW_THREADS
    6957             :     pid = _cwait(&status, pid, options);
    6958             :     Py_END_ALLOW_THREADS
    6959             :     if (pid == -1)
    6960             :         return posix_error();
    6961             : 
    6962             :     /* shift the status left a byte so this is more like the POSIX waitpid */
    6963             :     return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
    6964             : }
    6965             : #endif /* HAVE_WAITPID || HAVE_CWAIT */
    6966             : 
    6967             : #ifdef HAVE_WAIT
    6968             : PyDoc_STRVAR(posix_wait__doc__,
    6969             : "wait() -> (pid, status)\n\n\
    6970             : Wait for completion of a child process.");
    6971             : 
    6972             : static PyObject *
    6973           0 : posix_wait(PyObject *self, PyObject *noargs)
    6974             : {
    6975             :     pid_t pid;
    6976             :     WAIT_TYPE status;
    6977           0 :     WAIT_STATUS_INT(status) = 0;
    6978             : 
    6979           0 :     Py_BEGIN_ALLOW_THREADS
    6980           0 :     pid = wait(&status);
    6981           0 :     Py_END_ALLOW_THREADS
    6982           0 :     if (pid == -1)
    6983           0 :         return posix_error();
    6984             : 
    6985           0 :     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
    6986             : }
    6987             : #endif
    6988             : 
    6989             : 
    6990             : #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
    6991             : PyDoc_STRVAR(readlink__doc__,
    6992             : "readlink(path, *, dir_fd=None) -> path\n\n\
    6993             : Return a string representing the path to which the symbolic link points.\n\
    6994             : \n\
    6995             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    6996             :   and path should be relative; path will then be relative to that directory.\n\
    6997             : dir_fd may not be implemented on your platform.\n\
    6998             :   If it is unavailable, using it will raise a NotImplementedError.");
    6999             : #endif
    7000             : 
    7001             : #ifdef HAVE_READLINK
    7002             : 
    7003             : static PyObject *
    7004           0 : posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
    7005             : {
    7006             :     path_t path;
    7007           0 :     int dir_fd = DEFAULT_DIR_FD;
    7008             :     char buffer[MAXPATHLEN];
    7009             :     ssize_t length;
    7010           0 :     PyObject *return_value = NULL;
    7011             :     static char *keywords[] = {"path", "dir_fd", NULL};
    7012             : 
    7013           0 :     memset(&path, 0, sizeof(path));
    7014           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
    7015             :                           path_converter, &path,
    7016             : #ifdef HAVE_READLINKAT
    7017             :                           dir_fd_converter, &dir_fd
    7018             : #else
    7019             :                           dir_fd_unavailable, &dir_fd
    7020             : #endif
    7021             :                           ))
    7022           0 :         return NULL;
    7023             : 
    7024           0 :     Py_BEGIN_ALLOW_THREADS
    7025             : #ifdef HAVE_READLINKAT
    7026           0 :     if (dir_fd != DEFAULT_DIR_FD)
    7027           0 :         length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer));
    7028             :     else
    7029             : #endif
    7030           0 :         length = readlink(path.narrow, buffer, sizeof(buffer));
    7031           0 :     Py_END_ALLOW_THREADS
    7032             : 
    7033           0 :     if (length < 0) {
    7034           0 :         return_value = path_posix_error("readlink", &path);
    7035           0 :         goto exit;
    7036             :     }
    7037             : 
    7038           0 :     if (PyUnicode_Check(path.object))
    7039           0 :         return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length);
    7040             :     else
    7041           0 :         return_value = PyBytes_FromStringAndSize(buffer, length);
    7042             : exit:
    7043           0 :     path_cleanup(&path);
    7044           0 :     return return_value;
    7045             : }
    7046             : 
    7047             : 
    7048             : #endif /* HAVE_READLINK */
    7049             : 
    7050             : 
    7051             : #ifdef HAVE_SYMLINK
    7052             : PyDoc_STRVAR(posix_symlink__doc__,
    7053             : "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
    7054             : Create a symbolic link pointing to src named dst.\n\n\
    7055             : target_is_directory is required on Windows if the target is to be\n\
    7056             :   interpreted as a directory.  (On Windows, symlink requires\n\
    7057             :   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n\
    7058             :   target_is_directory is ignored on non-Windows platforms.\n\
    7059             : \n\
    7060             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    7061             :   and path should be relative; path will then be relative to that directory.\n\
    7062             : dir_fd may not be implemented on your platform.\n\
    7063             :   If it is unavailable, using it will raise a NotImplementedError.");
    7064             : 
    7065             : #if defined(MS_WINDOWS)
    7066             : 
    7067             : /* Grab CreateSymbolicLinkW dynamically from kernel32 */
    7068             : static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL;
    7069             : static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL;
    7070             : static int
    7071             : check_CreateSymbolicLink()
    7072             : {
    7073             :     HINSTANCE hKernel32;
    7074             :     /* only recheck */
    7075             :     if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA)
    7076             :         return 1;
    7077             :     hKernel32 = GetModuleHandleW(L"KERNEL32");
    7078             :     *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
    7079             :                                                         "CreateSymbolicLinkW");
    7080             :     *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32,
    7081             :                                                         "CreateSymbolicLinkA");
    7082             :     return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA);
    7083             : }
    7084             : 
    7085             : #endif
    7086             : 
    7087             : static PyObject *
    7088           0 : posix_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
    7089             : {
    7090             :     path_t src;
    7091             :     path_t dst;
    7092           0 :     int dir_fd = DEFAULT_DIR_FD;
    7093           0 :     int target_is_directory = 0;
    7094             :     static char *keywords[] = {"src", "dst", "target_is_directory",
    7095             :                                "dir_fd", NULL};
    7096             :     PyObject *return_value;
    7097             : #ifdef MS_WINDOWS
    7098             :     DWORD result;
    7099             : #else
    7100             :     int result;
    7101             : #endif
    7102             : 
    7103           0 :     memset(&src, 0, sizeof(src));
    7104           0 :     src.argument_name = "src";
    7105           0 :     memset(&dst, 0, sizeof(dst));
    7106           0 :     dst.argument_name = "dst";
    7107             : 
    7108             : #ifdef MS_WINDOWS
    7109             :     if (!check_CreateSymbolicLink()) {
    7110             :         PyErr_SetString(PyExc_NotImplementedError,
    7111             :             "CreateSymbolicLink functions not found");
    7112             :                 return NULL;
    7113             :         }
    7114             :     if (!win32_can_symlink) {
    7115             :         PyErr_SetString(PyExc_OSError, "symbolic link privilege not held");
    7116             :                 return NULL;
    7117             :         }
    7118             : #endif
    7119             : 
    7120           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|i$O&:symlink",
    7121             :             keywords,
    7122             :             path_converter, &src,
    7123             :             path_converter, &dst,
    7124             :             &target_is_directory,
    7125             : #ifdef HAVE_SYMLINKAT
    7126             :             dir_fd_converter, &dir_fd
    7127             : #else
    7128             :             dir_fd_unavailable, &dir_fd
    7129             : #endif
    7130             :             ))
    7131           0 :         return NULL;
    7132             : 
    7133           0 :     if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
    7134           0 :         PyErr_SetString(PyExc_ValueError,
    7135             :             "symlink: src and dst must be the same type");
    7136           0 :         return_value = NULL;
    7137           0 :         goto exit;
    7138             :     }
    7139             : 
    7140             : #ifdef MS_WINDOWS
    7141             :     Py_BEGIN_ALLOW_THREADS
    7142             :     if (dst.wide)
    7143             :         result = Py_CreateSymbolicLinkW(dst.wide, src.wide,
    7144             :                                         target_is_directory);
    7145             :     else
    7146             :         result = Py_CreateSymbolicLinkA(dst.narrow, src.narrow,
    7147             :                                         target_is_directory);
    7148             :     Py_END_ALLOW_THREADS
    7149             : 
    7150             :     if (!result) {
    7151             :         return_value = win32_error_object("symlink", src.object);
    7152             :         goto exit;
    7153             :     }
    7154             : 
    7155             : #else
    7156             : 
    7157           0 :     Py_BEGIN_ALLOW_THREADS
    7158             : #if HAVE_SYMLINKAT
    7159           0 :     if (dir_fd != DEFAULT_DIR_FD)
    7160           0 :         result = symlinkat(src.narrow, dir_fd, dst.narrow);
    7161             :     else
    7162             : #endif
    7163           0 :         result = symlink(src.narrow, dst.narrow);
    7164           0 :     Py_END_ALLOW_THREADS
    7165             : 
    7166           0 :     if (result) {
    7167           0 :         return_value = path_error("symlink", &dst);
    7168           0 :         goto exit;
    7169             :     }
    7170             : #endif
    7171             : 
    7172           0 :     return_value = Py_None;
    7173           0 :     Py_INCREF(Py_None);
    7174           0 :     goto exit; /* silence "unused label" warning */
    7175             : exit:
    7176           0 :     path_cleanup(&src);
    7177           0 :     path_cleanup(&dst);
    7178           0 :     return return_value;
    7179             : }
    7180             : 
    7181             : #endif /* HAVE_SYMLINK */
    7182             : 
    7183             : 
    7184             : #if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
    7185             : 
    7186             : static PyObject *
    7187             : win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
    7188             : {
    7189             :     wchar_t *path;
    7190             :     DWORD n_bytes_returned;
    7191             :     DWORD io_result;
    7192             :     PyObject *po, *result;
    7193             :         int dir_fd;
    7194             :     HANDLE reparse_point_handle;
    7195             : 
    7196             :     char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    7197             :     REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
    7198             :     wchar_t *print_name;
    7199             : 
    7200             :     static char *keywords[] = {"path", "dir_fd", NULL};
    7201             : 
    7202             :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
    7203             :                           &po,
    7204             :                           dir_fd_unavailable, &dir_fd
    7205             :                           ))
    7206             :         return NULL;
    7207             : 
    7208             :     path = PyUnicode_AsUnicode(po);
    7209             :     if (path == NULL)
    7210             :         return NULL;
    7211             : 
    7212             :     /* First get a handle to the reparse point */
    7213             :     Py_BEGIN_ALLOW_THREADS
    7214             :     reparse_point_handle = CreateFileW(
    7215             :         path,
    7216             :         0,
    7217             :         0,
    7218             :         0,
    7219             :         OPEN_EXISTING,
    7220             :         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
    7221             :         0);
    7222             :     Py_END_ALLOW_THREADS
    7223             : 
    7224             :     if (reparse_point_handle==INVALID_HANDLE_VALUE)
    7225             :         return win32_error_object("readlink", po);
    7226             : 
    7227             :     Py_BEGIN_ALLOW_THREADS
    7228             :     /* New call DeviceIoControl to read the reparse point */
    7229             :     io_result = DeviceIoControl(
    7230             :         reparse_point_handle,
    7231             :         FSCTL_GET_REPARSE_POINT,
    7232             :         0, 0, /* in buffer */
    7233             :         target_buffer, sizeof(target_buffer),
    7234             :         &n_bytes_returned,
    7235             :         0 /* we're not using OVERLAPPED_IO */
    7236             :         );
    7237             :     CloseHandle(reparse_point_handle);
    7238             :     Py_END_ALLOW_THREADS
    7239             : 
    7240             :     if (io_result==0)
    7241             :         return win32_error_object("readlink", po);
    7242             : 
    7243             :     if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
    7244             :     {
    7245             :         PyErr_SetString(PyExc_ValueError,
    7246             :                 "not a symbolic link");
    7247             :         return NULL;
    7248             :     }
    7249             :     print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
    7250             :                  rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
    7251             : 
    7252             :     result = PyUnicode_FromWideChar(print_name,
    7253             :                     rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
    7254             :     return result;
    7255             : }
    7256             : 
    7257             : #endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
    7258             : 
    7259             : 
    7260             : static PyStructSequence_Field times_result_fields[] = {
    7261             :     {"user",    "user time"},
    7262             :     {"system",   "system time"},
    7263             :     {"children_user",    "user time of children"},
    7264             :     {"children_system",    "system time of children"},
    7265             :     {"elapsed",    "elapsed time since an arbitrary point in the past"},
    7266             :     {NULL}
    7267             : };
    7268             : 
    7269             : PyDoc_STRVAR(times_result__doc__,
    7270             : "times_result: Result from os.times().\n\n\
    7271             : This object may be accessed either as a tuple of\n\
    7272             :   (user, system, children_user, children_system, elapsed),\n\
    7273             : or via the attributes user, system, children_user, children_system,\n\
    7274             : and elapsed.\n\
    7275             : \n\
    7276             : See os.times for more information.");
    7277             : 
    7278             : static PyStructSequence_Desc times_result_desc = {
    7279             :     "times_result", /* name */
    7280             :     times_result__doc__, /* doc */
    7281             :     times_result_fields,
    7282             :     5
    7283             : };
    7284             : 
    7285             : static PyTypeObject TimesResultType;
    7286             : 
    7287             : #ifdef MS_WINDOWS
    7288             : #define HAVE_TIMES  /* mandatory, for the method table */
    7289             : #endif
    7290             : 
    7291             : #ifdef HAVE_TIMES
    7292             : 
    7293             : static PyObject *
    7294           0 : build_times_result(double user, double system,
    7295             :     double children_user, double children_system,
    7296             :     double elapsed)
    7297             : {
    7298           0 :     PyObject *value = PyStructSequence_New(&TimesResultType);
    7299           0 :     if (value == NULL)
    7300           0 :         return NULL;
    7301             : 
    7302             : #define SET(i, field) \
    7303             :     { \
    7304             :     PyObject *o = PyFloat_FromDouble(field); \
    7305             :     if (!o) { \
    7306             :         Py_DECREF(value); \
    7307             :         return NULL; \
    7308             :     } \
    7309             :     PyStructSequence_SET_ITEM(value, i, o); \
    7310             :     } \
    7311             : 
    7312           0 :     SET(0, user);
    7313           0 :     SET(1, system);
    7314           0 :     SET(2, children_user);
    7315           0 :     SET(3, children_system);
    7316           0 :     SET(4, elapsed);
    7317             : 
    7318             : #undef SET
    7319             : 
    7320           0 :     return value;
    7321             : }
    7322             : 
    7323             : PyDoc_STRVAR(posix_times__doc__,
    7324             : "times() -> times_result\n\n\
    7325             : Return an object containing floating point numbers indicating process\n\
    7326             : times.  The object behaves like a named tuple with these fields:\n\
    7327             :   (utime, stime, cutime, cstime, elapsed_time)");
    7328             : 
    7329             : #if defined(PYCC_VACPP) && defined(PYOS_OS2)
    7330             : static long
    7331             : system_uptime(void)
    7332             : {
    7333             :     ULONG     value = 0;
    7334             : 
    7335             :     Py_BEGIN_ALLOW_THREADS
    7336             :     DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
    7337             :     Py_END_ALLOW_THREADS
    7338             : 
    7339             :     return value;
    7340             : }
    7341             : 
    7342             : static PyObject *
    7343             : posix_times(PyObject *self, PyObject *noargs)
    7344             : {
    7345             :     /* Currently Only Uptime is Provided -- Others Later */
    7346             :     return build_times_result(
    7347             :                          (double)0 /* t.tms_utime / HZ */,
    7348             :                          (double)0 /* t.tms_stime / HZ */,
    7349             :                          (double)0 /* t.tms_cutime / HZ */,
    7350             :                          (double)0 /* t.tms_cstime / HZ */,
    7351             :                          (double)system_uptime() / 1000);
    7352             : }
    7353             : #elif defined(MS_WINDOWS)
    7354             : static PyObject *
    7355             : posix_times(PyObject *self, PyObject *noargs)
    7356             : {
    7357             :     FILETIME create, exit, kernel, user;
    7358             :     HANDLE hProc;
    7359             :     hProc = GetCurrentProcess();
    7360             :     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
    7361             :     /* The fields of a FILETIME structure are the hi and lo part
    7362             :        of a 64-bit value expressed in 100 nanosecond units.
    7363             :        1e7 is one second in such units; 1e-7 the inverse.
    7364             :        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
    7365             :     */
    7366             :     return build_times_result(
    7367             :         (double)(user.dwHighDateTime*429.4967296 +
    7368             :                  user.dwLowDateTime*1e-7),
    7369             :         (double)(kernel.dwHighDateTime*429.4967296 +
    7370             :                  kernel.dwLowDateTime*1e-7),
    7371             :         (double)0,
    7372             :         (double)0,
    7373             :         (double)0);
    7374             : }
    7375             : #else /* Neither Windows nor OS/2 */
    7376             : #define NEED_TICKS_PER_SECOND
    7377             : static long ticks_per_second = -1;
    7378             : static PyObject *
    7379           0 : posix_times(PyObject *self, PyObject *noargs)
    7380             : {
    7381             :     struct tms t;
    7382             :     clock_t c;
    7383           0 :     errno = 0;
    7384           0 :     c = times(&t);
    7385           0 :     if (c == (clock_t) -1)
    7386           0 :         return posix_error();
    7387           0 :     return build_times_result(
    7388           0 :                          (double)t.tms_utime / ticks_per_second,
    7389           0 :                          (double)t.tms_stime / ticks_per_second,
    7390           0 :                          (double)t.tms_cutime / ticks_per_second,
    7391           0 :                          (double)t.tms_cstime / ticks_per_second,
    7392           0 :                          (double)c / ticks_per_second);
    7393             : }
    7394             : #endif
    7395             : 
    7396             : #endif /* HAVE_TIMES */
    7397             : 
    7398             : 
    7399             : #ifdef HAVE_GETSID
    7400             : PyDoc_STRVAR(posix_getsid__doc__,
    7401             : "getsid(pid) -> sid\n\n\
    7402             : Call the system call getsid().");
    7403             : 
    7404             : static PyObject *
    7405           0 : posix_getsid(PyObject *self, PyObject *args)
    7406             : {
    7407             :     pid_t pid;
    7408             :     int sid;
    7409           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getsid", &pid))
    7410           0 :         return NULL;
    7411           0 :     sid = getsid(pid);
    7412           0 :     if (sid < 0)
    7413           0 :         return posix_error();
    7414           0 :     return PyLong_FromLong((long)sid);
    7415             : }
    7416             : #endif /* HAVE_GETSID */
    7417             : 
    7418             : 
    7419             : #ifdef HAVE_SETSID
    7420             : PyDoc_STRVAR(posix_setsid__doc__,
    7421             : "setsid()\n\n\
    7422             : Call the system call setsid().");
    7423             : 
    7424             : static PyObject *
    7425           0 : posix_setsid(PyObject *self, PyObject *noargs)
    7426             : {
    7427           0 :     if (setsid() < 0)
    7428           0 :         return posix_error();
    7429           0 :     Py_INCREF(Py_None);
    7430           0 :     return Py_None;
    7431             : }
    7432             : #endif /* HAVE_SETSID */
    7433             : 
    7434             : #ifdef HAVE_SETPGID
    7435             : PyDoc_STRVAR(posix_setpgid__doc__,
    7436             : "setpgid(pid, pgrp)\n\n\
    7437             : Call the system call setpgid().");
    7438             : 
    7439             : static PyObject *
    7440           0 : posix_setpgid(PyObject *self, PyObject *args)
    7441             : {
    7442             :     pid_t pid;
    7443             :     int pgrp;
    7444           0 :     if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:setpgid", &pid, &pgrp))
    7445           0 :         return NULL;
    7446           0 :     if (setpgid(pid, pgrp) < 0)
    7447           0 :         return posix_error();
    7448           0 :     Py_INCREF(Py_None);
    7449           0 :     return Py_None;
    7450             : }
    7451             : #endif /* HAVE_SETPGID */
    7452             : 
    7453             : 
    7454             : #ifdef HAVE_TCGETPGRP
    7455             : PyDoc_STRVAR(posix_tcgetpgrp__doc__,
    7456             : "tcgetpgrp(fd) -> pgid\n\n\
    7457             : Return the process group associated with the terminal given by a fd.");
    7458             : 
    7459             : static PyObject *
    7460           0 : posix_tcgetpgrp(PyObject *self, PyObject *args)
    7461             : {
    7462             :     int fd;
    7463             :     pid_t pgid;
    7464           0 :     if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
    7465           0 :         return NULL;
    7466           0 :     pgid = tcgetpgrp(fd);
    7467           0 :     if (pgid < 0)
    7468           0 :         return posix_error();
    7469           0 :     return PyLong_FromPid(pgid);
    7470             : }
    7471             : #endif /* HAVE_TCGETPGRP */
    7472             : 
    7473             : 
    7474             : #ifdef HAVE_TCSETPGRP
    7475             : PyDoc_STRVAR(posix_tcsetpgrp__doc__,
    7476             : "tcsetpgrp(fd, pgid)\n\n\
    7477             : Set the process group associated with the terminal given by a fd.");
    7478             : 
    7479             : static PyObject *
    7480           0 : posix_tcsetpgrp(PyObject *self, PyObject *args)
    7481             : {
    7482             :     int fd;
    7483             :     pid_t pgid;
    7484           0 :     if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid))
    7485           0 :         return NULL;
    7486           0 :     if (tcsetpgrp(fd, pgid) < 0)
    7487           0 :         return posix_error();
    7488           0 :     Py_INCREF(Py_None);
    7489           0 :     return Py_None;
    7490             : }
    7491             : #endif /* HAVE_TCSETPGRP */
    7492             : 
    7493             : /* Functions acting on file descriptors */
    7494             : 
    7495             : PyDoc_STRVAR(posix_open__doc__,
    7496             : "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
    7497             : Open a file for low level IO.  Returns a file handle (integer).\n\
    7498             : \n\
    7499             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    7500             :   and path should be relative; path will then be relative to that directory.\n\
    7501             : dir_fd may not be implemented on your platform.\n\
    7502             :   If it is unavailable, using it will raise a NotImplementedError.");
    7503             : 
    7504             : static PyObject *
    7505           0 : posix_open(PyObject *self, PyObject *args, PyObject *kwargs)
    7506             : {
    7507             :     path_t path;
    7508             :     int flags;
    7509           0 :     int mode = 0777;
    7510           0 :     int dir_fd = DEFAULT_DIR_FD;
    7511             :     int fd;
    7512           0 :     PyObject *return_value = NULL;
    7513             :     static char *keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
    7514             : 
    7515           0 :     memset(&path, 0, sizeof(path));
    7516           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|i$O&:open", keywords,
    7517             :         path_converter, &path,
    7518             :         &flags, &mode,
    7519             : #ifdef HAVE_OPENAT
    7520             :         dir_fd_converter, &dir_fd
    7521             : #else
    7522             :         dir_fd_unavailable, &dir_fd
    7523             : #endif
    7524             :         ))
    7525           0 :         return NULL;
    7526             : 
    7527           0 :     Py_BEGIN_ALLOW_THREADS
    7528             : #ifdef MS_WINDOWS
    7529             :     if (path.wide)
    7530             :         fd = _wopen(path.wide, flags, mode);
    7531             :     else
    7532             : #endif
    7533             : #ifdef HAVE_OPENAT
    7534           0 :     if (dir_fd != DEFAULT_DIR_FD)
    7535           0 :         fd = openat(dir_fd, path.narrow, flags, mode);
    7536             :     else
    7537             : #endif
    7538           0 :         fd = open(path.narrow, flags, mode);
    7539           0 :     Py_END_ALLOW_THREADS
    7540             : 
    7541           0 :     if (fd == -1) {
    7542             : #ifdef MS_WINDOWS
    7543             :         /* force use of posix_error here for exact backwards compatibility */
    7544             :         if (path.wide)
    7545             :             return_value = posix_error();
    7546             :         else
    7547             : #endif
    7548           0 :         return_value = path_error("open", &path);
    7549           0 :         goto exit;
    7550             :     }
    7551             : 
    7552           0 :     return_value = PyLong_FromLong((long)fd);
    7553             : 
    7554             : exit:
    7555           0 :     path_cleanup(&path);
    7556           0 :     return return_value;
    7557             : }
    7558             : 
    7559             : PyDoc_STRVAR(posix_close__doc__,
    7560             : "close(fd)\n\n\
    7561             : Close a file descriptor (for low level IO).");
    7562             : 
    7563             : static PyObject *
    7564           0 : posix_close(PyObject *self, PyObject *args)
    7565             : {
    7566             :     int fd, res;
    7567           0 :     if (!PyArg_ParseTuple(args, "i:close", &fd))
    7568           0 :         return NULL;
    7569             :     if (!_PyVerify_fd(fd))
    7570             :         return posix_error();
    7571           0 :     Py_BEGIN_ALLOW_THREADS
    7572           0 :     res = close(fd);
    7573           0 :     Py_END_ALLOW_THREADS
    7574           0 :     if (res < 0)
    7575           0 :         return posix_error();
    7576           0 :     Py_INCREF(Py_None);
    7577           0 :     return Py_None;
    7578             : }
    7579             : 
    7580             : 
    7581             : PyDoc_STRVAR(posix_closerange__doc__,
    7582             : "closerange(fd_low, fd_high)\n\n\
    7583             : Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
    7584             : 
    7585             : static PyObject *
    7586           0 : posix_closerange(PyObject *self, PyObject *args)
    7587             : {
    7588             :     int fd_from, fd_to, i;
    7589           0 :     if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
    7590           0 :         return NULL;
    7591           0 :     Py_BEGIN_ALLOW_THREADS
    7592           0 :     for (i = fd_from; i < fd_to; i++)
    7593             :         if (_PyVerify_fd(i))
    7594           0 :             close(i);
    7595           0 :     Py_END_ALLOW_THREADS
    7596           0 :     Py_RETURN_NONE;
    7597             : }
    7598             : 
    7599             : 
    7600             : PyDoc_STRVAR(posix_dup__doc__,
    7601             : "dup(fd) -> fd2\n\n\
    7602             : Return a duplicate of a file descriptor.");
    7603             : 
    7604             : static PyObject *
    7605           0 : posix_dup(PyObject *self, PyObject *args)
    7606             : {
    7607             :     int fd;
    7608           0 :     if (!PyArg_ParseTuple(args, "i:dup", &fd))
    7609           0 :         return NULL;
    7610             :     if (!_PyVerify_fd(fd))
    7611             :         return posix_error();
    7612           0 :     fd = dup(fd);
    7613           0 :     if (fd < 0)
    7614           0 :         return posix_error();
    7615           0 :     return PyLong_FromLong((long)fd);
    7616             : }
    7617             : 
    7618             : 
    7619             : PyDoc_STRVAR(posix_dup2__doc__,
    7620             : "dup2(old_fd, new_fd)\n\n\
    7621             : Duplicate file descriptor.");
    7622             : 
    7623             : static PyObject *
    7624           0 : posix_dup2(PyObject *self, PyObject *args)
    7625             : {
    7626             :     int fd, fd2, res;
    7627           0 :     if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
    7628           0 :         return NULL;
    7629             :     if (!_PyVerify_fd_dup2(fd, fd2))
    7630             :         return posix_error();
    7631           0 :     res = dup2(fd, fd2);
    7632           0 :     if (res < 0)
    7633           0 :         return posix_error();
    7634           0 :     Py_INCREF(Py_None);
    7635           0 :     return Py_None;
    7636             : }
    7637             : 
    7638             : #ifdef HAVE_LOCKF
    7639             : PyDoc_STRVAR(posix_lockf__doc__,
    7640             : "lockf(fd, cmd, len)\n\n\
    7641             : Apply, test or remove a POSIX lock on an open file descriptor.\n\n\
    7642             : fd is an open file descriptor.\n\
    7643             : cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\
    7644             : F_TEST.\n\
    7645             : len specifies the section of the file to lock.");
    7646             : 
    7647             : static PyObject *
    7648           0 : posix_lockf(PyObject *self, PyObject *args)
    7649             : {
    7650             :     int fd, cmd, res;
    7651             :     off_t len;
    7652           0 :     if (!PyArg_ParseTuple(args, "iiO&:lockf",
    7653             :             &fd, &cmd, _parse_off_t, &len))
    7654           0 :         return NULL;
    7655             : 
    7656           0 :     Py_BEGIN_ALLOW_THREADS
    7657           0 :     res = lockf(fd, cmd, len);
    7658           0 :     Py_END_ALLOW_THREADS
    7659             : 
    7660           0 :     if (res < 0)
    7661           0 :         return posix_error();
    7662             : 
    7663           0 :     Py_RETURN_NONE;
    7664             : }
    7665             : #endif
    7666             : 
    7667             : 
    7668             : PyDoc_STRVAR(posix_lseek__doc__,
    7669             : "lseek(fd, pos, how) -> newpos\n\n\
    7670             : Set the current position of a file descriptor.\n\
    7671             : Return the new cursor position in bytes, starting from the beginning.");
    7672             : 
    7673             : static PyObject *
    7674           0 : posix_lseek(PyObject *self, PyObject *args)
    7675             : {
    7676             :     int fd, how;
    7677             : #if defined(MS_WIN64) || defined(MS_WINDOWS)
    7678             :     PY_LONG_LONG pos, res;
    7679             : #else
    7680             :     off_t pos, res;
    7681             : #endif
    7682             :     PyObject *posobj;
    7683           0 :     if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
    7684           0 :         return NULL;
    7685             : #ifdef SEEK_SET
    7686             :     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
    7687           0 :     switch (how) {
    7688           0 :     case 0: how = SEEK_SET; break;
    7689           0 :     case 1: how = SEEK_CUR; break;
    7690           0 :     case 2: how = SEEK_END; break;
    7691             :     }
    7692             : #endif /* SEEK_END */
    7693             : 
    7694             : #if !defined(HAVE_LARGEFILE_SUPPORT)
    7695             :     pos = PyLong_AsLong(posobj);
    7696             : #else
    7697           0 :     pos = PyLong_AsLongLong(posobj);
    7698             : #endif
    7699           0 :     if (PyErr_Occurred())
    7700           0 :         return NULL;
    7701             : 
    7702             :     if (!_PyVerify_fd(fd))
    7703             :         return posix_error();
    7704           0 :     Py_BEGIN_ALLOW_THREADS
    7705             : #if defined(MS_WIN64) || defined(MS_WINDOWS)
    7706             :     res = _lseeki64(fd, pos, how);
    7707             : #else
    7708           0 :     res = lseek(fd, pos, how);
    7709             : #endif
    7710           0 :     Py_END_ALLOW_THREADS
    7711           0 :     if (res < 0)
    7712           0 :         return posix_error();
    7713             : 
    7714             : #if !defined(HAVE_LARGEFILE_SUPPORT)
    7715             :     return PyLong_FromLong(res);
    7716             : #else
    7717           0 :     return PyLong_FromLongLong(res);
    7718             : #endif
    7719             : }
    7720             : 
    7721             : 
    7722             : PyDoc_STRVAR(posix_read__doc__,
    7723             : "read(fd, buffersize) -> string\n\n\
    7724             : Read a file descriptor.");
    7725             : 
    7726             : static PyObject *
    7727           0 : posix_read(PyObject *self, PyObject *args)
    7728             : {
    7729             :     int fd, size;
    7730             :     Py_ssize_t n;
    7731             :     PyObject *buffer;
    7732           0 :     if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
    7733           0 :         return NULL;
    7734           0 :     if (size < 0) {
    7735           0 :         errno = EINVAL;
    7736           0 :         return posix_error();
    7737             :     }
    7738           0 :     buffer = PyBytes_FromStringAndSize((char *)NULL, size);
    7739           0 :     if (buffer == NULL)
    7740           0 :         return NULL;
    7741             :     if (!_PyVerify_fd(fd)) {
    7742             :         Py_DECREF(buffer);
    7743             :         return posix_error();
    7744             :     }
    7745           0 :     Py_BEGIN_ALLOW_THREADS
    7746           0 :     n = read(fd, PyBytes_AS_STRING(buffer), size);
    7747           0 :     Py_END_ALLOW_THREADS
    7748           0 :     if (n < 0) {
    7749           0 :         Py_DECREF(buffer);
    7750           0 :         return posix_error();
    7751             :     }
    7752           0 :     if (n != size)
    7753           0 :         _PyBytes_Resize(&buffer, n);
    7754           0 :     return buffer;
    7755             : }
    7756             : 
    7757             : #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
    7758             :     || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
    7759             : static Py_ssize_t
    7760           0 : iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
    7761             : {
    7762             :     int i, j;
    7763           0 :     Py_ssize_t blen, total = 0;
    7764             : 
    7765           0 :     *iov = PyMem_New(struct iovec, cnt);
    7766           0 :     if (*iov == NULL) {
    7767           0 :         PyErr_NoMemory();
    7768           0 :         return total;
    7769             :     }
    7770             : 
    7771           0 :     *buf = PyMem_New(Py_buffer, cnt);
    7772           0 :     if (*buf == NULL) {
    7773           0 :         PyMem_Del(*iov);
    7774           0 :         PyErr_NoMemory();
    7775           0 :         return total;
    7776             :     }
    7777             : 
    7778           0 :     for (i = 0; i < cnt; i++) {
    7779           0 :         PyObject *item = PySequence_GetItem(seq, i);
    7780           0 :         if (item == NULL)
    7781           0 :             goto fail;
    7782           0 :         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
    7783           0 :             Py_DECREF(item);
    7784           0 :             goto fail;
    7785             :         }
    7786           0 :         Py_DECREF(item);
    7787           0 :         (*iov)[i].iov_base = (*buf)[i].buf;
    7788           0 :         blen = (*buf)[i].len;
    7789           0 :         (*iov)[i].iov_len = blen;
    7790           0 :         total += blen;
    7791             :     }
    7792           0 :     return total;
    7793             : 
    7794             : fail:
    7795           0 :     PyMem_Del(*iov);
    7796           0 :     for (j = 0; j < i; j++) {
    7797           0 :         PyBuffer_Release(&(*buf)[j]);
    7798             :     }
    7799           0 :     PyMem_Del(*buf);
    7800           0 :     return 0;
    7801             : }
    7802             : 
    7803             : static void
    7804           0 : iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
    7805             : {
    7806             :     int i;
    7807           0 :     PyMem_Del(iov);
    7808           0 :     for (i = 0; i < cnt; i++) {
    7809           0 :         PyBuffer_Release(&buf[i]);
    7810             :     }
    7811           0 :     PyMem_Del(buf);
    7812           0 : }
    7813             : #endif
    7814             : 
    7815             : #ifdef HAVE_READV
    7816             : PyDoc_STRVAR(posix_readv__doc__,
    7817             : "readv(fd, buffers) -> bytesread\n\n\
    7818             : Read from a file descriptor into a number of writable buffers. buffers\n\
    7819             : is an arbitrary sequence of writable buffers.\n\
    7820             : Returns the total number of bytes read.");
    7821             : 
    7822             : static PyObject *
    7823           0 : posix_readv(PyObject *self, PyObject *args)
    7824             : {
    7825             :     int fd, cnt;
    7826             :     Py_ssize_t n;
    7827             :     PyObject *seq;
    7828             :     struct iovec *iov;
    7829             :     Py_buffer *buf;
    7830             : 
    7831           0 :     if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq))
    7832           0 :         return NULL;
    7833           0 :     if (!PySequence_Check(seq)) {
    7834           0 :         PyErr_SetString(PyExc_TypeError,
    7835             :             "readv() arg 2 must be a sequence");
    7836           0 :         return NULL;
    7837             :     }
    7838           0 :     cnt = PySequence_Size(seq);
    7839             : 
    7840           0 :     if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE))
    7841           0 :         return NULL;
    7842             : 
    7843           0 :     Py_BEGIN_ALLOW_THREADS
    7844           0 :     n = readv(fd, iov, cnt);
    7845           0 :     Py_END_ALLOW_THREADS
    7846             : 
    7847           0 :     iov_cleanup(iov, buf, cnt);
    7848           0 :     return PyLong_FromSsize_t(n);
    7849             : }
    7850             : #endif
    7851             : 
    7852             : #ifdef HAVE_PREAD
    7853             : PyDoc_STRVAR(posix_pread__doc__,
    7854             : "pread(fd, buffersize, offset) -> string\n\n\
    7855             : Read from a file descriptor, fd, at a position of offset. It will read up\n\
    7856             : to buffersize number of bytes. The file offset remains unchanged.");
    7857             : 
    7858             : static PyObject *
    7859           0 : posix_pread(PyObject *self, PyObject *args)
    7860             : {
    7861             :     int fd, size;
    7862             :     off_t offset;
    7863             :     Py_ssize_t n;
    7864             :     PyObject *buffer;
    7865           0 :     if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset))
    7866           0 :         return NULL;
    7867             : 
    7868           0 :     if (size < 0) {
    7869           0 :         errno = EINVAL;
    7870           0 :         return posix_error();
    7871             :     }
    7872           0 :     buffer = PyBytes_FromStringAndSize((char *)NULL, size);
    7873           0 :     if (buffer == NULL)
    7874           0 :         return NULL;
    7875             :     if (!_PyVerify_fd(fd)) {
    7876             :         Py_DECREF(buffer);
    7877             :         return posix_error();
    7878             :     }
    7879           0 :     Py_BEGIN_ALLOW_THREADS
    7880           0 :     n = pread(fd, PyBytes_AS_STRING(buffer), size, offset);
    7881           0 :     Py_END_ALLOW_THREADS
    7882           0 :     if (n < 0) {
    7883           0 :         Py_DECREF(buffer);
    7884           0 :         return posix_error();
    7885             :     }
    7886           0 :     if (n != size)
    7887           0 :         _PyBytes_Resize(&buffer, n);
    7888           0 :     return buffer;
    7889             : }
    7890             : #endif
    7891             : 
    7892             : PyDoc_STRVAR(posix_write__doc__,
    7893             : "write(fd, string) -> byteswritten\n\n\
    7894             : Write a string to a file descriptor.");
    7895             : 
    7896             : static PyObject *
    7897           0 : posix_write(PyObject *self, PyObject *args)
    7898             : {
    7899             :     Py_buffer pbuf;
    7900             :     int fd;
    7901             :     Py_ssize_t size, len;
    7902             : 
    7903           0 :     if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
    7904           0 :         return NULL;
    7905             :     if (!_PyVerify_fd(fd)) {
    7906             :         PyBuffer_Release(&pbuf);
    7907             :         return posix_error();
    7908             :     }
    7909           0 :     len = pbuf.len;
    7910           0 :     Py_BEGIN_ALLOW_THREADS
    7911             : #if defined(MS_WIN64) || defined(MS_WINDOWS)
    7912             :     if (len > INT_MAX)
    7913             :         len = INT_MAX;
    7914             :     size = write(fd, pbuf.buf, (int)len);
    7915             : #else
    7916           0 :     size = write(fd, pbuf.buf, len);
    7917             : #endif
    7918           0 :     Py_END_ALLOW_THREADS
    7919           0 :     PyBuffer_Release(&pbuf);
    7920           0 :     if (size < 0)
    7921           0 :         return posix_error();
    7922           0 :     return PyLong_FromSsize_t(size);
    7923             : }
    7924             : 
    7925             : #ifdef HAVE_SENDFILE
    7926             : PyDoc_STRVAR(posix_sendfile__doc__,
    7927             : "sendfile(out, in, offset, nbytes) -> byteswritten\n\
    7928             : sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
    7929             :             -> byteswritten\n\
    7930             : Copy nbytes bytes from file descriptor in to file descriptor out.");
    7931             : 
    7932             : static PyObject *
    7933           0 : posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
    7934             : {
    7935             :     int in, out;
    7936             :     Py_ssize_t ret;
    7937             :     off_t offset;
    7938             : 
    7939             : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
    7940             : #ifndef __APPLE__
    7941             :     Py_ssize_t len;
    7942             : #endif
    7943             :     PyObject *headers = NULL, *trailers = NULL;
    7944             :     Py_buffer *hbuf, *tbuf;
    7945             :     off_t sbytes;
    7946             :     struct sf_hdtr sf;
    7947             :     int flags = 0;
    7948             :     sf.headers = NULL;
    7949             :     sf.trailers = NULL;
    7950             :     static char *keywords[] = {"out", "in",
    7951             :                                 "offset", "count",
    7952             :                                 "headers", "trailers", "flags", NULL};
    7953             : 
    7954             : #ifdef __APPLE__
    7955             :     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
    7956             :         keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes,
    7957             : #else
    7958             :     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
    7959             :         keywords, &out, &in, _parse_off_t, &offset, &len,
    7960             : #endif
    7961             :                 &headers, &trailers, &flags))
    7962             :             return NULL;
    7963             :     if (headers != NULL) {
    7964             :         if (!PySequence_Check(headers)) {
    7965             :             PyErr_SetString(PyExc_TypeError,
    7966             :                 "sendfile() headers must be a sequence or None");
    7967             :             return NULL;
    7968             :         } else {
    7969             :             Py_ssize_t i = 0; /* Avoid uninitialized warning */
    7970             :             sf.hdr_cnt = PySequence_Size(headers);
    7971             :             if (sf.hdr_cnt > 0 &&
    7972             :                 !(i = iov_setup(&(sf.headers), &hbuf,
    7973             :                                 headers, sf.hdr_cnt, PyBUF_SIMPLE)))
    7974             :                 return NULL;
    7975             : #ifdef __APPLE__
    7976             :             sbytes += i;
    7977             : #endif
    7978             :         }
    7979             :     }
    7980             :     if (trailers != NULL) {
    7981             :         if (!PySequence_Check(trailers)) {
    7982             :             PyErr_SetString(PyExc_TypeError,
    7983             :                 "sendfile() trailers must be a sequence or None");
    7984             :             return NULL;
    7985             :         } else {
    7986             :             Py_ssize_t i = 0; /* Avoid uninitialized warning */
    7987             :             sf.trl_cnt = PySequence_Size(trailers);
    7988             :             if (sf.trl_cnt > 0 &&
    7989             :                 !(i = iov_setup(&(sf.trailers), &tbuf,
    7990             :                                 trailers, sf.trl_cnt, PyBUF_SIMPLE)))
    7991             :                 return NULL;
    7992             : #ifdef __APPLE__
    7993             :             sbytes += i;
    7994             : #endif
    7995             :         }
    7996             :     }
    7997             : 
    7998             :     Py_BEGIN_ALLOW_THREADS
    7999             : #ifdef __APPLE__
    8000             :     ret = sendfile(in, out, offset, &sbytes, &sf, flags);
    8001             : #else
    8002             :     ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
    8003             : #endif
    8004             :     Py_END_ALLOW_THREADS
    8005             : 
    8006             :     if (sf.headers != NULL)
    8007             :         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
    8008             :     if (sf.trailers != NULL)
    8009             :         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
    8010             : 
    8011             :     if (ret < 0) {
    8012             :         if ((errno == EAGAIN) || (errno == EBUSY)) {
    8013             :             if (sbytes != 0) {
    8014             :                 // some data has been sent
    8015             :                 goto done;
    8016             :             }
    8017             :             else {
    8018             :                 // no data has been sent; upper application is supposed
    8019             :                 // to retry on EAGAIN or EBUSY
    8020             :                 return posix_error();
    8021             :             }
    8022             :         }
    8023             :         return posix_error();
    8024             :     }
    8025             :     goto done;
    8026             : 
    8027             : done:
    8028             :     #if !defined(HAVE_LARGEFILE_SUPPORT)
    8029             :         return Py_BuildValue("l", sbytes);
    8030             :     #else
    8031             :         return Py_BuildValue("L", sbytes);
    8032             :     #endif
    8033             : 
    8034             : #else
    8035             :     Py_ssize_t count;
    8036             :     PyObject *offobj;
    8037             :     static char *keywords[] = {"out", "in",
    8038             :                                 "offset", "count", NULL};
    8039           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
    8040             :             keywords, &out, &in, &offobj, &count))
    8041           0 :         return NULL;
    8042             : #ifdef linux
    8043           0 :     if (offobj == Py_None) {
    8044           0 :         Py_BEGIN_ALLOW_THREADS
    8045           0 :         ret = sendfile(out, in, NULL, count);
    8046           0 :         Py_END_ALLOW_THREADS
    8047           0 :         if (ret < 0)
    8048           0 :             return posix_error();
    8049           0 :         return Py_BuildValue("n", ret);
    8050             :     }
    8051             : #endif
    8052           0 :     if (!_parse_off_t(offobj, &offset))
    8053           0 :         return NULL;
    8054           0 :     Py_BEGIN_ALLOW_THREADS
    8055           0 :     ret = sendfile(out, in, &offset, count);
    8056           0 :     Py_END_ALLOW_THREADS
    8057           0 :     if (ret < 0)
    8058           0 :         return posix_error();
    8059           0 :     return Py_BuildValue("n", ret);
    8060             : #endif
    8061             : }
    8062             : #endif
    8063             : 
    8064             : PyDoc_STRVAR(posix_fstat__doc__,
    8065             : "fstat(fd) -> stat result\n\n\
    8066             : Like stat(), but for an open file descriptor.\n\
    8067             : Equivalent to stat(fd=fd).");
    8068             : 
    8069             : static PyObject *
    8070           0 : posix_fstat(PyObject *self, PyObject *args)
    8071             : {
    8072             :     int fd;
    8073             :     STRUCT_STAT st;
    8074             :     int res;
    8075           0 :     if (!PyArg_ParseTuple(args, "i:fstat", &fd))
    8076           0 :         return NULL;
    8077             : #ifdef __VMS
    8078             :     /* on OpenVMS we must ensure that all bytes are written to the file */
    8079             :     fsync(fd);
    8080             : #endif
    8081           0 :     Py_BEGIN_ALLOW_THREADS
    8082           0 :     res = FSTAT(fd, &st);
    8083           0 :     Py_END_ALLOW_THREADS
    8084           0 :     if (res != 0) {
    8085             : #ifdef MS_WINDOWS
    8086             :         return win32_error("fstat", NULL);
    8087             : #else
    8088           0 :         return posix_error();
    8089             : #endif
    8090             :     }
    8091             : 
    8092           0 :     return _pystat_fromstructstat(&st);
    8093             : }
    8094             : 
    8095             : PyDoc_STRVAR(posix_isatty__doc__,
    8096             : "isatty(fd) -> bool\n\n\
    8097             : Return True if the file descriptor 'fd' is an open file descriptor\n\
    8098             : connected to the slave end of a terminal.");
    8099             : 
    8100             : static PyObject *
    8101           0 : posix_isatty(PyObject *self, PyObject *args)
    8102             : {
    8103             :     int fd;
    8104           0 :     if (!PyArg_ParseTuple(args, "i:isatty", &fd))
    8105           0 :         return NULL;
    8106             :     if (!_PyVerify_fd(fd))
    8107             :         return PyBool_FromLong(0);
    8108           0 :     return PyBool_FromLong(isatty(fd));
    8109             : }
    8110             : 
    8111             : #ifdef HAVE_PIPE
    8112             : PyDoc_STRVAR(posix_pipe__doc__,
    8113             : "pipe() -> (read_end, write_end)\n\n\
    8114             : Create a pipe.");
    8115             : 
    8116             : static PyObject *
    8117           0 : posix_pipe(PyObject *self, PyObject *noargs)
    8118             : {
    8119             : #if defined(PYOS_OS2)
    8120             :     HFILE read, write;
    8121             :     APIRET rc;
    8122             : 
    8123             :     rc = DosCreatePipe( &read, &write, 4096);
    8124             :     if (rc != NO_ERROR)
    8125             :         return os2_error(rc);
    8126             : 
    8127             :     return Py_BuildValue("(ii)", read, write);
    8128             : #else
    8129             : #if !defined(MS_WINDOWS)
    8130             :     int fds[2];
    8131             :     int res;
    8132           0 :     res = pipe(fds);
    8133           0 :     if (res != 0)
    8134           0 :         return posix_error();
    8135           0 :     return Py_BuildValue("(ii)", fds[0], fds[1]);
    8136             : #else /* MS_WINDOWS */
    8137             :     HANDLE read, write;
    8138             :     int read_fd, write_fd;
    8139             :     BOOL ok;
    8140             :     ok = CreatePipe(&read, &write, NULL, 0);
    8141             :     if (!ok)
    8142             :         return win32_error("CreatePipe", NULL);
    8143             :     read_fd = _open_osfhandle((Py_intptr_t)read, 0);
    8144             :     write_fd = _open_osfhandle((Py_intptr_t)write, 1);
    8145             :     return Py_BuildValue("(ii)", read_fd, write_fd);
    8146             : #endif /* MS_WINDOWS */
    8147             : #endif
    8148             : }
    8149             : #endif  /* HAVE_PIPE */
    8150             : 
    8151             : #ifdef HAVE_PIPE2
    8152             : PyDoc_STRVAR(posix_pipe2__doc__,
    8153             : "pipe2(flags) -> (read_end, write_end)\n\n\
    8154             : Create a pipe with flags set atomically.\n\
    8155             : flags can be constructed by ORing together one or more of these values:\n\
    8156             : O_NONBLOCK, O_CLOEXEC.\n\
    8157             : ");
    8158             : 
    8159             : static PyObject *
    8160           0 : posix_pipe2(PyObject *self, PyObject *arg)
    8161             : {
    8162             :     int flags;
    8163             :     int fds[2];
    8164             :     int res;
    8165             : 
    8166           0 :     flags = PyLong_AsLong(arg);
    8167           0 :     if (flags == -1 && PyErr_Occurred())
    8168           0 :         return NULL;
    8169             : 
    8170           0 :     res = pipe2(fds, flags);
    8171           0 :     if (res != 0)
    8172           0 :         return posix_error();
    8173           0 :     return Py_BuildValue("(ii)", fds[0], fds[1]);
    8174             : }
    8175             : #endif /* HAVE_PIPE2 */
    8176             : 
    8177             : #ifdef HAVE_WRITEV
    8178             : PyDoc_STRVAR(posix_writev__doc__,
    8179             : "writev(fd, buffers) -> byteswritten\n\n\
    8180             : Write the contents of buffers to a file descriptor, where buffers is an\n\
    8181             : arbitrary sequence of buffers.\n\
    8182             : Returns the total bytes written.");
    8183             : 
    8184             : static PyObject *
    8185           0 : posix_writev(PyObject *self, PyObject *args)
    8186             : {
    8187             :     int fd, cnt;
    8188             :     Py_ssize_t res;
    8189             :     PyObject *seq;
    8190             :     struct iovec *iov;
    8191             :     Py_buffer *buf;
    8192           0 :     if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq))
    8193           0 :         return NULL;
    8194           0 :     if (!PySequence_Check(seq)) {
    8195           0 :         PyErr_SetString(PyExc_TypeError,
    8196             :             "writev() arg 2 must be a sequence");
    8197           0 :         return NULL;
    8198             :     }
    8199           0 :     cnt = PySequence_Size(seq);
    8200             : 
    8201           0 :     if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) {
    8202           0 :         return NULL;
    8203             :     }
    8204             : 
    8205           0 :     Py_BEGIN_ALLOW_THREADS
    8206           0 :     res = writev(fd, iov, cnt);
    8207           0 :     Py_END_ALLOW_THREADS
    8208             : 
    8209           0 :     iov_cleanup(iov, buf, cnt);
    8210           0 :     return PyLong_FromSsize_t(res);
    8211             : }
    8212             : #endif
    8213             : 
    8214             : #ifdef HAVE_PWRITE
    8215             : PyDoc_STRVAR(posix_pwrite__doc__,
    8216             : "pwrite(fd, string, offset) -> byteswritten\n\n\
    8217             : Write string to a file descriptor, fd, from offset, leaving the file\n\
    8218             : offset unchanged.");
    8219             : 
    8220             : static PyObject *
    8221           0 : posix_pwrite(PyObject *self, PyObject *args)
    8222             : {
    8223             :     Py_buffer pbuf;
    8224             :     int fd;
    8225             :     off_t offset;
    8226             :     Py_ssize_t size;
    8227             : 
    8228           0 :     if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset))
    8229           0 :         return NULL;
    8230             : 
    8231             :     if (!_PyVerify_fd(fd)) {
    8232             :         PyBuffer_Release(&pbuf);
    8233             :         return posix_error();
    8234             :     }
    8235           0 :     Py_BEGIN_ALLOW_THREADS
    8236           0 :     size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset);
    8237           0 :     Py_END_ALLOW_THREADS
    8238           0 :     PyBuffer_Release(&pbuf);
    8239           0 :     if (size < 0)
    8240           0 :         return posix_error();
    8241           0 :     return PyLong_FromSsize_t(size);
    8242             : }
    8243             : #endif
    8244             : 
    8245             : #ifdef HAVE_MKFIFO
    8246             : PyDoc_STRVAR(posix_mkfifo__doc__,
    8247             : "mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\
    8248             : Create a FIFO (a POSIX named pipe).\n\
    8249             : \n\
    8250             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    8251             :   and path should be relative; path will then be relative to that directory.\n\
    8252             : dir_fd may not be implemented on your platform.\n\
    8253             :   If it is unavailable, using it will raise a NotImplementedError.");
    8254             : 
    8255             : static PyObject *
    8256           0 : posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs)
    8257             : {
    8258             :     path_t path;
    8259           0 :     int mode = 0666;
    8260           0 :     int dir_fd = DEFAULT_DIR_FD;
    8261             :     int result;
    8262           0 :     PyObject *return_value = NULL;
    8263             :     static char *keywords[] = {"path", "mode", "dir_fd", NULL};
    8264             : 
    8265           0 :     memset(&path, 0, sizeof(path));
    8266           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords,
    8267             :         path_converter, &path,
    8268             :         &mode,
    8269             : #ifdef HAVE_MKFIFOAT
    8270             :         dir_fd_converter, &dir_fd
    8271             : #else
    8272             :         dir_fd_unavailable, &dir_fd
    8273             : #endif
    8274             :         ))
    8275           0 :         return NULL;
    8276             : 
    8277           0 :     Py_BEGIN_ALLOW_THREADS
    8278             : #ifdef HAVE_MKFIFOAT
    8279           0 :     if (dir_fd != DEFAULT_DIR_FD)
    8280           0 :         result = mkfifoat(dir_fd, path.narrow, mode);
    8281             :     else
    8282             : #endif
    8283           0 :         result = mkfifo(path.narrow, mode);
    8284           0 :     Py_END_ALLOW_THREADS
    8285             : 
    8286           0 :     if (result < 0) {
    8287           0 :         return_value = posix_error();
    8288           0 :         goto exit;
    8289             :     }
    8290             : 
    8291           0 :     return_value = Py_None;
    8292           0 :     Py_INCREF(Py_None);
    8293             : 
    8294             : exit:
    8295           0 :     path_cleanup(&path);
    8296           0 :     return return_value;
    8297             : }
    8298             : #endif
    8299             : 
    8300             : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
    8301             : PyDoc_STRVAR(posix_mknod__doc__,
    8302             : "mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\
    8303             : Create a filesystem node (file, device special file or named pipe)\n\
    8304             : named filename. mode specifies both the permissions to use and the\n\
    8305             : type of node to be created, being combined (bitwise OR) with one of\n\
    8306             : S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
    8307             : device defines the newly created device special file (probably using\n\
    8308             : os.makedev()), otherwise it is ignored.\n\
    8309             : \n\
    8310             : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
    8311             :   and path should be relative; path will then be relative to that directory.\n\
    8312             : dir_fd may not be implemented on your platform.\n\
    8313             :   If it is unavailable, using it will raise a NotImplementedError.");
    8314             : 
    8315             : 
    8316             : static PyObject *
    8317           0 : posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs)
    8318             : {
    8319             :     path_t path;
    8320           0 :     int mode = 0666;
    8321           0 :     int device = 0;
    8322           0 :     int dir_fd = DEFAULT_DIR_FD;
    8323             :     int result;
    8324           0 :     PyObject *return_value = NULL;
    8325             :     static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL};
    8326             : 
    8327           0 :     memset(&path, 0, sizeof(path));
    8328           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|ii$O&:mknod", keywords,
    8329             :         path_converter, &path,
    8330             :         &mode, &device,
    8331             : #ifdef HAVE_MKNODAT
    8332             :         dir_fd_converter, &dir_fd
    8333             : #else
    8334             :         dir_fd_unavailable, &dir_fd
    8335             : #endif
    8336             :         ))
    8337           0 :         return NULL;
    8338             : 
    8339           0 :     Py_BEGIN_ALLOW_THREADS
    8340             : #ifdef HAVE_MKNODAT
    8341           0 :     if (dir_fd != DEFAULT_DIR_FD)
    8342           0 :         result = mknodat(dir_fd, path.narrow, mode, device);
    8343             :     else
    8344             : #endif
    8345           0 :         result = mknod(path.narrow, mode, device);
    8346           0 :     Py_END_ALLOW_THREADS
    8347             : 
    8348           0 :     if (result < 0) {
    8349           0 :         return_value = posix_error();
    8350           0 :         goto exit;
    8351             :     }
    8352             : 
    8353           0 :     return_value = Py_None;
    8354           0 :     Py_INCREF(Py_None);
    8355             : 
    8356             : exit:
    8357           0 :     path_cleanup(&path);
    8358           0 :     return return_value;
    8359             : }
    8360             : #endif
    8361             : 
    8362             : #ifdef HAVE_DEVICE_MACROS
    8363             : PyDoc_STRVAR(posix_major__doc__,
    8364             : "major(device) -> major number\n\
    8365             : Extracts a device major number from a raw device number.");
    8366             : 
    8367             : static PyObject *
    8368           0 : posix_major(PyObject *self, PyObject *args)
    8369             : {
    8370             :     int device;
    8371           0 :     if (!PyArg_ParseTuple(args, "i:major", &device))
    8372           0 :         return NULL;
    8373           0 :     return PyLong_FromLong((long)major(device));
    8374             : }
    8375             : 
    8376             : PyDoc_STRVAR(posix_minor__doc__,
    8377             : "minor(device) -> minor number\n\
    8378             : Extracts a device minor number from a raw device number.");
    8379             : 
    8380             : static PyObject *
    8381           0 : posix_minor(PyObject *self, PyObject *args)
    8382             : {
    8383             :     int device;
    8384           0 :     if (!PyArg_ParseTuple(args, "i:minor", &device))
    8385           0 :         return NULL;
    8386           0 :     return PyLong_FromLong((long)minor(device));
    8387             : }
    8388             : 
    8389             : PyDoc_STRVAR(posix_makedev__doc__,
    8390             : "makedev(major, minor) -> device number\n\
    8391             : Composes a raw device number from the major and minor device numbers.");
    8392             : 
    8393             : static PyObject *
    8394           0 : posix_makedev(PyObject *self, PyObject *args)
    8395             : {
    8396             :     int major, minor;
    8397           0 :     if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
    8398           0 :         return NULL;
    8399           0 :     return PyLong_FromLong((long)makedev(major, minor));
    8400             : }
    8401             : #endif /* device macros */
    8402             : 
    8403             : 
    8404             : #ifdef HAVE_FTRUNCATE
    8405             : PyDoc_STRVAR(posix_ftruncate__doc__,
    8406             : "ftruncate(fd, length)\n\n\
    8407             : Truncate a file to a specified length.");
    8408             : 
    8409             : static PyObject *
    8410           0 : posix_ftruncate(PyObject *self, PyObject *args)
    8411             : {
    8412             :     int fd;
    8413             :     off_t length;
    8414             :     int res;
    8415             : 
    8416           0 :     if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length))
    8417           0 :         return NULL;
    8418             : 
    8419           0 :     Py_BEGIN_ALLOW_THREADS
    8420           0 :     res = ftruncate(fd, length);
    8421           0 :     Py_END_ALLOW_THREADS
    8422           0 :     if (res < 0)
    8423           0 :         return posix_error();
    8424           0 :     Py_INCREF(Py_None);
    8425           0 :     return Py_None;
    8426             : }
    8427             : #endif
    8428             : 
    8429             : #ifdef HAVE_TRUNCATE
    8430             : PyDoc_STRVAR(posix_truncate__doc__,
    8431             : "truncate(path, length)\n\n\
    8432             : Truncate the file given by path to length bytes.\n\
    8433             : On some platforms, path may also be specified as an open file descriptor.\n\
    8434             :   If this functionality is unavailable, using it raises an exception.");
    8435             : 
    8436             : static PyObject *
    8437           0 : posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
    8438             : {
    8439             :     path_t path;
    8440             :     off_t length;
    8441             :     int res;
    8442           0 :     PyObject *result = NULL;
    8443             :     static char *keywords[] = {"path", "length", NULL};
    8444             : 
    8445           0 :     memset(&path, 0, sizeof(path));
    8446             : #ifdef HAVE_FTRUNCATE
    8447           0 :     path.allow_fd = 1;
    8448             : #endif
    8449           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords,
    8450             :                                      path_converter, &path,
    8451             :                                      _parse_off_t, &length))
    8452           0 :         return NULL;
    8453             : 
    8454           0 :     Py_BEGIN_ALLOW_THREADS
    8455             : #ifdef HAVE_FTRUNCATE
    8456           0 :     if (path.fd != -1)
    8457           0 :         res = ftruncate(path.fd, length);
    8458             :     else
    8459             : #endif
    8460           0 :         res = truncate(path.narrow, length);
    8461           0 :     Py_END_ALLOW_THREADS
    8462           0 :     if (res < 0)
    8463           0 :         result = path_posix_error("truncate", &path);
    8464             :     else {
    8465           0 :         Py_INCREF(Py_None);
    8466           0 :         result = Py_None;
    8467             :     }
    8468           0 :     path_cleanup(&path);
    8469           0 :     return result;
    8470             : }
    8471             : #endif
    8472             : 
    8473             : #ifdef HAVE_POSIX_FALLOCATE
    8474             : PyDoc_STRVAR(posix_posix_fallocate__doc__,
    8475             : "posix_fallocate(fd, offset, len)\n\n\
    8476             : Ensures that enough disk space is allocated for the file specified by fd\n\
    8477             : starting from offset and continuing for len bytes.");
    8478             : 
    8479             : static PyObject *
    8480           0 : posix_posix_fallocate(PyObject *self, PyObject *args)
    8481             : {
    8482             :     off_t len, offset;
    8483             :     int res, fd;
    8484             : 
    8485           0 :     if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate",
    8486             :             &fd, _parse_off_t, &offset, _parse_off_t, &len))
    8487           0 :         return NULL;
    8488             : 
    8489           0 :     Py_BEGIN_ALLOW_THREADS
    8490           0 :     res = posix_fallocate(fd, offset, len);
    8491           0 :     Py_END_ALLOW_THREADS
    8492           0 :     if (res != 0) {
    8493           0 :         errno = res;
    8494           0 :         return posix_error();
    8495             :     }
    8496           0 :     Py_RETURN_NONE;
    8497             : }
    8498             : #endif
    8499             : 
    8500             : #ifdef HAVE_POSIX_FADVISE
    8501             : PyDoc_STRVAR(posix_posix_fadvise__doc__,
    8502             : "posix_fadvise(fd, offset, len, advice)\n\n\
    8503             : Announces an intention to access data in a specific pattern thus allowing\n\
    8504             : the kernel to make optimizations.\n\
    8505             : The advice applies to the region of the file specified by fd starting at\n\
    8506             : offset and continuing for len bytes.\n\
    8507             : advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\
    8508             : POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\
    8509             : POSIX_FADV_DONTNEED.");
    8510             : 
    8511             : static PyObject *
    8512           0 : posix_posix_fadvise(PyObject *self, PyObject *args)
    8513             : {
    8514             :     off_t len, offset;
    8515             :     int res, fd, advice;
    8516             : 
    8517           0 :     if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise",
    8518             :             &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice))
    8519           0 :         return NULL;
    8520             : 
    8521           0 :     Py_BEGIN_ALLOW_THREADS
    8522           0 :     res = posix_fadvise(fd, offset, len, advice);
    8523           0 :     Py_END_ALLOW_THREADS
    8524           0 :     if (res != 0) {
    8525           0 :         errno = res;
    8526           0 :         return posix_error();
    8527             :     }
    8528           0 :     Py_RETURN_NONE;
    8529             : }
    8530             : #endif
    8531             : 
    8532             : #ifdef HAVE_PUTENV
    8533             : PyDoc_STRVAR(posix_putenv__doc__,
    8534             : "putenv(key, value)\n\n\
    8535             : Change or add an environment variable.");
    8536             : 
    8537             : /* Save putenv() parameters as values here, so we can collect them when they
    8538             :  * get re-set with another call for the same key. */
    8539             : static PyObject *posix_putenv_garbage;
    8540             : 
    8541             : static PyObject *
    8542           0 : posix_putenv(PyObject *self, PyObject *args)
    8543             : {
    8544           0 :     PyObject *newstr = NULL;
    8545             : #ifdef MS_WINDOWS
    8546             :     PyObject *os1, *os2;
    8547             :     wchar_t *newenv;
    8548             : 
    8549             :     if (!PyArg_ParseTuple(args,
    8550             :                           "UU:putenv",
    8551             :                           &os1, &os2))
    8552             :         return NULL;
    8553             : 
    8554             :     newstr = PyUnicode_FromFormat("%U=%U", os1, os2);
    8555             :     if (newstr == NULL) {
    8556             :         PyErr_NoMemory();
    8557             :         goto error;
    8558             :     }
    8559             :     if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) {
    8560             :         PyErr_Format(PyExc_ValueError,
    8561             :                      "the environment variable is longer than %u characters",
    8562             :                      _MAX_ENV);
    8563             :         goto error;
    8564             :     }
    8565             : 
    8566             :     newenv = PyUnicode_AsUnicode(newstr);
    8567             :     if (newenv == NULL)
    8568             :         goto error;
    8569             :     if (_wputenv(newenv)) {
    8570             :         posix_error();
    8571             :         goto error;
    8572             :     }
    8573             : #else
    8574             :     PyObject *os1, *os2;
    8575             :     char *s1, *s2;
    8576             :     char *newenv;
    8577             : 
    8578           0 :     if (!PyArg_ParseTuple(args,
    8579             :                           "O&O&:putenv",
    8580             :                           PyUnicode_FSConverter, &os1,
    8581             :                           PyUnicode_FSConverter, &os2))
    8582           0 :         return NULL;
    8583           0 :     s1 = PyBytes_AsString(os1);
    8584           0 :     s2 = PyBytes_AsString(os2);
    8585             : 
    8586           0 :     newstr = PyBytes_FromFormat("%s=%s", s1, s2);
    8587           0 :     if (newstr == NULL) {
    8588           0 :         PyErr_NoMemory();
    8589           0 :         goto error;
    8590             :     }
    8591             : 
    8592           0 :     newenv = PyBytes_AS_STRING(newstr);
    8593           0 :     if (putenv(newenv)) {
    8594           0 :         posix_error();
    8595           0 :         goto error;
    8596             :     }
    8597             : #endif
    8598             : 
    8599             :     /* Install the first arg and newstr in posix_putenv_garbage;
    8600             :      * this will cause previous value to be collected.  This has to
    8601             :      * happen after the real putenv() call because the old value
    8602             :      * was still accessible until then. */
    8603           0 :     if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) {
    8604             :         /* really not much we can do; just leak */
    8605           0 :         PyErr_Clear();
    8606             :     }
    8607             :     else {
    8608           0 :         Py_DECREF(newstr);
    8609             :     }
    8610             : 
    8611             : #ifndef MS_WINDOWS
    8612           0 :     Py_DECREF(os1);
    8613           0 :     Py_DECREF(os2);
    8614             : #endif
    8615           0 :     Py_RETURN_NONE;
    8616             : 
    8617             : error:
    8618             : #ifndef MS_WINDOWS
    8619           0 :     Py_DECREF(os1);
    8620           0 :     Py_DECREF(os2);
    8621             : #endif
    8622           0 :     Py_XDECREF(newstr);
    8623           0 :     return NULL;
    8624             : }
    8625             : #endif /* putenv */
    8626             : 
    8627             : #ifdef HAVE_UNSETENV
    8628             : PyDoc_STRVAR(posix_unsetenv__doc__,
    8629             : "unsetenv(key)\n\n\
    8630             : Delete an environment variable.");
    8631             : 
    8632             : static PyObject *
    8633           0 : posix_unsetenv(PyObject *self, PyObject *args)
    8634             : {
    8635             :     PyObject *name;
    8636             : #ifndef HAVE_BROKEN_UNSETENV
    8637             :     int err;
    8638             : #endif
    8639             : 
    8640           0 :     if (!PyArg_ParseTuple(args, "O&:unsetenv",
    8641             : 
    8642             :                           PyUnicode_FSConverter, &name))
    8643           0 :         return NULL;
    8644             : 
    8645             : #ifdef HAVE_BROKEN_UNSETENV
    8646             :     unsetenv(PyBytes_AS_STRING(name));
    8647             : #else
    8648           0 :     err = unsetenv(PyBytes_AS_STRING(name));
    8649           0 :     if (err) {
    8650           0 :         Py_DECREF(name);
    8651           0 :         return posix_error();
    8652             :     }
    8653             : #endif
    8654             : 
    8655             :     /* Remove the key from posix_putenv_garbage;
    8656             :      * this will cause it to be collected.  This has to
    8657             :      * happen after the real unsetenv() call because the
    8658             :      * old value was still accessible until then.
    8659             :      */
    8660           0 :     if (PyDict_DelItem(posix_putenv_garbage, name)) {
    8661             :         /* really not much we can do; just leak */
    8662           0 :         PyErr_Clear();
    8663             :     }
    8664           0 :     Py_DECREF(name);
    8665           0 :     Py_RETURN_NONE;
    8666             : }
    8667             : #endif /* unsetenv */
    8668             : 
    8669             : PyDoc_STRVAR(posix_strerror__doc__,
    8670             : "strerror(code) -> string\n\n\
    8671             : Translate an error code to a message string.");
    8672             : 
    8673             : static PyObject *
    8674           0 : posix_strerror(PyObject *self, PyObject *args)
    8675             : {
    8676             :     int code;
    8677             :     char *message;
    8678           0 :     if (!PyArg_ParseTuple(args, "i:strerror", &code))
    8679           0 :         return NULL;
    8680           0 :     message = strerror(code);
    8681           0 :     if (message == NULL) {
    8682           0 :         PyErr_SetString(PyExc_ValueError,
    8683             :                         "strerror() argument out of range");
    8684           0 :         return NULL;
    8685             :     }
    8686           0 :     return PyUnicode_DecodeLocale(message, "surrogateescape");
    8687             : }
    8688             : 
    8689             : 
    8690             : #ifdef HAVE_SYS_WAIT_H
    8691             : 
    8692             : #ifdef WCOREDUMP
    8693             : PyDoc_STRVAR(posix_WCOREDUMP__doc__,
    8694             : "WCOREDUMP(status) -> bool\n\n\
    8695             : Return True if the process returning 'status' was dumped to a core file.");
    8696             : 
    8697             : static PyObject *
    8698           0 : posix_WCOREDUMP(PyObject *self, PyObject *args)
    8699             : {
    8700             :     WAIT_TYPE status;
    8701           0 :     WAIT_STATUS_INT(status) = 0;
    8702             : 
    8703           0 :     if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
    8704           0 :         return NULL;
    8705             : 
    8706           0 :     return PyBool_FromLong(WCOREDUMP(status));
    8707             : }
    8708             : #endif /* WCOREDUMP */
    8709             : 
    8710             : #ifdef WIFCONTINUED
    8711             : PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
    8712             : "WIFCONTINUED(status) -> bool\n\n\
    8713             : Return True if the process returning 'status' was continued from a\n\
    8714             : job control stop.");
    8715             : 
    8716             : static PyObject *
    8717           0 : posix_WIFCONTINUED(PyObject *self, PyObject *args)
    8718             : {
    8719             :     WAIT_TYPE status;
    8720           0 :     WAIT_STATUS_INT(status) = 0;
    8721             : 
    8722           0 :     if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
    8723           0 :         return NULL;
    8724             : 
    8725           0 :     return PyBool_FromLong(WIFCONTINUED(status));
    8726             : }
    8727             : #endif /* WIFCONTINUED */
    8728             : 
    8729             : #ifdef WIFSTOPPED
    8730             : PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
    8731             : "WIFSTOPPED(status) -> bool\n\n\
    8732             : Return True if the process returning 'status' was stopped.");
    8733             : 
    8734             : static PyObject *
    8735           0 : posix_WIFSTOPPED(PyObject *self, PyObject *args)
    8736             : {
    8737             :     WAIT_TYPE status;
    8738           0 :     WAIT_STATUS_INT(status) = 0;
    8739             : 
    8740           0 :     if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
    8741           0 :         return NULL;
    8742             : 
    8743           0 :     return PyBool_FromLong(WIFSTOPPED(status));
    8744             : }
    8745             : #endif /* WIFSTOPPED */
    8746             : 
    8747             : #ifdef WIFSIGNALED
    8748             : PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
    8749             : "WIFSIGNALED(status) -> bool\n\n\
    8750             : Return True if the process returning 'status' was terminated by a signal.");
    8751             : 
    8752             : static PyObject *
    8753           0 : posix_WIFSIGNALED(PyObject *self, PyObject *args)
    8754             : {
    8755             :     WAIT_TYPE status;
    8756           0 :     WAIT_STATUS_INT(status) = 0;
    8757             : 
    8758           0 :     if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
    8759           0 :         return NULL;
    8760             : 
    8761           0 :     return PyBool_FromLong(WIFSIGNALED(status));
    8762             : }
    8763             : #endif /* WIFSIGNALED */
    8764             : 
    8765             : #ifdef WIFEXITED
    8766             : PyDoc_STRVAR(posix_WIFEXITED__doc__,
    8767             : "WIFEXITED(status) -> bool\n\n\
    8768             : Return true if the process returning 'status' exited using the exit()\n\
    8769             : system call.");
    8770             : 
    8771             : static PyObject *
    8772           0 : posix_WIFEXITED(PyObject *self, PyObject *args)
    8773             : {
    8774             :     WAIT_TYPE status;
    8775           0 :     WAIT_STATUS_INT(status) = 0;
    8776             : 
    8777           0 :     if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
    8778           0 :         return NULL;
    8779             : 
    8780           0 :     return PyBool_FromLong(WIFEXITED(status));
    8781             : }
    8782             : #endif /* WIFEXITED */
    8783             : 
    8784             : #ifdef WEXITSTATUS
    8785             : PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
    8786             : "WEXITSTATUS(status) -> integer\n\n\
    8787             : Return the process return code from 'status'.");
    8788             : 
    8789             : static PyObject *
    8790           0 : posix_WEXITSTATUS(PyObject *self, PyObject *args)
    8791             : {
    8792             :     WAIT_TYPE status;
    8793           0 :     WAIT_STATUS_INT(status) = 0;
    8794             : 
    8795           0 :     if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
    8796           0 :         return NULL;
    8797             : 
    8798           0 :     return Py_BuildValue("i", WEXITSTATUS(status));
    8799             : }
    8800             : #endif /* WEXITSTATUS */
    8801             : 
    8802             : #ifdef WTERMSIG
    8803             : PyDoc_STRVAR(posix_WTERMSIG__doc__,
    8804             : "WTERMSIG(status) -> integer\n\n\
    8805             : Return the signal that terminated the process that provided the 'status'\n\
    8806             : value.");
    8807             : 
    8808             : static PyObject *
    8809           0 : posix_WTERMSIG(PyObject *self, PyObject *args)
    8810             : {
    8811             :     WAIT_TYPE status;
    8812           0 :     WAIT_STATUS_INT(status) = 0;
    8813             : 
    8814           0 :     if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
    8815           0 :         return NULL;
    8816             : 
    8817           0 :     return Py_BuildValue("i", WTERMSIG(status));
    8818             : }
    8819             : #endif /* WTERMSIG */
    8820             : 
    8821             : #ifdef WSTOPSIG
    8822             : PyDoc_STRVAR(posix_WSTOPSIG__doc__,
    8823             : "WSTOPSIG(status) -> integer\n\n\
    8824             : Return the signal that stopped the process that provided\n\
    8825             : the 'status' value.");
    8826             : 
    8827             : static PyObject *
    8828           0 : posix_WSTOPSIG(PyObject *self, PyObject *args)
    8829             : {
    8830             :     WAIT_TYPE status;
    8831           0 :     WAIT_STATUS_INT(status) = 0;
    8832             : 
    8833           0 :     if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
    8834           0 :         return NULL;
    8835             : 
    8836           0 :     return Py_BuildValue("i", WSTOPSIG(status));
    8837             : }
    8838             : #endif /* WSTOPSIG */
    8839             : 
    8840             : #endif /* HAVE_SYS_WAIT_H */
    8841             : 
    8842             : 
    8843             : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
    8844             : #ifdef _SCO_DS
    8845             : /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
    8846             :    needed definitions in sys/statvfs.h */
    8847             : #define _SVID3
    8848             : #endif
    8849             : #include <sys/statvfs.h>
    8850             : 
    8851             : static PyObject*
    8852           0 : _pystatvfs_fromstructstatvfs(struct statvfs st) {
    8853           0 :     PyObject *v = PyStructSequence_New(&StatVFSResultType);
    8854           0 :     if (v == NULL)
    8855           0 :         return NULL;
    8856             : 
    8857             : #if !defined(HAVE_LARGEFILE_SUPPORT)
    8858             :     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
    8859             :     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
    8860             :     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
    8861             :     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
    8862             :     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
    8863             :     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
    8864             :     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
    8865             :     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
    8866             :     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
    8867             :     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
    8868             : #else
    8869           0 :     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
    8870           0 :     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
    8871           0 :     PyStructSequence_SET_ITEM(v, 2,
    8872             :                               PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
    8873           0 :     PyStructSequence_SET_ITEM(v, 3,
    8874             :                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
    8875           0 :     PyStructSequence_SET_ITEM(v, 4,
    8876             :                               PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
    8877           0 :     PyStructSequence_SET_ITEM(v, 5,
    8878             :                               PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
    8879           0 :     PyStructSequence_SET_ITEM(v, 6,
    8880             :                               PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
    8881           0 :     PyStructSequence_SET_ITEM(v, 7,
    8882             :                               PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
    8883           0 :     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
    8884           0 :     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
    8885             : #endif
    8886             : 
    8887           0 :     return v;
    8888             : }
    8889             : 
    8890             : PyDoc_STRVAR(posix_fstatvfs__doc__,
    8891             : "fstatvfs(fd) -> statvfs result\n\n\
    8892             : Perform an fstatvfs system call on the given fd.\n\
    8893             : Equivalent to statvfs(fd).");
    8894             : 
    8895             : static PyObject *
    8896           0 : posix_fstatvfs(PyObject *self, PyObject *args)
    8897             : {
    8898             :     int fd, res;
    8899             :     struct statvfs st;
    8900             : 
    8901           0 :     if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
    8902           0 :         return NULL;
    8903           0 :     Py_BEGIN_ALLOW_THREADS
    8904           0 :     res = fstatvfs(fd, &st);
    8905           0 :     Py_END_ALLOW_THREADS
    8906           0 :     if (res != 0)
    8907           0 :         return posix_error();
    8908             : 
    8909           0 :     return _pystatvfs_fromstructstatvfs(st);
    8910             : }
    8911             : #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
    8912             : 
    8913             : 
    8914             : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
    8915             : #include <sys/statvfs.h>
    8916             : 
    8917             : PyDoc_STRVAR(posix_statvfs__doc__,
    8918             : "statvfs(path)\n\n\
    8919             : Perform a statvfs system call on the given path.\n\
    8920             : \n\
    8921             : path may always be specified as a string.\n\
    8922             : On some platforms, path may also be specified as an open file descriptor.\n\
    8923             :   If this functionality is unavailable, using it raises an exception.");
    8924             : 
    8925             : static PyObject *
    8926           0 : posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs)
    8927             : {
    8928             :     static char *keywords[] = {"path", NULL};
    8929             :     path_t path;
    8930             :     int result;
    8931           0 :     PyObject *return_value = NULL;
    8932             :     struct statvfs st;
    8933             : 
    8934           0 :     memset(&path, 0, sizeof(path));
    8935             : #ifdef HAVE_FSTATVFS
    8936           0 :     path.allow_fd = 1;
    8937             : #endif
    8938           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords,
    8939             :         path_converter, &path
    8940             :         ))
    8941           0 :         return NULL;
    8942             : 
    8943           0 :     Py_BEGIN_ALLOW_THREADS
    8944             : #ifdef HAVE_FSTATVFS
    8945           0 :     if (path.fd != -1) {
    8946             : #ifdef __APPLE__
    8947             :         /* handle weak-linking on Mac OS X 10.3 */
    8948             :         if (fstatvfs == NULL) {
    8949             :             fd_specified("statvfs", path.fd);
    8950             :             goto exit;
    8951             :         }
    8952             : #endif
    8953           0 :         result = fstatvfs(path.fd, &st);
    8954             :     }
    8955             :     else
    8956             : #endif
    8957           0 :         result = statvfs(path.narrow, &st);
    8958           0 :     Py_END_ALLOW_THREADS
    8959             : 
    8960           0 :     if (result) {
    8961           0 :         return_value = path_posix_error("statvfs", &path);
    8962           0 :         goto exit;
    8963             :     }
    8964             : 
    8965           0 :     return_value = _pystatvfs_fromstructstatvfs(st);
    8966             : 
    8967             : exit:
    8968           0 :     path_cleanup(&path);
    8969           0 :     return return_value;
    8970             : }
    8971             : #endif /* HAVE_STATVFS */
    8972             : 
    8973             : #ifdef MS_WINDOWS
    8974             : PyDoc_STRVAR(win32__getdiskusage__doc__,
    8975             : "_getdiskusage(path) -> (total, free)\n\n\
    8976             : Return disk usage statistics about the given path as (total, free) tuple.");
    8977             : 
    8978             : static PyObject *
    8979             : win32__getdiskusage(PyObject *self, PyObject *args)
    8980             : {
    8981             :     BOOL retval;
    8982             :     ULARGE_INTEGER _, total, free;
    8983             :     const wchar_t *path;
    8984             : 
    8985             :     if (! PyArg_ParseTuple(args, "u", &path))
    8986             :         return NULL;
    8987             : 
    8988             :     Py_BEGIN_ALLOW_THREADS
    8989             :     retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
    8990             :     Py_END_ALLOW_THREADS
    8991             :     if (retval == 0)
    8992             :         return PyErr_SetFromWindowsErr(0);
    8993             : 
    8994             :     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
    8995             : }
    8996             : #endif
    8997             : 
    8998             : 
    8999             : /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
    9000             :  * It maps strings representing configuration variable names to
    9001             :  * integer values, allowing those functions to be called with the
    9002             :  * magic names instead of polluting the module's namespace with tons of
    9003             :  * rarely-used constants.  There are three separate tables that use
    9004             :  * these definitions.
    9005             :  *
    9006             :  * This code is always included, even if none of the interfaces that
    9007             :  * need it are included.  The #if hackery needed to avoid it would be
    9008             :  * sufficiently pervasive that it's not worth the loss of readability.
    9009             :  */
    9010             : struct constdef {
    9011             :     char *name;
    9012             :     long value;
    9013             : };
    9014             : 
    9015             : static int
    9016           0 : conv_confname(PyObject *arg, int *valuep, struct constdef *table,
    9017             :               size_t tablesize)
    9018             : {
    9019           0 :     if (PyLong_Check(arg)) {
    9020           0 :         *valuep = PyLong_AS_LONG(arg);
    9021           0 :         return 1;
    9022             :     }
    9023             :     else {
    9024             :         /* look up the value in the table using a binary search */
    9025           0 :         size_t lo = 0;
    9026             :         size_t mid;
    9027           0 :         size_t hi = tablesize;
    9028             :         int cmp;
    9029             :         const char *confname;
    9030           0 :         if (!PyUnicode_Check(arg)) {
    9031           0 :             PyErr_SetString(PyExc_TypeError,
    9032             :                 "configuration names must be strings or integers");
    9033           0 :             return 0;
    9034             :         }
    9035           0 :         confname = _PyUnicode_AsString(arg);
    9036           0 :         if (confname == NULL)
    9037           0 :             return 0;
    9038           0 :         while (lo < hi) {
    9039           0 :             mid = (lo + hi) / 2;
    9040           0 :             cmp = strcmp(confname, table[mid].name);
    9041           0 :             if (cmp < 0)
    9042           0 :                 hi = mid;
    9043           0 :             else if (cmp > 0)
    9044           0 :                 lo = mid + 1;
    9045             :             else {
    9046           0 :                 *valuep = table[mid].value;
    9047           0 :                 return 1;
    9048             :             }
    9049             :         }
    9050           0 :         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
    9051           0 :         return 0;
    9052             :     }
    9053             : }
    9054             : 
    9055             : 
    9056             : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
    9057             : static struct constdef  posix_constants_pathconf[] = {
    9058             : #ifdef _PC_ABI_AIO_XFER_MAX
    9059             :     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
    9060             : #endif
    9061             : #ifdef _PC_ABI_ASYNC_IO
    9062             :     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
    9063             : #endif
    9064             : #ifdef _PC_ASYNC_IO
    9065             :     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
    9066             : #endif
    9067             : #ifdef _PC_CHOWN_RESTRICTED
    9068             :     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
    9069             : #endif
    9070             : #ifdef _PC_FILESIZEBITS
    9071             :     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
    9072             : #endif
    9073             : #ifdef _PC_LAST
    9074             :     {"PC_LAST", _PC_LAST},
    9075             : #endif
    9076             : #ifdef _PC_LINK_MAX
    9077             :     {"PC_LINK_MAX",     _PC_LINK_MAX},
    9078             : #endif
    9079             : #ifdef _PC_MAX_CANON
    9080             :     {"PC_MAX_CANON",    _PC_MAX_CANON},
    9081             : #endif
    9082             : #ifdef _PC_MAX_INPUT
    9083             :     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
    9084             : #endif
    9085             : #ifdef _PC_NAME_MAX
    9086             :     {"PC_NAME_MAX",     _PC_NAME_MAX},
    9087             : #endif
    9088             : #ifdef _PC_NO_TRUNC
    9089             :     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
    9090             : #endif
    9091             : #ifdef _PC_PATH_MAX
    9092             :     {"PC_PATH_MAX",     _PC_PATH_MAX},
    9093             : #endif
    9094             : #ifdef _PC_PIPE_BUF
    9095             :     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
    9096             : #endif
    9097             : #ifdef _PC_PRIO_IO
    9098             :     {"PC_PRIO_IO",      _PC_PRIO_IO},
    9099             : #endif
    9100             : #ifdef _PC_SOCK_MAXBUF
    9101             :     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
    9102             : #endif
    9103             : #ifdef _PC_SYNC_IO
    9104             :     {"PC_SYNC_IO",      _PC_SYNC_IO},
    9105             : #endif
    9106             : #ifdef _PC_VDISABLE
    9107             :     {"PC_VDISABLE",     _PC_VDISABLE},
    9108             : #endif
    9109             : #ifdef _PC_ACL_ENABLED
    9110             :     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
    9111             : #endif
    9112             : #ifdef _PC_MIN_HOLE_SIZE
    9113             :     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
    9114             : #endif
    9115             : #ifdef _PC_ALLOC_SIZE_MIN
    9116             :     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
    9117             : #endif
    9118             : #ifdef _PC_REC_INCR_XFER_SIZE
    9119             :     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
    9120             : #endif
    9121             : #ifdef _PC_REC_MAX_XFER_SIZE
    9122             :     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
    9123             : #endif
    9124             : #ifdef _PC_REC_MIN_XFER_SIZE
    9125             :     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
    9126             : #endif
    9127             : #ifdef _PC_REC_XFER_ALIGN
    9128             :     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
    9129             : #endif
    9130             : #ifdef _PC_SYMLINK_MAX
    9131             :     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
    9132             : #endif
    9133             : #ifdef _PC_XATTR_ENABLED
    9134             :     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
    9135             : #endif
    9136             : #ifdef _PC_XATTR_EXISTS
    9137             :     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
    9138             : #endif
    9139             : #ifdef _PC_TIMESTAMP_RESOLUTION
    9140             :     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
    9141             : #endif
    9142             : };
    9143             : 
    9144             : static int
    9145           0 : conv_path_confname(PyObject *arg, int *valuep)
    9146             : {
    9147           0 :     return conv_confname(arg, valuep, posix_constants_pathconf,
    9148             :                          sizeof(posix_constants_pathconf)
    9149             :                            / sizeof(struct constdef));
    9150             : }
    9151             : #endif
    9152             : 
    9153             : #ifdef HAVE_FPATHCONF
    9154             : PyDoc_STRVAR(posix_fpathconf__doc__,
    9155             : "fpathconf(fd, name) -> integer\n\n\
    9156             : Return the configuration limit name for the file descriptor fd.\n\
    9157             : If there is no limit, return -1.");
    9158             : 
    9159             : static PyObject *
    9160           0 : posix_fpathconf(PyObject *self, PyObject *args)
    9161             : {
    9162           0 :     PyObject *result = NULL;
    9163             :     int name, fd;
    9164             : 
    9165           0 :     if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
    9166             :                          conv_path_confname, &name)) {
    9167             :         long limit;
    9168             : 
    9169           0 :         errno = 0;
    9170           0 :         limit = fpathconf(fd, name);
    9171           0 :         if (limit == -1 && errno != 0)
    9172           0 :             posix_error();
    9173             :         else
    9174           0 :             result = PyLong_FromLong(limit);
    9175             :     }
    9176           0 :     return result;
    9177             : }
    9178             : #endif
    9179             : 
    9180             : 
    9181             : #ifdef HAVE_PATHCONF
    9182             : PyDoc_STRVAR(posix_pathconf__doc__,
    9183             : "pathconf(path, name) -> integer\n\n\
    9184             : Return the configuration limit name for the file or directory path.\n\
    9185             : If there is no limit, return -1.\n\
    9186             : On some platforms, path may also be specified as an open file descriptor.\n\
    9187             :   If this functionality is unavailable, using it raises an exception.");
    9188             : 
    9189             : static PyObject *
    9190           0 : posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs)
    9191             : {
    9192             :     path_t path;
    9193           0 :     PyObject *result = NULL;
    9194             :     int name;
    9195             :     static char *keywords[] = {"path", "name", NULL};
    9196             : 
    9197           0 :     memset(&path, 0, sizeof(path));
    9198             : #ifdef HAVE_FPATHCONF
    9199           0 :     path.allow_fd = 1;
    9200             : #endif
    9201           0 :     if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords,
    9202             :                                     path_converter, &path,
    9203             :                                     conv_path_confname, &name)) {
    9204             :     long limit;
    9205             : 
    9206           0 :     errno = 0;
    9207             : #ifdef HAVE_FPATHCONF
    9208           0 :     if (path.fd != -1)
    9209           0 :         limit = fpathconf(path.fd, name);
    9210             :     else
    9211             : #endif
    9212           0 :         limit = pathconf(path.narrow, name);
    9213           0 :     if (limit == -1 && errno != 0) {
    9214           0 :         if (errno == EINVAL)
    9215             :             /* could be a path or name problem */
    9216           0 :             posix_error();
    9217             :         else
    9218           0 :             result = path_posix_error("pathconf", &path);
    9219             :     }
    9220             :     else
    9221           0 :         result = PyLong_FromLong(limit);
    9222             :     }
    9223           0 :     path_cleanup(&path);
    9224           0 :     return result;
    9225             : }
    9226             : #endif
    9227             : 
    9228             : #ifdef HAVE_CONFSTR
    9229             : static struct constdef posix_constants_confstr[] = {
    9230             : #ifdef _CS_ARCHITECTURE
    9231             :     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
    9232             : #endif
    9233             : #ifdef _CS_GNU_LIBC_VERSION
    9234             :     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
    9235             : #endif
    9236             : #ifdef _CS_GNU_LIBPTHREAD_VERSION
    9237             :     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
    9238             : #endif
    9239             : #ifdef _CS_HOSTNAME
    9240             :     {"CS_HOSTNAME",     _CS_HOSTNAME},
    9241             : #endif
    9242             : #ifdef _CS_HW_PROVIDER
    9243             :     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
    9244             : #endif
    9245             : #ifdef _CS_HW_SERIAL
    9246             :     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
    9247             : #endif
    9248             : #ifdef _CS_INITTAB_NAME
    9249             :     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
    9250             : #endif
    9251             : #ifdef _CS_LFS64_CFLAGS
    9252             :     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
    9253             : #endif
    9254             : #ifdef _CS_LFS64_LDFLAGS
    9255             :     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
    9256             : #endif
    9257             : #ifdef _CS_LFS64_LIBS
    9258             :     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
    9259             : #endif
    9260             : #ifdef _CS_LFS64_LINTFLAGS
    9261             :     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
    9262             : #endif
    9263             : #ifdef _CS_LFS_CFLAGS
    9264             :     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
    9265             : #endif
    9266             : #ifdef _CS_LFS_LDFLAGS
    9267             :     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
    9268             : #endif
    9269             : #ifdef _CS_LFS_LIBS
    9270             :     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
    9271             : #endif
    9272             : #ifdef _CS_LFS_LINTFLAGS
    9273             :     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
    9274             : #endif
    9275             : #ifdef _CS_MACHINE
    9276             :     {"CS_MACHINE",      _CS_MACHINE},
    9277             : #endif
    9278             : #ifdef _CS_PATH
    9279             :     {"CS_PATH", _CS_PATH},
    9280             : #endif
    9281             : #ifdef _CS_RELEASE
    9282             :     {"CS_RELEASE",      _CS_RELEASE},
    9283             : #endif
    9284             : #ifdef _CS_SRPC_DOMAIN
    9285             :     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
    9286             : #endif
    9287             : #ifdef _CS_SYSNAME
    9288             :     {"CS_SYSNAME",      _CS_SYSNAME},
    9289             : #endif
    9290             : #ifdef _CS_VERSION
    9291             :     {"CS_VERSION",      _CS_VERSION},
    9292             : #endif
    9293             : #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
    9294             :     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
    9295             : #endif
    9296             : #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
    9297             :     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
    9298             : #endif
    9299             : #ifdef _CS_XBS5_ILP32_OFF32_LIBS
    9300             :     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
    9301             : #endif
    9302             : #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
    9303             :     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
    9304             : #endif
    9305             : #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
    9306             :     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
    9307             : #endif
    9308             : #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
    9309             :     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
    9310             : #endif
    9311             : #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
    9312             :     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
    9313             : #endif
    9314             : #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
    9315             :     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
    9316             : #endif
    9317             : #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
    9318             :     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
    9319             : #endif
    9320             : #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
    9321             :     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
    9322             : #endif
    9323             : #ifdef _CS_XBS5_LP64_OFF64_LIBS
    9324             :     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
    9325             : #endif
    9326             : #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
    9327             :     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
    9328             : #endif
    9329             : #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
    9330             :     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
    9331             : #endif
    9332             : #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
    9333             :     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
    9334             : #endif
    9335             : #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
    9336             :     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
    9337             : #endif
    9338             : #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
    9339             :     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
    9340             : #endif
    9341             : #ifdef _MIPS_CS_AVAIL_PROCESSORS
    9342             :     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
    9343             : #endif
    9344             : #ifdef _MIPS_CS_BASE
    9345             :     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
    9346             : #endif
    9347             : #ifdef _MIPS_CS_HOSTID
    9348             :     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
    9349             : #endif
    9350             : #ifdef _MIPS_CS_HW_NAME
    9351             :     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
    9352             : #endif
    9353             : #ifdef _MIPS_CS_NUM_PROCESSORS
    9354             :     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
    9355             : #endif
    9356             : #ifdef _MIPS_CS_OSREL_MAJ
    9357             :     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
    9358             : #endif
    9359             : #ifdef _MIPS_CS_OSREL_MIN
    9360             :     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
    9361             : #endif
    9362             : #ifdef _MIPS_CS_OSREL_PATCH
    9363             :     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
    9364             : #endif
    9365             : #ifdef _MIPS_CS_OS_NAME
    9366             :     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
    9367             : #endif
    9368             : #ifdef _MIPS_CS_OS_PROVIDER
    9369             :     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
    9370             : #endif
    9371             : #ifdef _MIPS_CS_PROCESSORS
    9372             :     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
    9373             : #endif
    9374             : #ifdef _MIPS_CS_SERIAL
    9375             :     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
    9376             : #endif
    9377             : #ifdef _MIPS_CS_VENDOR
    9378             :     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
    9379             : #endif
    9380             : };
    9381             : 
    9382             : static int
    9383           0 : conv_confstr_confname(PyObject *arg, int *valuep)
    9384             : {
    9385           0 :     return conv_confname(arg, valuep, posix_constants_confstr,
    9386             :                          sizeof(posix_constants_confstr)
    9387             :                            / sizeof(struct constdef));
    9388             : }
    9389             : 
    9390             : PyDoc_STRVAR(posix_confstr__doc__,
    9391             : "confstr(name) -> string\n\n\
    9392             : Return a string-valued system configuration variable.");
    9393             : 
    9394             : static PyObject *
    9395           0 : posix_confstr(PyObject *self, PyObject *args)
    9396             : {
    9397           0 :     PyObject *result = NULL;
    9398             :     int name;
    9399             :     char buffer[255];
    9400             :     int len;
    9401             : 
    9402           0 :     if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
    9403           0 :         return NULL;
    9404             : 
    9405           0 :     errno = 0;
    9406           0 :     len = confstr(name, buffer, sizeof(buffer));
    9407           0 :     if (len == 0) {
    9408           0 :         if (errno) {
    9409           0 :             posix_error();
    9410           0 :             return NULL;
    9411             :         }
    9412             :         else {
    9413           0 :             Py_RETURN_NONE;
    9414             :         }
    9415             :     }
    9416             : 
    9417           0 :     if ((unsigned int)len >= sizeof(buffer)) {
    9418           0 :         char *buf = PyMem_Malloc(len);
    9419           0 :         if (buf == NULL)
    9420           0 :             return PyErr_NoMemory();
    9421           0 :         confstr(name, buf, len);
    9422           0 :         result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
    9423           0 :         PyMem_Free(buf);
    9424             :     }
    9425             :     else
    9426           0 :         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
    9427           0 :     return result;
    9428             : }
    9429             : #endif
    9430             : 
    9431             : 
    9432             : #ifdef HAVE_SYSCONF
    9433             : static struct constdef posix_constants_sysconf[] = {
    9434             : #ifdef _SC_2_CHAR_TERM
    9435             :     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
    9436             : #endif
    9437             : #ifdef _SC_2_C_BIND
    9438             :     {"SC_2_C_BIND",     _SC_2_C_BIND},
    9439             : #endif
    9440             : #ifdef _SC_2_C_DEV
    9441             :     {"SC_2_C_DEV",      _SC_2_C_DEV},
    9442             : #endif
    9443             : #ifdef _SC_2_C_VERSION
    9444             :     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
    9445             : #endif
    9446             : #ifdef _SC_2_FORT_DEV
    9447             :     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
    9448             : #endif
    9449             : #ifdef _SC_2_FORT_RUN
    9450             :     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
    9451             : #endif
    9452             : #ifdef _SC_2_LOCALEDEF
    9453             :     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
    9454             : #endif
    9455             : #ifdef _SC_2_SW_DEV
    9456             :     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
    9457             : #endif
    9458             : #ifdef _SC_2_UPE
    9459             :     {"SC_2_UPE",        _SC_2_UPE},
    9460             : #endif
    9461             : #ifdef _SC_2_VERSION
    9462             :     {"SC_2_VERSION",    _SC_2_VERSION},
    9463             : #endif
    9464             : #ifdef _SC_ABI_ASYNCHRONOUS_IO
    9465             :     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
    9466             : #endif
    9467             : #ifdef _SC_ACL
    9468             :     {"SC_ACL",  _SC_ACL},
    9469             : #endif
    9470             : #ifdef _SC_AIO_LISTIO_MAX
    9471             :     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
    9472             : #endif
    9473             : #ifdef _SC_AIO_MAX
    9474             :     {"SC_AIO_MAX",      _SC_AIO_MAX},
    9475             : #endif
    9476             : #ifdef _SC_AIO_PRIO_DELTA_MAX
    9477             :     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
    9478             : #endif
    9479             : #ifdef _SC_ARG_MAX
    9480             :     {"SC_ARG_MAX",      _SC_ARG_MAX},
    9481             : #endif
    9482             : #ifdef _SC_ASYNCHRONOUS_IO
    9483             :     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
    9484             : #endif
    9485             : #ifdef _SC_ATEXIT_MAX
    9486             :     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
    9487             : #endif
    9488             : #ifdef _SC_AUDIT
    9489             :     {"SC_AUDIT",        _SC_AUDIT},
    9490             : #endif
    9491             : #ifdef _SC_AVPHYS_PAGES
    9492             :     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
    9493             : #endif
    9494             : #ifdef _SC_BC_BASE_MAX
    9495             :     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
    9496             : #endif
    9497             : #ifdef _SC_BC_DIM_MAX
    9498             :     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
    9499             : #endif
    9500             : #ifdef _SC_BC_SCALE_MAX
    9501             :     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
    9502             : #endif
    9503             : #ifdef _SC_BC_STRING_MAX
    9504             :     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
    9505             : #endif
    9506             : #ifdef _SC_CAP
    9507             :     {"SC_CAP",  _SC_CAP},
    9508             : #endif
    9509             : #ifdef _SC_CHARCLASS_NAME_MAX
    9510             :     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
    9511             : #endif
    9512             : #ifdef _SC_CHAR_BIT
    9513             :     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
    9514             : #endif
    9515             : #ifdef _SC_CHAR_MAX
    9516             :     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
    9517             : #endif
    9518             : #ifdef _SC_CHAR_MIN
    9519             :     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
    9520             : #endif
    9521             : #ifdef _SC_CHILD_MAX
    9522             :     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
    9523             : #endif
    9524             : #ifdef _SC_CLK_TCK
    9525             :     {"SC_CLK_TCK",      _SC_CLK_TCK},
    9526             : #endif
    9527             : #ifdef _SC_COHER_BLKSZ
    9528             :     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
    9529             : #endif
    9530             : #ifdef _SC_COLL_WEIGHTS_MAX
    9531             :     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
    9532             : #endif
    9533             : #ifdef _SC_DCACHE_ASSOC
    9534             :     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
    9535             : #endif
    9536             : #ifdef _SC_DCACHE_BLKSZ
    9537             :     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
    9538             : #endif
    9539             : #ifdef _SC_DCACHE_LINESZ
    9540             :     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
    9541             : #endif
    9542             : #ifdef _SC_DCACHE_SZ
    9543             :     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
    9544             : #endif
    9545             : #ifdef _SC_DCACHE_TBLKSZ
    9546             :     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
    9547             : #endif
    9548             : #ifdef _SC_DELAYTIMER_MAX
    9549             :     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
    9550             : #endif
    9551             : #ifdef _SC_EQUIV_CLASS_MAX
    9552             :     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
    9553             : #endif
    9554             : #ifdef _SC_EXPR_NEST_MAX
    9555             :     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
    9556             : #endif
    9557             : #ifdef _SC_FSYNC
    9558             :     {"SC_FSYNC",        _SC_FSYNC},
    9559             : #endif
    9560             : #ifdef _SC_GETGR_R_SIZE_MAX
    9561             :     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
    9562             : #endif
    9563             : #ifdef _SC_GETPW_R_SIZE_MAX
    9564             :     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
    9565             : #endif
    9566             : #ifdef _SC_ICACHE_ASSOC
    9567             :     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
    9568             : #endif
    9569             : #ifdef _SC_ICACHE_BLKSZ
    9570             :     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
    9571             : #endif
    9572             : #ifdef _SC_ICACHE_LINESZ
    9573             :     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
    9574             : #endif
    9575             : #ifdef _SC_ICACHE_SZ
    9576             :     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
    9577             : #endif
    9578             : #ifdef _SC_INF
    9579             :     {"SC_INF",  _SC_INF},
    9580             : #endif
    9581             : #ifdef _SC_INT_MAX
    9582             :     {"SC_INT_MAX",      _SC_INT_MAX},
    9583             : #endif
    9584             : #ifdef _SC_INT_MIN
    9585             :     {"SC_INT_MIN",      _SC_INT_MIN},
    9586             : #endif
    9587             : #ifdef _SC_IOV_MAX
    9588             :     {"SC_IOV_MAX",      _SC_IOV_MAX},
    9589             : #endif
    9590             : #ifdef _SC_IP_SECOPTS
    9591             :     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
    9592             : #endif
    9593             : #ifdef _SC_JOB_CONTROL
    9594             :     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
    9595             : #endif
    9596             : #ifdef _SC_KERN_POINTERS
    9597             :     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
    9598             : #endif
    9599             : #ifdef _SC_KERN_SIM
    9600             :     {"SC_KERN_SIM",     _SC_KERN_SIM},
    9601             : #endif
    9602             : #ifdef _SC_LINE_MAX
    9603             :     {"SC_LINE_MAX",     _SC_LINE_MAX},
    9604             : #endif
    9605             : #ifdef _SC_LOGIN_NAME_MAX
    9606             :     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
    9607             : #endif
    9608             : #ifdef _SC_LOGNAME_MAX
    9609             :     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
    9610             : #endif
    9611             : #ifdef _SC_LONG_BIT
    9612             :     {"SC_LONG_BIT",     _SC_LONG_BIT},
    9613             : #endif
    9614             : #ifdef _SC_MAC
    9615             :     {"SC_MAC",  _SC_MAC},
    9616             : #endif
    9617             : #ifdef _SC_MAPPED_FILES
    9618             :     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
    9619             : #endif
    9620             : #ifdef _SC_MAXPID
    9621             :     {"SC_MAXPID",       _SC_MAXPID},
    9622             : #endif
    9623             : #ifdef _SC_MB_LEN_MAX
    9624             :     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
    9625             : #endif
    9626             : #ifdef _SC_MEMLOCK
    9627             :     {"SC_MEMLOCK",      _SC_MEMLOCK},
    9628             : #endif
    9629             : #ifdef _SC_MEMLOCK_RANGE
    9630             :     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
    9631             : #endif
    9632             : #ifdef _SC_MEMORY_PROTECTION
    9633             :     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
    9634             : #endif
    9635             : #ifdef _SC_MESSAGE_PASSING
    9636             :     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
    9637             : #endif
    9638             : #ifdef _SC_MMAP_FIXED_ALIGNMENT
    9639             :     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
    9640             : #endif
    9641             : #ifdef _SC_MQ_OPEN_MAX
    9642             :     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
    9643             : #endif
    9644             : #ifdef _SC_MQ_PRIO_MAX
    9645             :     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
    9646             : #endif
    9647             : #ifdef _SC_NACLS_MAX
    9648             :     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
    9649             : #endif
    9650             : #ifdef _SC_NGROUPS_MAX
    9651             :     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
    9652             : #endif
    9653             : #ifdef _SC_NL_ARGMAX
    9654             :     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
    9655             : #endif
    9656             : #ifdef _SC_NL_LANGMAX
    9657             :     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
    9658             : #endif
    9659             : #ifdef _SC_NL_MSGMAX
    9660             :     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
    9661             : #endif
    9662             : #ifdef _SC_NL_NMAX
    9663             :     {"SC_NL_NMAX",      _SC_NL_NMAX},
    9664             : #endif
    9665             : #ifdef _SC_NL_SETMAX
    9666             :     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
    9667             : #endif
    9668             : #ifdef _SC_NL_TEXTMAX
    9669             :     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
    9670             : #endif
    9671             : #ifdef _SC_NPROCESSORS_CONF
    9672             :     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
    9673             : #endif
    9674             : #ifdef _SC_NPROCESSORS_ONLN
    9675             :     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
    9676             : #endif
    9677             : #ifdef _SC_NPROC_CONF
    9678             :     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
    9679             : #endif
    9680             : #ifdef _SC_NPROC_ONLN
    9681             :     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
    9682             : #endif
    9683             : #ifdef _SC_NZERO
    9684             :     {"SC_NZERO",        _SC_NZERO},
    9685             : #endif
    9686             : #ifdef _SC_OPEN_MAX
    9687             :     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
    9688             : #endif
    9689             : #ifdef _SC_PAGESIZE
    9690             :     {"SC_PAGESIZE",     _SC_PAGESIZE},
    9691             : #endif
    9692             : #ifdef _SC_PAGE_SIZE
    9693             :     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
    9694             : #endif
    9695             : #ifdef _SC_PASS_MAX
    9696             :     {"SC_PASS_MAX",     _SC_PASS_MAX},
    9697             : #endif
    9698             : #ifdef _SC_PHYS_PAGES
    9699             :     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
    9700             : #endif
    9701             : #ifdef _SC_PII
    9702             :     {"SC_PII",  _SC_PII},
    9703             : #endif
    9704             : #ifdef _SC_PII_INTERNET
    9705             :     {"SC_PII_INTERNET", _SC_PII_INTERNET},
    9706             : #endif
    9707             : #ifdef _SC_PII_INTERNET_DGRAM
    9708             :     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
    9709             : #endif
    9710             : #ifdef _SC_PII_INTERNET_STREAM
    9711             :     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
    9712             : #endif
    9713             : #ifdef _SC_PII_OSI
    9714             :     {"SC_PII_OSI",      _SC_PII_OSI},
    9715             : #endif
    9716             : #ifdef _SC_PII_OSI_CLTS
    9717             :     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
    9718             : #endif
    9719             : #ifdef _SC_PII_OSI_COTS
    9720             :     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
    9721             : #endif
    9722             : #ifdef _SC_PII_OSI_M
    9723             :     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
    9724             : #endif
    9725             : #ifdef _SC_PII_SOCKET
    9726             :     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
    9727             : #endif
    9728             : #ifdef _SC_PII_XTI
    9729             :     {"SC_PII_XTI",      _SC_PII_XTI},
    9730             : #endif
    9731             : #ifdef _SC_POLL
    9732             :     {"SC_POLL", _SC_POLL},
    9733             : #endif
    9734             : #ifdef _SC_PRIORITIZED_IO
    9735             :     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
    9736             : #endif
    9737             : #ifdef _SC_PRIORITY_SCHEDULING
    9738             :     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
    9739             : #endif
    9740             : #ifdef _SC_REALTIME_SIGNALS
    9741             :     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
    9742             : #endif
    9743             : #ifdef _SC_RE_DUP_MAX
    9744             :     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
    9745             : #endif
    9746             : #ifdef _SC_RTSIG_MAX
    9747             :     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
    9748             : #endif
    9749             : #ifdef _SC_SAVED_IDS
    9750             :     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
    9751             : #endif
    9752             : #ifdef _SC_SCHAR_MAX
    9753             :     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
    9754             : #endif
    9755             : #ifdef _SC_SCHAR_MIN
    9756             :     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
    9757             : #endif
    9758             : #ifdef _SC_SELECT
    9759             :     {"SC_SELECT",       _SC_SELECT},
    9760             : #endif
    9761             : #ifdef _SC_SEMAPHORES
    9762             :     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
    9763             : #endif
    9764             : #ifdef _SC_SEM_NSEMS_MAX
    9765             :     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
    9766             : #endif
    9767             : #ifdef _SC_SEM_VALUE_MAX
    9768             :     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
    9769             : #endif
    9770             : #ifdef _SC_SHARED_MEMORY_OBJECTS
    9771             :     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
    9772             : #endif
    9773             : #ifdef _SC_SHRT_MAX
    9774             :     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
    9775             : #endif
    9776             : #ifdef _SC_SHRT_MIN
    9777             :     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
    9778             : #endif
    9779             : #ifdef _SC_SIGQUEUE_MAX
    9780             :     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
    9781             : #endif
    9782             : #ifdef _SC_SIGRT_MAX
    9783             :     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
    9784             : #endif
    9785             : #ifdef _SC_SIGRT_MIN
    9786             :     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
    9787             : #endif
    9788             : #ifdef _SC_SOFTPOWER
    9789             :     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
    9790             : #endif
    9791             : #ifdef _SC_SPLIT_CACHE
    9792             :     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
    9793             : #endif
    9794             : #ifdef _SC_SSIZE_MAX
    9795             :     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
    9796             : #endif
    9797             : #ifdef _SC_STACK_PROT
    9798             :     {"SC_STACK_PROT",   _SC_STACK_PROT},
    9799             : #endif
    9800             : #ifdef _SC_STREAM_MAX
    9801             :     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
    9802             : #endif
    9803             : #ifdef _SC_SYNCHRONIZED_IO
    9804             :     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
    9805             : #endif
    9806             : #ifdef _SC_THREADS
    9807             :     {"SC_THREADS",      _SC_THREADS},
    9808             : #endif
    9809             : #ifdef _SC_THREAD_ATTR_STACKADDR
    9810             :     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
    9811             : #endif
    9812             : #ifdef _SC_THREAD_ATTR_STACKSIZE
    9813             :     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
    9814             : #endif
    9815             : #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
    9816             :     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
    9817             : #endif
    9818             : #ifdef _SC_THREAD_KEYS_MAX
    9819             :     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
    9820             : #endif
    9821             : #ifdef _SC_THREAD_PRIORITY_SCHEDULING
    9822             :     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
    9823             : #endif
    9824             : #ifdef _SC_THREAD_PRIO_INHERIT
    9825             :     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
    9826             : #endif
    9827             : #ifdef _SC_THREAD_PRIO_PROTECT
    9828             :     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
    9829             : #endif
    9830             : #ifdef _SC_THREAD_PROCESS_SHARED
    9831             :     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
    9832             : #endif
    9833             : #ifdef _SC_THREAD_SAFE_FUNCTIONS
    9834             :     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
    9835             : #endif
    9836             : #ifdef _SC_THREAD_STACK_MIN
    9837             :     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
    9838             : #endif
    9839             : #ifdef _SC_THREAD_THREADS_MAX
    9840             :     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
    9841             : #endif
    9842             : #ifdef _SC_TIMERS
    9843             :     {"SC_TIMERS",       _SC_TIMERS},
    9844             : #endif
    9845             : #ifdef _SC_TIMER_MAX
    9846             :     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
    9847             : #endif
    9848             : #ifdef _SC_TTY_NAME_MAX
    9849             :     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
    9850             : #endif
    9851             : #ifdef _SC_TZNAME_MAX
    9852             :     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
    9853             : #endif
    9854             : #ifdef _SC_T_IOV_MAX
    9855             :     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
    9856             : #endif
    9857             : #ifdef _SC_UCHAR_MAX
    9858             :     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
    9859             : #endif
    9860             : #ifdef _SC_UINT_MAX
    9861             :     {"SC_UINT_MAX",     _SC_UINT_MAX},
    9862             : #endif
    9863             : #ifdef _SC_UIO_MAXIOV
    9864             :     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
    9865             : #endif
    9866             : #ifdef _SC_ULONG_MAX
    9867             :     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
    9868             : #endif
    9869             : #ifdef _SC_USHRT_MAX
    9870             :     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
    9871             : #endif
    9872             : #ifdef _SC_VERSION
    9873             :     {"SC_VERSION",      _SC_VERSION},
    9874             : #endif
    9875             : #ifdef _SC_WORD_BIT
    9876             :     {"SC_WORD_BIT",     _SC_WORD_BIT},
    9877             : #endif
    9878             : #ifdef _SC_XBS5_ILP32_OFF32
    9879             :     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
    9880             : #endif
    9881             : #ifdef _SC_XBS5_ILP32_OFFBIG
    9882             :     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
    9883             : #endif
    9884             : #ifdef _SC_XBS5_LP64_OFF64
    9885             :     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
    9886             : #endif
    9887             : #ifdef _SC_XBS5_LPBIG_OFFBIG
    9888             :     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
    9889             : #endif
    9890             : #ifdef _SC_XOPEN_CRYPT
    9891             :     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
    9892             : #endif
    9893             : #ifdef _SC_XOPEN_ENH_I18N
    9894             :     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
    9895             : #endif
    9896             : #ifdef _SC_XOPEN_LEGACY
    9897             :     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
    9898             : #endif
    9899             : #ifdef _SC_XOPEN_REALTIME
    9900             :     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
    9901             : #endif
    9902             : #ifdef _SC_XOPEN_REALTIME_THREADS
    9903             :     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
    9904             : #endif
    9905             : #ifdef _SC_XOPEN_SHM
    9906             :     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
    9907             : #endif
    9908             : #ifdef _SC_XOPEN_UNIX
    9909             :     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
    9910             : #endif
    9911             : #ifdef _SC_XOPEN_VERSION
    9912             :     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
    9913             : #endif
    9914             : #ifdef _SC_XOPEN_XCU_VERSION
    9915             :     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
    9916             : #endif
    9917             : #ifdef _SC_XOPEN_XPG2
    9918             :     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
    9919             : #endif
    9920             : #ifdef _SC_XOPEN_XPG3
    9921             :     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
    9922             : #endif
    9923             : #ifdef _SC_XOPEN_XPG4
    9924             :     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
    9925             : #endif
    9926             : };
    9927             : 
    9928             : static int
    9929           0 : conv_sysconf_confname(PyObject *arg, int *valuep)
    9930             : {
    9931           0 :     return conv_confname(arg, valuep, posix_constants_sysconf,
    9932             :                          sizeof(posix_constants_sysconf)
    9933             :                            / sizeof(struct constdef));
    9934             : }
    9935             : 
    9936             : PyDoc_STRVAR(posix_sysconf__doc__,
    9937             : "sysconf(name) -> integer\n\n\
    9938             : Return an integer-valued system configuration variable.");
    9939             : 
    9940             : static PyObject *
    9941           0 : posix_sysconf(PyObject *self, PyObject *args)
    9942             : {
    9943           0 :     PyObject *result = NULL;
    9944             :     int name;
    9945             : 
    9946           0 :     if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
    9947             :         int value;
    9948             : 
    9949           0 :         errno = 0;
    9950           0 :         value = sysconf(name);
    9951           0 :         if (value == -1 && errno != 0)
    9952           0 :             posix_error();
    9953             :         else
    9954           0 :             result = PyLong_FromLong(value);
    9955             :     }
    9956           0 :     return result;
    9957             : }
    9958             : #endif
    9959             : 
    9960             : 
    9961             : /* This code is used to ensure that the tables of configuration value names
    9962             :  * are in sorted order as required by conv_confname(), and also to build the
    9963             :  * the exported dictionaries that are used to publish information about the
    9964             :  * names available on the host platform.
    9965             :  *
    9966             :  * Sorting the table at runtime ensures that the table is properly ordered
    9967             :  * when used, even for platforms we're not able to test on.  It also makes
    9968             :  * it easier to add additional entries to the tables.
    9969             :  */
    9970             : 
    9971             : static int
    9972         567 : cmp_constdefs(const void *v1,  const void *v2)
    9973             : {
    9974         567 :     const struct constdef *c1 =
    9975             :     (const struct constdef *) v1;
    9976         567 :     const struct constdef *c2 =
    9977             :     (const struct constdef *) v2;
    9978             : 
    9979         567 :     return strcmp(c1->name, c2->name);
    9980             : }
    9981             : 
    9982             : static int
    9983           3 : setup_confname_table(struct constdef *table, size_t tablesize,
    9984             :                      char *tablename, PyObject *module)
    9985             : {
    9986           3 :     PyObject *d = NULL;
    9987             :     size_t i;
    9988             : 
    9989           3 :     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
    9990           3 :     d = PyDict_New();
    9991           3 :     if (d == NULL)
    9992           0 :         return -1;
    9993             : 
    9994         184 :     for (i=0; i < tablesize; ++i) {
    9995         181 :         PyObject *o = PyLong_FromLong(table[i].value);
    9996         181 :         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
    9997           0 :             Py_XDECREF(o);
    9998           0 :             Py_DECREF(d);
    9999           0 :             return -1;
   10000             :         }
   10001         181 :         Py_DECREF(o);
   10002             :     }
   10003           3 :     return PyModule_AddObject(module, tablename, d);
   10004             : }
   10005             : 
   10006             : /* Return -1 on failure, 0 on success. */
   10007             : static int
   10008           1 : setup_confname_tables(PyObject *module)
   10009             : {
   10010             : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
   10011           1 :     if (setup_confname_table(posix_constants_pathconf,
   10012             :                              sizeof(posix_constants_pathconf)
   10013             :                                / sizeof(struct constdef),
   10014             :                              "pathconf_names", module))
   10015           0 :         return -1;
   10016             : #endif
   10017             : #ifdef HAVE_CONFSTR
   10018           1 :     if (setup_confname_table(posix_constants_confstr,
   10019             :                              sizeof(posix_constants_confstr)
   10020             :                                / sizeof(struct constdef),
   10021             :                              "confstr_names", module))
   10022           0 :         return -1;
   10023             : #endif
   10024             : #ifdef HAVE_SYSCONF
   10025           1 :     if (setup_confname_table(posix_constants_sysconf,
   10026             :                              sizeof(posix_constants_sysconf)
   10027             :                                / sizeof(struct constdef),
   10028             :                              "sysconf_names", module))
   10029           0 :         return -1;
   10030             : #endif
   10031           1 :     return 0;
   10032             : }
   10033             : 
   10034             : 
   10035             : PyDoc_STRVAR(posix_abort__doc__,
   10036             : "abort() -> does not return!\n\n\
   10037             : Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
   10038             : in the hardest way possible on the hosting operating system.");
   10039             : 
   10040             : static PyObject *
   10041           0 : posix_abort(PyObject *self, PyObject *noargs)
   10042             : {
   10043           0 :     abort();
   10044             :     /*NOTREACHED*/
   10045             :     Py_FatalError("abort() called from Python code didn't abort!");
   10046             :     return NULL;
   10047             : }
   10048             : 
   10049             : #ifdef MS_WINDOWS
   10050             : PyDoc_STRVAR(win32_startfile__doc__,
   10051             : "startfile(filepath [, operation]) - Start a file with its associated\n\
   10052             : application.\n\
   10053             : \n\
   10054             : When \"operation\" is not specified or \"open\", this acts like\n\
   10055             : double-clicking the file in Explorer, or giving the file name as an\n\
   10056             : argument to the DOS \"start\" command: the file is opened with whatever\n\
   10057             : application (if any) its extension is associated.\n\
   10058             : When another \"operation\" is given, it specifies what should be done with\n\
   10059             : the file.  A typical operation is \"print\".\n\
   10060             : \n\
   10061             : startfile returns as soon as the associated application is launched.\n\
   10062             : There is no option to wait for the application to close, and no way\n\
   10063             : to retrieve the application's exit status.\n\
   10064             : \n\
   10065             : The filepath is relative to the current directory.  If you want to use\n\
   10066             : an absolute path, make sure the first character is not a slash (\"/\");\n\
   10067             : the underlying Win32 ShellExecute function doesn't work if it is.");
   10068             : 
   10069             : static PyObject *
   10070             : win32_startfile(PyObject *self, PyObject *args)
   10071             : {
   10072             :     PyObject *ofilepath;
   10073             :     char *filepath;
   10074             :     char *operation = NULL;
   10075             :     wchar_t *wpath, *woperation;
   10076             :     HINSTANCE rc;
   10077             : 
   10078             :     PyObject *unipath, *uoperation = NULL;
   10079             :     if (!PyArg_ParseTuple(args, "U|s:startfile",
   10080             :                           &unipath, &operation)) {
   10081             :         PyErr_Clear();
   10082             :         goto normal;
   10083             :     }
   10084             : 
   10085             :     if (operation) {
   10086             :         uoperation = PyUnicode_DecodeASCII(operation,
   10087             :                                            strlen(operation), NULL);
   10088             :         if (!uoperation) {
   10089             :             PyErr_Clear();
   10090             :             operation = NULL;
   10091             :             goto normal;
   10092             :         }
   10093             :     }
   10094             : 
   10095             :     wpath = PyUnicode_AsUnicode(unipath);
   10096             :     if (wpath == NULL)
   10097             :         goto normal;
   10098             :     if (uoperation) {
   10099             :         woperation = PyUnicode_AsUnicode(uoperation);
   10100             :         if (woperation == NULL)
   10101             :             goto normal;
   10102             :     }
   10103             :     else
   10104             :         woperation = NULL;
   10105             : 
   10106             :     Py_BEGIN_ALLOW_THREADS
   10107             :     rc = ShellExecuteW((HWND)0, woperation, wpath,
   10108             :                        NULL, NULL, SW_SHOWNORMAL);
   10109             :     Py_END_ALLOW_THREADS
   10110             : 
   10111             :     Py_XDECREF(uoperation);
   10112             :     if (rc <= (HINSTANCE)32) {
   10113             :         win32_error_object("startfile", unipath);
   10114             :         return NULL;
   10115             :     }
   10116             :     Py_INCREF(Py_None);
   10117             :     return Py_None;
   10118             : 
   10119             : normal:
   10120             :     if (!PyArg_ParseTuple(args, "O&|s:startfile",
   10121             :                           PyUnicode_FSConverter, &ofilepath,
   10122             :                           &operation))
   10123             :         return NULL;
   10124             :     if (win32_warn_bytes_api()) {
   10125             :         Py_DECREF(ofilepath);
   10126             :         return NULL;
   10127             :     }
   10128             :     filepath = PyBytes_AsString(ofilepath);
   10129             :     Py_BEGIN_ALLOW_THREADS
   10130             :     rc = ShellExecute((HWND)0, operation, filepath,
   10131             :                       NULL, NULL, SW_SHOWNORMAL);
   10132             :     Py_END_ALLOW_THREADS
   10133             :     if (rc <= (HINSTANCE)32) {
   10134             :         PyObject *errval = win32_error("startfile", filepath);
   10135             :         Py_DECREF(ofilepath);
   10136             :         return errval;
   10137             :     }
   10138             :     Py_DECREF(ofilepath);
   10139             :     Py_INCREF(Py_None);
   10140             :     return Py_None;
   10141             : }
   10142             : #endif
   10143             : 
   10144             : #ifdef HAVE_GETLOADAVG
   10145             : PyDoc_STRVAR(posix_getloadavg__doc__,
   10146             : "getloadavg() -> (float, float, float)\n\n\
   10147             : Return the number of processes in the system run queue averaged over\n\
   10148             : the last 1, 5, and 15 minutes or raises OSError if the load average\n\
   10149             : was unobtainable");
   10150             : 
   10151             : static PyObject *
   10152           0 : posix_getloadavg(PyObject *self, PyObject *noargs)
   10153             : {
   10154             :     double loadavg[3];
   10155           0 :     if (getloadavg(loadavg, 3)!=3) {
   10156           0 :         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
   10157           0 :         return NULL;
   10158             :     } else
   10159           0 :         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
   10160             : }
   10161             : #endif
   10162             : 
   10163             : PyDoc_STRVAR(device_encoding__doc__,
   10164             : "device_encoding(fd) -> str\n\n\
   10165             : Return a string describing the encoding of the device\n\
   10166             : if the output is a terminal; else return None.");
   10167             : 
   10168             : static PyObject *
   10169           0 : device_encoding(PyObject *self, PyObject *args)
   10170             : {
   10171             :     int fd;
   10172             : 
   10173           0 :     if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
   10174           0 :         return NULL;
   10175             : 
   10176           0 :     return _Py_device_encoding(fd);
   10177             : }
   10178             : 
   10179             : #ifdef HAVE_SETRESUID
   10180             : PyDoc_STRVAR(posix_setresuid__doc__,
   10181             : "setresuid(ruid, euid, suid)\n\n\
   10182             : Set the current process's real, effective, and saved user ids.");
   10183             : 
   10184             : static PyObject*
   10185           0 : posix_setresuid (PyObject *self, PyObject *args)
   10186             : {
   10187             :     /* We assume uid_t is no larger than a long. */
   10188             :     long ruid, euid, suid;
   10189           0 :     if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
   10190           0 :         return NULL;
   10191           0 :     if (setresuid(ruid, euid, suid) < 0)
   10192           0 :         return posix_error();
   10193           0 :     Py_RETURN_NONE;
   10194             : }
   10195             : #endif
   10196             : 
   10197             : #ifdef HAVE_SETRESGID
   10198             : PyDoc_STRVAR(posix_setresgid__doc__,
   10199             : "setresgid(rgid, egid, sgid)\n\n\
   10200             : Set the current process's real, effective, and saved group ids.");
   10201             : 
   10202             : static PyObject*
   10203           0 : posix_setresgid (PyObject *self, PyObject *args)
   10204             : {
   10205             :     /* We assume uid_t is no larger than a long. */
   10206             :     long rgid, egid, sgid;
   10207           0 :     if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
   10208           0 :         return NULL;
   10209           0 :     if (setresgid(rgid, egid, sgid) < 0)
   10210           0 :         return posix_error();
   10211           0 :     Py_RETURN_NONE;
   10212             : }
   10213             : #endif
   10214             : 
   10215             : #ifdef HAVE_GETRESUID
   10216             : PyDoc_STRVAR(posix_getresuid__doc__,
   10217             : "getresuid() -> (ruid, euid, suid)\n\n\
   10218             : Get tuple of the current process's real, effective, and saved user ids.");
   10219             : 
   10220             : static PyObject*
   10221           0 : posix_getresuid (PyObject *self, PyObject *noargs)
   10222             : {
   10223             :     uid_t ruid, euid, suid;
   10224             :     long l_ruid, l_euid, l_suid;
   10225           0 :     if (getresuid(&ruid, &euid, &suid) < 0)
   10226           0 :         return posix_error();
   10227             :     /* Force the values into long's as we don't know the size of uid_t. */
   10228           0 :     l_ruid = ruid;
   10229           0 :     l_euid = euid;
   10230           0 :     l_suid = suid;
   10231           0 :     return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
   10232             : }
   10233             : #endif
   10234             : 
   10235             : #ifdef HAVE_GETRESGID
   10236             : PyDoc_STRVAR(posix_getresgid__doc__,
   10237             : "getresgid() -> (rgid, egid, sgid)\n\n\
   10238             : Get tuple of the current process's real, effective, and saved group ids.");
   10239             : 
   10240             : static PyObject*
   10241           0 : posix_getresgid (PyObject *self, PyObject *noargs)
   10242             : {
   10243             :     uid_t rgid, egid, sgid;
   10244             :     long l_rgid, l_egid, l_sgid;
   10245           0 :     if (getresgid(&rgid, &egid, &sgid) < 0)
   10246           0 :         return posix_error();
   10247             :     /* Force the values into long's as we don't know the size of uid_t. */
   10248           0 :     l_rgid = rgid;
   10249           0 :     l_egid = egid;
   10250           0 :     l_sgid = sgid;
   10251           0 :     return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
   10252             : }
   10253             : #endif
   10254             : 
   10255             : #ifdef USE_XATTRS
   10256             : 
   10257             : PyDoc_STRVAR(posix_getxattr__doc__,
   10258             : "getxattr(path, attribute, *, follow_symlinks=True) -> value\n\n\
   10259             : Return the value of extended attribute attribute on path.\n\
   10260             : \n\
   10261             : path may be either a string or an open file descriptor.\n\
   10262             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
   10263             :   link, getxattr will examine the symbolic link itself instead of the file\n\
   10264             :   the link points to.");
   10265             : 
   10266             : static PyObject *
   10267           0 : posix_getxattr(PyObject *self, PyObject *args, PyObject *kwargs)
   10268             : {
   10269             :     path_t path;
   10270             :     path_t attribute;
   10271           0 :     int follow_symlinks = 1;
   10272           0 :     PyObject *buffer = NULL;
   10273             :     int i;
   10274             :     static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL};
   10275             : 
   10276           0 :     memset(&path, 0, sizeof(path));
   10277           0 :     memset(&attribute, 0, sizeof(attribute));
   10278           0 :     path.allow_fd = 1;
   10279           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:getxattr", keywords,
   10280             :         path_converter, &path,
   10281             :         path_converter, &attribute,
   10282             :         &follow_symlinks))
   10283           0 :         return NULL;
   10284             : 
   10285           0 :     if (fd_and_follow_symlinks_invalid("getxattr", path.fd, follow_symlinks))
   10286           0 :         goto exit;
   10287             : 
   10288           0 :     for (i = 0; ; i++) {
   10289             :         void *ptr;
   10290             :         ssize_t result;
   10291             :         static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
   10292           0 :         Py_ssize_t buffer_size = buffer_sizes[i];
   10293           0 :         if (!buffer_size) {
   10294           0 :             path_error("getxattr", &path);
   10295           0 :             goto exit;
   10296             :         }
   10297           0 :         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
   10298           0 :         if (!buffer)
   10299           0 :             goto exit;
   10300           0 :         ptr = PyBytes_AS_STRING(buffer);
   10301             : 
   10302           0 :         Py_BEGIN_ALLOW_THREADS;
   10303           0 :         if (path.fd >= 0)
   10304           0 :             result = fgetxattr(path.fd, attribute.narrow, ptr, buffer_size);
   10305           0 :         else if (follow_symlinks)
   10306           0 :             result = getxattr(path.narrow, attribute.narrow, ptr, buffer_size);
   10307             :         else
   10308           0 :             result = lgetxattr(path.narrow, attribute.narrow, ptr, buffer_size);
   10309           0 :         Py_END_ALLOW_THREADS;
   10310             : 
   10311           0 :         if (result < 0) {
   10312           0 :             Py_DECREF(buffer);
   10313           0 :             buffer = NULL;
   10314           0 :             if (errno == ERANGE)
   10315           0 :                 continue;
   10316           0 :             path_error("getxattr", &path);
   10317           0 :             goto exit;
   10318             :         }
   10319             : 
   10320           0 :         if (result != buffer_size) {
   10321             :             /* Can only shrink. */
   10322           0 :             _PyBytes_Resize(&buffer, result);
   10323             :         }
   10324           0 :         break;
   10325           0 :     }
   10326             : 
   10327             : exit:
   10328           0 :     path_cleanup(&path);
   10329           0 :     path_cleanup(&attribute);
   10330           0 :     return buffer;
   10331             : }
   10332             : 
   10333             : PyDoc_STRVAR(posix_setxattr__doc__,
   10334             : "setxattr(path, attribute, value, flags=0, *, follow_symlinks=True)\n\n\
   10335             : Set extended attribute attribute on path to value.\n\
   10336             : path may be either a string or an open file descriptor.\n\
   10337             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
   10338             :   link, setxattr will modify the symbolic link itself instead of the file\n\
   10339             :   the link points to.");
   10340             : 
   10341             : static PyObject *
   10342           0 : posix_setxattr(PyObject *self, PyObject *args, PyObject *kwargs)
   10343             : {
   10344             :     path_t path;
   10345             :     path_t attribute;
   10346             :     Py_buffer value;
   10347           0 :     int flags = 0;
   10348           0 :     int follow_symlinks = 1;
   10349             :     int result;
   10350           0 :     PyObject *return_value = NULL;
   10351             :     static char *keywords[] = {"path", "attribute", "value",
   10352             :                                "flags", "follow_symlinks", NULL};
   10353             : 
   10354           0 :     memset(&path, 0, sizeof(path));
   10355           0 :     path.allow_fd = 1;
   10356           0 :     memset(&attribute, 0, sizeof(attribute));
   10357           0 :     memset(&value, 0, sizeof(value));
   10358           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&y*|i$p:setxattr",
   10359             :         keywords,
   10360             :         path_converter, &path,
   10361             :         path_converter, &attribute,
   10362             :         &value, &flags,
   10363             :         &follow_symlinks))
   10364           0 :         return NULL;
   10365             : 
   10366           0 :     if (fd_and_follow_symlinks_invalid("setxattr", path.fd, follow_symlinks))
   10367           0 :         goto exit;
   10368             : 
   10369           0 :     Py_BEGIN_ALLOW_THREADS;
   10370           0 :     if (path.fd > -1)
   10371           0 :         result = fsetxattr(path.fd, attribute.narrow,
   10372           0 :                            value.buf, value.len, flags);
   10373           0 :     else if (follow_symlinks)
   10374           0 :         result = setxattr(path.narrow, attribute.narrow,
   10375           0 :                            value.buf, value.len, flags);
   10376             :     else
   10377           0 :         result = lsetxattr(path.narrow, attribute.narrow,
   10378           0 :                            value.buf, value.len, flags);
   10379           0 :     Py_END_ALLOW_THREADS;
   10380             : 
   10381           0 :     if (result) {
   10382           0 :         return_value = path_error("setxattr", &path);
   10383           0 :         goto exit;
   10384             :     }
   10385             : 
   10386           0 :     return_value = Py_None;
   10387           0 :     Py_INCREF(return_value);
   10388             : 
   10389             : exit:
   10390           0 :     path_cleanup(&path);
   10391           0 :     path_cleanup(&attribute);
   10392           0 :     PyBuffer_Release(&value);
   10393             : 
   10394           0 :     return return_value;
   10395             : }
   10396             : 
   10397             : PyDoc_STRVAR(posix_removexattr__doc__,
   10398             : "removexattr(path, attribute, *, follow_symlinks=True)\n\n\
   10399             : Remove extended attribute attribute on path.\n\
   10400             : path may be either a string or an open file descriptor.\n\
   10401             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
   10402             :   link, removexattr will modify the symbolic link itself instead of the file\n\
   10403             :   the link points to.");
   10404             : 
   10405             : static PyObject *
   10406           0 : posix_removexattr(PyObject *self, PyObject *args, PyObject *kwargs)
   10407             : {
   10408             :     path_t path;
   10409             :     path_t attribute;
   10410           0 :     int follow_symlinks = 1;
   10411             :     int result;
   10412           0 :     PyObject *return_value = NULL;
   10413             :     static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL};
   10414             : 
   10415           0 :     memset(&path, 0, sizeof(path));
   10416           0 :     memset(&attribute, 0, sizeof(attribute));
   10417           0 :     path.allow_fd = 1;
   10418           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:removexattr",
   10419             :                                      keywords,
   10420             :                                      path_converter, &path,
   10421             :                                      path_converter, &attribute,
   10422             :                                      &follow_symlinks))
   10423           0 :         return NULL;
   10424             : 
   10425           0 :     if (fd_and_follow_symlinks_invalid("removexattr", path.fd, follow_symlinks))
   10426           0 :         goto exit;
   10427             : 
   10428           0 :     Py_BEGIN_ALLOW_THREADS;
   10429           0 :     if (path.fd > -1)
   10430           0 :         result = fremovexattr(path.fd, attribute.narrow);
   10431           0 :     else if (follow_symlinks)
   10432           0 :         result = removexattr(path.narrow, attribute.narrow);
   10433             :     else
   10434           0 :         result = lremovexattr(path.narrow, attribute.narrow);
   10435           0 :     Py_END_ALLOW_THREADS;
   10436             : 
   10437           0 :     if (result) {
   10438           0 :         return_value = path_error("removexattr", &path);
   10439           0 :         goto exit;
   10440             :     }
   10441             : 
   10442           0 :     return_value = Py_None;
   10443           0 :     Py_INCREF(return_value);
   10444             : 
   10445             : exit:
   10446           0 :     path_cleanup(&path);
   10447           0 :     path_cleanup(&attribute);
   10448             : 
   10449           0 :     return return_value;
   10450             : }
   10451             : 
   10452             : PyDoc_STRVAR(posix_listxattr__doc__,
   10453             : "listxattr(path='.', *, follow_symlinks=True)\n\n\
   10454             : Return a list of extended attributes on path.\n\
   10455             : \n\
   10456             : path may be either None, a string, or an open file descriptor.\n\
   10457             : if path is None, listxattr will examine the current directory.\n\
   10458             : If follow_symlinks is False, and the last element of the path is a symbolic\n\
   10459             :   link, listxattr will examine the symbolic link itself instead of the file\n\
   10460             :   the link points to.");
   10461             : 
   10462             : static PyObject *
   10463           0 : posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
   10464             : {
   10465             :     path_t path;
   10466           0 :     int follow_symlinks = 1;
   10467             :     Py_ssize_t i;
   10468           0 :     PyObject *result = NULL;
   10469           0 :     char *buffer = NULL;
   10470             :     char *name;
   10471             :     static char *keywords[] = {"path", "follow_symlinks", NULL};
   10472             : 
   10473           0 :     memset(&path, 0, sizeof(path));
   10474           0 :     path.allow_fd = 1;
   10475           0 :     path.fd = -1;
   10476           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&$p:listxattr", keywords,
   10477             :         path_converter, &path,
   10478             :         &follow_symlinks))
   10479           0 :         return NULL;
   10480             : 
   10481           0 :     if (fd_and_follow_symlinks_invalid("listxattr", path.fd, follow_symlinks))
   10482           0 :         goto exit;
   10483             : 
   10484           0 :     name = path.narrow ? path.narrow : ".";
   10485           0 :     for (i = 0; ; i++) {
   10486             :         char *start, *trace, *end;
   10487             :         ssize_t length;
   10488             :         static Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
   10489           0 :         Py_ssize_t buffer_size = buffer_sizes[i];
   10490           0 :         if (!buffer_size) {
   10491             :             /* ERANGE */
   10492           0 :             path_error("listxattr", &path);
   10493           0 :             break;
   10494             :         }
   10495           0 :         buffer = PyMem_MALLOC(buffer_size);
   10496           0 :         if (!buffer) {
   10497           0 :             PyErr_NoMemory();
   10498           0 :             break;
   10499             :         }
   10500             : 
   10501           0 :         Py_BEGIN_ALLOW_THREADS;
   10502           0 :         if (path.fd > -1)
   10503           0 :             length = flistxattr(path.fd, buffer, buffer_size);
   10504           0 :         else if (follow_symlinks)
   10505           0 :             length = listxattr(name, buffer, buffer_size);
   10506             :         else
   10507           0 :             length = llistxattr(name, buffer, buffer_size);
   10508           0 :         Py_END_ALLOW_THREADS;
   10509             : 
   10510           0 :         if (length < 0) {
   10511           0 :             if (errno == ERANGE)
   10512           0 :                 continue;
   10513           0 :             path_error("listxattr", &path);
   10514           0 :             break;
   10515             :         }
   10516             : 
   10517           0 :         result = PyList_New(0);
   10518           0 :         if (!result) {
   10519           0 :             goto exit;
   10520             :         }
   10521             : 
   10522           0 :         end = buffer + length;
   10523           0 :         for (trace = start = buffer; trace != end; trace++) {
   10524           0 :             if (!*trace) {
   10525             :                 int error;
   10526           0 :                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
   10527             :                                                                  trace - start);
   10528           0 :                 if (!attribute) {
   10529           0 :                     Py_DECREF(result);
   10530           0 :                     result = NULL;
   10531           0 :                     goto exit;
   10532             :                 }
   10533           0 :                 error = PyList_Append(result, attribute);
   10534           0 :                 Py_DECREF(attribute);
   10535           0 :                 if (error) {
   10536           0 :                     Py_DECREF(result);
   10537           0 :                     result = NULL;
   10538           0 :                     goto exit;
   10539             :                 }
   10540           0 :                 start = trace + 1;
   10541             :             }
   10542             :         }
   10543           0 :     break;
   10544           0 :     }
   10545             : exit:
   10546           0 :     path_cleanup(&path);
   10547           0 :     if (buffer)
   10548           0 :         PyMem_FREE(buffer);
   10549           0 :     return result;
   10550             : }
   10551             : 
   10552             : #endif /* USE_XATTRS */
   10553             : 
   10554             : 
   10555             : PyDoc_STRVAR(posix_urandom__doc__,
   10556             : "urandom(n) -> str\n\n\
   10557             : Return n random bytes suitable for cryptographic use.");
   10558             : 
   10559             : static PyObject *
   10560           0 : posix_urandom(PyObject *self, PyObject *args)
   10561             : {
   10562             :     Py_ssize_t size;
   10563             :     PyObject *result;
   10564             :     int ret;
   10565             : 
   10566             :      /* Read arguments */
   10567           0 :     if (!PyArg_ParseTuple(args, "n:urandom", &size))
   10568           0 :         return NULL;
   10569           0 :     if (size < 0)
   10570           0 :         return PyErr_Format(PyExc_ValueError,
   10571             :                             "negative argument not allowed");
   10572           0 :     result = PyBytes_FromStringAndSize(NULL, size);
   10573           0 :     if (result == NULL)
   10574           0 :         return NULL;
   10575             : 
   10576           0 :     ret = _PyOS_URandom(PyBytes_AS_STRING(result),
   10577             :                         PyBytes_GET_SIZE(result));
   10578           0 :     if (ret == -1) {
   10579           0 :         Py_DECREF(result);
   10580           0 :         return NULL;
   10581             :     }
   10582           0 :     return result;
   10583             : }
   10584             : 
   10585             : /* Terminal size querying */
   10586             : 
   10587             : static PyTypeObject TerminalSizeType;
   10588             : 
   10589             : PyDoc_STRVAR(TerminalSize_docstring,
   10590             :     "A tuple of (columns, lines) for holding terminal window size");
   10591             : 
   10592             : static PyStructSequence_Field TerminalSize_fields[] = {
   10593             :     {"columns", "width of the terminal window in characters"},
   10594             :     {"lines", "height of the terminal window in characters"},
   10595             :     {NULL, NULL}
   10596             : };
   10597             : 
   10598             : static PyStructSequence_Desc TerminalSize_desc = {
   10599             :     "os.terminal_size",
   10600             :     TerminalSize_docstring,
   10601             :     TerminalSize_fields,
   10602             :     2,
   10603             : };
   10604             : 
   10605             : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
   10606             : PyDoc_STRVAR(termsize__doc__,
   10607             :     "Return the size of the terminal window as (columns, lines).\n"        \
   10608             :     "\n"                                                                   \
   10609             :     "The optional argument fd (default standard output) specifies\n"       \
   10610             :     "which file descriptor should be queried.\n"                           \
   10611             :     "\n"                                                                   \
   10612             :     "If the file descriptor is not connected to a terminal, an OSError\n"  \
   10613             :     "is thrown.\n"                                                         \
   10614             :     "\n"                                                                   \
   10615             :     "This function will only be defined if an implementation is\n"         \
   10616             :     "available for this system.\n"                                         \
   10617             :     "\n"                                                                   \
   10618             :     "shutil.get_terminal_size is the high-level function which should \n"  \
   10619             :     "normally be used, os.get_terminal_size is the low-level implementation.");
   10620             : 
   10621             : static PyObject*
   10622           0 : get_terminal_size(PyObject *self, PyObject *args)
   10623             : {
   10624             :     int columns, lines;
   10625             :     PyObject *termsize;
   10626             : 
   10627           0 :     int fd = fileno(stdout);
   10628             :     /* Under some conditions stdout may not be connected and
   10629             :      * fileno(stdout) may point to an invalid file descriptor. For example
   10630             :      * GUI apps don't have valid standard streams by default.
   10631             :      *
   10632             :      * If this happens, and the optional fd argument is not present,
   10633             :      * the ioctl below will fail returning EBADF. This is what we want.
   10634             :      */
   10635             : 
   10636           0 :     if (!PyArg_ParseTuple(args, "|i", &fd))
   10637           0 :         return NULL;
   10638             : 
   10639             : #ifdef TERMSIZE_USE_IOCTL
   10640             :     {
   10641             :         struct winsize w;
   10642           0 :         if (ioctl(fd, TIOCGWINSZ, &w))
   10643           0 :             return PyErr_SetFromErrno(PyExc_OSError);
   10644           0 :         columns = w.ws_col;
   10645           0 :         lines = w.ws_row;
   10646             :     }
   10647             : #endif /* TERMSIZE_USE_IOCTL */
   10648             : 
   10649             : #ifdef TERMSIZE_USE_CONIO
   10650             :     {
   10651             :         DWORD nhandle;
   10652             :         HANDLE handle;
   10653             :         CONSOLE_SCREEN_BUFFER_INFO csbi;
   10654             :         switch (fd) {
   10655             :         case 0: nhandle = STD_INPUT_HANDLE;
   10656             :             break;
   10657             :         case 1: nhandle = STD_OUTPUT_HANDLE;
   10658             :             break;
   10659             :         case 2: nhandle = STD_ERROR_HANDLE;
   10660             :             break;
   10661             :         default:
   10662             :             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
   10663             :         }
   10664             :         handle = GetStdHandle(nhandle);
   10665             :         if (handle == NULL)
   10666             :             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
   10667             :         if (handle == INVALID_HANDLE_VALUE)
   10668             :             return PyErr_SetFromWindowsErr(0);
   10669             : 
   10670             :         if (!GetConsoleScreenBufferInfo(handle, &csbi))
   10671             :             return PyErr_SetFromWindowsErr(0);
   10672             : 
   10673             :         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
   10674             :         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
   10675             :     }
   10676             : #endif /* TERMSIZE_USE_CONIO */
   10677             : 
   10678           0 :     termsize = PyStructSequence_New(&TerminalSizeType);
   10679           0 :     if (termsize == NULL)
   10680           0 :         return NULL;
   10681           0 :     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
   10682           0 :     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
   10683           0 :     if (PyErr_Occurred()) {
   10684           0 :         Py_DECREF(termsize);
   10685           0 :         return NULL;
   10686             :     }
   10687           0 :     return termsize;
   10688             : }
   10689             : #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
   10690             : 
   10691             : 
   10692             : static PyMethodDef posix_methods[] = {
   10693             :     {"access",          (PyCFunction)posix_access,
   10694             :                         METH_VARARGS | METH_KEYWORDS,
   10695             :                         posix_access__doc__},
   10696             : #ifdef HAVE_TTYNAME
   10697             :     {"ttyname",         posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
   10698             : #endif
   10699             :     {"chdir",           (PyCFunction)posix_chdir,
   10700             :                         METH_VARARGS | METH_KEYWORDS,
   10701             :                         posix_chdir__doc__},
   10702             : #ifdef HAVE_CHFLAGS
   10703             :     {"chflags",         (PyCFunction)posix_chflags,
   10704             :                         METH_VARARGS | METH_KEYWORDS,
   10705             :                         posix_chflags__doc__},
   10706             : #endif /* HAVE_CHFLAGS */
   10707             :     {"chmod",           (PyCFunction)posix_chmod,
   10708             :                         METH_VARARGS | METH_KEYWORDS,
   10709             :                         posix_chmod__doc__},
   10710             : #ifdef HAVE_FCHMOD
   10711             :     {"fchmod",          posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
   10712             : #endif /* HAVE_FCHMOD */
   10713             : #ifdef HAVE_CHOWN
   10714             :     {"chown",           (PyCFunction)posix_chown,
   10715             :                         METH_VARARGS | METH_KEYWORDS,
   10716             :                         posix_chown__doc__},
   10717             : #endif /* HAVE_CHOWN */
   10718             : #ifdef HAVE_LCHMOD
   10719             :     {"lchmod",          posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
   10720             : #endif /* HAVE_LCHMOD */
   10721             : #ifdef HAVE_FCHOWN
   10722             :     {"fchown",          posix_fchown, METH_VARARGS, posix_fchown__doc__},
   10723             : #endif /* HAVE_FCHOWN */
   10724             : #ifdef HAVE_LCHFLAGS
   10725             :     {"lchflags",        posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
   10726             : #endif /* HAVE_LCHFLAGS */
   10727             : #ifdef HAVE_LCHOWN
   10728             :     {"lchown",          posix_lchown, METH_VARARGS, posix_lchown__doc__},
   10729             : #endif /* HAVE_LCHOWN */
   10730             : #ifdef HAVE_CHROOT
   10731             :     {"chroot",          posix_chroot, METH_VARARGS, posix_chroot__doc__},
   10732             : #endif
   10733             : #ifdef HAVE_CTERMID
   10734             :     {"ctermid",         posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
   10735             : #endif
   10736             : #ifdef HAVE_GETCWD
   10737             :     {"getcwd",          (PyCFunction)posix_getcwd_unicode,
   10738             :     METH_NOARGS, posix_getcwd__doc__},
   10739             :     {"getcwdb",         (PyCFunction)posix_getcwd_bytes,
   10740             :     METH_NOARGS, posix_getcwdb__doc__},
   10741             : #endif
   10742             : #if defined(HAVE_LINK) || defined(MS_WINDOWS)
   10743             :     {"link",            (PyCFunction)posix_link,
   10744             :                         METH_VARARGS | METH_KEYWORDS,
   10745             :                         posix_link__doc__},
   10746             : #endif /* HAVE_LINK */
   10747             :     {"listdir",         (PyCFunction)posix_listdir,
   10748             :                         METH_VARARGS | METH_KEYWORDS,
   10749             :                         posix_listdir__doc__},
   10750             :     {"lstat",           (PyCFunction)posix_lstat,
   10751             :                         METH_VARARGS | METH_KEYWORDS,
   10752             :                         posix_lstat__doc__},
   10753             :     {"mkdir",           (PyCFunction)posix_mkdir,
   10754             :                         METH_VARARGS | METH_KEYWORDS,
   10755             :                         posix_mkdir__doc__},
   10756             : #ifdef HAVE_NICE
   10757             :     {"nice",            posix_nice, METH_VARARGS, posix_nice__doc__},
   10758             : #endif /* HAVE_NICE */
   10759             : #ifdef HAVE_GETPRIORITY
   10760             :     {"getpriority",     posix_getpriority, METH_VARARGS, posix_getpriority__doc__},
   10761             : #endif /* HAVE_GETPRIORITY */
   10762             : #ifdef HAVE_SETPRIORITY
   10763             :     {"setpriority",     posix_setpriority, METH_VARARGS, posix_setpriority__doc__},
   10764             : #endif /* HAVE_SETPRIORITY */
   10765             : #ifdef HAVE_READLINK
   10766             :     {"readlink",        (PyCFunction)posix_readlink,
   10767             :                         METH_VARARGS | METH_KEYWORDS,
   10768             :                         readlink__doc__},
   10769             : #endif /* HAVE_READLINK */
   10770             : #if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
   10771             :     {"readlink",        (PyCFunction)win_readlink,
   10772             :                         METH_VARARGS | METH_KEYWORDS,
   10773             :                         readlink__doc__},
   10774             : #endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
   10775             :     {"rename",          (PyCFunction)posix_rename,
   10776             :                         METH_VARARGS | METH_KEYWORDS,
   10777             :                         posix_rename__doc__},
   10778             :     {"replace",         (PyCFunction)posix_replace,
   10779             :                         METH_VARARGS | METH_KEYWORDS,
   10780             :                         posix_replace__doc__},
   10781             :     {"rmdir",           (PyCFunction)posix_rmdir,
   10782             :                         METH_VARARGS | METH_KEYWORDS,
   10783             :                         posix_rmdir__doc__},
   10784             :     {"stat",            (PyCFunction)posix_stat,
   10785             :                         METH_VARARGS | METH_KEYWORDS,
   10786             :                         posix_stat__doc__},
   10787             :     {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
   10788             : #if defined(HAVE_SYMLINK)
   10789             :     {"symlink",         (PyCFunction)posix_symlink,
   10790             :                         METH_VARARGS | METH_KEYWORDS,
   10791             :                         posix_symlink__doc__},
   10792             : #endif /* HAVE_SYMLINK */
   10793             : #ifdef HAVE_SYSTEM
   10794             :     {"system",          posix_system, METH_VARARGS, posix_system__doc__},
   10795             : #endif
   10796             :     {"umask",           posix_umask, METH_VARARGS, posix_umask__doc__},
   10797             : #ifdef HAVE_UNAME
   10798             :     {"uname",           posix_uname, METH_NOARGS, posix_uname__doc__},
   10799             : #endif /* HAVE_UNAME */
   10800             :     {"unlink",          (PyCFunction)posix_unlink,
   10801             :                         METH_VARARGS | METH_KEYWORDS,
   10802             :                         posix_unlink__doc__},
   10803             :     {"remove",          (PyCFunction)posix_unlink,
   10804             :                         METH_VARARGS | METH_KEYWORDS,
   10805             :                         posix_remove__doc__},
   10806             :     {"utime",           (PyCFunction)posix_utime,
   10807             :                         METH_VARARGS | METH_KEYWORDS, posix_utime__doc__},
   10808             : #ifdef HAVE_TIMES
   10809             :     {"times",           posix_times, METH_NOARGS, posix_times__doc__},
   10810             : #endif /* HAVE_TIMES */
   10811             :     {"_exit",           posix__exit, METH_VARARGS, posix__exit__doc__},
   10812             : #ifdef HAVE_EXECV
   10813             :     {"execv",           posix_execv, METH_VARARGS, posix_execv__doc__},
   10814             :     {"execve",          (PyCFunction)posix_execve,
   10815             :                         METH_VARARGS | METH_KEYWORDS,
   10816             :                         posix_execve__doc__},
   10817             : #endif /* HAVE_EXECV */
   10818             : #ifdef HAVE_SPAWNV
   10819             :     {"spawnv",          posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
   10820             :     {"spawnve",         posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
   10821             : #if defined(PYOS_OS2)
   10822             :     {"spawnvp",         posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
   10823             :     {"spawnvpe",        posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
   10824             : #endif /* PYOS_OS2 */
   10825             : #endif /* HAVE_SPAWNV */
   10826             : #ifdef HAVE_FORK1
   10827             :     {"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
   10828             : #endif /* HAVE_FORK1 */
   10829             : #ifdef HAVE_FORK
   10830             :     {"fork",            posix_fork, METH_NOARGS, posix_fork__doc__},
   10831             : #endif /* HAVE_FORK */
   10832             : #ifdef HAVE_SCHED_H
   10833             : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
   10834             :     {"sched_get_priority_max", posix_sched_get_priority_max, METH_VARARGS, posix_sched_get_priority_max__doc__},
   10835             :     {"sched_get_priority_min", posix_sched_get_priority_min, METH_VARARGS, posix_sched_get_priority_min__doc__},
   10836             : #endif
   10837             : #ifdef HAVE_SCHED_SETPARAM
   10838             :     {"sched_getparam", posix_sched_getparam, METH_VARARGS, posix_sched_getparam__doc__},
   10839             : #endif
   10840             : #ifdef HAVE_SCHED_SETSCHEDULER
   10841             :     {"sched_getscheduler", posix_sched_getscheduler, METH_VARARGS, posix_sched_getscheduler__doc__},
   10842             : #endif
   10843             : #ifdef HAVE_SCHED_RR_GET_INTERVAL
   10844             :     {"sched_rr_get_interval", posix_sched_rr_get_interval, METH_VARARGS, posix_sched_rr_get_interval__doc__},
   10845             : #endif
   10846             : #ifdef HAVE_SCHED_SETPARAM
   10847             :     {"sched_setparam", posix_sched_setparam, METH_VARARGS, posix_sched_setparam__doc__},
   10848             : #endif
   10849             : #ifdef HAVE_SCHED_SETSCHEDULER
   10850             :     {"sched_setscheduler", posix_sched_setscheduler, METH_VARARGS, posix_sched_setscheduler__doc__},
   10851             : #endif
   10852             :     {"sched_yield",     posix_sched_yield, METH_NOARGS, posix_sched_yield__doc__},
   10853             : #ifdef HAVE_SCHED_SETAFFINITY
   10854             :     {"sched_setaffinity", posix_sched_setaffinity, METH_VARARGS, posix_sched_setaffinity__doc__},
   10855             :     {"sched_getaffinity", posix_sched_getaffinity, METH_VARARGS, posix_sched_getaffinity__doc__},
   10856             : #endif
   10857             : #endif /* HAVE_SCHED_H */
   10858             : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
   10859             :     {"openpty",         posix_openpty, METH_NOARGS, posix_openpty__doc__},
   10860             : #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
   10861             : #ifdef HAVE_FORKPTY
   10862             :     {"forkpty",         posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
   10863             : #endif /* HAVE_FORKPTY */
   10864             : #ifdef HAVE_GETEGID
   10865             :     {"getegid",         posix_getegid, METH_NOARGS, posix_getegid__doc__},
   10866             : #endif /* HAVE_GETEGID */
   10867             : #ifdef HAVE_GETEUID
   10868             :     {"geteuid",         posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
   10869             : #endif /* HAVE_GETEUID */
   10870             : #ifdef HAVE_GETGID
   10871             :     {"getgid",          posix_getgid, METH_NOARGS, posix_getgid__doc__},
   10872             : #endif /* HAVE_GETGID */
   10873             : #ifdef HAVE_GETGROUPLIST
   10874             :     {"getgrouplist",    posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
   10875             : #endif
   10876             : #ifdef HAVE_GETGROUPS
   10877             :     {"getgroups",       posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
   10878             : #endif
   10879             :     {"getpid",          posix_getpid, METH_NOARGS, posix_getpid__doc__},
   10880             : #ifdef HAVE_GETPGRP
   10881             :     {"getpgrp",         posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
   10882             : #endif /* HAVE_GETPGRP */
   10883             : #ifdef HAVE_GETPPID
   10884             :     {"getppid",         posix_getppid, METH_NOARGS, posix_getppid__doc__},
   10885             : #endif /* HAVE_GETPPID */
   10886             : #ifdef HAVE_GETUID
   10887             :     {"getuid",          posix_getuid, METH_NOARGS, posix_getuid__doc__},
   10888             : #endif /* HAVE_GETUID */
   10889             : #ifdef HAVE_GETLOGIN
   10890             :     {"getlogin",        posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
   10891             : #endif
   10892             : #ifdef HAVE_KILL
   10893             :     {"kill",            posix_kill, METH_VARARGS, posix_kill__doc__},
   10894             : #endif /* HAVE_KILL */
   10895             : #ifdef HAVE_KILLPG
   10896             :     {"killpg",          posix_killpg, METH_VARARGS, posix_killpg__doc__},
   10897             : #endif /* HAVE_KILLPG */
   10898             : #ifdef HAVE_PLOCK
   10899             :     {"plock",           posix_plock, METH_VARARGS, posix_plock__doc__},
   10900             : #endif /* HAVE_PLOCK */
   10901             : #ifdef MS_WINDOWS
   10902             :     {"startfile",       win32_startfile, METH_VARARGS, win32_startfile__doc__},
   10903             :     {"kill",    win32_kill, METH_VARARGS, win32_kill__doc__},
   10904             : #endif
   10905             : #ifdef HAVE_SETUID
   10906             :     {"setuid",          posix_setuid, METH_VARARGS, posix_setuid__doc__},
   10907             : #endif /* HAVE_SETUID */
   10908             : #ifdef HAVE_SETEUID
   10909             :     {"seteuid",         posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
   10910             : #endif /* HAVE_SETEUID */
   10911             : #ifdef HAVE_SETEGID
   10912             :     {"setegid",         posix_setegid, METH_VARARGS, posix_setegid__doc__},
   10913             : #endif /* HAVE_SETEGID */
   10914             : #ifdef HAVE_SETREUID
   10915             :     {"setreuid",        posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
   10916             : #endif /* HAVE_SETREUID */
   10917             : #ifdef HAVE_SETREGID
   10918             :     {"setregid",        posix_setregid, METH_VARARGS, posix_setregid__doc__},
   10919             : #endif /* HAVE_SETREGID */
   10920             : #ifdef HAVE_SETGID
   10921             :     {"setgid",          posix_setgid, METH_VARARGS, posix_setgid__doc__},
   10922             : #endif /* HAVE_SETGID */
   10923             : #ifdef HAVE_SETGROUPS
   10924             :     {"setgroups",       posix_setgroups, METH_O, posix_setgroups__doc__},
   10925             : #endif /* HAVE_SETGROUPS */
   10926             : #ifdef HAVE_INITGROUPS
   10927             :     {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
   10928             : #endif /* HAVE_INITGROUPS */
   10929             : #ifdef HAVE_GETPGID
   10930             :     {"getpgid",         posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
   10931             : #endif /* HAVE_GETPGID */
   10932             : #ifdef HAVE_SETPGRP
   10933             :     {"setpgrp",         posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
   10934             : #endif /* HAVE_SETPGRP */
   10935             : #ifdef HAVE_WAIT
   10936             :     {"wait",            posix_wait, METH_NOARGS, posix_wait__doc__},
   10937             : #endif /* HAVE_WAIT */
   10938             : #ifdef HAVE_WAIT3
   10939             :     {"wait3",           posix_wait3, METH_VARARGS, posix_wait3__doc__},
   10940             : #endif /* HAVE_WAIT3 */
   10941             : #ifdef HAVE_WAIT4
   10942             :     {"wait4",           posix_wait4, METH_VARARGS, posix_wait4__doc__},
   10943             : #endif /* HAVE_WAIT4 */
   10944             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
   10945             :     {"waitid",          posix_waitid, METH_VARARGS, posix_waitid__doc__},
   10946             : #endif
   10947             : #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
   10948             :     {"waitpid",         posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
   10949             : #endif /* HAVE_WAITPID */
   10950             : #ifdef HAVE_GETSID
   10951             :     {"getsid",          posix_getsid, METH_VARARGS, posix_getsid__doc__},
   10952             : #endif /* HAVE_GETSID */
   10953             : #ifdef HAVE_SETSID
   10954             :     {"setsid",          posix_setsid, METH_NOARGS, posix_setsid__doc__},
   10955             : #endif /* HAVE_SETSID */
   10956             : #ifdef HAVE_SETPGID
   10957             :     {"setpgid",         posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
   10958             : #endif /* HAVE_SETPGID */
   10959             : #ifdef HAVE_TCGETPGRP
   10960             :     {"tcgetpgrp",       posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
   10961             : #endif /* HAVE_TCGETPGRP */
   10962             : #ifdef HAVE_TCSETPGRP
   10963             :     {"tcsetpgrp",       posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
   10964             : #endif /* HAVE_TCSETPGRP */
   10965             :     {"open",            (PyCFunction)posix_open,\
   10966             :                         METH_VARARGS | METH_KEYWORDS,
   10967             :                         posix_open__doc__},
   10968             :     {"close",           posix_close, METH_VARARGS, posix_close__doc__},
   10969             :     {"closerange",      posix_closerange, METH_VARARGS, posix_closerange__doc__},
   10970             :     {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
   10971             :     {"dup",             posix_dup, METH_VARARGS, posix_dup__doc__},
   10972             :     {"dup2",            posix_dup2, METH_VARARGS, posix_dup2__doc__},
   10973             : #ifdef HAVE_LOCKF
   10974             :     {"lockf",           posix_lockf, METH_VARARGS, posix_lockf__doc__},
   10975             : #endif
   10976             :     {"lseek",           posix_lseek, METH_VARARGS, posix_lseek__doc__},
   10977             :     {"read",            posix_read, METH_VARARGS, posix_read__doc__},
   10978             : #ifdef HAVE_READV
   10979             :     {"readv",           posix_readv, METH_VARARGS, posix_readv__doc__},
   10980             : #endif
   10981             : #ifdef HAVE_PREAD
   10982             :     {"pread",           posix_pread, METH_VARARGS, posix_pread__doc__},
   10983             : #endif
   10984             :     {"write",           posix_write, METH_VARARGS, posix_write__doc__},
   10985             : #ifdef HAVE_WRITEV
   10986             :     {"writev",          posix_writev, METH_VARARGS, posix_writev__doc__},
   10987             : #endif
   10988             : #ifdef HAVE_PWRITE
   10989             :     {"pwrite",          posix_pwrite, METH_VARARGS, posix_pwrite__doc__},
   10990             : #endif
   10991             : #ifdef HAVE_SENDFILE
   10992             :     {"sendfile",        (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
   10993             :                             posix_sendfile__doc__},
   10994             : #endif
   10995             :     {"fstat",           posix_fstat, METH_VARARGS, posix_fstat__doc__},
   10996             :     {"isatty",          posix_isatty, METH_VARARGS, posix_isatty__doc__},
   10997             : #ifdef HAVE_PIPE
   10998             :     {"pipe",            posix_pipe, METH_NOARGS, posix_pipe__doc__},
   10999             : #endif
   11000             : #ifdef HAVE_PIPE2
   11001             :     {"pipe2",           posix_pipe2, METH_O, posix_pipe2__doc__},
   11002             : #endif
   11003             : #ifdef HAVE_MKFIFO
   11004             :     {"mkfifo",          (PyCFunction)posix_mkfifo,
   11005             :                         METH_VARARGS | METH_KEYWORDS,
   11006             :                         posix_mkfifo__doc__},
   11007             : #endif
   11008             : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
   11009             :     {"mknod",           (PyCFunction)posix_mknod,
   11010             :                         METH_VARARGS | METH_KEYWORDS,
   11011             :                         posix_mknod__doc__},
   11012             : #endif
   11013             : #ifdef HAVE_DEVICE_MACROS
   11014             :     {"major",           posix_major, METH_VARARGS, posix_major__doc__},
   11015             :     {"minor",           posix_minor, METH_VARARGS, posix_minor__doc__},
   11016             :     {"makedev",         posix_makedev, METH_VARARGS, posix_makedev__doc__},
   11017             : #endif
   11018             : #ifdef HAVE_FTRUNCATE
   11019             :     {"ftruncate",       posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
   11020             : #endif
   11021             : #ifdef HAVE_TRUNCATE
   11022             :     {"truncate",        (PyCFunction)posix_truncate,
   11023             :                         METH_VARARGS | METH_KEYWORDS,
   11024             :                         posix_truncate__doc__},
   11025             : #endif
   11026             : #ifdef HAVE_POSIX_FALLOCATE
   11027             :     {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__},
   11028             : #endif
   11029             : #ifdef HAVE_POSIX_FADVISE
   11030             :     {"posix_fadvise",   posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__},
   11031             : #endif
   11032             : #ifdef HAVE_PUTENV
   11033             :     {"putenv",          posix_putenv, METH_VARARGS, posix_putenv__doc__},
   11034             : #endif
   11035             : #ifdef HAVE_UNSETENV
   11036             :     {"unsetenv",        posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
   11037             : #endif
   11038             :     {"strerror",        posix_strerror, METH_VARARGS, posix_strerror__doc__},
   11039             : #ifdef HAVE_FCHDIR
   11040             :     {"fchdir",          posix_fchdir, METH_O, posix_fchdir__doc__},
   11041             : #endif
   11042             : #ifdef HAVE_FSYNC
   11043             :     {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
   11044             : #endif
   11045             : #ifdef HAVE_SYNC
   11046             :     {"sync",        posix_sync, METH_NOARGS, posix_sync__doc__},
   11047             : #endif
   11048             : #ifdef HAVE_FDATASYNC
   11049             :     {"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
   11050             : #endif
   11051             : #ifdef HAVE_SYS_WAIT_H
   11052             : #ifdef WCOREDUMP
   11053             :     {"WCOREDUMP",       posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
   11054             : #endif /* WCOREDUMP */
   11055             : #ifdef WIFCONTINUED
   11056             :     {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
   11057             : #endif /* WIFCONTINUED */
   11058             : #ifdef WIFSTOPPED
   11059             :     {"WIFSTOPPED",      posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
   11060             : #endif /* WIFSTOPPED */
   11061             : #ifdef WIFSIGNALED
   11062             :     {"WIFSIGNALED",     posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
   11063             : #endif /* WIFSIGNALED */
   11064             : #ifdef WIFEXITED
   11065             :     {"WIFEXITED",       posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
   11066             : #endif /* WIFEXITED */
   11067             : #ifdef WEXITSTATUS
   11068             :     {"WEXITSTATUS",     posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
   11069             : #endif /* WEXITSTATUS */
   11070             : #ifdef WTERMSIG
   11071             :     {"WTERMSIG",        posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
   11072             : #endif /* WTERMSIG */
   11073             : #ifdef WSTOPSIG
   11074             :     {"WSTOPSIG",        posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
   11075             : #endif /* WSTOPSIG */
   11076             : #endif /* HAVE_SYS_WAIT_H */
   11077             : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
   11078             :     {"fstatvfs",        posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
   11079             : #endif
   11080             : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
   11081             :     {"statvfs",         (PyCFunction)posix_statvfs,
   11082             :                         METH_VARARGS | METH_KEYWORDS,
   11083             :                         posix_statvfs__doc__},
   11084             : #endif
   11085             : #ifdef HAVE_CONFSTR
   11086             :     {"confstr",         posix_confstr, METH_VARARGS, posix_confstr__doc__},
   11087             : #endif
   11088             : #ifdef HAVE_SYSCONF
   11089             :     {"sysconf",         posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
   11090             : #endif
   11091             : #ifdef HAVE_FPATHCONF
   11092             :     {"fpathconf",       posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
   11093             : #endif
   11094             : #ifdef HAVE_PATHCONF
   11095             :     {"pathconf",        (PyCFunction)posix_pathconf,
   11096             :                         METH_VARARGS | METH_KEYWORDS,
   11097             :                         posix_pathconf__doc__},
   11098             : #endif
   11099             :     {"abort",           posix_abort, METH_NOARGS, posix_abort__doc__},
   11100             : #ifdef MS_WINDOWS
   11101             :     {"_getfullpathname",        posix__getfullpathname, METH_VARARGS, NULL},
   11102             :     {"_getfinalpathname",       posix__getfinalpathname, METH_VARARGS, NULL},
   11103             :     {"_getfileinformation",     posix__getfileinformation, METH_VARARGS, NULL},
   11104             :     {"_isdir",                  posix__isdir, METH_VARARGS, posix__isdir__doc__},
   11105             :     {"_getdiskusage",           win32__getdiskusage, METH_VARARGS, win32__getdiskusage__doc__},
   11106             : #endif
   11107             : #ifdef HAVE_GETLOADAVG
   11108             :     {"getloadavg",      posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
   11109             : #endif
   11110             :     {"urandom",         posix_urandom,   METH_VARARGS, posix_urandom__doc__},
   11111             : #ifdef HAVE_SETRESUID
   11112             :     {"setresuid",       posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
   11113             : #endif
   11114             : #ifdef HAVE_SETRESGID
   11115             :     {"setresgid",       posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
   11116             : #endif
   11117             : #ifdef HAVE_GETRESUID
   11118             :     {"getresuid",       posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
   11119             : #endif
   11120             : #ifdef HAVE_GETRESGID
   11121             :     {"getresgid",       posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
   11122             : #endif
   11123             : 
   11124             : #ifdef USE_XATTRS
   11125             :     {"setxattr", (PyCFunction)posix_setxattr,
   11126             :                  METH_VARARGS | METH_KEYWORDS,
   11127             :                  posix_setxattr__doc__},
   11128             :     {"getxattr", (PyCFunction)posix_getxattr,
   11129             :                  METH_VARARGS | METH_KEYWORDS,
   11130             :                  posix_getxattr__doc__},
   11131             :     {"removexattr", (PyCFunction)posix_removexattr,
   11132             :                  METH_VARARGS | METH_KEYWORDS,
   11133             :                  posix_removexattr__doc__},
   11134             :     {"listxattr", (PyCFunction)posix_listxattr,
   11135             :                  METH_VARARGS | METH_KEYWORDS,
   11136             :                  posix_listxattr__doc__},
   11137             : #endif
   11138             : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
   11139             :     {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
   11140             : #endif
   11141             :     {NULL,              NULL}            /* Sentinel */
   11142             : };
   11143             : 
   11144             : 
   11145             : static int
   11146          82 : ins(PyObject *module, char *symbol, long value)
   11147             : {
   11148          82 :     return PyModule_AddIntConstant(module, symbol, value);
   11149             : }
   11150             : 
   11151             : #if defined(PYOS_OS2)
   11152             : /* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
   11153             : static int insertvalues(PyObject *module)
   11154             : {
   11155             :     APIRET    rc;
   11156             :     ULONG     values[QSV_MAX+1];
   11157             :     PyObject *v;
   11158             :     char     *ver, tmp[50];
   11159             : 
   11160             :     Py_BEGIN_ALLOW_THREADS
   11161             :     rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
   11162             :     Py_END_ALLOW_THREADS
   11163             : 
   11164             :     if (rc != NO_ERROR) {
   11165             :         os2_error(rc);
   11166             :         return -1;
   11167             :     }
   11168             : 
   11169             :     if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
   11170             :     if (ins(module, "memkernel",    values[QSV_TOTRESMEM])) return -1;
   11171             :     if (ins(module, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
   11172             :     if (ins(module, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
   11173             :     if (ins(module, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
   11174             :     if (ins(module, "revision",     values[QSV_VERSION_REVISION])) return -1;
   11175             :     if (ins(module, "timeslice",    values[QSV_MIN_SLICE])) return -1;
   11176             : 
   11177             :     switch (values[QSV_VERSION_MINOR]) {
   11178             :     case 0:  ver = "2.00"; break;
   11179             :     case 10: ver = "2.10"; break;
   11180             :     case 11: ver = "2.11"; break;
   11181             :     case 30: ver = "3.00"; break;
   11182             :     case 40: ver = "4.00"; break;
   11183             :     case 50: ver = "5.00"; break;
   11184             :     default:
   11185             :         PyOS_snprintf(tmp, sizeof(tmp),
   11186             :                       "%d-%d", values[QSV_VERSION_MAJOR],
   11187             :                       values[QSV_VERSION_MINOR]);
   11188             :         ver = &tmp[0];
   11189             :     }
   11190             : 
   11191             :     /* Add Indicator of the Version of the Operating System */
   11192             :     if (PyModule_AddStringConstant(module, "version", tmp) < 0)
   11193             :         return -1;
   11194             : 
   11195             :     /* Add Indicator of Which Drive was Used to Boot the System */
   11196             :     tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
   11197             :     tmp[1] = ':';
   11198             :     tmp[2] = '\0';
   11199             : 
   11200             :     return PyModule_AddStringConstant(module, "bootdrive", tmp);
   11201             : }
   11202             : #endif
   11203             : 
   11204             : #if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
   11205             : static int
   11206             : enable_symlink()
   11207             : {
   11208             :     HANDLE tok;
   11209             :     TOKEN_PRIVILEGES tok_priv;
   11210             :     LUID luid;
   11211             :     int meth_idx = 0;
   11212             : 
   11213             :     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok))
   11214             :         return 0;
   11215             : 
   11216             :     if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid))
   11217             :         return 0;
   11218             : 
   11219             :     tok_priv.PrivilegeCount = 1;
   11220             :     tok_priv.Privileges[0].Luid = luid;
   11221             :     tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   11222             : 
   11223             :     if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv,
   11224             :                                sizeof(TOKEN_PRIVILEGES),
   11225             :                                (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
   11226             :         return 0;
   11227             : 
   11228             :     /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */
   11229             :     return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1;
   11230             : }
   11231             : #endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
   11232             : 
   11233             : static int
   11234           1 : all_ins(PyObject *d)
   11235             : {
   11236             : #ifdef F_OK
   11237           1 :     if (ins(d, "F_OK", (long)F_OK)) return -1;
   11238             : #endif
   11239             : #ifdef R_OK
   11240           1 :     if (ins(d, "R_OK", (long)R_OK)) return -1;
   11241             : #endif
   11242             : #ifdef W_OK
   11243           1 :     if (ins(d, "W_OK", (long)W_OK)) return -1;
   11244             : #endif
   11245             : #ifdef X_OK
   11246           1 :     if (ins(d, "X_OK", (long)X_OK)) return -1;
   11247             : #endif
   11248             : #ifdef NGROUPS_MAX
   11249           1 :     if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
   11250             : #endif
   11251             : #ifdef TMP_MAX
   11252           1 :     if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
   11253             : #endif
   11254             : #ifdef WCONTINUED
   11255           1 :     if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
   11256             : #endif
   11257             : #ifdef WNOHANG
   11258           1 :     if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
   11259             : #endif
   11260             : #ifdef WUNTRACED
   11261           1 :     if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
   11262             : #endif
   11263             : #ifdef O_RDONLY
   11264           1 :     if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
   11265             : #endif
   11266             : #ifdef O_WRONLY
   11267           1 :     if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
   11268             : #endif
   11269             : #ifdef O_RDWR
   11270           1 :     if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
   11271             : #endif
   11272             : #ifdef O_NDELAY
   11273           1 :     if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
   11274             : #endif
   11275             : #ifdef O_NONBLOCK
   11276           1 :     if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
   11277             : #endif
   11278             : #ifdef O_APPEND
   11279           1 :     if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
   11280             : #endif
   11281             : #ifdef O_DSYNC
   11282           1 :     if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
   11283             : #endif
   11284             : #ifdef O_RSYNC
   11285           1 :     if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
   11286             : #endif
   11287             : #ifdef O_SYNC
   11288           1 :     if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
   11289             : #endif
   11290             : #ifdef O_NOCTTY
   11291           1 :     if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
   11292             : #endif
   11293             : #ifdef O_CREAT
   11294           1 :     if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
   11295             : #endif
   11296             : #ifdef O_EXCL
   11297           1 :     if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
   11298             : #endif
   11299             : #ifdef O_TRUNC
   11300           1 :     if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
   11301             : #endif
   11302             : #ifdef O_BINARY
   11303             :     if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
   11304             : #endif
   11305             : #ifdef O_TEXT
   11306             :     if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
   11307             : #endif
   11308             : #ifdef O_XATTR
   11309             :     if (ins(d, "O_XATTR", (long)O_XATTR)) return -1;
   11310             : #endif
   11311             : #ifdef O_LARGEFILE
   11312           1 :     if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
   11313             : #endif
   11314             : #ifdef O_SHLOCK
   11315             :     if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
   11316             : #endif
   11317             : #ifdef O_EXLOCK
   11318             :     if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
   11319             : #endif
   11320             : #ifdef O_EXEC
   11321             :     if (ins(d, "O_EXEC", (long)O_EXEC)) return -1;
   11322             : #endif
   11323             : #ifdef O_SEARCH
   11324             :     if (ins(d, "O_SEARCH", (long)O_SEARCH)) return -1;
   11325             : #endif
   11326             : #ifdef O_TTY_INIT
   11327             :     if (ins(d, "O_TTY_INIT", (long)O_TTY_INIT)) return -1;
   11328             : #endif
   11329             : #ifdef PRIO_PROCESS
   11330           1 :     if (ins(d, "PRIO_PROCESS", (long)PRIO_PROCESS)) return -1;
   11331             : #endif
   11332             : #ifdef PRIO_PGRP
   11333           1 :     if (ins(d, "PRIO_PGRP", (long)PRIO_PGRP)) return -1;
   11334             : #endif
   11335             : #ifdef PRIO_USER
   11336           1 :     if (ins(d, "PRIO_USER", (long)PRIO_USER)) return -1;
   11337             : #endif
   11338             : #ifdef O_CLOEXEC
   11339           1 :     if (ins(d, "O_CLOEXEC", (long)O_CLOEXEC)) return -1;
   11340             : #endif
   11341             : #ifdef O_ACCMODE
   11342           1 :     if (ins(d, "O_ACCMODE", (long)O_ACCMODE)) return -1;
   11343             : #endif
   11344             : 
   11345             : 
   11346             : #ifdef SEEK_HOLE
   11347           1 :     if (ins(d, "SEEK_HOLE", (long)SEEK_HOLE)) return -1;
   11348             : #endif
   11349             : #ifdef SEEK_DATA
   11350           1 :     if (ins(d, "SEEK_DATA", (long)SEEK_DATA)) return -1;
   11351             : #endif
   11352             : 
   11353             : /* MS Windows */
   11354             : #ifdef O_NOINHERIT
   11355             :     /* Don't inherit in child processes. */
   11356             :     if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
   11357             : #endif
   11358             : #ifdef _O_SHORT_LIVED
   11359             :     /* Optimize for short life (keep in memory). */
   11360             :     /* MS forgot to define this one with a non-underscore form too. */
   11361             :     if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
   11362             : #endif
   11363             : #ifdef O_TEMPORARY
   11364             :     /* Automatically delete when last handle is closed. */
   11365             :     if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
   11366             : #endif
   11367             : #ifdef O_RANDOM
   11368             :     /* Optimize for random access. */
   11369             :     if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
   11370             : #endif
   11371             : #ifdef O_SEQUENTIAL
   11372             :     /* Optimize for sequential access. */
   11373             :     if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
   11374             : #endif
   11375             : 
   11376             : /* GNU extensions. */
   11377             : #ifdef O_ASYNC
   11378             :     /* Send a SIGIO signal whenever input or output
   11379             :        becomes available on file descriptor */
   11380           1 :     if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
   11381             : #endif
   11382             : #ifdef O_DIRECT
   11383             :     /* Direct disk access. */
   11384           1 :     if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
   11385             : #endif
   11386             : #ifdef O_DIRECTORY
   11387             :     /* Must be a directory.      */
   11388           1 :     if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
   11389             : #endif
   11390             : #ifdef O_NOFOLLOW
   11391             :     /* Do not follow links.      */
   11392           1 :     if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
   11393             : #endif
   11394             : #ifdef O_NOLINKS
   11395             :     /* Fails if link count of the named file is greater than 1 */
   11396             :     if (ins(d, "O_NOLINKS", (long)O_NOLINKS)) return -1;
   11397             : #endif
   11398             : #ifdef O_NOATIME
   11399             :     /* Do not update the access time. */
   11400           1 :     if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
   11401             : #endif
   11402             : 
   11403             :     /* These come from sysexits.h */
   11404             : #ifdef EX_OK
   11405           1 :     if (ins(d, "EX_OK", (long)EX_OK)) return -1;
   11406             : #endif /* EX_OK */
   11407             : #ifdef EX_USAGE
   11408           1 :     if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
   11409             : #endif /* EX_USAGE */
   11410             : #ifdef EX_DATAERR
   11411           1 :     if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
   11412             : #endif /* EX_DATAERR */
   11413             : #ifdef EX_NOINPUT
   11414           1 :     if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
   11415             : #endif /* EX_NOINPUT */
   11416             : #ifdef EX_NOUSER
   11417           1 :     if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
   11418             : #endif /* EX_NOUSER */
   11419             : #ifdef EX_NOHOST
   11420           1 :     if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
   11421             : #endif /* EX_NOHOST */
   11422             : #ifdef EX_UNAVAILABLE
   11423           1 :     if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
   11424             : #endif /* EX_UNAVAILABLE */
   11425             : #ifdef EX_SOFTWARE
   11426           1 :     if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
   11427             : #endif /* EX_SOFTWARE */
   11428             : #ifdef EX_OSERR
   11429           1 :     if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
   11430             : #endif /* EX_OSERR */
   11431             : #ifdef EX_OSFILE
   11432           1 :     if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
   11433             : #endif /* EX_OSFILE */
   11434             : #ifdef EX_CANTCREAT
   11435           1 :     if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
   11436             : #endif /* EX_CANTCREAT */
   11437             : #ifdef EX_IOERR
   11438           1 :     if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
   11439             : #endif /* EX_IOERR */
   11440             : #ifdef EX_TEMPFAIL
   11441           1 :     if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
   11442             : #endif /* EX_TEMPFAIL */
   11443             : #ifdef EX_PROTOCOL
   11444           1 :     if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
   11445             : #endif /* EX_PROTOCOL */
   11446             : #ifdef EX_NOPERM
   11447           1 :     if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
   11448             : #endif /* EX_NOPERM */
   11449             : #ifdef EX_CONFIG
   11450           1 :     if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
   11451             : #endif /* EX_CONFIG */
   11452             : #ifdef EX_NOTFOUND
   11453             :     if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
   11454             : #endif /* EX_NOTFOUND */
   11455             : 
   11456             :     /* statvfs */
   11457             : #ifdef ST_RDONLY
   11458           1 :     if (ins(d, "ST_RDONLY", (long)ST_RDONLY)) return -1;
   11459             : #endif /* ST_RDONLY */
   11460             : #ifdef ST_NOSUID
   11461           1 :     if (ins(d, "ST_NOSUID", (long)ST_NOSUID)) return -1;
   11462             : #endif /* ST_NOSUID */
   11463             : 
   11464             :     /* FreeBSD sendfile() constants */
   11465             : #ifdef SF_NODISKIO
   11466             :     if (ins(d, "SF_NODISKIO", (long)SF_NODISKIO)) return -1;
   11467             : #endif
   11468             : #ifdef SF_MNOWAIT
   11469             :     if (ins(d, "SF_MNOWAIT", (long)SF_MNOWAIT)) return -1;
   11470             : #endif
   11471             : #ifdef SF_SYNC
   11472             :     if (ins(d, "SF_SYNC", (long)SF_SYNC)) return -1;
   11473             : #endif
   11474             : 
   11475             :     /* constants for posix_fadvise */
   11476             : #ifdef POSIX_FADV_NORMAL
   11477           1 :     if (ins(d, "POSIX_FADV_NORMAL", (long)POSIX_FADV_NORMAL)) return -1;
   11478             : #endif
   11479             : #ifdef POSIX_FADV_SEQUENTIAL
   11480           1 :     if (ins(d, "POSIX_FADV_SEQUENTIAL", (long)POSIX_FADV_SEQUENTIAL)) return -1;
   11481             : #endif
   11482             : #ifdef POSIX_FADV_RANDOM
   11483           1 :     if (ins(d, "POSIX_FADV_RANDOM", (long)POSIX_FADV_RANDOM)) return -1;
   11484             : #endif
   11485             : #ifdef POSIX_FADV_NOREUSE
   11486           1 :     if (ins(d, "POSIX_FADV_NOREUSE", (long)POSIX_FADV_NOREUSE)) return -1;
   11487             : #endif
   11488             : #ifdef POSIX_FADV_WILLNEED
   11489           1 :     if (ins(d, "POSIX_FADV_WILLNEED", (long)POSIX_FADV_WILLNEED)) return -1;
   11490             : #endif
   11491             : #ifdef POSIX_FADV_DONTNEED
   11492           1 :     if (ins(d, "POSIX_FADV_DONTNEED", (long)POSIX_FADV_DONTNEED)) return -1;
   11493             : #endif
   11494             : 
   11495             :     /* constants for waitid */
   11496             : #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
   11497           1 :     if (ins(d, "P_PID", (long)P_PID)) return -1;
   11498           1 :     if (ins(d, "P_PGID", (long)P_PGID)) return -1;
   11499           1 :     if (ins(d, "P_ALL", (long)P_ALL)) return -1;
   11500             : #endif
   11501             : #ifdef WEXITED
   11502           1 :     if (ins(d, "WEXITED", (long)WEXITED)) return -1;
   11503             : #endif
   11504             : #ifdef WNOWAIT
   11505           1 :     if (ins(d, "WNOWAIT", (long)WNOWAIT)) return -1;
   11506             : #endif
   11507             : #ifdef WSTOPPED
   11508           1 :     if (ins(d, "WSTOPPED", (long)WSTOPPED)) return -1;
   11509             : #endif
   11510             : #ifdef CLD_EXITED
   11511           1 :     if (ins(d, "CLD_EXITED", (long)CLD_EXITED)) return -1;
   11512             : #endif
   11513             : #ifdef CLD_DUMPED
   11514           1 :     if (ins(d, "CLD_DUMPED", (long)CLD_DUMPED)) return -1;
   11515             : #endif
   11516             : #ifdef CLD_TRAPPED
   11517           1 :     if (ins(d, "CLD_TRAPPED", (long)CLD_TRAPPED)) return -1;
   11518             : #endif
   11519             : #ifdef CLD_CONTINUED
   11520           1 :     if (ins(d, "CLD_CONTINUED", (long)CLD_CONTINUED)) return -1;
   11521             : #endif
   11522             : 
   11523             :     /* constants for lockf */
   11524             : #ifdef F_LOCK
   11525           1 :     if (ins(d, "F_LOCK", (long)F_LOCK)) return -1;
   11526             : #endif
   11527             : #ifdef F_TLOCK
   11528           1 :     if (ins(d, "F_TLOCK", (long)F_TLOCK)) return -1;
   11529             : #endif
   11530             : #ifdef F_ULOCK
   11531           1 :     if (ins(d, "F_ULOCK", (long)F_ULOCK)) return -1;
   11532             : #endif
   11533             : #ifdef F_TEST
   11534           1 :     if (ins(d, "F_TEST", (long)F_TEST)) return -1;
   11535             : #endif
   11536             : 
   11537             : #ifdef HAVE_SPAWNV
   11538             : #if defined(PYOS_OS2) && defined(PYCC_GCC)
   11539             :     if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
   11540             :     if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
   11541             :     if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
   11542             :     if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
   11543             :     if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
   11544             :     if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
   11545             :     if (ins(d, "P_PM", (long)P_PM)) return -1;
   11546             :     if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
   11547             :     if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
   11548             :     if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
   11549             :     if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
   11550             :     if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
   11551             :     if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
   11552             :     if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
   11553             :     if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
   11554             :     if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
   11555             :     if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
   11556             :     if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
   11557             :     if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
   11558             :     if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
   11559             : #else
   11560             :     if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
   11561             :     if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
   11562             :     if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
   11563             :     if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
   11564             :     if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
   11565             : #endif
   11566             : #endif
   11567             : 
   11568             : #ifdef HAVE_SCHED_H
   11569           1 :     if (ins(d, "SCHED_OTHER", (long)SCHED_OTHER)) return -1;
   11570           1 :     if (ins(d, "SCHED_FIFO", (long)SCHED_FIFO)) return -1;
   11571           1 :     if (ins(d, "SCHED_RR", (long)SCHED_RR)) return -1;
   11572             : #ifdef SCHED_SPORADIC
   11573             :     if (ins(d, "SCHED_SPORADIC", (long)SCHED_SPORADIC) return -1;
   11574             : #endif
   11575             : #ifdef SCHED_BATCH
   11576           1 :     if (ins(d, "SCHED_BATCH", (long)SCHED_BATCH)) return -1;
   11577             : #endif
   11578             : #ifdef SCHED_IDLE
   11579           1 :     if (ins(d, "SCHED_IDLE", (long)SCHED_IDLE)) return -1;
   11580             : #endif
   11581             : #ifdef SCHED_RESET_ON_FORK
   11582           1 :     if (ins(d, "SCHED_RESET_ON_FORK", (long)SCHED_RESET_ON_FORK)) return -1;
   11583             : #endif
   11584             : #ifdef SCHED_SYS
   11585             :     if (ins(d, "SCHED_SYS", (long)SCHED_SYS)) return -1;
   11586             : #endif
   11587             : #ifdef SCHED_IA
   11588             :     if (ins(d, "SCHED_IA", (long)SCHED_IA)) return -1;
   11589             : #endif
   11590             : #ifdef SCHED_FSS
   11591             :     if (ins(d, "SCHED_FSS", (long)SCHED_FSS)) return -1;
   11592             : #endif
   11593             : #ifdef SCHED_FX
   11594             :     if (ins(d, "SCHED_FX", (long)SCHED_FSS)) return -1;
   11595             : #endif
   11596             : #endif
   11597             : 
   11598             : #ifdef USE_XATTRS
   11599           1 :     if (ins(d, "XATTR_CREATE", (long)XATTR_CREATE)) return -1;
   11600           1 :     if (ins(d, "XATTR_REPLACE", (long)XATTR_REPLACE)) return -1;
   11601           1 :     if (ins(d, "XATTR_SIZE_MAX", (long)XATTR_SIZE_MAX)) return -1;
   11602             : #endif
   11603             : 
   11604             : #ifdef RTLD_LAZY
   11605           1 :     if (PyModule_AddIntMacro(d, RTLD_LAZY)) return -1;
   11606             : #endif
   11607             : #ifdef RTLD_NOW
   11608           1 :     if (PyModule_AddIntMacro(d, RTLD_NOW)) return -1;
   11609             : #endif
   11610             : #ifdef RTLD_GLOBAL
   11611           1 :     if (PyModule_AddIntMacro(d, RTLD_GLOBAL)) return -1;
   11612             : #endif
   11613             : #ifdef RTLD_LOCAL
   11614           1 :     if (PyModule_AddIntMacro(d, RTLD_LOCAL)) return -1;
   11615             : #endif
   11616             : #ifdef RTLD_NODELETE
   11617           1 :     if (PyModule_AddIntMacro(d, RTLD_NODELETE)) return -1;
   11618             : #endif
   11619             : #ifdef RTLD_NOLOAD
   11620           1 :     if (PyModule_AddIntMacro(d, RTLD_NOLOAD)) return -1;
   11621             : #endif
   11622             : #ifdef RTLD_DEEPBIND
   11623           1 :     if (PyModule_AddIntMacro(d, RTLD_DEEPBIND)) return -1;
   11624             : #endif
   11625             : 
   11626             : #if defined(PYOS_OS2)
   11627             :     if (insertvalues(d)) return -1;
   11628             : #endif
   11629           1 :     return 0;
   11630             : }
   11631             : 
   11632             : 
   11633             : #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
   11634             : #define INITFUNC PyInit_nt
   11635             : #define MODNAME "nt"
   11636             : 
   11637             : #elif defined(PYOS_OS2)
   11638             : #define INITFUNC PyInit_os2
   11639             : #define MODNAME "os2"
   11640             : 
   11641             : #else
   11642             : #define INITFUNC PyInit_posix
   11643             : #define MODNAME "posix"
   11644             : #endif
   11645             : 
   11646             : static struct PyModuleDef posixmodule = {
   11647             :     PyModuleDef_HEAD_INIT,
   11648             :     MODNAME,
   11649             :     posix__doc__,
   11650             :     -1,
   11651             :     posix_methods,
   11652             :     NULL,
   11653             :     NULL,
   11654             :     NULL,
   11655             :     NULL
   11656             : };
   11657             : 
   11658             : 
   11659             : static char *have_functions[] = {
   11660             : 
   11661             : #ifdef HAVE_FACCESSAT
   11662             :     "HAVE_FACCESSAT",
   11663             : #endif
   11664             : 
   11665             : #ifdef HAVE_FCHDIR
   11666             :     "HAVE_FCHDIR",
   11667             : #endif
   11668             : 
   11669             : #ifdef HAVE_FCHMOD
   11670             :     "HAVE_FCHMOD",
   11671             : #endif
   11672             : 
   11673             : #ifdef HAVE_FCHMODAT
   11674             :     "HAVE_FCHMODAT",
   11675             : #endif
   11676             : 
   11677             : #ifdef HAVE_FCHOWN
   11678             :     "HAVE_FCHOWN",
   11679             : #endif
   11680             : 
   11681             : #ifdef HAVE_FEXECVE
   11682             :     "HAVE_FEXECVE",
   11683             : #endif
   11684             : 
   11685             : #ifdef HAVE_FDOPENDIR
   11686             :     "HAVE_FDOPENDIR",
   11687             : #endif
   11688             : 
   11689             : #ifdef HAVE_FPATHCONF
   11690             :     "HAVE_FPATHCONF",
   11691             : #endif
   11692             : 
   11693             : #ifdef HAVE_FSTATAT
   11694             :     "HAVE_FSTATAT",
   11695             : #endif
   11696             : 
   11697             : #ifdef HAVE_FSTATVFS
   11698             :     "HAVE_FSTATVFS",
   11699             : #endif
   11700             : 
   11701             : #ifdef HAVE_FTRUNCATE
   11702             :     "HAVE_FTRUNCATE",
   11703             : #endif
   11704             : 
   11705             : #ifdef HAVE_FUTIMENS
   11706             :     "HAVE_FUTIMENS",
   11707             : #endif
   11708             : 
   11709             : #ifdef HAVE_FUTIMES
   11710             :     "HAVE_FUTIMES",
   11711             : #endif
   11712             : 
   11713             : #ifdef HAVE_FUTIMESAT
   11714             :     "HAVE_FUTIMESAT",
   11715             : #endif
   11716             : 
   11717             : #ifdef HAVE_LINKAT
   11718             :     "HAVE_LINKAT",
   11719             : #endif
   11720             : 
   11721             : #ifdef HAVE_LCHFLAGS
   11722             :     "HAVE_LCHFLAGS",
   11723             : #endif
   11724             : 
   11725             : #ifdef HAVE_LCHMOD
   11726             :     "HAVE_LCHMOD",
   11727             : #endif
   11728             : 
   11729             : #ifdef HAVE_LCHOWN
   11730             :     "HAVE_LCHOWN",
   11731             : #endif
   11732             : 
   11733             : #ifdef HAVE_LSTAT
   11734             :     "HAVE_LSTAT",
   11735             : #endif
   11736             : 
   11737             : #ifdef HAVE_LUTIMES
   11738             :     "HAVE_LUTIMES",
   11739             : #endif
   11740             : 
   11741             : #ifdef HAVE_MKDIRAT
   11742             :     "HAVE_MKDIRAT",
   11743             : #endif
   11744             : 
   11745             : #ifdef HAVE_MKFIFOAT
   11746             :     "HAVE_MKFIFOAT",
   11747             : #endif
   11748             : 
   11749             : #ifdef HAVE_MKNODAT
   11750             :     "HAVE_MKNODAT",
   11751             : #endif
   11752             : 
   11753             : #ifdef HAVE_OPENAT
   11754             :     "HAVE_OPENAT",
   11755             : #endif
   11756             : 
   11757             : #ifdef HAVE_READLINKAT
   11758             :     "HAVE_READLINKAT",
   11759             : #endif
   11760             : 
   11761             : #ifdef HAVE_RENAMEAT
   11762             :     "HAVE_RENAMEAT",
   11763             : #endif
   11764             : 
   11765             : #ifdef HAVE_SYMLINKAT
   11766             :     "HAVE_SYMLINKAT",
   11767             : #endif
   11768             : 
   11769             : #ifdef HAVE_UNLINKAT
   11770             :     "HAVE_UNLINKAT",
   11771             : #endif
   11772             : 
   11773             : #ifdef HAVE_UTIMENSAT
   11774             :     "HAVE_UTIMENSAT",
   11775             : #endif
   11776             : 
   11777             : #ifdef MS_WINDOWS
   11778             :     "MS_WINDOWS",
   11779             : #endif
   11780             : 
   11781             :     NULL
   11782             : };
   11783             : 
   11784             : 
   11785             : PyMODINIT_FUNC
   11786           1 : INITFUNC(void)
   11787             : {
   11788             :     PyObject *m, *v;
   11789             :     PyObject *list;
   11790             :     char **trace;
   11791             : 
   11792             : #if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
   11793             :     win32_can_symlink = enable_symlink();
   11794             : #endif
   11795             : 
   11796           1 :     m = PyModule_Create(&posixmodule);
   11797           1 :     if (m == NULL)
   11798           0 :         return NULL;
   11799             : 
   11800             :     /* Initialize environ dictionary */
   11801           1 :     v = convertenviron();
   11802           1 :     Py_XINCREF(v);
   11803           1 :     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
   11804           0 :         return NULL;
   11805           1 :     Py_DECREF(v);
   11806             : 
   11807           1 :     if (all_ins(m))
   11808           0 :         return NULL;
   11809             : 
   11810           1 :     if (setup_confname_tables(m))
   11811           0 :         return NULL;
   11812             : 
   11813           1 :     Py_INCREF(PyExc_OSError);
   11814           1 :     PyModule_AddObject(m, "error", PyExc_OSError);
   11815             : 
   11816             : #ifdef HAVE_PUTENV
   11817           1 :     if (posix_putenv_garbage == NULL)
   11818           1 :         posix_putenv_garbage = PyDict_New();
   11819             : #endif
   11820             : 
   11821           1 :     if (!initialized) {
   11822             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
   11823           1 :         waitid_result_desc.name = MODNAME ".waitid_result";
   11824           1 :         PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc);
   11825             : #endif
   11826             : 
   11827           1 :         stat_result_desc.name = MODNAME ".stat_result";
   11828           1 :         stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
   11829           1 :         stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
   11830           1 :         stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
   11831           1 :         PyStructSequence_InitType(&StatResultType, &stat_result_desc);
   11832           1 :         structseq_new = StatResultType.tp_new;
   11833           1 :         StatResultType.tp_new = statresult_new;
   11834             : 
   11835           1 :         statvfs_result_desc.name = MODNAME ".statvfs_result";
   11836           1 :         PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
   11837             : #ifdef NEED_TICKS_PER_SECOND
   11838             : #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
   11839           1 :         ticks_per_second = sysconf(_SC_CLK_TCK);
   11840             : #  elif defined(HZ)
   11841             :         ticks_per_second = HZ;
   11842             : #  else
   11843             :         ticks_per_second = 60; /* magic fallback value; may be bogus */
   11844             : #  endif
   11845             : #endif
   11846             : 
   11847             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
   11848           1 :         sched_param_desc.name = MODNAME ".sched_param";
   11849           1 :         PyStructSequence_InitType(&SchedParamType, &sched_param_desc);
   11850           1 :         SchedParamType.tp_new = sched_param_new;
   11851             : #endif
   11852             : 
   11853             :         /* initialize TerminalSize_info */
   11854           1 :         PyStructSequence_InitType(&TerminalSizeType, &TerminalSize_desc);
   11855             :     }
   11856             : #if defined(HAVE_WAITID) && !defined(__APPLE__)
   11857           1 :     Py_INCREF((PyObject*) &WaitidResultType);
   11858           1 :     PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType);
   11859             : #endif
   11860           1 :     Py_INCREF((PyObject*) &StatResultType);
   11861           1 :     PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
   11862           1 :     Py_INCREF((PyObject*) &StatVFSResultType);
   11863           1 :     PyModule_AddObject(m, "statvfs_result",
   11864             :                        (PyObject*) &StatVFSResultType);
   11865             : 
   11866             : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
   11867           1 :     Py_INCREF(&SchedParamType);
   11868           1 :     PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType);
   11869             : #endif
   11870             : 
   11871           1 :     times_result_desc.name = MODNAME ".times_result";
   11872           1 :     PyStructSequence_InitType(&TimesResultType, &times_result_desc);
   11873           1 :     PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType);
   11874             : 
   11875           1 :     uname_result_desc.name = MODNAME ".uname_result";
   11876           1 :     PyStructSequence_InitType(&UnameResultType, &uname_result_desc);
   11877           1 :     PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType);
   11878             : 
   11879             : #ifdef __APPLE__
   11880             :     /*
   11881             :      * Step 2 of weak-linking support on Mac OS X.
   11882             :      *
   11883             :      * The code below removes functions that are not available on the
   11884             :      * currently active platform.
   11885             :      *
   11886             :      * This block allow one to use a python binary that was build on
   11887             :      * OSX 10.4 on OSX 10.3, without losing access to new APIs on
   11888             :      * OSX 10.4.
   11889             :      */
   11890             : #ifdef HAVE_FSTATVFS
   11891             :     if (fstatvfs == NULL) {
   11892             :         if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
   11893             :             return NULL;
   11894             :         }
   11895             :     }
   11896             : #endif /* HAVE_FSTATVFS */
   11897             : 
   11898             : #ifdef HAVE_STATVFS
   11899             :     if (statvfs == NULL) {
   11900             :         if (PyObject_DelAttrString(m, "statvfs") == -1) {
   11901             :             return NULL;
   11902             :         }
   11903             :     }
   11904             : #endif /* HAVE_STATVFS */
   11905             : 
   11906             : # ifdef HAVE_LCHOWN
   11907             :     if (lchown == NULL) {
   11908             :         if (PyObject_DelAttrString(m, "lchown") == -1) {
   11909             :             return NULL;
   11910             :         }
   11911             :     }
   11912             : #endif /* HAVE_LCHOWN */
   11913             : 
   11914             : 
   11915             : #endif /* __APPLE__ */
   11916             : 
   11917           1 :     Py_INCREF(&TerminalSizeType);
   11918           1 :     PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType);
   11919             : 
   11920           1 :     billion = PyLong_FromLong(1000000000);
   11921           1 :     if (!billion)
   11922           0 :         return NULL;
   11923             : 
   11924             :     /* suppress "function not used" warnings */
   11925             :     {
   11926             :     int ignored;
   11927           1 :     fd_specified("", -1);
   11928           1 :     follow_symlinks_specified("", 1);
   11929           1 :     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
   11930           1 :     dir_fd_converter(Py_None, &ignored);
   11931           1 :     dir_fd_unavailable(Py_None, &ignored);
   11932             :     }
   11933             : 
   11934             :     /*
   11935             :      * provide list of locally available functions
   11936             :      * so os.py can populate support_* lists
   11937             :      */
   11938           1 :     list = PyList_New(0);
   11939           1 :     if (!list)
   11940           0 :         return NULL;
   11941          28 :     for (trace = have_functions; *trace; trace++) {
   11942          27 :         PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
   11943          27 :         if (!unicode)
   11944           0 :             return NULL;
   11945          27 :         if (PyList_Append(list, unicode))
   11946           0 :             return NULL;
   11947          27 :         Py_DECREF(unicode);
   11948             :     }
   11949           1 :     PyModule_AddObject(m, "_have_functions", list);
   11950             : 
   11951           1 :     initialized = 1;
   11952             : 
   11953           1 :     return m;
   11954             : 
   11955             : }
   11956             : 
   11957             : #ifdef __cplusplus
   11958             : }
   11959             : #endif

Generated by: LCOV version 1.10