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