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