/* POSIX module implementation */ /* This file is also used for Windows NT/MS-Win. In that case the module actually calls itself 'nt', not 'posix', and a few functions are either unimplemented or implemented differently. The source assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent of the compiler used. Different compilers define their own feature test macro, e.g. '_MSC_VER'. */ #include "Python.h" #ifdef __VXWORKS__ # include "pycore_bitutils.h" // _Py_popcount32() #endif #include "pycore_abstract.h" // _PyNumber_Index() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_ReInitThreads() #include "pycore_fileutils.h" // _Py_closerange() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_long.h" // _PyLong_IsNegative() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyObject_LookupSpecial() #include "pycore_pylifecycle.h" // _PyOS_URandom() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_signal.h" // Py_NSIG #include "pycore_time.h" // _PyLong_FromTime_t() #include "pycore_typeobject.h" // _PyType_AddMethod() #ifdef HAVE_UNISTD_H # include <unistd.h> // symlink() #endif #ifdef MS_WINDOWS # include <windows.h> # if !defined(MS_WINDOWS_GAMES) || defined(MS_WINDOWS_DESKTOP) # include <pathcch.h> # endif # include <winioctl.h> # include <lmcons.h> // UNLEN # include "osdefs.h" // SEP # include <aclapi.h> // SetEntriesInAcl # include <sddl.h> // SDDL_REVISION_1 # if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) #define HAVE_SYMLINK # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */ #endif #ifndef MS_WINDOWS # include "posixmodule.h" #else # include "pycore_fileutils_windows.h" # include "winreparse.h" #endif #if !defined(EX_OK) && defined(EXIT_SUCCESS) #define EX_OK … #endif #ifdef __APPLE__ /* Needed for the implementation of os.statvfs */ # include <sys/param.h> # include <sys/mount.h> #endif /* On android API level 21, 'AT_EACCESS' is not declared although * HAVE_FACCESSAT is defined. */ #ifdef __ANDROID__ # undef HAVE_FACCESSAT #endif #include <stdio.h> // ctermid() #include <stdlib.h> // system() #ifdef HAVE_SYS_TIME_H # include <sys/time.h> // futimes() #endif // SGI apparently needs this forward declaration #ifdef HAVE__GETPTY # include <sys/types.h> // mode_t extern char * _getpty(int *, int, mode_t, int); #endif /* * A number of APIs are available on macOS from a certain macOS version. * To support building with a new SDK while deploying to older versions * the availability test is split into two: * - HAVE_<FUNCTION>: The configure check for compile time availability * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability * * The latter is always true when not on macOS, or when using a compiler * that does not support __has_builtin (older versions of Xcode). * * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME: * if (HAVE_<FUNCTION>_RUNTIME) { ... } * * In mixing the test with other tests or using negations will result in compile * errors. */ #if defined(__APPLE__) #include <mach/mach.h> #if defined(__has_builtin) #if __has_builtin(__builtin_available) #define HAVE_BUILTIN_AVAILABLE … #endif #endif #ifdef HAVE_BUILTIN_AVAILABLE #define HAVE_FSTATAT_RUNTIME … #define HAVE_FACCESSAT_RUNTIME … #define HAVE_FCHMODAT_RUNTIME … #define HAVE_FCHOWNAT_RUNTIME … #define HAVE_LINKAT_RUNTIME … #define HAVE_FDOPENDIR_RUNTIME … #define HAVE_MKDIRAT_RUNTIME … #define HAVE_RENAMEAT_RUNTIME … #define HAVE_UNLINKAT_RUNTIME … #define HAVE_OPENAT_RUNTIME … #define HAVE_READLINKAT_RUNTIME … #define HAVE_SYMLINKAT_RUNTIME … #define HAVE_FUTIMENS_RUNTIME … #define HAVE_UTIMENSAT_RUNTIME … #define HAVE_PWRITEV_RUNTIME … #define HAVE_MKFIFOAT_RUNTIME … #define HAVE_MKNODAT_RUNTIME … #define HAVE_PTSNAME_R_RUNTIME … #define HAVE_POSIX_SPAWN_SETSID_RUNTIME … #else /* Xcode 8 or earlier */ /* __builtin_available is not present in these compilers, but * some of the symbols might be weak linked (10.10 SDK or later * deploying on 10.9. * * Fall back to the older style of availability checking for * symbols introduced in macOS 10.10. */ # ifdef HAVE_FSTATAT #define HAVE_FSTATAT_RUNTIME … # endif # ifdef HAVE_FACCESSAT #define HAVE_FACCESSAT_RUNTIME … # endif # ifdef HAVE_FCHMODAT #define HAVE_FCHMODAT_RUNTIME … # endif # ifdef HAVE_FCHOWNAT #define HAVE_FCHOWNAT_RUNTIME … # endif # ifdef HAVE_LINKAT #define HAVE_LINKAT_RUNTIME … # endif # ifdef HAVE_FDOPENDIR #define HAVE_FDOPENDIR_RUNTIME … # endif # ifdef HAVE_MKDIRAT #define HAVE_MKDIRAT_RUNTIME … # endif # ifdef HAVE_RENAMEAT #define HAVE_RENAMEAT_RUNTIME … # endif # ifdef HAVE_UNLINKAT #define HAVE_UNLINKAT_RUNTIME … # endif # ifdef HAVE_OPENAT #define HAVE_OPENAT_RUNTIME … # endif # ifdef HAVE_READLINKAT #define HAVE_READLINKAT_RUNTIME … # endif # ifdef HAVE_SYMLINKAT #define HAVE_SYMLINKAT_RUNTIME … # endif # ifdef HAVE_UTIMENSAT #define HAVE_UTIMENSAT_RUNTIME … # endif # ifdef HAVE_FUTIMENS #define HAVE_FUTIMENS_RUNTIME … # endif # ifdef HAVE_PWRITEV #define HAVE_PWRITEV_RUNTIME … # endif # ifdef HAVE_MKFIFOAT #define HAVE_MKFIFOAT_RUNTIME … # endif # ifdef HAVE_MKNODAT #define HAVE_MKNODAT_RUNTIME … # endif # ifdef HAVE_PTSNAME_R #define HAVE_PTSNAME_R_RUNTIME … # endif #endif #ifdef HAVE_FUTIMESAT /* Some of the logic for weak linking depends on this assertion */ # error "HAVE_FUTIMESAT unexpectedly defined" #endif #else #define HAVE_FSTATAT_RUNTIME … #define HAVE_FACCESSAT_RUNTIME … #define HAVE_FCHMODAT_RUNTIME … #define HAVE_FCHOWNAT_RUNTIME … #define HAVE_LINKAT_RUNTIME … #define HAVE_FDOPENDIR_RUNTIME … #define HAVE_MKDIRAT_RUNTIME … #define HAVE_RENAMEAT_RUNTIME … #define HAVE_UNLINKAT_RUNTIME … #define HAVE_OPENAT_RUNTIME … #define HAVE_READLINKAT_RUNTIME … #define HAVE_SYMLINKAT_RUNTIME … #define HAVE_FUTIMENS_RUNTIME … #define HAVE_UTIMENSAT_RUNTIME … #define HAVE_PWRITEV_RUNTIME … #define HAVE_MKFIFOAT_RUNTIME … #define HAVE_MKNODAT_RUNTIME … #define HAVE_PTSNAME_R_RUNTIME … #endif PyDoc_STRVAR(posix__doc__, "This module provides access to operating system functionality that is\n\ standardized by the C Standard and the POSIX standard (a thinly\n\ disguised Unix interface). Refer to the library manual and\n\ corresponding Unix manual entries for more information on calls."); #ifdef HAVE_SYS_UIO_H # include <sys/uio.h> #endif #ifdef HAVE_SYS_TYPES_H /* Should be included before <sys/sysmacros.h> on HP-UX v3 */ # include <sys/types.h> #endif /* HAVE_SYS_TYPES_H */ #ifdef HAVE_SYS_SYSMACROS_H /* GNU C Library: major(), minor(), makedev() */ # include <sys/sysmacros.h> #endif #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif /* HAVE_SYS_STAT_H */ #ifdef HAVE_SYS_WAIT_H # include <sys/wait.h> // WNOHANG #endif #ifdef HAVE_LINUX_WAIT_H # include <linux/wait.h> // P_PIDFD #endif #ifdef HAVE_SIGNAL_H # include <signal.h> #endif #ifdef HAVE_FCNTL_H # include <fcntl.h> #endif #ifdef HAVE_GRP_H # include <grp.h> #endif #ifdef HAVE_SYSEXITS_H # include <sysexits.h> #endif #ifdef HAVE_SYS_LOADAVG_H # include <sys/loadavg.h> #endif #ifdef HAVE_SYS_SENDFILE_H # include <sys/sendfile.h> #endif #if defined(__APPLE__) # include <copyfile.h> #endif #ifdef HAVE_SCHED_H # include <sched.h> #endif #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) # undef HAVE_SCHED_SETAFFINITY #endif #if defined(HAVE_SYS_XATTR_H) # if defined(HAVE_LINUX_LIMITS_H) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) #define USE_XATTRS # include <linux/limits.h> // Needed for XATTR_SIZE_MAX on musl libc. # endif # if defined(__CYGWIN__) #define USE_XATTRS # include <cygwin/limits.h> // Needed for XATTR_SIZE_MAX and XATTR_LIST_MAX. # endif #endif #ifdef USE_XATTRS # include <sys/xattr.h> #endif #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) # ifdef HAVE_SYS_SOCKET_H # include <sys/socket.h> # endif #endif #ifdef HAVE_DLFCN_H # include <dlfcn.h> #endif #ifdef __hpux # include <sys/mpctl.h> #endif #if defined(__DragonFly__) || \ defined(__OpenBSD__) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) || \ defined(__APPLE__) # include <sys/sysctl.h> #endif #ifdef HAVE_LINUX_RANDOM_H # include <linux/random.h> #endif #ifdef HAVE_GETRANDOM_SYSCALL # include <sys/syscall.h> #endif #ifdef HAVE_WINDOWS_CONSOLE_IO #define TERMSIZE_USE_CONIO #elif defined(HAVE_SYS_IOCTL_H) # include <sys/ioctl.h> # if defined(HAVE_TERMIOS_H) # include <termios.h> # endif # if defined(TIOCGWINSZ) #define TERMSIZE_USE_IOCTL # endif #endif /* HAVE_WINDOWS_CONSOLE_IO */ /* Various compilers have only certain posix functions */ /* XXX Gosh I wish these were all moved into pyconfig.h */ #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ #define HAVE_OPENDIR … #define HAVE_SYSTEM … # include <process.h> #elif defined( _MSC_VER) /* Microsoft compiler */ # if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM) #define HAVE_GETPPID … # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_APP | MS_WINDOWS_SYSTEM */ # if defined(MS_WINDOWS_DESKTOP) #define HAVE_GETLOGIN … # endif /* MS_WINDOWS_DESKTOP */ # if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM) #define HAVE_SPAWNV … #define HAVE_EXECV … #define HAVE_WSPAWNV … #define HAVE_WEXECV … #define HAVE_SYSTEM … #define HAVE_CWAIT … # endif /* MS_WINDOWS_DESKTOP | MS_WINDOWS_SYSTEM */ #define HAVE_PIPE … #define HAVE_FSYNC … #define fsync … #endif /* ! __WATCOMC__ || __QNX__ */ /*[clinic input] # one of the few times we lie about this name! module os [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ #ifndef _MSC_VER #if defined(__sgi)&&_COMPILER_VERSION>=700 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode (default) */ extern char *ctermid_r(char *); #endif #endif /* !_MSC_VER */ #if defined(__VXWORKS__) # include <vxCpuLib.h> # include <rtpLib.h> # include <wait.h> # include <taskLib.h> # ifndef _P_WAIT #define _P_WAIT … #define _P_NOWAIT … #define _P_NOWAITO … # endif #endif /* __VXWORKS__ */ #ifdef HAVE_POSIX_SPAWN # include <spawn.h> #endif #ifdef HAVE_UTIME_H # include <utime.h> #endif /* HAVE_UTIME_H */ #ifdef HAVE_SYS_UTIME_H # include <sys/utime.h> #define HAVE_UTIME_H … #endif /* HAVE_SYS_UTIME_H */ #ifdef HAVE_SYS_TIMES_H # include <sys/times.h> #endif /* HAVE_SYS_TIMES_H */ #ifdef HAVE_SYS_PARAM_H # include <sys/param.h> #endif /* HAVE_SYS_PARAM_H */ #ifdef HAVE_SYS_UTSNAME_H # include <sys/utsname.h> #endif /* HAVE_SYS_UTSNAME_H */ #ifdef HAVE_DIRENT_H # include <dirent.h> #define NAMLEN(dirent) … #else # if defined(__WATCOMC__) && !defined(__QNX__) # include <direct.h> #define NAMLEN … # else #define dirent … #define NAMLEN … # endif # ifdef HAVE_SYS_NDIR_H # include <sys/ndir.h> # endif # ifdef HAVE_SYS_DIR_H # include <sys/dir.h> # endif # ifdef HAVE_NDIR_H # include <ndir.h> # endif #endif #ifdef _MSC_VER # ifdef HAVE_DIRECT_H # include <direct.h> # endif # ifdef HAVE_IO_H # include <io.h> # endif # ifdef HAVE_PROCESS_H # include <process.h> # endif # include <malloc.h> #endif /* _MSC_VER */ #ifndef MAXPATHLEN # if defined(PATH_MAX) && PATH_MAX > 1024 #define MAXPATHLEN … # else #define MAXPATHLEN … # endif #endif /* MAXPATHLEN */ #ifdef UNION_WAIT /* Emulate some macros on systems that have a union instead of macros */ # ifndef WIFEXITED #define WIFEXITED … # endif # ifndef WEXITSTATUS #define WEXITSTATUS … # endif # ifndef WTERMSIG #define WTERMSIG … # endif #define WAIT_TYPE … #define WAIT_STATUS_INT … #else /* !UNION_WAIT */ #define WAIT_TYPE … #define WAIT_STATUS_INT(s) … #endif /* UNION_WAIT */ /* Don't use the "_r" form if we don't need it (also, won't have a prototype for it, at least on Solaris -- maybe others as well?). */ #if defined(HAVE_CTERMID_R) #define USE_CTERMID_R #endif /* choose the appropriate stat and fstat functions and return structs */ #undef STAT #undef FSTAT #undef STRUCT_STAT #ifdef MS_WINDOWS #define STAT … #define LSTAT … #define FSTAT … #define STRUCT_STAT … #else #define STAT … #define LSTAT … #define FSTAT … #define STRUCT_STAT … #endif #if defined(MAJOR_IN_MKDEV) # include <sys/mkdev.h> #else # if defined(MAJOR_IN_SYSMACROS) # include <sys/sysmacros.h> # endif # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) # include <sys/mkdev.h> # endif #endif #ifdef MS_WINDOWS #define INITFUNC … #define MODNAME … #define MODNAME_OBJ … #else #define INITFUNC … #define MODNAME … #define MODNAME_OBJ … #endif #if defined(__sun) /* Something to implement in autoconf, not present in autoconf 2.69 */ #define HAVE_STRUCT_STAT_ST_FSTYPE … #endif /* memfd_create is either defined in sys/mman.h or sys/memfd.h * linux/memfd.h defines additional flags */ #ifdef HAVE_SYS_MMAN_H # include <sys/mman.h> #endif #ifdef HAVE_SYS_MEMFD_H # include <sys/memfd.h> #endif #ifdef HAVE_LINUX_MEMFD_H # include <linux/memfd.h> #endif /* eventfd() */ #ifdef HAVE_SYS_EVENTFD_H # include <sys/eventfd.h> #endif /* timerfd_create() */ #ifdef HAVE_SYS_TIMERFD_H # include <sys/timerfd.h> #endif #ifdef _Py_MEMORY_SANITIZER # include <sanitizer/msan_interface.h> #endif #ifdef HAVE_FORK static void run_at_forkers(PyObject *lst, int reverse) { … } void PyOS_BeforeFork(void) { … } void PyOS_AfterFork_Parent(void) { … } void PyOS_AfterFork_Child(void) { … } static int register_at_forker(PyObject **lst, PyObject *func) { … } #endif /* HAVE_FORK */ /* Legacy wrapper */ void PyOS_AfterFork(void) { … } #ifdef MS_WINDOWS /* defined in fileutils.c */ void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG, FILE_BASIC_INFO *, FILE_ID_INFO *, struct _Py_stat_struct *); void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *, struct _Py_stat_struct *); #endif #ifndef MS_WINDOWS PyObject * _PyLong_FromUid(uid_t uid) { … } PyObject * _PyLong_FromGid(gid_t gid) { … } int _Py_Uid_Converter(PyObject *obj, uid_t *p) { … } int _Py_Gid_Converter(PyObject *obj, gid_t *p) { … } #endif /* MS_WINDOWS */ static PyObject * _PyLong_FromDev(dev_t dev) { … } #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS) static int _Py_Dev_Converter(PyObject *obj, void *p) { … } #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */ #ifdef AT_FDCWD /* * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); * without the int cast, the value gets interpreted as uint (4291925331), * which doesn't play nicely with all the initializer lines in this file that * look like this: * int dir_fd = DEFAULT_DIR_FD; */ #define DEFAULT_DIR_FD … #else #define DEFAULT_DIR_FD … #endif static int _fd_converter(PyObject *o, int *p) { … } static int dir_fd_converter(PyObject *o, void *p) { … } _posixstate; static inline _posixstate* get_posix_state(PyObject *module) { … } /* * A PyArg_ParseTuple "converter" function * that handles filesystem paths in the manner * preferred by the os module. * * path_converter accepts (Unicode) strings and their * subclasses, and bytes and their subclasses. What * it does with the argument depends on path.make_wide: * * * If path.make_wide is nonzero, if we get a (Unicode) * string we extract the wchar_t * and return it; if we * get bytes we decode to wchar_t * and return that. * * * If path.make_wide is zero, if we get bytes we extract * the char_t * and return it; if we get a (Unicode) * string we encode to char_t * and return that. * * path_converter also optionally accepts signed * integers (representing open file descriptors) instead * of path strings. * * Input fields: * path.nullable * If nonzero, the path is permitted to be None. * path.nonstrict * If nonzero, the path is permitted to contain * embedded null characters and have any length. * path.make_wide * If nonzero, the converter always uses wide, decoding if necessary, else * it always uses narrow, encoding if necessary. The default value is * nonzero on Windows, else zero. * path.suppress_value_error * If nonzero, raising ValueError is suppressed. * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. * path.function_name * If non-NULL, path_converter will use that as the name * of the function in error messages. * (If path.function_name is NULL it omits the function name.) * path.argument_name * If non-NULL, path_converter will use that as the name * of the parameter in error messages. * (If path.argument_name is NULL it uses "path".) * * Output fields: * path.wide * Points to the path if it was expressed as Unicode * or if it was bytes and decoded to Unicode. * path.narrow * Points to the path if it was expressed as bytes, * or if it was Unicode and encoded to bytes. * path.fd * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any * sort of string. * * WARNING: if your "path" parameter is optional, and is * unspecified, path_converter will never get called. * So if you set allow_fd, you *MUST* initialize path.fd = -1 * yourself! * path.value_error * If nonzero, then suppress_value_error was specified and a ValueError * occurred. * path.length * The length of the path in characters, if specified as * a string. * path.object * The original object passed in (if get a PathLike object, * the result of PyOS_FSPath() is treated as the original object). * Own a reference to the object. * path.cleanup * For internal use only. May point to a temporary object. * (Pay no attention to the man behind the curtain.) * * At most one of path.wide or path.narrow will be non-NULL. * If path was None and path.nullable was set, * or if path was an integer and path.allow_fd was set, * both path.wide and path.narrow will be NULL * and path.length will be 0. * * path_converter takes care to not write to the path_t * unless it's successful. However it must reset the * "cleanup" field each time it's called. * * Use as follows: * path_t path; * memset(&path, 0, sizeof(path)); * PyArg_ParseTuple(args, "O&", path_converter, &path); * // ... use values from path ... * path_cleanup(&path); * * (Note that if PyArg_Parse fails you don't need to call * path_cleanup(). However it is safe to do so.) */ path_t; #define PATH_T_INITIALIZE(function_name, argument_name, nullable, nonstrict, \ make_wide, suppress_value_error, allow_fd) … #ifdef MS_WINDOWS #define PATH_T_INITIALIZE_P … #else #define PATH_T_INITIALIZE_P(function_name, argument_name, nullable, \ nonstrict, suppress_value_error, allow_fd) … #endif static void path_cleanup(path_t *path) { … } static int path_converter(PyObject *o, void *p) { … } static void argument_unavailable_error(const char *function_name, const char *argument_name) { … } static int dir_fd_unavailable(PyObject *o, void *p) { … } static int fd_specified(const char *function_name, int fd) { … } static int follow_symlinks_specified(const char *function_name, int follow_symlinks) { … } static int path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) { … } static int dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) { … } static int fd_and_follow_symlinks_invalid(const char *function_name, int fd, int follow_symlinks) { … } static int dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, int follow_symlinks) { … } #if defined(HAVE_WAITID) static int idtype_t_converter(PyObject *arg, void *addr) { … } #endif #ifdef MS_WINDOWS typedef long long Py_off_t; #else Py_off_t; #endif static int Py_off_t_converter(PyObject *arg, void *addr) { … } static PyObject * PyLong_FromPy_off_t(Py_off_t offset) { … } #ifdef HAVE_SIGSET_T /* Convert an iterable of integers to a sigset. Return 1 on success, return 0 and raise an exception on error. */ int _Py_Sigset_Converter(PyObject *obj, void *addr) { … } #endif /* HAVE_SIGSET_T */ /* Return a dictionary corresponding to the POSIX environment table */ #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) /* On Darwin/MacOSX a shared library or framework has no access to ** environ directly, we must obtain it with _NSGetEnviron(). See also ** man environ(7). */ #include <crt_externs.h> #define USE_DARWIN_NS_GET_ENVIRON … #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) extern char **environ; #endif /* !_MSC_VER */ static PyObject * convertenviron(void) { … } /* Set a POSIX-specific error from errno, and return NULL */ static PyObject * posix_error(void) { … } #ifdef MS_WINDOWS static PyObject * win32_error(const char* function, const char* filename) { /* XXX We should pass the function name along in the future. (winreg.c also wants to pass the function name.) This would however require an additional param to the Windows error object, which is non-trivial. */ errno = GetLastError(); if (filename) return PyErr_SetFromWindowsErrWithFilename(errno, filename); else return PyErr_SetFromWindowsErr(errno); } static PyObject * win32_error_object_err(const char* function, PyObject* filename, DWORD err) { /* XXX - see win32_error for comments on 'function' */ if (filename) return PyErr_SetExcFromWindowsErrWithFilenameObject( PyExc_OSError, err, filename); else return PyErr_SetFromWindowsErr(err); } static PyObject * win32_error_object(const char* function, PyObject* filename) { errno = GetLastError(); return win32_error_object_err(function, filename, errno); } #endif /* MS_WINDOWS */ static PyObject * posix_path_object_error(PyObject *path) { … } static PyObject * path_object_error(PyObject *path) { … } static PyObject * path_object_error2(PyObject *path, PyObject *path2) { … } static PyObject * path_error(path_t *path) { … } static PyObject * posix_path_error(path_t *path) { … } static PyObject * path_error2(path_t *path, path_t *path2) { … } /* POSIX generic methods */ static PyObject * posix_fildes_fd(int fd, int (*func)(int)) { … } #ifdef MS_WINDOWS /* This is a reimplementation of the C library's chdir function, but one that produces Win32 errors instead of DOS error codes. chdir is essentially a wrapper around SetCurrentDirectory; however, it also needs to set "magic" environment variables indicating the per-drive current directory, which are of the form =<drive>: */ static BOOL __stdcall win32_wchdir(LPCWSTR path) { wchar_t path_buf[MAX_PATH], *new_path = path_buf; int result; wchar_t env[4] = L"=x:"; if(!SetCurrentDirectoryW(path)) return FALSE; result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); if (!result) return FALSE; if (result > Py_ARRAY_LENGTH(path_buf)) { new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); if (!new_path) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } result = GetCurrentDirectoryW(result, new_path); if (!result) { PyMem_RawFree(new_path); return FALSE; } } int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || wcsncmp(new_path, L"//", 2) == 0); if (!is_unc_like_path) { env[1] = new_path[0]; result = SetEnvironmentVariableW(env, new_path); } if (new_path != path_buf) PyMem_RawFree(new_path); return result ? TRUE : FALSE; } #endif #ifdef MS_WINDOWS /* The CRT of Windows has a number of flaws wrt. its stat() implementation: - time stamps are restricted to second resolution - file modification times suffer from forth-and-back conversions between UTC and local time Therefore, we implement our own stat, based on the Win32 API directly. */ #define HAVE_STAT_NSEC … #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES … #define HAVE_STRUCT_STAT_ST_REPARSE_TAG … static void find_data_to_file_info(WIN32_FIND_DATAW *pFileData, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) { memset(info, 0, sizeof(*info)); info->dwFileAttributes = pFileData->dwFileAttributes; info->ftCreationTime = pFileData->ftCreationTime; info->ftLastAccessTime = pFileData->ftLastAccessTime; info->ftLastWriteTime = pFileData->ftLastWriteTime; info->nFileSizeHigh = pFileData->nFileSizeHigh; info->nFileSizeLow = pFileData->nFileSizeLow; /* info->nNumberOfLinks = 1; */ if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) *reparse_tag = pFileData->dwReserved0; else *reparse_tag = 0; } static BOOL attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) { HANDLE hFindFile; WIN32_FIND_DATAW FileData; LPCWSTR filename = pszFile; size_t n = wcslen(pszFile); if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { // cannot use PyMem_Malloc here because we do not hold the GIL filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); if(!filename) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { ((LPWSTR)filename)[n] = L'\0'; } if (!n || (n == 1 && filename[1] == L':')) { // Nothing left to query free((void *)filename); return FALSE; } } hFindFile = FindFirstFileW(filename, &FileData); if (pszFile != filename) { free((void *)filename); } if (hFindFile == INVALID_HANDLE_VALUE) { return FALSE; } FindClose(hFindFile); find_data_to_file_info(&FileData, info, reparse_tag); return TRUE; } static void update_st_mode_from_path(const wchar_t *path, DWORD attr, struct _Py_stat_struct *result) { if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* Fix the file execute permissions. This hack sets S_IEXEC if the filename has an extension that is commonly used by files that CreateProcessW can execute. A real implementation calls GetSecurityInfo, OpenThreadToken/OpenProcessToken, and AccessCheck to check for generic read, write, and execute access. */ const wchar_t *fileExtension = wcsrchr(path, '.'); if (fileExtension) { if (_wcsicmp(fileExtension, L".exe") == 0 || _wcsicmp(fileExtension, L".bat") == 0 || _wcsicmp(fileExtension, L".cmd") == 0 || _wcsicmp(fileExtension, L".com") == 0) { result->st_mode |= 0111; } } } } static int win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { HANDLE hFile; BY_HANDLE_FILE_INFORMATION fileInfo; FILE_BASIC_INFO basicInfo; FILE_BASIC_INFO *pBasicInfo = NULL; FILE_ID_INFO idInfo; FILE_ID_INFO *pIdInfo = NULL; FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; DWORD fileType, error; BOOL isUnhandledTag = FALSE; int retval = 0; DWORD access = FILE_READ_ATTRIBUTES; DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ if (!traverse) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { /* Either the path doesn't exist, or the caller lacks access. */ error = GetLastError(); switch (error) { case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ case ERROR_SHARING_VIOLATION: /* It's a paging file. */ /* Try reading the parent directory. */ if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { /* Cannot read the parent directory. */ switch (GetLastError()) { case ERROR_FILE_NOT_FOUND: /* File cannot be found */ case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */ case ERROR_NOT_READY: /* Drive exists but unavailable */ case ERROR_BAD_NET_NAME: /* Remote drive unavailable */ break; /* Restore the error from CreateFileW(). */ default: SetLastError(error); } return -1; } if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (traverse || !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { /* The stat call has to traverse but cannot, so fail. */ SetLastError(error); return -1; } } break; case ERROR_INVALID_PARAMETER: /* \\.\con requires read or write access. */ hFile = CreateFileW(path, access | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { SetLastError(error); return -1; } break; case ERROR_CANT_ACCESS_FILE: /* bpo37834: open unhandled reparse points if traverse fails. */ if (traverse) { traverse = FALSE; isUnhandledTag = TRUE; hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); } if (hFile == INVALID_HANDLE_VALUE) { SetLastError(error); return -1; } break; default: return -1; } } if (hFile != INVALID_HANDLE_VALUE) { /* Handle types other than files on disk. */ fileType = GetFileType(hFile); if (fileType != FILE_TYPE_DISK) { if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { retval = -1; goto cleanup; } DWORD fileAttributes = GetFileAttributesW(path); memset(result, 0, sizeof(*result)); if (fileAttributes != INVALID_FILE_ATTRIBUTES && fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* \\.\pipe\ or \\.\mailslot\ */ result->st_mode = _S_IFDIR; } else if (fileType == FILE_TYPE_CHAR) { /* \\.\nul */ result->st_mode = _S_IFCHR; } else if (fileType == FILE_TYPE_PIPE) { /* \\.\pipe\spam */ result->st_mode = _S_IFIFO; } /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ goto cleanup; } /* Query the reparse tag, and traverse a non-link. */ if (!traverse) { if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, &tagInfo, sizeof(tagInfo))) { /* Allow devices that do not support FileAttributeTagInfo. */ switch (GetLastError()) { case ERROR_INVALID_PARAMETER: case ERROR_INVALID_FUNCTION: case ERROR_NOT_SUPPORTED: tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; tagInfo.ReparseTag = 0; break; default: retval = -1; goto cleanup; } } else if (tagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { if (isUnhandledTag) { /* Traversing previously failed for either this link or its target. */ SetLastError(ERROR_CANT_ACCESS_FILE); retval = -1; goto cleanup; } /* Traverse a non-link, but not if traversing already failed for an unhandled tag. */ } else if (!isUnhandledTag) { CloseHandle(hFile); return win32_xstat_slow_impl(path, result, TRUE); } } } if (!GetFileInformationByHandle(hFile, &fileInfo) || !GetFileInformationByHandleEx(hFile, FileBasicInfo, &basicInfo, sizeof(basicInfo))) { switch (GetLastError()) { case ERROR_INVALID_PARAMETER: case ERROR_INVALID_FUNCTION: case ERROR_NOT_SUPPORTED: /* Volumes and physical disks are block devices, e.g. \\.\C: and \\.\PhysicalDrive0. */ memset(result, 0, sizeof(*result)); result->st_mode = 0x6000; /* S_IFBLK */ goto cleanup; } retval = -1; goto cleanup; } /* Successfully got FileBasicInfo, so we'll pass it along */ pBasicInfo = &basicInfo; if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) { /* Successfully got FileIdInfo, so pass it along */ pIdInfo = &idInfo; } } _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result); update_st_mode_from_path(path, fileInfo.dwFileAttributes, result); cleanup: if (hFile != INVALID_HANDLE_VALUE) { /* Preserve last error if we are failing */ error = retval ? GetLastError() : 0; if (!CloseHandle(hFile)) { retval = -1; } else if (retval) { /* Restore last error */ SetLastError(error); } } return retval; } static int win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { FILE_STAT_BASIC_INFORMATION statInfo; if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &statInfo, sizeof(statInfo))) { if (// Cannot use fast path for reparse points ... !(statInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) // ... unless it's a name surrogate (symlink) and we're not following || (!traverse && IsReparseTagNameSurrogate(statInfo.ReparseTag)) ) { _Py_stat_basic_info_to_stat(&statInfo, result); update_st_mode_from_path(path, statInfo.FileAttributes, result); return 0; } } else { switch(GetLastError()) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_NOT_READY: case ERROR_BAD_NET_NAME: /* These errors aren't worth retrying with the slow path */ return -1; case ERROR_NOT_SUPPORTED: /* indicates the API couldn't be loaded */ break; } } return win32_xstat_slow_impl(path, result, traverse); } static int win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { /* Protocol violation: we explicitly clear errno, instead of setting it to a POSIX error. Callers should use GetLastError. */ int code = win32_xstat_impl(path, result, traverse); errno = 0; /* ctime is only deprecated from 3.12, so we copy birthtime across */ result->st_ctime = result->st_birthtime; result->st_ctime_nsec = result->st_birthtime_nsec; return code; } /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w In Posix, stat automatically traverses symlinks and returns the stat structure for the target. In Windows, the equivalent GetFileAttributes by default does not traverse symlinks and instead returns attributes for the symlink. Instead, we will open the file (which *does* traverse symlinks by default) and GetFileInformationByHandle(). */ static int win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) { return win32_xstat(path, result, FALSE); } static int win32_stat(const wchar_t* path, struct _Py_stat_struct *result) { return win32_xstat(path, result, TRUE); } #endif /* MS_WINDOWS */ PyDoc_STRVAR(stat_result__doc__, "stat_result: Result from stat, fstat, or lstat.\n\n\ This object may be accessed either as a tuple of\n\ (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ \n\ Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ or st_flags, they are available as attributes only.\n\ \n\ See os.stat for more information."); static PyStructSequence_Field stat_result_fields[] = …; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE #define ST_BLKSIZE_IDX … #else #define ST_BLKSIZE_IDX … #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS #define ST_BLOCKS_IDX … #else #define ST_BLOCKS_IDX … #endif #ifdef HAVE_STRUCT_STAT_ST_RDEV #define ST_RDEV_IDX … #else #define ST_RDEV_IDX … #endif #ifdef HAVE_STRUCT_STAT_ST_FLAGS #define ST_FLAGS_IDX … #else #define ST_FLAGS_IDX … #endif #ifdef HAVE_STRUCT_STAT_ST_GEN #define ST_GEN_IDX … #else #define ST_GEN_IDX … #endif #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) || defined(MS_WINDOWS) #define ST_BIRTHTIME_IDX … #else #define ST_BIRTHTIME_IDX … #endif #ifdef MS_WINDOWS #define ST_BIRTHTIME_NS_IDX … #else #define ST_BIRTHTIME_NS_IDX … #endif #if defined(HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES) || defined(MS_WINDOWS) #define ST_FILE_ATTRIBUTES_IDX … #else #define ST_FILE_ATTRIBUTES_IDX … #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE #define ST_FSTYPE_IDX … #else #define ST_FSTYPE_IDX … #endif #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG #define ST_REPARSE_TAG_IDX … #else #define ST_REPARSE_TAG_IDX … #endif static PyStructSequence_Desc stat_result_desc = …; PyDoc_STRVAR(statvfs_result__doc__, "statvfs_result: Result from statvfs or fstatvfs.\n\n\ This object may be accessed either as a tuple of\n\ (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ \n\ See os.statvfs for more information."); static PyStructSequence_Field statvfs_result_fields[] = …; static PyStructSequence_Desc statvfs_result_desc = …; #if defined(HAVE_WAITID) PyDoc_STRVAR(waitid_result__doc__, "waitid_result: Result from waitid.\n\n\ This object may be accessed either as a tuple of\n\ (si_pid, si_uid, si_signo, si_status, si_code),\n\ or via the attributes si_pid, si_uid, and so on.\n\ \n\ See os.waitid for more information."); static PyStructSequence_Field waitid_result_fields[] = …; static PyStructSequence_Desc waitid_result_desc = …; #endif static PyObject * statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { … } static int _posix_clear(PyObject *module) { … } static int _posix_traverse(PyObject *module, visitproc visit, void *arg) { … } static void _posix_free(void *module) { … } static int fill_time(PyObject *module, PyObject *v, int s_index, int f_index, int ns_index, time_t sec, unsigned long nsec) { … } #ifdef MS_WINDOWS static PyObject* _pystat_l128_from_l64_l64(uint64_t low, uint64_t high) { PyObject *o_low = PyLong_FromUnsignedLongLong(low); if (!o_low || !high) { return o_low; } PyObject *o_high = PyLong_FromUnsignedLongLong(high); PyObject *l64 = o_high ? PyLong_FromLong(64) : NULL; if (!l64) { Py_XDECREF(o_high); Py_DECREF(o_low); return NULL; } Py_SETREF(o_high, PyNumber_Lshift(o_high, l64)); Py_DECREF(l64); if (!o_high) { Py_DECREF(o_low); return NULL; } Py_SETREF(o_low, PyNumber_Add(o_low, o_high)); Py_DECREF(o_high); return o_low; } #endif /* pack a system stat C structure into the Python stat tuple (used by posix_stat() and posix_fstat()) */ static PyObject* _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) { … } /* POSIX methods */ static PyObject * posix_do_stat(PyObject *module, const char *function_name, path_t *path, int dir_fd, int follow_symlinks) { … } /*[python input] for s in """ FACCESSAT FCHMODAT FCHOWNAT FSTATAT LINKAT MKDIRAT MKFIFOAT MKNODAT OPENAT READLINKAT SYMLINKAT UNLINKAT """.strip().split(): s = s.strip() print(""" #ifdef HAVE_{s} #define {s}_DIR_FD_CONVERTER dir_fd_converter #else #define {s}_DIR_FD_CONVERTER dir_fd_unavailable #endif """.rstrip().format(s=s)) for s in """ FCHDIR FCHMOD FCHOWN FDOPENDIR FEXECVE FPATHCONF FSTATVFS FTRUNCATE """.strip().split(): s = s.strip() print(""" #ifdef HAVE_{s} #define PATH_HAVE_{s} 1 #else #define PATH_HAVE_{s} 0 #endif """.rstrip().format(s=s)) [python start generated code]*/ #ifdef HAVE_FACCESSAT #define FACCESSAT_DIR_FD_CONVERTER … #else #define FACCESSAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_FCHMODAT #define FCHMODAT_DIR_FD_CONVERTER … #else #define FCHMODAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_FCHOWNAT #define FCHOWNAT_DIR_FD_CONVERTER … #else #define FCHOWNAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_FSTATAT #define FSTATAT_DIR_FD_CONVERTER … #else #define FSTATAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_LINKAT #define LINKAT_DIR_FD_CONVERTER … #else #define LINKAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_MKDIRAT #define MKDIRAT_DIR_FD_CONVERTER … #else #define MKDIRAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_MKFIFOAT #define MKFIFOAT_DIR_FD_CONVERTER … #else #define MKFIFOAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_MKNODAT #define MKNODAT_DIR_FD_CONVERTER … #else #define MKNODAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_OPENAT #define OPENAT_DIR_FD_CONVERTER … #else #define OPENAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_READLINKAT #define READLINKAT_DIR_FD_CONVERTER … #else #define READLINKAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_SYMLINKAT #define SYMLINKAT_DIR_FD_CONVERTER … #else #define SYMLINKAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_UNLINKAT #define UNLINKAT_DIR_FD_CONVERTER … #else #define UNLINKAT_DIR_FD_CONVERTER … #endif #ifdef HAVE_FCHDIR #define PATH_HAVE_FCHDIR … #else #define PATH_HAVE_FCHDIR … #endif #ifdef HAVE_FCHMOD #define PATH_HAVE_FCHMOD … #else #define PATH_HAVE_FCHMOD … #endif #ifdef HAVE_FCHOWN #define PATH_HAVE_FCHOWN … #else #define PATH_HAVE_FCHOWN … #endif #ifdef HAVE_FDOPENDIR #define PATH_HAVE_FDOPENDIR … #else #define PATH_HAVE_FDOPENDIR … #endif #ifdef HAVE_FEXECVE #define PATH_HAVE_FEXECVE … #else #define PATH_HAVE_FEXECVE … #endif #ifdef HAVE_FPATHCONF #define PATH_HAVE_FPATHCONF … #else #define PATH_HAVE_FPATHCONF … #endif #ifdef HAVE_FSTATVFS #define PATH_HAVE_FSTATVFS … #else #define PATH_HAVE_FSTATVFS … #endif #ifdef HAVE_FTRUNCATE #define PATH_HAVE_FTRUNCATE … #else #define PATH_HAVE_FTRUNCATE … #endif /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ #ifdef MS_WINDOWS #undef PATH_HAVE_FTRUNCATE #define PATH_HAVE_FTRUNCATE … #undef PATH_HAVE_FCHMOD #define PATH_HAVE_FCHMOD … #endif /*[python input] class path_t_converter(CConverter): type = "path_t" impl_by_reference = True parse_by_reference = True converter = 'path_converter' def converter_init(self, *, allow_fd=False, make_wide=None, nonstrict=False, nullable=False, suppress_value_error=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): fail("Can't specify a default to the path_t converter!") if self.c_default not in (None, 'Py_None'): raise RuntimeError("Can't specify a c_default to the path_t converter!") self.nullable = nullable self.nonstrict = nonstrict self.make_wide = make_wide self.suppress_value_error = suppress_value_error self.allow_fd = allow_fd def pre_render(self): def strify(value): if isinstance(value, str): return value return str(int(bool(value))) # add self.py_name here when merging with posixmodule conversion if self.make_wide is None: self.c_default = 'PATH_T_INITIALIZE_P("{}", "{}", {}, {}, {}, {})'.format( self.function.name, self.name, strify(self.nullable), strify(self.nonstrict), strify(self.suppress_value_error), strify(self.allow_fd), ) else: self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {}, {}, {}, {})'.format( self.function.name, self.name, strify(self.nullable), strify(self.nonstrict), strify(self.make_wide), strify(self.suppress_value_error), strify(self.allow_fd), ) def cleanup(self): return "path_cleanup(&" + self.name + ");\n" class dir_fd_converter(CConverter): type = 'int' def converter_init(self, requires=None): if self.default in (unspecified, None): self.c_default = 'DEFAULT_DIR_FD' if isinstance(requires, str): self.converter = requires.upper() + '_DIR_FD_CONVERTER' else: self.converter = 'dir_fd_converter' class uid_t_converter(CConverter): type = "uid_t" converter = '_Py_Uid_Converter' class gid_t_converter(CConverter): type = "gid_t" converter = '_Py_Gid_Converter' class dev_t_converter(CConverter): type = 'dev_t' converter = '_Py_Dev_Converter' class dev_t_return_converter(unsigned_long_return_converter): type = 'dev_t' conversion_fn = '_PyLong_FromDev' unsigned_cast = '(dev_t)' class FSConverter_converter(CConverter): type = 'PyObject *' converter = 'PyUnicode_FSConverter' def converter_init(self): if self.default is not unspecified: fail("FSConverter_converter does not support default values") self.c_default = 'NULL' def cleanup(self): return "Py_XDECREF(" + self.name + ");\n" class pid_t_converter(CConverter): type = 'pid_t' format_unit = '" _Py_PARSE_PID "' def parse_arg(self, argname, displayname, *, limited_capi): return self.format_code(""" {paramname} = PyLong_AsPid({argname}); if ({paramname} == (pid_t)(-1) && PyErr_Occurred()) {{{{ goto exit; }}}} """, argname=argname) class idtype_t_converter(CConverter): type = 'idtype_t' converter = 'idtype_t_converter' class id_t_converter(CConverter): type = 'id_t' format_unit = '" _Py_PARSE_PID "' def parse_arg(self, argname, displayname, *, limited_capi): return self.format_code(""" {paramname} = (id_t)PyLong_AsPid({argname}); if ({paramname} == (id_t)(-1) && PyErr_Occurred()) {{{{ goto exit; }}}} """, argname=argname) class intptr_t_converter(CConverter): type = 'intptr_t' format_unit = '" _Py_PARSE_INTPTR "' def parse_arg(self, argname, displayname, *, limited_capi): return self.format_code(""" {paramname} = (intptr_t)PyLong_AsVoidPtr({argname}); if (!{paramname} && PyErr_Occurred()) {{{{ goto exit; }}}} """, argname=argname) class Py_off_t_converter(CConverter): type = 'Py_off_t' converter = 'Py_off_t_converter' class Py_off_t_return_converter(long_return_converter): type = 'Py_off_t' conversion_fn = 'PyLong_FromPy_off_t' class confname_converter(CConverter): type="int" converter="conv_confname" def converter_init(self, *, table): self.table = table def parse_arg(self, argname, displayname, *, limited_capi): return self.format_code(""" if (!{converter}(module, {argname}, &{paramname}, "{table}")) {{{{ goto exit; }}}} """, argname=argname, converter=self.converter, table=self.table) [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=8189d5ae78244626]*/ /*[clinic input] os.stat path : path_t(allow_fd=True) Path to be examined; can be string, bytes, a path-like object or open-file-descriptor int. * dir_fd : dir_fd(requires='fstatat') = None If not None, it should be a file descriptor open to a directory, and path should be a relative string; path will then be relative to that directory. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, stat will examine the symbolic link itself instead of the file the link points to. Perform a stat system call on the given path. dir_fd and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. It's an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. [clinic start generated code]*/ static PyObject * os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/ { … } /*[clinic input] os.lstat path : path_t * dir_fd : dir_fd(requires='fstatat') = None Perform a stat system call on the given path, without following symbolic links. Like stat(), but do not follow symbolic links. Equivalent to stat(path, follow_symlinks=False). [clinic start generated code]*/ static PyObject * os_lstat_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/ { … } /*[clinic input] os.access -> bool path: path_t Path to be tested; can be string, bytes, or a path-like object. mode: int Operating-system mode bitfield. Can be F_OK to test existence, or the inclusive-OR of R_OK, W_OK, and X_OK. * dir_fd : dir_fd(requires='faccessat') = None If not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. effective_ids: bool = False If True, access will use the effective uid/gid instead of the real uid/gid. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, access will examine the symbolic link itself instead of the file the link points to. Use the real uid/gid to test for access to a path. {parameters} dir_fd, effective_ids, and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. Note that most operations will use the effective uid/gid, therefore this routine can be used in a suid/sgid environment to test if the invoking user has the specified access to the path. [clinic start generated code]*/ static int os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks) /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/ { … } #ifndef F_OK #define F_OK … #endif #ifndef R_OK #define R_OK … #endif #ifndef W_OK #define W_OK … #endif #ifndef X_OK #define X_OK … #endif #ifdef HAVE_TTYNAME /*[clinic input] os.ttyname fd: int Integer file descriptor handle. / Return the name of the terminal device connected to 'fd'. [clinic start generated code]*/ static PyObject * os_ttyname_impl(PyObject *module, int fd) /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ { … } #endif #ifdef HAVE_CTERMID /*[clinic input] os.ctermid Return the name of the controlling terminal for this process. [clinic start generated code]*/ static PyObject * os_ctermid_impl(PyObject *module) /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/ { … } #endif /* HAVE_CTERMID */ /*[clinic input] os.chdir path: path_t(allow_fd='PATH_HAVE_FCHDIR') Change the current working directory to the specified path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_chdir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ { … } #ifdef HAVE_FCHDIR /*[clinic input] os.fchdir fd: fildes Change to the directory of the given file descriptor. fd must be opened on a directory, not a file. Equivalent to os.chdir(fd). [clinic start generated code]*/ static PyObject * os_fchdir_impl(PyObject *module, int fd) /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/ { … } #endif /* HAVE_FCHDIR */ #ifdef MS_WINDOWS #define CHMOD_DEFAULT_FOLLOW_SYMLINKS … #else #define CHMOD_DEFAULT_FOLLOW_SYMLINKS … #endif #ifdef MS_WINDOWS static int win32_lchmod(LPCWSTR path, int mode) { DWORD attr = GetFileAttributesW(path); if (attr == INVALID_FILE_ATTRIBUTES) { return 0; } if (mode & _S_IWRITE) { attr &= ~FILE_ATTRIBUTE_READONLY; } else { attr |= FILE_ATTRIBUTE_READONLY; } return SetFileAttributesW(path, attr); } static int win32_hchmod(HANDLE hfile, int mode) { FILE_BASIC_INFO info; if (!GetFileInformationByHandleEx(hfile, FileBasicInfo, &info, sizeof(info))) { return 0; } if (mode & _S_IWRITE) { info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; } else { info.FileAttributes |= FILE_ATTRIBUTE_READONLY; } return SetFileInformationByHandle(hfile, FileBasicInfo, &info, sizeof(info)); } static int win32_fchmod(int fd, int mode) { HANDLE hfile = _Py_get_osfhandle_noraise(fd); if (hfile == INVALID_HANDLE_VALUE) { SetLastError(ERROR_INVALID_HANDLE); return 0; } return win32_hchmod(hfile, mode); } #endif /* MS_WINDOWS */ /*[clinic input] os.chmod path: path_t(allow_fd='PATH_HAVE_FCHMOD') Path to be modified. May always be specified as a str, bytes, or a path-like object. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. mode: int Operating-system mode bitfield. Be careful when using number literals for *mode*. The conventional UNIX notation for numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in Python. * dir_fd : dir_fd(requires='fchmodat') = None If not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. follow_symlinks: bool(c_default="CHMOD_DEFAULT_FOLLOW_SYMLINKS", \ py_default="(os.name != 'nt')") = CHMOD_DEFAULT_FOLLOW_SYMLINKS If False, and the last element of the path is a symbolic link, chmod will modify the symbolic link itself instead of the file the link points to. Change the access permissions of a file. It is an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. dir_fd and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=5cf6a94915cc7bff input=fcf115d174b9f3d8]*/ { … } #if defined(HAVE_FCHMOD) || defined(MS_WINDOWS) /*[clinic input] os.fchmod fd: int The file descriptor of the file to be modified. mode: int Operating-system mode bitfield. Be careful when using number literals for *mode*. The conventional UNIX notation for numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in Python. Change the access permissions of the file given by file descriptor fd. Equivalent to os.chmod(fd, mode). [clinic start generated code]*/ static PyObject * os_fchmod_impl(PyObject *module, int fd, int mode) /*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/ { … } #endif /* HAVE_FCHMOD || MS_WINDOWS */ #if defined(HAVE_LCHMOD) || defined(MS_WINDOWS) /*[clinic input] os.lchmod path: path_t mode: int Change the access permissions of a file, without following symbolic links. If path is a symlink, this affects the link itself rather than the target. Equivalent to chmod(path, mode, follow_symlinks=False)." [clinic start generated code]*/ static PyObject * os_lchmod_impl(PyObject *module, path_t *path, int mode) /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/ { int res; if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { return NULL; } #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS res = win32_lchmod(path->wide, mode); Py_END_ALLOW_THREADS if (!res) { path_error(path); return NULL; } #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS res = lchmod(path->narrow, mode); Py_END_ALLOW_THREADS if (res < 0) { path_error(path); return NULL; } #endif /* MS_WINDOWS */ Py_RETURN_NONE; } #endif /* HAVE_LCHMOD || MS_WINDOWS */ #ifdef HAVE_CHFLAGS /*[clinic input] os.chflags path: path_t flags: unsigned_long(bitwise=True) follow_symlinks: bool=True Set file flags. If follow_symlinks is False, and the last element of the path is a symbolic link, chflags will change flags on the symbolic link itself instead of the file the link points to. follow_symlinks may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, int follow_symlinks) /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/ { int result; #ifndef HAVE_LCHFLAGS if (follow_symlinks_specified("chflags", follow_symlinks)) return NULL; #endif if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef HAVE_LCHFLAGS if (!follow_symlinks) result = lchflags(path->narrow, flags); else #endif result = chflags(path->narrow, flags); Py_END_ALLOW_THREADS if (result) return path_error(path); Py_RETURN_NONE; } #endif /* HAVE_CHFLAGS */ #ifdef HAVE_LCHFLAGS /*[clinic input] os.lchflags path: path_t flags: unsigned_long(bitwise=True) Set file flags. This function will not follow symbolic links. Equivalent to chflags(path, flags, follow_symlinks=False). [clinic start generated code]*/ static PyObject * os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags) /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/ { int res; if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS res = lchflags(path->narrow, flags); Py_END_ALLOW_THREADS if (res < 0) { return path_error(path); } Py_RETURN_NONE; } #endif /* HAVE_LCHFLAGS */ #ifdef HAVE_CHROOT /*[clinic input] os.chroot path: path_t Change root directory to path. [clinic start generated code]*/ static PyObject * os_chroot_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/ { … } #endif /* HAVE_CHROOT */ #ifdef HAVE_FSYNC /*[clinic input] os.fsync fd: fildes Force write of fd to disk. [clinic start generated code]*/ static PyObject * os_fsync_impl(PyObject *module, int fd) /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/ { … } #endif /* HAVE_FSYNC */ #ifdef HAVE_SYNC /*[clinic input] os.sync Force write of everything to disk. [clinic start generated code]*/ static PyObject * os_sync_impl(PyObject *module) /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/ { … } #endif /* HAVE_SYNC */ #ifdef HAVE_FDATASYNC #ifdef __hpux extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ #endif /*[clinic input] os.fdatasync fd: fildes Force write of fd to disk without forcing update of metadata. [clinic start generated code]*/ static PyObject * os_fdatasync_impl(PyObject *module, int fd) /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/ { … } #endif /* HAVE_FDATASYNC */ #ifdef HAVE_CHOWN /*[clinic input] os.chown path : path_t(allow_fd='PATH_HAVE_FCHOWN') Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int. uid: uid_t gid: gid_t * dir_fd : dir_fd(requires='fchownat') = None If not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, stat will examine the symbolic link itself instead of the file the link points to. Change the owner and group id of path to the numeric uid and gid.\ path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. If follow_symlinks is False, and the last element of the path is a symbolic link, chown will modify the symbolic link itself instead of the file the link points to. It is an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. dir_fd and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/ { … } #endif /* HAVE_CHOWN */ #ifdef HAVE_FCHOWN /*[clinic input] os.fchown fd: int uid: uid_t gid: gid_t Change the owner and group id of the file specified by file descriptor. Equivalent to os.chown(fd, uid, gid). [clinic start generated code]*/ static PyObject * os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid) /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/ { … } #endif /* HAVE_FCHOWN */ #ifdef HAVE_LCHOWN /*[clinic input] os.lchown path : path_t uid: uid_t gid: gid_t Change the owner and group id of path to the numeric uid and gid. This function will not follow symbolic links. Equivalent to os.chown(path, uid, gid, follow_symlinks=False). [clinic start generated code]*/ static PyObject * os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid) /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/ { … } #endif /* HAVE_LCHOWN */ static PyObject * posix_getcwd(int use_bytes) { … } /*[clinic input] os.getcwd Return a unicode string representing the current working directory. [clinic start generated code]*/ static PyObject * os_getcwd_impl(PyObject *module) /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/ { … } /*[clinic input] os.getcwdb Return a bytes string representing the current working directory. [clinic start generated code]*/ static PyObject * os_getcwdb_impl(PyObject *module) /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/ { … } #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) #define HAVE_LINK … #endif #ifdef HAVE_LINK /*[clinic input] os.link src : path_t dst : path_t * src_dir_fd : dir_fd = None dst_dir_fd : dir_fd = None follow_symlinks: bool = True Create a hard link to a file. If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. If follow_symlinks is False, and the last element of src is a symbolic link, link will create a link to the symbolic link itself instead of the file the link points to. src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks) /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ { … } #endif #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) static PyObject * _listdir_windows_no_opendir(path_t *path, PyObject *list) { PyObject *v; HANDLE hFindFile = INVALID_HANDLE_VALUE; BOOL result, return_bytes; wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ /* only claim to have space for MAX_PATH */ Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; wchar_t *wnamebuf = NULL; WIN32_FIND_DATAW wFileData; const wchar_t *po_wchars; if (!path->wide) { /* Default arg: "." */ po_wchars = L"."; len = 1; return_bytes = 0; } else { po_wchars = path->wide; len = wcslen(path->wide); return_bytes = PyBytes_Check(path->object); } /* The +5 is so we can append "\\*.*\0" */ wnamebuf = PyMem_New(wchar_t, len + 5); if (!wnamebuf) { PyErr_NoMemory(); goto exit; } wcscpy(wnamebuf, po_wchars); if (len > 0) { wchar_t wch = wnamebuf[len-1]; if (wch != SEP && wch != ALTSEP && wch != L':') wnamebuf[len++] = SEP; wcscpy(wnamebuf + len, L"*.*"); } if ((list = PyList_New(0)) == NULL) { goto exit; } Py_BEGIN_ALLOW_THREADS hFindFile = FindFirstFileW(wnamebuf, &wFileData); Py_END_ALLOW_THREADS if (hFindFile == INVALID_HANDLE_VALUE) { int error = GetLastError(); if (error == ERROR_FILE_NOT_FOUND) goto exit; path_error(path); Py_CLEAR(list); goto exit; } do { /* Skip over . and .. */ if (wcscmp(wFileData.cFileName, L".") != 0 && wcscmp(wFileData.cFileName, L"..") != 0) { v = PyUnicode_FromWideChar(wFileData.cFileName, wcslen(wFileData.cFileName)); if (return_bytes && v) { Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); } if (v == NULL) { Py_CLEAR(list); break; } if (PyList_Append(list, v) != 0) { Py_DECREF(v); Py_CLEAR(list); break; } Py_DECREF(v); } Py_BEGIN_ALLOW_THREADS result = FindNextFileW(hFindFile, &wFileData); Py_END_ALLOW_THREADS /* FindNextFile sets error to ERROR_NO_MORE_FILES if it got to the end of the directory. */ if (!result && GetLastError() != ERROR_NO_MORE_FILES) { path_error(path); Py_CLEAR(list); goto exit; } } while (result == TRUE); exit: if (hFindFile != INVALID_HANDLE_VALUE) { if (FindClose(hFindFile) == FALSE) { if (list != NULL) { path_error(path); Py_CLEAR(list); } } } PyMem_Free(wnamebuf); return list; } /* end of _listdir_windows_no_opendir */ #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ static PyObject * _posix_listdir(path_t *path, PyObject *list) { … } /* end of _posix_listdir */ #endif /* which OS */ /*[clinic input] os.listdir path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None Return a list containing the names of the files in the directory. path can be specified as either str, bytes, or a path-like object. If path is bytes, the filenames returned will also be bytes; in all other circumstances the filenames returned will be str. If path is None, uses the path='.'. On some platforms, path may also be specified as an open file descriptor;\ the file descriptor must refer to a directory. If this functionality is unavailable, using it raises NotImplementedError. The list is in arbitrary order. It does not include the special entries '.' and '..' even if they are present in the directory. [clinic start generated code]*/ static PyObject * os_listdir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/ { … } #ifdef MS_WINDOWS /*[clinic input] os.listdrives Return a list containing the names of drives in the system. A drive name typically looks like 'C:\\'. [clinic start generated code]*/ static PyObject * os_listdrives_impl(PyObject *module) /*[clinic end generated code: output=aaece9dacdf682b5 input=1af9ccc9e583798e]*/ { /* Number of possible drives is limited, so 256 should always be enough. On the day when it is not, listmounts() will have to be used. */ wchar_t buffer[256]; DWORD buflen = Py_ARRAY_LENGTH(buffer); PyObject *result = NULL; if (PySys_Audit("os.listdrives", NULL) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS; buflen = GetLogicalDriveStringsW(buflen, buffer); Py_END_ALLOW_THREADS; if (!buflen) { PyErr_SetFromWindowsErr(0); return NULL; } else if (buflen >= Py_ARRAY_LENGTH(buffer)) { PyErr_SetFromWindowsErr(ERROR_MORE_DATA); return NULL; } /* buflen includes a null terminator, so remove it */ PyObject *str = PyUnicode_FromWideChar(buffer, buflen - 1); if (str) { PyObject *nullchar = PyUnicode_FromStringAndSize("\0", 1); if (nullchar) { result = PyUnicode_Split(str, nullchar, -1); Py_DECREF(nullchar); } Py_DECREF(str); } return result; } /*[clinic input] os.listvolumes Return a list containing the volumes in the system. Volumes are typically represented as a GUID path. [clinic start generated code]*/ static PyObject * os_listvolumes_impl(PyObject *module) /*[clinic end generated code: output=534e10ea2bf9d386 input=f6e4e70371f11e99]*/ { PyObject *result = PyList_New(0); HANDLE find = INVALID_HANDLE_VALUE; wchar_t buffer[MAX_PATH + 1]; if (!result) { return NULL; } if (PySys_Audit("os.listvolumes", NULL) < 0) { Py_DECREF(result); return NULL; } int err = 0; Py_BEGIN_ALLOW_THREADS; find = FindFirstVolumeW(buffer, Py_ARRAY_LENGTH(buffer)); if (find == INVALID_HANDLE_VALUE) { err = GetLastError(); } Py_END_ALLOW_THREADS; while (!err) { PyObject *s = PyUnicode_FromWideChar(buffer, -1); if (!s || PyList_Append(result, s) < 0) { Py_XDECREF(s); Py_CLEAR(result); break; } Py_DECREF(s); Py_BEGIN_ALLOW_THREADS; if (!FindNextVolumeW(find, buffer, Py_ARRAY_LENGTH(buffer))) { err = GetLastError(); } Py_END_ALLOW_THREADS; } if (find != INVALID_HANDLE_VALUE) { Py_BEGIN_ALLOW_THREADS; FindVolumeClose(find); Py_END_ALLOW_THREADS; } if (err && err != ERROR_NO_MORE_FILES) { PyErr_SetFromWindowsErr(err); Py_XDECREF(result); result = NULL; } return result; } /*[clinic input] os.listmounts volume: path_t Return a list containing mount points for a particular volume. 'volume' should be a GUID path as returned from os.listvolumes. [clinic start generated code]*/ static PyObject * os_listmounts_impl(PyObject *module, path_t *volume) /*[clinic end generated code: output=06da49679de4512e input=a8a27178e3f67845]*/ { wchar_t default_buffer[MAX_PATH + 1]; DWORD buflen = Py_ARRAY_LENGTH(default_buffer); LPWSTR buffer = default_buffer; DWORD attributes; PyObject *str = NULL; PyObject *nullchar = NULL; PyObject *result = NULL; /* Ensure we have a valid volume path before continuing */ Py_BEGIN_ALLOW_THREADS attributes = GetFileAttributesW(volume->wide); Py_END_ALLOW_THREADS if (attributes == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_UNRECOGNIZED_VOLUME) { return PyErr_SetFromWindowsErr(ERROR_UNRECOGNIZED_VOLUME); } if (PySys_Audit("os.listmounts", "O", volume->object) < 0) { return NULL; } while (1) { BOOL success; Py_BEGIN_ALLOW_THREADS success = GetVolumePathNamesForVolumeNameW(volume->wide, buffer, buflen, &buflen); Py_END_ALLOW_THREADS if (success) { break; } if (GetLastError() != ERROR_MORE_DATA) { PyErr_SetFromWindowsErr(0); goto exit; } if (buffer != default_buffer) { PyMem_Free((void *)buffer); } buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * buflen); if (!buffer) { PyErr_NoMemory(); goto exit; } } if (buflen < 2) { result = PyList_New(0); goto exit; } // buflen includes two null terminators, one for the last string // and one for the array of strings. str = PyUnicode_FromWideChar(buffer, buflen - 2); nullchar = PyUnicode_FromStringAndSize("\0", 1); if (str && nullchar) { result = PyUnicode_Split(str, nullchar, -1); } exit: if (buffer != default_buffer) { PyMem_Free(buffer); } Py_XDECREF(nullchar); Py_XDECREF(str); return result; } /*[clinic input] os._path_isdevdrive path: path_t Determines whether the specified path is on a Windows Dev Drive. [clinic start generated code]*/ static PyObject * os__path_isdevdrive_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=1f437ea6677433a2 input=ee83e4996a48e23d]*/ { #ifndef PERSISTENT_VOLUME_STATE_DEV_VOLUME /* This flag will be documented at https://learn.microsoft.com/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_fs_persistent_volume_information after release, and will be available in the latest WinSDK. We include the flag to avoid a specific version dependency on the latest WinSDK. */ const int PERSISTENT_VOLUME_STATE_DEV_VOLUME = 0x00002000; #endif int err = 0; PyObject *r = NULL; wchar_t volume[MAX_PATH]; Py_BEGIN_ALLOW_THREADS if (!GetVolumePathNameW(path->wide, volume, MAX_PATH)) { /* invalid path of some kind */ /* Note that this also includes the case where a volume is mounted in a path longer than 260 characters. This is likely to be rare and problematic for other reasons, so a (soft) failure in this check seems okay. */ err = GetLastError(); } else if (GetDriveTypeW(volume) != DRIVE_FIXED) { /* only care about local dev drives */ r = Py_False; } else { HANDLE hVolume = CreateFileW( volume, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if (hVolume == INVALID_HANDLE_VALUE) { err = GetLastError(); } else { FILE_FS_PERSISTENT_VOLUME_INFORMATION volumeState = {0}; volumeState.Version = 1; volumeState.FlagMask = PERSISTENT_VOLUME_STATE_DEV_VOLUME; if (!DeviceIoControl( hVolume, FSCTL_QUERY_PERSISTENT_VOLUME_STATE, &volumeState, sizeof(volumeState), &volumeState, sizeof(volumeState), NULL, NULL )) { err = GetLastError(); } CloseHandle(hVolume); if (err == ERROR_INVALID_PARAMETER) { /* not supported on this platform */ r = Py_False; } else if (!err) { r = (volumeState.VolumeFlags & PERSISTENT_VOLUME_STATE_DEV_VOLUME) ? Py_True : Py_False; } } } Py_END_ALLOW_THREADS if (err) { PyErr_SetFromWindowsErr(err); return NULL; } if (r) { return Py_NewRef(r); } return NULL; } int _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p) { wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; DWORD result; result = GetFullPathNameW(path, Py_ARRAY_LENGTH(woutbuf), woutbuf, NULL); if (!result) { return -1; } if (result >= Py_ARRAY_LENGTH(woutbuf)) { if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); } else { woutbufp = NULL; } if (!woutbufp) { *abspath_p = NULL; return 0; } result = GetFullPathNameW(path, result, woutbufp, NULL); if (!result) { PyMem_RawFree(woutbufp); return -1; } } if (woutbufp != woutbuf) { *abspath_p = woutbufp; return 0; } *abspath_p = _PyMem_RawWcsdup(woutbufp); return 0; } /* A helper function for abspath on win32 */ /*[clinic input] os._getfullpathname path: path_t / [clinic start generated code]*/ static PyObject * os__getfullpathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ { wchar_t *abspath; if (_PyOS_getfullpathname(path->wide, &abspath) < 0) { return win32_error_object("GetFullPathNameW", path->object); } if (abspath == NULL) { return PyErr_NoMemory(); } PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath)); PyMem_RawFree(abspath); if (str == NULL) { return NULL; } if (PyBytes_Check(path->object)) { Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); } return str; } /*[clinic input] os._getfinalpathname path: path_t / A helper function for samepath on windows. [clinic start generated code]*/ static PyObject * os__getfinalpathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ { HANDLE hFile; wchar_t buf[MAXPATHLEN], *target_path = buf; int buf_size = Py_ARRAY_LENGTH(buf); int result_length; PyObject *result; Py_BEGIN_ALLOW_THREADS hFile = CreateFileW( path->wide, 0, /* desired access */ 0, /* share mode */ NULL, /* security attributes */ OPEN_EXISTING, /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ FILE_FLAG_BACKUP_SEMANTICS, NULL); Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) { return win32_error_object("CreateFileW", path->object); } /* We have a good handle to the target, use it to determine the target path name. */ while (1) { Py_BEGIN_ALLOW_THREADS result_length = GetFinalPathNameByHandleW(hFile, target_path, buf_size, VOLUME_NAME_DOS); Py_END_ALLOW_THREADS if (!result_length) { result = win32_error_object("GetFinalPathNameByHandleW", path->object); goto cleanup; } if (result_length < buf_size) { break; } wchar_t *tmp; tmp = PyMem_Realloc(target_path != buf ? target_path : NULL, result_length * sizeof(*tmp)); if (!tmp) { result = PyErr_NoMemory(); goto cleanup; } buf_size = result_length; target_path = tmp; } result = PyUnicode_FromWideChar(target_path, result_length); if (result && PyBytes_Check(path->object)) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } cleanup: if (target_path != buf) { PyMem_Free(target_path); } CloseHandle(hFile); return result; } /*[clinic input] os._findfirstfile path: path_t / A function to get the real file name without accessing the file in Windows. [clinic start generated code]*/ static PyObject * os__findfirstfile_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=106dd3f0779c83dd input=0734dff70f60e1a8]*/ { PyObject *result; HANDLE hFindFile; WIN32_FIND_DATAW wFileData; WCHAR *wRealFileName; Py_BEGIN_ALLOW_THREADS hFindFile = FindFirstFileW(path->wide, &wFileData); Py_END_ALLOW_THREADS if (hFindFile == INVALID_HANDLE_VALUE) { path_error(path); return NULL; } wRealFileName = wFileData.cFileName; result = PyUnicode_FromWideChar(wRealFileName, wcslen(wRealFileName)); FindClose(hFindFile); return result; } /*[clinic input] os._getvolumepathname path: path_t A helper function for ismount on Win32. [clinic start generated code]*/ static PyObject * os__getvolumepathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ { PyObject *result; wchar_t *mountpath=NULL; size_t buflen; BOOL ret; /* Volume path should be shorter than entire path */ buflen = Py_MAX(path->length, MAX_PATH); if (buflen > PY_DWORD_MAX) { PyErr_SetString(PyExc_OverflowError, "path too long"); return NULL; } mountpath = PyMem_New(wchar_t, buflen); if (mountpath == NULL) return PyErr_NoMemory(); Py_BEGIN_ALLOW_THREADS ret = GetVolumePathNameW(path->wide, mountpath, Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); Py_END_ALLOW_THREADS if (!ret) { result = win32_error_object("_getvolumepathname", path->object); goto exit; } result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); if (PyBytes_Check(path->object)) Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); exit: PyMem_Free(mountpath); return result; } /*[clinic input] os._path_splitroot path: path_t Removes everything after the root on Win32. [clinic start generated code]*/ static PyObject * os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/ { wchar_t *buffer; wchar_t *end; PyObject *result = NULL; HRESULT ret; buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); if (!buffer) { return NULL; } wcscpy(buffer, path->wide); for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { *p = L'\\'; } Py_BEGIN_ALLOW_THREADS ret = PathCchSkipRoot(buffer, &end); Py_END_ALLOW_THREADS if (FAILED(ret)) { result = Py_BuildValue("sO", "", path->object); } else if (end != buffer) { size_t rootLen = (size_t)(end - buffer); result = Py_BuildValue("NN", PyUnicode_FromWideChar(path->wide, rootLen), PyUnicode_FromWideChar(path->wide + rootLen, -1) ); } else { result = Py_BuildValue("Os", path->object, ""); } PyMem_Free(buffer); return result; } #define PY_IFREG … #define PY_IFDIR … #define PY_IFLNK … #define PY_IFMNT … #define PY_IFLRP … #define PY_IFRRP … static inline BOOL _testInfo(DWORD attributes, DWORD reparseTag, BOOL diskDevice, int testedType) { switch (testedType) { case PY_IFREG: return diskDevice && attributes && !(attributes & FILE_ATTRIBUTE_DIRECTORY); case PY_IFDIR: return attributes & FILE_ATTRIBUTE_DIRECTORY; case PY_IFLNK: return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) && reparseTag == IO_REPARSE_TAG_SYMLINK; case PY_IFMNT: return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) && reparseTag == IO_REPARSE_TAG_MOUNT_POINT; case PY_IFLRP: return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) && IsReparseTagNameSurrogate(reparseTag); case PY_IFRRP: return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) && reparseTag && !IsReparseTagNameSurrogate(reparseTag); } return FALSE; } static BOOL _testFileTypeByHandle(HANDLE hfile, int testedType, BOOL diskOnly) { assert(testedType == PY_IFREG || testedType == PY_IFDIR || testedType == PY_IFLNK || testedType == PY_IFMNT || testedType == PY_IFLRP || testedType == PY_IFRRP); BOOL diskDevice = GetFileType(hfile) == FILE_TYPE_DISK; if (diskOnly && !diskDevice) { return FALSE; } if (testedType != PY_IFREG && testedType != PY_IFDIR) { FILE_ATTRIBUTE_TAG_INFO info; return GetFileInformationByHandleEx(hfile, FileAttributeTagInfo, &info, sizeof(info)) && _testInfo(info.FileAttributes, info.ReparseTag, diskDevice, testedType); } FILE_BASIC_INFO info; return GetFileInformationByHandleEx(hfile, FileBasicInfo, &info, sizeof(info)) && _testInfo(info.FileAttributes, 0, diskDevice, testedType); } static BOOL _testFileTypeByName(LPCWSTR path, int testedType) { assert(testedType == PY_IFREG || testedType == PY_IFDIR || testedType == PY_IFLNK || testedType == PY_IFMNT || testedType == PY_IFLRP || testedType == PY_IFRRP); FILE_STAT_BASIC_INFORMATION info; if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info, sizeof(info))) { BOOL diskDevice = info.DeviceType == FILE_DEVICE_DISK || info.DeviceType == FILE_DEVICE_VIRTUAL_DISK || info.DeviceType == FILE_DEVICE_CD_ROM; BOOL result = _testInfo(info.FileAttributes, info.ReparseTag, diskDevice, testedType); if (!result || (testedType != PY_IFREG && testedType != PY_IFDIR) || !(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { return result; } } else if (_Py_GetFileInformationByName_ErrorIsTrustworthy( GetLastError())) { return FALSE; } DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; if (testedType != PY_IFREG && testedType != PY_IFDIR) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, flags, NULL); if (hfile != INVALID_HANDLE_VALUE) { BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE); CloseHandle(hfile); return result; } switch (GetLastError()) { case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: int rc; STRUCT_STAT st; if (testedType == PY_IFREG || testedType == PY_IFDIR) { rc = STAT(path, &st); } else { // PY_IFRRP is not generally supported in this case, except for // unhandled reparse points such as IO_REPARSE_TAG_APPEXECLINK. rc = LSTAT(path, &st); } if (!rc) { return _testInfo(st.st_file_attributes, st.st_reparse_tag, st.st_mode & S_IFREG, testedType); } } return FALSE; } static BOOL _testFileExistsByName(LPCWSTR path, BOOL followLinks) { FILE_STAT_BASIC_INFORMATION info; if (_Py_GetFileInformationByName(path, FileStatBasicByNameInfo, &info, sizeof(info))) { if (!(info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) || !followLinks && IsReparseTagNameSurrogate(info.ReparseTag)) { return TRUE; } } else if (_Py_GetFileInformationByName_ErrorIsTrustworthy( GetLastError())) { return FALSE; } DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; if (!followLinks) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, flags, NULL); if (hfile != INVALID_HANDLE_VALUE) { if (followLinks) { CloseHandle(hfile); return TRUE; } // Regular Reparse Points (PY_IFRRP) have to be traversed. BOOL result = _testFileTypeByHandle(hfile, PY_IFRRP, FALSE); CloseHandle(hfile); if (!result) { return TRUE; } hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hfile != INVALID_HANDLE_VALUE) { CloseHandle(hfile); return TRUE; } } switch (GetLastError()) { case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: case ERROR_CANT_ACCESS_FILE: case ERROR_INVALID_PARAMETER: STRUCT_STAT _st; return followLinks ? !STAT(path, &_st): !LSTAT(path, &_st); } return FALSE; } static BOOL _testFileExists(path_t *path, BOOL followLinks) { BOOL result = FALSE; if (path->value_error) { return FALSE; } Py_BEGIN_ALLOW_THREADS if (path->fd != -1) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { if (GetFileType(hfile) != FILE_TYPE_UNKNOWN || !GetLastError()) { result = TRUE; } } } else if (path->wide) { result = _testFileExistsByName(path->wide, followLinks); } Py_END_ALLOW_THREADS return result; } static BOOL _testFileType(path_t *path, int testedType) { BOOL result = FALSE; if (path->value_error) { return FALSE; } Py_BEGIN_ALLOW_THREADS if (path->fd != -1) { HANDLE hfile = _Py_get_osfhandle_noraise(path->fd); if (hfile != INVALID_HANDLE_VALUE) { result = _testFileTypeByHandle(hfile, testedType, TRUE); } } else if (path->wide) { result = _testFileTypeByName(path->wide, testedType); } Py_END_ALLOW_THREADS return result; } /*[clinic input] os._path_exists -> bool path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path exists. Returns False for broken symbolic links. [clinic start generated code]*/ static int os__path_exists_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=8da13acf666e16ba input=142beabfc66783eb]*/ { return _testFileExists(path, TRUE); } /*[clinic input] os._path_lexists -> bool path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path exists. Returns True for broken symbolic links. [clinic start generated code]*/ static int os__path_lexists_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=e7240ed5fc45bff3 input=208205112a3cc1ed]*/ { return _testFileExists(path, FALSE); } /*[clinic input] os._path_isdir -> bool s as path: path_t(allow_fd=True, suppress_value_error=True) Return true if the pathname refers to an existing directory. [clinic start generated code]*/ static int os__path_isdir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=d5786196f9e2fa7a input=132a3b5301aecf79]*/ { return _testFileType(path, PY_IFDIR); } /*[clinic input] os._path_isfile -> bool path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path is a regular file [clinic start generated code]*/ static int os__path_isfile_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=5c3073bc212b9863 input=4ac1fd350b30a39e]*/ { return _testFileType(path, PY_IFREG); } /*[clinic input] os._path_islink -> bool path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path is a symbolic link [clinic start generated code]*/ static int os__path_islink_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=30da7bda8296adcc input=7510ce05b547debb]*/ { return _testFileType(path, PY_IFLNK); } /*[clinic input] os._path_isjunction -> bool path: path_t(allow_fd=True, suppress_value_error=True) Test whether a path is a junction [clinic start generated code]*/ static int os__path_isjunction_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=e1d17a9dd18a9945 input=7dcb8bc4e972fcaf]*/ { return _testFileType(path, PY_IFMNT); } #undef PY_IFREG #undef PY_IFDIR #undef PY_IFLNK #undef PY_IFMNT #undef PY_IFLRP #undef PY_IFRRP #endif /* MS_WINDOWS */ /*[clinic input] os._path_splitroot_ex p as path: path_t(make_wide=True, nonstrict=True) Split a pathname into drive, root and tail. The tail contains anything after the root. [clinic start generated code]*/ static PyObject * os__path_splitroot_ex_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=4b0072b6cdf4b611 input=4556b615c7cc13f2]*/ { … } /*[clinic input] os._path_normpath path: path_t(make_wide=True, nonstrict=True) Normalize path, eliminating double slashes, etc. [clinic start generated code]*/ static PyObject * os__path_normpath_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=d353e7ed9410c044 input=3d4ac23b06332dcb]*/ { … } /*[clinic input] os.mkdir path : path_t mode: int = 0o777 * dir_fd : dir_fd(requires='mkdirat') = None # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ Create a directory. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. The mode argument is ignored on Windows. Where it is used, the current umask value is first masked out. [clinic start generated code]*/ static PyObject * os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ { … } /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ #if defined(HAVE_SYS_RESOURCE_H) #include <sys/resource.h> #endif #ifdef HAVE_NICE /*[clinic input] os.nice increment: int / Add increment to the priority of process and return the new priority. [clinic start generated code]*/ static PyObject * os_nice_impl(PyObject *module, int increment) /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/ { … } #endif /* HAVE_NICE */ #ifdef HAVE_GETPRIORITY /*[clinic input] os.getpriority which: int who: int Return program scheduling priority. [clinic start generated code]*/ static PyObject * os_getpriority_impl(PyObject *module, int which, int who) /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/ { … } #endif /* HAVE_GETPRIORITY */ #ifdef HAVE_SETPRIORITY /*[clinic input] os.setpriority which: int who: int priority: int Set program scheduling priority. [clinic start generated code]*/ static PyObject * os_setpriority_impl(PyObject *module, int which, int who, int priority) /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/ { … } #endif /* HAVE_SETPRIORITY */ static PyObject * internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) { … } /*[clinic input] os.rename src : path_t dst : path_t * src_dir_fd : dir_fd = None dst_dir_fd : dir_fd = None Rename a file or directory. If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. src_dir_fd and dst_dir_fd, may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/ { … } /*[clinic input] os.replace = os.rename Rename a file or directory, overwriting the destination. If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. src_dir_fd and dst_dir_fd, may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ { … } /*[clinic input] os.rmdir path: path_t * dir_fd: dir_fd(requires='unlinkat') = None Remove a directory. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ { … } #ifdef HAVE_SYSTEM #ifdef MS_WINDOWS /*[clinic input] os.system -> long command: Py_UNICODE Execute the command in a subshell. [clinic start generated code]*/ static long os_system_impl(PyObject *module, const wchar_t *command) /*[clinic end generated code: output=dd528cbd5943a679 input=303f5ce97df606b0]*/ { long result; if (PySys_Audit("os.system", "(u)", command) < 0) { return -1; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH result = _wsystem(command); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS return result; } #else /* MS_WINDOWS */ /*[clinic input] os.system -> long command: FSConverter Execute the command in a subshell. [clinic start generated code]*/ static long os_system_impl(PyObject *module, PyObject *command) /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ { … } #endif #endif /* HAVE_SYSTEM */ #ifdef HAVE_UMASK /*[clinic input] os.umask mask: int / Set the current numeric umask and return the previous umask. [clinic start generated code]*/ static PyObject * os_umask_impl(PyObject *module, int mask) /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/ { … } #endif #ifdef MS_WINDOWS /* override the default DeleteFileW behavior so that directory symlinks can be removed with this function, the same as with Unix symlinks */ BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) { WIN32_FILE_ATTRIBUTE_DATA info; WIN32_FIND_DATAW find_data; HANDLE find_data_handle; int is_directory = 0; int is_link = 0; if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; /* Get WIN32_FIND_DATA structure for the path to determine if it is a symlink */ if(is_directory && info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { find_data_handle = FindFirstFileW(lpFileName, &find_data); if(find_data_handle != INVALID_HANDLE_VALUE) { /* IO_REPARSE_TAG_SYMLINK if it is a symlink and IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; FindClose(find_data_handle); } } } if (is_directory && is_link) return RemoveDirectoryW(lpFileName); return DeleteFileW(lpFileName); } #endif /* MS_WINDOWS */ /*[clinic input] os.unlink path: path_t * dir_fd: dir_fd(requires='unlinkat')=None Remove a file (same as remove()). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_unlink_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ { … } /*[clinic input] os.remove = os.unlink Remove a file (same as unlink()). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_remove_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/ { … } static PyStructSequence_Field uname_result_fields[] = …; PyDoc_STRVAR(uname_result__doc__, "uname_result: Result from os.uname().\n\n\ This object may be accessed either as a tuple of\n\ (sysname, nodename, release, version, machine),\n\ or via the attributes sysname, nodename, release, version, and machine.\n\ \n\ See os.uname for more information."); static PyStructSequence_Desc uname_result_desc = …; #ifdef HAVE_UNAME /*[clinic input] os.uname Return an object identifying the current operating system. The object behaves like a named tuple with the following fields: (sysname, nodename, release, version, machine) [clinic start generated code]*/ static PyObject * os_uname_impl(PyObject *module) /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/ { … } #endif /* HAVE_UNAME */ utime_t; /* * these macros assume that "ut" is a pointer to a utime_t * they also intentionally leak the declaration of a pointer named "time" */ #define UTIME_TO_TIMESPEC … \ #define UTIME_TO_TIMEVAL … \ #define UTIME_TO_UTIMBUF … #define UTIME_TO_TIME_T … \ #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) static int utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) { … } #define FUTIMENSAT_DIR_FD_CONVERTER … #else #define FUTIMENSAT_DIR_FD_CONVERTER … #endif #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) static int utime_fd(utime_t *ut, int fd) { … } #define PATH_UTIME_HAVE_FD … #else #define PATH_UTIME_HAVE_FD … #endif #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) #define UTIME_HAVE_NOFOLLOW_SYMLINKS #endif #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS static int utime_nofollow_symlinks(utime_t *ut, const char *path) { … } #endif #ifndef MS_WINDOWS static int utime_default(utime_t *ut, const char *path) { … } #endif static int split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns) { … } /*[clinic input] os.utime path: path_t(allow_fd='PATH_UTIME_HAVE_FD') times: object = None * ns: object = NULL dir_fd: dir_fd(requires='futimensat') = None follow_symlinks: bool=True # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ Set the access and modified time of path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. If times is not None, it must be a tuple (atime, mtime); atime and mtime should be expressed as float seconds since the epoch. If ns is specified, it must be a tuple (atime_ns, mtime_ns); atime_ns and mtime_ns should be expressed as integer nanoseconds since the epoch. If times is None and ns is unspecified, utime uses the current time. Specifying tuples for both times and ns is an error. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. If follow_symlinks is False, and the last element of the path is a symbolic link, utime will modify the symbolic link itself instead of the file the link points to. It is an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. dir_fd and follow_symlinks may not be available on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/ { … } /* Process operations */ /*[clinic input] os._exit status: int Exit to the system with specified status, without normal exit processing. [clinic start generated code]*/ static PyObject * os__exit_impl(PyObject *module, int status) /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/ { … } #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) #define EXECV_CHAR … #else #define EXECV_CHAR … #endif #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN) static void free_string_array(EXECV_CHAR **array, Py_ssize_t count) { … } static int fsconvert_strdup(PyObject *o, EXECV_CHAR **out) { … } #endif #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN) static EXECV_CHAR** parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) { … } static EXECV_CHAR** parse_arglist(PyObject* argv, Py_ssize_t *argc) { … } #endif #ifdef HAVE_EXECV /*[clinic input] os.execv path: path_t Path of executable file. argv: object Tuple or list of strings. / Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ static PyObject * os_execv_impl(PyObject *module, path_t *path, PyObject *argv) /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ { … } /*[clinic input] os.execve path: path_t(allow_fd='PATH_HAVE_FEXECVE') Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ static PyObject * os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ { … } #endif /* HAVE_EXECV */ #ifdef HAVE_POSIX_SPAWN enum posix_spawn_file_actions_identifier { … }; #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) static int convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res); #endif static int parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler, posix_spawnattr_t *attrp) { … } static int parse_file_actions(PyObject *file_actions, posix_spawn_file_actions_t *file_actionsp, PyObject *temp_buffer) { … } static PyObject * py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) { … } /*[clinic input] os.posix_spawn path: path_t Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. / * file_actions: object(c_default='NULL') = () A sequence of file action tuples. setpgroup: object = NULL The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. resetids: bool = False If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. setsid: bool = False If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. setsigmask: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. setsigdef: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. scheduler: object = NULL A tuple with the scheduler policy (optional) and parameters. Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) /*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/ { … } #endif /* HAVE_POSIX_SPAWN */ #ifdef HAVE_POSIX_SPAWNP /*[clinic input] os.posix_spawnp path: path_t Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. / * file_actions: object(c_default='NULL') = () A sequence of file action tuples. setpgroup: object = NULL The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. resetids: bool = False If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. setsid: bool = False If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. setsigmask: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. setsigdef: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. scheduler: object = NULL A tuple with the scheduler policy (optional) and parameters. Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) /*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/ { … } #endif /* HAVE_POSIX_SPAWNP */ #ifdef HAVE_RTPSPAWN static intptr_t _rtp_spawn(int mode, const char *rtpFileName, const char *argv[], const char *envp[]) { RTP_ID rtpid; int status; pid_t res; int async_err = 0; /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes. uStackSize=0 cannot be used, the default stack size is too small for Python. */ if (envp) { rtpid = rtpSpawn(rtpFileName, argv, envp, 100, 0x1000000, 0, VX_FP_TASK); } else { rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ, 100, 0x1000000, 0, VX_FP_TASK); } if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { do { res = waitpid((pid_t)rtpid, &status, 0); } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return RTP_ID_ERROR; return ((intptr_t)status); } return ((intptr_t)rtpid); } #endif #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) /*[clinic input] os.spawnv mode: int Mode of process creation. path: path_t Path of executable file. argv: object Tuple or list of strings. / Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ { EXECV_CHAR **argvlist; int i; Py_ssize_t argc; intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); /* spawnv has three arguments: (mode, path, argv), where argv is a list or tuple of strings. */ if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; } else if (PyTuple_Check(argv)) { argc = PyTuple_Size(argv); getitem = PyTuple_GetItem; } else { PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must be a tuple or list"); return NULL; } if (argc == 0) { PyErr_SetString(PyExc_ValueError, "spawnv() arg 2 cannot be empty"); return NULL; } argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { if (!fsconvert_strdup((*getitem)(argv, i), &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString( PyExc_TypeError, "spawnv() arg 2 must contain only strings"); return NULL; } if (i == 0 && !argvlist[0][0]) { free_string_array(argvlist, i + 1); PyErr_SetString( PyExc_ValueError, "spawnv() arg 2 first element cannot be empty"); return NULL; } } argvlist[argc] = NULL; #if !defined(HAVE_RTPSPAWN) if (mode == _OLD_P_OVERLAY) mode = _P_OVERLAY; #endif if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, Py_None) < 0) { free_string_array(argvlist, argc); return NULL; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnv(mode, path->wide, argvlist); #elif defined(HAVE_RTPSPAWN) spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL); #else spawnval = _spawnv(mode, path->narrow, argvlist); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS int saved_errno = errno; free_string_array(argvlist, argc); if (spawnval == -1) { errno = saved_errno; posix_error(); return NULL; } return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); } /*[clinic input] os.spawnve mode: int Mode of process creation. path: path_t Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. / Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, PyObject *env) /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ { EXECV_CHAR **argvlist; EXECV_CHAR **envlist; PyObject *res = NULL; Py_ssize_t argc, i, envc; intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); Py_ssize_t lastarg = 0; /* spawnve has four arguments: (mode, path, argv, env), where argv is a list or tuple of strings and env is a dictionary like posix.environ. */ if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; } else if (PyTuple_Check(argv)) { argc = PyTuple_Size(argv); getitem = PyTuple_GetItem; } else { PyErr_SetString(PyExc_TypeError, "spawnve() arg 2 must be a tuple or list"); goto fail_0; } if (argc == 0) { PyErr_SetString(PyExc_ValueError, "spawnve() arg 2 cannot be empty"); goto fail_0; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "spawnve() arg 3 must be a mapping object"); goto fail_0; } argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { PyErr_NoMemory(); goto fail_0; } for (i = 0; i < argc; i++) { if (!fsconvert_strdup((*getitem)(argv, i), &argvlist[i])) { lastarg = i; goto fail_1; } if (i == 0 && !argvlist[0][0]) { lastarg = i + 1; PyErr_SetString( PyExc_ValueError, "spawnv() arg 2 first element cannot be empty"); goto fail_1; } } lastarg = argc; argvlist[argc] = NULL; envlist = parse_envlist(env, &envc); if (envlist == NULL) goto fail_1; #if !defined(HAVE_RTPSPAWN) if (mode == _OLD_P_OVERLAY) mode = _P_OVERLAY; #endif if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { goto fail_2; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnve(mode, path->wide, argvlist, envlist); #elif defined(HAVE_RTPSPAWN) spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, (const char **)envlist); #else spawnval = _spawnve(mode, path->narrow, argvlist, envlist); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (spawnval == -1) (void) posix_error(); else res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); fail_2: while (--envc >= 0) { PyMem_Free(envlist[envc]); } PyMem_Free(envlist); fail_1: free_string_array(argvlist, lastarg); fail_0: return res; } #endif /* HAVE_SPAWNV */ #ifdef HAVE_FORK /* Helper function to validate arguments. Returns 0 on success. non-zero on failure with a TypeError raised. If obj is non-NULL it must be callable. */ static int check_null_or_callable(PyObject *obj, const char* obj_name) { … } /*[clinic input] os.register_at_fork * before: object=NULL A callable to be called in the parent before the fork() syscall. after_in_child: object=NULL A callable to be called in the child after fork(). after_in_parent: object=NULL A callable to be called in the parent after fork(). Register callables to be called when forking a new process. 'before' callbacks are called in reverse order. 'after_in_child' and 'after_in_parent' callbacks are called in order. [clinic start generated code]*/ static PyObject * os_register_at_fork_impl(PyObject *module, PyObject *before, PyObject *after_in_child, PyObject *after_in_parent) /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/ { … } #endif /* HAVE_FORK */ #if defined(HAVE_FORK1) || defined(HAVE_FORKPTY) || defined(HAVE_FORK) // Common code to raise a warning if we detect there is more than one thread // running in the process. Best effort, silent if unable to count threads. // Constraint: Quick. Never overcounts. Never leaves an error set. // // This should only be called from the parent process after // PyOS_AfterFork_Parent(). static void warn_about_fork_with_threads(const char* name) { … } #endif // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK #ifdef HAVE_FORK1 /*[clinic input] os.fork1 Fork a child process with a single multiplexed (i.e., not bound) thread. Return 0 to child process and PID of child to parent process. [clinic start generated code]*/ static PyObject * os_fork1_impl(PyObject *module) /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/ { pid_t pid; PyInterpreterState *interp = _PyInterpreterState_GET(); if (_PyInterpreterState_GetFinalizing(interp) != NULL) { PyErr_SetString(PyExc_PythonFinalizationError, "can't fork at interpreter shutdown"); return NULL; } if (!_Py_IsMainInterpreter(interp)) { PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); return NULL; } PyOS_BeforeFork(); pid = fork1(); int saved_errno = errno; if (pid == 0) { /* child: this clobbers and resets the import lock. */ PyOS_AfterFork_Child(); } else { /* parent: release the import lock. */ PyOS_AfterFork_Parent(); // After PyOS_AfterFork_Parent() starts the world to avoid deadlock. warn_about_fork_with_threads("fork1"); } if (pid == -1) { errno = saved_errno; return posix_error(); } return PyLong_FromPid(pid); } #endif /* HAVE_FORK1 */ #ifdef HAVE_FORK /*[clinic input] os.fork Fork a child process. Return 0 to child process and PID of child to parent process. [clinic start generated code]*/ static PyObject * os_fork_impl(PyObject *module) /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/ { … } #endif /* HAVE_FORK */ #ifdef HAVE_SCHED_H #ifdef HAVE_SCHED_GET_PRIORITY_MAX /*[clinic input] os.sched_get_priority_max policy: int Get the maximum scheduling priority for policy. [clinic start generated code]*/ static PyObject * os_sched_get_priority_max_impl(PyObject *module, int policy) /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/ { … } /*[clinic input] os.sched_get_priority_min policy: int Get the minimum scheduling priority for policy. [clinic start generated code]*/ static PyObject * os_sched_get_priority_min_impl(PyObject *module, int policy) /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/ { … } #endif /* HAVE_SCHED_GET_PRIORITY_MAX */ #ifdef HAVE_SCHED_SETSCHEDULER /*[clinic input] os.sched_getscheduler pid: pid_t / Get the scheduling policy for the process identified by pid. Passing 0 for pid returns the scheduling policy for the calling process. [clinic start generated code]*/ static PyObject * os_sched_getscheduler_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/ { … } #endif /* HAVE_SCHED_SETSCHEDULER */ #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) /*[clinic input] class os.sched_param "PyObject *" "SchedParamType" @classmethod os.sched_param.__new__ sched_priority: object A scheduling parameter. Currently has only one field: sched_priority [clinic start generated code]*/ static PyObject * os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/ { … } static PyObject * os_sched_param_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) { … } static PyMethodDef os_sched_param_reduce_method = …; PyDoc_VAR(os_sched_param__doc__); static PyStructSequence_Field sched_param_fields[] = …; static PyStructSequence_Desc sched_param_desc = …; static int convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res) { … } #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */ #ifdef HAVE_SCHED_SETSCHEDULER /*[clinic input] os.sched_setscheduler pid: pid_t policy: int param as param_obj: object / Set the scheduling policy for the process identified by pid. If pid is 0, the calling process is changed. param is an instance of sched_param. [clinic start generated code]*/ static PyObject * os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, PyObject *param_obj) /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/ { … } #endif /* HAVE_SCHED_SETSCHEDULER*/ #ifdef HAVE_SCHED_SETPARAM /*[clinic input] os.sched_getparam pid: pid_t / Returns scheduling parameters for the process identified by pid. If pid is 0, returns parameters for the calling process. Return value is an instance of sched_param. [clinic start generated code]*/ static PyObject * os_sched_getparam_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/ { … } /*[clinic input] os.sched_setparam pid: pid_t param as param_obj: object / Set scheduling parameters for the process identified by pid. If pid is 0, sets parameters for the calling process. param should be an instance of sched_param. [clinic start generated code]*/ static PyObject * os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj) /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/ { … } #endif /* HAVE_SCHED_SETPARAM */ #ifdef HAVE_SCHED_RR_GET_INTERVAL /*[clinic input] os.sched_rr_get_interval -> double pid: pid_t / Return the round-robin quantum for the process identified by pid, in seconds. Value returned is a float. [clinic start generated code]*/ static double os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/ { … } #endif /* HAVE_SCHED_RR_GET_INTERVAL */ /*[clinic input] os.sched_yield Voluntarily relinquish the CPU. [clinic start generated code]*/ static PyObject * os_sched_yield_impl(PyObject *module) /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ { … } #ifdef HAVE_SCHED_SETAFFINITY /* The minimum number of CPUs allocated in a cpu_set_t */ static const int NCPUS_START = …; /*[clinic input] os.sched_setaffinity pid: pid_t mask : object / Set the CPU affinity of the process identified by pid to mask. mask should be an iterable of integers identifying CPUs. [clinic start generated code]*/ static PyObject * os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask) /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/ { … } /*[clinic input] os.sched_getaffinity pid: pid_t / Return the affinity of the process identified by pid (or the current process if zero). The affinity is returned as a set of CPU identifiers. [clinic start generated code]*/ static PyObject * os_sched_getaffinity_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ { … } #endif /* HAVE_SCHED_SETAFFINITY */ #endif /* HAVE_SCHED_H */ #ifdef HAVE_POSIX_OPENPT /*[clinic input] os.posix_openpt -> int oflag: int / Open and return a file descriptor for a master pseudo-terminal device. Performs a posix_openpt() C function call. The oflag argument is used to set file status flags and file access modes as specified in the manual page of posix_openpt() of your system. [clinic start generated code]*/ static int os_posix_openpt_impl(PyObject *module, int oflag) /*[clinic end generated code: output=ee0bc2624305fc79 input=0de33d0e29693caa]*/ { … } #endif /* HAVE_POSIX_OPENPT */ #ifdef HAVE_GRANTPT /*[clinic input] os.grantpt fd: fildes File descriptor of a master pseudo-terminal device. / Grant access to the slave pseudo-terminal device. Performs a grantpt() C function call. [clinic start generated code]*/ static PyObject * os_grantpt_impl(PyObject *module, int fd) /*[clinic end generated code: output=dfd580015cf548ab input=0668e3b96760e849]*/ { … } #endif /* HAVE_GRANTPT */ #ifdef HAVE_UNLOCKPT /*[clinic input] os.unlockpt fd: fildes File descriptor of a master pseudo-terminal device. / Unlock a pseudo-terminal master/slave pair. Performs an unlockpt() C function call. [clinic start generated code]*/ static PyObject * os_unlockpt_impl(PyObject *module, int fd) /*[clinic end generated code: output=e08d354dec12d30c input=de7ab1f59f69a2b4]*/ { … } #endif /* HAVE_UNLOCKPT */ #if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) static PyObject * py_ptsname(int fd) { … } /*[clinic input] os.ptsname fd: fildes File descriptor of a master pseudo-terminal device. / Return the name of the slave pseudo-terminal device. If the ptsname_r() C function is available, it is called; otherwise, performs a ptsname() C function call. [clinic start generated code]*/ static PyObject * os_ptsname_impl(PyObject *module, int fd) /*[clinic end generated code: output=ef300fadc5675872 input=1369ccc0546f3130]*/ { … } #endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */ /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) #define DEV_PTY_FILE … #define HAVE_DEV_PTMX #else #define DEV_PTY_FILE … #endif #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) #ifdef HAVE_PTY_H #include <pty.h> #ifdef HAVE_UTMP_H #include <utmp.h> #endif /* HAVE_UTMP_H */ #elif defined(HAVE_LIBUTIL_H) #include <libutil.h> #elif defined(HAVE_UTIL_H) #include <util.h> #endif /* HAVE_PTY_H */ #ifdef HAVE_STROPTS_H #include <stropts.h> #endif #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) /*[clinic input] os.openpty Open a pseudo-terminal. Return a tuple of (master_fd, slave_fd) containing open file descriptors for both the master and slave ends. [clinic start generated code]*/ static PyObject * os_openpty_impl(PyObject *module) /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/ { … } #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_SETSID) && defined(TIOCSCTTY) #define HAVE_FALLBACK_LOGIN_TTY … #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */ #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) /*[clinic input] os.login_tty fd: fildes / Prepare the tty of which fd is a file descriptor for a new login session. Make the calling process a session leader; make the tty the controlling tty, the stdin, the stdout, and the stderr of the calling process; close fd. [clinic start generated code]*/ static PyObject * os_login_tty_impl(PyObject *module, int fd) /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/ { … } #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */ #ifdef HAVE_FORKPTY /*[clinic input] os.forkpty Fork a new process with a new pseudo-terminal as controlling tty. Returns a tuple of (pid, master_fd). Like fork(), return pid of 0 to the child process, and pid of child to the parent process. To both, return fd of newly opened pseudo-terminal. [clinic start generated code]*/ static PyObject * os_forkpty_impl(PyObject *module) /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/ { … } #endif /* HAVE_FORKPTY */ #ifdef HAVE_GETEGID /*[clinic input] os.getegid Return the current process's effective group id. [clinic start generated code]*/ static PyObject * os_getegid_impl(PyObject *module) /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/ { … } #endif /* HAVE_GETEGID */ #ifdef HAVE_GETEUID /*[clinic input] os.geteuid Return the current process's effective user id. [clinic start generated code]*/ static PyObject * os_geteuid_impl(PyObject *module) /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/ { … } #endif /* HAVE_GETEUID */ #ifdef HAVE_GETGID /*[clinic input] os.getgid Return the current process's group id. [clinic start generated code]*/ static PyObject * os_getgid_impl(PyObject *module) /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/ { … } #endif /* HAVE_GETGID */ #if defined(HAVE_GETPID) /*[clinic input] os.getpid Return the current process id. [clinic start generated code]*/ static PyObject * os_getpid_impl(PyObject *module) /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/ { … } #endif /* defined(HAVE_GETPID) */ #ifdef NGROUPS_MAX #define MAX_GROUPS … #else /* defined to be 16 on Solaris7, so this should be a small number */ #define MAX_GROUPS … #endif #ifdef HAVE_GETGROUPLIST #ifdef __APPLE__ /*[clinic input] os.getgrouplist user: str username to lookup group as basegid: int base group id of the user / Returns a list of groups to which a user belongs. [clinic start generated code]*/ static PyObject * os_getgrouplist_impl(PyObject *module, const char *user, int basegid) /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/ #else /*[clinic input] os.getgrouplist user: str username to lookup group as basegid: gid_t base group id of the user / Returns a list of groups to which a user belongs. [clinic start generated code]*/ static PyObject * os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/ #endif { … } #endif /* HAVE_GETGROUPLIST */ #ifdef HAVE_GETGROUPS /*[clinic input] os.getgroups Return list of supplemental group IDs for the process. [clinic start generated code]*/ static PyObject * os_getgroups_impl(PyObject *module) /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/ { … } #endif /* HAVE_GETGROUPS */ #ifdef HAVE_INITGROUPS #ifdef __APPLE__ /*[clinic input] os.initgroups username as oname: FSConverter gid: int / Initialize the group access list. Call the system initgroups() to initialize the group access list with all of the groups of which the specified username is a member, plus the specified group id. [clinic start generated code]*/ static PyObject * os_initgroups_impl(PyObject *module, PyObject *oname, int gid) /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/ #else /*[clinic input] os.initgroups username as oname: FSConverter gid: gid_t / Initialize the group access list. Call the system initgroups() to initialize the group access list with all of the groups of which the specified username is a member, plus the specified group id. [clinic start generated code]*/ static PyObject * os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid) /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/ #endif { … } #endif /* HAVE_INITGROUPS */ #ifdef HAVE_GETPGID /*[clinic input] os.getpgid pid: pid_t Call the system call getpgid(), and return the result. [clinic start generated code]*/ static PyObject * os_getpgid_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/ { … } #endif /* HAVE_GETPGID */ #ifdef HAVE_GETPGRP /*[clinic input] os.getpgrp Return the current process group id. [clinic start generated code]*/ static PyObject * os_getpgrp_impl(PyObject *module) /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/ { … } #endif /* HAVE_GETPGRP */ #ifdef HAVE_SETPGRP /*[clinic input] os.setpgrp Make the current process the leader of its process group. [clinic start generated code]*/ static PyObject * os_setpgrp_impl(PyObject *module) /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/ { … } #endif /* HAVE_SETPGRP */ #ifdef HAVE_GETPPID #ifdef MS_WINDOWS #include <winternl.h> #include <ProcessSnapshot.h> // The structure definition in winternl.h may be incomplete. // This structure is the full version from the MSDN documentation. typedef struct _PROCESS_BASIC_INFORMATION_FULL { NTSTATUS ExitStatus; PVOID PebBaseAddress; ULONG_PTR AffinityMask; LONG BasePriority; ULONG_PTR UniqueProcessId; ULONG_PTR InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION_FULL; typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) ( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL); // This function returns the process ID of the parent process. // Returns 0 on failure. static ULONG win32_getppid_fast(void) { NTSTATUS status; HMODULE ntdll; PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess; PROCESS_BASIC_INFORMATION_FULL basic_information; static ULONG cached_ppid = 0; if (cached_ppid) { // No need to query the kernel again. return cached_ppid; } ntdll = GetModuleHandleW(L"ntdll.dll"); if (!ntdll) { return 0; } pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(ntdll, "NtQueryInformationProcess"); if (!pNtQueryInformationProcess) { return 0; } status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &basic_information, sizeof(basic_information), NULL); if (!NT_SUCCESS(status)) { return 0; } // Perform sanity check on the parent process ID we received from NtQueryInformationProcess. // The check covers values which exceed the 32-bit range (if running on x64) as well as // zero and (ULONG) -1. if (basic_information.InheritedFromUniqueProcessId == 0 || basic_information.InheritedFromUniqueProcessId >= ULONG_MAX) { return 0; } // Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId // structure member contains a ULONG_PTR which represents the process ID of our parent // process. This process ID will be correctly returned even if the parent process has // exited or been terminated. cached_ppid = (ULONG) basic_information.InheritedFromUniqueProcessId; return cached_ppid; } static PyObject* win32_getppid(void) { DWORD error; PyObject* result = NULL; HANDLE process = GetCurrentProcess(); HPSS snapshot = NULL; ULONG pid; pid = win32_getppid_fast(); if (pid != 0) { return PyLong_FromUnsignedLong(pid); } // If failure occurs in win32_getppid_fast(), fall back to using the PSS API. error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot); if (error != ERROR_SUCCESS) { return PyErr_SetFromWindowsErr(error); } PSS_PROCESS_INFORMATION info; error = PssQuerySnapshot(snapshot, PSS_QUERY_PROCESS_INFORMATION, &info, sizeof(info)); if (error == ERROR_SUCCESS) { result = PyLong_FromUnsignedLong(info.ParentProcessId); } else { result = PyErr_SetFromWindowsErr(error); } PssFreeSnapshot(process, snapshot); return result; } #endif /*MS_WINDOWS*/ /*[clinic input] os.getppid Return the parent's process id. If the parent process has already exited, Windows machines will still return its id; others systems will return the id of the 'init' process (1). [clinic start generated code]*/ static PyObject * os_getppid_impl(PyObject *module) /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/ { … } #endif /* HAVE_GETPPID */ #ifdef HAVE_GETLOGIN /*[clinic input] os.getlogin Return the actual login name. [clinic start generated code]*/ static PyObject * os_getlogin_impl(PyObject *module) /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/ { … } #endif /* HAVE_GETLOGIN */ #ifdef HAVE_GETUID /*[clinic input] os.getuid Return the current process's user id. [clinic start generated code]*/ static PyObject * os_getuid_impl(PyObject *module) /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/ { … } #endif /* HAVE_GETUID */ #ifdef MS_WINDOWS #define HAVE_KILL #endif /* MS_WINDOWS */ #ifdef HAVE_KILL /*[clinic input] os.kill pid: pid_t signal: Py_ssize_t / Kill a process with a signal. [clinic start generated code]*/ static PyObject * os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal) /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/ { … } #endif /* HAVE_KILL */ #ifdef HAVE_KILLPG /*[clinic input] os.killpg pgid: pid_t signal: int / Kill a process group with a signal. [clinic start generated code]*/ static PyObject * os_killpg_impl(PyObject *module, pid_t pgid, int signal) /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/ { … } #endif /* HAVE_KILLPG */ #ifdef HAVE_PLOCK #ifdef HAVE_SYS_LOCK_H #include <sys/lock.h> #endif /*[clinic input] os.plock op: int / Lock program segments into memory."); [clinic start generated code]*/ static PyObject * os_plock_impl(PyObject *module, int op) /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/ { if (plock(op) == -1) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_PLOCK */ #ifdef HAVE_SETUID /*[clinic input] os.setuid uid: uid_t / Set the current process's user id. [clinic start generated code]*/ static PyObject * os_setuid_impl(PyObject *module, uid_t uid) /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/ { … } #endif /* HAVE_SETUID */ #ifdef HAVE_SETEUID /*[clinic input] os.seteuid euid: uid_t / Set the current process's effective user id. [clinic start generated code]*/ static PyObject * os_seteuid_impl(PyObject *module, uid_t euid) /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/ { … } #endif /* HAVE_SETEUID */ #ifdef HAVE_SETEGID /*[clinic input] os.setegid egid: gid_t / Set the current process's effective group id. [clinic start generated code]*/ static PyObject * os_setegid_impl(PyObject *module, gid_t egid) /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/ { … } #endif /* HAVE_SETEGID */ #ifdef HAVE_SETREUID /*[clinic input] os.setreuid ruid: uid_t euid: uid_t / Set the current process's real and effective user ids. [clinic start generated code]*/ static PyObject * os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid) /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/ { … } #endif /* HAVE_SETREUID */ #ifdef HAVE_SETREGID /*[clinic input] os.setregid rgid: gid_t egid: gid_t / Set the current process's real and effective group ids. [clinic start generated code]*/ static PyObject * os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid) /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/ { … } #endif /* HAVE_SETREGID */ #ifdef HAVE_SETGID /*[clinic input] os.setgid gid: gid_t / Set the current process's group id. [clinic start generated code]*/ static PyObject * os_setgid_impl(PyObject *module, gid_t gid) /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/ { … } #endif /* HAVE_SETGID */ #ifdef HAVE_SETGROUPS /*[clinic input] os.setgroups groups: object / Set the groups of the current process to list. [clinic start generated code]*/ static PyObject * os_setgroups(PyObject *module, PyObject *groups) /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ { … } #endif /* HAVE_SETGROUPS */ #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) static PyObject * wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) { … } #endif /* HAVE_WAIT3 || HAVE_WAIT4 */ #ifdef HAVE_WAIT3 /*[clinic input] os.wait3 options: int Wait for completion of a child process. Returns a tuple of information about the child process: (pid, status, rusage) [clinic start generated code]*/ static PyObject * os_wait3_impl(PyObject *module, int options) /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/ { … } #endif /* HAVE_WAIT3 */ #ifdef HAVE_WAIT4 /*[clinic input] os.wait4 pid: pid_t options: int Wait for completion of a specific child process. Returns a tuple of information about the child process: (pid, status, rusage) [clinic start generated code]*/ static PyObject * os_wait4_impl(PyObject *module, pid_t pid, int options) /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/ { … } #endif /* HAVE_WAIT4 */ #if defined(HAVE_WAITID) /*[clinic input] os.waitid idtype: idtype_t Must be one of be P_PID, P_PGID or P_ALL. id: id_t The id to wait on. options: int Constructed from the ORing of one or more of WEXITED, WSTOPPED or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. / Returns the result of waiting for a process or processes. Returns either waitid_result or None if WNOHANG is specified and there are no children in a waitable state. [clinic start generated code]*/ static PyObject * os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/ { … } #endif /* defined(HAVE_WAITID) */ #if defined(HAVE_WAITPID) /*[clinic input] os.waitpid pid: pid_t options: int / Wait for completion of a given child process. Returns a tuple of information regarding the child process: (pid, status) The options argument is ignored on Windows. [clinic start generated code]*/ static PyObject * os_waitpid_impl(PyObject *module, pid_t pid, int options) /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/ { … } #elif defined(HAVE_CWAIT) /* MS C has a variant of waitpid() that's usable for most purposes. */ /*[clinic input] os.waitpid pid: intptr_t options: int / Wait for completion of a given process. Returns a tuple of information regarding the process: (pid, status << 8) The options argument is ignored on Windows. [clinic start generated code]*/ static PyObject * os_waitpid_impl(PyObject *module, intptr_t pid, int options) /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ { int status; intptr_t res; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH res = _cwait(&status, pid, options); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return (!async_err) ? posix_error() : NULL; unsigned long long ustatus = (unsigned int)status; /* shift the status left a byte so this is more like the POSIX waitpid */ return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8); } #endif #ifdef HAVE_WAIT /*[clinic input] os.wait Wait for completion of a child process. Returns a tuple of information about the child process: (pid, status) [clinic start generated code]*/ static PyObject * os_wait_impl(PyObject *module) /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/ { … } #endif /* HAVE_WAIT */ // This system call always crashes on older Android versions. #if defined(__linux__) && defined(__NR_pidfd_open) && \ !(defined(__ANDROID__) && __ANDROID_API__ < 31) /*[clinic input] os.pidfd_open pid: pid_t flags: unsigned_int = 0 Return a file descriptor referring to the process *pid*. The descriptor can be used to perform process management without races and signals. [clinic start generated code]*/ static PyObject * os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags) /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/ { … } #endif #ifdef HAVE_SETNS /*[clinic input] os.setns fd: fildes A file descriptor to a namespace. nstype: int = 0 Type of namespace. Move the calling thread into different namespaces. [clinic start generated code]*/ static PyObject * os_setns_impl(PyObject *module, int fd, int nstype) /*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/ { … } #endif #ifdef HAVE_UNSHARE /*[clinic input] os.unshare flags: int Namespaces to be unshared. Disassociate parts of a process (or thread) execution context. [clinic start generated code]*/ static PyObject * os_unshare_impl(PyObject *module, int flags) /*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/ { … } #endif #if defined(HAVE_READLINK) || defined(MS_WINDOWS) /*[clinic input] os.readlink path: path_t * dir_fd: dir_fd(requires='readlinkat') = None Return a string representing the path to which the symbolic link points. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_readlink_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ { … } #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ #if defined(MS_WINDOWS) /* Remove the last portion of the path - return 0 on success */ static int _dirnameW(WCHAR *path) { WCHAR *ptr; size_t length = wcsnlen_s(path, MAX_PATH); if (length == MAX_PATH) { return -1; } /* walk the path from the end until a backslash is encountered */ for(ptr = path + length; ptr != path; ptr--) { if (*ptr == L'\\' || *ptr == L'/') { break; } } *ptr = 0; return 0; } #endif #ifdef HAVE_SYMLINK #if defined(MS_WINDOWS) /* Is this path absolute? */ static int _is_absW(const WCHAR *path) { return path[0] == L'\\' || path[0] == L'/' || (path[0] && path[1] == L':'); } /* join root and rest with a backslash - return 0 on success */ static int _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) { if (_is_absW(rest)) { return wcscpy_s(dest_path, MAX_PATH, rest); } if (wcscpy_s(dest_path, MAX_PATH, root)) { return -1; } if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { return -1; } return wcscat_s(dest_path, MAX_PATH, rest); } /* Return True if the path at src relative to dest is a directory */ static int _check_dirW(LPCWSTR src, LPCWSTR dest) { WIN32_FILE_ATTRIBUTE_DATA src_info; WCHAR dest_parent[MAX_PATH]; WCHAR src_resolved[MAX_PATH] = L""; /* dest_parent = os.path.dirname(dest) */ if (wcscpy_s(dest_parent, MAX_PATH, dest) || _dirnameW(dest_parent)) { return 0; } /* src_resolved = os.path.join(dest_parent, src) */ if (_joinW(src_resolved, dest_parent, src)) { return 0; } return ( GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ); } #endif /*[clinic input] os.symlink src: path_t dst: path_t target_is_directory: bool = False * dir_fd: dir_fd(requires='symlinkat')=None # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ Create a symbolic link pointing to src named dst. target_is_directory is required on Windows if the target is to be interpreted as a directory. (On Windows, symlink requires Windows 6.0 or greater, and raises a NotImplementedError otherwise.) target_is_directory is ignored on non-Windows platforms. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_symlink_impl(PyObject *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd) /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/ { … } #endif /* HAVE_SYMLINK */ static PyStructSequence_Field times_result_fields[] = …; PyDoc_STRVAR(times_result__doc__, "times_result: Result from os.times().\n\n\ This object may be accessed either as a tuple of\n\ (user, system, children_user, children_system, elapsed),\n\ or via the attributes user, system, children_user, children_system,\n\ and elapsed.\n\ \n\ See os.times for more information."); static PyStructSequence_Desc times_result_desc = …; static PyObject * build_times_result(PyObject *module, double user, double system, double children_user, double children_system, double elapsed) { … } /*[clinic input] os.times Return a collection containing process timing information. The object returned behaves like a named tuple with these fields: (utime, stime, cutime, cstime, elapsed_time) All fields are floating-point numbers. [clinic start generated code]*/ static PyObject * os_times_impl(PyObject *module) /*[clinic end generated code: output=35f640503557d32a input=8dbfe33a2dcc3df3]*/ { … } #if defined(HAVE_TIMERFD_CREATE) #define ONE_SECOND_IN_NS … #define EXTRACT_NSEC … #define CONVERT_SEC_AND_NSEC_TO_DOUBLE(sec, nsec) … static PyObject * build_itimerspec(const struct itimerspec* curr_value) { … } static PyObject * build_itimerspec_ns(const struct itimerspec* curr_value) { … } /*[clinic input] os.timerfd_create clockid: int A valid clock ID constant as timer file descriptor. time.CLOCK_REALTIME time.CLOCK_MONOTONIC time.CLOCK_BOOTTIME / * flags: int = 0 0 or a bit mask of os.TFD_NONBLOCK or os.TFD_CLOEXEC. os.TFD_NONBLOCK If *TFD_NONBLOCK* is set as a flag, read doesn't blocks. If *TFD_NONBLOCK* is not set as a flag, read block until the timer fires. os.TFD_CLOEXEC If *TFD_CLOEXEC* is set as a flag, enable the close-on-exec flag Create and return a timer file descriptor. [clinic start generated code]*/ static PyObject * os_timerfd_create_impl(PyObject *module, int clockid, int flags) /*[clinic end generated code: output=1caae80fb168004a input=64b7020c5ac0b8f4]*/ { … } /*[clinic input] os.timerfd_settime fd: fildes A timer file descriptor. / * flags: int = 0 0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET. initial as initial_double: double = 0.0 The initial expiration time, in seconds. interval as interval_double: double = 0.0 The timer's interval, in seconds. Alter a timer file descriptor's internal timer in seconds. [clinic start generated code]*/ static PyObject * os_timerfd_settime_impl(PyObject *module, int fd, int flags, double initial_double, double interval_double) /*[clinic end generated code: output=df4c1bce6859224e input=81d2c0d7e936e8a7]*/ { … } /*[clinic input] os.timerfd_settime_ns fd: fildes A timer file descriptor. / * flags: int = 0 0 or a bit mask of TFD_TIMER_ABSTIME or TFD_TIMER_CANCEL_ON_SET. initial: long_long = 0 initial expiration timing in seconds. interval: long_long = 0 interval for the timer in seconds. Alter a timer file descriptor's internal timer in nanoseconds. [clinic start generated code]*/ static PyObject * os_timerfd_settime_ns_impl(PyObject *module, int fd, int flags, long long initial, long long interval) /*[clinic end generated code: output=6273ec7d7b4cc0b3 input=261e105d6e42f5bc]*/ { … } /*[clinic input] os.timerfd_gettime fd: fildes A timer file descriptor. / Return a tuple of a timer file descriptor's (interval, next expiration) in float seconds. [clinic start generated code]*/ static PyObject * os_timerfd_gettime_impl(PyObject *module, int fd) /*[clinic end generated code: output=ec5a94a66cfe6ab4 input=8148e3430870da1c]*/ { … } /*[clinic input] os.timerfd_gettime_ns fd: fildes A timer file descriptor. / Return a tuple of a timer file descriptor's (interval, next expiration) in nanoseconds. [clinic start generated code]*/ static PyObject * os_timerfd_gettime_ns_impl(PyObject *module, int fd) /*[clinic end generated code: output=580633a4465f39fe input=a825443e4c6b40ac]*/ { … } #undef ONE_SECOND_IN_NS #undef EXTRACT_NSEC #endif /* HAVE_TIMERFD_CREATE */ #ifdef HAVE_GETSID /*[clinic input] os.getsid pid: pid_t / Call the system call getsid(pid) and return the result. [clinic start generated code]*/ static PyObject * os_getsid_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/ { … } #endif /* HAVE_GETSID */ #ifdef HAVE_SETSID /*[clinic input] os.setsid Call the system call setsid(). [clinic start generated code]*/ static PyObject * os_setsid_impl(PyObject *module) /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/ { … } #endif /* HAVE_SETSID */ #ifdef HAVE_SETPGID /*[clinic input] os.setpgid pid: pid_t pgrp: pid_t / Call the system call setpgid(pid, pgrp). [clinic start generated code]*/ static PyObject * os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp) /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/ { … } #endif /* HAVE_SETPGID */ #ifdef HAVE_TCGETPGRP /*[clinic input] os.tcgetpgrp fd: int / Return the process group associated with the terminal specified by fd. [clinic start generated code]*/ static PyObject * os_tcgetpgrp_impl(PyObject *module, int fd) /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/ { … } #endif /* HAVE_TCGETPGRP */ #ifdef HAVE_TCSETPGRP /*[clinic input] os.tcsetpgrp fd: int pgid: pid_t / Set the process group associated with the terminal specified by fd. [clinic start generated code]*/ static PyObject * os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid) /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/ { … } #endif /* HAVE_TCSETPGRP */ /* Functions acting on file descriptors */ #ifdef O_CLOEXEC extern int _Py_open_cloexec_works; #endif /*[clinic input] os.open -> int path: path_t flags: int mode: int = 0o777 * dir_fd: dir_fd(requires='openat') = None # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ Open a file for low level IO. Returns a file descriptor (integer). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static int os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/ { … } /*[clinic input] os.close fd: int Close a file descriptor. [clinic start generated code]*/ static PyObject * os_close_impl(PyObject *module, int fd) /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ { … } /*[clinic input] os.closerange fd_low: int fd_high: int / Closes all file descriptors in [fd_low, fd_high), ignoring errors. [clinic start generated code]*/ static PyObject * os_closerange_impl(PyObject *module, int fd_low, int fd_high) /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ { … } /*[clinic input] os.dup -> int fd: int / Return a duplicate of a file descriptor. [clinic start generated code]*/ static int os_dup_impl(PyObject *module, int fd) /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/ { … } // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). // dup2.c provides working dup2() if and only if F_DUPFD is available. #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) /*[clinic input] os.dup2 -> int fd: int fd2: int inheritable: bool=True Duplicate file descriptor. [clinic start generated code]*/ static int os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ { … } #endif #ifdef HAVE_LOCKF /*[clinic input] os.lockf fd: int An open file descriptor. command: int One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. length: Py_off_t The number of bytes to lock, starting at the current position. / Apply, test or remove a POSIX lock on an open file descriptor. [clinic start generated code]*/ static PyObject * os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/ { … } #endif /* HAVE_LOCKF */ /*[clinic input] os.lseek -> Py_off_t fd: int An open file descriptor, as returned by os.open(). position: Py_off_t Position, interpreted relative to 'whence'. whence as how: int The relative position to seek from. Valid values are: - SEEK_SET: seek from the start of the file. - SEEK_CUR: seek from the current file position. - SEEK_END: seek from the end of the file. / Set the position of a file descriptor. Return the new position. The return value is the number of bytes relative to the beginning of the file. [clinic start generated code]*/ static Py_off_t os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) /*[clinic end generated code: output=971e1efb6b30bd2f input=f096e754c5367504]*/ { … } /*[clinic input] os.read fd: int length: Py_ssize_t / Read from a file descriptor. Returns a bytes object. [clinic start generated code]*/ static PyObject * os_read_impl(PyObject *module, int fd, Py_ssize_t length) /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/ { … } #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ || defined(__APPLE__))) \ || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \ || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) static int iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) { … } static void iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) { … } #endif #ifdef HAVE_READV /*[clinic input] os.readv -> Py_ssize_t fd: int buffers: object / Read from a file descriptor fd into an iterable of buffers. The buffers should be mutable buffers accepting bytes. readv will transfer data into each buffer until it is full and then move on to the next buffer in the sequence to hold the rest of the data. readv returns the total number of bytes read, which may be less than the total capacity of all the buffers. [clinic start generated code]*/ static Py_ssize_t os_readv_impl(PyObject *module, int fd, PyObject *buffers) /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ { … } #endif /* HAVE_READV */ #ifdef HAVE_PREAD /*[clinic input] os.pread fd: int length: Py_ssize_t offset: Py_off_t / Read a number of bytes from a file descriptor starting at a particular offset. Read length bytes from file descriptor fd, starting at offset bytes from the beginning of the file. The file offset remains unchanged. [clinic start generated code]*/ static PyObject * os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/ { … } #endif /* HAVE_PREAD */ #if defined(HAVE_PREADV) || defined (HAVE_PREADV2) /*[clinic input] os.preadv -> Py_ssize_t fd: int buffers: object offset: Py_off_t flags: int = 0 / Reads from a file descriptor into a number of mutable bytes-like objects. Combines the functionality of readv() and pread(). As readv(), it will transfer data into each buffer until it is full and then move on to the next buffer in the sequence to hold the rest of the data. Its fourth argument, specifies the file offset at which the input operation is to be performed. It will return the total number of bytes read (which can be less than the total capacity of all the objects). The flags argument contains a bitwise OR of zero or more of the following flags: - RWF_HIPRI - RWF_NOWAIT Using non-zero flags requires Linux 4.6 or newer. [clinic start generated code]*/ static Py_ssize_t os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ { … } #endif /* HAVE_PREADV */ /*[clinic input] os.write -> Py_ssize_t fd: int data: Py_buffer / Write a bytes object to a file descriptor. [clinic start generated code]*/ static Py_ssize_t os_write_impl(PyObject *module, int fd, Py_buffer *data) /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/ { … } #ifdef HAVE_SENDFILE #ifdef __APPLE__ /*[clinic input] os.sendfile out_fd: int in_fd: int offset: Py_off_t count as sbytes: Py_off_t headers: object(c_default="NULL") = () trailers: object(c_default="NULL") = () flags: int = 0 Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, Py_off_t sbytes, PyObject *headers, PyObject *trailers, int flags) /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/ #elif defined(__FreeBSD__) || defined(__DragonFly__) /*[clinic input] os.sendfile out_fd: int in_fd: int offset: Py_off_t count: Py_ssize_t headers: object(c_default="NULL") = () trailers: object(c_default="NULL") = () flags: int = 0 Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, Py_ssize_t count, PyObject *headers, PyObject *trailers, int flags) /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ #else /*[clinic input] os.sendfile out_fd: int in_fd: int offset as offobj: object count: Py_ssize_t Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, Py_ssize_t count) /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ #endif { … } #endif /* HAVE_SENDFILE */ #if defined(__APPLE__) /*[clinic input] os._fcopyfile in_fd: int out_fd: int flags: int / Efficiently copy content or metadata of 2 regular file descriptors (macOS). [clinic start generated code]*/ static PyObject * os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags) /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/ { int ret; Py_BEGIN_ALLOW_THREADS ret = fcopyfile(in_fd, out_fd, NULL, flags); Py_END_ALLOW_THREADS if (ret < 0) return posix_error(); Py_RETURN_NONE; } #endif /*[clinic input] os.fstat fd : int Perform a stat system call on the given file descriptor. Like stat(), but for an open file descriptor. Equivalent to os.stat(fd). [clinic start generated code]*/ static PyObject * os_fstat_impl(PyObject *module, int fd) /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/ { … } /*[clinic input] os.isatty -> bool fd: int / Return True if the fd is connected to a terminal. Return True if the file descriptor is an open file descriptor connected to the slave end of a terminal. [clinic start generated code]*/ static int os_isatty_impl(PyObject *module, int fd) /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ { … } #ifdef HAVE_PIPE /*[clinic input] os.pipe Create a pipe. Returns a tuple of two file descriptors: (read_fd, write_fd) [clinic start generated code]*/ static PyObject * os_pipe_impl(PyObject *module) /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/ { … } #endif /* HAVE_PIPE */ #ifdef HAVE_PIPE2 /*[clinic input] os.pipe2 flags: int / Create a pipe with flags set atomically. Returns a tuple of two file descriptors: (read_fd, write_fd) flags can be constructed by ORing together one or more of these values: O_NONBLOCK, O_CLOEXEC. [clinic start generated code]*/ static PyObject * os_pipe2_impl(PyObject *module, int flags) /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/ { … } #endif /* HAVE_PIPE2 */ #ifdef HAVE_WRITEV /*[clinic input] os.writev -> Py_ssize_t fd: int buffers: object / Iterate over buffers, and write the contents of each to a file descriptor. Returns the total number of bytes written. buffers must be a sequence of bytes-like objects. [clinic start generated code]*/ static Py_ssize_t os_writev_impl(PyObject *module, int fd, PyObject *buffers) /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ { … } #endif /* HAVE_WRITEV */ #ifdef HAVE_PWRITE /*[clinic input] os.pwrite -> Py_ssize_t fd: int buffer: Py_buffer offset: Py_off_t / Write bytes to a file descriptor starting at a particular offset. Write buffer to fd, starting at offset bytes from the beginning of the file. Returns the number of bytes written. Does not change the current file offset. [clinic start generated code]*/ static Py_ssize_t os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) /*[clinic end generated code: output=c74da630758ee925 input=614acbc7e5a0339a]*/ { … } #endif /* HAVE_PWRITE */ #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) /*[clinic input] os.pwritev -> Py_ssize_t fd: int buffers: object offset: Py_off_t flags: int = 0 / Writes the contents of bytes-like objects to a file descriptor at a given offset. Combines the functionality of writev() and pwrite(). All buffers must be a sequence of bytes-like objects. Buffers are processed in array order. Entire contents of first buffer is written before proceeding to second, and so on. The operating system may set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. This function writes the contents of each object to the file descriptor and returns the total number of bytes written. The flags argument contains a bitwise OR of zero or more of the following flags: - RWF_DSYNC - RWF_SYNC - RWF_APPEND Using non-zero flags requires Linux 4.7 or newer. [clinic start generated code]*/ static Py_ssize_t os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { … } #endif /* HAVE_PWRITEV */ #ifdef HAVE_COPY_FILE_RANGE /*[clinic input] os.copy_file_range src: int Source file descriptor. dst: int Destination file descriptor. count: Py_ssize_t Number of bytes to copy. offset_src: object = None Starting offset in src. offset_dst: object = None Starting offset in dst. Copy count bytes from one file descriptor to another. If offset_src is None, then src is read from the current position; respectively for offset_dst. [clinic start generated code]*/ static PyObject * os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst) /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ { … } #endif /* HAVE_COPY_FILE_RANGE*/ #if (defined(HAVE_SPLICE) && !defined(_AIX)) /*[clinic input] os.splice src: int Source file descriptor. dst: int Destination file descriptor. count: Py_ssize_t Number of bytes to copy. offset_src: object = None Starting offset in src. offset_dst: object = None Starting offset in dst. flags: unsigned_int = 0 Flags to modify the semantics of the call. Transfer count bytes from one pipe to a descriptor or vice versa. If offset_src is None, then src is read from the current position; respectively for offset_dst. The offset associated to the file descriptor that refers to a pipe must be None. [clinic start generated code]*/ static PyObject * os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst, unsigned int flags) /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ { … } #endif /* HAVE_SPLICE*/ #ifdef HAVE_MKFIFO /*[clinic input] os.mkfifo path: path_t mode: int=0o666 * dir_fd: dir_fd(requires='mkfifoat')=None Create a "fifo" (a POSIX named pipe). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd) /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/ { … } #endif /* HAVE_MKFIFO */ #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) /*[clinic input] os.mknod path: path_t mode: int=0o600 device: dev_t=0 * dir_fd: dir_fd(requires='mknodat')=None Create a node in the file system. Create a node in the file system (file, device special file or named pipe) at path. mode specifies both the permissions to use and the type of node to be created, being combined (bitwise OR) with one of S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, device defines the newly created device special file (probably using os.makedev()). Otherwise device is ignored. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, int dir_fd) /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/ { … } #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ #ifdef HAVE_DEVICE_MACROS static PyObject * major_minor_conv(unsigned int value) { … } static int major_minor_check(dev_t value) { … } /*[clinic input] os.major device: dev_t / Extracts a device major number from a raw device number. [clinic start generated code]*/ static PyObject * os_major_impl(PyObject *module, dev_t device) /*[clinic end generated code: output=4071ffee17647891 input=b1a0a14ec9448229]*/ { … } /*[clinic input] os.minor device: dev_t / Extracts a device minor number from a raw device number. [clinic start generated code]*/ static PyObject * os_minor_impl(PyObject *module, dev_t device) /*[clinic end generated code: output=306cb78e3bc5004f input=2f686e463682a9da]*/ { … } /*[clinic input] os.makedev -> dev_t major: dev_t minor: dev_t / Composes a raw device number from the major and minor device numbers. [clinic start generated code]*/ static dev_t os_makedev_impl(PyObject *module, dev_t major, dev_t minor) /*[clinic end generated code: output=cad6125c51f5af80 input=2146126ec02e55c1]*/ { … } #endif /* HAVE_DEVICE_MACROS */ #if defined HAVE_FTRUNCATE || defined MS_WINDOWS /*[clinic input] os.ftruncate fd: int length: Py_off_t / Truncate a file, specified by file descriptor, to a specific length. [clinic start generated code]*/ static PyObject * os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/ { … } #endif /* HAVE_FTRUNCATE || MS_WINDOWS */ #if defined HAVE_TRUNCATE || defined MS_WINDOWS /*[clinic input] os.truncate path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') length: Py_off_t Truncate a file, specified by path, to a specific length. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/ { … } #endif /* HAVE_TRUNCATE || MS_WINDOWS */ /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is defined, which is the case in Python on AIX. AIX bug report: http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) #define POSIX_FADVISE_AIX_BUG #endif /* GH-111804: Due to posix_fallocate() not having consistent semantics across OSs, support was dropped in WASI preview2. */ #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \ !defined(__wasi__) /*[clinic input] os.posix_fallocate fd: int offset: Py_off_t length: Py_off_t / Ensure a file has allocated at least a particular number of bytes on disk. Ensure that the file specified by fd encompasses a range of bytes starting at offset bytes from the beginning and continuing for length bytes. [clinic start generated code]*/ static PyObject * os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length) /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/ { … } #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */ #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) /*[clinic input] os.posix_fadvise fd: int offset: Py_off_t length: Py_off_t advice: int / Announce an intention to access data in a specific pattern. Announce an intention to access data in a specific pattern, thus allowing the kernel to make optimizations. The advice applies to the region of the file specified by fd starting at offset and continuing for length bytes. advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or POSIX_FADV_DONTNEED. [clinic start generated code]*/ static PyObject * os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length, int advice) /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/ { … } #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ #ifdef MS_WINDOWS static PyObject* win32_putenv(PyObject *name, PyObject *value) { /* Search from index 1 because on Windows starting '=' is allowed for defining hidden environment variables. */ if (PyUnicode_GET_LENGTH(name) == 0 || PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); return NULL; } PyObject *unicode; if (value != NULL) { unicode = PyUnicode_FromFormat("%U=%U", name, value); } else { unicode = PyUnicode_FromFormat("%U=", name); } if (unicode == NULL) { return NULL; } Py_ssize_t size; wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); Py_DECREF(unicode); if (env == NULL) { return NULL; } if (size > _MAX_ENV) { PyErr_Format(PyExc_ValueError, "the environment variable is longer than %u characters", _MAX_ENV); PyMem_Free(env); return NULL; } if (wcslen(env) != (size_t)size) { PyErr_SetString(PyExc_ValueError, "embedded null character"); PyMem_Free(env); return NULL; } /* _wputenv() and SetEnvironmentVariableW() update the environment in the Process Environment Block (PEB). _wputenv() also updates CRT 'environ' and '_wenviron' variables, whereas SetEnvironmentVariableW() does not. Prefer _wputenv() to be compatible with C libraries using CRT variables and CRT functions using these variables (ex: getenv()). */ int err = _wputenv(env); if (err) { posix_error(); PyMem_Free(env); return NULL; } PyMem_Free(env); Py_RETURN_NONE; } #endif #ifdef MS_WINDOWS /*[clinic input] os.putenv name: unicode value: unicode / Change or add an environment variable. [clinic start generated code]*/ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ { if (PySys_Audit("os.putenv", "OO", name, value) < 0) { return NULL; } return win32_putenv(name, value); } #else /*[clinic input] os.putenv name: FSConverter value: FSConverter / Change or add an environment variable. [clinic start generated code]*/ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/ { … } #endif /* !defined(MS_WINDOWS) */ #ifdef MS_WINDOWS /*[clinic input] os.unsetenv name: unicode / Delete an environment variable. [clinic start generated code]*/ static PyObject * os_unsetenv_impl(PyObject *module, PyObject *name) /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/ { if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { return NULL; } return win32_putenv(name, NULL); } #else /*[clinic input] os.unsetenv name: FSConverter / Delete an environment variable. [clinic start generated code]*/ static PyObject * os_unsetenv_impl(PyObject *module, PyObject *name) /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/ { … } #endif /* !MS_WINDOWS */ /*[clinic input] os.strerror code: int / Translate an error code to a message string. [clinic start generated code]*/ static PyObject * os_strerror_impl(PyObject *module, int code) /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/ { … } #ifdef HAVE_SYS_WAIT_H #ifdef WCOREDUMP /*[clinic input] os.WCOREDUMP -> bool status: int / Return True if the process returning status was dumped to a core file. [clinic start generated code]*/ static int os_WCOREDUMP_impl(PyObject *module, int status) /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/ { … } #endif /* WCOREDUMP */ #ifdef WIFCONTINUED /*[clinic input] os.WIFCONTINUED -> bool status: int Return True if a particular process was continued from a job control stop. Return True if the process returning status was continued from a job control stop. [clinic start generated code]*/ static int os_WIFCONTINUED_impl(PyObject *module, int status) /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/ { … } #endif /* WIFCONTINUED */ #ifdef WIFSTOPPED /*[clinic input] os.WIFSTOPPED -> bool status: int Return True if the process returning status was stopped. [clinic start generated code]*/ static int os_WIFSTOPPED_impl(PyObject *module, int status) /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/ { … } #endif /* WIFSTOPPED */ #ifdef WIFSIGNALED /*[clinic input] os.WIFSIGNALED -> bool status: int Return True if the process returning status was terminated by a signal. [clinic start generated code]*/ static int os_WIFSIGNALED_impl(PyObject *module, int status) /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/ { … } #endif /* WIFSIGNALED */ #ifdef WIFEXITED /*[clinic input] os.WIFEXITED -> bool status: int Return True if the process returning status exited via the exit() system call. [clinic start generated code]*/ static int os_WIFEXITED_impl(PyObject *module, int status) /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/ { … } #endif /* WIFEXITED */ #ifdef WEXITSTATUS /*[clinic input] os.WEXITSTATUS -> int status: int Return the process return code from status. [clinic start generated code]*/ static int os_WEXITSTATUS_impl(PyObject *module, int status) /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/ { … } #endif /* WEXITSTATUS */ #ifdef WTERMSIG /*[clinic input] os.WTERMSIG -> int status: int Return the signal that terminated the process that provided the status value. [clinic start generated code]*/ static int os_WTERMSIG_impl(PyObject *module, int status) /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/ { … } #endif /* WTERMSIG */ #ifdef WSTOPSIG /*[clinic input] os.WSTOPSIG -> int status: int Return the signal that stopped the process that provided the status value. [clinic start generated code]*/ static int os_WSTOPSIG_impl(PyObject *module, int status) /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/ { … } #endif /* WSTOPSIG */ #endif /* HAVE_SYS_WAIT_H */ #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) #ifdef _SCO_DS /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the needed definitions in sys/statvfs.h */ #define _SVID3 #endif #include <sys/statvfs.h> #ifdef __APPLE__ /* On macOS struct statvfs uses 32-bit integers for block counts, * resulting in overflow when filesystems are larger than 4TB. Therefore * os.statvfs is implemented in terms of statfs(2). */ static PyObject* _pystatvfs_fromstructstatfs(PyObject *module, struct statfs st) { PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType; PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType); if (v == NULL) { return NULL; } long flags = 0; if (st.f_flags & MNT_RDONLY) { flags |= ST_RDONLY; } if (st.f_flags & MNT_NOSUID) { flags |= ST_NOSUID; } _Static_assert(sizeof(st.f_blocks) == sizeof(long long), "assuming large file"); #define SET_ITEM … SET_ITEM(v, 0, PyLong_FromLong((long) st.f_iosize)); SET_ITEM(v, 1, PyLong_FromLong((long) st.f_bsize)); SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks)); SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree)); SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail)); SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files)); SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree)); SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_ffree)); SET_ITEM(v, 8, PyLong_FromLong((long) flags)); SET_ITEM(v, 9, PyLong_FromLong((long) NAME_MAX)); SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0])); #undef SET_ITEM return v; } #else static PyObject* _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) { … } #endif /*[clinic input] os.fstatvfs fd: int / Perform an fstatvfs system call on the given fd. Equivalent to statvfs(fd). [clinic start generated code]*/ static PyObject * os_fstatvfs_impl(PyObject *module, int fd) /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/ { … } #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) #include <sys/statvfs.h> /*[clinic input] os.statvfs path: path_t(allow_fd='PATH_HAVE_FSTATVFS') Perform a statvfs system call on the given path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_statvfs_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/ { … } #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ #ifdef MS_WINDOWS /*[clinic input] os._getdiskusage path: path_t Return disk usage statistics about the given path as a (total, free) tuple. [clinic start generated code]*/ static PyObject * os__getdiskusage_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ { BOOL retval; ULARGE_INTEGER _, total, free; DWORD err = 0; Py_BEGIN_ALLOW_THREADS retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); Py_END_ALLOW_THREADS if (retval == 0) { if (GetLastError() == ERROR_DIRECTORY) { wchar_t *dir_path = NULL; dir_path = PyMem_New(wchar_t, path->length + 1); if (dir_path == NULL) { return PyErr_NoMemory(); } wcscpy_s(dir_path, path->length + 1, path->wide); if (_dirnameW(dir_path) != -1) { Py_BEGIN_ALLOW_THREADS retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free); Py_END_ALLOW_THREADS } /* Record the last error in case it's modified by PyMem_Free. */ err = GetLastError(); PyMem_Free(dir_path); if (retval) { goto success; } } return PyErr_SetFromWindowsErr(err); } success: return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); } #endif /* MS_WINDOWS */ /* This is used for fpathconf(), pathconf(), confstr() and sysconf(). * It maps strings representing configuration variable names to * integer values, allowing those functions to be called with the * magic names instead of polluting the module's namespace with tons of * rarely-used constants. There are three separate tables that use * these definitions. * * This code is always included, even if none of the interfaces that * need it are included. The #if hackery needed to avoid it would be * sufficiently pervasive that it's not worth the loss of readability. */ struct constdef { … }; static int conv_confname(PyObject *module, PyObject *arg, int *valuep, const char *tablename) { … } #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) static struct constdef posix_constants_pathconf[] = …; #endif #ifdef HAVE_FPATHCONF /*[clinic input] os.fpathconf -> long fd: fildes name: confname(table="pathconf_names") / Return the configuration limit name for the file descriptor fd. If there is no limit, return -1. [clinic start generated code]*/ static long os_fpathconf_impl(PyObject *module, int fd, int name) /*[clinic end generated code: output=d5b7042425fc3e21 input=023d44589c9ed6aa]*/ { … } #endif /* HAVE_FPATHCONF */ #ifdef HAVE_PATHCONF /*[clinic input] os.pathconf -> long path: path_t(allow_fd='PATH_HAVE_FPATHCONF') name: confname(table="pathconf_names") Return the configuration limit name for the file or directory path. If there is no limit, return -1. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static long os_pathconf_impl(PyObject *module, path_t *path, int name) /*[clinic end generated code: output=5bedee35b293a089 input=6f6072f57b10c787]*/ { … } #endif /* HAVE_PATHCONF */ #ifdef HAVE_CONFSTR static struct constdef posix_constants_confstr[] = …; /*[clinic input] os.confstr name: confname(table="confstr_names") / Return a string-valued system configuration variable. [clinic start generated code]*/ static PyObject * os_confstr_impl(PyObject *module, int name) /*[clinic end generated code: output=bfb0b1b1e49b9383 input=4c6ffca2837ec959]*/ { … } #endif /* HAVE_CONFSTR */ #ifdef HAVE_SYSCONF static struct constdef posix_constants_sysconf[] = …; /*[clinic input] os.sysconf -> long name: confname(table="sysconf_names") / Return an integer-valued system configuration variable. [clinic start generated code]*/ static long os_sysconf_impl(PyObject *module, int name) /*[clinic end generated code: output=3662f945fc0cc756 input=930b8f23b5d15086]*/ { … } #endif /* HAVE_SYSCONF */ static int setup_confname_table(struct constdef *table, size_t tablesize, const char *tablename, PyObject *module) { … } /* Return -1 on failure, 0 on success. */ static int setup_confname_tables(PyObject *module) { … } /*[clinic input] os.abort Abort the interpreter immediately. This function 'dumps core' or otherwise fails in the hardest way possible on the hosting operating system. This function never returns. [clinic start generated code]*/ static PyObject * os_abort_impl(PyObject *module) /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ { … } #ifdef MS_WINDOWS /* Grab ShellExecute dynamically from shell32 */ static int has_ShellExecute = -1; static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT); static int check_ShellExecute(void) { HINSTANCE hShell32; /* only recheck */ if (-1 == has_ShellExecute) { Py_BEGIN_ALLOW_THREADS /* Security note: this call is not vulnerable to "DLL hijacking". SHELL32 is part of "KnownDLLs" and so Windows always load the system SHELL32.DLL, even if there is another SHELL32.DLL in the DLL search path. */ hShell32 = LoadLibraryW(L"SHELL32"); if (hShell32) { *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, "ShellExecuteW"); has_ShellExecute = Py_ShellExecuteW != NULL; } else { has_ShellExecute = 0; } Py_END_ALLOW_THREADS } return has_ShellExecute; } /*[clinic input] os.startfile filepath: path_t operation: Py_UNICODE = NULL arguments: Py_UNICODE = NULL cwd: path_t(nullable=True) = None show_cmd: int = 1 Start a file with its associated application. When "operation" is not specified or "open", this acts like double-clicking the file in Explorer, or giving the file name as an argument to the DOS "start" command: the file is opened with whatever application (if any) its extension is associated. When another "operation" is given, it specifies what should be done with the file. A typical operation is "print". "arguments" is passed to the application, but should be omitted if the file is a document. "cwd" is the working directory for the operation. If "filepath" is relative, it will be resolved against this directory. This argument should usually be an absolute path. "show_cmd" can be used to override the recommended visibility option. See the Windows ShellExecute documentation for values. startfile returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application's exit status. The filepath is relative to the current directory. If you want to use an absolute path, make sure the first character is not a slash ("/"); the underlying Win32 ShellExecute function doesn't work if it is. [clinic start generated code]*/ static PyObject * os_startfile_impl(PyObject *module, path_t *filepath, const wchar_t *operation, const wchar_t *arguments, path_t *cwd, int show_cmd) /*[clinic end generated code: output=1c6f2f3340e31ffa input=8248997b80669622]*/ { HINSTANCE rc; if(!check_ShellExecute()) { /* If the OS doesn't have ShellExecute, return a NotImplementedError. */ return PyErr_Format(PyExc_NotImplementedError, "startfile not available on this platform"); } if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { return NULL; } if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, arguments, cwd->object ? cwd->object : Py_None, show_cmd) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, arguments, cwd->wide, show_cmd); Py_END_ALLOW_THREADS if (rc <= (HINSTANCE)32) { win32_error_object("startfile", filepath->object); return NULL; } Py_RETURN_NONE; } #endif /* MS_WINDOWS */ #ifdef HAVE_GETLOADAVG /*[clinic input] os.getloadavg Return average recent system load information. Return the number of processes in the system run queue averaged over the last 1, 5, and 15 minutes as a tuple of three floats. Raises OSError if the load average was unobtainable. [clinic start generated code]*/ static PyObject * os_getloadavg_impl(PyObject *module) /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/ { … } #endif /* HAVE_GETLOADAVG */ /*[clinic input] os.device_encoding fd: int Return a string describing the encoding of a terminal's file descriptor. The file descriptor must be attached to a terminal. If the device is not a terminal, return None. [clinic start generated code]*/ static PyObject * os_device_encoding_impl(PyObject *module, int fd) /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/ { … } #ifdef HAVE_SETRESUID /*[clinic input] os.setresuid ruid: uid_t euid: uid_t suid: uid_t / Set the current process's real, effective, and saved user ids. [clinic start generated code]*/ static PyObject * os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid) /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/ { … } #endif /* HAVE_SETRESUID */ #ifdef HAVE_SETRESGID /*[clinic input] os.setresgid rgid: gid_t egid: gid_t sgid: gid_t / Set the current process's real, effective, and saved group ids. [clinic start generated code]*/ static PyObject * os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid) /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/ { … } #endif /* HAVE_SETRESGID */ #ifdef HAVE_GETRESUID /*[clinic input] os.getresuid Return a tuple of the current process's real, effective, and saved user ids. [clinic start generated code]*/ static PyObject * os_getresuid_impl(PyObject *module) /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/ { … } #endif /* HAVE_GETRESUID */ #ifdef HAVE_GETRESGID /*[clinic input] os.getresgid Return a tuple of the current process's real, effective, and saved group ids. [clinic start generated code]*/ static PyObject * os_getresgid_impl(PyObject *module) /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/ { … } #endif /* HAVE_GETRESGID */ #ifdef USE_XATTRS /*[clinic input] os.getxattr path: path_t(allow_fd=True) attribute: path_t * follow_symlinks: bool = True Return the value of extended attribute attribute on path. path may be either a string, a path-like object, or an open file descriptor. If follow_symlinks is False, and the last element of the path is a symbolic link, getxattr will examine the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ { … } /*[clinic input] os.setxattr path: path_t(allow_fd=True) attribute: path_t value: Py_buffer flags: int = 0 * follow_symlinks: bool = True Set extended attribute attribute on path to value. path may be either a string, a path-like object, or an open file descriptor. If follow_symlinks is False, and the last element of the path is a symbolic link, setxattr will modify the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks) /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/ { … } /*[clinic input] os.removexattr path: path_t(allow_fd=True) attribute: path_t * follow_symlinks: bool = True Remove extended attribute attribute on path. path may be either a string, a path-like object, or an open file descriptor. If follow_symlinks is False, and the last element of the path is a symbolic link, removexattr will modify the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/ { … } /*[clinic input] os.listxattr path: path_t(allow_fd=True, nullable=True) = None * follow_symlinks: bool = True Return a list of extended attributes on path. path may be either None, a string, a path-like object, or an open file descriptor. if path is None, listxattr will examine the current directory. If follow_symlinks is False, and the last element of the path is a symbolic link, listxattr will examine the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/ { … } #endif /* USE_XATTRS */ /*[clinic input] os.urandom size: Py_ssize_t / Return a bytes object containing random bytes suitable for cryptographic use. [clinic start generated code]*/ static PyObject * os_urandom_impl(PyObject *module, Py_ssize_t size) /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/ { … } #ifdef HAVE_MEMFD_CREATE /*[clinic input] os.memfd_create name: FSConverter flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC [clinic start generated code]*/ static PyObject * os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/ { … } #endif #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) /*[clinic input] os.eventfd initval: unsigned_int flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC Creates and returns an event notification file descriptor. [clinic start generated code]*/ static PyObject * os_eventfd_impl(PyObject *module, unsigned int initval, int flags) /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ { … } /*[clinic input] os.eventfd_read fd: fildes Read eventfd value [clinic start generated code]*/ static PyObject * os_eventfd_read_impl(PyObject *module, int fd) /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ { … } /*[clinic input] os.eventfd_write fd: fildes value: unsigned_long_long Write eventfd value. [clinic start generated code]*/ static PyObject * os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ { … } #endif /* HAVE_EVENTFD && EFD_CLOEXEC */ /* Terminal size querying */ PyDoc_STRVAR(TerminalSize_docstring, "A tuple of (columns, lines) for holding terminal window size"); static PyStructSequence_Field TerminalSize_fields[] = …; static PyStructSequence_Desc TerminalSize_desc = …; #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) /*[clinic input] os.get_terminal_size fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1 / Return the size of the terminal window as (columns, lines). The optional argument fd (default standard output) specifies which file descriptor should be queried. If the file descriptor is not connected to a terminal, an OSError is thrown. This function will only be defined if an implementation is available for this system. shutil.get_terminal_size is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation. [clinic start generated code]*/ static PyObject * os_get_terminal_size_impl(PyObject *module, int fd) /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/ { … } #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ /*[clinic input] os.cpu_count Return the number of logical CPUs in the system. Return None if indeterminable. [clinic start generated code]*/ static PyObject * os_cpu_count_impl(PyObject *module) /*[clinic end generated code: output=5fc29463c3936a9c input=ba2f6f8980a0e2eb]*/ { … } /*[clinic input] os.get_inheritable -> bool fd: int / Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ static int os_get_inheritable_impl(PyObject *module, int fd) /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ { … } /*[clinic input] os.set_inheritable fd: int inheritable: int / Set the inheritable flag of the specified file descriptor. [clinic start generated code]*/ static PyObject * os_set_inheritable_impl(PyObject *module, int fd, int inheritable) /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ { … } #ifdef MS_WINDOWS #ifndef HANDLE_FLAG_INHERIT #define HANDLE_FLAG_INHERIT … #endif /*[clinic input] os.get_handle_inheritable -> bool handle: intptr_t / Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ static int os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ { DWORD flags; if (!GetHandleInformation((HANDLE)handle, &flags)) { PyErr_SetFromWindowsErr(0); return -1; } return flags & HANDLE_FLAG_INHERIT; } /*[clinic input] os.set_handle_inheritable handle: intptr_t inheritable: bool / Set the inheritable flag of the specified handle. [clinic start generated code]*/ static PyObject * os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable) /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ { DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { PyErr_SetFromWindowsErr(0); return NULL; } Py_RETURN_NONE; } #endif /* MS_WINDOWS */ /*[clinic input] os.get_blocking -> bool fd: int / Get the blocking mode of the file descriptor. Return False if the O_NONBLOCK flag is set, True if the flag is cleared. [clinic start generated code]*/ static int os_get_blocking_impl(PyObject *module, int fd) /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/ { … } /*[clinic input] os.set_blocking fd: int blocking: bool / Set the blocking mode of the specified file descriptor. Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag otherwise. [clinic start generated code]*/ static PyObject * os_set_blocking_impl(PyObject *module, int fd, int blocking) /*[clinic end generated code: output=384eb43aa0762a9d input=7e9dfc9b14804dd4]*/ { … } /*[clinic input] class os.DirEntry "DirEntry *" "DirEntryType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/ DirEntry; static void DirEntry_dealloc(DirEntry *entry) { … } /* Forward reference */ static int DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, int follow_symlinks, unsigned short mode_bits); /*[clinic input] os.DirEntry.is_symlink -> bool defining_class: defining_class / Return True if the entry is a symbolic link; cached per entry. [clinic start generated code]*/ static int os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class) /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/ { … } /*[clinic input] os.DirEntry.is_junction -> bool Return True if the entry is a junction; cached per entry. [clinic start generated code]*/ static int os_DirEntry_is_junction_impl(DirEntry *self) /*[clinic end generated code: output=97f64d5d99eeccb5 input=4fc8e701eea118a1]*/ { … } static PyObject * DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) { … } static PyObject * DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self) { … } /*[clinic input] os.DirEntry.stat defining_class: defining_class / * follow_symlinks: bool = True Return stat_result object for the entry; cached per entry. [clinic start generated code]*/ static PyObject * os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks) /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/ { … } /* Set exception and return -1 on error, 0 for False, 1 for True */ static int DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, int follow_symlinks, unsigned short mode_bits) { … } /*[clinic input] os.DirEntry.is_dir -> bool defining_class: defining_class / * follow_symlinks: bool = True Return True if the entry is a directory; cached per entry. [clinic start generated code]*/ static int os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks) /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/ { … } /*[clinic input] os.DirEntry.is_file -> bool defining_class: defining_class / * follow_symlinks: bool = True Return True if the entry is a file; cached per entry. [clinic start generated code]*/ static int os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks) /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/ { … } /*[clinic input] os.DirEntry.inode Return inode of the entry; cached per entry. [clinic start generated code]*/ static PyObject * os_DirEntry_inode_impl(DirEntry *self) /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/ { … } static PyObject * DirEntry_repr(DirEntry *self) { … } /*[clinic input] os.DirEntry.__fspath__ Returns the path for the entry. [clinic start generated code]*/ static PyObject * os_DirEntry___fspath___impl(DirEntry *self) /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/ { … } static PyMemberDef DirEntry_members[] = …; #include "clinic/posixmodule.c.h" static PyMethodDef DirEntry_methods[] = …; static PyType_Slot DirEntryType_slots[] = …; static PyType_Spec DirEntryType_spec = …; #ifdef MS_WINDOWS static wchar_t * join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename) { Py_ssize_t path_len; Py_ssize_t size; wchar_t *result; wchar_t ch; if (!path_wide) { /* Default arg: "." */ path_wide = L"."; path_len = 1; } else { path_len = wcslen(path_wide); } /* The +1's are for the path separator and the NUL */ size = path_len + 1 + wcslen(filename) + 1; result = PyMem_New(wchar_t, size); if (!result) { PyErr_NoMemory(); return NULL; } wcscpy(result, path_wide); if (path_len > 0) { ch = result[path_len - 1]; if (ch != SEP && ch != ALTSEP && ch != L':') result[path_len++] = SEP; wcscpy(result + path_len, filename); } return result; } static PyObject * DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW) { DirEntry *entry; BY_HANDLE_FILE_INFORMATION file_info; ULONG reparse_tag; wchar_t *joined_path; PyObject *DirEntryType = get_posix_state(module)->DirEntryType; entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType); if (!entry) return NULL; entry->name = NULL; entry->path = NULL; entry->stat = NULL; entry->lstat = NULL; entry->got_file_index = 0; entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); if (!entry->name) goto error; int return_bytes = path->wide && PyBytes_Check(path->object); if (return_bytes) { Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name)); if (!entry->name) goto error; } joined_path = join_path_filenameW(path->wide, dataW->cFileName); if (!joined_path) goto error; entry->path = PyUnicode_FromWideChar(joined_path, -1); PyMem_Free(joined_path); if (!entry->path) goto error; if (return_bytes) { Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path)); if (!entry->path) goto error; } find_data_to_file_info(dataW, &file_info, &reparse_tag); _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat); /* ctime is only deprecated from 3.12, so we copy birthtime across */ entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime; entry->win32_lstat.st_ctime_nsec = entry->win32_lstat.st_birthtime_nsec; return (PyObject *)entry; error: Py_DECREF(entry); return NULL; } #else /* POSIX */ static char * join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len) { … } static PyObject * DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name, Py_ssize_t name_len, ino_t d_ino #ifdef HAVE_DIRENT_D_TYPE , unsigned char d_type #endif ) { … } #endif ScandirIterator; #ifdef MS_WINDOWS static int ScandirIterator_is_closed(ScandirIterator *iterator) { return iterator->handle == INVALID_HANDLE_VALUE; } static void ScandirIterator_closedir(ScandirIterator *iterator) { HANDLE handle = iterator->handle; if (handle == INVALID_HANDLE_VALUE) return; iterator->handle = INVALID_HANDLE_VALUE; Py_BEGIN_ALLOW_THREADS FindClose(handle); Py_END_ALLOW_THREADS } static PyObject * ScandirIterator_iternext(ScandirIterator *iterator) { WIN32_FIND_DATAW *file_data = &iterator->file_data; BOOL success; PyObject *entry; /* Happens if the iterator is iterated twice, or closed explicitly */ if (iterator->handle == INVALID_HANDLE_VALUE) return NULL; while (1) { if (!iterator->first_time) { Py_BEGIN_ALLOW_THREADS success = FindNextFileW(iterator->handle, file_data); Py_END_ALLOW_THREADS if (!success) { /* Error or no more files */ if (GetLastError() != ERROR_NO_MORE_FILES) path_error(&iterator->path); break; } } iterator->first_time = 0; /* Skip over . and .. */ if (wcscmp(file_data->cFileName, L".") != 0 && wcscmp(file_data->cFileName, L"..") != 0) { PyObject *module = PyType_GetModule(Py_TYPE(iterator)); entry = DirEntry_from_find_data(module, &iterator->path, file_data); if (!entry) break; return entry; } /* Loop till we get a non-dot directory or finish iterating */ } /* Error or no more files */ ScandirIterator_closedir(iterator); return NULL; } #else /* POSIX */ static int ScandirIterator_is_closed(ScandirIterator *iterator) { … } static void ScandirIterator_closedir(ScandirIterator *iterator) { … } static PyObject * ScandirIterator_iternext(ScandirIterator *iterator) { … } #endif static PyObject * ScandirIterator_close(ScandirIterator *self, PyObject *args) { … } static PyObject * ScandirIterator_enter(PyObject *self, PyObject *args) { … } static PyObject * ScandirIterator_exit(ScandirIterator *self, PyObject *args) { … } static void ScandirIterator_finalize(ScandirIterator *iterator) { … } static void ScandirIterator_dealloc(ScandirIterator *iterator) { … } static PyMethodDef ScandirIterator_methods[] = …; static PyType_Slot ScandirIteratorType_slots[] = …; static PyType_Spec ScandirIteratorType_spec = …; /*[clinic input] os.scandir path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None Return an iterator of DirEntry objects for given path. path can be specified as either str, bytes, or a path-like object. If path is bytes, the names of yielded DirEntry objects will also be bytes; in all other circumstances they will be str. If path is None, uses the path='.'. [clinic start generated code]*/ static PyObject * os_scandir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/ { … } /* Return the file system path representation of the object. If the object is str or bytes, then allow it to pass through with an incremented refcount. If the object defines __fspath__(), then return the result of that method. All other types raise a TypeError. */ PyObject * PyOS_FSPath(PyObject *path) { … } /*[clinic input] os.fspath path: object Return the file system path representation of the object. If the object is str or bytes, then allow it to pass through as-is. If the object defines __fspath__(), then return the result of that method. All other types raise a TypeError. [clinic start generated code]*/ static PyObject * os_fspath_impl(PyObject *module, PyObject *path) /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/ { … } #ifdef HAVE_GETRANDOM_SYSCALL /*[clinic input] os.getrandom size: Py_ssize_t flags: int=0 Obtain a series of random bytes. [clinic start generated code]*/ static PyObject * os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/ { … } #endif /* HAVE_GETRANDOM_SYSCALL */ #if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM) /* bpo-36085: Helper functions for managing DLL search directories * on win32 */ /*[clinic input] os._add_dll_directory path: path_t Add a path to the DLL search path. This search path is used when resolving dependencies for imported extension modules (the module itself is resolved through sys.path), and also by ctypes. Returns an opaque value that may be passed to os.remove_dll_directory to remove this directory from the search path. [clinic start generated code]*/ static PyObject * os__add_dll_directory_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/ { DLL_DIRECTORY_COOKIE cookie = 0; DWORD err = 0; if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS if (!(cookie = AddDllDirectory(path->wide))) { err = GetLastError(); } Py_END_ALLOW_THREADS if (err) { return win32_error_object_err("add_dll_directory", path->object, err); } return PyCapsule_New(cookie, "DLL directory cookie", NULL); } /*[clinic input] os._remove_dll_directory cookie: object Removes a path from the DLL search path. The parameter is an opaque value that was returned from os.add_dll_directory. You can only remove directories that you added yourself. [clinic start generated code]*/ static PyObject * os__remove_dll_directory_impl(PyObject *module, PyObject *cookie) /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/ { DLL_DIRECTORY_COOKIE cookieValue; DWORD err = 0; if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) { PyErr_SetString(PyExc_TypeError, "Provided cookie was not returned from os.add_dll_directory"); return NULL; } cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer( cookie, "DLL directory cookie"); Py_BEGIN_ALLOW_THREADS if (!RemoveDllDirectory(cookieValue)) { err = GetLastError(); } Py_END_ALLOW_THREADS if (err) { return win32_error_object_err("remove_dll_directory", NULL, err); } if (PyCapsule_SetName(cookie, NULL)) { return NULL; } Py_RETURN_NONE; } #endif /* MS_WINDOWS_APP || MS_WINDOWS_SYSTEM */ /* Only check if WIFEXITED is available: expect that it comes with WEXITSTATUS, WIFSIGNALED, etc. os.waitstatus_to_exitcode() is implemented in C and not in Python, so subprocess can safely call it during late Python finalization without risking that used os attributes were set to None by finalize_modules(). */ #if defined(WIFEXITED) || defined(MS_WINDOWS) /*[clinic input] os.waitstatus_to_exitcode status as status_obj: object Convert a wait status to an exit code. On Unix: * If WIFEXITED(status) is true, return WEXITSTATUS(status). * If WIFSIGNALED(status) is true, return -WTERMSIG(status). * Otherwise, raise a ValueError. On Windows, return status shifted right by 8 bits. On Unix, if the process is being traced or if waitpid() was called with WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true. This function must not be called if WIFSTOPPED(status) is true. [clinic start generated code]*/ static PyObject * os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ { … } #endif #if defined(MS_WINDOWS) /*[clinic input] os._supports_virtual_terminal Checks if virtual terminal is supported in windows [clinic start generated code]*/ static PyObject * os__supports_virtual_terminal_impl(PyObject *module) /*[clinic end generated code: output=bd0556a6d9d99fe6 input=0752c98e5d321542]*/ { DWORD mode = 0; HANDLE handle = GetStdHandle(STD_ERROR_HANDLE); if (!GetConsoleMode(handle, &mode)) { Py_RETURN_FALSE; } return PyBool_FromLong(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING); } #endif /*[clinic input] os._inputhook Calls PyOS_CallInputHook droppong the GIL first [clinic start generated code]*/ static PyObject * os__inputhook_impl(PyObject *module) /*[clinic end generated code: output=525aca4ef3c6149f input=fc531701930d064f]*/ { … } /*[clinic input] os._is_inputhook_installed Checks if PyOS_CallInputHook is set [clinic start generated code]*/ static PyObject * os__is_inputhook_installed_impl(PyObject *module) /*[clinic end generated code: output=3b3eab4f672c689a input=ff177c9938dd76d8]*/ { … } /*[clinic input] os._create_environ Create the environment dictionary. [clinic start generated code]*/ static PyObject * os__create_environ_impl(PyObject *module) /*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/ { … } static PyMethodDef posix_methods[] = …; static int all_ins(PyObject *m) { … } #define PROBE(name, test) … #ifdef HAVE_FSTATAT PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME) #endif #ifdef HAVE_FACCESSAT PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME) #endif #ifdef HAVE_FCHMODAT PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME) #endif #ifdef HAVE_FCHOWNAT PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME) #endif #ifdef HAVE_LINKAT PROBE(probe_linkat, HAVE_LINKAT_RUNTIME) #endif #ifdef HAVE_FDOPENDIR PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME) #endif #ifdef HAVE_MKDIRAT PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) #endif #ifdef HAVE_MKFIFOAT PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME) #endif #ifdef HAVE_MKNODAT PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME) #endif #ifdef HAVE_RENAMEAT PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) #endif #ifdef HAVE_UNLINKAT PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME) #endif #ifdef HAVE_OPENAT PROBE(probe_openat, HAVE_OPENAT_RUNTIME) #endif #ifdef HAVE_READLINKAT PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME) #endif #ifdef HAVE_SYMLINKAT PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME) #endif #ifdef HAVE_FUTIMENS PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME) #endif #ifdef HAVE_UTIMENSAT PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME) #endif #ifdef HAVE_PTSNAME_R PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME) #endif static const struct have_function { … } have_functions[] = …; static int posixmodule_exec(PyObject *m) { … } static PyModuleDef_Slot posixmodile_slots[] = …; static struct PyModuleDef posixmodule = …; PyMODINIT_FUNC INITFUNC(void) { … }