posixmodule.c revision c9c2c8b034ee9fb61ee8487545e9711ac2bbcf61
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/* See also ../Dos/dosmodule.c */
15
16#ifdef __APPLE__
17   /*
18    * Step 1 of support for weak-linking a number of symbols existing on
19    * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
20    * at the end of this file for more information.
21    */
22#  pragma weak lchown
23#  pragma weak statvfs
24#  pragma weak fstatvfs
25
26#endif /* __APPLE__ */
27
28#define PY_SSIZE_T_CLEAN
29
30#include "Python.h"
31
32#if defined(__VMS)
33#    include <unixio.h>
34#endif /* defined(__VMS) */
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40PyDoc_STRVAR(posix__doc__,
41"This module provides access to operating system functionality that is\n\
42standardized by the C Standard and the POSIX standard (a thinly\n\
43disguised Unix interface).  Refer to the library manual and\n\
44corresponding Unix manual entries for more information on calls.");
45
46
47#if defined(PYOS_OS2)
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_TYPES_H
63#include <sys/types.h>
64#endif /* HAVE_SYS_TYPES_H */
65
66#ifdef HAVE_SYS_STAT_H
67#include <sys/stat.h>
68#endif /* HAVE_SYS_STAT_H */
69
70#ifdef HAVE_SYS_WAIT_H
71#include <sys/wait.h>           /* For WNOHANG */
72#endif
73
74#ifdef HAVE_SIGNAL_H
75#include <signal.h>
76#endif
77
78#ifdef HAVE_FCNTL_H
79#include <fcntl.h>
80#endif /* HAVE_FCNTL_H */
81
82#ifdef HAVE_GRP_H
83#include <grp.h>
84#endif
85
86#ifdef HAVE_SYSEXITS_H
87#include <sysexits.h>
88#endif /* HAVE_SYSEXITS_H */
89
90#ifdef HAVE_SYS_LOADAVG_H
91#include <sys/loadavg.h>
92#endif
93
94#ifdef HAVE_LANGINFO_H
95#include <langinfo.h>
96#endif
97
98#ifdef HAVE_SYS_SENDFILE_H
99#include <sys/sendfile.h>
100#endif
101
102#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
103#ifdef HAVE_SYS_SOCKET_H
104#include <sys/socket.h>
105#endif
106
107#ifdef HAVE_SYS_UIO_H
108#include <sys/uio.h>
109#endif
110#endif
111
112/* Various compilers have only certain posix functions */
113/* XXX Gosh I wish these were all moved into pyconfig.h */
114#if defined(PYCC_VACPP) && defined(PYOS_OS2)
115#include <process.h>
116#else
117#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
118#define HAVE_GETCWD     1
119#define HAVE_OPENDIR    1
120#define HAVE_SYSTEM     1
121#if defined(__OS2__)
122#define HAVE_EXECV      1
123#define HAVE_WAIT       1
124#endif
125#include <process.h>
126#else
127#ifdef __BORLANDC__             /* Borland compiler */
128#define HAVE_EXECV      1
129#define HAVE_GETCWD     1
130#define HAVE_OPENDIR    1
131#define HAVE_PIPE       1
132#define HAVE_SYSTEM     1
133#define HAVE_WAIT       1
134#else
135#ifdef _MSC_VER         /* Microsoft compiler */
136#define HAVE_GETCWD     1
137#define HAVE_GETPPID    1
138#define HAVE_GETLOGIN   1
139#define HAVE_SPAWNV     1
140#define HAVE_EXECV      1
141#define HAVE_PIPE       1
142#define HAVE_SYSTEM     1
143#define HAVE_CWAIT      1
144#define HAVE_FSYNC      1
145#define fsync _commit
146#else
147#if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
148/* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
149#else                   /* all other compilers */
150/* Unix functions that the configure script doesn't check for */
151#define HAVE_EXECV      1
152#define HAVE_FORK       1
153#if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
154#define HAVE_FORK1      1
155#endif
156#define HAVE_GETCWD     1
157#define HAVE_GETEGID    1
158#define HAVE_GETEUID    1
159#define HAVE_GETGID     1
160#define HAVE_GETPPID    1
161#define HAVE_GETUID     1
162#define HAVE_KILL       1
163#define HAVE_OPENDIR    1
164#define HAVE_PIPE       1
165#define HAVE_SYSTEM     1
166#define HAVE_WAIT       1
167#define HAVE_TTYNAME    1
168#endif  /* PYOS_OS2 && PYCC_GCC && __VMS */
169#endif  /* _MSC_VER */
170#endif  /* __BORLANDC__ */
171#endif  /* ! __WATCOMC__ || __QNX__ */
172#endif /* ! __IBMC__ */
173
174#ifndef _MSC_VER
175
176#if defined(__sgi)&&_COMPILER_VERSION>=700
177/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
178   (default) */
179extern char        *ctermid_r(char *);
180#endif
181
182#ifndef HAVE_UNISTD_H
183#if defined(PYCC_VACPP)
184extern int mkdir(char *);
185#else
186#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
187extern int mkdir(const char *);
188#else
189extern int mkdir(const char *, mode_t);
190#endif
191#endif
192#if defined(__IBMC__) || defined(__IBMCPP__)
193extern int chdir(char *);
194extern int rmdir(char *);
195#else
196extern int chdir(const char *);
197extern int rmdir(const char *);
198#endif
199#ifdef __BORLANDC__
200extern int chmod(const char *, int);
201#else
202extern int chmod(const char *, mode_t);
203#endif
204/*#ifdef HAVE_FCHMOD
205extern int fchmod(int, mode_t);
206#endif*/
207/*#ifdef HAVE_LCHMOD
208extern int lchmod(const char *, mode_t);
209#endif*/
210extern int chown(const char *, uid_t, gid_t);
211extern char *getcwd(char *, int);
212extern char *strerror(int);
213extern int link(const char *, const char *);
214extern int rename(const char *, const char *);
215extern int stat(const char *, struct stat *);
216extern int unlink(const char *);
217#ifdef HAVE_SYMLINK
218extern int symlink(const char *, const char *);
219#endif /* HAVE_SYMLINK */
220#ifdef HAVE_LSTAT
221extern int lstat(const char *, struct stat *);
222#endif /* HAVE_LSTAT */
223#endif /* !HAVE_UNISTD_H */
224
225#endif /* !_MSC_VER */
226
227#ifdef HAVE_UTIME_H
228#include <utime.h>
229#endif /* HAVE_UTIME_H */
230
231#ifdef HAVE_SYS_UTIME_H
232#include <sys/utime.h>
233#define HAVE_UTIME_H /* pretend we do for the rest of this file */
234#endif /* HAVE_SYS_UTIME_H */
235
236#ifdef HAVE_SYS_TIMES_H
237#include <sys/times.h>
238#endif /* HAVE_SYS_TIMES_H */
239
240#ifdef HAVE_SYS_PARAM_H
241#include <sys/param.h>
242#endif /* HAVE_SYS_PARAM_H */
243
244#ifdef HAVE_SYS_UTSNAME_H
245#include <sys/utsname.h>
246#endif /* HAVE_SYS_UTSNAME_H */
247
248#ifdef HAVE_DIRENT_H
249#include <dirent.h>
250#define NAMLEN(dirent) strlen((dirent)->d_name)
251#else
252#if defined(__WATCOMC__) && !defined(__QNX__)
253#include <direct.h>
254#define NAMLEN(dirent) strlen((dirent)->d_name)
255#else
256#define dirent direct
257#define NAMLEN(dirent) (dirent)->d_namlen
258#endif
259#ifdef HAVE_SYS_NDIR_H
260#include <sys/ndir.h>
261#endif
262#ifdef HAVE_SYS_DIR_H
263#include <sys/dir.h>
264#endif
265#ifdef HAVE_NDIR_H
266#include <ndir.h>
267#endif
268#endif
269
270#ifdef _MSC_VER
271#ifdef HAVE_DIRECT_H
272#include <direct.h>
273#endif
274#ifdef HAVE_IO_H
275#include <io.h>
276#endif
277#ifdef HAVE_PROCESS_H
278#include <process.h>
279#endif
280#ifndef VOLUME_NAME_DOS
281#define VOLUME_NAME_DOS 0x0
282#endif
283#ifndef VOLUME_NAME_NT
284#define VOLUME_NAME_NT  0x2
285#endif
286#ifndef IO_REPARSE_TAG_SYMLINK
287#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
288#endif
289#include "osdefs.h"
290#include <malloc.h>
291#include <windows.h>
292#include <shellapi.h>   /* for ShellExecute() */
293#include <lmcons.h>     /* for UNLEN */
294#ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */
295#define HAVE_SYMLINK
296static int win32_can_symlink = 0;
297#endif
298#endif /* _MSC_VER */
299
300#if defined(PYCC_VACPP) && defined(PYOS_OS2)
301#include <io.h>
302#endif /* OS2 */
303
304#ifndef MAXPATHLEN
305#if defined(PATH_MAX) && PATH_MAX > 1024
306#define MAXPATHLEN PATH_MAX
307#else
308#define MAXPATHLEN 1024
309#endif
310#endif /* MAXPATHLEN */
311
312#ifdef UNION_WAIT
313/* Emulate some macros on systems that have a union instead of macros */
314
315#ifndef WIFEXITED
316#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
317#endif
318
319#ifndef WEXITSTATUS
320#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
321#endif
322
323#ifndef WTERMSIG
324#define WTERMSIG(u_wait) ((u_wait).w_termsig)
325#endif
326
327#define WAIT_TYPE union wait
328#define WAIT_STATUS_INT(s) (s.w_status)
329
330#else /* !UNION_WAIT */
331#define WAIT_TYPE int
332#define WAIT_STATUS_INT(s) (s)
333#endif /* UNION_WAIT */
334
335/* Don't use the "_r" form if we don't need it (also, won't have a
336   prototype for it, at least on Solaris -- maybe others as well?). */
337#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
338#define USE_CTERMID_R
339#endif
340
341/* choose the appropriate stat and fstat functions and return structs */
342#undef STAT
343#undef FSTAT
344#undef STRUCT_STAT
345#if defined(MS_WIN64) || defined(MS_WINDOWS)
346#       define STAT win32_stat
347#       define FSTAT win32_fstat
348#       define STRUCT_STAT struct win32_stat
349#else
350#       define STAT stat
351#       define FSTAT fstat
352#       define STRUCT_STAT struct stat
353#endif
354
355#if defined(MAJOR_IN_MKDEV)
356#include <sys/mkdev.h>
357#else
358#if defined(MAJOR_IN_SYSMACROS)
359#include <sys/sysmacros.h>
360#endif
361#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
362#include <sys/mkdev.h>
363#endif
364#endif
365
366int
367PyParse_off_t(PyObject* arg, void* addr)
368{
369#if !defined(HAVE_LARGEFILE_SUPPORT)
370    *((off_t*)addr) = PyLong_AsLong(arg);
371#else
372    *((off_t*)addr) = PyLong_Check(arg) ? PyLong_AsLongLong(arg)
373            : PyLong_AsLong(arg);
374#endif
375    if (PyErr_Occurred())
376        return 0;
377    return 1;
378}
379
380#if defined _MSC_VER && _MSC_VER >= 1400
381/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
382 * valid and throw an assertion if it isn't.
383 * Normally, an invalid fd is likely to be a C program error and therefore
384 * an assertion can be useful, but it does contradict the POSIX standard
385 * which for write(2) states:
386 *    "Otherwise, -1 shall be returned and errno set to indicate the error."
387 *    "[EBADF] The fildes argument is not a valid file descriptor open for
388 *     writing."
389 * Furthermore, python allows the user to enter any old integer
390 * as a fd and should merely raise a python exception on error.
391 * The Microsoft CRT doesn't provide an official way to check for the
392 * validity of a file descriptor, but we can emulate its internal behaviour
393 * by using the exported __pinfo data member and knowledge of the
394 * internal structures involved.
395 * The structures below must be updated for each version of visual studio
396 * according to the file internal.h in the CRT source, until MS comes
397 * up with a less hacky way to do this.
398 * (all of this is to avoid globally modifying the CRT behaviour using
399 * _set_invalid_parameter_handler() and _CrtSetReportMode())
400 */
401/* The actual size of the structure is determined at runtime.
402 * Only the first items must be present.
403 */
404typedef struct {
405    intptr_t osfhnd;
406    char osfile;
407} my_ioinfo;
408
409extern __declspec(dllimport) char * __pioinfo[];
410#define IOINFO_L2E 5
411#define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
412#define IOINFO_ARRAYS 64
413#define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
414#define FOPEN 0x01
415#define _NO_CONSOLE_FILENO (intptr_t)-2
416
417/* This function emulates what the windows CRT does to validate file handles */
418int
419_PyVerify_fd(int fd)
420{
421    const int i1 = fd >> IOINFO_L2E;
422    const int i2 = fd & ((1 << IOINFO_L2E) - 1);
423
424    static size_t sizeof_ioinfo = 0;
425
426    /* Determine the actual size of the ioinfo structure,
427     * as used by the CRT loaded in memory
428     */
429    if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
430        sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
431    }
432    if (sizeof_ioinfo == 0) {
433        /* This should not happen... */
434        goto fail;
435    }
436
437    /* See that it isn't a special CLEAR fileno */
438    if (fd != _NO_CONSOLE_FILENO) {
439        /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that.  Instead
440         * we check pointer validity and other info
441         */
442        if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
443            /* finally, check that the file is open */
444            my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
445            if (info->osfile & FOPEN) {
446                return 1;
447            }
448        }
449    }
450  fail:
451    errno = EBADF;
452    return 0;
453}
454
455/* the special case of checking dup2.  The target fd must be in a sensible range */
456static int
457_PyVerify_fd_dup2(int fd1, int fd2)
458{
459    if (!_PyVerify_fd(fd1))
460        return 0;
461    if (fd2 == _NO_CONSOLE_FILENO)
462        return 0;
463    if ((unsigned)fd2 < _NHANDLE_)
464        return 1;
465    else
466        return 0;
467}
468#else
469/* dummy version. _PyVerify_fd() is already defined in fileobject.h */
470#define _PyVerify_fd_dup2(A, B) (1)
471#endif
472
473#ifdef MS_WINDOWS
474/* The following structure was copied from
475   http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
476   include doesn't seem to be present in the Windows SDK (at least as included
477   with Visual Studio Express). */
478typedef struct _REPARSE_DATA_BUFFER {
479    ULONG ReparseTag;
480    USHORT ReparseDataLength;
481    USHORT Reserved;
482    union {
483        struct {
484            USHORT SubstituteNameOffset;
485            USHORT SubstituteNameLength;
486            USHORT PrintNameOffset;
487            USHORT PrintNameLength;
488            ULONG Flags;
489            WCHAR PathBuffer[1];
490        } SymbolicLinkReparseBuffer;
491
492        struct {
493            USHORT SubstituteNameOffset;
494            USHORT  SubstituteNameLength;
495            USHORT  PrintNameOffset;
496            USHORT  PrintNameLength;
497            WCHAR  PathBuffer[1];
498        } MountPointReparseBuffer;
499
500        struct {
501            UCHAR  DataBuffer[1];
502        } GenericReparseBuffer;
503    };
504} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
505
506#define REPARSE_DATA_BUFFER_HEADER_SIZE  FIELD_OFFSET(REPARSE_DATA_BUFFER,\
507                                                      GenericReparseBuffer)
508#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE  ( 16 * 1024 )
509
510static int
511win32_read_link(HANDLE reparse_point_handle, ULONG *reparse_tag, wchar_t **target_path)
512{
513    char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
514    REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
515    DWORD n_bytes_returned;
516    const wchar_t *ptr;
517    wchar_t *buf;
518    size_t len;
519
520    if (0 == DeviceIoControl(
521        reparse_point_handle,
522        FSCTL_GET_REPARSE_POINT,
523        NULL, 0, /* in buffer */
524        target_buffer, sizeof(target_buffer),
525        &n_bytes_returned,
526        NULL)) /* we're not using OVERLAPPED_IO */
527        return -1;
528
529    if (reparse_tag)
530        *reparse_tag = rdb->ReparseTag;
531
532    if (target_path) {
533        switch (rdb->ReparseTag) {
534        case IO_REPARSE_TAG_SYMLINK:
535            /* XXX: Maybe should use SubstituteName? */
536            ptr = rdb->SymbolicLinkReparseBuffer.PathBuffer +
537                  rdb->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
538            len = rdb->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(WCHAR);
539            break;
540        case IO_REPARSE_TAG_MOUNT_POINT:
541            ptr = rdb->MountPointReparseBuffer.PathBuffer +
542                  rdb->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR);
543            len = rdb->MountPointReparseBuffer.SubstituteNameLength/sizeof(WCHAR);
544            break;
545        default:
546            SetLastError(ERROR_REPARSE_TAG_MISMATCH); /* XXX: Proper error code? */
547            return -1;
548        }
549        buf = (wchar_t *)malloc(sizeof(wchar_t)*(len+1));
550        if (!buf) {
551            SetLastError(ERROR_OUTOFMEMORY);
552            return -1;
553        }
554        wcsncpy(buf, ptr, len);
555        buf[len] = L'\0';
556        if (wcsncmp(buf, L"\\??\\", 4) == 0)
557            buf[1] = L'\\';
558        *target_path = buf;
559    }
560
561    return 0;
562}
563#endif /* MS_WINDOWS */
564
565/* Return a dictionary corresponding to the POSIX environment table */
566#ifdef WITH_NEXT_FRAMEWORK
567/* On Darwin/MacOSX a shared library or framework has no access to
568** environ directly, we must obtain it with _NSGetEnviron().
569*/
570#include <crt_externs.h>
571static char **environ;
572#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
573extern char **environ;
574#endif /* !_MSC_VER */
575
576static PyObject *
577convertenviron(void)
578{
579    PyObject *d;
580#ifdef MS_WINDOWS
581    wchar_t **e;
582#else
583    char **e;
584#endif
585#if defined(PYOS_OS2)
586    APIRET rc;
587    char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
588#endif
589
590    d = PyDict_New();
591    if (d == NULL)
592        return NULL;
593#ifdef WITH_NEXT_FRAMEWORK
594    if (environ == NULL)
595        environ = *_NSGetEnviron();
596#endif
597#ifdef MS_WINDOWS
598    /* _wenviron must be initialized in this way if the program is started
599       through main() instead of wmain(). */
600    _wgetenv(L"");
601    if (_wenviron == NULL)
602        return d;
603    /* This part ignores errors */
604    for (e = _wenviron; *e != NULL; e++) {
605        PyObject *k;
606        PyObject *v;
607        wchar_t *p = wcschr(*e, L'=');
608        if (p == NULL)
609            continue;
610        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
611        if (k == NULL) {
612            PyErr_Clear();
613            continue;
614        }
615        v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
616        if (v == NULL) {
617            PyErr_Clear();
618            Py_DECREF(k);
619            continue;
620        }
621        if (PyDict_GetItem(d, k) == NULL) {
622            if (PyDict_SetItem(d, k, v) != 0)
623                PyErr_Clear();
624        }
625        Py_DECREF(k);
626        Py_DECREF(v);
627    }
628#else
629    if (environ == NULL)
630        return d;
631    /* This part ignores errors */
632    for (e = environ; *e != NULL; e++) {
633        PyObject *k;
634        PyObject *v;
635        char *p = strchr(*e, '=');
636        if (p == NULL)
637            continue;
638        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
639        if (k == NULL) {
640            PyErr_Clear();
641            continue;
642        }
643        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
644        if (v == NULL) {
645            PyErr_Clear();
646            Py_DECREF(k);
647            continue;
648        }
649        if (PyDict_GetItem(d, k) == NULL) {
650            if (PyDict_SetItem(d, k, v) != 0)
651                PyErr_Clear();
652        }
653        Py_DECREF(k);
654        Py_DECREF(v);
655    }
656#endif
657#if defined(PYOS_OS2)
658    rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
659    if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
660        PyObject *v = PyBytes_FromString(buffer);
661        PyDict_SetItemString(d, "BEGINLIBPATH", v);
662        Py_DECREF(v);
663    }
664    rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
665    if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
666        PyObject *v = PyBytes_FromString(buffer);
667        PyDict_SetItemString(d, "ENDLIBPATH", v);
668        Py_DECREF(v);
669    }
670#endif
671    return d;
672}
673
674/* Set a POSIX-specific error from errno, and return NULL */
675
676static PyObject *
677posix_error(void)
678{
679    return PyErr_SetFromErrno(PyExc_OSError);
680}
681static PyObject *
682posix_error_with_filename(char* name)
683{
684    return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
685}
686
687
688static PyObject *
689posix_error_with_allocated_filename(PyObject* name)
690{
691    PyObject *name_str, *rc;
692    name_str = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AsString(name),
693                                                PyBytes_GET_SIZE(name));
694    Py_DECREF(name);
695    rc = PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
696                                              name_str);
697    Py_XDECREF(name_str);
698    return rc;
699}
700
701#ifdef MS_WINDOWS
702static PyObject *
703win32_error(char* function, const char* filename)
704{
705    /* XXX We should pass the function name along in the future.
706       (winreg.c also wants to pass the function name.)
707       This would however require an additional param to the
708       Windows error object, which is non-trivial.
709    */
710    errno = GetLastError();
711    if (filename)
712        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
713    else
714        return PyErr_SetFromWindowsErr(errno);
715}
716
717static PyObject *
718win32_error_unicode(char* function, Py_UNICODE* filename)
719{
720    /* XXX - see win32_error for comments on 'function' */
721    errno = GetLastError();
722    if (filename)
723        return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, 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_FromUnicode(PyUnicode_AS_UNICODE(*param),
737                                       PyUnicode_GET_SIZE(*param));
738    else
739        *param = PyUnicode_FromEncodedObject(*param,
740                                             Py_FileSystemDefaultEncoding,
741                                             "strict");
742    return (*param) != NULL;
743}
744
745#endif /* MS_WINDOWS */
746
747#if defined(PYOS_OS2)
748/**********************************************************************
749 *         Helper Function to Trim and Format OS/2 Messages
750 **********************************************************************/
751static void
752os2_formatmsg(char *msgbuf, int msglen, char *reason)
753{
754    msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
755
756    if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
757        char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
758
759        while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
760            *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
761    }
762
763    /* Add Optional Reason Text */
764    if (reason) {
765        strcat(msgbuf, " : ");
766        strcat(msgbuf, reason);
767    }
768}
769
770/**********************************************************************
771 *             Decode an OS/2 Operating System Error Code
772 *
773 * A convenience function to lookup an OS/2 error code and return a
774 * text message we can use to raise a Python exception.
775 *
776 * Notes:
777 *   The messages for errors returned from the OS/2 kernel reside in
778 *   the file OSO001.MSG in the \OS2 directory hierarchy.
779 *
780 **********************************************************************/
781static char *
782os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
783{
784    APIRET rc;
785    ULONG  msglen;
786
787    /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
788    Py_BEGIN_ALLOW_THREADS
789    rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
790                       errorcode, "oso001.msg", &msglen);
791    Py_END_ALLOW_THREADS
792
793    if (rc == NO_ERROR)
794        os2_formatmsg(msgbuf, msglen, reason);
795    else
796        PyOS_snprintf(msgbuf, msgbuflen,
797                      "unknown OS error #%d", errorcode);
798
799    return msgbuf;
800}
801
802/* Set an OS/2-specific error and return NULL.  OS/2 kernel
803   errors are not in a global variable e.g. 'errno' nor are
804   they congruent with posix error numbers. */
805
806static PyObject *
807os2_error(int code)
808{
809    char text[1024];
810    PyObject *v;
811
812    os2_strerror(text, sizeof(text), code, "");
813
814    v = Py_BuildValue("(is)", code, text);
815    if (v != NULL) {
816        PyErr_SetObject(PyExc_OSError, v);
817        Py_DECREF(v);
818    }
819    return NULL; /* Signal to Python that an Exception is Pending */
820}
821
822#endif /* OS2 */
823
824/* POSIX generic methods */
825
826static PyObject *
827posix_fildes(PyObject *fdobj, int (*func)(int))
828{
829    int fd;
830    int res;
831    fd = PyObject_AsFileDescriptor(fdobj);
832    if (fd < 0)
833        return NULL;
834    if (!_PyVerify_fd(fd))
835        return posix_error();
836    Py_BEGIN_ALLOW_THREADS
837    res = (*func)(fd);
838    Py_END_ALLOW_THREADS
839    if (res < 0)
840        return posix_error();
841    Py_INCREF(Py_None);
842    return Py_None;
843}
844
845static PyObject *
846posix_1str(PyObject *args, char *format, int (*func)(const char*))
847{
848    PyObject *opath1 = NULL;
849    char *path1;
850    int res;
851    if (!PyArg_ParseTuple(args, format,
852                          PyUnicode_FSConverter, &opath1))
853        return NULL;
854    path1 = PyBytes_AsString(opath1);
855    Py_BEGIN_ALLOW_THREADS
856    res = (*func)(path1);
857    Py_END_ALLOW_THREADS
858    if (res < 0)
859        return posix_error_with_allocated_filename(opath1);
860    Py_DECREF(opath1);
861    Py_INCREF(Py_None);
862    return Py_None;
863}
864
865static PyObject *
866posix_2str(PyObject *args,
867           char *format,
868           int (*func)(const char *, const char *))
869{
870    PyObject *opath1 = NULL, *opath2 = NULL;
871    char *path1, *path2;
872    int res;
873    if (!PyArg_ParseTuple(args, format,
874                          PyUnicode_FSConverter, &opath1,
875                          PyUnicode_FSConverter, &opath2)) {
876        return NULL;
877    }
878    path1 = PyBytes_AsString(opath1);
879    path2 = PyBytes_AsString(opath2);
880    Py_BEGIN_ALLOW_THREADS
881    res = (*func)(path1, path2);
882    Py_END_ALLOW_THREADS
883    Py_DECREF(opath1);
884    Py_DECREF(opath2);
885    if (res != 0)
886        /* XXX how to report both path1 and path2??? */
887        return posix_error();
888    Py_INCREF(Py_None);
889    return Py_None;
890}
891
892#ifdef MS_WINDOWS
893static PyObject*
894win32_1str(PyObject* args, char* func,
895           char* format, BOOL (__stdcall *funcA)(LPCSTR),
896           char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
897{
898    PyObject *uni;
899    char *ansi;
900    BOOL result;
901
902    if (!PyArg_ParseTuple(args, wformat, &uni))
903        PyErr_Clear();
904    else {
905        Py_BEGIN_ALLOW_THREADS
906        result = funcW(PyUnicode_AsUnicode(uni));
907        Py_END_ALLOW_THREADS
908        if (!result)
909            return win32_error_unicode(func, PyUnicode_AsUnicode(uni));
910        Py_INCREF(Py_None);
911        return Py_None;
912    }
913    if (!PyArg_ParseTuple(args, format, &ansi))
914        return NULL;
915    Py_BEGIN_ALLOW_THREADS
916    result = funcA(ansi);
917    Py_END_ALLOW_THREADS
918    if (!result)
919        return win32_error(func, ansi);
920    Py_INCREF(Py_None);
921    return Py_None;
922
923}
924
925/* This is a reimplementation of the C library's chdir function,
926   but one that produces Win32 errors instead of DOS error codes.
927   chdir is essentially a wrapper around SetCurrentDirectory; however,
928   it also needs to set "magic" environment variables indicating
929   the per-drive current directory, which are of the form =<drive>: */
930static BOOL __stdcall
931win32_chdir(LPCSTR path)
932{
933    char new_path[MAX_PATH+1];
934    int result;
935    char env[4] = "=x:";
936
937    if(!SetCurrentDirectoryA(path))
938        return FALSE;
939    result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
940    if (!result)
941        return FALSE;
942    /* In the ANSI API, there should not be any paths longer
943       than MAX_PATH. */
944    assert(result <= MAX_PATH+1);
945    if (strncmp(new_path, "\\\\", 2) == 0 ||
946        strncmp(new_path, "//", 2) == 0)
947        /* UNC path, nothing to do. */
948        return TRUE;
949    env[1] = new_path[0];
950    return SetEnvironmentVariableA(env, new_path);
951}
952
953/* The Unicode version differs from the ANSI version
954   since the current directory might exceed MAX_PATH characters */
955static BOOL __stdcall
956win32_wchdir(LPCWSTR path)
957{
958    wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
959    int result;
960    wchar_t env[4] = L"=x:";
961
962    if(!SetCurrentDirectoryW(path))
963        return FALSE;
964    result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
965    if (!result)
966        return FALSE;
967    if (result > MAX_PATH+1) {
968        new_path = malloc(result * sizeof(wchar_t));
969        if (!new_path) {
970            SetLastError(ERROR_OUTOFMEMORY);
971            return FALSE;
972        }
973        result = GetCurrentDirectoryW(result, new_path);
974        if (!result) {
975            free(new_path);
976            return FALSE;
977        }
978    }
979    if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
980        wcsncmp(new_path, L"//", 2) == 0)
981        /* UNC path, nothing to do. */
982        return TRUE;
983    env[1] = new_path[0];
984    result = SetEnvironmentVariableW(env, new_path);
985    if (new_path != _new_path)
986        free(new_path);
987    return result;
988}
989#endif
990
991#ifdef MS_WINDOWS
992/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
993   - time stamps are restricted to second resolution
994   - file modification times suffer from forth-and-back conversions between
995     UTC and local time
996   Therefore, we implement our own stat, based on the Win32 API directly.
997*/
998#define HAVE_STAT_NSEC 1
999
1000struct win32_stat{
1001    int st_dev;
1002    __int64 st_ino;
1003    unsigned short st_mode;
1004    int st_nlink;
1005    int st_uid;
1006    int st_gid;
1007    int st_rdev;
1008    __int64 st_size;
1009    time_t st_atime;
1010    int st_atime_nsec;
1011    time_t st_mtime;
1012    int st_mtime_nsec;
1013    time_t st_ctime;
1014    int st_ctime_nsec;
1015};
1016
1017static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
1018
1019static void
1020FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
1021{
1022    /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
1023    /* Cannot simply cast and dereference in_ptr,
1024       since it might not be aligned properly */
1025    __int64 in;
1026    memcpy(&in, in_ptr, sizeof(in));
1027    *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
1028    *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
1029}
1030
1031static void
1032time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
1033{
1034    /* XXX endianness */
1035    __int64 out;
1036    out = time_in + secs_between_epochs;
1037    out = out * 10000000 + nsec_in / 100;
1038    memcpy(out_ptr, &out, sizeof(out));
1039}
1040
1041/* Below, we *know* that ugo+r is 0444 */
1042#if _S_IREAD != 0400
1043#error Unsupported C library
1044#endif
1045static int
1046attributes_to_mode(DWORD attr)
1047{
1048    int m = 0;
1049    if (attr & FILE_ATTRIBUTE_DIRECTORY)
1050        m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
1051    else
1052        m |= _S_IFREG;
1053    if (attr & FILE_ATTRIBUTE_READONLY)
1054        m |= 0444;
1055    else
1056        m |= 0666;
1057    return m;
1058}
1059
1060static int
1061attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct win32_stat *result)
1062{
1063    memset(result, 0, sizeof(*result));
1064    result->st_mode = attributes_to_mode(info->dwFileAttributes);
1065    result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
1066    FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
1067    FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1068    FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
1069    result->st_nlink = info->nNumberOfLinks;
1070    result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
1071    if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
1072        /* first clear the S_IFMT bits */
1073        result->st_mode ^= (result->st_mode & 0170000);
1074        /* now set the bits that make this a symlink */
1075        result->st_mode |= 0120000;
1076    }
1077
1078    return 0;
1079}
1080
1081static BOOL
1082attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1083{
1084    HANDLE hFindFile;
1085    WIN32_FIND_DATAA FileData;
1086    hFindFile = FindFirstFileA(pszFile, &FileData);
1087    if (hFindFile == INVALID_HANDLE_VALUE)
1088        return FALSE;
1089    FindClose(hFindFile);
1090    memset(info, 0, sizeof(*info));
1091    *reparse_tag = 0;
1092    info->dwFileAttributes = FileData.dwFileAttributes;
1093    info->ftCreationTime   = FileData.ftCreationTime;
1094    info->ftLastAccessTime = FileData.ftLastAccessTime;
1095    info->ftLastWriteTime  = FileData.ftLastWriteTime;
1096    info->nFileSizeHigh    = FileData.nFileSizeHigh;
1097    info->nFileSizeLow     = FileData.nFileSizeLow;
1098/*  info->nNumberOfLinks   = 1; */
1099    if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1100        *reparse_tag = FileData.dwReserved0;
1101    return TRUE;
1102}
1103
1104static BOOL
1105attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1106{
1107    HANDLE hFindFile;
1108    WIN32_FIND_DATAW FileData;
1109    hFindFile = FindFirstFileW(pszFile, &FileData);
1110    if (hFindFile == INVALID_HANDLE_VALUE)
1111        return FALSE;
1112    FindClose(hFindFile);
1113    memset(info, 0, sizeof(*info));
1114    *reparse_tag = 0;
1115    info->dwFileAttributes = FileData.dwFileAttributes;
1116    info->ftCreationTime   = FileData.ftCreationTime;
1117    info->ftLastAccessTime = FileData.ftLastAccessTime;
1118    info->ftLastWriteTime  = FileData.ftLastWriteTime;
1119    info->nFileSizeHigh    = FileData.nFileSizeHigh;
1120    info->nFileSizeLow     = FileData.nFileSizeLow;
1121/*  info->nNumberOfLinks   = 1; */
1122    if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1123        *reparse_tag = FileData.dwReserved0;
1124    return TRUE;
1125}
1126
1127#ifndef SYMLOOP_MAX
1128#define SYMLOOP_MAX ( 88 )
1129#endif
1130
1131static int
1132win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result, BOOL traverse, int depth);
1133
1134static int
1135win32_xstat_impl(const char *path, struct win32_stat *result, BOOL traverse, int depth)
1136{
1137    int code;
1138    HANDLE hFile;
1139    BY_HANDLE_FILE_INFORMATION info;
1140    ULONG reparse_tag = 0;
1141    wchar_t *target_path;
1142    const char *dot;
1143
1144    if (depth > SYMLOOP_MAX) {
1145        SetLastError(ERROR_CANT_RESOLVE_FILENAME); /* XXX: ELOOP? */
1146        return -1;
1147    }
1148
1149    hFile = CreateFileA(
1150        path,
1151        0, /* desired access */
1152        0, /* share mode */
1153        NULL, /* security attributes */
1154        OPEN_EXISTING,
1155        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1156        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,
1157        NULL);
1158
1159    if (hFile == INVALID_HANDLE_VALUE) {
1160        /* Either the target doesn't exist, or we don't have access to
1161           get a handle to it. If the former, we need to return an error.
1162           If the latter, we can use attributes_from_dir. */
1163        if (GetLastError() != ERROR_SHARING_VIOLATION)
1164            return -1;
1165        /* Could not get attributes on open file. Fall back to
1166           reading the directory. */
1167        if (!attributes_from_dir(path, &info, &reparse_tag))
1168            /* Very strange. This should not fail now */
1169            return -1;
1170        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1171            if (traverse) {
1172                /* Should traverse, but could not open reparse point handle */
1173                SetLastError(ERROR_SHARING_VIOLATION);
1174                return -1;
1175            }
1176        }
1177    } else {
1178        if (!GetFileInformationByHandle(hFile, &info)) {
1179            CloseHandle(hFile);
1180            return -1;;
1181        }
1182        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1183            code = win32_read_link(hFile, &reparse_tag, traverse ? &target_path : NULL);
1184            CloseHandle(hFile);
1185            if (code < 0)
1186                return code;
1187            if (traverse) {
1188                code = win32_xstat_impl_w(target_path, result, traverse, depth + 1);
1189                free(target_path);
1190                return code;
1191            }
1192        } else
1193            CloseHandle(hFile);
1194    }
1195    attribute_data_to_stat(&info, reparse_tag, result);
1196
1197    /* Set S_IEXEC if it is an .exe, .bat, ... */
1198    dot = strrchr(path, '.');
1199    if (dot) {
1200        if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
1201            stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
1202            result->st_mode |= 0111;
1203    }
1204    return 0;
1205}
1206
1207static int
1208win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result, BOOL traverse, int depth)
1209{
1210    int code;
1211    HANDLE hFile;
1212    BY_HANDLE_FILE_INFORMATION info;
1213    ULONG reparse_tag = 0;
1214	wchar_t *target_path;
1215    const wchar_t *dot;
1216
1217    if (depth > SYMLOOP_MAX) {
1218        SetLastError(ERROR_CANT_RESOLVE_FILENAME); /* XXX: ELOOP? */
1219        return -1;
1220    }
1221
1222    hFile = CreateFileW(
1223        path,
1224        0, /* desired access */
1225        0, /* share mode */
1226        NULL, /* security attributes */
1227        OPEN_EXISTING,
1228        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1229        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,
1230        NULL);
1231
1232    if (hFile == INVALID_HANDLE_VALUE) {
1233        /* Either the target doesn't exist, or we don't have access to
1234           get a handle to it. If the former, we need to return an error.
1235           If the latter, we can use attributes_from_dir. */
1236        if (GetLastError() != ERROR_SHARING_VIOLATION)
1237            return -1;
1238        /* Could not get attributes on open file. Fall back to
1239           reading the directory. */
1240        if (!attributes_from_dir_w(path, &info, &reparse_tag))
1241            /* Very strange. This should not fail now */
1242            return -1;
1243        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1244            if (traverse) {
1245                /* Should traverse, but could not open reparse point handle */
1246                SetLastError(ERROR_SHARING_VIOLATION);
1247                return -1;
1248            }
1249        }
1250    } else {
1251        if (!GetFileInformationByHandle(hFile, &info)) {
1252            CloseHandle(hFile);
1253            return -1;;
1254        }
1255        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1256            code = win32_read_link(hFile, &reparse_tag, traverse ? &target_path : NULL);
1257            CloseHandle(hFile);
1258            if (code < 0)
1259                return code;
1260            if (traverse) {
1261                code = win32_xstat_impl_w(target_path, result, traverse, depth + 1);
1262                free(target_path);
1263                return code;
1264            }
1265        } else
1266            CloseHandle(hFile);
1267    }
1268    attribute_data_to_stat(&info, reparse_tag, result);
1269
1270    /* Set S_IEXEC if it is an .exe, .bat, ... */
1271    dot = wcsrchr(path, '.');
1272    if (dot) {
1273        if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
1274            _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
1275            result->st_mode |= 0111;
1276    }
1277    return 0;
1278}
1279
1280static int
1281win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
1282{
1283    /* Protocol violation: we explicitly clear errno, instead of
1284       setting it to a POSIX error. Callers should use GetLastError. */
1285    int code = win32_xstat_impl(path, result, traverse, 0);
1286    errno = 0;
1287    return code;
1288}
1289
1290static int
1291win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
1292{
1293    /* Protocol violation: we explicitly clear errno, instead of
1294       setting it to a POSIX error. Callers should use GetLastError. */
1295    int code = win32_xstat_impl_w(path, result, traverse, 0);
1296    errno = 0;
1297    return code;
1298}
1299
1300/* About the following functions: win32_lstat, win32_lstat_w, win32_stat,
1301   win32_stat_w
1302
1303   In Posix, stat automatically traverses symlinks and returns the stat
1304   structure for the target.  In Windows, the equivalent GetFileAttributes by
1305   default does not traverse symlinks and instead returns attributes for
1306   the symlink.
1307
1308   Therefore, win32_lstat will get the attributes traditionally, and
1309   win32_stat will first explicitly resolve the symlink target and then will
1310   call win32_lstat on that result.
1311
1312   The _w represent Unicode equivalents of the aformentioned ANSI functions. */
1313
1314static int
1315win32_lstat(const char* path, struct win32_stat *result)
1316{
1317    return win32_xstat(path, result, FALSE);
1318}
1319
1320static int
1321win32_lstat_w(const wchar_t* path, struct win32_stat *result)
1322{
1323    return win32_xstat_w(path, result, FALSE);
1324}
1325
1326static int
1327win32_stat(const char* path, struct win32_stat *result)
1328{
1329    return win32_xstat(path, result, TRUE);
1330}
1331
1332static int
1333win32_stat_w(const wchar_t* path, struct win32_stat *result)
1334{
1335    return win32_xstat_w(path, result, TRUE);
1336}
1337
1338static int
1339win32_fstat(int file_number, struct win32_stat *result)
1340{
1341    BY_HANDLE_FILE_INFORMATION info;
1342    HANDLE h;
1343    int type;
1344
1345    h = (HANDLE)_get_osfhandle(file_number);
1346
1347    /* Protocol violation: we explicitly clear errno, instead of
1348       setting it to a POSIX error. Callers should use GetLastError. */
1349    errno = 0;
1350
1351    if (h == INVALID_HANDLE_VALUE) {
1352        /* This is really a C library error (invalid file handle).
1353           We set the Win32 error to the closes one matching. */
1354        SetLastError(ERROR_INVALID_HANDLE);
1355        return -1;
1356    }
1357    memset(result, 0, sizeof(*result));
1358
1359    type = GetFileType(h);
1360    if (type == FILE_TYPE_UNKNOWN) {
1361        DWORD error = GetLastError();
1362        if (error != 0) {
1363            return -1;
1364        }
1365        /* else: valid but unknown file */
1366    }
1367
1368    if (type != FILE_TYPE_DISK) {
1369        if (type == FILE_TYPE_CHAR)
1370            result->st_mode = _S_IFCHR;
1371        else if (type == FILE_TYPE_PIPE)
1372            result->st_mode = _S_IFIFO;
1373        return 0;
1374    }
1375
1376    if (!GetFileInformationByHandle(h, &info)) {
1377        return -1;
1378    }
1379
1380    attribute_data_to_stat(&info, 0, result);
1381    /* specific to fstat() */
1382    result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1383    return 0;
1384}
1385
1386#endif /* MS_WINDOWS */
1387
1388PyDoc_STRVAR(stat_result__doc__,
1389"stat_result: Result from stat or lstat.\n\n\
1390This object may be accessed either as a tuple of\n\
1391  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1392or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1393\n\
1394Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1395or st_flags, they are available as attributes only.\n\
1396\n\
1397See os.stat for more information.");
1398
1399static PyStructSequence_Field stat_result_fields[] = {
1400    {"st_mode",    "protection bits"},
1401    {"st_ino",     "inode"},
1402    {"st_dev",     "device"},
1403    {"st_nlink",   "number of hard links"},
1404    {"st_uid",     "user ID of owner"},
1405    {"st_gid",     "group ID of owner"},
1406    {"st_size",    "total size, in bytes"},
1407    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1408    {NULL,   "integer time of last access"},
1409    {NULL,   "integer time of last modification"},
1410    {NULL,   "integer time of last change"},
1411    {"st_atime",   "time of last access"},
1412    {"st_mtime",   "time of last modification"},
1413    {"st_ctime",   "time of last change"},
1414#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1415    {"st_blksize", "blocksize for filesystem I/O"},
1416#endif
1417#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1418    {"st_blocks",  "number of blocks allocated"},
1419#endif
1420#ifdef HAVE_STRUCT_STAT_ST_RDEV
1421    {"st_rdev",    "device type (if inode device)"},
1422#endif
1423#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1424    {"st_flags",   "user defined flags for file"},
1425#endif
1426#ifdef HAVE_STRUCT_STAT_ST_GEN
1427    {"st_gen",    "generation number"},
1428#endif
1429#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1430    {"st_birthtime",   "time of creation"},
1431#endif
1432    {0}
1433};
1434
1435#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1436#define ST_BLKSIZE_IDX 13
1437#else
1438#define ST_BLKSIZE_IDX 12
1439#endif
1440
1441#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1442#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1443#else
1444#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1445#endif
1446
1447#ifdef HAVE_STRUCT_STAT_ST_RDEV
1448#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1449#else
1450#define ST_RDEV_IDX ST_BLOCKS_IDX
1451#endif
1452
1453#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1454#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1455#else
1456#define ST_FLAGS_IDX ST_RDEV_IDX
1457#endif
1458
1459#ifdef HAVE_STRUCT_STAT_ST_GEN
1460#define ST_GEN_IDX (ST_FLAGS_IDX+1)
1461#else
1462#define ST_GEN_IDX ST_FLAGS_IDX
1463#endif
1464
1465#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1466#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1467#else
1468#define ST_BIRTHTIME_IDX ST_GEN_IDX
1469#endif
1470
1471static PyStructSequence_Desc stat_result_desc = {
1472    "stat_result", /* name */
1473    stat_result__doc__, /* doc */
1474    stat_result_fields,
1475    10
1476};
1477
1478PyDoc_STRVAR(statvfs_result__doc__,
1479"statvfs_result: Result from statvfs or fstatvfs.\n\n\
1480This object may be accessed either as a tuple of\n\
1481  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1482or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1483\n\
1484See os.statvfs for more information.");
1485
1486static PyStructSequence_Field statvfs_result_fields[] = {
1487    {"f_bsize",  },
1488    {"f_frsize", },
1489    {"f_blocks", },
1490    {"f_bfree",  },
1491    {"f_bavail", },
1492    {"f_files",  },
1493    {"f_ffree",  },
1494    {"f_favail", },
1495    {"f_flag",   },
1496    {"f_namemax",},
1497    {0}
1498};
1499
1500static PyStructSequence_Desc statvfs_result_desc = {
1501    "statvfs_result", /* name */
1502    statvfs_result__doc__, /* doc */
1503    statvfs_result_fields,
1504    10
1505};
1506
1507static int initialized;
1508static PyTypeObject StatResultType;
1509static PyTypeObject StatVFSResultType;
1510static newfunc structseq_new;
1511
1512static PyObject *
1513statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1514{
1515    PyStructSequence *result;
1516    int i;
1517
1518    result = (PyStructSequence*)structseq_new(type, args, kwds);
1519    if (!result)
1520        return NULL;
1521    /* If we have been initialized from a tuple,
1522       st_?time might be set to None. Initialize it
1523       from the int slots.  */
1524    for (i = 7; i <= 9; i++) {
1525        if (result->ob_item[i+3] == Py_None) {
1526            Py_DECREF(Py_None);
1527            Py_INCREF(result->ob_item[i]);
1528            result->ob_item[i+3] = result->ob_item[i];
1529        }
1530    }
1531    return (PyObject*)result;
1532}
1533
1534
1535
1536/* If true, st_?time is float. */
1537static int _stat_float_times = 1;
1538
1539PyDoc_STRVAR(stat_float_times__doc__,
1540"stat_float_times([newval]) -> oldval\n\n\
1541Determine whether os.[lf]stat represents time stamps as float objects.\n\
1542If newval is True, future calls to stat() return floats, if it is False,\n\
1543future calls return ints. \n\
1544If newval is omitted, return the current setting.\n");
1545
1546static PyObject*
1547stat_float_times(PyObject* self, PyObject *args)
1548{
1549    int newval = -1;
1550    if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
1551        return NULL;
1552    if (newval == -1)
1553        /* Return old value */
1554        return PyBool_FromLong(_stat_float_times);
1555    _stat_float_times = newval;
1556    Py_INCREF(Py_None);
1557    return Py_None;
1558}
1559
1560static void
1561fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
1562{
1563    PyObject *fval,*ival;
1564#if SIZEOF_TIME_T > SIZEOF_LONG
1565    ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
1566#else
1567    ival = PyLong_FromLong((long)sec);
1568#endif
1569    if (!ival)
1570        return;
1571    if (_stat_float_times) {
1572        fval = PyFloat_FromDouble(sec + 1e-9*nsec);
1573    } else {
1574        fval = ival;
1575        Py_INCREF(fval);
1576    }
1577    PyStructSequence_SET_ITEM(v, index, ival);
1578    PyStructSequence_SET_ITEM(v, index+3, fval);
1579}
1580
1581/* pack a system stat C structure into the Python stat tuple
1582   (used by posix_stat() and posix_fstat()) */
1583static PyObject*
1584_pystat_fromstructstat(STRUCT_STAT *st)
1585{
1586    unsigned long ansec, mnsec, cnsec;
1587    PyObject *v = PyStructSequence_New(&StatResultType);
1588    if (v == NULL)
1589        return NULL;
1590
1591    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
1592#ifdef HAVE_LARGEFILE_SUPPORT
1593    PyStructSequence_SET_ITEM(v, 1,
1594                              PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
1595#else
1596    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
1597#endif
1598#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
1599    PyStructSequence_SET_ITEM(v, 2,
1600                              PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
1601#else
1602    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long)st->st_dev));
1603#endif
1604    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
1605    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long)st->st_uid));
1606    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long)st->st_gid));
1607#ifdef HAVE_LARGEFILE_SUPPORT
1608    PyStructSequence_SET_ITEM(v, 6,
1609                              PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
1610#else
1611    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
1612#endif
1613
1614#if defined(HAVE_STAT_TV_NSEC)
1615    ansec = st->st_atim.tv_nsec;
1616    mnsec = st->st_mtim.tv_nsec;
1617    cnsec = st->st_ctim.tv_nsec;
1618#elif defined(HAVE_STAT_TV_NSEC2)
1619    ansec = st->st_atimespec.tv_nsec;
1620    mnsec = st->st_mtimespec.tv_nsec;
1621    cnsec = st->st_ctimespec.tv_nsec;
1622#elif defined(HAVE_STAT_NSEC)
1623    ansec = st->st_atime_nsec;
1624    mnsec = st->st_mtime_nsec;
1625    cnsec = st->st_ctime_nsec;
1626#else
1627    ansec = mnsec = cnsec = 0;
1628#endif
1629    fill_time(v, 7, st->st_atime, ansec);
1630    fill_time(v, 8, st->st_mtime, mnsec);
1631    fill_time(v, 9, st->st_ctime, cnsec);
1632
1633#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1634    PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
1635                              PyLong_FromLong((long)st->st_blksize));
1636#endif
1637#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1638    PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
1639                              PyLong_FromLong((long)st->st_blocks));
1640#endif
1641#ifdef HAVE_STRUCT_STAT_ST_RDEV
1642    PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
1643                              PyLong_FromLong((long)st->st_rdev));
1644#endif
1645#ifdef HAVE_STRUCT_STAT_ST_GEN
1646    PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
1647                              PyLong_FromLong((long)st->st_gen));
1648#endif
1649#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1650    {
1651      PyObject *val;
1652      unsigned long bsec,bnsec;
1653      bsec = (long)st->st_birthtime;
1654#ifdef HAVE_STAT_TV_NSEC2
1655      bnsec = st->st_birthtimespec.tv_nsec;
1656#else
1657      bnsec = 0;
1658#endif
1659      if (_stat_float_times) {
1660        val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
1661      } else {
1662        val = PyLong_FromLong((long)bsec);
1663      }
1664      PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
1665                                val);
1666    }
1667#endif
1668#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1669    PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
1670                              PyLong_FromLong((long)st->st_flags));
1671#endif
1672
1673    if (PyErr_Occurred()) {
1674        Py_DECREF(v);
1675        return NULL;
1676    }
1677
1678    return v;
1679}
1680
1681static PyObject *
1682posix_do_stat(PyObject *self, PyObject *args,
1683              char *format,
1684#ifdef __VMS
1685              int (*statfunc)(const char *, STRUCT_STAT *, ...),
1686#else
1687              int (*statfunc)(const char *, STRUCT_STAT *),
1688#endif
1689              char *wformat,
1690              int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
1691{
1692    STRUCT_STAT st;
1693    PyObject *opath;
1694    char *path;
1695    int res;
1696    PyObject *result;
1697
1698#ifdef MS_WINDOWS
1699    PyUnicodeObject *po;
1700    if (PyArg_ParseTuple(args, wformat, &po)) {
1701        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
1702
1703        Py_BEGIN_ALLOW_THREADS
1704            /* PyUnicode_AS_UNICODE result OK without
1705               thread lock as it is a simple dereference. */
1706        res = wstatfunc(wpath, &st);
1707        Py_END_ALLOW_THREADS
1708
1709        if (res != 0)
1710            return win32_error_unicode("stat", wpath);
1711        return _pystat_fromstructstat(&st);
1712    }
1713    /* Drop the argument parsing error as narrow strings
1714       are also valid. */
1715    PyErr_Clear();
1716#endif
1717
1718    if (!PyArg_ParseTuple(args, format,
1719                          PyUnicode_FSConverter, &opath))
1720        return NULL;
1721    path = PyBytes_AsString(opath);
1722    Py_BEGIN_ALLOW_THREADS
1723    res = (*statfunc)(path, &st);
1724    Py_END_ALLOW_THREADS
1725
1726    if (res != 0) {
1727#ifdef MS_WINDOWS
1728        result = win32_error("stat", path);
1729#else
1730        result = posix_error_with_filename(path);
1731#endif
1732    }
1733    else
1734        result = _pystat_fromstructstat(&st);
1735
1736    Py_DECREF(opath);
1737    return result;
1738}
1739
1740/* POSIX methods */
1741
1742PyDoc_STRVAR(posix_access__doc__,
1743"access(path, mode) -> True if granted, False otherwise\n\n\
1744Use the real uid/gid to test for access to a path.  Note that most\n\
1745operations will use the effective uid/gid, therefore this routine can\n\
1746be used in a suid/sgid environment to test if the invoking user has the\n\
1747specified access to the path.  The mode argument can be F_OK to test\n\
1748existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
1749
1750static PyObject *
1751posix_access(PyObject *self, PyObject *args)
1752{
1753    PyObject *opath;
1754    char *path;
1755    int mode;
1756
1757#ifdef MS_WINDOWS
1758    DWORD attr;
1759    PyUnicodeObject *po;
1760    if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
1761        Py_BEGIN_ALLOW_THREADS
1762        /* PyUnicode_AS_UNICODE OK without thread lock as
1763           it is a simple dereference. */
1764        attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1765        Py_END_ALLOW_THREADS
1766        goto finish;
1767    }
1768    /* Drop the argument parsing error as narrow strings
1769       are also valid. */
1770    PyErr_Clear();
1771    if (!PyArg_ParseTuple(args, "O&i:access",
1772                          PyUnicode_FSConverter, &opath, &mode))
1773        return NULL;
1774    path = PyBytes_AsString(opath);
1775    Py_BEGIN_ALLOW_THREADS
1776    attr = GetFileAttributesA(path);
1777    Py_END_ALLOW_THREADS
1778    Py_DECREF(opath);
1779finish:
1780    if (attr == 0xFFFFFFFF)
1781        /* File does not exist, or cannot read attributes */
1782        return PyBool_FromLong(0);
1783    /* Access is possible if either write access wasn't requested, or
1784       the file isn't read-only, or if it's a directory, as there are
1785       no read-only directories on Windows. */
1786    return PyBool_FromLong(!(mode & 2)
1787                           || !(attr & FILE_ATTRIBUTE_READONLY)
1788                           || (attr & FILE_ATTRIBUTE_DIRECTORY));
1789#else
1790    int res;
1791    if (!PyArg_ParseTuple(args, "O&i:access",
1792                          PyUnicode_FSConverter, &opath, &mode))
1793        return NULL;
1794    path = PyBytes_AsString(opath);
1795    Py_BEGIN_ALLOW_THREADS
1796    res = access(path, mode);
1797    Py_END_ALLOW_THREADS
1798    Py_DECREF(opath);
1799    return PyBool_FromLong(res == 0);
1800#endif
1801}
1802
1803#ifndef F_OK
1804#define F_OK 0
1805#endif
1806#ifndef R_OK
1807#define R_OK 4
1808#endif
1809#ifndef W_OK
1810#define W_OK 2
1811#endif
1812#ifndef X_OK
1813#define X_OK 1
1814#endif
1815
1816#ifdef HAVE_TTYNAME
1817PyDoc_STRVAR(posix_ttyname__doc__,
1818"ttyname(fd) -> string\n\n\
1819Return the name of the terminal device connected to 'fd'.");
1820
1821static PyObject *
1822posix_ttyname(PyObject *self, PyObject *args)
1823{
1824    int id;
1825    char *ret;
1826
1827    if (!PyArg_ParseTuple(args, "i:ttyname", &id))
1828        return NULL;
1829
1830#if defined(__VMS)
1831    /* file descriptor 0 only, the default input device (stdin) */
1832    if (id == 0) {
1833        ret = ttyname();
1834    }
1835    else {
1836        ret = NULL;
1837    }
1838#else
1839    ret = ttyname(id);
1840#endif
1841    if (ret == NULL)
1842        return posix_error();
1843    return PyUnicode_DecodeFSDefault(ret);
1844}
1845#endif
1846
1847#ifdef HAVE_CTERMID
1848PyDoc_STRVAR(posix_ctermid__doc__,
1849"ctermid() -> string\n\n\
1850Return the name of the controlling terminal for this process.");
1851
1852static PyObject *
1853posix_ctermid(PyObject *self, PyObject *noargs)
1854{
1855    char *ret;
1856    char buffer[L_ctermid];
1857
1858#ifdef USE_CTERMID_R
1859    ret = ctermid_r(buffer);
1860#else
1861    ret = ctermid(buffer);
1862#endif
1863    if (ret == NULL)
1864        return posix_error();
1865    return PyUnicode_DecodeFSDefault(buffer);
1866}
1867#endif
1868
1869PyDoc_STRVAR(posix_chdir__doc__,
1870"chdir(path)\n\n\
1871Change the current working directory to the specified path.");
1872
1873static PyObject *
1874posix_chdir(PyObject *self, PyObject *args)
1875{
1876#ifdef MS_WINDOWS
1877    return win32_1str(args, "chdir", "y:chdir", win32_chdir, "U:chdir", win32_wchdir);
1878#elif defined(PYOS_OS2) && defined(PYCC_GCC)
1879    return posix_1str(args, "O&:chdir", _chdir2);
1880#elif defined(__VMS)
1881    return posix_1str(args, "O&:chdir", (int (*)(const char *))chdir);
1882#else
1883    return posix_1str(args, "O&:chdir", chdir);
1884#endif
1885}
1886
1887#ifdef HAVE_FCHDIR
1888PyDoc_STRVAR(posix_fchdir__doc__,
1889"fchdir(fildes)\n\n\
1890Change to the directory of the given file descriptor.  fildes must be\n\
1891opened on a directory, not a file.");
1892
1893static PyObject *
1894posix_fchdir(PyObject *self, PyObject *fdobj)
1895{
1896    return posix_fildes(fdobj, fchdir);
1897}
1898#endif /* HAVE_FCHDIR */
1899
1900
1901PyDoc_STRVAR(posix_chmod__doc__,
1902"chmod(path, mode)\n\n\
1903Change the access permissions of a file.");
1904
1905static PyObject *
1906posix_chmod(PyObject *self, PyObject *args)
1907{
1908    PyObject *opath = NULL;
1909    char *path = NULL;
1910    int i;
1911    int res;
1912#ifdef MS_WINDOWS
1913    DWORD attr;
1914    PyUnicodeObject *po;
1915    if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) {
1916        Py_BEGIN_ALLOW_THREADS
1917        attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1918        if (attr != 0xFFFFFFFF) {
1919            if (i & _S_IWRITE)
1920                attr &= ~FILE_ATTRIBUTE_READONLY;
1921            else
1922                attr |= FILE_ATTRIBUTE_READONLY;
1923            res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr);
1924        }
1925        else
1926            res = 0;
1927        Py_END_ALLOW_THREADS
1928        if (!res)
1929            return win32_error_unicode("chmod",
1930                                       PyUnicode_AS_UNICODE(po));
1931        Py_INCREF(Py_None);
1932        return Py_None;
1933    }
1934    /* Drop the argument parsing error as narrow strings
1935       are also valid. */
1936    PyErr_Clear();
1937
1938    if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter,
1939                          &opath, &i))
1940        return NULL;
1941    path = PyBytes_AsString(opath);
1942    Py_BEGIN_ALLOW_THREADS
1943    attr = GetFileAttributesA(path);
1944    if (attr != 0xFFFFFFFF) {
1945        if (i & _S_IWRITE)
1946            attr &= ~FILE_ATTRIBUTE_READONLY;
1947        else
1948            attr |= FILE_ATTRIBUTE_READONLY;
1949        res = SetFileAttributesA(path, attr);
1950    }
1951    else
1952        res = 0;
1953    Py_END_ALLOW_THREADS
1954    if (!res) {
1955        win32_error("chmod", path);
1956        Py_DECREF(opath);
1957        return NULL;
1958    }
1959    Py_DECREF(opath);
1960    Py_INCREF(Py_None);
1961    return Py_None;
1962#else /* MS_WINDOWS */
1963    if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter,
1964                          &opath, &i))
1965        return NULL;
1966    path = PyBytes_AsString(opath);
1967    Py_BEGIN_ALLOW_THREADS
1968    res = chmod(path, i);
1969    Py_END_ALLOW_THREADS
1970    if (res < 0)
1971        return posix_error_with_allocated_filename(opath);
1972    Py_DECREF(opath);
1973    Py_INCREF(Py_None);
1974    return Py_None;
1975#endif
1976}
1977
1978#ifdef HAVE_FCHMOD
1979PyDoc_STRVAR(posix_fchmod__doc__,
1980"fchmod(fd, mode)\n\n\
1981Change the access permissions of the file given by file\n\
1982descriptor fd.");
1983
1984static PyObject *
1985posix_fchmod(PyObject *self, PyObject *args)
1986{
1987    int fd, mode, res;
1988    if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
1989        return NULL;
1990    Py_BEGIN_ALLOW_THREADS
1991    res = fchmod(fd, mode);
1992    Py_END_ALLOW_THREADS
1993    if (res < 0)
1994        return posix_error();
1995    Py_RETURN_NONE;
1996}
1997#endif /* HAVE_FCHMOD */
1998
1999#ifdef HAVE_LCHMOD
2000PyDoc_STRVAR(posix_lchmod__doc__,
2001"lchmod(path, mode)\n\n\
2002Change the access permissions of a file. If path is a symlink, this\n\
2003affects the link itself rather than the target.");
2004
2005static PyObject *
2006posix_lchmod(PyObject *self, PyObject *args)
2007{
2008    PyObject *opath;
2009    char *path;
2010    int i;
2011    int res;
2012    if (!PyArg_ParseTuple(args, "O&i:lchmod", PyUnicode_FSConverter,
2013                          &opath, &i))
2014        return NULL;
2015    path = PyBytes_AsString(opath);
2016    Py_BEGIN_ALLOW_THREADS
2017    res = lchmod(path, i);
2018    Py_END_ALLOW_THREADS
2019    if (res < 0)
2020        return posix_error_with_allocated_filename(opath);
2021    Py_DECREF(opath);
2022    Py_RETURN_NONE;
2023}
2024#endif /* HAVE_LCHMOD */
2025
2026
2027#ifdef HAVE_CHFLAGS
2028PyDoc_STRVAR(posix_chflags__doc__,
2029"chflags(path, flags)\n\n\
2030Set file flags.");
2031
2032static PyObject *
2033posix_chflags(PyObject *self, PyObject *args)
2034{
2035    PyObject *opath;
2036    char *path;
2037    unsigned long flags;
2038    int res;
2039    if (!PyArg_ParseTuple(args, "O&k:chflags",
2040                          PyUnicode_FSConverter, &opath, &flags))
2041        return NULL;
2042    path = PyBytes_AsString(opath);
2043    Py_BEGIN_ALLOW_THREADS
2044    res = chflags(path, flags);
2045    Py_END_ALLOW_THREADS
2046    if (res < 0)
2047        return posix_error_with_allocated_filename(opath);
2048    Py_DECREF(opath);
2049    Py_INCREF(Py_None);
2050    return Py_None;
2051}
2052#endif /* HAVE_CHFLAGS */
2053
2054#ifdef HAVE_LCHFLAGS
2055PyDoc_STRVAR(posix_lchflags__doc__,
2056"lchflags(path, flags)\n\n\
2057Set file flags.\n\
2058This function will not follow symbolic links.");
2059
2060static PyObject *
2061posix_lchflags(PyObject *self, PyObject *args)
2062{
2063    PyObject *opath;
2064    char *path;
2065    unsigned long flags;
2066    int res;
2067    if (!PyArg_ParseTuple(args, "O&k:lchflags",
2068                          PyUnicode_FSConverter, &opath, &flags))
2069        return NULL;
2070    path = PyBytes_AsString(opath);
2071    Py_BEGIN_ALLOW_THREADS
2072    res = lchflags(path, flags);
2073    Py_END_ALLOW_THREADS
2074    if (res < 0)
2075        return posix_error_with_allocated_filename(opath);
2076    Py_DECREF(opath);
2077    Py_INCREF(Py_None);
2078    return Py_None;
2079}
2080#endif /* HAVE_LCHFLAGS */
2081
2082#ifdef HAVE_CHROOT
2083PyDoc_STRVAR(posix_chroot__doc__,
2084"chroot(path)\n\n\
2085Change root directory to path.");
2086
2087static PyObject *
2088posix_chroot(PyObject *self, PyObject *args)
2089{
2090    return posix_1str(args, "O&:chroot", chroot);
2091}
2092#endif
2093
2094#ifdef HAVE_FSYNC
2095PyDoc_STRVAR(posix_fsync__doc__,
2096"fsync(fildes)\n\n\
2097force write of file with filedescriptor to disk.");
2098
2099static PyObject *
2100posix_fsync(PyObject *self, PyObject *fdobj)
2101{
2102    return posix_fildes(fdobj, fsync);
2103}
2104#endif /* HAVE_FSYNC */
2105
2106#ifdef HAVE_FDATASYNC
2107
2108#ifdef __hpux
2109extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
2110#endif
2111
2112PyDoc_STRVAR(posix_fdatasync__doc__,
2113"fdatasync(fildes)\n\n\
2114force write of file with filedescriptor to disk.\n\
2115 does not force update of metadata.");
2116
2117static PyObject *
2118posix_fdatasync(PyObject *self, PyObject *fdobj)
2119{
2120    return posix_fildes(fdobj, fdatasync);
2121}
2122#endif /* HAVE_FDATASYNC */
2123
2124
2125#ifdef HAVE_CHOWN
2126PyDoc_STRVAR(posix_chown__doc__,
2127"chown(path, uid, gid)\n\n\
2128Change the owner and group id of path to the numeric uid and gid.");
2129
2130static PyObject *
2131posix_chown(PyObject *self, PyObject *args)
2132{
2133    PyObject *opath;
2134    char *path;
2135    long uid, gid;
2136    int res;
2137    if (!PyArg_ParseTuple(args, "O&ll:chown",
2138                          PyUnicode_FSConverter, &opath,
2139                          &uid, &gid))
2140        return NULL;
2141    path = PyBytes_AsString(opath);
2142    Py_BEGIN_ALLOW_THREADS
2143    res = chown(path, (uid_t) uid, (gid_t) gid);
2144    Py_END_ALLOW_THREADS
2145    if (res < 0)
2146        return posix_error_with_allocated_filename(opath);
2147    Py_DECREF(opath);
2148    Py_INCREF(Py_None);
2149    return Py_None;
2150}
2151#endif /* HAVE_CHOWN */
2152
2153#ifdef HAVE_FCHOWN
2154PyDoc_STRVAR(posix_fchown__doc__,
2155"fchown(fd, uid, gid)\n\n\
2156Change the owner and group id of the file given by file descriptor\n\
2157fd to the numeric uid and gid.");
2158
2159static PyObject *
2160posix_fchown(PyObject *self, PyObject *args)
2161{
2162    int fd;
2163    long uid, gid;
2164    int res;
2165    if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid))
2166        return NULL;
2167    Py_BEGIN_ALLOW_THREADS
2168    res = fchown(fd, (uid_t) uid, (gid_t) gid);
2169    Py_END_ALLOW_THREADS
2170    if (res < 0)
2171        return posix_error();
2172    Py_RETURN_NONE;
2173}
2174#endif /* HAVE_FCHOWN */
2175
2176#ifdef HAVE_LCHOWN
2177PyDoc_STRVAR(posix_lchown__doc__,
2178"lchown(path, uid, gid)\n\n\
2179Change the owner and group id of path to the numeric uid and gid.\n\
2180This function will not follow symbolic links.");
2181
2182static PyObject *
2183posix_lchown(PyObject *self, PyObject *args)
2184{
2185    PyObject *opath;
2186    char *path;
2187    long uid, gid;
2188    int res;
2189    if (!PyArg_ParseTuple(args, "O&ll:lchown",
2190                          PyUnicode_FSConverter, &opath,
2191                          &uid, &gid))
2192        return NULL;
2193    path = PyBytes_AsString(opath);
2194    Py_BEGIN_ALLOW_THREADS
2195    res = lchown(path, (uid_t) uid, (gid_t) gid);
2196    Py_END_ALLOW_THREADS
2197    if (res < 0)
2198        return posix_error_with_allocated_filename(opath);
2199    Py_DECREF(opath);
2200    Py_INCREF(Py_None);
2201    return Py_None;
2202}
2203#endif /* HAVE_LCHOWN */
2204
2205
2206#ifdef HAVE_GETCWD
2207static PyObject *
2208posix_getcwd(int use_bytes)
2209{
2210    char buf[1026];
2211    char *res;
2212
2213#ifdef MS_WINDOWS
2214    if (!use_bytes) {
2215        wchar_t wbuf[1026];
2216        wchar_t *wbuf2 = wbuf;
2217        PyObject *resobj;
2218        DWORD len;
2219        Py_BEGIN_ALLOW_THREADS
2220        len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
2221        /* If the buffer is large enough, len does not include the
2222           terminating \0. If the buffer is too small, len includes
2223           the space needed for the terminator. */
2224        if (len >= sizeof wbuf/ sizeof wbuf[0]) {
2225            wbuf2 = malloc(len * sizeof(wchar_t));
2226            if (wbuf2)
2227                len = GetCurrentDirectoryW(len, wbuf2);
2228        }
2229        Py_END_ALLOW_THREADS
2230        if (!wbuf2) {
2231            PyErr_NoMemory();
2232            return NULL;
2233        }
2234        if (!len) {
2235            if (wbuf2 != wbuf) free(wbuf2);
2236            return win32_error("getcwdu", NULL);
2237        }
2238        resobj = PyUnicode_FromWideChar(wbuf2, len);
2239        if (wbuf2 != wbuf) free(wbuf2);
2240        return resobj;
2241    }
2242#endif
2243
2244    Py_BEGIN_ALLOW_THREADS
2245#if defined(PYOS_OS2) && defined(PYCC_GCC)
2246    res = _getcwd2(buf, sizeof buf);
2247#else
2248    res = getcwd(buf, sizeof buf);
2249#endif
2250    Py_END_ALLOW_THREADS
2251    if (res == NULL)
2252        return posix_error();
2253    if (use_bytes)
2254        return PyBytes_FromStringAndSize(buf, strlen(buf));
2255    return PyUnicode_DecodeFSDefault(buf);
2256}
2257
2258PyDoc_STRVAR(posix_getcwd__doc__,
2259"getcwd() -> path\n\n\
2260Return a unicode string representing the current working directory.");
2261
2262static PyObject *
2263posix_getcwd_unicode(PyObject *self)
2264{
2265    return posix_getcwd(0);
2266}
2267
2268PyDoc_STRVAR(posix_getcwdb__doc__,
2269"getcwdb() -> path\n\n\
2270Return a bytes string representing the current working directory.");
2271
2272static PyObject *
2273posix_getcwd_bytes(PyObject *self)
2274{
2275    return posix_getcwd(1);
2276}
2277#endif
2278
2279
2280#ifdef HAVE_LINK
2281PyDoc_STRVAR(posix_link__doc__,
2282"link(src, dst)\n\n\
2283Create a hard link to a file.");
2284
2285static PyObject *
2286posix_link(PyObject *self, PyObject *args)
2287{
2288    return posix_2str(args, "O&O&:link", link);
2289}
2290#endif /* HAVE_LINK */
2291
2292#ifdef MS_WINDOWS
2293PyDoc_STRVAR(win32_link__doc__,
2294"link(src, dst)\n\n\
2295Create a hard link to a file.");
2296
2297static PyObject *
2298win32_link(PyObject *self, PyObject *args)
2299{
2300    PyObject *osrc, *odst;
2301    char *src, *dst;
2302    BOOL rslt;
2303
2304    PyUnicodeObject *usrc, *udst;
2305    if (PyArg_ParseTuple(args, "UU:link", &usrc, &udst)) {
2306        Py_BEGIN_ALLOW_THREADS
2307        rslt = CreateHardLinkW(PyUnicode_AS_UNICODE(udst),
2308                               PyUnicode_AS_UNICODE(usrc), NULL);
2309        Py_END_ALLOW_THREADS
2310
2311        if (rslt == 0)
2312            return win32_error("link", NULL);
2313
2314        Py_RETURN_NONE;
2315    }
2316
2317    /* Narrow strings also valid. */
2318    PyErr_Clear();
2319
2320    if (!PyArg_ParseTuple(args, "O&O&:link", PyUnicode_FSConverter, &osrc,
2321                          PyUnicode_FSConverter, &odst))
2322        return NULL;
2323
2324    src = PyBytes_AsString(osrc);
2325    dst = PyBytes_AsString(odst);
2326
2327    Py_BEGIN_ALLOW_THREADS
2328    rslt = CreateHardLinkA(dst, src, NULL);
2329    Py_END_ALLOW_THREADS
2330
2331    Py_DECREF(osrc);
2332    Py_DECREF(odst);
2333    if (rslt == 0)
2334        return win32_error("link", NULL);
2335
2336    Py_RETURN_NONE;
2337}
2338#endif /* MS_WINDOWS */
2339
2340
2341PyDoc_STRVAR(posix_listdir__doc__,
2342"listdir([path]) -> list_of_strings\n\n\
2343Return a list containing the names of the entries in the directory.\n\
2344\n\
2345    path: path of directory to list (default: '.')\n\
2346\n\
2347The list is in arbitrary order.  It does not include the special\n\
2348entries '.' and '..' even if they are present in the directory.");
2349
2350static PyObject *
2351posix_listdir(PyObject *self, PyObject *args)
2352{
2353    /* XXX Should redo this putting the (now four) versions of opendir
2354       in separate files instead of having them all here... */
2355#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
2356
2357    PyObject *d, *v;
2358    HANDLE hFindFile;
2359    BOOL result;
2360    WIN32_FIND_DATA FileData;
2361    PyObject *opath;
2362    char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
2363    char *bufptr = namebuf;
2364    Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
2365
2366    PyObject *po = NULL;
2367    if (PyArg_ParseTuple(args, "|U:listdir", &po)) {
2368        WIN32_FIND_DATAW wFileData;
2369        Py_UNICODE *wnamebuf, *po_wchars;
2370
2371        if (po == NULL) { /* Default arg: "." */
2372            po_wchars = L".";
2373            len = 1;
2374        } else {
2375            po_wchars = PyUnicode_AS_UNICODE(po);
2376            len = PyUnicode_GET_SIZE(po);
2377        }
2378        /* Overallocate for \\*.*\0 */
2379        wnamebuf = malloc((len + 5) * sizeof(wchar_t));
2380        if (!wnamebuf) {
2381            PyErr_NoMemory();
2382            return NULL;
2383        }
2384        wcscpy(wnamebuf, po_wchars);
2385        if (len > 0) {
2386            Py_UNICODE wch = wnamebuf[len-1];
2387            if (wch != L'/' && wch != L'\\' && wch != L':')
2388                wnamebuf[len++] = L'\\';
2389            wcscpy(wnamebuf + len, L"*.*");
2390        }
2391        if ((d = PyList_New(0)) == NULL) {
2392            free(wnamebuf);
2393            return NULL;
2394        }
2395        Py_BEGIN_ALLOW_THREADS
2396        hFindFile = FindFirstFileW(wnamebuf, &wFileData);
2397        Py_END_ALLOW_THREADS
2398        if (hFindFile == INVALID_HANDLE_VALUE) {
2399            int error = GetLastError();
2400            if (error == ERROR_FILE_NOT_FOUND) {
2401                free(wnamebuf);
2402                return d;
2403            }
2404            Py_DECREF(d);
2405            win32_error_unicode("FindFirstFileW", wnamebuf);
2406            free(wnamebuf);
2407            return NULL;
2408        }
2409        do {
2410            /* Skip over . and .. */
2411            if (wcscmp(wFileData.cFileName, L".") != 0 &&
2412                wcscmp(wFileData.cFileName, L"..") != 0) {
2413                v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName));
2414                if (v == NULL) {
2415                    Py_DECREF(d);
2416                    d = NULL;
2417                    break;
2418                }
2419                if (PyList_Append(d, v) != 0) {
2420                    Py_DECREF(v);
2421                    Py_DECREF(d);
2422                    d = NULL;
2423                    break;
2424                }
2425                Py_DECREF(v);
2426            }
2427            Py_BEGIN_ALLOW_THREADS
2428            result = FindNextFileW(hFindFile, &wFileData);
2429            Py_END_ALLOW_THREADS
2430            /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2431               it got to the end of the directory. */
2432            if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2433                Py_DECREF(d);
2434                win32_error_unicode("FindNextFileW", wnamebuf);
2435                FindClose(hFindFile);
2436                free(wnamebuf);
2437                return NULL;
2438            }
2439        } while (result == TRUE);
2440
2441        if (FindClose(hFindFile) == FALSE) {
2442            Py_DECREF(d);
2443            win32_error_unicode("FindClose", wnamebuf);
2444            free(wnamebuf);
2445            return NULL;
2446        }
2447        free(wnamebuf);
2448        return d;
2449    }
2450    /* Drop the argument parsing error as narrow strings
2451       are also valid. */
2452    PyErr_Clear();
2453
2454    if (!PyArg_ParseTuple(args, "O&:listdir",
2455                          PyUnicode_FSConverter, &opath))
2456        return NULL;
2457    if (PyBytes_GET_SIZE(opath)+1 > MAX_PATH) {
2458        PyErr_SetString(PyExc_ValueError, "path too long");
2459        Py_DECREF(opath);
2460        return NULL;
2461    }
2462    strcpy(namebuf, PyBytes_AsString(opath));
2463    len = PyObject_Size(opath);
2464    Py_DECREF(opath);
2465    if (len > 0) {
2466        char ch = namebuf[len-1];
2467        if (ch != SEP && ch != ALTSEP && ch != ':')
2468            namebuf[len++] = '/';
2469        strcpy(namebuf + len, "*.*");
2470    }
2471
2472    if ((d = PyList_New(0)) == NULL)
2473        return NULL;
2474
2475    Py_BEGIN_ALLOW_THREADS
2476    hFindFile = FindFirstFile(namebuf, &FileData);
2477    Py_END_ALLOW_THREADS
2478    if (hFindFile == INVALID_HANDLE_VALUE) {
2479        int error = GetLastError();
2480        if (error == ERROR_FILE_NOT_FOUND)
2481            return d;
2482        Py_DECREF(d);
2483        return win32_error("FindFirstFile", namebuf);
2484    }
2485    do {
2486        /* Skip over . and .. */
2487        if (strcmp(FileData.cFileName, ".") != 0 &&
2488            strcmp(FileData.cFileName, "..") != 0) {
2489            v = PyBytes_FromString(FileData.cFileName);
2490            if (v == NULL) {
2491                Py_DECREF(d);
2492                d = NULL;
2493                break;
2494            }
2495            if (PyList_Append(d, v) != 0) {
2496                Py_DECREF(v);
2497                Py_DECREF(d);
2498                d = NULL;
2499                break;
2500            }
2501            Py_DECREF(v);
2502        }
2503        Py_BEGIN_ALLOW_THREADS
2504        result = FindNextFile(hFindFile, &FileData);
2505        Py_END_ALLOW_THREADS
2506        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2507           it got to the end of the directory. */
2508        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2509            Py_DECREF(d);
2510            win32_error("FindNextFile", namebuf);
2511            FindClose(hFindFile);
2512            return NULL;
2513        }
2514    } while (result == TRUE);
2515
2516    if (FindClose(hFindFile) == FALSE) {
2517        Py_DECREF(d);
2518        return win32_error("FindClose", namebuf);
2519    }
2520
2521    return d;
2522
2523#elif defined(PYOS_OS2)
2524
2525#ifndef MAX_PATH
2526#define MAX_PATH    CCHMAXPATH
2527#endif
2528    PyObject *oname;
2529    char *name, *pt;
2530    Py_ssize_t len;
2531    PyObject *d, *v;
2532    char namebuf[MAX_PATH+5];
2533    HDIR  hdir = 1;
2534    ULONG srchcnt = 1;
2535    FILEFINDBUF3   ep;
2536    APIRET rc;
2537
2538    if (!PyArg_ParseTuple(args, "O&:listdir",
2539                          PyUnicode_FSConverter, &oname))
2540        return NULL;
2541    name = PyBytes_AsString(oname);
2542    len = PyBytes_GET_SIZE(oname);
2543    if (len >= MAX_PATH) {
2544        Py_DECREF(oname);
2545        PyErr_SetString(PyExc_ValueError, "path too long");
2546        return NULL;
2547    }
2548    strcpy(namebuf, name);
2549    for (pt = namebuf; *pt; pt++)
2550        if (*pt == ALTSEP)
2551            *pt = SEP;
2552    if (namebuf[len-1] != SEP)
2553        namebuf[len++] = SEP;
2554    strcpy(namebuf + len, "*.*");
2555
2556    if ((d = PyList_New(0)) == NULL) {
2557        Py_DECREF(oname);
2558        return NULL;
2559    }
2560
2561    rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
2562                      &hdir,           /* Handle to Use While Search Directory */
2563                      FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
2564                      &ep, sizeof(ep), /* Structure to Receive Directory Entry */
2565                      &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
2566                      FIL_STANDARD);   /* Format of Entry (EAs or Not) */
2567
2568    if (rc != NO_ERROR) {
2569        errno = ENOENT;
2570        return posix_error_with_allocated_filename(oname);
2571    }
2572
2573    if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
2574        do {
2575            if (ep.achName[0] == '.'
2576            && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
2577                continue; /* Skip Over "." and ".." Names */
2578
2579            strcpy(namebuf, ep.achName);
2580
2581            /* Leave Case of Name Alone -- In Native Form */
2582            /* (Removed Forced Lowercasing Code) */
2583
2584            v = PyBytes_FromString(namebuf);
2585            if (v == NULL) {
2586                Py_DECREF(d);
2587                d = NULL;
2588                break;
2589            }
2590            if (PyList_Append(d, v) != 0) {
2591                Py_DECREF(v);
2592                Py_DECREF(d);
2593                d = NULL;
2594                break;
2595            }
2596            Py_DECREF(v);
2597        } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
2598    }
2599
2600    Py_DECREF(oname);
2601    return d;
2602#else
2603    PyObject *oname;
2604    char *name;
2605    PyObject *d, *v;
2606    DIR *dirp;
2607    struct dirent *ep;
2608    int arg_is_unicode = 1;
2609
2610    errno = 0;
2611    /* v is never read, so it does not need to be initialized yet. */
2612    if (!PyArg_ParseTuple(args, "|U:listdir", &v)) {
2613        arg_is_unicode = 0;
2614        PyErr_Clear();
2615    }
2616    oname = NULL;
2617    if (!PyArg_ParseTuple(args, "|O&:listdir", PyUnicode_FSConverter, &oname))
2618        return NULL;
2619    if (oname == NULL) { /* Default arg: "." */
2620        oname = PyBytes_FromString(".");
2621    }
2622    name = PyBytes_AsString(oname);
2623    Py_BEGIN_ALLOW_THREADS
2624    dirp = opendir(name);
2625    Py_END_ALLOW_THREADS
2626    if (dirp == NULL) {
2627        return posix_error_with_allocated_filename(oname);
2628    }
2629    if ((d = PyList_New(0)) == NULL) {
2630        Py_BEGIN_ALLOW_THREADS
2631        closedir(dirp);
2632        Py_END_ALLOW_THREADS
2633        Py_DECREF(oname);
2634        return NULL;
2635    }
2636    for (;;) {
2637        errno = 0;
2638        Py_BEGIN_ALLOW_THREADS
2639        ep = readdir(dirp);
2640        Py_END_ALLOW_THREADS
2641        if (ep == NULL) {
2642            if (errno == 0) {
2643                break;
2644            } else {
2645                Py_BEGIN_ALLOW_THREADS
2646                closedir(dirp);
2647                Py_END_ALLOW_THREADS
2648                Py_DECREF(d);
2649                return posix_error_with_allocated_filename(oname);
2650            }
2651        }
2652        if (ep->d_name[0] == '.' &&
2653            (NAMLEN(ep) == 1 ||
2654             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
2655            continue;
2656        if (arg_is_unicode)
2657            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
2658        else
2659            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
2660        if (v == NULL) {
2661            Py_CLEAR(d);
2662            break;
2663        }
2664        if (PyList_Append(d, v) != 0) {
2665            Py_DECREF(v);
2666            Py_CLEAR(d);
2667            break;
2668        }
2669        Py_DECREF(v);
2670    }
2671    Py_BEGIN_ALLOW_THREADS
2672    closedir(dirp);
2673    Py_END_ALLOW_THREADS
2674    Py_DECREF(oname);
2675
2676    return d;
2677
2678#endif /* which OS */
2679}  /* end of posix_listdir */
2680
2681#ifdef MS_WINDOWS
2682/* A helper function for abspath on win32 */
2683static PyObject *
2684posix__getfullpathname(PyObject *self, PyObject *args)
2685{
2686    PyObject *opath;
2687    char *path;
2688    char outbuf[MAX_PATH*2];
2689    char *temp;
2690#ifdef MS_WINDOWS
2691    PyUnicodeObject *po;
2692    if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
2693        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
2694        Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
2695        Py_UNICODE *wtemp;
2696        DWORD result;
2697        PyObject *v;
2698        result = GetFullPathNameW(wpath,
2699                                  sizeof(woutbuf)/sizeof(woutbuf[0]),
2700                                  woutbuf, &wtemp);
2701        if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
2702            woutbufp = malloc(result * sizeof(Py_UNICODE));
2703            if (!woutbufp)
2704                return PyErr_NoMemory();
2705            result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
2706        }
2707        if (result)
2708            v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
2709        else
2710            v = win32_error_unicode("GetFullPathNameW", wpath);
2711        if (woutbufp != woutbuf)
2712            free(woutbufp);
2713        return v;
2714    }
2715    /* Drop the argument parsing error as narrow strings
2716       are also valid. */
2717    PyErr_Clear();
2718
2719#endif
2720    if (!PyArg_ParseTuple (args, "O&:_getfullpathname",
2721                           PyUnicode_FSConverter, &opath))
2722        return NULL;
2723    path = PyBytes_AsString(opath);
2724    if (!GetFullPathName(path, sizeof(outbuf)/sizeof(outbuf[0]),
2725                         outbuf, &temp)) {
2726        win32_error("GetFullPathName", path);
2727        Py_DECREF(opath);
2728        return NULL;
2729    }
2730    Py_DECREF(opath);
2731    if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
2732        return PyUnicode_Decode(outbuf, strlen(outbuf),
2733                                Py_FileSystemDefaultEncoding, NULL);
2734    }
2735    return PyBytes_FromString(outbuf);
2736} /* end of posix__getfullpathname */
2737
2738/* Grab GetFinalPathNameByHandle dynamically from kernel32 */
2739static int has_GetFinalPathNameByHandle = 0;
2740static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
2741                                                      DWORD);
2742static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
2743                                                      DWORD);
2744static int
2745check_GetFinalPathNameByHandle()
2746{
2747    HINSTANCE hKernel32;
2748    /* only recheck */
2749    if (!has_GetFinalPathNameByHandle)
2750    {
2751        hKernel32 = GetModuleHandle("KERNEL32");
2752        *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
2753                                                "GetFinalPathNameByHandleA");
2754        *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
2755                                                "GetFinalPathNameByHandleW");
2756        has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
2757                                       Py_GetFinalPathNameByHandleW;
2758    }
2759    return has_GetFinalPathNameByHandle;
2760}
2761
2762/* A helper function for samepath on windows */
2763static PyObject *
2764posix__getfinalpathname(PyObject *self, PyObject *args)
2765{
2766    HANDLE hFile;
2767    int buf_size;
2768    wchar_t *target_path;
2769    int result_length;
2770    PyObject *result;
2771    wchar_t *path;
2772
2773    if (!PyArg_ParseTuple(args, "u|:_getfinalpathname", &path)) {
2774        return NULL;
2775    }
2776
2777    if(!check_GetFinalPathNameByHandle()) {
2778        /* If the OS doesn't have GetFinalPathNameByHandle, return a
2779           NotImplementedError. */
2780        return PyErr_Format(PyExc_NotImplementedError,
2781            "GetFinalPathNameByHandle not available on this platform");
2782    }
2783
2784    hFile = CreateFileW(
2785        path,
2786        0, /* desired access */
2787        0, /* share mode */
2788        NULL, /* security attributes */
2789        OPEN_EXISTING,
2790        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
2791        FILE_FLAG_BACKUP_SEMANTICS,
2792        NULL);
2793
2794    if(hFile == INVALID_HANDLE_VALUE) {
2795        return win32_error_unicode("GetFinalPathNamyByHandle", path);
2796        return PyErr_Format(PyExc_RuntimeError,
2797                            "Could not get a handle to file.");
2798    }
2799
2800    /* We have a good handle to the target, use it to determine the
2801       target path name. */
2802    buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
2803
2804    if(!buf_size)
2805        return win32_error_unicode("GetFinalPathNameByHandle", path);
2806
2807    target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
2808    if(!target_path)
2809        return PyErr_NoMemory();
2810
2811    result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
2812                                                 buf_size, VOLUME_NAME_DOS);
2813    if(!result_length)
2814        return win32_error_unicode("GetFinalPathNamyByHandle", path);
2815
2816    if(!CloseHandle(hFile))
2817        return win32_error_unicode("GetFinalPathNameByHandle", path);
2818
2819    target_path[result_length] = 0;
2820    result = PyUnicode_FromUnicode(target_path, result_length);
2821    free(target_path);
2822    return result;
2823
2824} /* end of posix__getfinalpathname */
2825
2826static PyObject *
2827posix__getfileinformation(PyObject *self, PyObject *args)
2828{
2829    HANDLE hFile;
2830    BY_HANDLE_FILE_INFORMATION info;
2831    int fd;
2832
2833    if (!PyArg_ParseTuple(args, "i:_getfileinformation", &fd))
2834        return NULL;
2835
2836    if (!_PyVerify_fd(fd))
2837        return posix_error();
2838
2839    hFile = (HANDLE)_get_osfhandle(fd);
2840    if (hFile == INVALID_HANDLE_VALUE)
2841        return posix_error();
2842
2843    if (!GetFileInformationByHandle(hFile, &info))
2844        return win32_error("_getfileinformation", NULL);
2845
2846    return Py_BuildValue("iii", info.dwVolumeSerialNumber,
2847                                info.nFileIndexHigh,
2848                                info.nFileIndexLow);
2849}
2850#endif /* MS_WINDOWS */
2851
2852PyDoc_STRVAR(posix_mkdir__doc__,
2853"mkdir(path [, mode=0777])\n\n\
2854Create a directory.");
2855
2856static PyObject *
2857posix_mkdir(PyObject *self, PyObject *args)
2858{
2859    int res;
2860    PyObject *opath;
2861    char *path;
2862    int mode = 0777;
2863
2864#ifdef MS_WINDOWS
2865    PyUnicodeObject *po;
2866    if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) {
2867        Py_BEGIN_ALLOW_THREADS
2868        /* PyUnicode_AS_UNICODE OK without thread lock as
2869           it is a simple dereference. */
2870        res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL);
2871        Py_END_ALLOW_THREADS
2872        if (!res)
2873            return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po));
2874        Py_INCREF(Py_None);
2875        return Py_None;
2876    }
2877    /* Drop the argument parsing error as narrow strings
2878       are also valid. */
2879    PyErr_Clear();
2880    if (!PyArg_ParseTuple(args, "O&|i:mkdir",
2881                          PyUnicode_FSConverter, &opath, &mode))
2882        return NULL;
2883    path = PyBytes_AsString(opath);
2884    Py_BEGIN_ALLOW_THREADS
2885    /* PyUnicode_AS_UNICODE OK without thread lock as
2886       it is a simple dereference. */
2887    res = CreateDirectoryA(path, NULL);
2888    Py_END_ALLOW_THREADS
2889    if (!res) {
2890        win32_error("mkdir", path);
2891        Py_DECREF(opath);
2892        return NULL;
2893    }
2894    Py_DECREF(opath);
2895    Py_INCREF(Py_None);
2896    return Py_None;
2897#else
2898
2899    if (!PyArg_ParseTuple(args, "O&|i:mkdir",
2900                          PyUnicode_FSConverter, &opath, &mode))
2901        return NULL;
2902    path = PyBytes_AsString(opath);
2903    Py_BEGIN_ALLOW_THREADS
2904#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
2905    res = mkdir(path);
2906#else
2907    res = mkdir(path, mode);
2908#endif
2909    Py_END_ALLOW_THREADS
2910    if (res < 0)
2911        return posix_error_with_allocated_filename(opath);
2912    Py_DECREF(opath);
2913    Py_INCREF(Py_None);
2914    return Py_None;
2915#endif
2916}
2917
2918
2919/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
2920#if defined(HAVE_SYS_RESOURCE_H)
2921#include <sys/resource.h>
2922#endif
2923
2924
2925#ifdef HAVE_NICE
2926PyDoc_STRVAR(posix_nice__doc__,
2927"nice(inc) -> new_priority\n\n\
2928Decrease the priority of process by inc and return the new priority.");
2929
2930static PyObject *
2931posix_nice(PyObject *self, PyObject *args)
2932{
2933    int increment, value;
2934
2935    if (!PyArg_ParseTuple(args, "i:nice", &increment))
2936        return NULL;
2937
2938    /* There are two flavours of 'nice': one that returns the new
2939       priority (as required by almost all standards out there) and the
2940       Linux/FreeBSD/BSDI one, which returns '0' on success and advices
2941       the use of getpriority() to get the new priority.
2942
2943       If we are of the nice family that returns the new priority, we
2944       need to clear errno before the call, and check if errno is filled
2945       before calling posix_error() on a returnvalue of -1, because the
2946       -1 may be the actual new priority! */
2947
2948    errno = 0;
2949    value = nice(increment);
2950#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
2951    if (value == 0)
2952        value = getpriority(PRIO_PROCESS, 0);
2953#endif
2954    if (value == -1 && errno != 0)
2955        /* either nice() or getpriority() returned an error */
2956        return posix_error();
2957    return PyLong_FromLong((long) value);
2958}
2959#endif /* HAVE_NICE */
2960
2961PyDoc_STRVAR(posix_rename__doc__,
2962"rename(old, new)\n\n\
2963Rename a file or directory.");
2964
2965static PyObject *
2966posix_rename(PyObject *self, PyObject *args)
2967{
2968#ifdef MS_WINDOWS
2969    PyObject *o1, *o2;
2970    char *p1, *p2;
2971    BOOL result;
2972    if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2))
2973        goto error;
2974    if (!convert_to_unicode(&o1))
2975        goto error;
2976    if (!convert_to_unicode(&o2)) {
2977        Py_DECREF(o1);
2978        goto error;
2979    }
2980    Py_BEGIN_ALLOW_THREADS
2981    result = MoveFileW(PyUnicode_AsUnicode(o1),
2982                       PyUnicode_AsUnicode(o2));
2983    Py_END_ALLOW_THREADS
2984    Py_DECREF(o1);
2985    Py_DECREF(o2);
2986    if (!result)
2987        return win32_error("rename", NULL);
2988    Py_INCREF(Py_None);
2989    return Py_None;
2990error:
2991    PyErr_Clear();
2992    if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2))
2993        return NULL;
2994    Py_BEGIN_ALLOW_THREADS
2995    result = MoveFileA(p1, p2);
2996    Py_END_ALLOW_THREADS
2997    if (!result)
2998        return win32_error("rename", NULL);
2999    Py_INCREF(Py_None);
3000    return Py_None;
3001#else
3002    return posix_2str(args, "O&O&:rename", rename);
3003#endif
3004}
3005
3006
3007PyDoc_STRVAR(posix_rmdir__doc__,
3008"rmdir(path)\n\n\
3009Remove a directory.");
3010
3011static PyObject *
3012posix_rmdir(PyObject *self, PyObject *args)
3013{
3014#ifdef MS_WINDOWS
3015    return win32_1str(args, "rmdir", "y:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW);
3016#else
3017    return posix_1str(args, "O&:rmdir", rmdir);
3018#endif
3019}
3020
3021
3022PyDoc_STRVAR(posix_stat__doc__,
3023"stat(path) -> stat result\n\n\
3024Perform a stat system call on the given path.");
3025
3026static PyObject *
3027posix_stat(PyObject *self, PyObject *args)
3028{
3029#ifdef MS_WINDOWS
3030    return posix_do_stat(self, args, "O&:stat", STAT, "U:stat", win32_stat_w);
3031#else
3032    return posix_do_stat(self, args, "O&:stat", STAT, NULL, NULL);
3033#endif
3034}
3035
3036
3037#ifdef HAVE_SYSTEM
3038PyDoc_STRVAR(posix_system__doc__,
3039"system(command) -> exit_status\n\n\
3040Execute the command (a string) in a subshell.");
3041
3042static PyObject *
3043posix_system(PyObject *self, PyObject *args)
3044{
3045    long sts;
3046#ifdef MS_WINDOWS
3047    wchar_t *command;
3048    if (!PyArg_ParseTuple(args, "u:system", &command))
3049        return NULL;
3050
3051    Py_BEGIN_ALLOW_THREADS
3052    sts = _wsystem(command);
3053    Py_END_ALLOW_THREADS
3054#else
3055    PyObject *command_obj;
3056    char *command;
3057    if (!PyArg_ParseTuple(args, "O&:system",
3058                          PyUnicode_FSConverter, &command_obj))
3059        return NULL;
3060
3061    command = PyBytes_AsString(command_obj);
3062    Py_BEGIN_ALLOW_THREADS
3063    sts = system(command);
3064    Py_END_ALLOW_THREADS
3065    Py_DECREF(command_obj);
3066#endif
3067    return PyLong_FromLong(sts);
3068}
3069#endif
3070
3071
3072PyDoc_STRVAR(posix_umask__doc__,
3073"umask(new_mask) -> old_mask\n\n\
3074Set the current numeric umask and return the previous umask.");
3075
3076static PyObject *
3077posix_umask(PyObject *self, PyObject *args)
3078{
3079    int i;
3080    if (!PyArg_ParseTuple(args, "i:umask", &i))
3081        return NULL;
3082    i = (int)umask(i);
3083    if (i < 0)
3084        return posix_error();
3085    return PyLong_FromLong((long)i);
3086}
3087
3088#ifdef MS_WINDOWS
3089
3090/* override the default DeleteFileW behavior so that directory
3091symlinks can be removed with this function, the same as with
3092Unix symlinks */
3093BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
3094{
3095    WIN32_FILE_ATTRIBUTE_DATA info;
3096    WIN32_FIND_DATAW find_data;
3097    HANDLE find_data_handle;
3098    int is_directory = 0;
3099    int is_link = 0;
3100
3101    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
3102        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
3103
3104        /* Get WIN32_FIND_DATA structure for the path to determine if
3105           it is a symlink */
3106        if(is_directory &&
3107           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
3108            find_data_handle = FindFirstFileW(lpFileName, &find_data);
3109
3110            if(find_data_handle != INVALID_HANDLE_VALUE) {
3111                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
3112                FindClose(find_data_handle);
3113            }
3114        }
3115    }
3116
3117    if (is_directory && is_link)
3118        return RemoveDirectoryW(lpFileName);
3119
3120    return DeleteFileW(lpFileName);
3121}
3122#endif /* MS_WINDOWS */
3123
3124PyDoc_STRVAR(posix_unlink__doc__,
3125"unlink(path)\n\n\
3126Remove a file (same as remove(path)).");
3127
3128PyDoc_STRVAR(posix_remove__doc__,
3129"remove(path)\n\n\
3130Remove a file (same as unlink(path)).");
3131
3132static PyObject *
3133posix_unlink(PyObject *self, PyObject *args)
3134{
3135#ifdef MS_WINDOWS
3136    return win32_1str(args, "remove", "y:remove", DeleteFileA,
3137                      "U:remove", Py_DeleteFileW);
3138#else
3139    return posix_1str(args, "O&:remove", unlink);
3140#endif
3141}
3142
3143
3144#ifdef HAVE_UNAME
3145PyDoc_STRVAR(posix_uname__doc__,
3146"uname() -> (sysname, nodename, release, version, machine)\n\n\
3147Return a tuple identifying the current operating system.");
3148
3149static PyObject *
3150posix_uname(PyObject *self, PyObject *noargs)
3151{
3152    struct utsname u;
3153    int res;
3154
3155    Py_BEGIN_ALLOW_THREADS
3156    res = uname(&u);
3157    Py_END_ALLOW_THREADS
3158    if (res < 0)
3159        return posix_error();
3160    return Py_BuildValue("(sssss)",
3161                         u.sysname,
3162                         u.nodename,
3163                         u.release,
3164                         u.version,
3165                         u.machine);
3166}
3167#endif /* HAVE_UNAME */
3168
3169static int
3170extract_time(PyObject *t, time_t* sec, long* usec)
3171{
3172    time_t intval;
3173    if (PyFloat_Check(t)) {
3174        double tval = PyFloat_AsDouble(t);
3175        PyObject *intobj = PyNumber_Long(t);
3176        if (!intobj)
3177            return -1;
3178#if SIZEOF_TIME_T > SIZEOF_LONG
3179        intval = PyLong_AsUnsignedLongLongMask(intobj);
3180#else
3181        intval = PyLong_AsLong(intobj);
3182#endif
3183        Py_DECREF(intobj);
3184        if (intval == -1 && PyErr_Occurred())
3185            return -1;
3186        *sec = intval;
3187        *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
3188        if (*usec < 0)
3189            /* If rounding gave us a negative number,
3190               truncate.  */
3191            *usec = 0;
3192        return 0;
3193    }
3194#if SIZEOF_TIME_T > SIZEOF_LONG
3195    intval = PyLong_AsUnsignedLongLongMask(t);
3196#else
3197    intval = PyLong_AsLong(t);
3198#endif
3199    if (intval == -1 && PyErr_Occurred())
3200        return -1;
3201    *sec = intval;
3202    *usec = 0;
3203    return 0;
3204}
3205
3206PyDoc_STRVAR(posix_utime__doc__,
3207"utime(path, (atime, mtime))\n\
3208utime(path, None)\n\n\
3209Set the access and modified time of the file to the given values.  If the\n\
3210second form is used, set the access and modified times to the current time.");
3211
3212static PyObject *
3213posix_utime(PyObject *self, PyObject *args)
3214{
3215#ifdef MS_WINDOWS
3216    PyObject *arg;
3217    PyUnicodeObject *obwpath;
3218    wchar_t *wpath = NULL;
3219    PyObject *oapath;
3220    char *apath;
3221    HANDLE hFile;
3222    time_t atimesec, mtimesec;
3223    long ausec, musec;
3224    FILETIME atime, mtime;
3225    PyObject *result = NULL;
3226
3227    if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) {
3228        wpath = PyUnicode_AS_UNICODE(obwpath);
3229        Py_BEGIN_ALLOW_THREADS
3230        hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
3231                            NULL, OPEN_EXISTING,
3232                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
3233        Py_END_ALLOW_THREADS
3234        if (hFile == INVALID_HANDLE_VALUE)
3235            return win32_error_unicode("utime", wpath);
3236    } else
3237        /* Drop the argument parsing error as narrow strings
3238           are also valid. */
3239        PyErr_Clear();
3240
3241    if (!wpath) {
3242        if (!PyArg_ParseTuple(args, "O&O:utime",
3243                        PyUnicode_FSConverter, &oapath, &arg))
3244            return NULL;
3245        apath = PyBytes_AsString(oapath);
3246        Py_BEGIN_ALLOW_THREADS
3247        hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0,
3248                            NULL, OPEN_EXISTING,
3249                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
3250        Py_END_ALLOW_THREADS
3251        if (hFile == INVALID_HANDLE_VALUE) {
3252            win32_error("utime", apath);
3253            Py_DECREF(oapath);
3254            return NULL;
3255        }
3256        Py_DECREF(oapath);
3257    }
3258
3259    if (arg == Py_None) {
3260        SYSTEMTIME now;
3261        GetSystemTime(&now);
3262        if (!SystemTimeToFileTime(&now, &mtime) ||
3263            !SystemTimeToFileTime(&now, &atime)) {
3264            win32_error("utime", NULL);
3265            goto done;
3266        }
3267    }
3268    else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
3269        PyErr_SetString(PyExc_TypeError,
3270                        "utime() arg 2 must be a tuple (atime, mtime)");
3271        goto done;
3272    }
3273    else {
3274        if (extract_time(PyTuple_GET_ITEM(arg, 0),
3275                         &atimesec, &ausec) == -1)
3276            goto done;
3277        time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
3278        if (extract_time(PyTuple_GET_ITEM(arg, 1),
3279                         &mtimesec, &musec) == -1)
3280            goto done;
3281        time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
3282    }
3283    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
3284        /* Avoid putting the file name into the error here,
3285           as that may confuse the user into believing that
3286           something is wrong with the file, when it also
3287           could be the time stamp that gives a problem. */
3288        win32_error("utime", NULL);
3289        goto done;
3290    }
3291    Py_INCREF(Py_None);
3292    result = Py_None;
3293done:
3294    CloseHandle(hFile);
3295    return result;
3296#else /* MS_WINDOWS */
3297
3298    PyObject *opath;
3299    char *path;
3300    time_t atime, mtime;
3301    long ausec, musec;
3302    int res;
3303    PyObject* arg;
3304
3305#if defined(HAVE_UTIMES)
3306    struct timeval buf[2];
3307#define ATIME buf[0].tv_sec
3308#define MTIME buf[1].tv_sec
3309#elif defined(HAVE_UTIME_H)
3310/* XXX should define struct utimbuf instead, above */
3311    struct utimbuf buf;
3312#define ATIME buf.actime
3313#define MTIME buf.modtime
3314#define UTIME_ARG &buf
3315#else /* HAVE_UTIMES */
3316    time_t buf[2];
3317#define ATIME buf[0]
3318#define MTIME buf[1]
3319#define UTIME_ARG buf
3320#endif /* HAVE_UTIMES */
3321
3322
3323    if (!PyArg_ParseTuple(args, "O&O:utime",
3324                          PyUnicode_FSConverter, &opath, &arg))
3325        return NULL;
3326    path = PyBytes_AsString(opath);
3327    if (arg == Py_None) {
3328        /* optional time values not given */
3329        Py_BEGIN_ALLOW_THREADS
3330        res = utime(path, NULL);
3331        Py_END_ALLOW_THREADS
3332    }
3333    else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
3334        PyErr_SetString(PyExc_TypeError,
3335                        "utime() arg 2 must be a tuple (atime, mtime)");
3336        Py_DECREF(opath);
3337        return NULL;
3338    }
3339    else {
3340        if (extract_time(PyTuple_GET_ITEM(arg, 0),
3341                         &atime, &ausec) == -1) {
3342            Py_DECREF(opath);
3343            return NULL;
3344        }
3345        if (extract_time(PyTuple_GET_ITEM(arg, 1),
3346                         &mtime, &musec) == -1) {
3347            Py_DECREF(opath);
3348            return NULL;
3349        }
3350        ATIME = atime;
3351        MTIME = mtime;
3352#ifdef HAVE_UTIMES
3353        buf[0].tv_usec = ausec;
3354        buf[1].tv_usec = musec;
3355        Py_BEGIN_ALLOW_THREADS
3356        res = utimes(path, buf);
3357        Py_END_ALLOW_THREADS
3358#else
3359        Py_BEGIN_ALLOW_THREADS
3360        res = utime(path, UTIME_ARG);
3361        Py_END_ALLOW_THREADS
3362#endif /* HAVE_UTIMES */
3363    }
3364    if (res < 0) {
3365        return posix_error_with_allocated_filename(opath);
3366    }
3367    Py_DECREF(opath);
3368    Py_INCREF(Py_None);
3369    return Py_None;
3370#undef UTIME_ARG
3371#undef ATIME
3372#undef MTIME
3373#endif /* MS_WINDOWS */
3374}
3375
3376
3377/* Process operations */
3378
3379PyDoc_STRVAR(posix__exit__doc__,
3380"_exit(status)\n\n\
3381Exit to the system with specified status, without normal exit processing.");
3382
3383static PyObject *
3384posix__exit(PyObject *self, PyObject *args)
3385{
3386    int sts;
3387    if (!PyArg_ParseTuple(args, "i:_exit", &sts))
3388        return NULL;
3389    _exit(sts);
3390    return NULL; /* Make gcc -Wall happy */
3391}
3392
3393#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
3394static void
3395free_string_array(char **array, Py_ssize_t count)
3396{
3397    Py_ssize_t i;
3398    for (i = 0; i < count; i++)
3399        PyMem_Free(array[i]);
3400    PyMem_DEL(array);
3401}
3402
3403static
3404int fsconvert_strdup(PyObject *o, char**out)
3405{
3406    PyObject *bytes;
3407    Py_ssize_t size;
3408    if (!PyUnicode_FSConverter(o, &bytes))
3409        return 0;
3410    size = PyBytes_GET_SIZE(bytes);
3411    *out = PyMem_Malloc(size+1);
3412    if (!*out)
3413        return 0;
3414    memcpy(*out, PyBytes_AsString(bytes), size+1);
3415    Py_DECREF(bytes);
3416    return 1;
3417}
3418#endif
3419
3420
3421#ifdef HAVE_EXECV
3422PyDoc_STRVAR(posix_execv__doc__,
3423"execv(path, args)\n\n\
3424Execute an executable path with arguments, replacing current process.\n\
3425\n\
3426    path: path of executable file\n\
3427    args: tuple or list of strings");
3428
3429static PyObject *
3430posix_execv(PyObject *self, PyObject *args)
3431{
3432    PyObject *opath;
3433    char *path;
3434    PyObject *argv;
3435    char **argvlist;
3436    Py_ssize_t i, argc;
3437    PyObject *(*getitem)(PyObject *, Py_ssize_t);
3438
3439    /* execv has two arguments: (path, argv), where
3440       argv is a list or tuple of strings. */
3441
3442    if (!PyArg_ParseTuple(args, "O&O:execv",
3443                          PyUnicode_FSConverter,
3444                          &opath, &argv))
3445        return NULL;
3446    path = PyBytes_AsString(opath);
3447    if (PyList_Check(argv)) {
3448        argc = PyList_Size(argv);
3449        getitem = PyList_GetItem;
3450    }
3451    else if (PyTuple_Check(argv)) {
3452        argc = PyTuple_Size(argv);
3453        getitem = PyTuple_GetItem;
3454    }
3455    else {
3456        PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
3457        Py_DECREF(opath);
3458        return NULL;
3459    }
3460    if (argc < 1) {
3461        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
3462        Py_DECREF(opath);
3463        return NULL;
3464    }
3465
3466    argvlist = PyMem_NEW(char *, argc+1);
3467    if (argvlist == NULL) {
3468        Py_DECREF(opath);
3469        return PyErr_NoMemory();
3470    }
3471    for (i = 0; i < argc; i++) {
3472        if (!fsconvert_strdup((*getitem)(argv, i),
3473                              &argvlist[i])) {
3474            free_string_array(argvlist, i);
3475            PyErr_SetString(PyExc_TypeError,
3476                            "execv() arg 2 must contain only strings");
3477            Py_DECREF(opath);
3478            return NULL;
3479
3480        }
3481    }
3482    argvlist[argc] = NULL;
3483
3484    execv(path, argvlist);
3485
3486    /* If we get here it's definitely an error */
3487
3488    free_string_array(argvlist, argc);
3489    Py_DECREF(opath);
3490    return posix_error();
3491}
3492
3493static char**
3494parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
3495{
3496    char **envlist;
3497    Py_ssize_t i, pos, envc;
3498    PyObject *keys=NULL, *vals=NULL;
3499    PyObject *key, *val, *key2, *val2;
3500    char *p, *k, *v;
3501    size_t len;
3502
3503    i = PyMapping_Size(env);
3504    if (i < 0)
3505        return NULL;
3506    envlist = PyMem_NEW(char *, i + 1);
3507    if (envlist == NULL) {
3508        PyErr_NoMemory();
3509        return NULL;
3510    }
3511    envc = 0;
3512    keys = PyMapping_Keys(env);
3513    vals = PyMapping_Values(env);
3514    if (!keys || !vals)
3515        goto error;
3516    if (!PyList_Check(keys) || !PyList_Check(vals)) {
3517        PyErr_Format(PyExc_TypeError,
3518                     "env.keys() or env.values() is not a list");
3519        goto error;
3520    }
3521
3522    for (pos = 0; pos < i; pos++) {
3523        key = PyList_GetItem(keys, pos);
3524        val = PyList_GetItem(vals, pos);
3525        if (!key || !val)
3526            goto error;
3527
3528        if (PyUnicode_FSConverter(key, &key2) == 0)
3529            goto error;
3530        if (PyUnicode_FSConverter(val, &val2) == 0) {
3531            Py_DECREF(key2);
3532            goto error;
3533        }
3534
3535#if defined(PYOS_OS2)
3536        /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
3537        if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
3538#endif
3539        k = PyBytes_AsString(key2);
3540        v = PyBytes_AsString(val2);
3541        len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2;
3542
3543        p = PyMem_NEW(char, len);
3544        if (p == NULL) {
3545            PyErr_NoMemory();
3546            Py_DECREF(key2);
3547            Py_DECREF(val2);
3548            goto error;
3549        }
3550        PyOS_snprintf(p, len, "%s=%s", k, v);
3551        envlist[envc++] = p;
3552        Py_DECREF(key2);
3553        Py_DECREF(val2);
3554#if defined(PYOS_OS2)
3555        }
3556#endif
3557    }
3558    Py_DECREF(vals);
3559    Py_DECREF(keys);
3560
3561    envlist[envc] = 0;
3562    *envc_ptr = envc;
3563    return envlist;
3564
3565error:
3566    Py_XDECREF(keys);
3567    Py_XDECREF(vals);
3568    while (--envc >= 0)
3569        PyMem_DEL(envlist[envc]);
3570    PyMem_DEL(envlist);
3571    return NULL;
3572}
3573
3574PyDoc_STRVAR(posix_execve__doc__,
3575"execve(path, args, env)\n\n\
3576Execute a path with arguments and environment, replacing current process.\n\
3577\n\
3578    path: path of executable file\n\
3579    args: tuple or list of arguments\n\
3580    env: dictionary of strings mapping to strings");
3581
3582static PyObject *
3583posix_execve(PyObject *self, PyObject *args)
3584{
3585    PyObject *opath;
3586    char *path;
3587    PyObject *argv, *env;
3588    char **argvlist;
3589    char **envlist;
3590    Py_ssize_t i, argc, envc;
3591    PyObject *(*getitem)(PyObject *, Py_ssize_t);
3592    Py_ssize_t lastarg = 0;
3593
3594    /* execve has three arguments: (path, argv, env), where
3595       argv is a list or tuple of strings and env is a dictionary
3596       like posix.environ. */
3597
3598    if (!PyArg_ParseTuple(args, "O&OO:execve",
3599                          PyUnicode_FSConverter,
3600                          &opath, &argv, &env))
3601        return NULL;
3602    path = PyBytes_AsString(opath);
3603    if (PyList_Check(argv)) {
3604        argc = PyList_Size(argv);
3605        getitem = PyList_GetItem;
3606    }
3607    else if (PyTuple_Check(argv)) {
3608        argc = PyTuple_Size(argv);
3609        getitem = PyTuple_GetItem;
3610    }
3611    else {
3612        PyErr_SetString(PyExc_TypeError,
3613                        "execve() arg 2 must be a tuple or list");
3614        goto fail_0;
3615    }
3616    if (!PyMapping_Check(env)) {
3617        PyErr_SetString(PyExc_TypeError,
3618                        "execve() arg 3 must be a mapping object");
3619        goto fail_0;
3620    }
3621
3622    argvlist = PyMem_NEW(char *, argc+1);
3623    if (argvlist == NULL) {
3624        PyErr_NoMemory();
3625        goto fail_0;
3626    }
3627    for (i = 0; i < argc; i++) {
3628        if (!fsconvert_strdup((*getitem)(argv, i),
3629                              &argvlist[i]))
3630        {
3631            lastarg = i;
3632            goto fail_1;
3633        }
3634    }
3635    lastarg = argc;
3636    argvlist[argc] = NULL;
3637
3638    envlist = parse_envlist(env, &envc);
3639    if (envlist == NULL)
3640        goto fail_1;
3641
3642    execve(path, argvlist, envlist);
3643
3644    /* If we get here it's definitely an error */
3645
3646    (void) posix_error();
3647
3648    while (--envc >= 0)
3649        PyMem_DEL(envlist[envc]);
3650    PyMem_DEL(envlist);
3651  fail_1:
3652    free_string_array(argvlist, lastarg);
3653  fail_0:
3654    Py_DECREF(opath);
3655    return NULL;
3656}
3657#endif /* HAVE_EXECV */
3658
3659
3660#ifdef HAVE_SPAWNV
3661PyDoc_STRVAR(posix_spawnv__doc__,
3662"spawnv(mode, path, args)\n\n\
3663Execute the program 'path' in a new process.\n\
3664\n\
3665    mode: mode of process creation\n\
3666    path: path of executable file\n\
3667    args: tuple or list of strings");
3668
3669static PyObject *
3670posix_spawnv(PyObject *self, PyObject *args)
3671{
3672    PyObject *opath;
3673    char *path;
3674    PyObject *argv;
3675    char **argvlist;
3676    int mode, i;
3677    Py_ssize_t argc;
3678    Py_intptr_t spawnval;
3679    PyObject *(*getitem)(PyObject *, Py_ssize_t);
3680
3681    /* spawnv has three arguments: (mode, path, argv), where
3682       argv is a list or tuple of strings. */
3683
3684    if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode,
3685                          PyUnicode_FSConverter,
3686                          &opath, &argv))
3687        return NULL;
3688    path = PyBytes_AsString(opath);
3689    if (PyList_Check(argv)) {
3690        argc = PyList_Size(argv);
3691        getitem = PyList_GetItem;
3692    }
3693    else if (PyTuple_Check(argv)) {
3694        argc = PyTuple_Size(argv);
3695        getitem = PyTuple_GetItem;
3696    }
3697    else {
3698        PyErr_SetString(PyExc_TypeError,
3699                        "spawnv() arg 2 must be a tuple or list");
3700        Py_DECREF(opath);
3701        return NULL;
3702    }
3703
3704    argvlist = PyMem_NEW(char *, argc+1);
3705    if (argvlist == NULL) {
3706        Py_DECREF(opath);
3707        return PyErr_NoMemory();
3708    }
3709    for (i = 0; i < argc; i++) {
3710        if (!fsconvert_strdup((*getitem)(argv, i),
3711                              &argvlist[i])) {
3712            free_string_array(argvlist, i);
3713            PyErr_SetString(
3714                PyExc_TypeError,
3715                "spawnv() arg 2 must contain only strings");
3716            Py_DECREF(opath);
3717            return NULL;
3718        }
3719    }
3720    argvlist[argc] = NULL;
3721
3722#if defined(PYOS_OS2) && defined(PYCC_GCC)
3723    Py_BEGIN_ALLOW_THREADS
3724    spawnval = spawnv(mode, path, argvlist);
3725    Py_END_ALLOW_THREADS
3726#else
3727    if (mode == _OLD_P_OVERLAY)
3728        mode = _P_OVERLAY;
3729
3730    Py_BEGIN_ALLOW_THREADS
3731    spawnval = _spawnv(mode, path, argvlist);
3732    Py_END_ALLOW_THREADS
3733#endif
3734
3735    free_string_array(argvlist, argc);
3736    Py_DECREF(opath);
3737
3738    if (spawnval == -1)
3739        return posix_error();
3740    else
3741#if SIZEOF_LONG == SIZEOF_VOID_P
3742        return Py_BuildValue("l", (long) spawnval);
3743#else
3744        return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3745#endif
3746}
3747
3748
3749PyDoc_STRVAR(posix_spawnve__doc__,
3750"spawnve(mode, path, args, env)\n\n\
3751Execute the program 'path' in a new process.\n\
3752\n\
3753    mode: mode of process creation\n\
3754    path: path of executable file\n\
3755    args: tuple or list of arguments\n\
3756    env: dictionary of strings mapping to strings");
3757
3758static PyObject *
3759posix_spawnve(PyObject *self, PyObject *args)
3760{
3761    PyObject *opath;
3762    char *path;
3763    PyObject *argv, *env;
3764    char **argvlist;
3765    char **envlist;
3766    PyObject *res = NULL;
3767    int mode;
3768    Py_ssize_t argc, i, envc;
3769    Py_intptr_t spawnval;
3770    PyObject *(*getitem)(PyObject *, Py_ssize_t);
3771    Py_ssize_t lastarg = 0;
3772
3773    /* spawnve has four arguments: (mode, path, argv, env), where
3774       argv is a list or tuple of strings and env is a dictionary
3775       like posix.environ. */
3776
3777    if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode,
3778                          PyUnicode_FSConverter,
3779                          &opath, &argv, &env))
3780        return NULL;
3781    path = PyBytes_AsString(opath);
3782    if (PyList_Check(argv)) {
3783        argc = PyList_Size(argv);
3784        getitem = PyList_GetItem;
3785    }
3786    else if (PyTuple_Check(argv)) {
3787        argc = PyTuple_Size(argv);
3788        getitem = PyTuple_GetItem;
3789    }
3790    else {
3791        PyErr_SetString(PyExc_TypeError,
3792                        "spawnve() arg 2 must be a tuple or list");
3793        goto fail_0;
3794    }
3795    if (!PyMapping_Check(env)) {
3796        PyErr_SetString(PyExc_TypeError,
3797                        "spawnve() arg 3 must be a mapping object");
3798        goto fail_0;
3799    }
3800
3801    argvlist = PyMem_NEW(char *, argc+1);
3802    if (argvlist == NULL) {
3803        PyErr_NoMemory();
3804        goto fail_0;
3805    }
3806    for (i = 0; i < argc; i++) {
3807        if (!fsconvert_strdup((*getitem)(argv, i),
3808                              &argvlist[i]))
3809        {
3810            lastarg = i;
3811            goto fail_1;
3812        }
3813    }
3814    lastarg = argc;
3815    argvlist[argc] = NULL;
3816
3817    envlist = parse_envlist(env, &envc);
3818    if (envlist == NULL)
3819        goto fail_1;
3820
3821#if defined(PYOS_OS2) && defined(PYCC_GCC)
3822    Py_BEGIN_ALLOW_THREADS
3823    spawnval = spawnve(mode, path, argvlist, envlist);
3824    Py_END_ALLOW_THREADS
3825#else
3826    if (mode == _OLD_P_OVERLAY)
3827        mode = _P_OVERLAY;
3828
3829    Py_BEGIN_ALLOW_THREADS
3830    spawnval = _spawnve(mode, path, argvlist, envlist);
3831    Py_END_ALLOW_THREADS
3832#endif
3833
3834    if (spawnval == -1)
3835        (void) posix_error();
3836    else
3837#if SIZEOF_LONG == SIZEOF_VOID_P
3838        res = Py_BuildValue("l", (long) spawnval);
3839#else
3840        res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3841#endif
3842
3843    while (--envc >= 0)
3844        PyMem_DEL(envlist[envc]);
3845    PyMem_DEL(envlist);
3846  fail_1:
3847    free_string_array(argvlist, lastarg);
3848  fail_0:
3849    Py_DECREF(opath);
3850    return res;
3851}
3852
3853/* OS/2 supports spawnvp & spawnvpe natively */
3854#if defined(PYOS_OS2)
3855PyDoc_STRVAR(posix_spawnvp__doc__,
3856"spawnvp(mode, file, args)\n\n\
3857Execute the program 'file' in a new process, using the environment\n\
3858search path to find the file.\n\
3859\n\
3860    mode: mode of process creation\n\
3861    file: executable file name\n\
3862    args: tuple or list of strings");
3863
3864static PyObject *
3865posix_spawnvp(PyObject *self, PyObject *args)
3866{
3867    PyObject *opath;
3868    char *path;
3869    PyObject *argv;
3870    char **argvlist;
3871    int mode, i, argc;
3872    Py_intptr_t spawnval;
3873    PyObject *(*getitem)(PyObject *, Py_ssize_t);
3874
3875    /* spawnvp has three arguments: (mode, path, argv), where
3876       argv is a list or tuple of strings. */
3877
3878    if (!PyArg_ParseTuple(args, "iO&O:spawnvp", &mode,
3879                          PyUnicode_FSConverter,
3880                          &opath, &argv))
3881        return NULL;
3882    path = PyBytes_AsString(opath);
3883    if (PyList_Check(argv)) {
3884        argc = PyList_Size(argv);
3885        getitem = PyList_GetItem;
3886    }
3887    else if (PyTuple_Check(argv)) {
3888        argc = PyTuple_Size(argv);
3889        getitem = PyTuple_GetItem;
3890    }
3891    else {
3892        PyErr_SetString(PyExc_TypeError,
3893                        "spawnvp() arg 2 must be a tuple or list");
3894        Py_DECREF(opath);
3895        return NULL;
3896    }
3897
3898    argvlist = PyMem_NEW(char *, argc+1);
3899    if (argvlist == NULL) {
3900        Py_DECREF(opath);
3901        return PyErr_NoMemory();
3902    }
3903    for (i = 0; i < argc; i++) {
3904        if (!fsconvert_strdup((*getitem)(argv, i),
3905                              &argvlist[i])) {
3906            free_string_array(argvlist, i);
3907            PyErr_SetString(
3908                PyExc_TypeError,
3909                "spawnvp() arg 2 must contain only strings");
3910            Py_DECREF(opath);
3911            return NULL;
3912        }
3913    }
3914    argvlist[argc] = NULL;
3915
3916    Py_BEGIN_ALLOW_THREADS
3917#if defined(PYCC_GCC)
3918    spawnval = spawnvp(mode, path, argvlist);
3919#else
3920    spawnval = _spawnvp(mode, path, argvlist);
3921#endif
3922    Py_END_ALLOW_THREADS
3923
3924    free_string_array(argvlist, argc);
3925    Py_DECREF(opath);
3926
3927    if (spawnval == -1)
3928        return posix_error();
3929    else
3930        return Py_BuildValue("l", (long) spawnval);
3931}
3932
3933
3934PyDoc_STRVAR(posix_spawnvpe__doc__,
3935"spawnvpe(mode, file, args, env)\n\n\
3936Execute the program 'file' in a new process, using the environment\n\
3937search path to find the file.\n\
3938\n\
3939    mode: mode of process creation\n\
3940    file: executable file name\n\
3941    args: tuple or list of arguments\n\
3942    env: dictionary of strings mapping to strings");
3943
3944static PyObject *
3945posix_spawnvpe(PyObject *self, PyObject *args)
3946{
3947    PyObject *opath
3948    char *path;
3949    PyObject *argv, *env;
3950    char **argvlist;
3951    char **envlist;
3952    PyObject *res=NULL;
3953    int mode;
3954    Py_ssize_t argc, i, envc;
3955    Py_intptr_t spawnval;
3956    PyObject *(*getitem)(PyObject *, Py_ssize_t);
3957    int lastarg = 0;
3958
3959    /* spawnvpe has four arguments: (mode, path, argv, env), where
3960       argv is a list or tuple of strings and env is a dictionary
3961       like posix.environ. */
3962
3963    if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
3964                          PyUnicode_FSConverter,
3965                          &opath, &argv, &env))
3966        return NULL;
3967    path = PyBytes_AsString(opath);
3968    if (PyList_Check(argv)) {
3969        argc = PyList_Size(argv);
3970        getitem = PyList_GetItem;
3971    }
3972    else if (PyTuple_Check(argv)) {
3973        argc = PyTuple_Size(argv);
3974        getitem = PyTuple_GetItem;
3975    }
3976    else {
3977        PyErr_SetString(PyExc_TypeError,
3978                        "spawnvpe() arg 2 must be a tuple or list");
3979        goto fail_0;
3980    }
3981    if (!PyMapping_Check(env)) {
3982        PyErr_SetString(PyExc_TypeError,
3983                        "spawnvpe() arg 3 must be a mapping object");
3984        goto fail_0;
3985    }
3986
3987    argvlist = PyMem_NEW(char *, argc+1);
3988    if (argvlist == NULL) {
3989        PyErr_NoMemory();
3990        goto fail_0;
3991    }
3992    for (i = 0; i < argc; i++) {
3993        if (!fsconvert_strdup((*getitem)(argv, i),
3994                              &argvlist[i]))
3995        {
3996            lastarg = i;
3997            goto fail_1;
3998        }
3999    }
4000    lastarg = argc;
4001    argvlist[argc] = NULL;
4002
4003    envlist = parse_envlist(env, &envc);
4004    if (envlist == NULL)
4005        goto fail_1;
4006
4007    Py_BEGIN_ALLOW_THREADS
4008#if defined(PYCC_GCC)
4009    spawnval = spawnvpe(mode, path, argvlist, envlist);
4010#else
4011    spawnval = _spawnvpe(mode, path, argvlist, envlist);
4012#endif
4013    Py_END_ALLOW_THREADS
4014
4015    if (spawnval == -1)
4016        (void) posix_error();
4017    else
4018        res = Py_BuildValue("l", (long) spawnval);
4019
4020    while (--envc >= 0)
4021        PyMem_DEL(envlist[envc]);
4022    PyMem_DEL(envlist);
4023  fail_1:
4024    free_string_array(argvlist, lastarg);
4025  fail_0:
4026    Py_DECREF(opath);
4027    return res;
4028}
4029#endif /* PYOS_OS2 */
4030#endif /* HAVE_SPAWNV */
4031
4032
4033#ifdef HAVE_FORK1
4034PyDoc_STRVAR(posix_fork1__doc__,
4035"fork1() -> pid\n\n\
4036Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
4037\n\
4038Return 0 to child process and PID of child to parent process.");
4039
4040static PyObject *
4041posix_fork1(PyObject *self, PyObject *noargs)
4042{
4043    pid_t pid;
4044    int result = 0;
4045    _PyImport_AcquireLock();
4046    pid = fork1();
4047    if (pid == 0) {
4048        /* child: this clobbers and resets the import lock. */
4049        PyOS_AfterFork();
4050    } else {
4051        /* parent: release the import lock. */
4052        result = _PyImport_ReleaseLock();
4053    }
4054    if (pid == -1)
4055        return posix_error();
4056    if (result < 0) {
4057        /* Don't clobber the OSError if the fork failed. */
4058        PyErr_SetString(PyExc_RuntimeError,
4059                        "not holding the import lock");
4060        return NULL;
4061    }
4062    return PyLong_FromPid(pid);
4063}
4064#endif
4065
4066
4067#ifdef HAVE_FORK
4068PyDoc_STRVAR(posix_fork__doc__,
4069"fork() -> pid\n\n\
4070Fork a child process.\n\
4071Return 0 to child process and PID of child to parent process.");
4072
4073static PyObject *
4074posix_fork(PyObject *self, PyObject *noargs)
4075{
4076    pid_t pid;
4077    int result = 0;
4078    _PyImport_AcquireLock();
4079    pid = fork();
4080    if (pid == 0) {
4081        /* child: this clobbers and resets the import lock. */
4082        PyOS_AfterFork();
4083    } else {
4084        /* parent: release the import lock. */
4085        result = _PyImport_ReleaseLock();
4086    }
4087    if (pid == -1)
4088        return posix_error();
4089    if (result < 0) {
4090        /* Don't clobber the OSError if the fork failed. */
4091        PyErr_SetString(PyExc_RuntimeError,
4092                        "not holding the import lock");
4093        return NULL;
4094    }
4095    return PyLong_FromPid(pid);
4096}
4097#endif
4098
4099/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
4100/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
4101#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
4102#define DEV_PTY_FILE "/dev/ptc"
4103#define HAVE_DEV_PTMX
4104#else
4105#define DEV_PTY_FILE "/dev/ptmx"
4106#endif
4107
4108#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
4109#ifdef HAVE_PTY_H
4110#include <pty.h>
4111#else
4112#ifdef HAVE_LIBUTIL_H
4113#include <libutil.h>
4114#else
4115#ifdef HAVE_UTIL_H
4116#include <util.h>
4117#endif /* HAVE_UTIL_H */
4118#endif /* HAVE_LIBUTIL_H */
4119#endif /* HAVE_PTY_H */
4120#ifdef HAVE_STROPTS_H
4121#include <stropts.h>
4122#endif
4123#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
4124
4125#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
4126PyDoc_STRVAR(posix_openpty__doc__,
4127"openpty() -> (master_fd, slave_fd)\n\n\
4128Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
4129
4130static PyObject *
4131posix_openpty(PyObject *self, PyObject *noargs)
4132{
4133    int master_fd, slave_fd;
4134#ifndef HAVE_OPENPTY
4135    char * slave_name;
4136#endif
4137#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
4138    PyOS_sighandler_t sig_saved;
4139#ifdef sun
4140    extern char *ptsname(int fildes);
4141#endif
4142#endif
4143
4144#ifdef HAVE_OPENPTY
4145    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
4146        return posix_error();
4147#elif defined(HAVE__GETPTY)
4148    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
4149    if (slave_name == NULL)
4150        return posix_error();
4151
4152    slave_fd = open(slave_name, O_RDWR);
4153    if (slave_fd < 0)
4154        return posix_error();
4155#else
4156    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
4157    if (master_fd < 0)
4158        return posix_error();
4159    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
4160    /* change permission of slave */
4161    if (grantpt(master_fd) < 0) {
4162        PyOS_setsig(SIGCHLD, sig_saved);
4163        return posix_error();
4164    }
4165    /* unlock slave */
4166    if (unlockpt(master_fd) < 0) {
4167        PyOS_setsig(SIGCHLD, sig_saved);
4168        return posix_error();
4169    }
4170    PyOS_setsig(SIGCHLD, sig_saved);
4171    slave_name = ptsname(master_fd); /* get name of slave */
4172    if (slave_name == NULL)
4173        return posix_error();
4174    slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
4175    if (slave_fd < 0)
4176        return posix_error();
4177#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
4178    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
4179    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
4180#ifndef __hpux
4181    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
4182#endif /* __hpux */
4183#endif /* HAVE_CYGWIN */
4184#endif /* HAVE_OPENPTY */
4185
4186    return Py_BuildValue("(ii)", master_fd, slave_fd);
4187
4188}
4189#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
4190
4191#ifdef HAVE_FORKPTY
4192PyDoc_STRVAR(posix_forkpty__doc__,
4193"forkpty() -> (pid, master_fd)\n\n\
4194Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
4195Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
4196To both, return fd of newly opened pseudo-terminal.\n");
4197
4198static PyObject *
4199posix_forkpty(PyObject *self, PyObject *noargs)
4200{
4201    int master_fd = -1, result = 0;
4202    pid_t pid;
4203
4204    _PyImport_AcquireLock();
4205    pid = forkpty(&master_fd, NULL, NULL, NULL);
4206    if (pid == 0) {
4207        /* child: this clobbers and resets the import lock. */
4208        PyOS_AfterFork();
4209    } else {
4210        /* parent: release the import lock. */
4211        result = _PyImport_ReleaseLock();
4212    }
4213    if (pid == -1)
4214        return posix_error();
4215    if (result < 0) {
4216        /* Don't clobber the OSError if the fork failed. */
4217        PyErr_SetString(PyExc_RuntimeError,
4218                        "not holding the import lock");
4219        return NULL;
4220    }
4221    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
4222}
4223#endif
4224
4225#ifdef HAVE_GETEGID
4226PyDoc_STRVAR(posix_getegid__doc__,
4227"getegid() -> egid\n\n\
4228Return the current process's effective group id.");
4229
4230static PyObject *
4231posix_getegid(PyObject *self, PyObject *noargs)
4232{
4233    return PyLong_FromLong((long)getegid());
4234}
4235#endif
4236
4237
4238#ifdef HAVE_GETEUID
4239PyDoc_STRVAR(posix_geteuid__doc__,
4240"geteuid() -> euid\n\n\
4241Return the current process's effective user id.");
4242
4243static PyObject *
4244posix_geteuid(PyObject *self, PyObject *noargs)
4245{
4246    return PyLong_FromLong((long)geteuid());
4247}
4248#endif
4249
4250
4251#ifdef HAVE_GETGID
4252PyDoc_STRVAR(posix_getgid__doc__,
4253"getgid() -> gid\n\n\
4254Return the current process's group id.");
4255
4256static PyObject *
4257posix_getgid(PyObject *self, PyObject *noargs)
4258{
4259    return PyLong_FromLong((long)getgid());
4260}
4261#endif
4262
4263
4264PyDoc_STRVAR(posix_getpid__doc__,
4265"getpid() -> pid\n\n\
4266Return the current process id");
4267
4268static PyObject *
4269posix_getpid(PyObject *self, PyObject *noargs)
4270{
4271    return PyLong_FromPid(getpid());
4272}
4273
4274
4275#ifdef HAVE_GETGROUPS
4276PyDoc_STRVAR(posix_getgroups__doc__,
4277"getgroups() -> list of group IDs\n\n\
4278Return list of supplemental group IDs for the process.");
4279
4280static PyObject *
4281posix_getgroups(PyObject *self, PyObject *noargs)
4282{
4283    PyObject *result = NULL;
4284
4285#ifdef NGROUPS_MAX
4286#define MAX_GROUPS NGROUPS_MAX
4287#else
4288    /* defined to be 16 on Solaris7, so this should be a small number */
4289#define MAX_GROUPS 64
4290#endif
4291    gid_t grouplist[MAX_GROUPS];
4292
4293    /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
4294     * This is a helper variable to store the intermediate result when
4295     * that happens.
4296     *
4297     * To keep the code readable the OSX behaviour is unconditional,
4298     * according to the POSIX spec this should be safe on all unix-y
4299     * systems.
4300     */
4301    gid_t* alt_grouplist = grouplist;
4302    int n;
4303
4304    n = getgroups(MAX_GROUPS, grouplist);
4305    if (n < 0) {
4306        if (errno == EINVAL) {
4307            n = getgroups(0, NULL);
4308            if (n == -1) {
4309                return posix_error();
4310            }
4311            if (n == 0) {
4312                /* Avoid malloc(0) */
4313                alt_grouplist = grouplist;
4314            } else {
4315                alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
4316                if (alt_grouplist == NULL) {
4317                    errno = EINVAL;
4318                    return posix_error();
4319                }
4320                n = getgroups(n, alt_grouplist);
4321                if (n == -1) {
4322                    PyMem_Free(alt_grouplist);
4323                    return posix_error();
4324                }
4325            }
4326        } else {
4327            return posix_error();
4328        }
4329    }
4330    result = PyList_New(n);
4331    if (result != NULL) {
4332        int i;
4333        for (i = 0; i < n; ++i) {
4334            PyObject *o = PyLong_FromLong((long)alt_grouplist[i]);
4335            if (o == NULL) {
4336                Py_DECREF(result);
4337                result = NULL;
4338                break;
4339            }
4340            PyList_SET_ITEM(result, i, o);
4341        }
4342    }
4343
4344    if (alt_grouplist != grouplist) {
4345        PyMem_Free(alt_grouplist);
4346    }
4347
4348    return result;
4349}
4350#endif
4351
4352#ifdef HAVE_INITGROUPS
4353PyDoc_STRVAR(posix_initgroups__doc__,
4354"initgroups(username, gid) -> None\n\n\
4355Call the system initgroups() to initialize the group access list with all of\n\
4356the groups of which the specified username is a member, plus the specified\n\
4357group id.");
4358
4359static PyObject *
4360posix_initgroups(PyObject *self, PyObject *args)
4361{
4362    PyObject *oname;
4363    char *username;
4364    int res;
4365    long gid;
4366
4367    if (!PyArg_ParseTuple(args, "O&l:initgroups",
4368                          PyUnicode_FSConverter, &oname, &gid))
4369        return NULL;
4370    username = PyBytes_AS_STRING(oname);
4371
4372    res = initgroups(username, (gid_t) gid);
4373    Py_DECREF(oname);
4374    if (res == -1)
4375        return PyErr_SetFromErrno(PyExc_OSError);
4376
4377    Py_INCREF(Py_None);
4378    return Py_None;
4379}
4380#endif
4381
4382#ifdef HAVE_GETPGID
4383PyDoc_STRVAR(posix_getpgid__doc__,
4384"getpgid(pid) -> pgid\n\n\
4385Call the system call getpgid().");
4386
4387static PyObject *
4388posix_getpgid(PyObject *self, PyObject *args)
4389{
4390    pid_t pid, pgid;
4391    if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getpgid", &pid))
4392        return NULL;
4393    pgid = getpgid(pid);
4394    if (pgid < 0)
4395        return posix_error();
4396    return PyLong_FromPid(pgid);
4397}
4398#endif /* HAVE_GETPGID */
4399
4400
4401#ifdef HAVE_GETPGRP
4402PyDoc_STRVAR(posix_getpgrp__doc__,
4403"getpgrp() -> pgrp\n\n\
4404Return the current process group id.");
4405
4406static PyObject *
4407posix_getpgrp(PyObject *self, PyObject *noargs)
4408{
4409#ifdef GETPGRP_HAVE_ARG
4410    return PyLong_FromPid(getpgrp(0));
4411#else /* GETPGRP_HAVE_ARG */
4412    return PyLong_FromPid(getpgrp());
4413#endif /* GETPGRP_HAVE_ARG */
4414}
4415#endif /* HAVE_GETPGRP */
4416
4417
4418#ifdef HAVE_SETPGRP
4419PyDoc_STRVAR(posix_setpgrp__doc__,
4420"setpgrp()\n\n\
4421Make this process the process group leader.");
4422
4423static PyObject *
4424posix_setpgrp(PyObject *self, PyObject *noargs)
4425{
4426#ifdef SETPGRP_HAVE_ARG
4427    if (setpgrp(0, 0) < 0)
4428#else /* SETPGRP_HAVE_ARG */
4429    if (setpgrp() < 0)
4430#endif /* SETPGRP_HAVE_ARG */
4431        return posix_error();
4432    Py_INCREF(Py_None);
4433    return Py_None;
4434}
4435
4436#endif /* HAVE_SETPGRP */
4437
4438#ifdef HAVE_GETPPID
4439
4440#ifdef MS_WINDOWS
4441#include <tlhelp32.h>
4442
4443static PyObject*
4444win32_getppid()
4445{
4446    HANDLE snapshot;
4447    pid_t mypid;
4448    PyObject* result = NULL;
4449    BOOL have_record;
4450    PROCESSENTRY32 pe;
4451
4452    mypid = getpid(); /* This function never fails */
4453
4454    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
4455    if (snapshot == INVALID_HANDLE_VALUE)
4456        return PyErr_SetFromWindowsErr(GetLastError());
4457
4458    pe.dwSize = sizeof(pe);
4459    have_record = Process32First(snapshot, &pe);
4460    while (have_record) {
4461        if (mypid == (pid_t)pe.th32ProcessID) {
4462            /* We could cache the ulong value in a static variable. */
4463            result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
4464            break;
4465        }
4466
4467        have_record = Process32Next(snapshot, &pe);
4468    }
4469
4470    /* If our loop exits and our pid was not found (result will be NULL)
4471     * then GetLastError will return ERROR_NO_MORE_FILES. This is an
4472     * error anyway, so let's raise it. */
4473    if (!result)
4474        result = PyErr_SetFromWindowsErr(GetLastError());
4475
4476    CloseHandle(snapshot);
4477
4478    return result;
4479}
4480#endif /*MS_WINDOWS*/
4481
4482PyDoc_STRVAR(posix_getppid__doc__,
4483"getppid() -> ppid\n\n\
4484Return the parent's process id.  If the parent process has already exited,\n\
4485Windows machines will still return its id; others systems will return the id\n\
4486of the 'init' process (1).");
4487
4488static PyObject *
4489posix_getppid(PyObject *self, PyObject *noargs)
4490{
4491#ifdef MS_WINDOWS
4492    return win32_getppid();
4493#else
4494    return PyLong_FromPid(getppid());
4495#endif
4496}
4497#endif /* HAVE_GETPPID */
4498
4499
4500#ifdef HAVE_GETLOGIN
4501PyDoc_STRVAR(posix_getlogin__doc__,
4502"getlogin() -> string\n\n\
4503Return the actual login name.");
4504
4505static PyObject *
4506posix_getlogin(PyObject *self, PyObject *noargs)
4507{
4508    PyObject *result = NULL;
4509#ifdef MS_WINDOWS
4510    wchar_t user_name[UNLEN + 1];
4511    DWORD num_chars = sizeof(user_name)/sizeof(user_name[0]);
4512
4513    if (GetUserNameW(user_name, &num_chars)) {
4514        /* num_chars is the number of unicode chars plus null terminator */
4515        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
4516    }
4517    else
4518        result = PyErr_SetFromWindowsErr(GetLastError());
4519#else
4520    char *name;
4521    int old_errno = errno;
4522
4523    errno = 0;
4524    name = getlogin();
4525    if (name == NULL) {
4526        if (errno)
4527            posix_error();
4528        else
4529            PyErr_SetString(PyExc_OSError, "unable to determine login name");
4530    }
4531    else
4532        result = PyUnicode_DecodeFSDefault(name);
4533    errno = old_errno;
4534#endif
4535    return result;
4536}
4537#endif /* HAVE_GETLOGIN */
4538
4539#ifdef HAVE_GETUID
4540PyDoc_STRVAR(posix_getuid__doc__,
4541"getuid() -> uid\n\n\
4542Return the current process's user id.");
4543
4544static PyObject *
4545posix_getuid(PyObject *self, PyObject *noargs)
4546{
4547    return PyLong_FromLong((long)getuid());
4548}
4549#endif
4550
4551
4552#ifdef HAVE_KILL
4553PyDoc_STRVAR(posix_kill__doc__,
4554"kill(pid, sig)\n\n\
4555Kill a process with a signal.");
4556
4557static PyObject *
4558posix_kill(PyObject *self, PyObject *args)
4559{
4560    pid_t pid;
4561    int sig;
4562    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:kill", &pid, &sig))
4563        return NULL;
4564#if defined(PYOS_OS2) && !defined(PYCC_GCC)
4565    if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
4566        APIRET rc;
4567        if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
4568            return os2_error(rc);
4569
4570    } else if (sig == XCPT_SIGNAL_KILLPROC) {
4571        APIRET rc;
4572        if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
4573            return os2_error(rc);
4574
4575    } else
4576        return NULL; /* Unrecognized Signal Requested */
4577#else
4578    if (kill(pid, sig) == -1)
4579        return posix_error();
4580#endif
4581    Py_INCREF(Py_None);
4582    return Py_None;
4583}
4584#endif
4585
4586#ifdef HAVE_KILLPG
4587PyDoc_STRVAR(posix_killpg__doc__,
4588"killpg(pgid, sig)\n\n\
4589Kill a process group with a signal.");
4590
4591static PyObject *
4592posix_killpg(PyObject *self, PyObject *args)
4593{
4594    int sig;
4595    pid_t pgid;
4596    /* XXX some man pages make the `pgid` parameter an int, others
4597       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
4598       take the same type. Moreover, pid_t is always at least as wide as
4599       int (else compilation of this module fails), which is safe. */
4600    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:killpg", &pgid, &sig))
4601        return NULL;
4602    if (killpg(pgid, sig) == -1)
4603        return posix_error();
4604    Py_INCREF(Py_None);
4605    return Py_None;
4606}
4607#endif
4608
4609#ifdef MS_WINDOWS
4610PyDoc_STRVAR(win32_kill__doc__,
4611"kill(pid, sig)\n\n\
4612Kill a process with a signal.");
4613
4614static PyObject *
4615win32_kill(PyObject *self, PyObject *args)
4616{
4617    PyObject *result;
4618    DWORD pid, sig, err;
4619    HANDLE handle;
4620
4621    if (!PyArg_ParseTuple(args, "kk:kill", &pid, &sig))
4622        return NULL;
4623
4624    /* Console processes which share a common console can be sent CTRL+C or
4625       CTRL+BREAK events, provided they handle said events. */
4626    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
4627        if (GenerateConsoleCtrlEvent(sig, pid) == 0) {
4628            err = GetLastError();
4629            PyErr_SetFromWindowsErr(err);
4630        }
4631        else
4632            Py_RETURN_NONE;
4633    }
4634
4635    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
4636       attempt to open and terminate the process. */
4637    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
4638    if (handle == NULL) {
4639        err = GetLastError();
4640        return PyErr_SetFromWindowsErr(err);
4641    }
4642
4643    if (TerminateProcess(handle, sig) == 0) {
4644        err = GetLastError();
4645        result = PyErr_SetFromWindowsErr(err);
4646    } else {
4647        Py_INCREF(Py_None);
4648        result = Py_None;
4649    }
4650
4651    CloseHandle(handle);
4652    return result;
4653}
4654#endif /* MS_WINDOWS */
4655
4656#ifdef HAVE_PLOCK
4657
4658#ifdef HAVE_SYS_LOCK_H
4659#include <sys/lock.h>
4660#endif
4661
4662PyDoc_STRVAR(posix_plock__doc__,
4663"plock(op)\n\n\
4664Lock program segments into memory.");
4665
4666static PyObject *
4667posix_plock(PyObject *self, PyObject *args)
4668{
4669    int op;
4670    if (!PyArg_ParseTuple(args, "i:plock", &op))
4671        return NULL;
4672    if (plock(op) == -1)
4673        return posix_error();
4674    Py_INCREF(Py_None);
4675    return Py_None;
4676}
4677#endif
4678
4679#ifdef HAVE_SETUID
4680PyDoc_STRVAR(posix_setuid__doc__,
4681"setuid(uid)\n\n\
4682Set the current process's user id.");
4683
4684static PyObject *
4685posix_setuid(PyObject *self, PyObject *args)
4686{
4687    long uid_arg;
4688    uid_t uid;
4689    if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
4690        return NULL;
4691    uid = uid_arg;
4692    if (uid != uid_arg) {
4693        PyErr_SetString(PyExc_OverflowError, "user id too big");
4694        return NULL;
4695    }
4696    if (setuid(uid) < 0)
4697        return posix_error();
4698    Py_INCREF(Py_None);
4699    return Py_None;
4700}
4701#endif /* HAVE_SETUID */
4702
4703
4704#ifdef HAVE_SETEUID
4705PyDoc_STRVAR(posix_seteuid__doc__,
4706"seteuid(uid)\n\n\
4707Set the current process's effective user id.");
4708
4709static PyObject *
4710posix_seteuid (PyObject *self, PyObject *args)
4711{
4712    long euid_arg;
4713    uid_t euid;
4714    if (!PyArg_ParseTuple(args, "l", &euid_arg))
4715        return NULL;
4716    euid = euid_arg;
4717    if (euid != euid_arg) {
4718        PyErr_SetString(PyExc_OverflowError, "user id too big");
4719        return NULL;
4720    }
4721    if (seteuid(euid) < 0) {
4722        return posix_error();
4723    } else {
4724        Py_INCREF(Py_None);
4725        return Py_None;
4726    }
4727}
4728#endif /* HAVE_SETEUID */
4729
4730#ifdef HAVE_SETEGID
4731PyDoc_STRVAR(posix_setegid__doc__,
4732"setegid(gid)\n\n\
4733Set the current process's effective group id.");
4734
4735static PyObject *
4736posix_setegid (PyObject *self, PyObject *args)
4737{
4738    long egid_arg;
4739    gid_t egid;
4740    if (!PyArg_ParseTuple(args, "l", &egid_arg))
4741        return NULL;
4742    egid = egid_arg;
4743    if (egid != egid_arg) {
4744        PyErr_SetString(PyExc_OverflowError, "group id too big");
4745        return NULL;
4746    }
4747    if (setegid(egid) < 0) {
4748        return posix_error();
4749    } else {
4750        Py_INCREF(Py_None);
4751        return Py_None;
4752    }
4753}
4754#endif /* HAVE_SETEGID */
4755
4756#ifdef HAVE_SETREUID
4757PyDoc_STRVAR(posix_setreuid__doc__,
4758"setreuid(ruid, euid)\n\n\
4759Set the current process's real and effective user ids.");
4760
4761static PyObject *
4762posix_setreuid (PyObject *self, PyObject *args)
4763{
4764    long ruid_arg, euid_arg;
4765    uid_t ruid, euid;
4766    if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
4767        return NULL;
4768    if (ruid_arg == -1)
4769        ruid = (uid_t)-1;  /* let the compiler choose how -1 fits */
4770    else
4771        ruid = ruid_arg;  /* otherwise, assign from our long */
4772    if (euid_arg == -1)
4773        euid = (uid_t)-1;
4774    else
4775        euid = euid_arg;
4776    if ((euid_arg != -1 && euid != euid_arg) ||
4777        (ruid_arg != -1 && ruid != ruid_arg)) {
4778        PyErr_SetString(PyExc_OverflowError, "user id too big");
4779        return NULL;
4780    }
4781    if (setreuid(ruid, euid) < 0) {
4782        return posix_error();
4783    } else {
4784        Py_INCREF(Py_None);
4785        return Py_None;
4786    }
4787}
4788#endif /* HAVE_SETREUID */
4789
4790#ifdef HAVE_SETREGID
4791PyDoc_STRVAR(posix_setregid__doc__,
4792"setregid(rgid, egid)\n\n\
4793Set the current process's real and effective group ids.");
4794
4795static PyObject *
4796posix_setregid (PyObject *self, PyObject *args)
4797{
4798    long rgid_arg, egid_arg;
4799    gid_t rgid, egid;
4800    if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
4801        return NULL;
4802    if (rgid_arg == -1)
4803        rgid = (gid_t)-1;  /* let the compiler choose how -1 fits */
4804    else
4805        rgid = rgid_arg;  /* otherwise, assign from our long */
4806    if (egid_arg == -1)
4807        egid = (gid_t)-1;
4808    else
4809        egid = egid_arg;
4810    if ((egid_arg != -1 && egid != egid_arg) ||
4811        (rgid_arg != -1 && rgid != rgid_arg)) {
4812        PyErr_SetString(PyExc_OverflowError, "group id too big");
4813        return NULL;
4814    }
4815    if (setregid(rgid, egid) < 0) {
4816        return posix_error();
4817    } else {
4818        Py_INCREF(Py_None);
4819        return Py_None;
4820    }
4821}
4822#endif /* HAVE_SETREGID */
4823
4824#ifdef HAVE_SETGID
4825PyDoc_STRVAR(posix_setgid__doc__,
4826"setgid(gid)\n\n\
4827Set the current process's group id.");
4828
4829static PyObject *
4830posix_setgid(PyObject *self, PyObject *args)
4831{
4832    long gid_arg;
4833    gid_t gid;
4834    if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
4835        return NULL;
4836    gid = gid_arg;
4837    if (gid != gid_arg) {
4838        PyErr_SetString(PyExc_OverflowError, "group id too big");
4839        return NULL;
4840    }
4841    if (setgid(gid) < 0)
4842        return posix_error();
4843    Py_INCREF(Py_None);
4844    return Py_None;
4845}
4846#endif /* HAVE_SETGID */
4847
4848#ifdef HAVE_SETGROUPS
4849PyDoc_STRVAR(posix_setgroups__doc__,
4850"setgroups(list)\n\n\
4851Set the groups of the current process to list.");
4852
4853static PyObject *
4854posix_setgroups(PyObject *self, PyObject *groups)
4855{
4856    int i, len;
4857    gid_t grouplist[MAX_GROUPS];
4858
4859    if (!PySequence_Check(groups)) {
4860        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
4861        return NULL;
4862    }
4863    len = PySequence_Size(groups);
4864    if (len > MAX_GROUPS) {
4865        PyErr_SetString(PyExc_ValueError, "too many groups");
4866        return NULL;
4867    }
4868    for(i = 0; i < len; i++) {
4869        PyObject *elem;
4870        elem = PySequence_GetItem(groups, i);
4871        if (!elem)
4872            return NULL;
4873        if (!PyLong_Check(elem)) {
4874            PyErr_SetString(PyExc_TypeError,
4875                            "groups must be integers");
4876            Py_DECREF(elem);
4877            return NULL;
4878        } else {
4879            unsigned long x = PyLong_AsUnsignedLong(elem);
4880            if (PyErr_Occurred()) {
4881                PyErr_SetString(PyExc_TypeError,
4882                                "group id too big");
4883                Py_DECREF(elem);
4884                return NULL;
4885            }
4886            grouplist[i] = x;
4887            /* read back the value to see if it fitted in gid_t */
4888            if (grouplist[i] != x) {
4889                PyErr_SetString(PyExc_TypeError,
4890                                "group id too big");
4891                Py_DECREF(elem);
4892                return NULL;
4893            }
4894        }
4895        Py_DECREF(elem);
4896    }
4897
4898    if (setgroups(len, grouplist) < 0)
4899        return posix_error();
4900    Py_INCREF(Py_None);
4901    return Py_None;
4902}
4903#endif /* HAVE_SETGROUPS */
4904
4905#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
4906static PyObject *
4907wait_helper(pid_t pid, int status, struct rusage *ru)
4908{
4909    PyObject *result;
4910    static PyObject *struct_rusage;
4911
4912    if (pid == -1)
4913        return posix_error();
4914
4915    if (struct_rusage == NULL) {
4916        PyObject *m = PyImport_ImportModuleNoBlock("resource");
4917        if (m == NULL)
4918            return NULL;
4919        struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
4920        Py_DECREF(m);
4921        if (struct_rusage == NULL)
4922            return NULL;
4923    }
4924
4925    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
4926    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
4927    if (!result)
4928        return NULL;
4929
4930#ifndef doubletime
4931#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
4932#endif
4933
4934    PyStructSequence_SET_ITEM(result, 0,
4935                              PyFloat_FromDouble(doubletime(ru->ru_utime)));
4936    PyStructSequence_SET_ITEM(result, 1,
4937                              PyFloat_FromDouble(doubletime(ru->ru_stime)));
4938#define SET_INT(result, index, value)\
4939        PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
4940    SET_INT(result, 2, ru->ru_maxrss);
4941    SET_INT(result, 3, ru->ru_ixrss);
4942    SET_INT(result, 4, ru->ru_idrss);
4943    SET_INT(result, 5, ru->ru_isrss);
4944    SET_INT(result, 6, ru->ru_minflt);
4945    SET_INT(result, 7, ru->ru_majflt);
4946    SET_INT(result, 8, ru->ru_nswap);
4947    SET_INT(result, 9, ru->ru_inblock);
4948    SET_INT(result, 10, ru->ru_oublock);
4949    SET_INT(result, 11, ru->ru_msgsnd);
4950    SET_INT(result, 12, ru->ru_msgrcv);
4951    SET_INT(result, 13, ru->ru_nsignals);
4952    SET_INT(result, 14, ru->ru_nvcsw);
4953    SET_INT(result, 15, ru->ru_nivcsw);
4954#undef SET_INT
4955
4956    if (PyErr_Occurred()) {
4957        Py_DECREF(result);
4958        return NULL;
4959    }
4960
4961    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
4962}
4963#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
4964
4965#ifdef HAVE_WAIT3
4966PyDoc_STRVAR(posix_wait3__doc__,
4967"wait3(options) -> (pid, status, rusage)\n\n\
4968Wait for completion of a child process.");
4969
4970static PyObject *
4971posix_wait3(PyObject *self, PyObject *args)
4972{
4973    pid_t pid;
4974    int options;
4975    struct rusage ru;
4976    WAIT_TYPE status;
4977    WAIT_STATUS_INT(status) = 0;
4978
4979    if (!PyArg_ParseTuple(args, "i:wait3", &options))
4980        return NULL;
4981
4982    Py_BEGIN_ALLOW_THREADS
4983    pid = wait3(&status, options, &ru);
4984    Py_END_ALLOW_THREADS
4985
4986    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
4987}
4988#endif /* HAVE_WAIT3 */
4989
4990#ifdef HAVE_WAIT4
4991PyDoc_STRVAR(posix_wait4__doc__,
4992"wait4(pid, options) -> (pid, status, rusage)\n\n\
4993Wait for completion of a given child process.");
4994
4995static PyObject *
4996posix_wait4(PyObject *self, PyObject *args)
4997{
4998    pid_t pid;
4999    int options;
5000    struct rusage ru;
5001    WAIT_TYPE status;
5002    WAIT_STATUS_INT(status) = 0;
5003
5004    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
5005        return NULL;
5006
5007    Py_BEGIN_ALLOW_THREADS
5008    pid = wait4(pid, &status, options, &ru);
5009    Py_END_ALLOW_THREADS
5010
5011    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
5012}
5013#endif /* HAVE_WAIT4 */
5014
5015#ifdef HAVE_WAITPID
5016PyDoc_STRVAR(posix_waitpid__doc__,
5017"waitpid(pid, options) -> (pid, status)\n\n\
5018Wait for completion of a given child process.");
5019
5020static PyObject *
5021posix_waitpid(PyObject *self, PyObject *args)
5022{
5023    pid_t pid;
5024    int options;
5025    WAIT_TYPE status;
5026    WAIT_STATUS_INT(status) = 0;
5027
5028    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
5029        return NULL;
5030    Py_BEGIN_ALLOW_THREADS
5031    pid = waitpid(pid, &status, options);
5032    Py_END_ALLOW_THREADS
5033    if (pid == -1)
5034        return posix_error();
5035
5036    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
5037}
5038
5039#elif defined(HAVE_CWAIT)
5040
5041/* MS C has a variant of waitpid() that's usable for most purposes. */
5042PyDoc_STRVAR(posix_waitpid__doc__,
5043"waitpid(pid, options) -> (pid, status << 8)\n\n"
5044"Wait for completion of a given process.  options is ignored on Windows.");
5045
5046static PyObject *
5047posix_waitpid(PyObject *self, PyObject *args)
5048{
5049    Py_intptr_t pid;
5050    int status, options;
5051
5052    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
5053        return NULL;
5054    Py_BEGIN_ALLOW_THREADS
5055    pid = _cwait(&status, pid, options);
5056    Py_END_ALLOW_THREADS
5057    if (pid == -1)
5058        return posix_error();
5059
5060    /* shift the status left a byte so this is more like the POSIX waitpid */
5061    return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
5062}
5063#endif /* HAVE_WAITPID || HAVE_CWAIT */
5064
5065#ifdef HAVE_WAIT
5066PyDoc_STRVAR(posix_wait__doc__,
5067"wait() -> (pid, status)\n\n\
5068Wait for completion of a child process.");
5069
5070static PyObject *
5071posix_wait(PyObject *self, PyObject *noargs)
5072{
5073    pid_t pid;
5074    WAIT_TYPE status;
5075    WAIT_STATUS_INT(status) = 0;
5076
5077    Py_BEGIN_ALLOW_THREADS
5078    pid = wait(&status);
5079    Py_END_ALLOW_THREADS
5080    if (pid == -1)
5081        return posix_error();
5082
5083    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
5084}
5085#endif
5086
5087
5088PyDoc_STRVAR(posix_lstat__doc__,
5089"lstat(path) -> stat result\n\n\
5090Like stat(path), but do not follow symbolic links.");
5091
5092static PyObject *
5093posix_lstat(PyObject *self, PyObject *args)
5094{
5095#ifdef HAVE_LSTAT
5096    return posix_do_stat(self, args, "O&:lstat", lstat, NULL, NULL);
5097#else /* !HAVE_LSTAT */
5098#ifdef MS_WINDOWS
5099    return posix_do_stat(self, args, "O&:lstat", STAT, "U:lstat",
5100                         win32_lstat_w);
5101#else
5102    return posix_do_stat(self, args, "O&:lstat", STAT, NULL, NULL);
5103#endif
5104#endif /* !HAVE_LSTAT */
5105}
5106
5107
5108#ifdef HAVE_READLINK
5109PyDoc_STRVAR(posix_readlink__doc__,
5110"readlink(path) -> path\n\n\
5111Return a string representing the path to which the symbolic link points.");
5112
5113static PyObject *
5114posix_readlink(PyObject *self, PyObject *args)
5115{
5116    PyObject* v;
5117    char buf[MAXPATHLEN];
5118    PyObject *opath;
5119    char *path;
5120    int n;
5121    int arg_is_unicode = 0;
5122
5123    if (!PyArg_ParseTuple(args, "O&:readlink",
5124                          PyUnicode_FSConverter, &opath))
5125        return NULL;
5126    path = PyBytes_AsString(opath);
5127    v = PySequence_GetItem(args, 0);
5128    if (v == NULL) {
5129        Py_DECREF(opath);
5130        return NULL;
5131    }
5132
5133    if (PyUnicode_Check(v)) {
5134        arg_is_unicode = 1;
5135    }
5136    Py_DECREF(v);
5137
5138    Py_BEGIN_ALLOW_THREADS
5139    n = readlink(path, buf, (int) sizeof buf);
5140    Py_END_ALLOW_THREADS
5141    if (n < 0)
5142        return posix_error_with_allocated_filename(opath);
5143
5144    Py_DECREF(opath);
5145    if (arg_is_unicode)
5146        return PyUnicode_DecodeFSDefaultAndSize(buf, n);
5147    else
5148        return PyBytes_FromStringAndSize(buf, n);
5149}
5150#endif /* HAVE_READLINK */
5151
5152
5153#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
5154PyDoc_STRVAR(posix_symlink__doc__,
5155"symlink(src, dst)\n\n\
5156Create a symbolic link pointing to src named dst.");
5157
5158static PyObject *
5159posix_symlink(PyObject *self, PyObject *args)
5160{
5161    return posix_2str(args, "O&O&:symlink", symlink);
5162}
5163#endif /* HAVE_SYMLINK */
5164
5165#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
5166
5167PyDoc_STRVAR(win_readlink__doc__,
5168"readlink(path) -> path\n\n\
5169Return a string representing the path to which the symbolic link points.");
5170
5171/* Windows readlink implementation */
5172static PyObject *
5173win_readlink(PyObject *self, PyObject *args)
5174{
5175    wchar_t *path;
5176    DWORD n_bytes_returned;
5177    DWORD io_result;
5178    PyObject *result;
5179    HANDLE reparse_point_handle;
5180
5181    char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
5182    REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
5183    wchar_t *print_name;
5184
5185    if (!PyArg_ParseTuple(args,
5186                  "u:readlink",
5187                  &path))
5188        return NULL;
5189
5190    /* First get a handle to the reparse point */
5191    Py_BEGIN_ALLOW_THREADS
5192    reparse_point_handle = CreateFileW(
5193        path,
5194        0,
5195        0,
5196        0,
5197        OPEN_EXISTING,
5198        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
5199        0);
5200    Py_END_ALLOW_THREADS
5201
5202    if (reparse_point_handle==INVALID_HANDLE_VALUE)
5203    {
5204        return win32_error_unicode("readlink", path);
5205    }
5206
5207    Py_BEGIN_ALLOW_THREADS
5208    /* New call DeviceIoControl to read the reparse point */
5209    io_result = DeviceIoControl(
5210        reparse_point_handle,
5211        FSCTL_GET_REPARSE_POINT,
5212        0, 0, /* in buffer */
5213        target_buffer, sizeof(target_buffer),
5214        &n_bytes_returned,
5215        0 /* we're not using OVERLAPPED_IO */
5216        );
5217    CloseHandle(reparse_point_handle);
5218    Py_END_ALLOW_THREADS
5219
5220    if (io_result==0)
5221    {
5222        return win32_error_unicode("readlink", path);
5223    }
5224
5225    if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
5226    {
5227        PyErr_SetString(PyExc_ValueError,
5228                "not a symbolic link");
5229        return NULL;
5230    }
5231    print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
5232                 rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
5233
5234    result = PyUnicode_FromWideChar(print_name,
5235                    rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
5236    return result;
5237}
5238
5239#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
5240
5241#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
5242
5243/* Grab CreateSymbolicLinkW dynamically from kernel32 */
5244static int has_CreateSymbolicLinkW = 0;
5245static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD);
5246static int
5247check_CreateSymbolicLinkW()
5248{
5249    HINSTANCE hKernel32;
5250    /* only recheck */
5251    if (has_CreateSymbolicLinkW)
5252        return has_CreateSymbolicLinkW;
5253    hKernel32 = GetModuleHandle("KERNEL32");
5254    *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
5255                                                        "CreateSymbolicLinkW");
5256    if (Py_CreateSymbolicLinkW)
5257        has_CreateSymbolicLinkW = 1;
5258    return has_CreateSymbolicLinkW;
5259}
5260
5261PyDoc_STRVAR(win_symlink__doc__,
5262"symlink(src, dst, target_is_directory=False)\n\n\
5263Create a symbolic link pointing to src named dst.\n\
5264target_is_directory is required if the target is to be interpreted as\n\
5265a directory.\n\
5266This function requires Windows 6.0 or greater, and raises a\n\
5267NotImplementedError otherwise.");
5268
5269static PyObject *
5270win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
5271{
5272    static char *kwlist[] = {"src", "dest", "target_is_directory", NULL};
5273    PyObject *src, *dest;
5274    int target_is_directory = 0;
5275    DWORD res;
5276    WIN32_FILE_ATTRIBUTE_DATA src_info;
5277
5278    if (!check_CreateSymbolicLinkW())
5279    {
5280        /* raise NotImplementedError */
5281        return PyErr_Format(PyExc_NotImplementedError,
5282            "CreateSymbolicLinkW not found");
5283    }
5284    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:symlink",
5285        kwlist, &src, &dest, &target_is_directory))
5286        return NULL;
5287
5288    if (win32_can_symlink == 0)
5289        return PyErr_Format(PyExc_OSError, "symbolic link privilege not held");
5290
5291    if (!convert_to_unicode(&src)) { return NULL; }
5292    if (!convert_to_unicode(&dest)) {
5293        Py_DECREF(src);
5294        return NULL;
5295    }
5296
5297    /* if src is a directory, ensure target_is_directory==1 */
5298    if(
5299        GetFileAttributesExW(
5300            PyUnicode_AsUnicode(src), GetFileExInfoStandard, &src_info
5301        ))
5302    {
5303        target_is_directory = target_is_directory ||
5304            (src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5305    }
5306
5307    Py_BEGIN_ALLOW_THREADS
5308    res = Py_CreateSymbolicLinkW(
5309        PyUnicode_AsUnicode(dest),
5310        PyUnicode_AsUnicode(src),
5311        target_is_directory);
5312    Py_END_ALLOW_THREADS
5313    Py_DECREF(src);
5314    Py_DECREF(dest);
5315    if (!res)
5316    {
5317        return win32_error_unicode("symlink", PyUnicode_AsUnicode(src));
5318    }
5319
5320    Py_INCREF(Py_None);
5321    return Py_None;
5322}
5323#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
5324
5325#ifdef HAVE_TIMES
5326#if defined(PYCC_VACPP) && defined(PYOS_OS2)
5327static long
5328system_uptime(void)
5329{
5330    ULONG     value = 0;
5331
5332    Py_BEGIN_ALLOW_THREADS
5333    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
5334    Py_END_ALLOW_THREADS
5335
5336    return value;
5337}
5338
5339static PyObject *
5340posix_times(PyObject *self, PyObject *noargs)
5341{
5342    /* Currently Only Uptime is Provided -- Others Later */
5343    return Py_BuildValue("ddddd",
5344                         (double)0 /* t.tms_utime / HZ */,
5345                         (double)0 /* t.tms_stime / HZ */,
5346                         (double)0 /* t.tms_cutime / HZ */,
5347                         (double)0 /* t.tms_cstime / HZ */,
5348                         (double)system_uptime() / 1000);
5349}
5350#else /* not OS2 */
5351#define NEED_TICKS_PER_SECOND
5352static long ticks_per_second = -1;
5353static PyObject *
5354posix_times(PyObject *self, PyObject *noargs)
5355{
5356    struct tms t;
5357    clock_t c;
5358    errno = 0;
5359    c = times(&t);
5360    if (c == (clock_t) -1)
5361        return posix_error();
5362    return Py_BuildValue("ddddd",
5363                         (double)t.tms_utime / ticks_per_second,
5364                         (double)t.tms_stime / ticks_per_second,
5365                         (double)t.tms_cutime / ticks_per_second,
5366                         (double)t.tms_cstime / ticks_per_second,
5367                         (double)c / ticks_per_second);
5368}
5369#endif /* not OS2 */
5370#endif /* HAVE_TIMES */
5371
5372
5373#ifdef MS_WINDOWS
5374#define HAVE_TIMES      /* so the method table will pick it up */
5375static PyObject *
5376posix_times(PyObject *self, PyObject *noargs)
5377{
5378    FILETIME create, exit, kernel, user;
5379    HANDLE hProc;
5380    hProc = GetCurrentProcess();
5381    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
5382    /* The fields of a FILETIME structure are the hi and lo part
5383       of a 64-bit value expressed in 100 nanosecond units.
5384       1e7 is one second in such units; 1e-7 the inverse.
5385       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
5386    */
5387    return Py_BuildValue(
5388        "ddddd",
5389        (double)(user.dwHighDateTime*429.4967296 +
5390                 user.dwLowDateTime*1e-7),
5391        (double)(kernel.dwHighDateTime*429.4967296 +
5392                 kernel.dwLowDateTime*1e-7),
5393        (double)0,
5394        (double)0,
5395        (double)0);
5396}
5397#endif /* MS_WINDOWS */
5398
5399#ifdef HAVE_TIMES
5400PyDoc_STRVAR(posix_times__doc__,
5401"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
5402Return a tuple of floating point numbers indicating process times.");
5403#endif
5404
5405
5406#ifdef HAVE_GETSID
5407PyDoc_STRVAR(posix_getsid__doc__,
5408"getsid(pid) -> sid\n\n\
5409Call the system call getsid().");
5410
5411static PyObject *
5412posix_getsid(PyObject *self, PyObject *args)
5413{
5414    pid_t pid;
5415    int sid;
5416    if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getsid", &pid))
5417        return NULL;
5418    sid = getsid(pid);
5419    if (sid < 0)
5420        return posix_error();
5421    return PyLong_FromLong((long)sid);
5422}
5423#endif /* HAVE_GETSID */
5424
5425
5426#ifdef HAVE_SETSID
5427PyDoc_STRVAR(posix_setsid__doc__,
5428"setsid()\n\n\
5429Call the system call setsid().");
5430
5431static PyObject *
5432posix_setsid(PyObject *self, PyObject *noargs)
5433{
5434    if (setsid() < 0)
5435        return posix_error();
5436    Py_INCREF(Py_None);
5437    return Py_None;
5438}
5439#endif /* HAVE_SETSID */
5440
5441#ifdef HAVE_SETPGID
5442PyDoc_STRVAR(posix_setpgid__doc__,
5443"setpgid(pid, pgrp)\n\n\
5444Call the system call setpgid().");
5445
5446static PyObject *
5447posix_setpgid(PyObject *self, PyObject *args)
5448{
5449    pid_t pid;
5450    int pgrp;
5451    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:setpgid", &pid, &pgrp))
5452        return NULL;
5453    if (setpgid(pid, pgrp) < 0)
5454        return posix_error();
5455    Py_INCREF(Py_None);
5456    return Py_None;
5457}
5458#endif /* HAVE_SETPGID */
5459
5460
5461#ifdef HAVE_TCGETPGRP
5462PyDoc_STRVAR(posix_tcgetpgrp__doc__,
5463"tcgetpgrp(fd) -> pgid\n\n\
5464Return the process group associated with the terminal given by a fd.");
5465
5466static PyObject *
5467posix_tcgetpgrp(PyObject *self, PyObject *args)
5468{
5469    int fd;
5470    pid_t pgid;
5471    if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
5472        return NULL;
5473    pgid = tcgetpgrp(fd);
5474    if (pgid < 0)
5475        return posix_error();
5476    return PyLong_FromPid(pgid);
5477}
5478#endif /* HAVE_TCGETPGRP */
5479
5480
5481#ifdef HAVE_TCSETPGRP
5482PyDoc_STRVAR(posix_tcsetpgrp__doc__,
5483"tcsetpgrp(fd, pgid)\n\n\
5484Set the process group associated with the terminal given by a fd.");
5485
5486static PyObject *
5487posix_tcsetpgrp(PyObject *self, PyObject *args)
5488{
5489    int fd;
5490    pid_t pgid;
5491    if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid))
5492        return NULL;
5493    if (tcsetpgrp(fd, pgid) < 0)
5494        return posix_error();
5495    Py_INCREF(Py_None);
5496    return Py_None;
5497}
5498#endif /* HAVE_TCSETPGRP */
5499
5500/* Functions acting on file descriptors */
5501
5502PyDoc_STRVAR(posix_open__doc__,
5503"open(filename, flag [, mode=0777]) -> fd\n\n\
5504Open a file (for low level IO).");
5505
5506static PyObject *
5507posix_open(PyObject *self, PyObject *args)
5508{
5509    PyObject *ofile;
5510    char *file;
5511    int flag;
5512    int mode = 0777;
5513    int fd;
5514
5515#ifdef MS_WINDOWS
5516    PyUnicodeObject *po;
5517    if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) {
5518        Py_BEGIN_ALLOW_THREADS
5519        /* PyUnicode_AS_UNICODE OK without thread
5520           lock as it is a simple dereference. */
5521        fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode);
5522        Py_END_ALLOW_THREADS
5523        if (fd < 0)
5524            return posix_error();
5525        return PyLong_FromLong((long)fd);
5526    }
5527    /* Drop the argument parsing error as narrow strings
5528       are also valid. */
5529    PyErr_Clear();
5530#endif
5531
5532    if (!PyArg_ParseTuple(args, "O&i|i",
5533                          PyUnicode_FSConverter, &ofile,
5534                          &flag, &mode))
5535        return NULL;
5536    file = PyBytes_AsString(ofile);
5537    Py_BEGIN_ALLOW_THREADS
5538    fd = open(file, flag, mode);
5539    Py_END_ALLOW_THREADS
5540    if (fd < 0)
5541        return posix_error_with_allocated_filename(ofile);
5542    Py_DECREF(ofile);
5543    return PyLong_FromLong((long)fd);
5544}
5545
5546
5547PyDoc_STRVAR(posix_close__doc__,
5548"close(fd)\n\n\
5549Close a file descriptor (for low level IO).");
5550
5551static PyObject *
5552posix_close(PyObject *self, PyObject *args)
5553{
5554    int fd, res;
5555    if (!PyArg_ParseTuple(args, "i:close", &fd))
5556        return NULL;
5557    if (!_PyVerify_fd(fd))
5558        return posix_error();
5559    Py_BEGIN_ALLOW_THREADS
5560    res = close(fd);
5561    Py_END_ALLOW_THREADS
5562    if (res < 0)
5563        return posix_error();
5564    Py_INCREF(Py_None);
5565    return Py_None;
5566}
5567
5568
5569PyDoc_STRVAR(posix_closerange__doc__,
5570"closerange(fd_low, fd_high)\n\n\
5571Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
5572
5573static PyObject *
5574posix_closerange(PyObject *self, PyObject *args)
5575{
5576    int fd_from, fd_to, i;
5577    if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
5578        return NULL;
5579    Py_BEGIN_ALLOW_THREADS
5580    for (i = fd_from; i < fd_to; i++)
5581        if (_PyVerify_fd(i))
5582            close(i);
5583    Py_END_ALLOW_THREADS
5584    Py_RETURN_NONE;
5585}
5586
5587
5588PyDoc_STRVAR(posix_dup__doc__,
5589"dup(fd) -> fd2\n\n\
5590Return a duplicate of a file descriptor.");
5591
5592static PyObject *
5593posix_dup(PyObject *self, PyObject *args)
5594{
5595    int fd;
5596    if (!PyArg_ParseTuple(args, "i:dup", &fd))
5597        return NULL;
5598    if (!_PyVerify_fd(fd))
5599        return posix_error();
5600    Py_BEGIN_ALLOW_THREADS
5601    fd = dup(fd);
5602    Py_END_ALLOW_THREADS
5603    if (fd < 0)
5604        return posix_error();
5605    return PyLong_FromLong((long)fd);
5606}
5607
5608
5609PyDoc_STRVAR(posix_dup2__doc__,
5610"dup2(old_fd, new_fd)\n\n\
5611Duplicate file descriptor.");
5612
5613static PyObject *
5614posix_dup2(PyObject *self, PyObject *args)
5615{
5616    int fd, fd2, res;
5617    if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
5618        return NULL;
5619    if (!_PyVerify_fd_dup2(fd, fd2))
5620        return posix_error();
5621    Py_BEGIN_ALLOW_THREADS
5622    res = dup2(fd, fd2);
5623    Py_END_ALLOW_THREADS
5624    if (res < 0)
5625        return posix_error();
5626    Py_INCREF(Py_None);
5627    return Py_None;
5628}
5629
5630
5631PyDoc_STRVAR(posix_lseek__doc__,
5632"lseek(fd, pos, how) -> newpos\n\n\
5633Set the current position of a file descriptor.");
5634
5635static PyObject *
5636posix_lseek(PyObject *self, PyObject *args)
5637{
5638    int fd, how;
5639#if defined(MS_WIN64) || defined(MS_WINDOWS)
5640    PY_LONG_LONG pos, res;
5641#else
5642    off_t pos, res;
5643#endif
5644    PyObject *posobj;
5645    if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
5646        return NULL;
5647#ifdef SEEK_SET
5648    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
5649    switch (how) {
5650    case 0: how = SEEK_SET; break;
5651    case 1: how = SEEK_CUR; break;
5652    case 2: how = SEEK_END; break;
5653    }
5654#endif /* SEEK_END */
5655
5656#if !defined(HAVE_LARGEFILE_SUPPORT)
5657    pos = PyLong_AsLong(posobj);
5658#else
5659    pos = PyLong_Check(posobj) ?
5660        PyLong_AsLongLong(posobj) : PyLong_AsLong(posobj);
5661#endif
5662    if (PyErr_Occurred())
5663        return NULL;
5664
5665    if (!_PyVerify_fd(fd))
5666        return posix_error();
5667    Py_BEGIN_ALLOW_THREADS
5668#if defined(MS_WIN64) || defined(MS_WINDOWS)
5669    res = _lseeki64(fd, pos, how);
5670#else
5671    res = lseek(fd, pos, how);
5672#endif
5673    Py_END_ALLOW_THREADS
5674    if (res < 0)
5675        return posix_error();
5676
5677#if !defined(HAVE_LARGEFILE_SUPPORT)
5678    return PyLong_FromLong(res);
5679#else
5680    return PyLong_FromLongLong(res);
5681#endif
5682}
5683
5684
5685PyDoc_STRVAR(posix_read__doc__,
5686"read(fd, buffersize) -> string\n\n\
5687Read a file descriptor.");
5688
5689static PyObject *
5690posix_read(PyObject *self, PyObject *args)
5691{
5692    int fd, size;
5693    Py_ssize_t n;
5694    PyObject *buffer;
5695    if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
5696        return NULL;
5697    if (size < 0) {
5698        errno = EINVAL;
5699        return posix_error();
5700    }
5701    buffer = PyBytes_FromStringAndSize((char *)NULL, size);
5702    if (buffer == NULL)
5703        return NULL;
5704    if (!_PyVerify_fd(fd)) {
5705        Py_DECREF(buffer);
5706        return posix_error();
5707    }
5708    Py_BEGIN_ALLOW_THREADS
5709    n = read(fd, PyBytes_AS_STRING(buffer), size);
5710    Py_END_ALLOW_THREADS
5711    if (n < 0) {
5712        Py_DECREF(buffer);
5713        return posix_error();
5714    }
5715    if (n != size)
5716        _PyBytes_Resize(&buffer, n);
5717    return buffer;
5718}
5719
5720
5721PyDoc_STRVAR(posix_write__doc__,
5722"write(fd, string) -> byteswritten\n\n\
5723Write a string to a file descriptor.");
5724
5725static PyObject *
5726posix_write(PyObject *self, PyObject *args)
5727{
5728    Py_buffer pbuf;
5729    int fd;
5730    Py_ssize_t size, len;
5731
5732    if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
5733        return NULL;
5734    if (!_PyVerify_fd(fd)) {
5735        PyBuffer_Release(&pbuf);
5736        return posix_error();
5737    }
5738    len = pbuf.len;
5739    Py_BEGIN_ALLOW_THREADS
5740#if defined(MS_WIN64) || defined(MS_WINDOWS)
5741    if (len > INT_MAX)
5742        len = INT_MAX;
5743    size = write(fd, pbuf.buf, (int)len);
5744#else
5745    size = write(fd, pbuf.buf, len);
5746#endif
5747    Py_END_ALLOW_THREADS
5748    PyBuffer_Release(&pbuf);
5749    if (size < 0)
5750        return posix_error();
5751    return PyLong_FromSsize_t(size);
5752}
5753
5754#ifdef HAVE_SENDFILE
5755#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
5756static int
5757iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
5758{
5759    int i, j;
5760    *iov = PyMem_New(struct iovec, cnt);
5761    if (*iov == NULL) {
5762        PyErr_NoMemory();
5763        return 0;
5764    }
5765    *buf = PyMem_New(Py_buffer, cnt);
5766    if (*buf == NULL) {
5767        PyMem_Del(*iov);
5768        PyErr_NoMemory();
5769        return 0;
5770    }
5771
5772    for (i = 0; i < cnt; i++) {
5773        if (PyObject_GetBuffer(PySequence_GetItem(seq, i), &(*buf)[i],
5774                type) == -1) {
5775            PyMem_Del(*iov);
5776            for (j = 0; j < i; j++) {
5777                PyBuffer_Release(&(*buf)[j]);
5778           }
5779            PyMem_Del(*buf);
5780            return 0;
5781        }
5782        (*iov)[i].iov_base = (*buf)[i].buf;
5783        (*iov)[i].iov_len = (*buf)[i].len;
5784    }
5785    return 1;
5786}
5787
5788static void
5789iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
5790{
5791    int i;
5792    PyMem_Del(iov);
5793    for (i = 0; i < cnt; i++) {
5794        PyBuffer_Release(&buf[i]);
5795    }
5796    PyMem_Del(buf);
5797}
5798#endif
5799
5800PyDoc_STRVAR(posix_sendfile__doc__,
5801"sendfile(out, in, offset, nbytes) -> byteswritten\n\
5802sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
5803            -> byteswritten\n\
5804Copy nbytes bytes from file descriptor in to file descriptor out.");
5805
5806static PyObject *
5807posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
5808{
5809    int in, out;
5810    Py_ssize_t ret;
5811    off_t offset;
5812
5813#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
5814#ifndef __APPLE__
5815    Py_ssize_t len;
5816#endif
5817    PyObject *headers = NULL, *trailers = NULL;
5818    Py_buffer *hbuf, *tbuf;
5819    off_t sbytes;
5820    struct sf_hdtr sf;
5821    int flags = 0;
5822    sf.headers = NULL;
5823    sf.trailers = NULL;
5824    static char *keywords[] = {"out", "in",
5825                                "offset", "count",
5826                                "headers", "trailers", "flags", NULL};
5827
5828#ifdef __APPLE__
5829    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
5830        keywords, &out, &in, PyParse_off_t, &offset, PyParse_off_t, &sbytes,
5831#else
5832    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
5833        keywords, &out, &in, PyParse_off_t, &offset, &len,
5834#endif
5835                &headers, &trailers, &flags))
5836            return NULL;
5837    if (headers != NULL) {
5838        if (!PySequence_Check(headers)) {
5839            PyErr_SetString(PyExc_TypeError,
5840                "sendfile() headers must be a sequence or None");
5841            return NULL;
5842        } else {
5843            sf.hdr_cnt = PySequence_Size(headers);
5844            if (sf.hdr_cnt > 0 && !iov_setup(&(sf.headers), &hbuf,
5845                    headers, sf.hdr_cnt, PyBUF_SIMPLE))
5846                return NULL;
5847        }
5848    }
5849    if (trailers != NULL) {
5850        if (!PySequence_Check(trailers)) {
5851            PyErr_SetString(PyExc_TypeError,
5852                "sendfile() trailers must be a sequence or None");
5853            return NULL;
5854        } else {
5855            sf.trl_cnt = PySequence_Size(trailers);
5856            if (sf.trl_cnt > 0 && !iov_setup(&(sf.trailers), &tbuf,
5857                    trailers, sf.trl_cnt, PyBUF_SIMPLE))
5858                return NULL;
5859        }
5860    }
5861
5862    Py_BEGIN_ALLOW_THREADS
5863#ifdef __APPLE__
5864    ret = sendfile(in, out, offset, &sbytes, &sf, flags);
5865#else
5866    ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
5867#endif
5868    Py_END_ALLOW_THREADS
5869
5870    if (sf.headers != NULL)
5871        iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
5872    if (sf.trailers != NULL)
5873        iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
5874
5875    if (ret < 0) {
5876        if ((errno == EAGAIN) || (errno == EBUSY)) {
5877            if (sbytes != 0) {
5878                // some data has been sent
5879                goto done;
5880            }
5881            else {
5882                // no data has been sent; upper application is supposed
5883                // to retry on EAGAIN or EBUSY
5884                return posix_error();
5885            }
5886        }
5887        return posix_error();
5888    }
5889    goto done;
5890
5891done:
5892    #if !defined(HAVE_LARGEFILE_SUPPORT)
5893        return Py_BuildValue("l", sbytes);
5894    #else
5895        return Py_BuildValue("L", sbytes);
5896    #endif
5897
5898#else
5899    Py_ssize_t count;
5900    PyObject *offobj;
5901    static char *keywords[] = {"out", "in",
5902                                "offset", "count", NULL};
5903    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
5904            keywords, &out, &in, &offobj, &count))
5905        return NULL;
5906#ifdef linux
5907    if (offobj == Py_None) {
5908        Py_BEGIN_ALLOW_THREADS
5909        ret = sendfile(out, in, NULL, count);
5910        Py_END_ALLOW_THREADS
5911        if (ret < 0)
5912            return posix_error();
5913        Py_INCREF(Py_None);
5914        return Py_BuildValue("nO", ret, Py_None);
5915    }
5916#endif
5917    PyParse_off_t(offobj, &offset);
5918    Py_BEGIN_ALLOW_THREADS
5919    ret = sendfile(out, in, &offset, count);
5920    Py_END_ALLOW_THREADS
5921    if (ret < 0)
5922        return posix_error();
5923    return Py_BuildValue("n", ret);
5924#endif
5925}
5926#endif
5927
5928PyDoc_STRVAR(posix_fstat__doc__,
5929"fstat(fd) -> stat result\n\n\
5930Like stat(), but for an open file descriptor.");
5931
5932static PyObject *
5933posix_fstat(PyObject *self, PyObject *args)
5934{
5935    int fd;
5936    STRUCT_STAT st;
5937    int res;
5938    if (!PyArg_ParseTuple(args, "i:fstat", &fd))
5939        return NULL;
5940#ifdef __VMS
5941    /* on OpenVMS we must ensure that all bytes are written to the file */
5942    fsync(fd);
5943#endif
5944    if (!_PyVerify_fd(fd))
5945        return posix_error();
5946    Py_BEGIN_ALLOW_THREADS
5947    res = FSTAT(fd, &st);
5948    Py_END_ALLOW_THREADS
5949    if (res != 0) {
5950#ifdef MS_WINDOWS
5951        return win32_error("fstat", NULL);
5952#else
5953        return posix_error();
5954#endif
5955    }
5956
5957    return _pystat_fromstructstat(&st);
5958}
5959
5960PyDoc_STRVAR(posix_isatty__doc__,
5961"isatty(fd) -> bool\n\n\
5962Return True if the file descriptor 'fd' is an open file descriptor\n\
5963connected to the slave end of a terminal.");
5964
5965static PyObject *
5966posix_isatty(PyObject *self, PyObject *args)
5967{
5968    int fd;
5969    if (!PyArg_ParseTuple(args, "i:isatty", &fd))
5970        return NULL;
5971    if (!_PyVerify_fd(fd))
5972        return PyBool_FromLong(0);
5973    return PyBool_FromLong(isatty(fd));
5974}
5975
5976#ifdef HAVE_PIPE
5977PyDoc_STRVAR(posix_pipe__doc__,
5978"pipe() -> (read_end, write_end)\n\n\
5979Create a pipe.");
5980
5981static PyObject *
5982posix_pipe(PyObject *self, PyObject *noargs)
5983{
5984#if defined(PYOS_OS2)
5985    HFILE read, write;
5986    APIRET rc;
5987
5988    Py_BEGIN_ALLOW_THREADS
5989    rc = DosCreatePipe( &read, &write, 4096);
5990    Py_END_ALLOW_THREADS
5991    if (rc != NO_ERROR)
5992        return os2_error(rc);
5993
5994    return Py_BuildValue("(ii)", read, write);
5995#else
5996#if !defined(MS_WINDOWS)
5997    int fds[2];
5998    int res;
5999    Py_BEGIN_ALLOW_THREADS
6000    res = pipe(fds);
6001    Py_END_ALLOW_THREADS
6002    if (res != 0)
6003        return posix_error();
6004    return Py_BuildValue("(ii)", fds[0], fds[1]);
6005#else /* MS_WINDOWS */
6006    HANDLE read, write;
6007    int read_fd, write_fd;
6008    BOOL ok;
6009    Py_BEGIN_ALLOW_THREADS
6010    ok = CreatePipe(&read, &write, NULL, 0);
6011    Py_END_ALLOW_THREADS
6012    if (!ok)
6013        return win32_error("CreatePipe", NULL);
6014    read_fd = _open_osfhandle((Py_intptr_t)read, 0);
6015    write_fd = _open_osfhandle((Py_intptr_t)write, 1);
6016    return Py_BuildValue("(ii)", read_fd, write_fd);
6017#endif /* MS_WINDOWS */
6018#endif
6019}
6020#endif  /* HAVE_PIPE */
6021
6022
6023#ifdef HAVE_MKFIFO
6024PyDoc_STRVAR(posix_mkfifo__doc__,
6025"mkfifo(filename [, mode=0666])\n\n\
6026Create a FIFO (a POSIX named pipe).");
6027
6028static PyObject *
6029posix_mkfifo(PyObject *self, PyObject *args)
6030{
6031    PyObject *opath;
6032    char *filename;
6033    int mode = 0666;
6034    int res;
6035    if (!PyArg_ParseTuple(args, "O&|i:mkfifo", PyUnicode_FSConverter, &opath,
6036                          &mode))
6037        return NULL;
6038    filename = PyBytes_AS_STRING(opath);
6039    Py_BEGIN_ALLOW_THREADS
6040    res = mkfifo(filename, mode);
6041    Py_END_ALLOW_THREADS
6042    Py_DECREF(opath);
6043    if (res < 0)
6044        return posix_error();
6045    Py_INCREF(Py_None);
6046    return Py_None;
6047}
6048#endif
6049
6050
6051#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
6052PyDoc_STRVAR(posix_mknod__doc__,
6053"mknod(filename [, mode=0600, device])\n\n\
6054Create a filesystem node (file, device special file or named pipe)\n\
6055named filename. mode specifies both the permissions to use and the\n\
6056type of node to be created, being combined (bitwise OR) with one of\n\
6057S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
6058device defines the newly created device special file (probably using\n\
6059os.makedev()), otherwise it is ignored.");
6060
6061
6062static PyObject *
6063posix_mknod(PyObject *self, PyObject *args)
6064{
6065    PyObject *opath;
6066    char *filename;
6067    int mode = 0600;
6068    int device = 0;
6069    int res;
6070    if (!PyArg_ParseTuple(args, "O&|ii:mknod", PyUnicode_FSConverter, &opath,
6071                          &mode, &device))
6072        return NULL;
6073    filename = PyBytes_AS_STRING(opath);
6074    Py_BEGIN_ALLOW_THREADS
6075    res = mknod(filename, mode, device);
6076    Py_END_ALLOW_THREADS
6077    Py_DECREF(opath);
6078    if (res < 0)
6079        return posix_error();
6080    Py_INCREF(Py_None);
6081    return Py_None;
6082}
6083#endif
6084
6085#ifdef HAVE_DEVICE_MACROS
6086PyDoc_STRVAR(posix_major__doc__,
6087"major(device) -> major number\n\
6088Extracts a device major number from a raw device number.");
6089
6090static PyObject *
6091posix_major(PyObject *self, PyObject *args)
6092{
6093    int device;
6094    if (!PyArg_ParseTuple(args, "i:major", &device))
6095        return NULL;
6096    return PyLong_FromLong((long)major(device));
6097}
6098
6099PyDoc_STRVAR(posix_minor__doc__,
6100"minor(device) -> minor number\n\
6101Extracts a device minor number from a raw device number.");
6102
6103static PyObject *
6104posix_minor(PyObject *self, PyObject *args)
6105{
6106    int device;
6107    if (!PyArg_ParseTuple(args, "i:minor", &device))
6108        return NULL;
6109    return PyLong_FromLong((long)minor(device));
6110}
6111
6112PyDoc_STRVAR(posix_makedev__doc__,
6113"makedev(major, minor) -> device number\n\
6114Composes a raw device number from the major and minor device numbers.");
6115
6116static PyObject *
6117posix_makedev(PyObject *self, PyObject *args)
6118{
6119    int major, minor;
6120    if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
6121        return NULL;
6122    return PyLong_FromLong((long)makedev(major, minor));
6123}
6124#endif /* device macros */
6125
6126
6127#ifdef HAVE_FTRUNCATE
6128PyDoc_STRVAR(posix_ftruncate__doc__,
6129"ftruncate(fd, length)\n\n\
6130Truncate a file to a specified length.");
6131
6132static PyObject *
6133posix_ftruncate(PyObject *self, PyObject *args)
6134{
6135    int fd;
6136    off_t length;
6137    int res;
6138    PyObject *lenobj;
6139
6140    if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
6141        return NULL;
6142
6143#if !defined(HAVE_LARGEFILE_SUPPORT)
6144    length = PyLong_AsLong(lenobj);
6145#else
6146    length = PyLong_Check(lenobj) ?
6147        PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj);
6148#endif
6149    if (PyErr_Occurred())
6150        return NULL;
6151
6152    Py_BEGIN_ALLOW_THREADS
6153    res = ftruncate(fd, length);
6154    Py_END_ALLOW_THREADS
6155    if (res < 0)
6156        return posix_error();
6157    Py_INCREF(Py_None);
6158    return Py_None;
6159}
6160#endif
6161
6162#ifdef HAVE_PUTENV
6163PyDoc_STRVAR(posix_putenv__doc__,
6164"putenv(key, value)\n\n\
6165Change or add an environment variable.");
6166
6167/* Save putenv() parameters as values here, so we can collect them when they
6168 * get re-set with another call for the same key. */
6169static PyObject *posix_putenv_garbage;
6170
6171static PyObject *
6172posix_putenv(PyObject *self, PyObject *args)
6173{
6174#ifdef MS_WINDOWS
6175    wchar_t *s1, *s2;
6176    wchar_t *newenv;
6177#else
6178    PyObject *os1, *os2;
6179    char *s1, *s2;
6180    char *newenv;
6181#endif
6182    PyObject *newstr = NULL;
6183    size_t len;
6184
6185#ifdef MS_WINDOWS
6186    if (!PyArg_ParseTuple(args,
6187                          "uu:putenv",
6188                          &s1, &s2))
6189        return NULL;
6190#else
6191    if (!PyArg_ParseTuple(args,
6192                          "O&O&:putenv",
6193                          PyUnicode_FSConverter, &os1,
6194                          PyUnicode_FSConverter, &os2))
6195        return NULL;
6196    s1 = PyBytes_AsString(os1);
6197    s2 = PyBytes_AsString(os2);
6198#endif
6199
6200#if defined(PYOS_OS2)
6201    if (stricmp(s1, "BEGINLIBPATH") == 0) {
6202        APIRET rc;
6203
6204        rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
6205        if (rc != NO_ERROR) {
6206            os2_error(rc);
6207            goto error;
6208        }
6209
6210    } else if (stricmp(s1, "ENDLIBPATH") == 0) {
6211        APIRET rc;
6212
6213        rc = DosSetExtLIBPATH(s2, END_LIBPATH);
6214        if (rc != NO_ERROR) {
6215            os2_error(rc);
6216            goto error;
6217        }
6218    } else {
6219#endif
6220    /* XXX This can leak memory -- not easy to fix :-( */
6221    /* len includes space for a trailing \0; the size arg to
6222       PyBytes_FromStringAndSize does not count that */
6223#ifdef MS_WINDOWS
6224    len = wcslen(s1) + wcslen(s2) + 2;
6225    newstr = PyUnicode_FromUnicode(NULL, (int)len - 1);
6226#else
6227    len = PyBytes_GET_SIZE(os1) + PyBytes_GET_SIZE(os2) + 2;
6228    newstr = PyBytes_FromStringAndSize(NULL, (int)len - 1);
6229#endif
6230    if (newstr == NULL) {
6231        PyErr_NoMemory();
6232        goto error;
6233    }
6234#ifdef MS_WINDOWS
6235    newenv = PyUnicode_AsUnicode(newstr);
6236    _snwprintf(newenv, len, L"%s=%s", s1, s2);
6237    if (_wputenv(newenv)) {
6238        posix_error();
6239        goto error;
6240    }
6241#else
6242    newenv = PyBytes_AS_STRING(newstr);
6243    PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
6244    if (putenv(newenv)) {
6245        posix_error();
6246        goto error;
6247    }
6248#endif
6249
6250    /* Install the first arg and newstr in posix_putenv_garbage;
6251     * this will cause previous value to be collected.  This has to
6252     * happen after the real putenv() call because the old value
6253     * was still accessible until then. */
6254    if (PyDict_SetItem(posix_putenv_garbage,
6255#ifdef MS_WINDOWS
6256                       PyTuple_GET_ITEM(args, 0),
6257#else
6258                       os1,
6259#endif
6260                       newstr)) {
6261        /* really not much we can do; just leak */
6262        PyErr_Clear();
6263    }
6264    else {
6265        Py_DECREF(newstr);
6266    }
6267
6268#if defined(PYOS_OS2)
6269    }
6270#endif
6271
6272#ifndef MS_WINDOWS
6273    Py_DECREF(os1);
6274    Py_DECREF(os2);
6275#endif
6276    Py_RETURN_NONE;
6277
6278error:
6279#ifndef MS_WINDOWS
6280    Py_DECREF(os1);
6281    Py_DECREF(os2);
6282#endif
6283    Py_XDECREF(newstr);
6284    return NULL;
6285}
6286#endif /* putenv */
6287
6288#ifdef HAVE_UNSETENV
6289PyDoc_STRVAR(posix_unsetenv__doc__,
6290"unsetenv(key)\n\n\
6291Delete an environment variable.");
6292
6293static PyObject *
6294posix_unsetenv(PyObject *self, PyObject *args)
6295{
6296#ifdef MS_WINDOWS
6297    char *s1;
6298
6299    if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
6300        return NULL;
6301#else
6302    PyObject *os1;
6303    char *s1;
6304
6305    if (!PyArg_ParseTuple(args, "O&:unsetenv",
6306                          PyUnicode_FSConverter, &os1))
6307        return NULL;
6308    s1 = PyBytes_AsString(os1);
6309#endif
6310
6311    unsetenv(s1);
6312
6313    /* Remove the key from posix_putenv_garbage;
6314     * this will cause it to be collected.  This has to
6315     * happen after the real unsetenv() call because the
6316     * old value was still accessible until then.
6317     */
6318    if (PyDict_DelItem(posix_putenv_garbage,
6319#ifdef MS_WINDOWS
6320                       PyTuple_GET_ITEM(args, 0)
6321#else
6322                       os1
6323#endif
6324                       )) {
6325        /* really not much we can do; just leak */
6326        PyErr_Clear();
6327    }
6328
6329#ifndef MS_WINDOWS
6330    Py_DECREF(os1);
6331#endif
6332    Py_RETURN_NONE;
6333}
6334#endif /* unsetenv */
6335
6336PyDoc_STRVAR(posix_strerror__doc__,
6337"strerror(code) -> string\n\n\
6338Translate an error code to a message string.");
6339
6340static PyObject *
6341posix_strerror(PyObject *self, PyObject *args)
6342{
6343    int code;
6344    char *message;
6345    if (!PyArg_ParseTuple(args, "i:strerror", &code))
6346        return NULL;
6347    message = strerror(code);
6348    if (message == NULL) {
6349        PyErr_SetString(PyExc_ValueError,
6350                        "strerror() argument out of range");
6351        return NULL;
6352    }
6353    return PyUnicode_FromString(message);
6354}
6355
6356
6357#ifdef HAVE_SYS_WAIT_H
6358
6359#ifdef WCOREDUMP
6360PyDoc_STRVAR(posix_WCOREDUMP__doc__,
6361"WCOREDUMP(status) -> bool\n\n\
6362Return True if the process returning 'status' was dumped to a core file.");
6363
6364static PyObject *
6365posix_WCOREDUMP(PyObject *self, PyObject *args)
6366{
6367    WAIT_TYPE status;
6368    WAIT_STATUS_INT(status) = 0;
6369
6370    if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
6371        return NULL;
6372
6373    return PyBool_FromLong(WCOREDUMP(status));
6374}
6375#endif /* WCOREDUMP */
6376
6377#ifdef WIFCONTINUED
6378PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
6379"WIFCONTINUED(status) -> bool\n\n\
6380Return True if the process returning 'status' was continued from a\n\
6381job control stop.");
6382
6383static PyObject *
6384posix_WIFCONTINUED(PyObject *self, PyObject *args)
6385{
6386    WAIT_TYPE status;
6387    WAIT_STATUS_INT(status) = 0;
6388
6389    if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
6390        return NULL;
6391
6392    return PyBool_FromLong(WIFCONTINUED(status));
6393}
6394#endif /* WIFCONTINUED */
6395
6396#ifdef WIFSTOPPED
6397PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
6398"WIFSTOPPED(status) -> bool\n\n\
6399Return True if the process returning 'status' was stopped.");
6400
6401static PyObject *
6402posix_WIFSTOPPED(PyObject *self, PyObject *args)
6403{
6404    WAIT_TYPE status;
6405    WAIT_STATUS_INT(status) = 0;
6406
6407    if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
6408        return NULL;
6409
6410    return PyBool_FromLong(WIFSTOPPED(status));
6411}
6412#endif /* WIFSTOPPED */
6413
6414#ifdef WIFSIGNALED
6415PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
6416"WIFSIGNALED(status) -> bool\n\n\
6417Return True if the process returning 'status' was terminated by a signal.");
6418
6419static PyObject *
6420posix_WIFSIGNALED(PyObject *self, PyObject *args)
6421{
6422    WAIT_TYPE status;
6423    WAIT_STATUS_INT(status) = 0;
6424
6425    if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
6426        return NULL;
6427
6428    return PyBool_FromLong(WIFSIGNALED(status));
6429}
6430#endif /* WIFSIGNALED */
6431
6432#ifdef WIFEXITED
6433PyDoc_STRVAR(posix_WIFEXITED__doc__,
6434"WIFEXITED(status) -> bool\n\n\
6435Return true if the process returning 'status' exited using the exit()\n\
6436system call.");
6437
6438static PyObject *
6439posix_WIFEXITED(PyObject *self, PyObject *args)
6440{
6441    WAIT_TYPE status;
6442    WAIT_STATUS_INT(status) = 0;
6443
6444    if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
6445        return NULL;
6446
6447    return PyBool_FromLong(WIFEXITED(status));
6448}
6449#endif /* WIFEXITED */
6450
6451#ifdef WEXITSTATUS
6452PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
6453"WEXITSTATUS(status) -> integer\n\n\
6454Return the process return code from 'status'.");
6455
6456static PyObject *
6457posix_WEXITSTATUS(PyObject *self, PyObject *args)
6458{
6459    WAIT_TYPE status;
6460    WAIT_STATUS_INT(status) = 0;
6461
6462    if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
6463        return NULL;
6464
6465    return Py_BuildValue("i", WEXITSTATUS(status));
6466}
6467#endif /* WEXITSTATUS */
6468
6469#ifdef WTERMSIG
6470PyDoc_STRVAR(posix_WTERMSIG__doc__,
6471"WTERMSIG(status) -> integer\n\n\
6472Return the signal that terminated the process that provided the 'status'\n\
6473value.");
6474
6475static PyObject *
6476posix_WTERMSIG(PyObject *self, PyObject *args)
6477{
6478    WAIT_TYPE status;
6479    WAIT_STATUS_INT(status) = 0;
6480
6481    if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
6482        return NULL;
6483
6484    return Py_BuildValue("i", WTERMSIG(status));
6485}
6486#endif /* WTERMSIG */
6487
6488#ifdef WSTOPSIG
6489PyDoc_STRVAR(posix_WSTOPSIG__doc__,
6490"WSTOPSIG(status) -> integer\n\n\
6491Return the signal that stopped the process that provided\n\
6492the 'status' value.");
6493
6494static PyObject *
6495posix_WSTOPSIG(PyObject *self, PyObject *args)
6496{
6497    WAIT_TYPE status;
6498    WAIT_STATUS_INT(status) = 0;
6499
6500    if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
6501        return NULL;
6502
6503    return Py_BuildValue("i", WSTOPSIG(status));
6504}
6505#endif /* WSTOPSIG */
6506
6507#endif /* HAVE_SYS_WAIT_H */
6508
6509
6510#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
6511#ifdef _SCO_DS
6512/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
6513   needed definitions in sys/statvfs.h */
6514#define _SVID3
6515#endif
6516#include <sys/statvfs.h>
6517
6518static PyObject*
6519_pystatvfs_fromstructstatvfs(struct statvfs st) {
6520    PyObject *v = PyStructSequence_New(&StatVFSResultType);
6521    if (v == NULL)
6522        return NULL;
6523
6524#if !defined(HAVE_LARGEFILE_SUPPORT)
6525    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
6526    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
6527    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
6528    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
6529    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
6530    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
6531    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
6532    PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
6533    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
6534    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
6535#else
6536    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
6537    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
6538    PyStructSequence_SET_ITEM(v, 2,
6539                              PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
6540    PyStructSequence_SET_ITEM(v, 3,
6541                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
6542    PyStructSequence_SET_ITEM(v, 4,
6543                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
6544    PyStructSequence_SET_ITEM(v, 5,
6545                              PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
6546    PyStructSequence_SET_ITEM(v, 6,
6547                              PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
6548    PyStructSequence_SET_ITEM(v, 7,
6549                              PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
6550    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
6551    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
6552#endif
6553
6554    return v;
6555}
6556
6557PyDoc_STRVAR(posix_fstatvfs__doc__,
6558"fstatvfs(fd) -> statvfs result\n\n\
6559Perform an fstatvfs system call on the given fd.");
6560
6561static PyObject *
6562posix_fstatvfs(PyObject *self, PyObject *args)
6563{
6564    int fd, res;
6565    struct statvfs st;
6566
6567    if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
6568        return NULL;
6569    Py_BEGIN_ALLOW_THREADS
6570    res = fstatvfs(fd, &st);
6571    Py_END_ALLOW_THREADS
6572    if (res != 0)
6573        return posix_error();
6574
6575    return _pystatvfs_fromstructstatvfs(st);
6576}
6577#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
6578
6579
6580#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
6581#include <sys/statvfs.h>
6582
6583PyDoc_STRVAR(posix_statvfs__doc__,
6584"statvfs(path) -> statvfs result\n\n\
6585Perform a statvfs system call on the given path.");
6586
6587static PyObject *
6588posix_statvfs(PyObject *self, PyObject *args)
6589{
6590    char *path;
6591    int res;
6592    struct statvfs st;
6593    if (!PyArg_ParseTuple(args, "s:statvfs", &path))
6594        return NULL;
6595    Py_BEGIN_ALLOW_THREADS
6596    res = statvfs(path, &st);
6597    Py_END_ALLOW_THREADS
6598    if (res != 0)
6599        return posix_error_with_filename(path);
6600
6601    return _pystatvfs_fromstructstatvfs(st);
6602}
6603#endif /* HAVE_STATVFS */
6604
6605/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
6606 * It maps strings representing configuration variable names to
6607 * integer values, allowing those functions to be called with the
6608 * magic names instead of polluting the module's namespace with tons of
6609 * rarely-used constants.  There are three separate tables that use
6610 * these definitions.
6611 *
6612 * This code is always included, even if none of the interfaces that
6613 * need it are included.  The #if hackery needed to avoid it would be
6614 * sufficiently pervasive that it's not worth the loss of readability.
6615 */
6616struct constdef {
6617    char *name;
6618    long value;
6619};
6620
6621static int
6622conv_confname(PyObject *arg, int *valuep, struct constdef *table,
6623              size_t tablesize)
6624{
6625    if (PyLong_Check(arg)) {
6626        *valuep = PyLong_AS_LONG(arg);
6627        return 1;
6628    }
6629    else {
6630        /* look up the value in the table using a binary search */
6631        size_t lo = 0;
6632        size_t mid;
6633        size_t hi = tablesize;
6634        int cmp;
6635        const char *confname;
6636        if (!PyUnicode_Check(arg)) {
6637            PyErr_SetString(PyExc_TypeError,
6638                "configuration names must be strings or integers");
6639            return 0;
6640        }
6641        confname = _PyUnicode_AsString(arg);
6642        if (confname == NULL)
6643            return 0;
6644        while (lo < hi) {
6645            mid = (lo + hi) / 2;
6646            cmp = strcmp(confname, table[mid].name);
6647            if (cmp < 0)
6648                hi = mid;
6649            else if (cmp > 0)
6650                lo = mid + 1;
6651            else {
6652                *valuep = table[mid].value;
6653                return 1;
6654            }
6655        }
6656        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
6657        return 0;
6658    }
6659}
6660
6661
6662#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
6663static struct constdef  posix_constants_pathconf[] = {
6664#ifdef _PC_ABI_AIO_XFER_MAX
6665    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
6666#endif
6667#ifdef _PC_ABI_ASYNC_IO
6668    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
6669#endif
6670#ifdef _PC_ASYNC_IO
6671    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
6672#endif
6673#ifdef _PC_CHOWN_RESTRICTED
6674    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
6675#endif
6676#ifdef _PC_FILESIZEBITS
6677    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
6678#endif
6679#ifdef _PC_LAST
6680    {"PC_LAST", _PC_LAST},
6681#endif
6682#ifdef _PC_LINK_MAX
6683    {"PC_LINK_MAX",     _PC_LINK_MAX},
6684#endif
6685#ifdef _PC_MAX_CANON
6686    {"PC_MAX_CANON",    _PC_MAX_CANON},
6687#endif
6688#ifdef _PC_MAX_INPUT
6689    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
6690#endif
6691#ifdef _PC_NAME_MAX
6692    {"PC_NAME_MAX",     _PC_NAME_MAX},
6693#endif
6694#ifdef _PC_NO_TRUNC
6695    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
6696#endif
6697#ifdef _PC_PATH_MAX
6698    {"PC_PATH_MAX",     _PC_PATH_MAX},
6699#endif
6700#ifdef _PC_PIPE_BUF
6701    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
6702#endif
6703#ifdef _PC_PRIO_IO
6704    {"PC_PRIO_IO",      _PC_PRIO_IO},
6705#endif
6706#ifdef _PC_SOCK_MAXBUF
6707    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
6708#endif
6709#ifdef _PC_SYNC_IO
6710    {"PC_SYNC_IO",      _PC_SYNC_IO},
6711#endif
6712#ifdef _PC_VDISABLE
6713    {"PC_VDISABLE",     _PC_VDISABLE},
6714#endif
6715#ifdef _PC_ACL_ENABLED
6716    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
6717#endif
6718#ifdef _PC_MIN_HOLE_SIZE
6719    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
6720#endif
6721#ifdef _PC_ALLOC_SIZE_MIN
6722    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
6723#endif
6724#ifdef _PC_REC_INCR_XFER_SIZE
6725    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
6726#endif
6727#ifdef _PC_REC_MAX_XFER_SIZE
6728    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
6729#endif
6730#ifdef _PC_REC_MIN_XFER_SIZE
6731    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
6732#endif
6733#ifdef _PC_REC_XFER_ALIGN
6734    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
6735#endif
6736#ifdef _PC_SYMLINK_MAX
6737    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
6738#endif
6739#ifdef _PC_XATTR_ENABLED
6740    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
6741#endif
6742#ifdef _PC_XATTR_EXISTS
6743    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
6744#endif
6745#ifdef _PC_TIMESTAMP_RESOLUTION
6746    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
6747#endif
6748};
6749
6750static int
6751conv_path_confname(PyObject *arg, int *valuep)
6752{
6753    return conv_confname(arg, valuep, posix_constants_pathconf,
6754                         sizeof(posix_constants_pathconf)
6755                           / sizeof(struct constdef));
6756}
6757#endif
6758
6759#ifdef HAVE_FPATHCONF
6760PyDoc_STRVAR(posix_fpathconf__doc__,
6761"fpathconf(fd, name) -> integer\n\n\
6762Return the configuration limit name for the file descriptor fd.\n\
6763If there is no limit, return -1.");
6764
6765static PyObject *
6766posix_fpathconf(PyObject *self, PyObject *args)
6767{
6768    PyObject *result = NULL;
6769    int name, fd;
6770
6771    if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
6772                         conv_path_confname, &name)) {
6773        long limit;
6774
6775        errno = 0;
6776        limit = fpathconf(fd, name);
6777        if (limit == -1 && errno != 0)
6778            posix_error();
6779        else
6780            result = PyLong_FromLong(limit);
6781    }
6782    return result;
6783}
6784#endif
6785
6786
6787#ifdef HAVE_PATHCONF
6788PyDoc_STRVAR(posix_pathconf__doc__,
6789"pathconf(path, name) -> integer\n\n\
6790Return the configuration limit name for the file or directory path.\n\
6791If there is no limit, return -1.");
6792
6793static PyObject *
6794posix_pathconf(PyObject *self, PyObject *args)
6795{
6796    PyObject *result = NULL;
6797    int name;
6798    char *path;
6799
6800    if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
6801                         conv_path_confname, &name)) {
6802    long limit;
6803
6804    errno = 0;
6805    limit = pathconf(path, name);
6806    if (limit == -1 && errno != 0) {
6807        if (errno == EINVAL)
6808            /* could be a path or name problem */
6809            posix_error();
6810        else
6811            posix_error_with_filename(path);
6812    }
6813    else
6814        result = PyLong_FromLong(limit);
6815    }
6816    return result;
6817}
6818#endif
6819
6820#ifdef HAVE_CONFSTR
6821static struct constdef posix_constants_confstr[] = {
6822#ifdef _CS_ARCHITECTURE
6823    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
6824#endif
6825#ifdef _CS_GNU_LIBC_VERSION
6826    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
6827#endif
6828#ifdef _CS_GNU_LIBPTHREAD_VERSION
6829    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
6830#endif
6831#ifdef _CS_HOSTNAME
6832    {"CS_HOSTNAME",     _CS_HOSTNAME},
6833#endif
6834#ifdef _CS_HW_PROVIDER
6835    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
6836#endif
6837#ifdef _CS_HW_SERIAL
6838    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
6839#endif
6840#ifdef _CS_INITTAB_NAME
6841    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
6842#endif
6843#ifdef _CS_LFS64_CFLAGS
6844    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
6845#endif
6846#ifdef _CS_LFS64_LDFLAGS
6847    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
6848#endif
6849#ifdef _CS_LFS64_LIBS
6850    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
6851#endif
6852#ifdef _CS_LFS64_LINTFLAGS
6853    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
6854#endif
6855#ifdef _CS_LFS_CFLAGS
6856    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
6857#endif
6858#ifdef _CS_LFS_LDFLAGS
6859    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
6860#endif
6861#ifdef _CS_LFS_LIBS
6862    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
6863#endif
6864#ifdef _CS_LFS_LINTFLAGS
6865    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
6866#endif
6867#ifdef _CS_MACHINE
6868    {"CS_MACHINE",      _CS_MACHINE},
6869#endif
6870#ifdef _CS_PATH
6871    {"CS_PATH", _CS_PATH},
6872#endif
6873#ifdef _CS_RELEASE
6874    {"CS_RELEASE",      _CS_RELEASE},
6875#endif
6876#ifdef _CS_SRPC_DOMAIN
6877    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
6878#endif
6879#ifdef _CS_SYSNAME
6880    {"CS_SYSNAME",      _CS_SYSNAME},
6881#endif
6882#ifdef _CS_VERSION
6883    {"CS_VERSION",      _CS_VERSION},
6884#endif
6885#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
6886    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
6887#endif
6888#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
6889    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
6890#endif
6891#ifdef _CS_XBS5_ILP32_OFF32_LIBS
6892    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
6893#endif
6894#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
6895    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
6896#endif
6897#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
6898    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
6899#endif
6900#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
6901    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
6902#endif
6903#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
6904    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
6905#endif
6906#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
6907    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
6908#endif
6909#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
6910    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
6911#endif
6912#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
6913    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
6914#endif
6915#ifdef _CS_XBS5_LP64_OFF64_LIBS
6916    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
6917#endif
6918#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
6919    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
6920#endif
6921#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
6922    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
6923#endif
6924#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
6925    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
6926#endif
6927#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
6928    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
6929#endif
6930#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
6931    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
6932#endif
6933#ifdef _MIPS_CS_AVAIL_PROCESSORS
6934    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
6935#endif
6936#ifdef _MIPS_CS_BASE
6937    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
6938#endif
6939#ifdef _MIPS_CS_HOSTID
6940    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
6941#endif
6942#ifdef _MIPS_CS_HW_NAME
6943    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
6944#endif
6945#ifdef _MIPS_CS_NUM_PROCESSORS
6946    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
6947#endif
6948#ifdef _MIPS_CS_OSREL_MAJ
6949    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
6950#endif
6951#ifdef _MIPS_CS_OSREL_MIN
6952    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
6953#endif
6954#ifdef _MIPS_CS_OSREL_PATCH
6955    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
6956#endif
6957#ifdef _MIPS_CS_OS_NAME
6958    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
6959#endif
6960#ifdef _MIPS_CS_OS_PROVIDER
6961    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
6962#endif
6963#ifdef _MIPS_CS_PROCESSORS
6964    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
6965#endif
6966#ifdef _MIPS_CS_SERIAL
6967    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
6968#endif
6969#ifdef _MIPS_CS_VENDOR
6970    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
6971#endif
6972};
6973
6974static int
6975conv_confstr_confname(PyObject *arg, int *valuep)
6976{
6977    return conv_confname(arg, valuep, posix_constants_confstr,
6978                         sizeof(posix_constants_confstr)
6979                           / sizeof(struct constdef));
6980}
6981
6982PyDoc_STRVAR(posix_confstr__doc__,
6983"confstr(name) -> string\n\n\
6984Return a string-valued system configuration variable.");
6985
6986static PyObject *
6987posix_confstr(PyObject *self, PyObject *args)
6988{
6989    PyObject *result = NULL;
6990    int name;
6991    char buffer[255];
6992    int len;
6993
6994    if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
6995        return NULL;
6996
6997    errno = 0;
6998    len = confstr(name, buffer, sizeof(buffer));
6999    if (len == 0) {
7000        if (errno) {
7001            posix_error();
7002            return NULL;
7003        }
7004        else {
7005            Py_RETURN_NONE;
7006        }
7007    }
7008
7009    if ((unsigned int)len >= sizeof(buffer)) {
7010        char *buf = PyMem_Malloc(len);
7011        if (buf == NULL)
7012            return PyErr_NoMemory();
7013        confstr(name, buf, len);
7014        result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
7015        PyMem_Free(buf);
7016    }
7017    else
7018        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
7019    return result;
7020}
7021#endif
7022
7023
7024#ifdef HAVE_SYSCONF
7025static struct constdef posix_constants_sysconf[] = {
7026#ifdef _SC_2_CHAR_TERM
7027    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
7028#endif
7029#ifdef _SC_2_C_BIND
7030    {"SC_2_C_BIND",     _SC_2_C_BIND},
7031#endif
7032#ifdef _SC_2_C_DEV
7033    {"SC_2_C_DEV",      _SC_2_C_DEV},
7034#endif
7035#ifdef _SC_2_C_VERSION
7036    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
7037#endif
7038#ifdef _SC_2_FORT_DEV
7039    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
7040#endif
7041#ifdef _SC_2_FORT_RUN
7042    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
7043#endif
7044#ifdef _SC_2_LOCALEDEF
7045    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
7046#endif
7047#ifdef _SC_2_SW_DEV
7048    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
7049#endif
7050#ifdef _SC_2_UPE
7051    {"SC_2_UPE",        _SC_2_UPE},
7052#endif
7053#ifdef _SC_2_VERSION
7054    {"SC_2_VERSION",    _SC_2_VERSION},
7055#endif
7056#ifdef _SC_ABI_ASYNCHRONOUS_IO
7057    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
7058#endif
7059#ifdef _SC_ACL
7060    {"SC_ACL",  _SC_ACL},
7061#endif
7062#ifdef _SC_AIO_LISTIO_MAX
7063    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
7064#endif
7065#ifdef _SC_AIO_MAX
7066    {"SC_AIO_MAX",      _SC_AIO_MAX},
7067#endif
7068#ifdef _SC_AIO_PRIO_DELTA_MAX
7069    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
7070#endif
7071#ifdef _SC_ARG_MAX
7072    {"SC_ARG_MAX",      _SC_ARG_MAX},
7073#endif
7074#ifdef _SC_ASYNCHRONOUS_IO
7075    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
7076#endif
7077#ifdef _SC_ATEXIT_MAX
7078    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
7079#endif
7080#ifdef _SC_AUDIT
7081    {"SC_AUDIT",        _SC_AUDIT},
7082#endif
7083#ifdef _SC_AVPHYS_PAGES
7084    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
7085#endif
7086#ifdef _SC_BC_BASE_MAX
7087    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
7088#endif
7089#ifdef _SC_BC_DIM_MAX
7090    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
7091#endif
7092#ifdef _SC_BC_SCALE_MAX
7093    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
7094#endif
7095#ifdef _SC_BC_STRING_MAX
7096    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
7097#endif
7098#ifdef _SC_CAP
7099    {"SC_CAP",  _SC_CAP},
7100#endif
7101#ifdef _SC_CHARCLASS_NAME_MAX
7102    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
7103#endif
7104#ifdef _SC_CHAR_BIT
7105    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
7106#endif
7107#ifdef _SC_CHAR_MAX
7108    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
7109#endif
7110#ifdef _SC_CHAR_MIN
7111    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
7112#endif
7113#ifdef _SC_CHILD_MAX
7114    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
7115#endif
7116#ifdef _SC_CLK_TCK
7117    {"SC_CLK_TCK",      _SC_CLK_TCK},
7118#endif
7119#ifdef _SC_COHER_BLKSZ
7120    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
7121#endif
7122#ifdef _SC_COLL_WEIGHTS_MAX
7123    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
7124#endif
7125#ifdef _SC_DCACHE_ASSOC
7126    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
7127#endif
7128#ifdef _SC_DCACHE_BLKSZ
7129    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
7130#endif
7131#ifdef _SC_DCACHE_LINESZ
7132    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
7133#endif
7134#ifdef _SC_DCACHE_SZ
7135    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
7136#endif
7137#ifdef _SC_DCACHE_TBLKSZ
7138    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
7139#endif
7140#ifdef _SC_DELAYTIMER_MAX
7141    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
7142#endif
7143#ifdef _SC_EQUIV_CLASS_MAX
7144    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
7145#endif
7146#ifdef _SC_EXPR_NEST_MAX
7147    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
7148#endif
7149#ifdef _SC_FSYNC
7150    {"SC_FSYNC",        _SC_FSYNC},
7151#endif
7152#ifdef _SC_GETGR_R_SIZE_MAX
7153    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
7154#endif
7155#ifdef _SC_GETPW_R_SIZE_MAX
7156    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
7157#endif
7158#ifdef _SC_ICACHE_ASSOC
7159    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
7160#endif
7161#ifdef _SC_ICACHE_BLKSZ
7162    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
7163#endif
7164#ifdef _SC_ICACHE_LINESZ
7165    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
7166#endif
7167#ifdef _SC_ICACHE_SZ
7168    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
7169#endif
7170#ifdef _SC_INF
7171    {"SC_INF",  _SC_INF},
7172#endif
7173#ifdef _SC_INT_MAX
7174    {"SC_INT_MAX",      _SC_INT_MAX},
7175#endif
7176#ifdef _SC_INT_MIN
7177    {"SC_INT_MIN",      _SC_INT_MIN},
7178#endif
7179#ifdef _SC_IOV_MAX
7180    {"SC_IOV_MAX",      _SC_IOV_MAX},
7181#endif
7182#ifdef _SC_IP_SECOPTS
7183    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
7184#endif
7185#ifdef _SC_JOB_CONTROL
7186    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
7187#endif
7188#ifdef _SC_KERN_POINTERS
7189    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
7190#endif
7191#ifdef _SC_KERN_SIM
7192    {"SC_KERN_SIM",     _SC_KERN_SIM},
7193#endif
7194#ifdef _SC_LINE_MAX
7195    {"SC_LINE_MAX",     _SC_LINE_MAX},
7196#endif
7197#ifdef _SC_LOGIN_NAME_MAX
7198    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
7199#endif
7200#ifdef _SC_LOGNAME_MAX
7201    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
7202#endif
7203#ifdef _SC_LONG_BIT
7204    {"SC_LONG_BIT",     _SC_LONG_BIT},
7205#endif
7206#ifdef _SC_MAC
7207    {"SC_MAC",  _SC_MAC},
7208#endif
7209#ifdef _SC_MAPPED_FILES
7210    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
7211#endif
7212#ifdef _SC_MAXPID
7213    {"SC_MAXPID",       _SC_MAXPID},
7214#endif
7215#ifdef _SC_MB_LEN_MAX
7216    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
7217#endif
7218#ifdef _SC_MEMLOCK
7219    {"SC_MEMLOCK",      _SC_MEMLOCK},
7220#endif
7221#ifdef _SC_MEMLOCK_RANGE
7222    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
7223#endif
7224#ifdef _SC_MEMORY_PROTECTION
7225    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
7226#endif
7227#ifdef _SC_MESSAGE_PASSING
7228    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
7229#endif
7230#ifdef _SC_MMAP_FIXED_ALIGNMENT
7231    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
7232#endif
7233#ifdef _SC_MQ_OPEN_MAX
7234    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
7235#endif
7236#ifdef _SC_MQ_PRIO_MAX
7237    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
7238#endif
7239#ifdef _SC_NACLS_MAX
7240    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
7241#endif
7242#ifdef _SC_NGROUPS_MAX
7243    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
7244#endif
7245#ifdef _SC_NL_ARGMAX
7246    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
7247#endif
7248#ifdef _SC_NL_LANGMAX
7249    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
7250#endif
7251#ifdef _SC_NL_MSGMAX
7252    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
7253#endif
7254#ifdef _SC_NL_NMAX
7255    {"SC_NL_NMAX",      _SC_NL_NMAX},
7256#endif
7257#ifdef _SC_NL_SETMAX
7258    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
7259#endif
7260#ifdef _SC_NL_TEXTMAX
7261    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
7262#endif
7263#ifdef _SC_NPROCESSORS_CONF
7264    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
7265#endif
7266#ifdef _SC_NPROCESSORS_ONLN
7267    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
7268#endif
7269#ifdef _SC_NPROC_CONF
7270    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
7271#endif
7272#ifdef _SC_NPROC_ONLN
7273    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
7274#endif
7275#ifdef _SC_NZERO
7276    {"SC_NZERO",        _SC_NZERO},
7277#endif
7278#ifdef _SC_OPEN_MAX
7279    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
7280#endif
7281#ifdef _SC_PAGESIZE
7282    {"SC_PAGESIZE",     _SC_PAGESIZE},
7283#endif
7284#ifdef _SC_PAGE_SIZE
7285    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
7286#endif
7287#ifdef _SC_PASS_MAX
7288    {"SC_PASS_MAX",     _SC_PASS_MAX},
7289#endif
7290#ifdef _SC_PHYS_PAGES
7291    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
7292#endif
7293#ifdef _SC_PII
7294    {"SC_PII",  _SC_PII},
7295#endif
7296#ifdef _SC_PII_INTERNET
7297    {"SC_PII_INTERNET", _SC_PII_INTERNET},
7298#endif
7299#ifdef _SC_PII_INTERNET_DGRAM
7300    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
7301#endif
7302#ifdef _SC_PII_INTERNET_STREAM
7303    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
7304#endif
7305#ifdef _SC_PII_OSI
7306    {"SC_PII_OSI",      _SC_PII_OSI},
7307#endif
7308#ifdef _SC_PII_OSI_CLTS
7309    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
7310#endif
7311#ifdef _SC_PII_OSI_COTS
7312    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
7313#endif
7314#ifdef _SC_PII_OSI_M
7315    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
7316#endif
7317#ifdef _SC_PII_SOCKET
7318    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
7319#endif
7320#ifdef _SC_PII_XTI
7321    {"SC_PII_XTI",      _SC_PII_XTI},
7322#endif
7323#ifdef _SC_POLL
7324    {"SC_POLL", _SC_POLL},
7325#endif
7326#ifdef _SC_PRIORITIZED_IO
7327    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
7328#endif
7329#ifdef _SC_PRIORITY_SCHEDULING
7330    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
7331#endif
7332#ifdef _SC_REALTIME_SIGNALS
7333    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
7334#endif
7335#ifdef _SC_RE_DUP_MAX
7336    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
7337#endif
7338#ifdef _SC_RTSIG_MAX
7339    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
7340#endif
7341#ifdef _SC_SAVED_IDS
7342    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
7343#endif
7344#ifdef _SC_SCHAR_MAX
7345    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
7346#endif
7347#ifdef _SC_SCHAR_MIN
7348    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
7349#endif
7350#ifdef _SC_SELECT
7351    {"SC_SELECT",       _SC_SELECT},
7352#endif
7353#ifdef _SC_SEMAPHORES
7354    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
7355#endif
7356#ifdef _SC_SEM_NSEMS_MAX
7357    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
7358#endif
7359#ifdef _SC_SEM_VALUE_MAX
7360    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
7361#endif
7362#ifdef _SC_SHARED_MEMORY_OBJECTS
7363    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
7364#endif
7365#ifdef _SC_SHRT_MAX
7366    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
7367#endif
7368#ifdef _SC_SHRT_MIN
7369    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
7370#endif
7371#ifdef _SC_SIGQUEUE_MAX
7372    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
7373#endif
7374#ifdef _SC_SIGRT_MAX
7375    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
7376#endif
7377#ifdef _SC_SIGRT_MIN
7378    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
7379#endif
7380#ifdef _SC_SOFTPOWER
7381    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
7382#endif
7383#ifdef _SC_SPLIT_CACHE
7384    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
7385#endif
7386#ifdef _SC_SSIZE_MAX
7387    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
7388#endif
7389#ifdef _SC_STACK_PROT
7390    {"SC_STACK_PROT",   _SC_STACK_PROT},
7391#endif
7392#ifdef _SC_STREAM_MAX
7393    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
7394#endif
7395#ifdef _SC_SYNCHRONIZED_IO
7396    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
7397#endif
7398#ifdef _SC_THREADS
7399    {"SC_THREADS",      _SC_THREADS},
7400#endif
7401#ifdef _SC_THREAD_ATTR_STACKADDR
7402    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
7403#endif
7404#ifdef _SC_THREAD_ATTR_STACKSIZE
7405    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
7406#endif
7407#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
7408    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
7409#endif
7410#ifdef _SC_THREAD_KEYS_MAX
7411    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
7412#endif
7413#ifdef _SC_THREAD_PRIORITY_SCHEDULING
7414    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
7415#endif
7416#ifdef _SC_THREAD_PRIO_INHERIT
7417    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
7418#endif
7419#ifdef _SC_THREAD_PRIO_PROTECT
7420    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
7421#endif
7422#ifdef _SC_THREAD_PROCESS_SHARED
7423    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
7424#endif
7425#ifdef _SC_THREAD_SAFE_FUNCTIONS
7426    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
7427#endif
7428#ifdef _SC_THREAD_STACK_MIN
7429    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
7430#endif
7431#ifdef _SC_THREAD_THREADS_MAX
7432    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
7433#endif
7434#ifdef _SC_TIMERS
7435    {"SC_TIMERS",       _SC_TIMERS},
7436#endif
7437#ifdef _SC_TIMER_MAX
7438    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
7439#endif
7440#ifdef _SC_TTY_NAME_MAX
7441    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
7442#endif
7443#ifdef _SC_TZNAME_MAX
7444    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
7445#endif
7446#ifdef _SC_T_IOV_MAX
7447    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
7448#endif
7449#ifdef _SC_UCHAR_MAX
7450    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
7451#endif
7452#ifdef _SC_UINT_MAX
7453    {"SC_UINT_MAX",     _SC_UINT_MAX},
7454#endif
7455#ifdef _SC_UIO_MAXIOV
7456    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
7457#endif
7458#ifdef _SC_ULONG_MAX
7459    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
7460#endif
7461#ifdef _SC_USHRT_MAX
7462    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
7463#endif
7464#ifdef _SC_VERSION
7465    {"SC_VERSION",      _SC_VERSION},
7466#endif
7467#ifdef _SC_WORD_BIT
7468    {"SC_WORD_BIT",     _SC_WORD_BIT},
7469#endif
7470#ifdef _SC_XBS5_ILP32_OFF32
7471    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
7472#endif
7473#ifdef _SC_XBS5_ILP32_OFFBIG
7474    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
7475#endif
7476#ifdef _SC_XBS5_LP64_OFF64
7477    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
7478#endif
7479#ifdef _SC_XBS5_LPBIG_OFFBIG
7480    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
7481#endif
7482#ifdef _SC_XOPEN_CRYPT
7483    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
7484#endif
7485#ifdef _SC_XOPEN_ENH_I18N
7486    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
7487#endif
7488#ifdef _SC_XOPEN_LEGACY
7489    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
7490#endif
7491#ifdef _SC_XOPEN_REALTIME
7492    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
7493#endif
7494#ifdef _SC_XOPEN_REALTIME_THREADS
7495    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
7496#endif
7497#ifdef _SC_XOPEN_SHM
7498    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
7499#endif
7500#ifdef _SC_XOPEN_UNIX
7501    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
7502#endif
7503#ifdef _SC_XOPEN_VERSION
7504    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
7505#endif
7506#ifdef _SC_XOPEN_XCU_VERSION
7507    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
7508#endif
7509#ifdef _SC_XOPEN_XPG2
7510    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
7511#endif
7512#ifdef _SC_XOPEN_XPG3
7513    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
7514#endif
7515#ifdef _SC_XOPEN_XPG4
7516    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
7517#endif
7518};
7519
7520static int
7521conv_sysconf_confname(PyObject *arg, int *valuep)
7522{
7523    return conv_confname(arg, valuep, posix_constants_sysconf,
7524                         sizeof(posix_constants_sysconf)
7525                           / sizeof(struct constdef));
7526}
7527
7528PyDoc_STRVAR(posix_sysconf__doc__,
7529"sysconf(name) -> integer\n\n\
7530Return an integer-valued system configuration variable.");
7531
7532static PyObject *
7533posix_sysconf(PyObject *self, PyObject *args)
7534{
7535    PyObject *result = NULL;
7536    int name;
7537
7538    if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
7539        int value;
7540
7541        errno = 0;
7542        value = sysconf(name);
7543        if (value == -1 && errno != 0)
7544            posix_error();
7545        else
7546            result = PyLong_FromLong(value);
7547    }
7548    return result;
7549}
7550#endif
7551
7552
7553/* This code is used to ensure that the tables of configuration value names
7554 * are in sorted order as required by conv_confname(), and also to build the
7555 * the exported dictionaries that are used to publish information about the
7556 * names available on the host platform.
7557 *
7558 * Sorting the table at runtime ensures that the table is properly ordered
7559 * when used, even for platforms we're not able to test on.  It also makes
7560 * it easier to add additional entries to the tables.
7561 */
7562
7563static int
7564cmp_constdefs(const void *v1,  const void *v2)
7565{
7566    const struct constdef *c1 =
7567    (const struct constdef *) v1;
7568    const struct constdef *c2 =
7569    (const struct constdef *) v2;
7570
7571    return strcmp(c1->name, c2->name);
7572}
7573
7574static int
7575setup_confname_table(struct constdef *table, size_t tablesize,
7576                     char *tablename, PyObject *module)
7577{
7578    PyObject *d = NULL;
7579    size_t i;
7580
7581    qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
7582    d = PyDict_New();
7583    if (d == NULL)
7584        return -1;
7585
7586    for (i=0; i < tablesize; ++i) {
7587        PyObject *o = PyLong_FromLong(table[i].value);
7588        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
7589            Py_XDECREF(o);
7590            Py_DECREF(d);
7591            return -1;
7592        }
7593        Py_DECREF(o);
7594    }
7595    return PyModule_AddObject(module, tablename, d);
7596}
7597
7598/* Return -1 on failure, 0 on success. */
7599static int
7600setup_confname_tables(PyObject *module)
7601{
7602#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
7603    if (setup_confname_table(posix_constants_pathconf,
7604                             sizeof(posix_constants_pathconf)
7605                               / sizeof(struct constdef),
7606                             "pathconf_names", module))
7607        return -1;
7608#endif
7609#ifdef HAVE_CONFSTR
7610    if (setup_confname_table(posix_constants_confstr,
7611                             sizeof(posix_constants_confstr)
7612                               / sizeof(struct constdef),
7613                             "confstr_names", module))
7614        return -1;
7615#endif
7616#ifdef HAVE_SYSCONF
7617    if (setup_confname_table(posix_constants_sysconf,
7618                             sizeof(posix_constants_sysconf)
7619                               / sizeof(struct constdef),
7620                             "sysconf_names", module))
7621        return -1;
7622#endif
7623    return 0;
7624}
7625
7626
7627PyDoc_STRVAR(posix_abort__doc__,
7628"abort() -> does not return!\n\n\
7629Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
7630in the hardest way possible on the hosting operating system.");
7631
7632static PyObject *
7633posix_abort(PyObject *self, PyObject *noargs)
7634{
7635    abort();
7636    /*NOTREACHED*/
7637    Py_FatalError("abort() called from Python code didn't abort!");
7638    return NULL;
7639}
7640
7641#ifdef MS_WINDOWS
7642PyDoc_STRVAR(win32_startfile__doc__,
7643"startfile(filepath [, operation]) - Start a file with its associated\n\
7644application.\n\
7645\n\
7646When \"operation\" is not specified or \"open\", this acts like\n\
7647double-clicking the file in Explorer, or giving the file name as an\n\
7648argument to the DOS \"start\" command: the file is opened with whatever\n\
7649application (if any) its extension is associated.\n\
7650When another \"operation\" is given, it specifies what should be done with\n\
7651the file.  A typical operation is \"print\".\n\
7652\n\
7653startfile returns as soon as the associated application is launched.\n\
7654There is no option to wait for the application to close, and no way\n\
7655to retrieve the application's exit status.\n\
7656\n\
7657The filepath is relative to the current directory.  If you want to use\n\
7658an absolute path, make sure the first character is not a slash (\"/\");\n\
7659the underlying Win32 ShellExecute function doesn't work if it is.");
7660
7661static PyObject *
7662win32_startfile(PyObject *self, PyObject *args)
7663{
7664    PyObject *ofilepath;
7665    char *filepath;
7666    char *operation = NULL;
7667    HINSTANCE rc;
7668
7669    PyObject *unipath, *woperation = NULL;
7670    if (!PyArg_ParseTuple(args, "U|s:startfile",
7671                          &unipath, &operation)) {
7672        PyErr_Clear();
7673        goto normal;
7674    }
7675
7676    if (operation) {
7677        woperation = PyUnicode_DecodeASCII(operation,
7678                                           strlen(operation), NULL);
7679        if (!woperation) {
7680            PyErr_Clear();
7681            operation = NULL;
7682            goto normal;
7683        }
7684    }
7685
7686    Py_BEGIN_ALLOW_THREADS
7687    rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
7688        PyUnicode_AS_UNICODE(unipath),
7689        NULL, NULL, SW_SHOWNORMAL);
7690    Py_END_ALLOW_THREADS
7691
7692    Py_XDECREF(woperation);
7693    if (rc <= (HINSTANCE)32) {
7694        PyObject *errval = win32_error_unicode("startfile",
7695                                               PyUnicode_AS_UNICODE(unipath));
7696        return errval;
7697    }
7698    Py_INCREF(Py_None);
7699    return Py_None;
7700
7701normal:
7702    if (!PyArg_ParseTuple(args, "O&|s:startfile",
7703                          PyUnicode_FSConverter, &ofilepath,
7704                          &operation))
7705        return NULL;
7706    filepath = PyBytes_AsString(ofilepath);
7707    Py_BEGIN_ALLOW_THREADS
7708    rc = ShellExecute((HWND)0, operation, filepath,
7709                      NULL, NULL, SW_SHOWNORMAL);
7710    Py_END_ALLOW_THREADS
7711    if (rc <= (HINSTANCE)32) {
7712        PyObject *errval = win32_error("startfile", filepath);
7713        Py_DECREF(ofilepath);
7714        return errval;
7715    }
7716    Py_DECREF(ofilepath);
7717    Py_INCREF(Py_None);
7718    return Py_None;
7719}
7720#endif
7721
7722#ifdef HAVE_GETLOADAVG
7723PyDoc_STRVAR(posix_getloadavg__doc__,
7724"getloadavg() -> (float, float, float)\n\n\
7725Return the number of processes in the system run queue averaged over\n\
7726the last 1, 5, and 15 minutes or raises OSError if the load average\n\
7727was unobtainable");
7728
7729static PyObject *
7730posix_getloadavg(PyObject *self, PyObject *noargs)
7731{
7732    double loadavg[3];
7733    if (getloadavg(loadavg, 3)!=3) {
7734        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
7735        return NULL;
7736    } else
7737        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
7738}
7739#endif
7740
7741#ifdef MS_WINDOWS
7742
7743PyDoc_STRVAR(win32_urandom__doc__,
7744"urandom(n) -> str\n\n\
7745Return n random bytes suitable for cryptographic use.");
7746
7747typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\
7748              LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\
7749              DWORD dwFlags );
7750typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\
7751              BYTE *pbBuffer );
7752
7753static CRYPTGENRANDOM pCryptGenRandom = NULL;
7754/* This handle is never explicitly released. Instead, the operating
7755   system will release it when the process terminates. */
7756static HCRYPTPROV hCryptProv = 0;
7757
7758static PyObject*
7759win32_urandom(PyObject *self, PyObject *args)
7760{
7761    int howMany;
7762    PyObject* result;
7763
7764    /* Read arguments */
7765    if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
7766        return NULL;
7767    if (howMany < 0)
7768        return PyErr_Format(PyExc_ValueError,
7769                            "negative argument not allowed");
7770
7771    if (hCryptProv == 0) {
7772        HINSTANCE hAdvAPI32 = NULL;
7773        CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
7774
7775        /* Obtain handle to the DLL containing CryptoAPI
7776           This should not fail         */
7777        hAdvAPI32 = GetModuleHandle("advapi32.dll");
7778        if(hAdvAPI32 == NULL)
7779            return win32_error("GetModuleHandle", NULL);
7780
7781        /* Obtain pointers to the CryptoAPI functions
7782           This will fail on some early versions of Win95 */
7783        pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(
7784                                        hAdvAPI32,
7785                                        "CryptAcquireContextA");
7786        if (pCryptAcquireContext == NULL)
7787            return PyErr_Format(PyExc_NotImplementedError,
7788                                "CryptAcquireContextA not found");
7789
7790        pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(
7791                                        hAdvAPI32, "CryptGenRandom");
7792        if (pCryptGenRandom == NULL)
7793            return PyErr_Format(PyExc_NotImplementedError,
7794                                "CryptGenRandom not found");
7795
7796        /* Acquire context */
7797        if (! pCryptAcquireContext(&hCryptProv, NULL, NULL,
7798                                   PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
7799            return win32_error("CryptAcquireContext", NULL);
7800    }
7801
7802    /* Allocate bytes */
7803    result = PyBytes_FromStringAndSize(NULL, howMany);
7804    if (result != NULL) {
7805        /* Get random data */
7806        memset(PyBytes_AS_STRING(result), 0, howMany); /* zero seed */
7807        if (! pCryptGenRandom(hCryptProv, howMany, (unsigned char*)
7808                              PyBytes_AS_STRING(result))) {
7809            Py_DECREF(result);
7810            return win32_error("CryptGenRandom", NULL);
7811        }
7812    }
7813    return result;
7814}
7815#endif
7816
7817PyDoc_STRVAR(device_encoding__doc__,
7818"device_encoding(fd) -> str\n\n\
7819Return a string describing the encoding of the device\n\
7820if the output is a terminal; else return None.");
7821
7822static PyObject *
7823device_encoding(PyObject *self, PyObject *args)
7824{
7825    int fd;
7826    if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
7827        return NULL;
7828    if (!_PyVerify_fd(fd) || !isatty(fd)) {
7829        Py_INCREF(Py_None);
7830        return Py_None;
7831    }
7832#if defined(MS_WINDOWS) || defined(MS_WIN64)
7833    if (fd == 0) {
7834        char buf[100];
7835        sprintf(buf, "cp%d", GetConsoleCP());
7836        return PyUnicode_FromString(buf);
7837    }
7838    if (fd == 1 || fd == 2) {
7839        char buf[100];
7840        sprintf(buf, "cp%d", GetConsoleOutputCP());
7841        return PyUnicode_FromString(buf);
7842    }
7843#elif defined(CODESET)
7844    {
7845        char *codeset = nl_langinfo(CODESET);
7846        if (codeset != NULL && codeset[0] != 0)
7847            return PyUnicode_FromString(codeset);
7848    }
7849#endif
7850    Py_INCREF(Py_None);
7851    return Py_None;
7852}
7853
7854#ifdef __VMS
7855/* Use openssl random routine */
7856#include <openssl/rand.h>
7857PyDoc_STRVAR(vms_urandom__doc__,
7858"urandom(n) -> str\n\n\
7859Return n random bytes suitable for cryptographic use.");
7860
7861static PyObject*
7862vms_urandom(PyObject *self, PyObject *args)
7863{
7864    int howMany;
7865    PyObject* result;
7866
7867    /* Read arguments */
7868    if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
7869        return NULL;
7870    if (howMany < 0)
7871        return PyErr_Format(PyExc_ValueError,
7872                            "negative argument not allowed");
7873
7874    /* Allocate bytes */
7875    result = PyBytes_FromStringAndSize(NULL, howMany);
7876    if (result != NULL) {
7877        /* Get random data */
7878        if (RAND_pseudo_bytes((unsigned char*)
7879                              PyBytes_AS_STRING(result),
7880                              howMany) < 0) {
7881            Py_DECREF(result);
7882            return PyErr_Format(PyExc_ValueError,
7883                                "RAND_pseudo_bytes");
7884        }
7885    }
7886    return result;
7887}
7888#endif
7889
7890#ifdef HAVE_SETRESUID
7891PyDoc_STRVAR(posix_setresuid__doc__,
7892"setresuid(ruid, euid, suid)\n\n\
7893Set the current process's real, effective, and saved user ids.");
7894
7895static PyObject*
7896posix_setresuid (PyObject *self, PyObject *args)
7897{
7898    /* We assume uid_t is no larger than a long. */
7899    long ruid, euid, suid;
7900    if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
7901        return NULL;
7902    if (setresuid(ruid, euid, suid) < 0)
7903        return posix_error();
7904    Py_RETURN_NONE;
7905}
7906#endif
7907
7908#ifdef HAVE_SETRESGID
7909PyDoc_STRVAR(posix_setresgid__doc__,
7910"setresgid(rgid, egid, sgid)\n\n\
7911Set the current process's real, effective, and saved group ids.");
7912
7913static PyObject*
7914posix_setresgid (PyObject *self, PyObject *args)
7915{
7916    /* We assume uid_t is no larger than a long. */
7917    long rgid, egid, sgid;
7918    if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
7919        return NULL;
7920    if (setresgid(rgid, egid, sgid) < 0)
7921        return posix_error();
7922    Py_RETURN_NONE;
7923}
7924#endif
7925
7926#ifdef HAVE_GETRESUID
7927PyDoc_STRVAR(posix_getresuid__doc__,
7928"getresuid() -> (ruid, euid, suid)\n\n\
7929Get tuple of the current process's real, effective, and saved user ids.");
7930
7931static PyObject*
7932posix_getresuid (PyObject *self, PyObject *noargs)
7933{
7934    uid_t ruid, euid, suid;
7935    long l_ruid, l_euid, l_suid;
7936    if (getresuid(&ruid, &euid, &suid) < 0)
7937        return posix_error();
7938    /* Force the values into long's as we don't know the size of uid_t. */
7939    l_ruid = ruid;
7940    l_euid = euid;
7941    l_suid = suid;
7942    return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
7943}
7944#endif
7945
7946#ifdef HAVE_GETRESGID
7947PyDoc_STRVAR(posix_getresgid__doc__,
7948"getresgid() -> (rgid, egid, sgid)\n\n\
7949Get tuple of the current process's real, effective, and saved group ids.");
7950
7951static PyObject*
7952posix_getresgid (PyObject *self, PyObject *noargs)
7953{
7954    uid_t rgid, egid, sgid;
7955    long l_rgid, l_egid, l_sgid;
7956    if (getresgid(&rgid, &egid, &sgid) < 0)
7957        return posix_error();
7958    /* Force the values into long's as we don't know the size of uid_t. */
7959    l_rgid = rgid;
7960    l_egid = egid;
7961    l_sgid = sgid;
7962    return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
7963}
7964#endif
7965
7966static PyMethodDef posix_methods[] = {
7967    {"access",          posix_access, METH_VARARGS, posix_access__doc__},
7968#ifdef HAVE_TTYNAME
7969    {"ttyname",         posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
7970#endif
7971    {"chdir",           posix_chdir, METH_VARARGS, posix_chdir__doc__},
7972#ifdef HAVE_CHFLAGS
7973    {"chflags",         posix_chflags, METH_VARARGS, posix_chflags__doc__},
7974#endif /* HAVE_CHFLAGS */
7975    {"chmod",           posix_chmod, METH_VARARGS, posix_chmod__doc__},
7976#ifdef HAVE_FCHMOD
7977    {"fchmod",          posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
7978#endif /* HAVE_FCHMOD */
7979#ifdef HAVE_CHOWN
7980    {"chown",           posix_chown, METH_VARARGS, posix_chown__doc__},
7981#endif /* HAVE_CHOWN */
7982#ifdef HAVE_LCHMOD
7983    {"lchmod",          posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
7984#endif /* HAVE_LCHMOD */
7985#ifdef HAVE_FCHOWN
7986    {"fchown",          posix_fchown, METH_VARARGS, posix_fchown__doc__},
7987#endif /* HAVE_FCHOWN */
7988#ifdef HAVE_LCHFLAGS
7989    {"lchflags",        posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
7990#endif /* HAVE_LCHFLAGS */
7991#ifdef HAVE_LCHOWN
7992    {"lchown",          posix_lchown, METH_VARARGS, posix_lchown__doc__},
7993#endif /* HAVE_LCHOWN */
7994#ifdef HAVE_CHROOT
7995    {"chroot",          posix_chroot, METH_VARARGS, posix_chroot__doc__},
7996#endif
7997#ifdef HAVE_CTERMID
7998    {"ctermid",         posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
7999#endif
8000#ifdef HAVE_GETCWD
8001    {"getcwd",          (PyCFunction)posix_getcwd_unicode,
8002    METH_NOARGS, posix_getcwd__doc__},
8003    {"getcwdb",         (PyCFunction)posix_getcwd_bytes,
8004    METH_NOARGS, posix_getcwdb__doc__},
8005#endif
8006#ifdef HAVE_LINK
8007    {"link",            posix_link, METH_VARARGS, posix_link__doc__},
8008#endif /* HAVE_LINK */
8009    {"listdir",         posix_listdir, METH_VARARGS, posix_listdir__doc__},
8010    {"lstat",           posix_lstat, METH_VARARGS, posix_lstat__doc__},
8011    {"mkdir",           posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
8012#ifdef HAVE_NICE
8013    {"nice",            posix_nice, METH_VARARGS, posix_nice__doc__},
8014#endif /* HAVE_NICE */
8015#ifdef HAVE_READLINK
8016    {"readlink",        posix_readlink, METH_VARARGS, posix_readlink__doc__},
8017#endif /* HAVE_READLINK */
8018#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
8019    {"readlink",        win_readlink, METH_VARARGS, win_readlink__doc__},
8020#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
8021    {"rename",          posix_rename, METH_VARARGS, posix_rename__doc__},
8022    {"rmdir",           posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
8023    {"stat",            posix_stat, METH_VARARGS, posix_stat__doc__},
8024    {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
8025#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
8026    {"symlink",         posix_symlink, METH_VARARGS, posix_symlink__doc__},
8027#endif /* HAVE_SYMLINK */
8028#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
8029    {"symlink", (PyCFunction)win_symlink, METH_VARARGS | METH_KEYWORDS,
8030                 win_symlink__doc__},
8031#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
8032#ifdef HAVE_SYSTEM
8033    {"system",          posix_system, METH_VARARGS, posix_system__doc__},
8034#endif
8035    {"umask",           posix_umask, METH_VARARGS, posix_umask__doc__},
8036#ifdef HAVE_UNAME
8037    {"uname",           posix_uname, METH_NOARGS, posix_uname__doc__},
8038#endif /* HAVE_UNAME */
8039    {"unlink",          posix_unlink, METH_VARARGS, posix_unlink__doc__},
8040    {"remove",          posix_unlink, METH_VARARGS, posix_remove__doc__},
8041    {"utime",           posix_utime, METH_VARARGS, posix_utime__doc__},
8042#ifdef HAVE_TIMES
8043    {"times",           posix_times, METH_NOARGS, posix_times__doc__},
8044#endif /* HAVE_TIMES */
8045    {"_exit",           posix__exit, METH_VARARGS, posix__exit__doc__},
8046#ifdef HAVE_EXECV
8047    {"execv",           posix_execv, METH_VARARGS, posix_execv__doc__},
8048    {"execve",          posix_execve, METH_VARARGS, posix_execve__doc__},
8049#endif /* HAVE_EXECV */
8050#ifdef HAVE_SPAWNV
8051    {"spawnv",          posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
8052    {"spawnve",         posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
8053#if defined(PYOS_OS2)
8054    {"spawnvp",         posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
8055    {"spawnvpe",        posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
8056#endif /* PYOS_OS2 */
8057#endif /* HAVE_SPAWNV */
8058#ifdef HAVE_FORK1
8059    {"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
8060#endif /* HAVE_FORK1 */
8061#ifdef HAVE_FORK
8062    {"fork",            posix_fork, METH_NOARGS, posix_fork__doc__},
8063#endif /* HAVE_FORK */
8064#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
8065    {"openpty",         posix_openpty, METH_NOARGS, posix_openpty__doc__},
8066#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
8067#ifdef HAVE_FORKPTY
8068    {"forkpty",         posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
8069#endif /* HAVE_FORKPTY */
8070#ifdef HAVE_GETEGID
8071    {"getegid",         posix_getegid, METH_NOARGS, posix_getegid__doc__},
8072#endif /* HAVE_GETEGID */
8073#ifdef HAVE_GETEUID
8074    {"geteuid",         posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
8075#endif /* HAVE_GETEUID */
8076#ifdef HAVE_GETGID
8077    {"getgid",          posix_getgid, METH_NOARGS, posix_getgid__doc__},
8078#endif /* HAVE_GETGID */
8079#ifdef HAVE_GETGROUPS
8080    {"getgroups",       posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
8081#endif
8082    {"getpid",          posix_getpid, METH_NOARGS, posix_getpid__doc__},
8083#ifdef HAVE_GETPGRP
8084    {"getpgrp",         posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
8085#endif /* HAVE_GETPGRP */
8086#ifdef HAVE_GETPPID
8087    {"getppid",         posix_getppid, METH_NOARGS, posix_getppid__doc__},
8088#endif /* HAVE_GETPPID */
8089#ifdef HAVE_GETUID
8090    {"getuid",          posix_getuid, METH_NOARGS, posix_getuid__doc__},
8091#endif /* HAVE_GETUID */
8092#ifdef HAVE_GETLOGIN
8093    {"getlogin",        posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
8094#endif
8095#ifdef HAVE_KILL
8096    {"kill",            posix_kill, METH_VARARGS, posix_kill__doc__},
8097#endif /* HAVE_KILL */
8098#ifdef HAVE_KILLPG
8099    {"killpg",          posix_killpg, METH_VARARGS, posix_killpg__doc__},
8100#endif /* HAVE_KILLPG */
8101#ifdef HAVE_PLOCK
8102    {"plock",           posix_plock, METH_VARARGS, posix_plock__doc__},
8103#endif /* HAVE_PLOCK */
8104#ifdef MS_WINDOWS
8105    {"startfile",       win32_startfile, METH_VARARGS, win32_startfile__doc__},
8106    {"kill",    win32_kill, METH_VARARGS, win32_kill__doc__},
8107    {"link",    win32_link, METH_VARARGS, win32_link__doc__},
8108#endif
8109#ifdef HAVE_SETUID
8110    {"setuid",          posix_setuid, METH_VARARGS, posix_setuid__doc__},
8111#endif /* HAVE_SETUID */
8112#ifdef HAVE_SETEUID
8113    {"seteuid",         posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
8114#endif /* HAVE_SETEUID */
8115#ifdef HAVE_SETEGID
8116    {"setegid",         posix_setegid, METH_VARARGS, posix_setegid__doc__},
8117#endif /* HAVE_SETEGID */
8118#ifdef HAVE_SETREUID
8119    {"setreuid",        posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
8120#endif /* HAVE_SETREUID */
8121#ifdef HAVE_SETREGID
8122    {"setregid",        posix_setregid, METH_VARARGS, posix_setregid__doc__},
8123#endif /* HAVE_SETREGID */
8124#ifdef HAVE_SETGID
8125    {"setgid",          posix_setgid, METH_VARARGS, posix_setgid__doc__},
8126#endif /* HAVE_SETGID */
8127#ifdef HAVE_SETGROUPS
8128    {"setgroups",       posix_setgroups, METH_O, posix_setgroups__doc__},
8129#endif /* HAVE_SETGROUPS */
8130#ifdef HAVE_INITGROUPS
8131    {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
8132#endif /* HAVE_INITGROUPS */
8133#ifdef HAVE_GETPGID
8134    {"getpgid",         posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
8135#endif /* HAVE_GETPGID */
8136#ifdef HAVE_SETPGRP
8137    {"setpgrp",         posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
8138#endif /* HAVE_SETPGRP */
8139#ifdef HAVE_WAIT
8140    {"wait",            posix_wait, METH_NOARGS, posix_wait__doc__},
8141#endif /* HAVE_WAIT */
8142#ifdef HAVE_WAIT3
8143    {"wait3",           posix_wait3, METH_VARARGS, posix_wait3__doc__},
8144#endif /* HAVE_WAIT3 */
8145#ifdef HAVE_WAIT4
8146    {"wait4",           posix_wait4, METH_VARARGS, posix_wait4__doc__},
8147#endif /* HAVE_WAIT4 */
8148#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
8149    {"waitpid",         posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
8150#endif /* HAVE_WAITPID */
8151#ifdef HAVE_GETSID
8152    {"getsid",          posix_getsid, METH_VARARGS, posix_getsid__doc__},
8153#endif /* HAVE_GETSID */
8154#ifdef HAVE_SETSID
8155    {"setsid",          posix_setsid, METH_NOARGS, posix_setsid__doc__},
8156#endif /* HAVE_SETSID */
8157#ifdef HAVE_SETPGID
8158    {"setpgid",         posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
8159#endif /* HAVE_SETPGID */
8160#ifdef HAVE_TCGETPGRP
8161    {"tcgetpgrp",       posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
8162#endif /* HAVE_TCGETPGRP */
8163#ifdef HAVE_TCSETPGRP
8164    {"tcsetpgrp",       posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
8165#endif /* HAVE_TCSETPGRP */
8166    {"open",            posix_open, METH_VARARGS, posix_open__doc__},
8167    {"close",           posix_close, METH_VARARGS, posix_close__doc__},
8168    {"closerange",      posix_closerange, METH_VARARGS, posix_closerange__doc__},
8169    {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
8170    {"dup",             posix_dup, METH_VARARGS, posix_dup__doc__},
8171    {"dup2",            posix_dup2, METH_VARARGS, posix_dup2__doc__},
8172    {"lseek",           posix_lseek, METH_VARARGS, posix_lseek__doc__},
8173    {"read",            posix_read, METH_VARARGS, posix_read__doc__},
8174    {"write",           posix_write, METH_VARARGS, posix_write__doc__},
8175#ifdef HAVE_SENDFILE
8176    {"sendfile",        (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
8177                            posix_sendfile__doc__},
8178#endif
8179    {"fstat",           posix_fstat, METH_VARARGS, posix_fstat__doc__},
8180    {"isatty",          posix_isatty, METH_VARARGS, posix_isatty__doc__},
8181#ifdef HAVE_PIPE
8182    {"pipe",            posix_pipe, METH_NOARGS, posix_pipe__doc__},
8183#endif
8184#ifdef HAVE_MKFIFO
8185    {"mkfifo",          posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
8186#endif
8187#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
8188    {"mknod",           posix_mknod, METH_VARARGS, posix_mknod__doc__},
8189#endif
8190#ifdef HAVE_DEVICE_MACROS
8191    {"major",           posix_major, METH_VARARGS, posix_major__doc__},
8192    {"minor",           posix_minor, METH_VARARGS, posix_minor__doc__},
8193    {"makedev",         posix_makedev, METH_VARARGS, posix_makedev__doc__},
8194#endif
8195#ifdef HAVE_FTRUNCATE
8196    {"ftruncate",       posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
8197#endif
8198#ifdef HAVE_PUTENV
8199    {"putenv",          posix_putenv, METH_VARARGS, posix_putenv__doc__},
8200#endif
8201#ifdef HAVE_UNSETENV
8202    {"unsetenv",        posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
8203#endif
8204    {"strerror",        posix_strerror, METH_VARARGS, posix_strerror__doc__},
8205#ifdef HAVE_FCHDIR
8206    {"fchdir",          posix_fchdir, METH_O, posix_fchdir__doc__},
8207#endif
8208#ifdef HAVE_FSYNC
8209    {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
8210#endif
8211#ifdef HAVE_FDATASYNC
8212    {"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
8213#endif
8214#ifdef HAVE_SYS_WAIT_H
8215#ifdef WCOREDUMP
8216    {"WCOREDUMP",       posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
8217#endif /* WCOREDUMP */
8218#ifdef WIFCONTINUED
8219    {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
8220#endif /* WIFCONTINUED */
8221#ifdef WIFSTOPPED
8222    {"WIFSTOPPED",      posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
8223#endif /* WIFSTOPPED */
8224#ifdef WIFSIGNALED
8225    {"WIFSIGNALED",     posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
8226#endif /* WIFSIGNALED */
8227#ifdef WIFEXITED
8228    {"WIFEXITED",       posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
8229#endif /* WIFEXITED */
8230#ifdef WEXITSTATUS
8231    {"WEXITSTATUS",     posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
8232#endif /* WEXITSTATUS */
8233#ifdef WTERMSIG
8234    {"WTERMSIG",        posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
8235#endif /* WTERMSIG */
8236#ifdef WSTOPSIG
8237    {"WSTOPSIG",        posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
8238#endif /* WSTOPSIG */
8239#endif /* HAVE_SYS_WAIT_H */
8240#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
8241    {"fstatvfs",        posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
8242#endif
8243#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
8244    {"statvfs",         posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
8245#endif
8246#ifdef HAVE_CONFSTR
8247    {"confstr",         posix_confstr, METH_VARARGS, posix_confstr__doc__},
8248#endif
8249#ifdef HAVE_SYSCONF
8250    {"sysconf",         posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
8251#endif
8252#ifdef HAVE_FPATHCONF
8253    {"fpathconf",       posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
8254#endif
8255#ifdef HAVE_PATHCONF
8256    {"pathconf",        posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
8257#endif
8258    {"abort",           posix_abort, METH_NOARGS, posix_abort__doc__},
8259#ifdef MS_WINDOWS
8260    {"_getfullpathname",        posix__getfullpathname, METH_VARARGS, NULL},
8261    {"_getfinalpathname",       posix__getfinalpathname, METH_VARARGS, NULL},
8262    {"_getfileinformation",     posix__getfileinformation, METH_VARARGS, NULL},
8263#endif
8264#ifdef HAVE_GETLOADAVG
8265    {"getloadavg",      posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
8266#endif
8267 #ifdef MS_WINDOWS
8268    {"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__},
8269 #endif
8270 #ifdef __VMS
8271    {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__},
8272 #endif
8273#ifdef HAVE_SETRESUID
8274    {"setresuid",       posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
8275#endif
8276#ifdef HAVE_SETRESGID
8277    {"setresgid",       posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
8278#endif
8279#ifdef HAVE_GETRESUID
8280    {"getresuid",       posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
8281#endif
8282#ifdef HAVE_GETRESGID
8283    {"getresgid",       posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
8284#endif
8285
8286    {NULL,              NULL}            /* Sentinel */
8287};
8288
8289
8290static int
8291ins(PyObject *module, char *symbol, long value)
8292{
8293    return PyModule_AddIntConstant(module, symbol, value);
8294}
8295
8296#if defined(PYOS_OS2)
8297/* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
8298static int insertvalues(PyObject *module)
8299{
8300    APIRET    rc;
8301    ULONG     values[QSV_MAX+1];
8302    PyObject *v;
8303    char     *ver, tmp[50];
8304
8305    Py_BEGIN_ALLOW_THREADS
8306    rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
8307    Py_END_ALLOW_THREADS
8308
8309    if (rc != NO_ERROR) {
8310        os2_error(rc);
8311        return -1;
8312    }
8313
8314    if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
8315    if (ins(module, "memkernel",    values[QSV_TOTRESMEM])) return -1;
8316    if (ins(module, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
8317    if (ins(module, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
8318    if (ins(module, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
8319    if (ins(module, "revision",     values[QSV_VERSION_REVISION])) return -1;
8320    if (ins(module, "timeslice",    values[QSV_MIN_SLICE])) return -1;
8321
8322    switch (values[QSV_VERSION_MINOR]) {
8323    case 0:  ver = "2.00"; break;
8324    case 10: ver = "2.10"; break;
8325    case 11: ver = "2.11"; break;
8326    case 30: ver = "3.00"; break;
8327    case 40: ver = "4.00"; break;
8328    case 50: ver = "5.00"; break;
8329    default:
8330        PyOS_snprintf(tmp, sizeof(tmp),
8331                      "%d-%d", values[QSV_VERSION_MAJOR],
8332                      values[QSV_VERSION_MINOR]);
8333        ver = &tmp[0];
8334    }
8335
8336    /* Add Indicator of the Version of the Operating System */
8337    if (PyModule_AddStringConstant(module, "version", tmp) < 0)
8338        return -1;
8339
8340    /* Add Indicator of Which Drive was Used to Boot the System */
8341    tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
8342    tmp[1] = ':';
8343    tmp[2] = '\0';
8344
8345    return PyModule_AddStringConstant(module, "bootdrive", tmp);
8346}
8347#endif
8348
8349#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
8350static int
8351enable_symlink()
8352{
8353    HANDLE tok;
8354    TOKEN_PRIVILEGES tok_priv;
8355    LUID luid;
8356    int meth_idx = 0;
8357
8358    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok))
8359        return 0;
8360
8361    if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid))
8362        return 0;
8363
8364    tok_priv.PrivilegeCount = 1;
8365    tok_priv.Privileges[0].Luid = luid;
8366    tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
8367
8368    if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv,
8369                               sizeof(TOKEN_PRIVILEGES),
8370                               (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
8371        return 0;
8372
8373    /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */
8374    return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1;
8375}
8376#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
8377
8378static int
8379all_ins(PyObject *d)
8380{
8381#ifdef F_OK
8382    if (ins(d, "F_OK", (long)F_OK)) return -1;
8383#endif
8384#ifdef R_OK
8385    if (ins(d, "R_OK", (long)R_OK)) return -1;
8386#endif
8387#ifdef W_OK
8388    if (ins(d, "W_OK", (long)W_OK)) return -1;
8389#endif
8390#ifdef X_OK
8391    if (ins(d, "X_OK", (long)X_OK)) return -1;
8392#endif
8393#ifdef NGROUPS_MAX
8394    if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
8395#endif
8396#ifdef TMP_MAX
8397    if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
8398#endif
8399#ifdef WCONTINUED
8400    if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
8401#endif
8402#ifdef WNOHANG
8403    if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
8404#endif
8405#ifdef WUNTRACED
8406    if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
8407#endif
8408#ifdef O_RDONLY
8409    if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
8410#endif
8411#ifdef O_WRONLY
8412    if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
8413#endif
8414#ifdef O_RDWR
8415    if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
8416#endif
8417#ifdef O_NDELAY
8418    if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
8419#endif
8420#ifdef O_NONBLOCK
8421    if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
8422#endif
8423#ifdef O_APPEND
8424    if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
8425#endif
8426#ifdef O_DSYNC
8427    if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
8428#endif
8429#ifdef O_RSYNC
8430    if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
8431#endif
8432#ifdef O_SYNC
8433    if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
8434#endif
8435#ifdef O_NOCTTY
8436    if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
8437#endif
8438#ifdef O_CREAT
8439    if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
8440#endif
8441#ifdef O_EXCL
8442    if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
8443#endif
8444#ifdef O_TRUNC
8445    if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
8446#endif
8447#ifdef O_BINARY
8448    if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
8449#endif
8450#ifdef O_TEXT
8451    if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
8452#endif
8453#ifdef O_LARGEFILE
8454    if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
8455#endif
8456#ifdef O_SHLOCK
8457    if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
8458#endif
8459#ifdef O_EXLOCK
8460    if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
8461#endif
8462
8463/* MS Windows */
8464#ifdef O_NOINHERIT
8465    /* Don't inherit in child processes. */
8466    if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
8467#endif
8468#ifdef _O_SHORT_LIVED
8469    /* Optimize for short life (keep in memory). */
8470    /* MS forgot to define this one with a non-underscore form too. */
8471    if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
8472#endif
8473#ifdef O_TEMPORARY
8474    /* Automatically delete when last handle is closed. */
8475    if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
8476#endif
8477#ifdef O_RANDOM
8478    /* Optimize for random access. */
8479    if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
8480#endif
8481#ifdef O_SEQUENTIAL
8482    /* Optimize for sequential access. */
8483    if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
8484#endif
8485
8486/* GNU extensions. */
8487#ifdef O_ASYNC
8488    /* Send a SIGIO signal whenever input or output
8489       becomes available on file descriptor */
8490    if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
8491#endif
8492#ifdef O_DIRECT
8493    /* Direct disk access. */
8494    if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
8495#endif
8496#ifdef O_DIRECTORY
8497    /* Must be a directory.      */
8498    if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
8499#endif
8500#ifdef O_NOFOLLOW
8501    /* Do not follow links.      */
8502    if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
8503#endif
8504#ifdef O_NOATIME
8505    /* Do not update the access time. */
8506    if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
8507#endif
8508
8509    /* These come from sysexits.h */
8510#ifdef EX_OK
8511    if (ins(d, "EX_OK", (long)EX_OK)) return -1;
8512#endif /* EX_OK */
8513#ifdef EX_USAGE
8514    if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
8515#endif /* EX_USAGE */
8516#ifdef EX_DATAERR
8517    if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
8518#endif /* EX_DATAERR */
8519#ifdef EX_NOINPUT
8520    if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
8521#endif /* EX_NOINPUT */
8522#ifdef EX_NOUSER
8523    if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
8524#endif /* EX_NOUSER */
8525#ifdef EX_NOHOST
8526    if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
8527#endif /* EX_NOHOST */
8528#ifdef EX_UNAVAILABLE
8529    if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
8530#endif /* EX_UNAVAILABLE */
8531#ifdef EX_SOFTWARE
8532    if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
8533#endif /* EX_SOFTWARE */
8534#ifdef EX_OSERR
8535    if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
8536#endif /* EX_OSERR */
8537#ifdef EX_OSFILE
8538    if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
8539#endif /* EX_OSFILE */
8540#ifdef EX_CANTCREAT
8541    if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
8542#endif /* EX_CANTCREAT */
8543#ifdef EX_IOERR
8544    if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
8545#endif /* EX_IOERR */
8546#ifdef EX_TEMPFAIL
8547    if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
8548#endif /* EX_TEMPFAIL */
8549#ifdef EX_PROTOCOL
8550    if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
8551#endif /* EX_PROTOCOL */
8552#ifdef EX_NOPERM
8553    if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
8554#endif /* EX_NOPERM */
8555#ifdef EX_CONFIG
8556    if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
8557#endif /* EX_CONFIG */
8558#ifdef EX_NOTFOUND
8559    if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
8560#endif /* EX_NOTFOUND */
8561
8562    /* statvfs */
8563#ifdef ST_RDONLY
8564    if (ins(d, "ST_RDONLY", (long)ST_RDONLY)) return -1;
8565#endif /* ST_RDONLY */
8566#ifdef ST_NOSUID
8567    if (ins(d, "ST_NOSUID", (long)ST_NOSUID)) return -1;
8568#endif /* ST_NOSUID */
8569
8570    /* FreeBSD sendfile() constants */
8571#ifdef SF_NODISKIO
8572    if (ins(d, "SF_NODISKIO", (long)SF_NODISKIO)) return -1;
8573#endif
8574#ifdef SF_MNOWAIT
8575    if (ins(d, "SF_MNOWAIT", (long)SF_MNOWAIT)) return -1;
8576#endif
8577#ifdef SF_SYNC
8578    if (ins(d, "SF_SYNC", (long)SF_SYNC)) return -1;
8579#endif
8580
8581#ifdef HAVE_SPAWNV
8582#if defined(PYOS_OS2) && defined(PYCC_GCC)
8583    if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
8584    if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
8585    if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
8586    if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
8587    if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
8588    if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
8589    if (ins(d, "P_PM", (long)P_PM)) return -1;
8590    if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
8591    if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
8592    if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
8593    if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
8594    if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
8595    if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
8596    if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
8597    if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
8598    if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
8599    if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
8600    if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
8601    if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
8602    if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
8603#else
8604    if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
8605    if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
8606    if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
8607    if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
8608    if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
8609#endif
8610#endif
8611
8612#if defined(PYOS_OS2)
8613    if (insertvalues(d)) return -1;
8614#endif
8615    return 0;
8616}
8617
8618
8619#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
8620#define INITFUNC PyInit_nt
8621#define MODNAME "nt"
8622
8623#elif defined(PYOS_OS2)
8624#define INITFUNC PyInit_os2
8625#define MODNAME "os2"
8626
8627#else
8628#define INITFUNC PyInit_posix
8629#define MODNAME "posix"
8630#endif
8631
8632static struct PyModuleDef posixmodule = {
8633    PyModuleDef_HEAD_INIT,
8634    MODNAME,
8635    posix__doc__,
8636    -1,
8637    posix_methods,
8638    NULL,
8639    NULL,
8640    NULL,
8641    NULL
8642};
8643
8644
8645PyMODINIT_FUNC
8646INITFUNC(void)
8647{
8648    PyObject *m, *v;
8649
8650#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
8651    win32_can_symlink = enable_symlink();
8652#endif
8653
8654    m = PyModule_Create(&posixmodule);
8655    if (m == NULL)
8656        return NULL;
8657
8658    /* Initialize environ dictionary */
8659    v = convertenviron();
8660    Py_XINCREF(v);
8661    if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
8662        return NULL;
8663    Py_DECREF(v);
8664
8665    if (all_ins(m))
8666        return NULL;
8667
8668    if (setup_confname_tables(m))
8669        return NULL;
8670
8671    Py_INCREF(PyExc_OSError);
8672    PyModule_AddObject(m, "error", PyExc_OSError);
8673
8674#ifdef HAVE_PUTENV
8675    if (posix_putenv_garbage == NULL)
8676        posix_putenv_garbage = PyDict_New();
8677#endif
8678
8679    if (!initialized) {
8680        stat_result_desc.name = MODNAME ".stat_result";
8681        stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
8682        stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
8683        stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
8684        PyStructSequence_InitType(&StatResultType, &stat_result_desc);
8685        structseq_new = StatResultType.tp_new;
8686        StatResultType.tp_new = statresult_new;
8687
8688        statvfs_result_desc.name = MODNAME ".statvfs_result";
8689        PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
8690#ifdef NEED_TICKS_PER_SECOND
8691#  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
8692        ticks_per_second = sysconf(_SC_CLK_TCK);
8693#  elif defined(HZ)
8694        ticks_per_second = HZ;
8695#  else
8696        ticks_per_second = 60; /* magic fallback value; may be bogus */
8697#  endif
8698#endif
8699    }
8700    Py_INCREF((PyObject*) &StatResultType);
8701    PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
8702    Py_INCREF((PyObject*) &StatVFSResultType);
8703    PyModule_AddObject(m, "statvfs_result",
8704                       (PyObject*) &StatVFSResultType);
8705    initialized = 1;
8706
8707#ifdef __APPLE__
8708    /*
8709     * Step 2 of weak-linking support on Mac OS X.
8710     *
8711     * The code below removes functions that are not available on the
8712     * currently active platform.
8713     *
8714     * This block allow one to use a python binary that was build on
8715     * OSX 10.4 on OSX 10.3, without loosing access to new APIs on
8716     * OSX 10.4.
8717     */
8718#ifdef HAVE_FSTATVFS
8719    if (fstatvfs == NULL) {
8720        if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
8721            return NULL;
8722        }
8723    }
8724#endif /* HAVE_FSTATVFS */
8725
8726#ifdef HAVE_STATVFS
8727    if (statvfs == NULL) {
8728        if (PyObject_DelAttrString(m, "statvfs") == -1) {
8729            return NULL;
8730        }
8731    }
8732#endif /* HAVE_STATVFS */
8733
8734# ifdef HAVE_LCHOWN
8735    if (lchown == NULL) {
8736        if (PyObject_DelAttrString(m, "lchown") == -1) {
8737            return NULL;
8738        }
8739    }
8740#endif /* HAVE_LCHOWN */
8741
8742
8743#endif /* __APPLE__ */
8744    return m;
8745
8746}
8747
8748#ifdef __cplusplus
8749}
8750#endif
8751