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