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