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 ×, &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, ¶m)) 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, ¶m) == -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, ¶m)) 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, ¶m)) 5735 return NULL; 5736 if (sched_setparam(pid, ¶m)) 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, ×_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