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