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
44extern "C" {
45#endif
46
47PyDoc_STRVAR(posix__doc__,
48"This module provides access to operating system functionality that is\n\
49standardized by the C Standard and the POSIX standard (a thinly\n\
50disguised Unix interface).  Refer to the library manual and\n\
51corresponding 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!
198module 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) */
207extern char        *ctermid_r(char *);
208#endif
209
210#ifndef HAVE_UNISTD_H
211#if defined(PYCC_VACPP)
212extern int mkdir(char *);
213#else
214#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
215extern int mkdir(const char *);
216#else
217extern int mkdir(const char *, mode_t);
218#endif
219#endif
220#if defined(__IBMC__) || defined(__IBMCPP__)
221extern int chdir(char *);
222extern int rmdir(char *);
223#else
224extern int chdir(const char *);
225extern int rmdir(const char *);
226#endif
227extern int chmod(const char *, mode_t);
228/*#ifdef HAVE_FCHMOD
229extern int fchmod(int, mode_t);
230#endif*/
231/*#ifdef HAVE_LCHMOD
232extern int lchmod(const char *, mode_t);
233#endif*/
234extern int chown(const char *, uid_t, gid_t);
235extern char *getcwd(char *, int);
236extern char *strerror(int);
237extern int link(const char *, const char *);
238extern int rename(const char *, const char *);
239extern int stat(const char *, struct stat *);
240extern int unlink(const char *);
241#ifdef HAVE_SYMLINK
242extern int symlink(const char *, const char *);
243#endif /* HAVE_SYMLINK */
244#ifdef HAVE_LSTAT
245extern 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
323static 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 */
403PyAPI_FUNC(void) _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
404PyAPI_FUNC(void) _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
405                                            ULONG, struct _Py_stat_struct *);
406#endif
407
408#ifdef MS_WINDOWS
409static int
410win32_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
421PyObject *
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
429PyObject *
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
437int
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
523success:
524    Py_DECREF(index);
525    *(uid_t *)p = uid;
526    return 1;
527
528underflow:
529    PyErr_SetString(PyExc_OverflowError,
530                    "uid is less than minimum");
531    goto fail;
532
533overflow:
534    PyErr_SetString(PyExc_OverflowError,
535                    "uid is greater than maximum");
536    /* fallthrough */
537
538fail:
539    Py_DECREF(index);
540    return 0;
541}
542
543int
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
630success:
631    Py_DECREF(index);
632    *(gid_t *)p = gid;
633    return 1;
634
635underflow:
636    PyErr_SetString(PyExc_OverflowError,
637                    "gid is less than minimum");
638    goto fail;
639
640overflow:
641    PyErr_SetString(PyExc_OverflowError,
642                    "gid is greater than maximum");
643    /* fallthrough */
644
645fail:
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)
656static 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
680static 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
710static int
711dir_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 */
815typedef 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
840static void
841path_cleanup(path_t *path)
842{
843    Py_CLEAR(path->object);
844    Py_CLEAR(path->cleanup);
845}
846
847static int
848path_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
1057static void
1058argument_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
1067static int
1068dir_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
1081static int
1082fd_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
1091static int
1092follow_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
1101static int
1102path_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
1117static int
1118dir_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
1129static int
1130fd_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
1142static int
1143dir_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
1161static int
1162Py_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
1174static PyObject *
1175PyLong_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
1186static int
1187win32_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>
1217static char **environ;
1218#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
1219extern char **environ;
1220#endif /* !_MSC_VER */
1221
1222static PyObject *
1223convertenviron(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
1304static PyObject *
1305posix_error(void)
1306{
1307    return PyErr_SetFromErrno(PyExc_OSError);
1308}
1309
1310#ifdef MS_WINDOWS
1311static PyObject *
1312win32_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
1326static PyObject *
1327win32_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
1342static PyObject *
1343path_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
1353static PyObject *
1354path_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
1364static PyObject *
1365path_error(path_t *path)
1366{
1367    return path_object_error(path->object);
1368}
1369
1370static PyObject *
1371path_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
1379static int
1380fildes_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
1391static PyObject *
1392posix_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>: */
1416static BOOL __stdcall
1417win32_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
1462static void
1463find_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
1481static BOOL
1482attributes_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
1494static BOOL
1495get_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
1532static int
1533win32_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
1624static int
1625win32_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
1644static int
1645win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
1646{
1647    return win32_xstat(path, result, FALSE);
1648}
1649
1650static int
1651win32_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
1658PyDoc_STRVAR(stat_result__doc__,
1659"stat_result: Result from stat, fstat, or lstat.\n\n\
1660This object may be accessed either as a tuple of\n\
1661  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1662or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1663\n\
1664Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1665or st_flags, they are available as attributes only.\n\
1666\n\
1667See os.stat for more information.");
1668
1669static 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
1753static PyStructSequence_Desc stat_result_desc = {
1754    "stat_result", /* name */
1755    stat_result__doc__, /* doc */
1756    stat_result_fields,
1757    10
1758};
1759
1760PyDoc_STRVAR(statvfs_result__doc__,
1761"statvfs_result: Result from statvfs or fstatvfs.\n\n\
1762This object may be accessed either as a tuple of\n\
1763  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1764or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1765\n\
1766See os.statvfs for more information.");
1767
1768static 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
1782static 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__)
1790PyDoc_STRVAR(waitid_result__doc__,
1791"waitid_result: Result from waitid.\n\n\
1792This object may be accessed either as a tuple of\n\
1793  (si_pid, si_uid, si_signo, si_status, si_code),\n\
1794or via the attributes si_pid, si_uid, and so on.\n\
1795\n\
1796See os.waitid for more information.");
1797
1798static PyStructSequence_Field waitid_result_fields[] = {
1799    {"si_pid",  },
1800    {"si_uid", },
1801    {"si_signo", },
1802    {"si_status",  },
1803    {"si_code", },
1804    {0}
1805};
1806
1807static PyStructSequence_Desc waitid_result_desc = {
1808    "waitid_result", /* name */
1809    waitid_result__doc__, /* doc */
1810    waitid_result_fields,
1811    5
1812};
1813static PyTypeObject WaitidResultType;
1814#endif
1815
1816static int initialized;
1817static PyTypeObject StatResultType;
1818static PyTypeObject StatVFSResultType;
1819#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
1820static PyTypeObject SchedParamType;
1821#endif
1822static newfunc structseq_new;
1823
1824static PyObject *
1825statresult_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. */
1849static int _stat_float_times = 1;
1850
1851PyDoc_STRVAR(stat_float_times__doc__,
1852"stat_float_times([newval]) -> oldval\n\n\
1853Determine whether os.[lf]stat represents time stamps as float objects.\n\
1854\n\
1855If value is True, future calls to stat() return floats; if it is False,\n\
1856future calls return ints.\n\
1857If 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 */
1860static PyObject*
1861stat_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
1878static PyObject *billion = NULL;
1879
1880static void
1881fill_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;
1916exit:
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()) */
1926static 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
2035static PyObject *
2036posix_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
2086for s in """
2087
2088FACCESSAT
2089FCHMODAT
2090FCHOWNAT
2091FSTATAT
2092LINKAT
2093MKDIRAT
2094MKFIFOAT
2095MKNODAT
2096OPENAT
2097READLINKAT
2098SYMLINKAT
2099UNLINKAT
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
2111for s in """
2112
2113FCHDIR
2114FCHMOD
2115FCHOWN
2116FDOPENDIR
2117FEXECVE
2118FPATHCONF
2119FSTATVFS
2120FTRUNCATE
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
2262class 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
2300class 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
2311class fildes_converter(CConverter):
2312    type = 'int'
2313    converter = 'fildes_converter'
2314
2315class uid_t_converter(CConverter):
2316    type = "uid_t"
2317    converter = '_Py_Uid_Converter'
2318
2319class gid_t_converter(CConverter):
2320    type = "gid_t"
2321    converter = '_Py_Gid_Converter'
2322
2323class dev_t_converter(CConverter):
2324    type = 'dev_t'
2325    converter = '_Py_Dev_Converter'
2326
2327class dev_t_return_converter(unsigned_long_return_converter):
2328    type = 'dev_t'
2329    conversion_fn = '_PyLong_FromDev'
2330    unsigned_cast = '(dev_t)'
2331
2332class 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
2343class pid_t_converter(CConverter):
2344    type = 'pid_t'
2345    format_unit = '" _Py_PARSE_PID "'
2346
2347class idtype_t_converter(int_converter):
2348    type = 'idtype_t'
2349
2350class id_t_converter(CConverter):
2351    type = 'id_t'
2352    format_unit = '" _Py_PARSE_PID "'
2353
2354class intptr_t_converter(CConverter):
2355    type = 'intptr_t'
2356    format_unit = '" _Py_PARSE_INTPTR "'
2357
2358class Py_off_t_converter(CConverter):
2359    type = 'Py_off_t'
2360    converter = 'Py_off_t_converter'
2361
2362class Py_off_t_return_converter(long_return_converter):
2363    type = 'Py_off_t'
2364    conversion_fn = 'PyLong_FromPy_off_t'
2365
2366class path_confname_converter(CConverter):
2367    type="int"
2368    converter="conv_path_confname"
2369
2370class confstr_confname_converter(path_confname_converter):
2371    converter='conv_confstr_confname'
2372
2373class sysconf_confname_converter(path_confname_converter):
2374    converter="conv_sysconf_confname"
2375
2376class 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
2386os.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
2404Perform a stat system call on the given path.
2405
2406dir_fd and follow_symlinks may not be implemented
2407  on your platform.  If they are unavailable, using them will raise a
2408  NotImplementedError.
2409
2410It'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
2415static PyObject *
2416os_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]
2424os.lstat
2425
2426    path : path_t
2427
2428    *
2429
2430    dir_fd : dir_fd(requires='fstatat') = None
2431
2432Perform a stat system call on the given path, without following symbolic links.
2433
2434Like stat(), but do not follow symbolic links.
2435Equivalent to stat(path, follow_symlinks=False).
2436[clinic start generated code]*/
2437
2438static PyObject *
2439os_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]
2448os.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
2473Use the real uid/gid to test for access to a path.
2474
2475{parameters}
2476dir_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
2480Note 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
2486static int
2487os_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]
2566os.ttyname -> DecodeFSDefault
2567
2568    fd: int
2569        Integer file descriptor handle.
2570
2571    /
2572
2573Return the name of the terminal device connected to 'fd'.
2574[clinic start generated code]*/
2575
2576static char *
2577os_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]
2591os.ctermid
2592
2593Return the name of the controlling terminal for this process.
2594[clinic start generated code]*/
2595
2596static PyObject *
2597os_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]
2616os.chdir
2617
2618    path: path_t(allow_fd='PATH_HAVE_FCHDIR')
2619
2620Change the current working directory to the specified path.
2621
2622path may always be specified as a string.
2623On 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
2627static PyObject *
2628os_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]
2657os.fchdir
2658
2659    fd: fildes
2660
2661Change to the directory of the given file descriptor.
2662
2663fd must be opened on a directory, not a file.
2664Equivalent to os.chdir(fd).
2665
2666[clinic start generated code]*/
2667
2668static PyObject *
2669os_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]
2678os.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
2700Change the access permissions of a file.
2701
2702It is an error to use dir_fd or follow_symlinks when specifying path as
2703  an open file descriptor.
2704dir_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
2709static PyObject *
2710os_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]
2807os.fchmod
2808
2809    fd: int
2810    mode: int
2811
2812Change the access permissions of the file given by file descriptor fd.
2813
2814Equivalent to os.chmod(fd, mode).
2815[clinic start generated code]*/
2816
2817static PyObject *
2818os_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]
2839os.lchmod
2840
2841    path: path_t
2842    mode: int
2843
2844Change the access permissions of a file, without following symbolic links.
2845
2846If path is a symlink, this affects the link itself rather than the target.
2847Equivalent to chmod(path, mode, follow_symlinks=False)."
2848[clinic start generated code]*/
2849
2850static PyObject *
2851os_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]
2869os.chflags
2870
2871    path: path_t
2872    flags: unsigned_long(bitwise=True)
2873    follow_symlinks: bool=True
2874
2875Set file flags.
2876
2877If 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.
2880follow_symlinks may not be implemented on your platform.  If it is
2881unavailable, using it will raise a NotImplementedError.
2882
2883[clinic start generated code]*/
2884
2885static PyObject *
2886os_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]
2916os.lchflags
2917
2918    path: path_t
2919    flags: unsigned_long(bitwise=True)
2920
2921Set file flags.
2922
2923This function will not follow symbolic links.
2924Equivalent to chflags(path, flags, follow_symlinks=False).
2925[clinic start generated code]*/
2926
2927static PyObject *
2928os_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]
2945os.chroot
2946    path: path_t
2947
2948Change root directory to path.
2949
2950[clinic start generated code]*/
2951
2952static PyObject *
2953os_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]
2969os.fsync
2970
2971    fd: fildes
2972
2973Force write of fd to disk.
2974[clinic start generated code]*/
2975
2976static PyObject *
2977os_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]
2987os.sync
2988
2989Force write of everything to disk.
2990[clinic start generated code]*/
2991
2992static PyObject *
2993os_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
3006extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3007#endif
3008
3009/*[clinic input]
3010os.fdatasync
3011
3012    fd: fildes
3013
3014Force write of fd to disk without forcing update of metadata.
3015[clinic start generated code]*/
3016
3017static PyObject *
3018os_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]
3028os.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
3049Change the owner and group id of path to the numeric uid and gid.\
3050
3051path may always be specified as a string.
3052On some platforms, path may also be specified as an open file descriptor.
3053  If this functionality is unavailable, using it raises an exception.
3054If 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.
3056If 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.
3059It is an error to use dir_fd or follow_symlinks when specifying path as
3060  an open file descriptor.
3061dir_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
3066static PyObject *
3067os_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]
3124os.fchown
3125
3126    fd: int
3127    uid: uid_t
3128    gid: gid_t
3129
3130Change the owner and group id of the file specified by file descriptor.
3131
3132Equivalent to os.chown(fd, uid, gid).
3133
3134[clinic start generated code]*/
3135
3136static PyObject *
3137os_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]
3158os.lchown
3159
3160    path : path_t
3161    uid: uid_t
3162    gid: gid_t
3163
3164Change the owner and group id of path to the numeric uid and gid.
3165
3166This function will not follow symbolic links.
3167Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3168[clinic start generated code]*/
3169
3170static PyObject *
3171os_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
3186static PyObject *
3187posix_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]
3270os.getcwd
3271
3272Return a unicode string representing the current working directory.
3273[clinic start generated code]*/
3274
3275static PyObject *
3276os_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]
3284os.getcwdb
3285
3286Return a bytes string representing the current working directory.
3287[clinic start generated code]*/
3288
3289static PyObject *
3290os_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
3304os.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
3313Create a hard link to a file.
3314
3315If 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.
3318If 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.
3321src_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
3326static PyObject *
3327os_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)
3383static 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
3465exit:
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
3481static 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
3573exit:
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]
3590os.listdir
3591
3592    path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
3593
3594Return a list containing the names of the files in the directory.
3595
3596path 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.
3599If path is None, uses the path='.'.
3600On 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
3604The list is in arbitrary order.  It does not include the special
3605entries '.' and '..' even if they are present in the directory.
3606
3607
3608[clinic start generated code]*/
3609
3610static PyObject *
3611os_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]
3624os._getfullpathname
3625
3626    path: path_t
3627    /
3628
3629[clinic start generated code]*/
3630
3631static PyObject *
3632os__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]
3662os._getfinalpathname
3663
3664    path: unicode
3665    /
3666
3667A helper function for samepath on windows.
3668[clinic start generated code]*/
3669
3670static PyObject *
3671os__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]
3724os._isdir
3725
3726    path: path_t
3727    /
3728
3729Return true if the pathname refers to an existing directory.
3730[clinic start generated code]*/
3731
3732static PyObject *
3733os__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]
3753os._getvolumepathname
3754
3755    path: unicode
3756
3757A helper function for ismount on Win32.
3758[clinic start generated code]*/
3759
3760static PyObject *
3761os__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
3798exit:
3799    PyMem_Free(mountpath);
3800    return result;
3801}
3802
3803#endif /* MS_WINDOWS */
3804
3805
3806/*[clinic input]
3807os.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
3819Create a directory.
3820
3821If 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.
3823dir_fd may not be implemented on your platform.
3824  If it is unavailable, using it will raise a NotImplementedError.
3825
3826The mode argument is ignored on Windows.
3827[clinic start generated code]*/
3828
3829static PyObject *
3830os_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]
3870os.nice
3871
3872    increment: int
3873    /
3874
3875Add increment to the priority of process and return the new priority.
3876[clinic start generated code]*/
3877
3878static PyObject *
3879os_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]
3910os.getpriority
3911
3912    which: int
3913    who: int
3914
3915Return program scheduling priority.
3916[clinic start generated code]*/
3917
3918static PyObject *
3919os_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]
3935os.setpriority
3936
3937    which: int
3938    who: int
3939    priority: int
3940
3941Set program scheduling priority.
3942[clinic start generated code]*/
3943
3944static PyObject *
3945os_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
3958static PyObject *
3959internal_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]
4012os.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
4020Rename a file or directory.
4021
4022If 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.
4025src_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
4029static PyObject *
4030os_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]
4039os.replace = os.rename
4040
4041Rename a file or directory, overwriting the destination.
4042
4043If 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.
4046src_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
4050static PyObject *
4051os_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]
4060os.rmdir
4061
4062    path: path_t
4063    *
4064    dir_fd: dir_fd(requires='unlinkat') = None
4065
4066Remove a directory.
4067
4068If 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.
4070dir_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
4074static PyObject *
4075os_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]
4104os.system -> long
4105
4106    command: Py_UNICODE
4107
4108Execute the command in a subshell.
4109[clinic start generated code]*/
4110
4111static long
4112os_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]
4125os.system -> long
4126
4127    command: FSConverter
4128
4129Execute the command in a subshell.
4130[clinic start generated code]*/
4131
4132static long
4133os_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]
4148os.umask
4149
4150    mask: int
4151    /
4152
4153Set the current numeric umask and return the previous umask.
4154[clinic start generated code]*/
4155
4156static PyObject *
4157os_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
4169symlinks can be removed with this function, the same as with
4170Unix symlinks */
4171BOOL 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]
4207os.unlink
4208
4209    path: path_t
4210    *
4211    dir_fd: dir_fd(requires='unlinkat')=None
4212
4213Remove a file (same as remove()).
4214
4215If 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.
4217dir_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
4222static PyObject *
4223os_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]
4252os.remove = os.unlink
4253
4254Remove a file (same as unlink()).
4255
4256If 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.
4258dir_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
4262static PyObject *
4263os_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
4270static 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
4279PyDoc_STRVAR(uname_result__doc__,
4280"uname_result: Result from os.uname().\n\n\
4281This object may be accessed either as a tuple of\n\
4282  (sysname, nodename, release, version, machine),\n\
4283or via the attributes sysname, nodename, release, version, and machine.\n\
4284\n\
4285See os.uname for more information.");
4286
4287static PyStructSequence_Desc uname_result_desc = {
4288    "uname_result", /* name */
4289    uname_result__doc__, /* doc */
4290    uname_result_fields,
4291    5
4292};
4293
4294static PyTypeObject UnameResultType;
4295
4296
4297#ifdef HAVE_UNAME
4298/*[clinic input]
4299os.uname
4300
4301Return an object identifying the current operating system.
4302
4303The object behaves like a named tuple with the following fields:
4304  (sysname, nodename, release, version, machine)
4305
4306[clinic start generated code]*/
4307
4308static PyObject *
4309os_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
4350typedef 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
4413static int
4414utime_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
4439static int
4440utime_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
4462static int
4463utime_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
4478static int
4479utime_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
4498static int
4499split_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;
4514exit:
4515    Py_XDECREF(divmod);
4516    return result;
4517}
4518
4519
4520/*[clinic input]
4521os.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
4532Set the access and modified time of path.
4533
4534path may always be specified as a string.
4535On some platforms, path may also be specified as an open file descriptor.
4536  If this functionality is unavailable, using it raises an exception.
4537
4538If times is not None, it must be a tuple (atime, mtime);
4539    atime and mtime should be expressed as float seconds since the epoch.
4540If 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.
4543If times is None and ns is unspecified, utime uses the current time.
4544Specifying tuples for both times and ns is an error.
4545
4546If 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.
4548If 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.
4551It is an error to use dir_fd or follow_symlinks when specifying path
4552  as an open file descriptor.
4553dir_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
4558static PyObject *
4559os_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
4704exit:
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]
4716os._exit
4717
4718    status: int
4719
4720Exit to the system with specified status, without normal exit processing.
4721[clinic start generated code]*/
4722
4723static PyObject *
4724os__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)
4738static void
4739free_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
4747static int
4748fsconvert_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)
4776static EXECV_CHAR**
4777parse_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
4848error:
4849    Py_XDECREF(keys);
4850    Py_XDECREF(vals);
4851    free_string_array(envlist, envc);
4852    return NULL;
4853}
4854
4855static EXECV_CHAR**
4856parse_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;
4876fail:
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]
4887os.execv
4888
4889    path: path_t
4890        Path of executable file.
4891    argv: object
4892        Tuple or list of strings.
4893    /
4894
4895Execute an executable path with arguments, replacing current process.
4896[clinic start generated code]*/
4897
4898static PyObject *
4899os_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]
4946os.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
4955Execute an executable path with arguments, replacing current process.
4956[clinic start generated code]*/
4957
4958static PyObject *
4959os_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]
5030os.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
5040Execute the program specified by path in a new process.
5041[clinic start generated code]*/
5042
5043static PyObject *
5044os_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]
5121os.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
5133Execute the program specified by path in a new process.
5134[clinic start generated code]*/
5135
5136static PyObject *
5137os_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]
5236os.fork1
5237
5238Fork a child process with a single multiplexed (i.e., not bound) thread.
5239
5240Return 0 to child process and PID of child to parent process.
5241[clinic start generated code]*/
5242
5243static PyObject *
5244os_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]
5273os.fork
5274
5275Fork a child process.
5276
5277Return 0 to child process and PID of child to parent process.
5278[clinic start generated code]*/
5279
5280static PyObject *
5281os_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]
5311os.sched_get_priority_max
5312
5313    policy: int
5314
5315Get the maximum scheduling priority for policy.
5316[clinic start generated code]*/
5317
5318static PyObject *
5319os_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]
5332os.sched_get_priority_min
5333
5334    policy: int
5335
5336Get the minimum scheduling priority for policy.
5337[clinic start generated code]*/
5338
5339static PyObject *
5340os_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]
5353os.sched_getscheduler
5354    pid: pid_t
5355    /
5356
5357Get the scheduling policy for the process identifiedy by pid.
5358
5359Passing 0 for pid returns the scheduling policy for the calling process.
5360[clinic start generated code]*/
5361
5362static PyObject *
5363os_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]
5378class os.sched_param "PyObject *" "&SchedParamType"
5379
5380@classmethod
5381os.sched_param.__new__
5382
5383    sched_priority: object
5384        A scheduling parameter.
5385
5386Current has only one field: sched_priority");
5387[clinic start generated code]*/
5388
5389static PyObject *
5390os_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
5404PyDoc_VAR(os_sched_param__doc__);
5405
5406static PyStructSequence_Field sched_param_fields[] = {
5407    {"sched_priority", "the scheduling priority"},
5408    {0}
5409};
5410
5411static PyStructSequence_Desc sched_param_desc = {
5412    "sched_param", /* name */
5413    os_sched_param__doc__, /* doc */
5414    sched_param_fields,
5415    1
5416};
5417
5418static int
5419convert_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]
5442os.sched_setscheduler
5443
5444    pid: pid_t
5445    policy: int
5446    param: sched_param
5447    /
5448
5449Set the scheduling policy for the process identified by pid.
5450
5451If pid is 0, the calling process is changed.
5452param is an instance of sched_param.
5453[clinic start generated code]*/
5454
5455static PyObject *
5456os_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]
5474os.sched_getparam
5475    pid: pid_t
5476    /
5477
5478Returns scheduling parameters for the process identified by pid.
5479
5480If pid is 0, returns parameters for the calling process.
5481Return value is an instance of sched_param.
5482[clinic start generated code]*/
5483
5484static PyObject *
5485os_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]
5508os.sched_setparam
5509    pid: pid_t
5510    param: sched_param
5511    /
5512
5513Set scheduling parameters for the process identified by pid.
5514
5515If pid is 0, sets parameters for the calling process.
5516param should be an instance of sched_param.
5517[clinic start generated code]*/
5518
5519static PyObject *
5520os_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]
5533os.sched_rr_get_interval -> double
5534    pid: pid_t
5535    /
5536
5537Return the round-robin quantum for the process identified by pid, in seconds.
5538
5539Value returned is a float.
5540[clinic start generated code]*/
5541
5542static double
5543os_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]
5557os.sched_yield
5558
5559Voluntarily relinquish the CPU.
5560[clinic start generated code]*/
5561
5562static PyObject *
5563os_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 */
5573static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
5574
5575/*[clinic input]
5576os.sched_setaffinity
5577    pid: pid_t
5578    mask : object
5579    /
5580
5581Set the CPU affinity of the process identified by pid to mask.
5582
5583mask should be an iterable of integers identifying CPUs.
5584[clinic start generated code]*/
5585
5586static PyObject *
5587os_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
5664error:
5665    if (cpu_set)
5666        CPU_FREE(cpu_set);
5667    Py_XDECREF(iterator);
5668    return NULL;
5669}
5670
5671
5672/*[clinic input]
5673os.sched_getaffinity
5674    pid: pid_t
5675    /
5676
5677Return the affinity of the process identified by pid (or the current process if zero).
5678
5679The affinity is returned as a set of CPU identifiers.
5680[clinic start generated code]*/
5681
5682static PyObject *
5683os_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
5729error:
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]
5770os.openpty
5771
5772Open a pseudo-terminal.
5773
5774Return a tuple of (master_fd, slave_fd) containing open file descriptors
5775for both the master and slave ends.
5776[clinic start generated code]*/
5777
5778static PyObject *
5779os_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
5856posix_error:
5857    posix_error();
5858error:
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]
5870os.forkpty
5871
5872Fork a new process with a new pseudo-terminal as controlling tty.
5873
5874Returns a tuple of (pid, master_fd).
5875Like fork(), return pid of 0 to the child process,
5876and pid of child to the parent process.
5877To both, return fd of newly opened pseudo-terminal.
5878[clinic start generated code]*/
5879
5880static PyObject *
5881os_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]
5911os.getegid
5912
5913Return the current process's effective group id.
5914[clinic start generated code]*/
5915
5916static PyObject *
5917os_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]
5927os.geteuid
5928
5929Return the current process's effective user id.
5930[clinic start generated code]*/
5931
5932static PyObject *
5933os_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]
5943os.getgid
5944
5945Return the current process's group id.
5946[clinic start generated code]*/
5947
5948static PyObject *
5949os_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]
5959os.getpid
5960
5961Return the current process id.
5962[clinic start generated code]*/
5963
5964static PyObject *
5965os_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 */
5975PyDoc_STRVAR(posix_getgrouplist__doc__,
5976"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
5977Returns 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
5981static PyObject *
5982posix_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]
6052os.getgroups
6053
6054Return list of supplemental group IDs for the process.
6055[clinic start generated code]*/
6056
6057static PyObject *
6058os_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
6161PyDoc_STRVAR(posix_initgroups__doc__,
6162"initgroups(username, gid) -> None\n\n\
6163Call the system initgroups() to initialize the group access list with all of\n\
6164the groups of which the specified username is a member, plus the specified\n\
6165group id.");
6166
6167/* AC 3.5: funny apple logic */
6168static PyObject *
6169posix_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]
6205os.getpgid
6206
6207    pid: pid_t
6208
6209Call the system call getpgid(), and return the result.
6210[clinic start generated code]*/
6211
6212static PyObject *
6213os_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]
6226os.getpgrp
6227
6228Return the current process group id.
6229[clinic start generated code]*/
6230
6231static PyObject *
6232os_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]
6246os.setpgrp
6247
6248Make the current process the leader of its process group.
6249[clinic start generated code]*/
6250
6251static PyObject *
6252os_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
6271static PyObject*
6272win32_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]
6312os.getppid
6313
6314Return the parent's process id.
6315
6316If the parent process has already exited, Windows machines will still
6317return its id; others systems will return the id of the 'init' process (1).
6318[clinic start generated code]*/
6319
6320static PyObject *
6321os_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]
6335os.getlogin
6336
6337Return the actual login name.
6338[clinic start generated code]*/
6339
6340static PyObject *
6341os_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]
6378os.getuid
6379
6380Return the current process's user id.
6381[clinic start generated code]*/
6382
6383static PyObject *
6384os_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]
6398os.kill
6399
6400    pid: pid_t
6401    signal: Py_ssize_t
6402    /
6403
6404Kill a process with a signal.
6405[clinic start generated code]*/
6406
6407static PyObject *
6408os_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]
6459os.killpg
6460
6461    pgid: pid_t
6462    signal: int
6463    /
6464
6465Kill a process group with a signal.
6466[clinic start generated code]*/
6467
6468static PyObject *
6469os_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]
6489os.plock
6490    op: int
6491    /
6492
6493Lock program segments into memory.");
6494[clinic start generated code]*/
6495
6496static PyObject *
6497os_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]
6509os.setuid
6510
6511    uid: uid_t
6512    /
6513
6514Set the current process's user id.
6515[clinic start generated code]*/
6516
6517static PyObject *
6518os_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]
6530os.seteuid
6531
6532    euid: uid_t
6533    /
6534
6535Set the current process's effective user id.
6536[clinic start generated code]*/
6537
6538static PyObject *
6539os_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]
6551os.setegid
6552
6553    egid: gid_t
6554    /
6555
6556Set the current process's effective group id.
6557[clinic start generated code]*/
6558
6559static PyObject *
6560os_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]
6572os.setreuid
6573
6574    ruid: uid_t
6575    euid: uid_t
6576    /
6577
6578Set the current process's real and effective user ids.
6579[clinic start generated code]*/
6580
6581static PyObject *
6582os_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]
6597os.setregid
6598
6599    rgid: gid_t
6600    egid: gid_t
6601    /
6602
6603Set the current process's real and effective group ids.
6604[clinic start generated code]*/
6605
6606static PyObject *
6607os_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]
6619os.setgid
6620    gid: gid_t
6621    /
6622
6623Set the current process's group id.
6624[clinic start generated code]*/
6625
6626static PyObject *
6627os_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]
6639os.setgroups
6640
6641    groups: object
6642    /
6643
6644Set the groups of the current process to list.
6645[clinic start generated code]*/
6646
6647static PyObject *
6648os_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)
6690static PyObject *
6691wait_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]
6753os.wait3
6754
6755    options: int
6756Wait for completion of a child process.
6757
6758Returns a tuple of information about the child process:
6759  (pid, status, rusage)
6760[clinic start generated code]*/
6761
6762static PyObject *
6763os_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
6788os.wait4
6789
6790    pid: pid_t
6791    options: int
6792
6793Wait for completion of a specific child process.
6794
6795Returns a tuple of information about the child process:
6796  (pid, status, rusage)
6797[clinic start generated code]*/
6798
6799static PyObject *
6800os_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]
6824os.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
6835Returns the result of waiting for a process or processes.
6836
6837Returns either waitid_result or None if WNOHANG is specified and there are
6838no children in a waitable state.
6839[clinic start generated code]*/
6840
6841static PyObject *
6842os_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]
6883os.waitpid
6884    pid: pid_t
6885    options: int
6886    /
6887
6888Wait for completion of a given child process.
6889
6890Returns a tuple of information regarding the child process:
6891    (pid, status)
6892
6893The options argument is ignored on Windows.
6894[clinic start generated code]*/
6895
6896static PyObject *
6897os_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]
6918os.waitpid
6919    pid: intptr_t
6920    options: int
6921    /
6922
6923Wait for completion of a given process.
6924
6925Returns a tuple of information regarding the process:
6926    (pid, status << 8)
6927
6928The options argument is ignored on Windows.
6929[clinic start generated code]*/
6930
6931static PyObject *
6932os_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]
6957os.wait
6958
6959Wait for completion of a child process.
6960
6961Returns a tuple of information about the child process:
6962    (pid, status)
6963[clinic start generated code]*/
6964
6965static PyObject *
6966os_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)
6988PyDoc_STRVAR(readlink__doc__,
6989"readlink(path, *, dir_fd=None) -> path\n\n\
6990Return a string representing the path to which the symbolic link points.\n\
6991\n\
6992If 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\
6994dir_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 */
7001static PyObject *
7002posix_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);
7037exit:
7038    path_cleanup(&path);
7039    return return_value;
7040}
7041
7042#endif /* HAVE_READLINK */
7043
7044#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
7045
7046static PyObject *
7047win_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 */
7126static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD) = NULL;
7127
7128static int
7129check_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 */
7142static 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? */
7156static 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 */
7164static 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 */
7185static 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]
7206os.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
7215Create a symbolic link pointing to src named dst.
7216
7217target_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
7222If 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.
7224dir_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
7229static PyObject *
7230os_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
7292static 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
7301PyDoc_STRVAR(times_result__doc__,
7302"times_result: Result from os.times().\n\n\
7303This object may be accessed either as a tuple of\n\
7304  (user, system, children_user, children_system, elapsed),\n\
7305or via the attributes user, system, children_user, children_system,\n\
7306and elapsed.\n\
7307\n\
7308See os.times for more information.");
7309
7310static PyStructSequence_Desc times_result_desc = {
7311    "times_result", /* name */
7312    times_result__doc__, /* doc */
7313    times_result_fields,
7314    5
7315};
7316
7317static PyTypeObject TimesResultType;
7318
7319#ifdef MS_WINDOWS
7320#define HAVE_TIMES  /* mandatory, for the method table */
7321#endif
7322
7323#ifdef HAVE_TIMES
7324
7325static PyObject *
7326build_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
7358static long ticks_per_second = -1;
7359#endif /* MS_WINDOWS */
7360
7361/*[clinic input]
7362os.times
7363
7364Return a collection containing process timing information.
7365
7366The object returned behaves like a named tuple with these fields:
7367  (utime, stime, cutime, cstime, elapsed_time)
7368All fields are floating point numbers.
7369[clinic start generated code]*/
7370
7371static PyObject *
7372os_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]
7417os.getsid
7418
7419    pid: pid_t
7420    /
7421
7422Call the system call getsid(pid) and return the result.
7423[clinic start generated code]*/
7424
7425static PyObject *
7426os_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]
7440os.setsid
7441
7442Call the system call setsid().
7443[clinic start generated code]*/
7444
7445static PyObject *
7446os_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]
7458os.setpgid
7459
7460    pid: pid_t
7461    pgrp: pid_t
7462    /
7463
7464Call the system call setpgid(pid, pgrp).
7465[clinic start generated code]*/
7466
7467static PyObject *
7468os_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]
7480os.tcgetpgrp
7481
7482    fd: int
7483    /
7484
7485Return the process group associated with the terminal specified by fd.
7486[clinic start generated code]*/
7487
7488static PyObject *
7489os_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]
7502os.tcsetpgrp
7503
7504    fd: int
7505    pgid: pid_t
7506    /
7507
7508Set the process group associated with the terminal specified by fd.
7509[clinic start generated code]*/
7510
7511static PyObject *
7512os_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
7524extern int _Py_open_cloexec_works;
7525#endif
7526
7527
7528/*[clinic input]
7529os.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
7538Open a file for low level IO.  Returns a file descriptor (integer).
7539
7540If 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.
7542dir_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
7546static int
7547os_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]
7600os.close
7601
7602    fd: int
7603
7604Close a file descriptor.
7605[clinic start generated code]*/
7606
7607static PyObject *
7608os_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]
7628os.closerange
7629
7630    fd_low: int
7631    fd_high: int
7632    /
7633
7634Closes all file descriptors in [fd_low, fd_high), ignoring errors.
7635[clinic start generated code]*/
7636
7637static PyObject *
7638os_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]
7653os.dup -> int
7654
7655    fd: int
7656    /
7657
7658Return a duplicate of a file descriptor.
7659[clinic start generated code]*/
7660
7661static int
7662os_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]
7670os.dup2
7671    fd: int
7672    fd2: int
7673    inheritable: bool=True
7674
7675Duplicate file descriptor.
7676[clinic start generated code]*/
7677
7678static PyObject *
7679os_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]
7761os.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
7771Apply, test or remove a POSIX lock on an open file descriptor.
7772
7773[clinic start generated code]*/
7774
7775static PyObject *
7776os_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]
7794os.lseek -> Py_off_t
7795
7796    fd: int
7797    position: Py_off_t
7798    how: int
7799    /
7800
7801Set the position of a file descriptor.  Return the new position.
7802
7803Return the new cursor position in number of bytes
7804relative to the beginning of the file.
7805[clinic start generated code]*/
7806
7807static Py_off_t
7808os_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]
7842os.read
7843    fd: int
7844    length: Py_ssize_t
7845    /
7846
7847Read from a file descriptor.  Returns a bytes object.
7848[clinic start generated code]*/
7849
7850static PyObject *
7851os_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)
7886static Py_ssize_t
7887iov_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
7921fail:
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
7930static void
7931iov_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]
7945os.readv -> Py_ssize_t
7946
7947    fd: int
7948    buffers: object
7949    /
7950
7951Read from a file descriptor fd into an iterable of buffers.
7952
7953The buffers should be mutable buffers accepting bytes.
7954readv will transfer data into each buffer until it is full
7955and then move on to the next buffer in the sequence to hold
7956the rest of the data.
7957
7958readv returns the total number of bytes read,
7959which may be less than the total capacity of all the buffers.
7960[clinic start generated code]*/
7961
7962static Py_ssize_t
7963os_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.
8004os.pread
8005
8006    fd: int
8007    length: int
8008    offset: Py_off_t
8009    /
8010
8011Read a number of bytes from a file descriptor starting at a particular offset.
8012
8013Read length bytes from file descriptor fd, starting at offset bytes from
8014the beginning of the file.  The file offset remains unchanged.
8015[clinic start generated code]*/
8016
8017static PyObject *
8018os_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]
8053os.write -> Py_ssize_t
8054
8055    fd: int
8056    data: Py_buffer
8057    /
8058
8059Write a bytes object to a file descriptor.
8060[clinic start generated code]*/
8061
8062static Py_ssize_t
8063os_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
8070PyDoc_STRVAR(posix_sendfile__doc__,
8071"sendfile(out, in, offset, count) -> byteswritten\n\
8072sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\
8073            -> byteswritten\n\
8074Copy count bytes from file descriptor in to file descriptor out.");
8075
8076/* AC 3.5: don't bother converting, has optional group*/
8077static PyObject *
8078posix_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
8179done:
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]
8223os.fstat
8224
8225    fd : int
8226
8227Perform a stat system call on the given file descriptor.
8228
8229Like stat(), but for an open file descriptor.
8230Equivalent to os.stat(fd).
8231[clinic start generated code]*/
8232
8233static PyObject *
8234os_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]
8259os.isatty -> bool
8260    fd: int
8261    /
8262
8263Return True if the fd is connected to a terminal.
8264
8265Return True if the file descriptor is an open file descriptor
8266connected to the slave end of a terminal.
8267[clinic start generated code]*/
8268
8269static int
8270os_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]
8283os.pipe
8284
8285Create a pipe.
8286
8287Returns a tuple of two file descriptors:
8288  (read_fd, write_fd)
8289[clinic start generated code]*/
8290
8291static PyObject *
8292os_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]
8366os.pipe2
8367
8368    flags: int
8369    /
8370
8371Create a pipe with flags set atomically.
8372
8373Returns a tuple of two file descriptors:
8374  (read_fd, write_fd)
8375
8376flags can be constructed by ORing together one or more of these values:
8377O_NONBLOCK, O_CLOEXEC.
8378[clinic start generated code]*/
8379
8380static PyObject *
8381os_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]
8397os.writev -> Py_ssize_t
8398    fd: int
8399    buffers: object
8400    /
8401
8402Iterate over buffers, and write the contents of each to a file descriptor.
8403
8404Returns the total number of bytes written.
8405buffers must be a sequence of bytes-like objects.
8406[clinic start generated code]*/
8407
8408static Py_ssize_t
8409os_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]
8446os.pwrite -> Py_ssize_t
8447
8448    fd: int
8449    buffer: Py_buffer
8450    offset: Py_off_t
8451    /
8452
8453Write bytes to a file descriptor starting at a particular offset.
8454
8455Write buffer to fd, starting at offset bytes from the beginning of
8456the file.  Returns the number of bytes writte.  Does not change the
8457current file offset.
8458[clinic start generated code]*/
8459
8460static Py_ssize_t
8461os_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]
8484os.mkfifo
8485
8486    path: path_t
8487    mode: int=0o666
8488    *
8489    dir_fd: dir_fd(requires='mkfifoat')=None
8490
8491Create a "fifo" (a POSIX named pipe).
8492
8493If 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.
8495dir_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
8499static PyObject *
8500os_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]
8527os.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
8535Create a node in the file system.
8536
8537Create a node in the file system (file, device special file or named pipe)
8538at path.  mode specifies both the permissions to use and the
8539type of node to be created, being combined (bitwise OR) with one of
8540S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
8541device defines the newly created device special file (probably using
8542os.makedev()).  Otherwise device is ignored.
8543
8544If 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.
8546dir_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
8550static PyObject *
8551os_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]
8579os.major -> unsigned_int
8580
8581    device: dev_t
8582    /
8583
8584Extracts a device major number from a raw device number.
8585[clinic start generated code]*/
8586
8587static unsigned int
8588os_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]
8596os.minor -> unsigned_int
8597
8598    device: dev_t
8599    /
8600
8601Extracts a device minor number from a raw device number.
8602[clinic start generated code]*/
8603
8604static unsigned int
8605os_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]
8613os.makedev -> dev_t
8614
8615    major: int
8616    minor: int
8617    /
8618
8619Composes a raw device number from the major and minor device numbers.
8620[clinic start generated code]*/
8621
8622static dev_t
8623os_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]
8633os.ftruncate
8634
8635    fd: int
8636    length: Py_off_t
8637    /
8638
8639Truncate a file, specified by file descriptor, to a specific length.
8640[clinic start generated code]*/
8641
8642static PyObject *
8643os_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]
8670os.truncate
8671    path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
8672    length: Py_off_t
8673
8674Truncate a file, specified by path, to a specific length.
8675
8676On 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
8680static PyObject *
8681os_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]
8728os.posix_fallocate
8729
8730    fd: int
8731    offset: Py_off_t
8732    length: Py_off_t
8733    /
8734
8735Ensure a file has allocated at least a particular number of bytes on disk.
8736
8737Ensure that the file specified by fd encompasses a range of bytes
8738starting at offset bytes from the beginning and continuing for length bytes.
8739[clinic start generated code]*/
8740
8741static PyObject *
8742os_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]
8764os.posix_fadvise
8765
8766    fd: int
8767    offset: Py_off_t
8768    length: Py_off_t
8769    advice: int
8770    /
8771
8772Announce an intention to access data in a specific pattern.
8773
8774Announce an intention to access data in a specific pattern, thus allowing
8775the kernel to make optimizations.
8776The advice applies to the region of the file specified by fd starting at
8777offset and continuing for length bytes.
8778advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
8779POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
8780POSIX_FADV_DONTNEED.
8781[clinic start generated code]*/
8782
8783static PyObject *
8784os_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. */
8807static PyObject *posix_putenv_garbage;
8808
8809static void
8810posix_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]
8826os.putenv
8827
8828    name: unicode
8829    value: unicode
8830    /
8831
8832Change or add an environment variable.
8833[clinic start generated code]*/
8834
8835static PyObject *
8836os_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
8864error:
8865    Py_DECREF(unicode);
8866    return NULL;
8867}
8868#else /* MS_WINDOWS */
8869/*[clinic input]
8870os.putenv
8871
8872    name: FSConverter
8873    value: FSConverter
8874    /
8875
8876Change or add an environment variable.
8877[clinic start generated code]*/
8878
8879static PyObject *
8880os_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]
8909os.unsetenv
8910    name: FSConverter
8911    /
8912
8913Delete an environment variable.
8914[clinic start generated code]*/
8915
8916static PyObject *
8917os_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]
8947os.strerror
8948
8949    code: int
8950    /
8951
8952Translate an error code to a message string.
8953[clinic start generated code]*/
8954
8955static PyObject *
8956os_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]
8972os.WCOREDUMP -> bool
8973
8974    status: int
8975    /
8976
8977Return True if the process returning status was dumped to a core file.
8978[clinic start generated code]*/
8979
8980static int
8981os_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]
8993os.WIFCONTINUED -> bool
8994
8995    status: int
8996
8997Return True if a particular process was continued from a job control stop.
8998
8999Return True if the process returning status was continued from a
9000job control stop.
9001[clinic start generated code]*/
9002
9003static int
9004os_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]
9016os.WIFSTOPPED -> bool
9017
9018    status: int
9019
9020Return True if the process returning status was stopped.
9021[clinic start generated code]*/
9022
9023static int
9024os_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]
9036os.WIFSIGNALED -> bool
9037
9038    status: int
9039
9040Return True if the process returning status was terminated by a signal.
9041[clinic start generated code]*/
9042
9043static int
9044os_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]
9056os.WIFEXITED -> bool
9057
9058    status: int
9059
9060Return True if the process returning status exited via the exit() system call.
9061[clinic start generated code]*/
9062
9063static int
9064os_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]
9076os.WEXITSTATUS -> int
9077
9078    status: int
9079
9080Return the process return code from status.
9081[clinic start generated code]*/
9082
9083static int
9084os_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]
9096os.WTERMSIG -> int
9097
9098    status: int
9099
9100Return the signal that terminated the process that provided the status value.
9101[clinic start generated code]*/
9102
9103static int
9104os_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]
9116os.WSTOPSIG -> int
9117
9118    status: int
9119
9120Return the signal that stopped the process that provided the status value.
9121[clinic start generated code]*/
9122
9123static int
9124os_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
9143static 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]
9188os.fstatvfs
9189    fd: int
9190    /
9191
9192Perform an fstatvfs system call on the given fd.
9193
9194Equivalent to statvfs(fd).
9195[clinic start generated code]*/
9196
9197static PyObject *
9198os_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]
9222os.statvfs
9223
9224    path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
9225
9226Perform a statvfs system call on the given path.
9227
9228path may always be specified as a string.
9229On 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
9233static PyObject *
9234os_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]
9268os._getdiskusage
9269
9270    path: Py_UNICODE
9271
9272Return disk usage statistics about the given path as a (total, free) tuple.
9273[clinic start generated code]*/
9274
9275static PyObject *
9276os__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 */
9304struct constdef {
9305    const char *name;
9306    int value;
9307};
9308
9309static int
9310conv_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)
9354static 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
9441static int
9442conv_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]
9453os.fpathconf -> long
9454
9455    fd: int
9456    name: path_confname
9457    /
9458
9459Return the configuration limit name for the file descriptor fd.
9460
9461If there is no limit, return -1.
9462[clinic start generated code]*/
9463
9464static long
9465os_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]
9482os.pathconf -> long
9483    path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
9484    name: path_confname
9485
9486Return the configuration limit name for the file or directory path.
9487
9488If there is no limit, return -1.
9489On 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
9493static long
9494os_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
9519static 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
9672static int
9673conv_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]
9682os.confstr
9683
9684    name: confstr_confname
9685    /
9686
9687Return a string-valued system configuration variable.
9688[clinic start generated code]*/
9689
9690static PyObject *
9691os_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
9728static 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
10223static int
10224conv_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]
10233os.sysconf -> long
10234    name: sysconf_confname
10235    /
10236
10237Return an integer-valued system configuration variable.
10238[clinic start generated code]*/
10239
10240static long
10241os_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
10265static int
10266cmp_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
10276static int
10277setup_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. */
10301static int
10302setup_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]
10330os.abort
10331
10332Abort the interpreter immediately.
10333
10334This function 'dumps core' or otherwise fails in the hardest way possible
10335on the hosting operating system.  This function never returns.
10336[clinic start generated code]*/
10337
10338static PyObject *
10339os_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 */
10350static int has_ShellExecute = -1;
10351static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
10352                                              LPCWSTR, INT);
10353static int
10354check_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]
10376os.startfile
10377    filepath: path_t
10378    operation: Py_UNICODE = NULL
10379
10380startfile(filepath [, operation])
10381
10382Start a file with its associated application.
10383
10384When "operation" is not specified or "open", this acts like
10385double-clicking the file in Explorer, or giving the file name as an
10386argument to the DOS "start" command: the file is opened with whatever
10387application (if any) its extension is associated.
10388When another "operation" is given, it specifies what should be done with
10389the file.  A typical operation is "print".
10390
10391startfile returns as soon as the associated application is launched.
10392There is no option to wait for the application to close, and no way
10393to retrieve the application's exit status.
10394
10395The filepath is relative to the current directory.  If you want to use
10396an absolute path, make sure the first character is not a slash ("/");
10397the underlying Win32 ShellExecute function doesn't work if it is.
10398[clinic start generated code]*/
10399
10400static PyObject *
10401os_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]
10429os.getloadavg
10430
10431Return average recent system load information.
10432
10433Return the number of processes in the system run queue averaged over
10434the last 1, 5, and 15 minutes as a tuple of three floats.
10435Raises OSError if the load average was unobtainable.
10436[clinic start generated code]*/
10437
10438static PyObject *
10439os_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]
10453os.device_encoding
10454    fd: int
10455
10456Return a string describing the encoding of a terminal's file descriptor.
10457
10458The file descriptor must be attached to a terminal.
10459If the device is not a terminal, return None.
10460[clinic start generated code]*/
10461
10462static PyObject *
10463os_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]
10472os.setresuid
10473
10474    ruid: uid_t
10475    euid: uid_t
10476    suid: uid_t
10477    /
10478
10479Set the current process's real, effective, and saved user ids.
10480[clinic start generated code]*/
10481
10482static PyObject *
10483os_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]
10495os.setresgid
10496
10497    rgid: gid_t
10498    egid: gid_t
10499    sgid: gid_t
10500    /
10501
10502Set the current process's real, effective, and saved group ids.
10503[clinic start generated code]*/
10504
10505static PyObject *
10506os_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]
10518os.getresuid
10519
10520Return a tuple of the current process's real, effective, and saved user ids.
10521[clinic start generated code]*/
10522
10523static PyObject *
10524os_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]
10539os.getresgid
10540
10541Return a tuple of the current process's real, effective, and saved group ids.
10542[clinic start generated code]*/
10543
10544static PyObject *
10545os_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]
10560os.getxattr
10561
10562    path: path_t(allow_fd=True)
10563    attribute: path_t
10564    *
10565    follow_symlinks: bool = True
10566
10567Return the value of extended attribute attribute on path.
10568
10569path may be either a string or an open file descriptor.
10570If 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
10576static PyObject *
10577os_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]
10630os.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
10639Set extended attribute attribute on path to value.
10640
10641path may be either a string or an open file descriptor.
10642If 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
10648static PyObject *
10649os_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]
10680os.removexattr
10681
10682    path: path_t(allow_fd=True)
10683    attribute: path_t
10684    *
10685    follow_symlinks: bool = True
10686
10687Remove extended attribute attribute on path.
10688
10689path may be either a string or an open file descriptor.
10690If 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
10696static PyObject *
10697os_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]
10724os.listxattr
10725
10726    path: path_t(allow_fd=True, nullable=True) = None
10727    *
10728    follow_symlinks: bool = True
10729
10730Return a list of extended attributes on path.
10731
10732path may be either None, a string, or an open file descriptor.
10733if path is None, listxattr will examine the current directory.
10734If 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
10739static PyObject *
10740os_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    }
10816exit:
10817    if (buffer)
10818        PyMem_FREE(buffer);
10819    return result;
10820}
10821#endif /* USE_XATTRS */
10822
10823
10824/*[clinic input]
10825os.urandom
10826
10827    size: Py_ssize_t
10828    /
10829
10830Return a bytes object containing random bytes suitable for cryptographic use.
10831[clinic start generated code]*/
10832
10833static PyObject *
10834os_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
10857static PyTypeObject TerminalSizeType;
10858
10859PyDoc_STRVAR(TerminalSize_docstring,
10860    "A tuple of (columns, lines) for holding terminal window size");
10861
10862static 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
10868static 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 */
10877PyDoc_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
10892static PyObject*
10893get_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]
10964os.cpu_count
10965
10966Return the number of CPUs in the system; return None if indeterminable.
10967
10968This number is not equivalent to the number of CPUs the current process can
10969use.  The number of usable CPUs can be obtained with
10970``len(os.sched_getaffinity(0))``
10971[clinic start generated code]*/
10972
10973static PyObject *
10974os_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]
11006os.get_inheritable -> bool
11007
11008    fd: int
11009    /
11010
11011Get the close-on-exe flag of the specified file descriptor.
11012[clinic start generated code]*/
11013
11014static int
11015os_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]
11027os.set_inheritable
11028    fd: int
11029    inheritable: int
11030    /
11031
11032Set the inheritable flag of the specified file descriptor.
11033[clinic start generated code]*/
11034
11035static PyObject *
11036os_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]
11052os.get_handle_inheritable -> bool
11053    handle: intptr_t
11054    /
11055
11056Get the close-on-exe flag of the specified file descriptor.
11057[clinic start generated code]*/
11058
11059static int
11060os_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]
11075os.set_handle_inheritable
11076    handle: intptr_t
11077    inheritable: bool
11078    /
11079
11080Set the inheritable flag of the specified handle.
11081[clinic start generated code]*/
11082
11083static PyObject *
11084os_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
11098PyDoc_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
11104static PyObject*
11105posix_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
11121PyDoc_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
11128static PyObject*
11129posix_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
11146PyDoc_STRVAR(posix_scandir__doc__,
11147"scandir(path='.') -> iterator of DirEntry objects for given path");
11148
11149static char *follow_symlinks_keywords[] = {"follow_symlinks", NULL};
11150
11151typedef 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
11169static void
11170DirEntry_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 */
11180static int
11181DirEntry_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 */
11184static int
11185DirEntry_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
11201static PyObject *
11202DirEntry_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
11212static PyObject *
11213DirEntry_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
11240static PyObject *
11241DirEntry_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
11254static PyObject *
11255DirEntry_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
11274static PyObject *
11275DirEntry_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 */
11287static int
11288DirEntry_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
11359error:
11360    Py_XDECREF(st_mode);
11361    Py_XDECREF(stat);
11362    return -1;
11363}
11364
11365static PyObject *
11366DirEntry_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
11376static PyObject *
11377DirEntry_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
11388static PyObject *
11389DirEntry_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
11400static PyObject *
11401DirEntry_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
11432static PyObject *
11433DirEntry_repr(DirEntry *self)
11434{
11435    return PyUnicode_FromFormat("<DirEntry %R>", self->name);
11436}
11437
11438static PyObject *
11439DirEntry_fspath(DirEntry *self)
11440{
11441    Py_INCREF(self->path);
11442    return self->path;
11443}
11444
11445static 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
11453static 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
11475static 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
11510static wchar_t *
11511join_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
11543static PyObject *
11544DirEntry_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
11588error:
11589    Py_DECREF(entry);
11590    return NULL;
11591}
11592
11593#else /* POSIX */
11594
11595static char *
11596join_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
11627static PyObject *
11628DirEntry_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
11669error:
11670    Py_XDECREF(entry);
11671    return NULL;
11672}
11673
11674#endif
11675
11676
11677typedef 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
11691static int
11692ScandirIterator_is_closed(ScandirIterator *iterator)
11693{
11694    return iterator->handle == INVALID_HANDLE_VALUE;
11695}
11696
11697static void
11698ScandirIterator_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
11711static PyObject *
11712ScandirIterator_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
11755static int
11756ScandirIterator_is_closed(ScandirIterator *iterator)
11757{
11758    return !iterator->dirp;
11759}
11760
11761static void
11762ScandirIterator_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
11776static PyObject *
11777ScandirIterator_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
11827static PyObject *
11828ScandirIterator_close(ScandirIterator *self, PyObject *args)
11829{
11830    ScandirIterator_closedir(self);
11831    Py_RETURN_NONE;
11832}
11833
11834static PyObject *
11835ScandirIterator_enter(PyObject *self, PyObject *args)
11836{
11837    Py_INCREF(self);
11838    return self;
11839}
11840
11841static PyObject *
11842ScandirIterator_exit(ScandirIterator *self, PyObject *args)
11843{
11844    ScandirIterator_closedir(self);
11845    Py_RETURN_NONE;
11846}
11847
11848static void
11849ScandirIterator_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
11874static void
11875ScandirIterator_dealloc(ScandirIterator *iterator)
11876{
11877    if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
11878        return;
11879
11880    Py_TYPE(iterator)->tp_free((PyObject *)iterator);
11881}
11882
11883static 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
11890static 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
11943static PyObject *
11944posix_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
12007error:
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*/
12019PyObject *
12020PyOS_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]
12060os.fspath
12061
12062    path: object
12063
12064Return the file system path representation of the object.
12065
12066If the object is str or bytes, then allow it to pass through as-is. If the
12067object defines __fspath__(), then return the result of that method. All other
12068types raise a TypeError.
12069[clinic start generated code]*/
12070
12071static PyObject *
12072os_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]
12080os.getrandom
12081
12082    size: Py_ssize_t
12083    flags: int=0
12084
12085Obtain a series of random bytes.
12086[clinic start generated code]*/
12087
12088static PyObject *
12089os_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
12133error:
12134    Py_DECREF(bytes);
12135    return NULL;
12136}
12137#endif   /* HAVE_GETRANDOM_SYSCALL */
12138
12139#include "clinic/posixmodule.c.h"
12140
12141/*[clinic input]
12142dump buffer
12143[clinic start generated code]*/
12144/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
12145
12146
12147static 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)
12345static int
12346enable_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
12372static int
12373all_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
12794static 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
12807static 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
12937PyMODINIT_FUNC
12938INITFUNC(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