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