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