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