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