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