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