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