summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c8017
1 files changed, 4323 insertions, 3694 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index d45f59e..7da1ab0 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6,7 +6,7 @@
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. '__BORLANDC__' or '_MSC_VER'. */
+ test macro, e.g. '_MSC_VER'. */
@@ -25,8 +25,11 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "structmember.h"
#ifndef MS_WINDOWS
#include "posixmodule.h"
+#else
+#include "winreparse.h"
#endif
#ifdef __cplusplus
@@ -141,13 +144,6 @@ corresponding Unix manual entries for more information on calls.");
#define HAVE_SYSTEM 1
#include <process.h>
#else
-#ifdef __BORLANDC__ /* Borland compiler */
-#define HAVE_EXECV 1
-#define HAVE_OPENDIR 1
-#define HAVE_PIPE 1
-#define HAVE_SYSTEM 1
-#define HAVE_WAIT 1
-#else
#ifdef _MSC_VER /* Microsoft compiler */
#define HAVE_GETPPID 1
#define HAVE_GETLOGIN 1
@@ -177,14 +173,14 @@ corresponding Unix manual entries for more information on calls.");
#define HAVE_WAIT 1
#define HAVE_TTYNAME 1
#endif /* _MSC_VER */
-#endif /* __BORLANDC__ */
#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=8cff096d1133288f]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
#ifndef _MSC_VER
@@ -211,11 +207,7 @@ extern int rmdir(char *);
extern int chdir(const char *);
extern int rmdir(const char *);
#endif
-#ifdef __BORLANDC__
-extern int chmod(const char *, int);
-#else
extern int chmod(const char *, mode_t);
-#endif
/*#ifdef HAVE_FCHMOD
extern int fchmod(int, mode_t);
#endif*/
@@ -301,6 +293,9 @@ extern int lstat(const char *, struct stat *);
#ifndef IO_REPARSE_TAG_SYMLINK
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
+#ifndef IO_REPARSE_TAG_MOUNT_POINT
+#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
+#endif
#include "osdefs.h"
#include <malloc.h>
#include <windows.h>
@@ -356,8 +351,8 @@ static int win32_can_symlink = 0;
#ifdef MS_WINDOWS
# define STAT win32_stat
# define LSTAT win32_lstat
-# define FSTAT win32_fstat
-# define STRUCT_STAT struct win32_stat
+# define FSTAT _Py_fstat_noraise
+# define STRUCT_STAT struct _Py_stat_struct
#else
# define STAT stat
# define LSTAT lstat
@@ -378,6 +373,20 @@ static int win32_can_symlink = 0;
#define DWORD_MAX 4294967295U
+#ifdef MS_WINDOWS
+#define INITFUNC PyInit_nt
+#define MODNAME "nt"
+#else
+#define INITFUNC PyInit_posix
+#define MODNAME "posix"
+#endif
+
+#ifdef MS_WINDOWS
+/* defined in fileutils.c */
+PyAPI_FUNC(void) _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
+PyAPI_FUNC(void) _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
+ ULONG, struct _Py_stat_struct *);
+#endif
#ifdef MS_WINDOWS
static int
@@ -701,7 +710,6 @@ dir_fd_converter(PyObject *o, void *p)
}
-
/*
* A PyArg_ParseTuple "converter" function
* that handles filesystem paths in the manner
@@ -797,8 +805,8 @@ typedef struct {
PyObject *cleanup;
} path_t;
-#define PATH_T_INITIALIZE(function_name, nullable, allow_fd) \
- {function_name, NULL, nullable, allow_fd, NULL, NULL, 0, 0, NULL, NULL}
+#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
+ {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
static void
path_cleanup(path_t *path) {
@@ -920,8 +928,8 @@ path_converter(PyObject *o, void *p) {
#endif
narrow = PyBytes_AS_STRING(bytes);
- if (length != strlen(narrow)) {
- FORMAT_EXCEPTION(PyExc_ValueError, "embedded NUL character in %s");
+ if ((size_t)length != strlen(narrow)) {
+ FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
Py_DECREF(bytes);
return 0;
}
@@ -1022,97 +1030,46 @@ dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd,
return 0;
}
-/* A helper used by a number of POSIX-only functions */
-#ifndef MS_WINDOWS
+#ifdef MS_WINDOWS
+ typedef PY_LONG_LONG Py_off_t;
+#else
+ typedef off_t Py_off_t;
+#endif
+
static int
-_parse_off_t(PyObject* arg, void* addr)
+Py_off_t_converter(PyObject *arg, void *addr)
{
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- *((off_t*)addr) = PyLong_AsLong(arg);
+#ifdef HAVE_LARGEFILE_SUPPORT
+ *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
#else
- *((off_t*)addr) = PyLong_AsLongLong(arg);
+ *((Py_off_t *)addr) = PyLong_AsLong(arg);
#endif
if (PyErr_Occurred())
return 0;
return 1;
}
+
+static PyObject *
+PyLong_FromPy_off_t(Py_off_t offset)
+{
+#ifdef HAVE_LARGEFILE_SUPPORT
+ return PyLong_FromLongLong(offset);
+#else
+ return PyLong_FromLong(offset);
#endif
+}
-#if defined _MSC_VER && _MSC_VER >= 1400
-/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
- * valid and raise an assertion if it isn't.
- * Normally, an invalid fd is likely to be a C program error and therefore
- * an assertion can be useful, but it does contradict the POSIX standard
- * which for write(2) states:
- * "Otherwise, -1 shall be returned and errno set to indicate the error."
- * "[EBADF] The fildes argument is not a valid file descriptor open for
- * writing."
- * Furthermore, python allows the user to enter any old integer
- * as a fd and should merely raise a python exception on error.
- * The Microsoft CRT doesn't provide an official way to check for the
- * validity of a file descriptor, but we can emulate its internal behaviour
- * by using the exported __pinfo data member and knowledge of the
- * internal structures involved.
- * The structures below must be updated for each version of visual studio
- * according to the file internal.h in the CRT source, until MS comes
- * up with a less hacky way to do this.
- * (all of this is to avoid globally modifying the CRT behaviour using
- * _set_invalid_parameter_handler() and _CrtSetReportMode())
- */
-/* The actual size of the structure is determined at runtime.
- * Only the first items must be present.
- */
-typedef struct {
- intptr_t osfhnd;
- char osfile;
-} my_ioinfo;
-extern __declspec(dllimport) char * __pioinfo[];
+#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900
+/* Legacy implementation of _PyVerify_fd_dup2 while transitioning to
+ * MSVC 14.0. This should eventually be removed. (issue23524)
+ */
#define IOINFO_L2E 5
-#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
#define IOINFO_ARRAYS 64
+#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
-#define FOPEN 0x01
#define _NO_CONSOLE_FILENO (intptr_t)-2
-/* This function emulates what the windows CRT does to validate file handles */
-int
-_PyVerify_fd(int fd)
-{
- const int i1 = fd >> IOINFO_L2E;
- const int i2 = fd & ((1 << IOINFO_L2E) - 1);
-
- static size_t sizeof_ioinfo = 0;
-
- /* Determine the actual size of the ioinfo structure,
- * as used by the CRT loaded in memory
- */
- if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
- sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
- }
- if (sizeof_ioinfo == 0) {
- /* This should not happen... */
- goto fail;
- }
-
- /* See that it isn't a special CLEAR fileno */
- if (fd != _NO_CONSOLE_FILENO) {
- /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
- * we check pointer validity and other info
- */
- if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
- /* finally, check that the file is open */
- my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
- if (info->osfile & FOPEN) {
- return 1;
- }
- }
- }
- fail:
- errno = EBADF;
- return 0;
-}
-
/* the special case of checking dup2. The target fd must be in a sensible range */
static int
_PyVerify_fd_dup2(int fd1, int fd2)
@@ -1127,46 +1084,10 @@ _PyVerify_fd_dup2(int fd1, int fd2)
return 0;
}
#else
-/* dummy version. _PyVerify_fd() is already defined in fileobject.h */
-#define _PyVerify_fd_dup2(A, B) (1)
+#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0)
#endif
#ifdef MS_WINDOWS
-/* The following structure was copied from
- http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
- include doesn't seem to be present in the Windows SDK (at least as included
- with Visual Studio Express). */
-typedef struct _REPARSE_DATA_BUFFER {
- ULONG ReparseTag;
- USHORT ReparseDataLength;
- USHORT Reserved;
- union {
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- ULONG Flags;
- WCHAR PathBuffer[1];
- } SymbolicLinkReparseBuffer;
-
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- WCHAR PathBuffer[1];
- } MountPointReparseBuffer;
-
- struct {
- UCHAR DataBuffer[1];
- } GenericReparseBuffer;
- };
-} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
-
-#define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER,\
- GenericReparseBuffer)
-#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
static int
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
@@ -1351,47 +1272,36 @@ path_error2(path_t *path, path_t *path2)
/* POSIX generic methods */
-static PyObject *
-posix_fildes(PyObject *fdobj, int (*func)(int))
+static int
+fildes_converter(PyObject *o, void *p)
{
int fd;
- int res;
- fd = PyObject_AsFileDescriptor(fdobj);
+ int *pointer = (int *)p;
+ fd = PyObject_AsFileDescriptor(o);
if (fd < 0)
- return NULL;
- if (!_PyVerify_fd(fd))
- return posix_error();
- Py_BEGIN_ALLOW_THREADS
- res = (*func)(fd);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ return 0;
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return 0;
+ }
+ *pointer = fd;
+ return 1;
}
static PyObject *
-posix_1str(const char *func_name, PyObject *args, char *format,
- int (*func)(const char*))
+posix_fildes_fd(int fd, int (*func)(int))
{
- path_t path;
int res;
- memset(&path, 0, sizeof(path));
- path.function_name = func_name;
- if (!PyArg_ParseTuple(args, format,
- path_converter, &path))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = (*func)(path.narrow);
- Py_END_ALLOW_THREADS
- if (res < 0) {
- path_error(&path);
- path_cleanup(&path);
- return NULL;
- }
- path_cleanup(&path);
- Py_INCREF(Py_None);
- return Py_None;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = (*func)(fd);
+ Py_END_ALLOW_THREADS
+ } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res != 0)
+ return (!async_err) ? posix_error() : NULL;
+ Py_RETURN_NONE;
}
@@ -1470,89 +1380,7 @@ win32_wchdir(LPCWSTR path)
Therefore, we implement our own stat, based on the Win32 API directly.
*/
#define HAVE_STAT_NSEC 1
-
-struct win32_stat{
- unsigned long st_dev;
- __int64 st_ino;
- unsigned short st_mode;
- int st_nlink;
- int st_uid;
- int st_gid;
- unsigned long st_rdev;
- __int64 st_size;
- time_t st_atime;
- int st_atime_nsec;
- time_t st_mtime;
- int st_mtime_nsec;
- time_t st_ctime;
- int st_ctime_nsec;
-};
-
-static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
-
-static void
-FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
-{
- /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
- /* Cannot simply cast and dereference in_ptr,
- since it might not be aligned properly */
- __int64 in;
- memcpy(&in, in_ptr, sizeof(in));
- *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
- *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
-}
-
-static void
-time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
-{
- /* XXX endianness */
- __int64 out;
- out = time_in + secs_between_epochs;
- out = out * 10000000 + nsec_in / 100;
- memcpy(out_ptr, &out, sizeof(out));
-}
-
-/* Below, we *know* that ugo+r is 0444 */
-#if _S_IREAD != 0400
-#error Unsupported C library
-#endif
-static int
-attributes_to_mode(DWORD attr)
-{
- int m = 0;
- if (attr & FILE_ATTRIBUTE_DIRECTORY)
- m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
- else
- m |= _S_IFREG;
- if (attr & FILE_ATTRIBUTE_READONLY)
- m |= 0444;
- else
- m |= 0666;
- return m;
-}
-
-static int
-attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct win32_stat *result)
-{
- memset(result, 0, sizeof(*result));
- result->st_mode = attributes_to_mode(info->dwFileAttributes);
- result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
- result->st_dev = info->dwVolumeSerialNumber;
- result->st_rdev = result->st_dev;
- FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
- FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
- FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
- result->st_nlink = info->nNumberOfLinks;
- result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
- if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
- /* first clear the S_IFMT bits */
- result->st_mode ^= (result->st_mode & S_IFMT);
- /* now set the bits that make this a symlink */
- result->st_mode |= S_IFLNK;
- }
-
- return 0;
-}
+#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
static BOOL
attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
@@ -1577,6 +1405,25 @@ attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *rep
return TRUE;
}
+static void
+find_data_to_file_info_w(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_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
{
@@ -1586,45 +1433,10 @@ attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE;
FindClose(hFindFile);
- memset(info, 0, sizeof(*info));
- *reparse_tag = 0;
- info->dwFileAttributes = FileData.dwFileAttributes;
- info->ftCreationTime = FileData.ftCreationTime;
- info->ftLastAccessTime = FileData.ftLastAccessTime;
- info->ftLastWriteTime = FileData.ftLastWriteTime;
- info->nFileSizeHigh = FileData.nFileSizeHigh;
- info->nFileSizeLow = FileData.nFileSizeLow;
-/* info->nNumberOfLinks = 1; */
- if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- *reparse_tag = FileData.dwReserved0;
+ find_data_to_file_info_w(&FileData, info, reparse_tag);
return TRUE;
}
-/* Grab GetFinalPathNameByHandle dynamically from kernel32 */
-static int has_GetFinalPathNameByHandle = -1;
-static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
- DWORD);
-static int
-check_GetFinalPathNameByHandle()
-{
- HINSTANCE hKernel32;
- DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
- DWORD);
-
- /* only recheck */
- if (-1 == has_GetFinalPathNameByHandle)
- {
- hKernel32 = GetModuleHandleW(L"KERNEL32");
- *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
- "GetFinalPathNameByHandleA");
- *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
- "GetFinalPathNameByHandleW");
- has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
- Py_GetFinalPathNameByHandleW;
- }
- return has_GetFinalPathNameByHandle;
-}
-
static BOOL
get_target_path(HANDLE hdl, wchar_t **target_path)
{
@@ -1633,8 +1445,8 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
/* We have a good handle to the target, use it to determine
the target path name (then we'll call lstat on it). */
- buf_size = Py_GetFinalPathNameByHandleW(hdl, 0, 0,
- VOLUME_NAME_DOS);
+ buf_size = GetFinalPathNameByHandleW(hdl, 0, 0,
+ VOLUME_NAME_DOS);
if(!buf_size)
return FALSE;
@@ -1644,7 +1456,7 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
return FALSE;
}
- result_length = Py_GetFinalPathNameByHandleW(hdl,
+ result_length = GetFinalPathNameByHandleW(hdl,
buf, buf_size, VOLUME_NAME_DOS);
if(!result_length) {
@@ -1664,10 +1476,10 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
}
static int
-win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
+win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
BOOL traverse);
static int
-win32_xstat_impl(const char *path, struct win32_stat *result,
+win32_xstat_impl(const char *path, struct _Py_stat_struct *result,
BOOL traverse)
{
int code;
@@ -1677,12 +1489,6 @@ win32_xstat_impl(const char *path, struct win32_stat *result,
wchar_t *target_path;
const char *dot;
- if(!check_GetFinalPathNameByHandle()) {
- /* If the OS doesn't have GetFinalPathNameByHandle, don't
- traverse reparse point. */
- traverse = FALSE;
- }
-
hFile = CreateFileA(
path,
FILE_READ_ATTRIBUTES, /* desired access */
@@ -1750,7 +1556,7 @@ win32_xstat_impl(const char *path, struct win32_stat *result,
} else
CloseHandle(hFile);
}
- attribute_data_to_stat(&info, reparse_tag, result);
+ _Py_attribute_data_to_stat(&info, reparse_tag, result);
/* Set S_IEXEC if it is an .exe, .bat, ... */
dot = strrchr(path, '.');
@@ -1763,7 +1569,7 @@ win32_xstat_impl(const char *path, struct win32_stat *result,
}
static int
-win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
+win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result,
BOOL traverse)
{
int code;
@@ -1773,12 +1579,6 @@ win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
wchar_t *target_path;
const wchar_t *dot;
- if(!check_GetFinalPathNameByHandle()) {
- /* If the OS doesn't have GetFinalPathNameByHandle, don't
- traverse reparse point. */
- traverse = FALSE;
- }
-
hFile = CreateFileW(
path,
FILE_READ_ATTRIBUTES, /* desired access */
@@ -1846,7 +1646,7 @@ win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
} else
CloseHandle(hFile);
}
- attribute_data_to_stat(&info, reparse_tag, result);
+ _Py_attribute_data_to_stat(&info, reparse_tag, result);
/* Set S_IEXEC if it is an .exe, .bat, ... */
dot = wcsrchr(path, '.');
@@ -1859,7 +1659,7 @@ win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
}
static int
-win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
+win32_xstat(const char *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. */
@@ -1869,7 +1669,7 @@ win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
}
static int
-win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
+win32_xstat_w(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. */
@@ -1891,80 +1691,29 @@ win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
The _w represent Unicode equivalents of the aforementioned ANSI functions. */
static int
-win32_lstat(const char* path, struct win32_stat *result)
+win32_lstat(const char* path, struct _Py_stat_struct *result)
{
return win32_xstat(path, result, FALSE);
}
static int
-win32_lstat_w(const wchar_t* path, struct win32_stat *result)
+win32_lstat_w(const wchar_t* path, struct _Py_stat_struct *result)
{
return win32_xstat_w(path, result, FALSE);
}
static int
-win32_stat(const char* path, struct win32_stat *result)
+win32_stat(const char* path, struct _Py_stat_struct *result)
{
return win32_xstat(path, result, TRUE);
}
static int
-win32_stat_w(const wchar_t* path, struct win32_stat *result)
+win32_stat_w(const wchar_t* path, struct _Py_stat_struct *result)
{
return win32_xstat_w(path, result, TRUE);
}
-static int
-win32_fstat(int file_number, struct win32_stat *result)
-{
- BY_HANDLE_FILE_INFORMATION info;
- HANDLE h;
- int type;
-
- if (!_PyVerify_fd(file_number))
- h = INVALID_HANDLE_VALUE;
- else
- h = (HANDLE)_get_osfhandle(file_number);
-
- /* Protocol violation: we explicitly clear errno, instead of
- setting it to a POSIX error. Callers should use GetLastError. */
- errno = 0;
-
- if (h == INVALID_HANDLE_VALUE) {
- /* This is really a C library error (invalid file handle).
- We set the Win32 error to the closes one matching. */
- SetLastError(ERROR_INVALID_HANDLE);
- return -1;
- }
- memset(result, 0, sizeof(*result));
-
- type = GetFileType(h);
- if (type == FILE_TYPE_UNKNOWN) {
- DWORD error = GetLastError();
- if (error != 0) {
- return -1;
- }
- /* else: valid but unknown file */
- }
-
- if (type != FILE_TYPE_DISK) {
- if (type == FILE_TYPE_CHAR)
- result->st_mode = _S_IFCHR;
- else if (type == FILE_TYPE_PIPE)
- result->st_mode = _S_IFIFO;
- return 0;
- }
-
- if (!GetFileInformationByHandle(h, &info)) {
- return -1;
- }
-
- attribute_data_to_stat(&info, 0, result);
- /* specific to fstat() */
- result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
- return 0;
-}
-
#endif /* MS_WINDOWS */
PyDoc_STRVAR(stat_result__doc__,
@@ -2014,6 +1763,9 @@ static PyStructSequence_Field stat_result_fields[] = {
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
{"st_birthtime", "time of creation"},
#endif
+#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
+ {"st_file_attributes", "Windows file attribute bits"},
+#endif
{0}
};
@@ -2053,6 +1805,12 @@ static PyStructSequence_Field stat_result_fields[] = {
#define ST_BIRTHTIME_IDX ST_GEN_IDX
#endif
+#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
+#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
+#else
+#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
+#endif
+
static PyStructSequence_Desc stat_result_desc = {
"stat_result", /* name */
stat_result__doc__, /* doc */
@@ -2154,10 +1912,12 @@ static int _stat_float_times = 1;
PyDoc_STRVAR(stat_float_times__doc__,
"stat_float_times([newval]) -> oldval\n\n\
Determine whether os.[lf]stat represents time stamps as float objects.\n\
-If newval is True, future calls to stat() return floats, if it is False,\n\
-future calls return ints. \n\
-If newval is omitted, return the current setting.\n");
+\n\
+If value is True, future calls to stat() return floats; if it is False,\n\
+future calls return ints.\n\
+If value is omitted, return the current setting.\n");
+/* AC 3.5: the public default value should be None, not ready for that yet */
static PyObject*
stat_float_times(PyObject* self, PyObject *args)
{
@@ -2317,6 +2077,10 @@ _pystat_fromstructstat(STRUCT_STAT *st)
PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
PyLong_FromLong((long)st->st_flags));
#endif
+#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
+ PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
+ PyLong_FromUnsignedLong(st->st_file_attributes));
+#endif
if (PyErr_Occurred()) {
Py_DECREF(v);
@@ -2380,12 +2144,177 @@ posix_do_stat(char *function_name, path_t *path,
return _pystat_fromstructstat(&st);
}
+/*[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 dir_fd_converter
+#else
+ #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_FCHMODAT
+ #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_FCHOWNAT
+ #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
#ifdef HAVE_FSTATAT
- #define OS_STAT_DIR_FD_CONVERTER dir_fd_converter
+ #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
#else
- #define OS_STAT_DIR_FD_CONVERTER dir_fd_unavailable
+ #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
#endif
+#ifdef HAVE_LINKAT
+ #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_MKDIRAT
+ #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_MKFIFOAT
+ #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_MKNODAT
+ #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_OPENAT
+ #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_READLINKAT
+ #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_SYMLINKAT
+ #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_UNLINKAT
+ #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
+#endif
+
+#ifdef HAVE_FCHDIR
+ #define PATH_HAVE_FCHDIR 1
+#else
+ #define PATH_HAVE_FCHDIR 0
+#endif
+
+#ifdef HAVE_FCHMOD
+ #define PATH_HAVE_FCHMOD 1
+#else
+ #define PATH_HAVE_FCHMOD 0
+#endif
+
+#ifdef HAVE_FCHOWN
+ #define PATH_HAVE_FCHOWN 1
+#else
+ #define PATH_HAVE_FCHOWN 0
+#endif
+
+#ifdef HAVE_FDOPENDIR
+ #define PATH_HAVE_FDOPENDIR 1
+#else
+ #define PATH_HAVE_FDOPENDIR 0
+#endif
+
+#ifdef HAVE_FEXECVE
+ #define PATH_HAVE_FEXECVE 1
+#else
+ #define PATH_HAVE_FEXECVE 0
+#endif
+
+#ifdef HAVE_FPATHCONF
+ #define PATH_HAVE_FPATHCONF 1
+#else
+ #define PATH_HAVE_FPATHCONF 0
+#endif
+
+#ifdef HAVE_FSTATVFS
+ #define PATH_HAVE_FSTATVFS 1
+#else
+ #define PATH_HAVE_FSTATVFS 0
+#endif
+
+#ifdef HAVE_FTRUNCATE
+ #define PATH_HAVE_FTRUNCATE 1
+#else
+ #define PATH_HAVE_FTRUNCATE 0
+#endif
+/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
+
/*[python input]
@@ -2400,22 +2329,25 @@ class path_t_converter(CConverter):
def converter_init(self, *, allow_fd=False, nullable=False):
# right now path_t doesn't support default values.
# to support a default value, you'll need to override initialize().
- if self.default is not unspecified:
+ if self.default not in (unspecified, None):
fail("Can't specify a default to the path_t converter!")
- if self.c_default is not None:
- fail("Can't specify a c_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.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
- self.c_default = 'PATH_T_INITIALIZE("{}", {}, {})'.format(
+ self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
self.function.name,
+ self.name,
strify(self.nullable),
strify(self.allow_fd),
)
@@ -2426,15 +2358,87 @@ class path_t_converter(CConverter):
class dir_fd_converter(CConverter):
type = 'int'
- converter = 'OS_STAT_DIR_FD_CONVERTER'
- def converter_init(self):
+ 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 fildes_converter(CConverter):
+ type = 'int'
+ converter = 'fildes_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 "'
+class idtype_t_converter(int_converter):
+ type = 'idtype_t'
+
+class id_t_converter(CConverter):
+ type = 'id_t'
+ format_unit = '" _Py_PARSE_PID "'
+
+class Py_intptr_t_converter(CConverter):
+ type = 'Py_intptr_t'
+ format_unit = '" _Py_PARSE_INTPTR "'
+
+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 path_confname_converter(CConverter):
+ type="int"
+ converter="conv_path_confname"
+
+class confstr_confname_converter(path_confname_converter):
+ converter='conv_confstr_confname'
+
+class sysconf_confname_converter(path_confname_converter):
+ converter="conv_sysconf_confname"
+
+class sched_param_converter(CConverter):
+ type = 'struct sched_param'
+ converter = 'convert_sched_param'
+ impl_by_reference = True;
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=5c9f456f53244fc3]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=affe68316f160401]*/
/*[clinic input]
@@ -2445,7 +2449,7 @@ os.stat
*
- dir_fd : dir_fd = None
+ 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.
@@ -2466,103 +2470,40 @@ It's an error to use dir_fd or follow_symlinks when specifying path as
[clinic start generated code]*/
-PyDoc_STRVAR(os_stat__doc__,
-"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n"
-"--\n"
-"\n"
-"Perform a stat system call on the given path.\n"
-"\n"
-" path\n"
-" Path to be examined; can be string, bytes, or open-file-descriptor int.\n"
-" dir_fd\n"
-" If not None, it should be a file descriptor open to a directory,\n"
-" and path should be a relative string; path will then be relative to\n"
-" that directory.\n"
-" follow_symlinks\n"
-" If False, and the last element of the path is a symbolic link,\n"
-" stat will examine the symbolic link itself instead of the file\n"
-" the link points to.\n"
-"\n"
-"dir_fd and follow_symlinks may not be implemented\n"
-" on your platform. If they are unavailable, using them will raise a\n"
-" NotImplementedError.\n"
-"\n"
-"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n"
-" an open file descriptor.");
-
-#define OS_STAT_METHODDEF \
- {"stat", (PyCFunction)os_stat, METH_VARARGS|METH_KEYWORDS, os_stat__doc__},
-
static PyObject *
-os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks);
-
-static PyObject *
-os_stat(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks)
+/*[clinic end generated code: output=708c225f94fcfc8e input=099d356c306fa24a]*/
{
- PyObject *return_value = NULL;
- static char *_keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
- path_t path = PATH_T_INITIALIZE("stat", 0, 1);
- int dir_fd = DEFAULT_DIR_FD;
- int follow_symlinks = 1;
+ return posix_do_stat("stat", path, dir_fd, follow_symlinks);
+}
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O&|$O&p:stat", _keywords,
- path_converter, &path, OS_STAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks))
- goto exit;
- return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks);
-exit:
- /* Cleanup for path */
- path_cleanup(&path);
+/*[clinic input]
+os.lstat
- return return_value;
-}
+ path : path_t
-static PyObject *
-os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks)
-/*[clinic end generated code: output=f1dcaa5e24db9882 input=5ae155bd475fd20a]*/
-{
- return posix_do_stat("stat", path, dir_fd, follow_symlinks);
-}
+ *
-PyDoc_STRVAR(posix_lstat__doc__,
-"lstat(path, *, dir_fd=None) -> stat result\n\n\
-Like stat(), but do not follow symbolic links.\n\
-Equivalent to stat(path, follow_symlinks=False).");
+ 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 *
-posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs)
+os_lstat_impl(PyModuleDef *module, path_t *path, int dir_fd)
+/*[clinic end generated code: output=7a748e333fcb39bd input=0b7474765927b925]*/
{
- static char *keywords[] = {"path", "dir_fd", NULL};
- path_t path;
- int dir_fd = DEFAULT_DIR_FD;
int follow_symlinks = 0;
- PyObject *return_value;
-
- memset(&path, 0, sizeof(path));
- path.function_name = "lstat";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", keywords,
- path_converter, &path,
-#ifdef HAVE_FSTATAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
- return_value = posix_do_stat("lstat", &path, dir_fd, follow_symlinks);
- path_cleanup(&path);
- return return_value;
+ return posix_do_stat("lstat", path, dir_fd, follow_symlinks);
}
-#ifdef HAVE_FACCESSAT
- #define OS_ACCESS_DIR_FD_CONVERTER dir_fd_converter
-#else
- #define OS_ACCESS_DIR_FD_CONVERTER dir_fd_unavailable
-#endif
/*[clinic input]
-os.access
+os.access -> bool
path: path_t(allow_fd=True)
Path to be tested; can be string, bytes, or open-file-descriptor int.
@@ -2573,7 +2514,7 @@ os.access
*
- dir_fd : dir_fd = None
+ 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.
@@ -2600,73 +2541,11 @@ Note that most operations will use the effective uid/gid, therefore this
[clinic start generated code]*/
-PyDoc_STRVAR(os_access__doc__,
-"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n"
-" follow_symlinks=True)\n"
-"--\n"
-"\n"
-"Use the real uid/gid to test for access to a path.\n"
-"\n"
-" path\n"
-" Path to be tested; can be string, bytes, or open-file-descriptor int.\n"
-" mode\n"
-" Operating-system mode bitfield. Can be F_OK to test existence,\n"
-" or the inclusive-OR of R_OK, W_OK, and X_OK.\n"
-" dir_fd\n"
-" If not None, it should be a file descriptor open to a directory,\n"
-" and path should be relative; path will then be relative to that\n"
-" directory.\n"
-" effective_ids\n"
-" If True, access will use the effective uid/gid instead of\n"
-" the real uid/gid.\n"
-" follow_symlinks\n"
-" If False, and the last element of the path is a symbolic link,\n"
-" access will examine the symbolic link itself instead of the file\n"
-" the link points to.\n"
-"\n"
-"dir_fd, effective_ids, and follow_symlinks may not be implemented\n"
-" on your platform. If they are unavailable, using them will raise a\n"
-" NotImplementedError.\n"
-"\n"
-"Note that most operations will use the effective uid/gid, therefore this\n"
-" routine can be used in a suid/sgid environment to test if the invoking user\n"
-" has the specified access to the path.");
-
-#define OS_ACCESS_METHODDEF \
- {"access", (PyCFunction)os_access, METH_VARARGS|METH_KEYWORDS, os_access__doc__},
-
-static PyObject *
-os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks);
-
-static PyObject *
-os_access(PyModuleDef *module, PyObject *args, PyObject *kwargs)
-{
- PyObject *return_value = NULL;
- static char *_keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL};
- path_t path = PATH_T_INITIALIZE("access", 0, 1);
- int mode;
- int dir_fd = DEFAULT_DIR_FD;
- int effective_ids = 0;
- int follow_symlinks = 1;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O&i|$O&pp:access", _keywords,
- path_converter, &path, &mode, OS_STAT_DIR_FD_CONVERTER, &dir_fd, &effective_ids, &follow_symlinks))
- goto exit;
- return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks);
-
-exit:
- /* Cleanup for path */
- path_cleanup(&path);
-
- return return_value;
-}
-
-static PyObject *
+static int
os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks)
-/*[clinic end generated code: output=a6ed4f151be9df0f input=2e2e7594371f5b7e]*/
+/*[clinic end generated code: output=f9e734db3d88b767 input=b75a756797af45ec]*/
{
- PyObject *return_value = NULL;
+ int return_value;
#ifdef MS_WINDOWS
DWORD attr;
@@ -2676,11 +2555,11 @@ os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effe
#ifndef HAVE_FACCESSAT
if (follow_symlinks_specified("access", follow_symlinks))
- goto exit;
+ return -1;
if (effective_ids) {
argument_unavailable_error("access", "effective_ids");
- goto exit;
+ return -1;
}
#endif
@@ -2700,11 +2579,10 @@ os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effe
* * or it's a directory.
* (Directories cannot be read-only on Windows.)
*/
- return_value = PyBool_FromLong(
- (attr != INVALID_FILE_ATTRIBUTES) &&
+ return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
(!(mode & 2) ||
!(attr & FILE_ATTRIBUTE_READONLY) ||
- (attr & FILE_ATTRIBUTE_DIRECTORY)));
+ (attr & FILE_ATTRIBUTE_DIRECTORY));
#else
Py_BEGIN_ALLOW_THREADS
@@ -2723,12 +2601,9 @@ os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effe
#endif
result = access(path->narrow, mode);
Py_END_ALLOW_THREADS
- return_value = PyBool_FromLong(!result);
+ return_value = !result;
#endif
-#ifndef HAVE_FACCESSAT
-exit:
-#endif
return return_value;
}
@@ -2747,7 +2622,6 @@ exit:
#ifdef HAVE_TTYNAME
-
/*[clinic input]
os.ttyname -> DecodeFSDefault
@@ -2759,44 +2633,9 @@ os.ttyname -> DecodeFSDefault
Return the name of the terminal device connected to 'fd'.
[clinic start generated code]*/
-PyDoc_STRVAR(os_ttyname__doc__,
-"ttyname($module, fd, /)\n"
-"--\n"
-"\n"
-"Return the name of the terminal device connected to \'fd\'.\n"
-"\n"
-" fd\n"
-" Integer file descriptor handle.");
-
-#define OS_TTYNAME_METHODDEF \
- {"ttyname", (PyCFunction)os_ttyname, METH_VARARGS, os_ttyname__doc__},
-
-static char *
-os_ttyname_impl(PyModuleDef *module, int fd);
-
-static PyObject *
-os_ttyname(PyModuleDef *module, PyObject *args)
-{
- PyObject *return_value = NULL;
- int fd;
- char *_return_value;
-
- if (!PyArg_ParseTuple(args,
- "i:ttyname",
- &fd))
- goto exit;
- _return_value = os_ttyname_impl(module, fd);
- if (_return_value == NULL)
- goto exit;
- return_value = PyUnicode_DecodeFSDefault(_return_value);
-
-exit:
- return return_value;
-}
-
static char *
os_ttyname_impl(PyModuleDef *module, int fd)
-/*[clinic end generated code: output=cee7bc4cffec01a2 input=5f72ca83e76b3b45]*/
+/*[clinic end generated code: output=03ad3d5ccaef75c3 input=5f72ca83e76b3b45]*/
{
char *ret;
@@ -2805,17 +2644,18 @@ os_ttyname_impl(PyModuleDef *module, int fd)
posix_error();
return ret;
}
-#else
-#define OS_TTYNAME_METHODDEF
#endif
#ifdef HAVE_CTERMID
-PyDoc_STRVAR(posix_ctermid__doc__,
-"ctermid() -> string\n\n\
-Return the name of the controlling terminal for this process.");
+/*[clinic input]
+os.ctermid
+
+Return the name of the controlling terminal for this process.
+[clinic start generated code]*/
static PyObject *
-posix_ctermid(PyObject *self, PyObject *noargs)
+os_ctermid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=1b73788201e0aebd input=3b87fdd52556382d]*/
{
char *ret;
char buffer[L_ctermid];
@@ -2829,106 +2669,111 @@ posix_ctermid(PyObject *self, PyObject *noargs)
return posix_error();
return PyUnicode_DecodeFSDefault(buffer);
}
-#endif
+#endif /* HAVE_CTERMID */
-PyDoc_STRVAR(posix_chdir__doc__,
-"chdir(path)\n\n\
-Change the current working directory to the specified path.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
+
+/*[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 *
-posix_chdir(PyObject *self, PyObject *args, PyObject *kwargs)
+os_chdir_impl(PyModuleDef *module, path_t *path)
+/*[clinic end generated code: output=7358e3a20fb5aa93 input=1a4a15b4d12cb15d]*/
{
- path_t path;
int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", NULL};
-
- memset(&path, 0, sizeof(path));
- path.function_name = "chdir";
-#ifdef HAVE_FCHDIR
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", keywords,
- path_converter, &path
- ))
- return NULL;
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path.wide)
- result = win32_wchdir(path.wide);
+ if (path->wide)
+ result = win32_wchdir(path->wide);
else
- result = win32_chdir(path.narrow);
+ result = win32_chdir(path->narrow);
result = !result; /* on unix, success = 0, on windows, success = !0 */
#else
#ifdef HAVE_FCHDIR
- if (path.fd != -1)
- result = fchdir(path.fd);
+ if (path->fd != -1)
+ result = fchdir(path->fd);
else
#endif
- result = chdir(path.narrow);
+ result = chdir(path->narrow);
#endif
Py_END_ALLOW_THREADS
if (result) {
- return_value = path_error(&path);
- goto exit;
+ return path_error(path);
}
- return_value = Py_None;
- Py_INCREF(Py_None);
-
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
+
#ifdef HAVE_FCHDIR
-PyDoc_STRVAR(posix_fchdir__doc__,
-"fchdir(fd)\n\n\
-Change to the directory of the given file descriptor. fd must be\n\
-opened on a directory, not a file. Equivalent to os.chdir(fd).");
+/*[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 *
-posix_fchdir(PyObject *self, PyObject *fdobj)
+os_fchdir_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=361d30df6b2d3418 input=18e816479a2fa985]*/
{
- return posix_fildes(fdobj, fchdir);
+ return posix_fildes_fd(fd, fchdir);
}
#endif /* HAVE_FCHDIR */
-PyDoc_STRVAR(posix_chmod__doc__,
-"chmod(path, mode, *, dir_fd=None, follow_symlinks=True)\n\n\
-Change the access permissions of a file.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, chmod will modify the symbolic link itself instead of the file the\n\
- link points to.\n\
-It is an error to use dir_fd or follow_symlinks when specifying path as\n\
- an open file descriptor.\n\
-dir_fd and follow_symlinks may not be implemented on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+/*[clinic input]
+os.chmod
+
+ path: path_t(allow_fd='PATH_HAVE_FCHMOD')
+ Path to be modified. May always be specified as a str or bytes.
+ 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.
+
+ *
+
+ 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 = True
+ 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 *
-posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
+os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int follow_symlinks)
+/*[clinic end generated code: output=96063c976f23106a input=7f1618e5e15cc196]*/
{
- path_t path;
- int mode;
- int dir_fd = DEFAULT_DIR_FD;
- int follow_symlinks = 1;
int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "mode", "dir_fd",
- "follow_symlinks", NULL};
#ifdef MS_WINDOWS
DWORD attr;
@@ -2938,33 +2783,17 @@ posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
int fchmodat_nofollow_unsupported = 0;
#endif
- memset(&path, 0, sizeof(path));
- path.function_name = "chmod";
-#ifdef HAVE_FCHMOD
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", keywords,
- path_converter, &path,
- &mode,
-#ifdef HAVE_FCHMODAT
- dir_fd_converter, &dir_fd,
-#else
- dir_fd_unavailable, &dir_fd,
-#endif
- &follow_symlinks))
- return NULL;
-
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
if (follow_symlinks_specified("chmod", follow_symlinks))
- goto exit;
+ return NULL;
#endif
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path.wide)
- attr = GetFileAttributesW(path.wide);
+ if (path->wide)
+ attr = GetFileAttributesW(path->wide);
else
- attr = GetFileAttributesA(path.narrow);
+ attr = GetFileAttributesA(path->narrow);
if (attr == INVALID_FILE_ATTRIBUTES)
result = 0;
else {
@@ -2972,27 +2801,26 @@ posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
attr &= ~FILE_ATTRIBUTE_READONLY;
else
attr |= FILE_ATTRIBUTE_READONLY;
- if (path.wide)
- result = SetFileAttributesW(path.wide, attr);
+ if (path->wide)
+ result = SetFileAttributesW(path->wide, attr);
else
- result = SetFileAttributesA(path.narrow, attr);
+ result = SetFileAttributesA(path->narrow, attr);
}
Py_END_ALLOW_THREADS
if (!result) {
- return_value = path_error(&path);
- goto exit;
+ return path_error(path);
}
#else /* MS_WINDOWS */
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FCHMOD
- if (path.fd != -1)
- result = fchmod(path.fd, mode);
+ if (path->fd != -1)
+ result = fchmod(path->fd, mode);
else
#endif
#ifdef HAVE_LCHMOD
if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
- result = lchmod(path.narrow, mode);
+ result = lchmod(path->narrow, mode);
else
#endif
#ifdef HAVE_FCHMODAT
@@ -3007,7 +2835,7 @@ posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
* support dir_fd and follow_symlinks=False. (Hopefully.)
* Until then, we need to be careful what exception we raise.
*/
- result = fchmodat(dir_fd, path.narrow, mode,
+ result = fchmodat(dir_fd, path->narrow, mode,
follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
/*
* But wait! We can't throw the exception without allowing threads,
@@ -3020,7 +2848,7 @@ posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
}
else
#endif
- result = chmod(path.narrow, mode);
+ result = chmod(path->narrow, mode);
Py_END_ALLOW_THREADS
if (result) {
@@ -3034,272 +2862,287 @@ posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
}
else
#endif
- return_value = path_error(&path);
- goto exit;
+ return path_error(path);
}
#endif
- Py_INCREF(Py_None);
- return_value = Py_None;
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
#ifdef HAVE_FCHMOD
-PyDoc_STRVAR(posix_fchmod__doc__,
-"fchmod(fd, mode)\n\n\
-Change the access permissions of the file given by file\n\
-descriptor fd. Equivalent to os.chmod(fd, mode).");
+/*[clinic input]
+os.fchmod
+
+ fd: int
+ mode: int
+
+Change the access permissions of the file given by file descriptor fd.
+
+Equivalent to os.chmod(fd, mode).
+[clinic start generated code]*/
static PyObject *
-posix_fchmod(PyObject *self, PyObject *args)
+os_fchmod_impl(PyModuleDef *module, int fd, int mode)
+/*[clinic end generated code: output=2ee31ca226d1ed33 input=8ab11975ca01ee5b]*/
{
- int fd, mode, res;
- if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = fchmod(fd, mode);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+ int res;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = fchmod(fd, mode);
+ Py_END_ALLOW_THREADS
+ } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res != 0)
+ return (!async_err) ? posix_error() : NULL;
+
Py_RETURN_NONE;
}
#endif /* HAVE_FCHMOD */
+
#ifdef HAVE_LCHMOD
-PyDoc_STRVAR(posix_lchmod__doc__,
-"lchmod(path, mode)\n\n\
-Change the access permissions of a file. If path is a symlink, this\n\
-affects the link itself rather than the target.\n\
-Equivalent to chmod(path, mode, follow_symlinks=False).");
+/*[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 *
-posix_lchmod(PyObject *self, PyObject *args)
+os_lchmod_impl(PyModuleDef *module, path_t *path, int mode)
+/*[clinic end generated code: output=7c0cc46588d89e46 input=90c5663c7465d24f]*/
{
- path_t path;
- int i;
int res;
- memset(&path, 0, sizeof(path));
- path.function_name = "lchmod";
- if (!PyArg_ParseTuple(args, "O&i:lchmod",
- path_converter, &path, &i))
- return NULL;
Py_BEGIN_ALLOW_THREADS
- res = lchmod(path.narrow, i);
+ res = lchmod(path->narrow, mode);
Py_END_ALLOW_THREADS
if (res < 0) {
- path_error(&path);
- path_cleanup(&path);
+ path_error(path);
return NULL;
}
- path_cleanup(&path);
Py_RETURN_NONE;
}
#endif /* HAVE_LCHMOD */
#ifdef HAVE_CHFLAGS
-PyDoc_STRVAR(posix_chflags__doc__,
-"chflags(path, flags, *, follow_symlinks=True)\n\n\
-Set file flags.\n\
-\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, chflags will change flags on the symbolic link itself instead of the\n\
- file the link points to.\n\
-follow_symlinks may not be implemented on your platform. If it is\n\
-unavailable, using it will raise a NotImplementedError.");
+/*[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 *
-posix_chflags(PyObject *self, PyObject *args, PyObject *kwargs)
+os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, int follow_symlinks)
+/*[clinic end generated code: output=9e5f9417afc20c4b input=0327e29feb876236]*/
{
- path_t path;
- unsigned long flags;
- int follow_symlinks = 1;
int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "flags", "follow_symlinks", NULL};
-
- memset(&path, 0, sizeof(path));
- path.function_name = "chflags";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|$i:chflags", keywords,
- path_converter, &path,
- &flags, &follow_symlinks))
- return NULL;
#ifndef HAVE_LCHFLAGS
if (follow_symlinks_specified("chflags", follow_symlinks))
- goto exit;
+ return NULL;
#endif
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_LCHFLAGS
if (!follow_symlinks)
- result = lchflags(path.narrow, flags);
+ result = lchflags(path->narrow, flags);
else
#endif
- result = chflags(path.narrow, flags);
+ result = chflags(path->narrow, flags);
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error(&path);
- goto exit;
- }
-
- return_value = Py_None;
- Py_INCREF(Py_None);
+ if (result)
+ return path_error(path);
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
#endif /* HAVE_CHFLAGS */
+
#ifdef HAVE_LCHFLAGS
-PyDoc_STRVAR(posix_lchflags__doc__,
-"lchflags(path, flags)\n\n\
-Set file flags.\n\
-This function will not follow symbolic links.\n\
-Equivalent to chflags(path, flags, follow_symlinks=False).");
+/*[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 *
-posix_lchflags(PyObject *self, PyObject *args)
+os_lchflags_impl(PyModuleDef *module, path_t *path, unsigned long flags)
+/*[clinic end generated code: output=6741322fb949661b input=f9f82ea8b585ca9d]*/
{
- path_t path;
- unsigned long flags;
int res;
- memset(&path, 0, sizeof(path));
- path.function_name = "lchflags";
- if (!PyArg_ParseTuple(args, "O&k:lchflags",
- path_converter, &path, &flags))
- return NULL;
Py_BEGIN_ALLOW_THREADS
- res = lchflags(path.narrow, flags);
+ res = lchflags(path->narrow, flags);
Py_END_ALLOW_THREADS
if (res < 0) {
- path_error(&path);
- path_cleanup(&path);
- return NULL;
+ return path_error(path);
}
- path_cleanup(&path);
Py_RETURN_NONE;
}
#endif /* HAVE_LCHFLAGS */
+
#ifdef HAVE_CHROOT
-PyDoc_STRVAR(posix_chroot__doc__,
-"chroot(path)\n\n\
-Change root directory to path.");
+/*[clinic input]
+os.chroot
+ path: path_t
+
+Change root directory to path.
+
+[clinic start generated code]*/
static PyObject *
-posix_chroot(PyObject *self, PyObject *args)
+os_chroot_impl(PyModuleDef *module, path_t *path)
+/*[clinic end generated code: output=b6dbfabe74ecaa9d input=14822965652c3dc3]*/
{
- return posix_1str("chroot", args, "O&:chroot", chroot);
+ int res;
+ Py_BEGIN_ALLOW_THREADS
+ res = chroot(path->narrow);
+ Py_END_ALLOW_THREADS
+ if (res < 0)
+ return path_error(path);
+ Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_CHROOT */
+
#ifdef HAVE_FSYNC
-PyDoc_STRVAR(posix_fsync__doc__,
-"fsync(fildes)\n\n\
-force write of file with filedescriptor to disk.");
+/*[clinic input]
+os.fsync
+
+ fd: fildes
+
+Force write of fd to disk.
+[clinic start generated code]*/
static PyObject *
-posix_fsync(PyObject *self, PyObject *fdobj)
+os_fsync_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=83a350851064aea7 input=21c3645c056967f2]*/
{
- return posix_fildes(fdobj, fsync);
+ return posix_fildes_fd(fd, fsync);
}
#endif /* HAVE_FSYNC */
+
#ifdef HAVE_SYNC
-PyDoc_STRVAR(posix_sync__doc__,
-"sync()\n\n\
-Force write of everything to disk.");
+/*[clinic input]
+os.sync
+
+Force write of everything to disk.
+[clinic start generated code]*/
static PyObject *
-posix_sync(PyObject *self, PyObject *noargs)
+os_sync_impl(PyModuleDef *module)
+/*[clinic end generated code: output=ba524f656c201c40 input=84749fe5e9b404ff]*/
{
Py_BEGIN_ALLOW_THREADS
sync();
Py_END_ALLOW_THREADS
Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_SYNC */
-#ifdef HAVE_FDATASYNC
+#ifdef HAVE_FDATASYNC
#ifdef __hpux
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
#endif
-PyDoc_STRVAR(posix_fdatasync__doc__,
-"fdatasync(fildes)\n\n\
-force write of file with filedescriptor to disk.\n\
- does not force update of metadata.");
+/*[clinic input]
+os.fdatasync
+
+ fd: fildes
+
+Force write of fd to disk without forcing update of metadata.
+[clinic start generated code]*/
static PyObject *
-posix_fdatasync(PyObject *self, PyObject *fdobj)
+os_fdatasync_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=e0f04a3aff515b75 input=bc74791ee54dd291]*/
{
- return posix_fildes(fdobj, fdatasync);
+ return posix_fildes_fd(fd, fdatasync);
}
#endif /* HAVE_FDATASYNC */
#ifdef HAVE_CHOWN
-PyDoc_STRVAR(posix_chown__doc__,
-"chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n\n\
-Change the owner and group id of path to the numeric uid and gid.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, chown will modify the symbolic link itself instead of the file the\n\
- link points to.\n\
-It is an error to use dir_fd or follow_symlinks when specifying path as\n\
- an open file descriptor.\n\
-dir_fd and follow_symlinks may not be implemented on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+/*[clinic input]
+os.chown
+
+ path : path_t(allow_fd='PATH_HAVE_FCHOWN')
+ Path to be examined; can be string, bytes, 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 *
-posix_chown(PyObject *self, PyObject *args, PyObject *kwargs)
+os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks)
+/*[clinic end generated code: output=59a8db91897fb46c input=a61cc35574814d5d]*/
{
- path_t path;
- uid_t uid;
- gid_t gid;
- int dir_fd = DEFAULT_DIR_FD;
- int follow_symlinks = 1;
int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "uid", "gid", "dir_fd",
- "follow_symlinks", NULL};
-
- memset(&path, 0, sizeof(path));
- path.function_name = "chown";
-#ifdef HAVE_FCHOWN
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&O&|$O&p:chown", keywords,
- path_converter, &path,
- _Py_Uid_Converter, &uid,
- _Py_Gid_Converter, &gid,
-#ifdef HAVE_FCHOWNAT
- dir_fd_converter, &dir_fd,
-#else
- dir_fd_unavailable, &dir_fd,
-#endif
- &follow_symlinks))
- return NULL;
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
if (follow_symlinks_specified("chown", follow_symlinks))
- goto exit;
+ return NULL;
#endif
- if (dir_fd_and_fd_invalid("chown", dir_fd, path.fd) ||
- fd_and_follow_symlinks_invalid("chown", path.fd, follow_symlinks))
- goto exit;
+ if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
+ fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
+ return NULL;
#ifdef __APPLE__
/*
@@ -3310,102 +3153,98 @@ posix_chown(PyObject *self, PyObject *args, PyObject *kwargs)
*/
if ((!follow_symlinks) && (lchown == NULL)) {
follow_symlinks_specified("chown", follow_symlinks);
- goto exit;
+ return NULL;
}
#endif
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FCHOWN
- if (path.fd != -1)
- result = fchown(path.fd, uid, gid);
+ if (path->fd != -1)
+ result = fchown(path->fd, uid, gid);
else
#endif
#ifdef HAVE_LCHOWN
if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
- result = lchown(path.narrow, uid, gid);
+ result = lchown(path->narrow, uid, gid);
else
#endif
#ifdef HAVE_FCHOWNAT
if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
- result = fchownat(dir_fd, path.narrow, uid, gid,
+ result = fchownat(dir_fd, path->narrow, uid, gid,
follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
else
#endif
- result = chown(path.narrow, uid, gid);
+ result = chown(path->narrow, uid, gid);
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error(&path);
- goto exit;
- }
-
- return_value = Py_None;
- Py_INCREF(Py_None);
+ if (result)
+ return path_error(path);
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
#endif /* HAVE_CHOWN */
+
#ifdef HAVE_FCHOWN
-PyDoc_STRVAR(posix_fchown__doc__,
-"fchown(fd, uid, gid)\n\n\
-Change the owner and group id of the file given by file descriptor\n\
-fd to the numeric uid and gid. Equivalent to os.chown(fd, uid, gid).");
+/*[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 *
-posix_fchown(PyObject *self, PyObject *args)
+os_fchown_impl(PyModuleDef *module, int fd, uid_t uid, gid_t gid)
+/*[clinic end generated code: output=7545abf8f6086d76 input=3af544ba1b13a0d7]*/
{
- int fd;
- uid_t uid;
- gid_t gid;
int res;
- if (!PyArg_ParseTuple(args, "iO&O&:fchown", &fd,
- _Py_Uid_Converter, &uid,
- _Py_Gid_Converter, &gid))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = fchown(fd, uid, gid);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = fchown(fd, uid, gid);
+ Py_END_ALLOW_THREADS
+ } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res != 0)
+ return (!async_err) ? posix_error() : NULL;
+
Py_RETURN_NONE;
}
#endif /* HAVE_FCHOWN */
+
#ifdef HAVE_LCHOWN
-PyDoc_STRVAR(posix_lchown__doc__,
-"lchown(path, uid, gid)\n\n\
-Change the owner and group id of path to the numeric uid and gid.\n\
-This function will not follow symbolic links.\n\
-Equivalent to os.chown(path, uid, gid, follow_symlinks=False).");
+/*[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 *
-posix_lchown(PyObject *self, PyObject *args)
+os_lchown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid)
+/*[clinic end generated code: output=bb0d2da1579ac275 input=b1c6014d563a7161]*/
{
- path_t path;
- uid_t uid;
- gid_t gid;
int res;
- memset(&path, 0, sizeof(path));
- path.function_name = "lchown";
- if (!PyArg_ParseTuple(args, "O&O&O&:lchown",
- path_converter, &path,
- _Py_Uid_Converter, &uid,
- _Py_Gid_Converter, &gid))
- return NULL;
Py_BEGIN_ALLOW_THREADS
- res = lchown(path.narrow, uid, gid);
+ res = lchown(path->narrow, uid, gid);
Py_END_ALLOW_THREADS
if (res < 0) {
- path_error(&path);
- path_cleanup(&path);
- return NULL;
+ return path_error(path);
}
- path_cleanup(&path);
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* HAVE_LCHOWN */
@@ -3462,148 +3301,124 @@ posix_getcwd(int use_bytes)
return PyUnicode_DecodeFSDefault(buf);
}
-PyDoc_STRVAR(posix_getcwd__doc__,
-"getcwd() -> path\n\n\
-Return a unicode string representing the current working directory.");
+
+/*[clinic input]
+os.getcwd
+
+Return a unicode string representing the current working directory.
+[clinic start generated code]*/
static PyObject *
-posix_getcwd_unicode(PyObject *self)
+os_getcwd_impl(PyModuleDef *module)
+/*[clinic end generated code: output=efe3a8c0121525ea input=f069211bb70e3d39]*/
{
return posix_getcwd(0);
}
-PyDoc_STRVAR(posix_getcwdb__doc__,
-"getcwdb() -> path\n\n\
-Return a bytes string representing the current working directory.");
+
+/*[clinic input]
+os.getcwdb
+
+Return a bytes string representing the current working directory.
+[clinic start generated code]*/
static PyObject *
-posix_getcwd_bytes(PyObject *self)
+os_getcwdb_impl(PyModuleDef *module)
+/*[clinic end generated code: output=7fce42ee4b2a296a input=f6f6a378dad3d9cb]*/
{
return posix_getcwd(1);
}
+
#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
#define HAVE_LINK 1
#endif
#ifdef HAVE_LINK
-PyDoc_STRVAR(posix_link__doc__,
-"link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True)\n\n\
-Create a hard link to a file.\n\
-\n\
-If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
- descriptor open to a directory, and the respective path string (src or dst)\n\
- should be relative; the path will then be relative to that directory.\n\
-If follow_symlinks is False, and the last element of src is a symbolic\n\
- link, link will create a link to the symbolic link itself instead of the\n\
- file the link points to.\n\
-src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n\
- platform. If they are unavailable, using them will raise a\n\
- NotImplementedError.");
-
-static PyObject *
-posix_link(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t src, dst;
- int src_dir_fd = DEFAULT_DIR_FD;
- int dst_dir_fd = DEFAULT_DIR_FD;
- int follow_symlinks = 1;
- PyObject *return_value = NULL;
- static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd",
- "follow_symlinks", NULL};
+/*[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(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks)
+/*[clinic end generated code: output=c0a9ded8111d2a79 input=b0095ebbcbaa7e04]*/
+{
#ifdef MS_WINDOWS
BOOL result;
#else
int result;
#endif
- memset(&src, 0, sizeof(src));
- memset(&dst, 0, sizeof(dst));
- src.function_name = "link";
- dst.function_name = "link";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|O&O&p:link", keywords,
- path_converter, &src,
- path_converter, &dst,
- dir_fd_converter, &src_dir_fd,
- dir_fd_converter, &dst_dir_fd,
- &follow_symlinks))
- return NULL;
-
#ifndef HAVE_LINKAT
if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
- goto exit;
+ return NULL;
}
#endif
- if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
+ if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
PyErr_SetString(PyExc_NotImplementedError,
"link: src and dst must be the same type");
- goto exit;
+ return NULL;
}
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (src.wide)
- result = CreateHardLinkW(dst.wide, src.wide, NULL);
+ if (src->wide)
+ result = CreateHardLinkW(dst->wide, src->wide, NULL);
else
- result = CreateHardLinkA(dst.narrow, src.narrow, NULL);
+ result = CreateHardLinkA(dst->narrow, src->narrow, NULL);
Py_END_ALLOW_THREADS
- if (!result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (!result)
+ return path_error2(src, dst);
#else
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_LINKAT
if ((src_dir_fd != DEFAULT_DIR_FD) ||
(dst_dir_fd != DEFAULT_DIR_FD) ||
(!follow_symlinks))
- result = linkat(src_dir_fd, src.narrow,
- dst_dir_fd, dst.narrow,
+ result = linkat(src_dir_fd, src->narrow,
+ dst_dir_fd, dst->narrow,
follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
else
#endif
- result = link(src.narrow, dst.narrow);
+ result = link(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (result)
+ return path_error2(src, dst);
#endif
- return_value = Py_None;
- Py_INCREF(Py_None);
-
-exit:
- path_cleanup(&src);
- path_cleanup(&dst);
- return return_value;
+ Py_RETURN_NONE;
}
#endif
-
-PyDoc_STRVAR(posix_listdir__doc__,
-"listdir(path='.') -> list_of_filenames\n\n\
-Return a list containing the names of the files in the directory.\n\
-The list is in arbitrary order. It does not include the special\n\
-entries '.' and '..' even if they are present in the directory.\n\
-\n\
-path can be specified as either str or bytes. If path is bytes,\n\
- the filenames returned will also be bytes; in all other circumstances\n\
- the filenames returned will be str.\n\
-On some platforms, path may also be specified as an open file descriptor;\n\
- the file descriptor must refer to a directory.\n\
- If this functionality is unavailable, using it raises NotImplementedError.");
-
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
static PyObject *
_listdir_windows_no_opendir(path_t *path, PyObject *list)
{
- static char *keywords[] = {"path", NULL};
PyObject *v;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
BOOL result;
@@ -3862,38 +3677,42 @@ exit:
} /* end of _posix_listdir */
#endif /* which OS */
-static PyObject *
-posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- PyObject *list = NULL;
- static char *keywords[] = {"path", NULL};
- PyObject *return_value;
- memset(&path, 0, sizeof(path));
- path.function_name = "listdir";
- path.nullable = 1;
-#ifdef HAVE_FDOPENDIR
- path.allow_fd = 1;
- path.fd = -1;
-#endif
+/*[clinic input]
+os.listdir
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", keywords,
- path_converter, &path)) {
- return NULL;
- }
+ 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 or bytes. 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(PyModuleDef *module, path_t *path)
+/*[clinic end generated code: output=1fbe67c1f780c8b7 input=09e300416e3cd729]*/
+{
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
- return_value = _listdir_windows_no_opendir(&path, list);
+ return _listdir_windows_no_opendir(path, NULL);
#else
- return_value = _posix_listdir(&path, list);
+ return _posix_listdir(path, NULL);
#endif
- path_cleanup(&path);
- return return_value;
}
#ifdef MS_WINDOWS
/* A helper function for abspath on win32 */
+/* AC 3.5: probably just convert to using path converter */
static PyObject *
posix__getfullpathname(PyObject *self, PyObject *args)
{
@@ -3949,36 +3768,35 @@ posix__getfullpathname(PyObject *self, PyObject *args)
Py_FileSystemDefaultEncoding, NULL);
}
return PyBytes_FromString(outbuf);
-} /* end of posix__getfullpathname */
+}
+/*[clinic input]
+os._getfinalpathname
+
+ path: unicode
+ /
+
+A helper function for samepath on windows.
+[clinic start generated code]*/
-/* A helper function for samepath on windows */
static PyObject *
-posix__getfinalpathname(PyObject *self, PyObject *args)
+os__getfinalpathname_impl(PyModuleDef *module, PyObject *path)
+/*[clinic end generated code: output=8be81a5f51a34bcf input=71d5e89334891bf4]*/
{
HANDLE hFile;
int buf_size;
wchar_t *target_path;
int result_length;
- PyObject *po, *result;
- wchar_t *path;
+ PyObject *result;
+ wchar_t *path_wchar;
- if (!PyArg_ParseTuple(args, "U|:_getfinalpathname", &po))
- return NULL;
- path = PyUnicode_AsUnicode(po);
- if (path == NULL)
+ path_wchar = PyUnicode_AsUnicode(path);
+ if (path_wchar == NULL)
return NULL;
- if(!check_GetFinalPathNameByHandle()) {
- /* If the OS doesn't have GetFinalPathNameByHandle, return a
- NotImplementedError. */
- return PyErr_Format(PyExc_NotImplementedError,
- "GetFinalPathNameByHandle not available on this platform");
- }
-
hFile = CreateFileW(
- path,
+ path_wchar,
0, /* desired access */
0, /* share mode */
NULL, /* security attributes */
@@ -3988,37 +3806,37 @@ posix__getfinalpathname(PyObject *self, PyObject *args)
NULL);
if(hFile == INVALID_HANDLE_VALUE)
- return win32_error_object("CreateFileW", po);
+ return win32_error_object("CreateFileW", path);
/* We have a good handle to the target, use it to determine the
target path name. */
- buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
+ buf_size = GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
if(!buf_size)
- return win32_error_object("GetFinalPathNameByHandle", po);
+ return win32_error_object("GetFinalPathNameByHandle", path);
target_path = PyMem_New(wchar_t, buf_size+1);
if(!target_path)
return PyErr_NoMemory();
- result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
- buf_size, VOLUME_NAME_DOS);
+ result_length = GetFinalPathNameByHandleW(hFile, target_path,
+ buf_size, VOLUME_NAME_DOS);
if(!result_length)
- return win32_error_object("GetFinalPathNamyByHandle", po);
+ return win32_error_object("GetFinalPathNamyByHandle", path);
if(!CloseHandle(hFile))
- return win32_error_object("CloseHandle", po);
+ return win32_error_object("CloseHandle", path);
target_path[result_length] = 0;
result = PyUnicode_FromWideChar(target_path, result_length);
PyMem_Free(target_path);
return result;
-
-} /* end of posix__getfinalpathname */
+}
PyDoc_STRVAR(posix__isdir__doc__,
"Return true if the pathname refers to an existing directory.");
+/* AC 3.5: convert using path converter */
static PyObject *
posix__isdir(PyObject *self, PyObject *args)
{
@@ -4055,22 +3873,26 @@ check:
Py_RETURN_FALSE;
}
-PyDoc_STRVAR(posix__getvolumepathname__doc__,
-"Return volume mount point of the specified path.");
-/* A helper function for ismount on windows */
+/*[clinic input]
+os._getvolumepathname
+
+ path: unicode
+
+A helper function for ismount on Win32.
+[clinic start generated code]*/
+
static PyObject *
-posix__getvolumepathname(PyObject *self, PyObject *args)
+os__getvolumepathname_impl(PyModuleDef *module, PyObject *path)
+/*[clinic end generated code: output=79a0ba729f956dbe input=7eacadc40acbda6b]*/
{
- PyObject *po, *result;
- wchar_t *path, *mountpath=NULL;
+ PyObject *result;
+ wchar_t *path_wchar, *mountpath=NULL;
size_t buflen;
BOOL ret;
- if (!PyArg_ParseTuple(args, "U|:_getvolumepathname", &po))
- return NULL;
- path = PyUnicode_AsUnicodeAndSize(po, &buflen);
- if (path == NULL)
+ path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen);
+ if (path_wchar == NULL)
return NULL;
buflen += 1;
@@ -4087,12 +3909,12 @@ posix__getvolumepathname(PyObject *self, PyObject *args)
return PyErr_NoMemory();
Py_BEGIN_ALLOW_THREADS
- ret = GetVolumePathNameW(path, mountpath,
+ ret = GetVolumePathNameW(path_wchar, mountpath,
Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
Py_END_ALLOW_THREADS
if (!ret) {
- result = win32_error_object("_getvolumepathname", po);
+ result = win32_error_object("_getvolumepathname", path);
goto exit;
}
result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
@@ -4101,78 +3923,66 @@ exit:
PyMem_Free(mountpath);
return result;
}
-/* end of posix__getvolumepathname */
#endif /* MS_WINDOWS */
-PyDoc_STRVAR(posix_mkdir__doc__,
-"mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
-Create a directory.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.\n\
-\n\
-The mode argument is ignored on Windows.");
+
+/*[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.
+[clinic start generated code]*/
static PyObject *
-posix_mkdir(PyObject *self, PyObject *args, PyObject *kwargs)
+os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd)
+/*[clinic end generated code: output=8bf1f738873ef2c5 input=e965f68377e9b1ce]*/
{
- path_t path;
- int mode = 0777;
- int dir_fd = DEFAULT_DIR_FD;
- static char *keywords[] = {"path", "mode", "dir_fd", NULL};
- PyObject *return_value = NULL;
int result;
- memset(&path, 0, sizeof(path));
- path.function_name = "mkdir";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", keywords,
- path_converter, &path, &mode,
-#ifdef HAVE_MKDIRAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
-
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path.wide)
- result = CreateDirectoryW(path.wide, NULL);
+ if (path->wide)
+ result = CreateDirectoryW(path->wide, NULL);
else
- result = CreateDirectoryA(path.narrow, NULL);
+ result = CreateDirectoryA(path->narrow, NULL);
Py_END_ALLOW_THREADS
- if (!result) {
- return_value = path_error(&path);
- goto exit;
- }
+ if (!result)
+ return path_error(path);
#else
Py_BEGIN_ALLOW_THREADS
#if HAVE_MKDIRAT
if (dir_fd != DEFAULT_DIR_FD)
- result = mkdirat(dir_fd, path.narrow, mode);
+ result = mkdirat(dir_fd, path->narrow, mode);
else
#endif
#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
- result = mkdir(path.narrow);
+ result = mkdir(path->narrow);
#else
- result = mkdir(path.narrow, mode);
+ result = mkdir(path->narrow, mode);
#endif
Py_END_ALLOW_THREADS
- if (result < 0) {
- return_value = path_error(&path);
- goto exit;
- }
+ if (result < 0)
+ return path_error(path);
#endif
- return_value = Py_None;
- Py_INCREF(Py_None);
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
@@ -4183,17 +3993,20 @@ exit:
#ifdef HAVE_NICE
-PyDoc_STRVAR(posix_nice__doc__,
-"nice(inc) -> new_priority\n\n\
-Decrease the priority of process by inc and return the new priority.");
+/*[clinic input]
+os.nice
+
+ increment: int
+ /
+
+Add increment to the priority of process and return the new priority.
+[clinic start generated code]*/
static PyObject *
-posix_nice(PyObject *self, PyObject *args)
+os_nice_impl(PyModuleDef *module, int increment)
+/*[clinic end generated code: output=8870418a3fc07b51 input=864be2d402a21da2]*/
{
- int increment, value;
-
- if (!PyArg_ParseTuple(args, "i:nice", &increment))
- return NULL;
+ int value;
/* There are two flavours of 'nice': one that returns the new
priority (as required by almost all standards out there) and the
@@ -4220,17 +4033,21 @@ posix_nice(PyObject *self, PyObject *args)
#ifdef HAVE_GETPRIORITY
-PyDoc_STRVAR(posix_getpriority__doc__,
-"getpriority(which, who) -> current_priority\n\n\
-Get program scheduling priority.");
+/*[clinic input]
+os.getpriority
+
+ which: int
+ who: int
+
+Return program scheduling priority.
+[clinic start generated code]*/
static PyObject *
-posix_getpriority(PyObject *self, PyObject *args)
+os_getpriority_impl(PyModuleDef *module, int which, int who)
+/*[clinic end generated code: output=4759937aa5b67ed6 input=9be615d40e2544ef]*/
{
- int which, who, retval;
+ int retval;
- if (!PyArg_ParseTuple(args, "ii", &which, &who))
- return NULL;
errno = 0;
retval = getpriority(which, who);
if (errno != 0)
@@ -4241,18 +4058,23 @@ posix_getpriority(PyObject *self, PyObject *args)
#ifdef HAVE_SETPRIORITY
-PyDoc_STRVAR(posix_setpriority__doc__,
-"setpriority(which, who, prio) -> None\n\n\
-Set program scheduling priority.");
+/*[clinic input]
+os.setpriority
+
+ which: int
+ who: int
+ priority: int
+
+Set program scheduling priority.
+[clinic start generated code]*/
static PyObject *
-posix_setpriority(PyObject *self, PyObject *args)
+os_setpriority_impl(PyModuleDef *module, int which, int who, int priority)
+/*[clinic end generated code: output=6497d3301547e7d5 input=710ccbf65b9dc513]*/
{
- int which, who, prio, retval;
+ int retval;
- if (!PyArg_ParseTuple(args, "iii", &which, &who, &prio))
- return NULL;
- retval = setpriority(which, who, prio);
+ retval = setpriority(which, who, priority);
if (retval == -1)
return posix_error();
Py_RETURN_NONE;
@@ -4261,17 +4083,10 @@ posix_setpriority(PyObject *self, PyObject *args)
static PyObject *
-internal_rename(PyObject *args, PyObject *kwargs, int is_replace)
+internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
{
char *function_name = is_replace ? "replace" : "rename";
- path_t src;
- path_t dst;
- int src_dir_fd = DEFAULT_DIR_FD;
- int dst_dir_fd = DEFAULT_DIR_FD;
int dir_fd_specified;
- PyObject *return_value = NULL;
- char format[24];
- static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
#ifdef MS_WINDOWS
BOOL result;
@@ -4280,210 +4095,198 @@ internal_rename(PyObject *args, PyObject *kwargs, int is_replace)
int result;
#endif
- memset(&src, 0, sizeof(src));
- memset(&dst, 0, sizeof(dst));
- src.function_name = function_name;
- dst.function_name = function_name;
- strcpy(format, "O&O&|$O&O&:");
- strcat(format, function_name);
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, keywords,
- path_converter, &src,
- path_converter, &dst,
- dir_fd_converter, &src_dir_fd,
- dir_fd_converter, &dst_dir_fd))
- return NULL;
-
dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
(dst_dir_fd != DEFAULT_DIR_FD);
#ifndef HAVE_RENAMEAT
if (dir_fd_specified) {
argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
- goto exit;
+ return NULL;
}
#endif
- if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
+ if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
PyErr_Format(PyExc_ValueError,
"%s: src and dst must be the same type", function_name);
- goto exit;
+ return NULL;
}
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (src.wide)
- result = MoveFileExW(src.wide, dst.wide, flags);
+ if (src->wide)
+ result = MoveFileExW(src->wide, dst->wide, flags);
else
- result = MoveFileExA(src.narrow, dst.narrow, flags);
+ result = MoveFileExA(src->narrow, dst->narrow, flags);
Py_END_ALLOW_THREADS
- if (!result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (!result)
+ return path_error2(src, dst);
#else
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_RENAMEAT
if (dir_fd_specified)
- result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow);
+ result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
else
#endif
- result = rename(src.narrow, dst.narrow);
+ result = rename(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (result)
+ return path_error2(src, dst);
#endif
-
- Py_INCREF(Py_None);
- return_value = Py_None;
-exit:
- path_cleanup(&src);
- path_cleanup(&dst);
- return return_value;
+ Py_RETURN_NONE;
}
-PyDoc_STRVAR(posix_rename__doc__,
-"rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
-Rename a file or directory.\n\
-\n\
-If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
- descriptor open to a directory, and the respective path string (src or dst)\n\
- should be relative; the path will then be relative to that directory.\n\
-src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+
+/*[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 *
-posix_rename(PyObject *self, PyObject *args, PyObject *kwargs)
+os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd)
+/*[clinic end generated code: output=1bb520bf2fad186d input=faa61c847912c850]*/
{
- return internal_rename(args, kwargs, 0);
+ return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
}
-PyDoc_STRVAR(posix_replace__doc__,
-"replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
-Rename a file or directory, overwriting the destination.\n\
-\n\
-If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
- descriptor open to a directory, and the respective path string (src or dst)\n\
- should be relative; the path will then be relative to that directory.\n\
-src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+
+/*[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 *
-posix_replace(PyObject *self, PyObject *args, PyObject *kwargs)
+os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd)
+/*[clinic end generated code: output=aa9ddad55fdef8e3 input=25515dfb107c8421]*/
{
- return internal_rename(args, kwargs, 1);
+ return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
}
-PyDoc_STRVAR(posix_rmdir__doc__,
-"rmdir(path, *, dir_fd=None)\n\n\
-Remove a directory.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
+
+/*[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 *
-posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs)
+os_rmdir_impl(PyModuleDef *module, path_t *path, int dir_fd)
+/*[clinic end generated code: output=cabadec80d5a77c7 input=38c8b375ca34a7e2]*/
{
- path_t path;
- int dir_fd = DEFAULT_DIR_FD;
- static char *keywords[] = {"path", "dir_fd", NULL};
int result;
- PyObject *return_value = NULL;
-
- memset(&path, 0, sizeof(path));
- path.function_name = "rmdir";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords,
- path_converter, &path,
-#ifdef HAVE_UNLINKAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path.wide)
- result = RemoveDirectoryW(path.wide);
+ if (path->wide)
+ result = RemoveDirectoryW(path->wide);
else
- result = RemoveDirectoryA(path.narrow);
+ result = RemoveDirectoryA(path->narrow);
result = !result; /* Windows, success=1, UNIX, success=0 */
#else
#ifdef HAVE_UNLINKAT
if (dir_fd != DEFAULT_DIR_FD)
- result = unlinkat(dir_fd, path.narrow, AT_REMOVEDIR);
+ result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
else
#endif
- result = rmdir(path.narrow);
+ result = rmdir(path->narrow);
#endif
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error(&path);
- goto exit;
- }
-
- return_value = Py_None;
- Py_INCREF(Py_None);
+ if (result)
+ return path_error(path);
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
#ifdef HAVE_SYSTEM
-PyDoc_STRVAR(posix_system__doc__,
-"system(command) -> exit_status\n\n\
-Execute the command (a string) in a subshell.");
-
-static PyObject *
-posix_system(PyObject *self, PyObject *args)
-{
- long sts;
#ifdef MS_WINDOWS
- wchar_t *command;
- if (!PyArg_ParseTuple(args, "u:system", &command))
- return NULL;
+/*[clinic input]
+os.system -> long
+
+ command: Py_UNICODE
+Execute the command in a subshell.
+[clinic start generated code]*/
+
+static long
+os_system_impl(PyModuleDef *module, Py_UNICODE *command)
+/*[clinic end generated code: output=4c3bd5abcd9c29e7 input=303f5ce97df606b0]*/
+{
+ long result;
Py_BEGIN_ALLOW_THREADS
- sts = _wsystem(command);
+ result = _wsystem(command);
Py_END_ALLOW_THREADS
-#else
- PyObject *command_obj;
- char *command;
- if (!PyArg_ParseTuple(args, "O&:system",
- PyUnicode_FSConverter, &command_obj))
- return NULL;
+ return result;
+}
+#else /* MS_WINDOWS */
+/*[clinic input]
+os.system -> long
+
+ command: FSConverter
+
+Execute the command in a subshell.
+[clinic start generated code]*/
- command = PyBytes_AsString(command_obj);
+static long
+os_system_impl(PyModuleDef *module, PyObject *command)
+/*[clinic end generated code: output=800f775e10b7be55 input=86a58554ba6094af]*/
+{
+ long result;
+ char *bytes = PyBytes_AsString(command);
Py_BEGIN_ALLOW_THREADS
- sts = system(command);
+ result = system(bytes);
Py_END_ALLOW_THREADS
- Py_DECREF(command_obj);
-#endif
- return PyLong_FromLong(sts);
+ return result;
}
#endif
+#endif /* HAVE_SYSTEM */
+
+
+/*[clinic input]
+os.umask
+ mask: int
+ /
-PyDoc_STRVAR(posix_umask__doc__,
-"umask(new_mask) -> old_mask\n\n\
-Set the current numeric umask and return the previous umask.");
+Set the current numeric umask and return the previous umask.
+[clinic start generated code]*/
static PyObject *
-posix_umask(PyObject *self, PyObject *args)
+os_umask_impl(PyModuleDef *module, int mask)
+/*[clinic end generated code: output=9e1fe3c9f14d6a05 input=ab6bfd9b24d8a7e8]*/
{
- int i;
- if (!PyArg_ParseTuple(args, "i:umask", &i))
- return NULL;
- i = (int)umask(i);
+ int i = (int)umask(mask);
if (i < 0)
return posix_error();
return PyLong_FromLong((long)i);
@@ -4512,7 +4315,10 @@ BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
find_data_handle = FindFirstFileW(lpFileName, &find_data);
if(find_data_handle != INVALID_HANDLE_VALUE) {
- is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
+ /* 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);
}
}
@@ -4525,81 +4331,71 @@ BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
}
#endif /* MS_WINDOWS */
-PyDoc_STRVAR(posix_unlink__doc__,
-"unlink(path, *, dir_fd=None)\n\n\
-Remove a file (same as remove()).\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
-PyDoc_STRVAR(posix_remove__doc__,
-"remove(path, *, dir_fd=None)\n\n\
-Remove a file (same as unlink()).\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
+/*[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 *
-posix_unlink(PyObject *self, PyObject *args, PyObject *kwargs)
+os_unlink_impl(PyModuleDef *module, path_t *path, int dir_fd)
+/*[clinic end generated code: output=474afd5cd09b237e input=d7bcde2b1b2a2552]*/
{
- path_t path;
- int dir_fd = DEFAULT_DIR_FD;
- static char *keywords[] = {"path", "dir_fd", NULL};
int result;
- PyObject *return_value = NULL;
-
- memset(&path, 0, sizeof(path));
- path.function_name = "unlink";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:unlink", keywords,
- path_converter, &path,
-#ifdef HAVE_UNLINKAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path.wide)
- result = Py_DeleteFileW(path.wide);
+ if (path->wide)
+ result = Py_DeleteFileW(path->wide);
else
- result = DeleteFileA(path.narrow);
+ result = DeleteFileA(path->narrow);
result = !result; /* Windows, success=1, UNIX, success=0 */
#else
#ifdef HAVE_UNLINKAT
if (dir_fd != DEFAULT_DIR_FD)
- result = unlinkat(dir_fd, path.narrow, 0);
+ result = unlinkat(dir_fd, path->narrow, 0);
else
#endif /* HAVE_UNLINKAT */
- result = unlink(path.narrow);
+ result = unlink(path->narrow);
#endif
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error(&path);
- goto exit;
- }
-
- return_value = Py_None;
- Py_INCREF(Py_None);
+ if (result)
+ return path_error(path);
-exit:
- path_cleanup(&path);
- return return_value;
+ Py_RETURN_NONE;
}
-PyDoc_STRVAR(posix_uname__doc__,
-"uname() -> uname_result\n\n\
-Return an object identifying the current operating system.\n\
-The object behaves like a named tuple with the following fields:\n\
- (sysname, nodename, release, version, machine)");
+/*[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(PyModuleDef *module, path_t *path, int dir_fd)
+/*[clinic end generated code: output=d0d5149e64832b9e input=e05c5ab55cd30983]*/
+{
+ return os_unlink_impl(module, path, dir_fd);
+}
+
static PyStructSequence_Field uname_result_fields[] = {
{"sysname", "operating system name"},
@@ -4629,8 +4425,19 @@ static PyTypeObject UnameResultType;
#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 *
-posix_uname(PyObject *self, PyObject *noargs)
+os_uname_impl(PyModuleDef *module)
+/*[clinic end generated code: output=01e1421b757e753f input=e68bd246db3043ed]*/
{
struct utsname u;
int res;
@@ -4669,31 +4476,6 @@ posix_uname(PyObject *self, PyObject *noargs)
#endif /* HAVE_UNAME */
-PyDoc_STRVAR(posix_utime__doc__,
-"utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\
-Set the access and modified time of path.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.\n\
-\n\
-If times is not None, it must be a tuple (atime, mtime);\n\
- atime and mtime should be expressed as float seconds since the epoch.\n\
-If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n\
- atime_ns and mtime_ns should be expressed as integer nanoseconds\n\
- since the epoch.\n\
-If both times and ns are None, utime uses the current time.\n\
-Specifying tuples for both times and ns is an error.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, utime will modify the symbolic link itself instead of the file the\n\
- link points to.\n\
-It is an error to use dir_fd or follow_symlinks when specifying path\n\
- as an open file descriptor.\n\
-dir_fd and follow_symlinks may not be available on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
typedef struct {
int now;
@@ -4779,6 +4561,9 @@ utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks)
#endif
}
+ #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
+#else
+ #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
#endif
#define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS))
@@ -4797,6 +4582,9 @@ utime_fd(utime_t *ut, int fd)
#endif
}
+ #define PATH_UTIME_HAVE_FD 1
+#else
+ #define PATH_UTIME_HAVE_FD 0
#endif
@@ -4862,19 +4650,49 @@ exit:
return result;
}
-static PyObject *
-posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- PyObject *times = NULL;
- PyObject *ns = NULL;
- int dir_fd = DEFAULT_DIR_FD;
- int follow_symlinks = 1;
- char *keywords[] = {"path", "times", "ns", "dir_fd",
- "follow_symlinks", NULL};
- utime_t utime;
+/*[clinic input]
+os.utime
+ path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
+ times: object = NULL
+ *
+ ns: object = NULL
+ dir_fd: dir_fd(requires='futimensat') = None
+ follow_symlinks: bool=True
+
+# "utime(path, times=None, *, ns=None, 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 not None, it must be a tuple (atime_ns, mtime_ns);
+ atime_ns and mtime_ns should be expressed as integer nanoseconds
+ since the epoch.
+If both times and ns are None, 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(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks)
+/*[clinic end generated code: output=c52d8fd0d1067f0b input=1f18c17d5941aa82]*/
+{
#ifdef MS_WINDOWS
HANDLE hFile;
FILETIME atime, mtime;
@@ -4883,25 +4701,9 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
#endif
PyObject *return_value = NULL;
+ utime_t utime;
- memset(&path, 0, sizeof(path));
- path.function_name = "utime";
memset(&utime, 0, sizeof(utime_t));
-#if UTIME_HAVE_FD
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O&|O$OO&p:utime", keywords,
- path_converter, &path,
- &times, &ns,
-#if UTIME_HAVE_DIR_FD
- dir_fd_converter, &dir_fd,
-#else
- dir_fd_unavailable, &dir_fd,
-#endif
- &follow_symlinks
- ))
- return NULL;
if (times && (times != Py_None) && ns) {
PyErr_SetString(PyExc_ValueError,
@@ -4921,9 +4723,9 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
}
utime.now = 0;
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
- &a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 ||
+ &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
- &m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) {
+ &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
goto exit;
}
utime.atime_s = a_sec;
@@ -4955,9 +4757,9 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
goto exit;
#endif
- if (path_and_dir_fd_invalid("utime", &path, dir_fd) ||
- dir_fd_and_fd_invalid("utime", dir_fd, path.fd) ||
- fd_and_follow_symlinks_invalid("utime", path.fd, follow_symlinks))
+ if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
+ dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
+ fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
goto exit;
#if !defined(HAVE_UTIMENSAT)
@@ -4971,17 +4773,17 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (path.wide)
- hFile = CreateFileW(path.wide, FILE_WRITE_ATTRIBUTES, 0,
+ if (path->wide)
+ hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
else
- hFile = CreateFileA(path.narrow, FILE_WRITE_ATTRIBUTES, 0,
+ hFile = CreateFileA(path->narrow, FILE_WRITE_ATTRIBUTES, 0,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
Py_END_ALLOW_THREADS
if (hFile == INVALID_HANDLE_VALUE) {
- path_error(&path);
+ path_error(path);
goto exit;
}
@@ -4990,8 +4792,8 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
atime = mtime;
}
else {
- time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
- time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
+ _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
+ _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
}
if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
/* Avoid putting the file name into the error here,
@@ -5006,23 +4808,23 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
#if UTIME_HAVE_NOFOLLOW_SYMLINKS
if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
- result = utime_nofollow_symlinks(&utime, path.narrow);
+ result = utime_nofollow_symlinks(&utime, path->narrow);
else
#endif
#if UTIME_HAVE_DIR_FD
if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
- result = utime_dir_fd(&utime, dir_fd, path.narrow, follow_symlinks);
+ result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
else
#endif
#if UTIME_HAVE_FD
- if (path.fd != -1)
- result = utime_fd(&utime, path.fd);
+ if (path->fd != -1)
+ result = utime_fd(&utime, path->fd);
else
#endif
- result = utime_default(&utime, path.narrow);
+ result = utime_default(&utime, path->narrow);
Py_END_ALLOW_THREADS
@@ -5038,7 +4840,6 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
return_value = Py_None;
exit:
- path_cleanup(&path);
#ifdef MS_WINDOWS
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
@@ -5048,17 +4849,20 @@ exit:
/* Process operations */
-PyDoc_STRVAR(posix__exit__doc__,
-"_exit(status)\n\n\
-Exit to the system with specified status, without normal exit processing.");
+
+/*[clinic input]
+os._exit
+
+ status: int
+
+Exit to the system with specified status, without normal exit processing.
+[clinic start generated code]*/
static PyObject *
-posix__exit(PyObject *self, PyObject *args)
+os__exit_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=472a3cbaf68f3621 input=5e6d57556b0c4a62]*/
{
- int sts;
- if (!PyArg_ParseTuple(args, "i:_exit", &sts))
- return NULL;
- _exit(sts);
+ _exit(status);
return NULL; /* Make gcc -Wall happy */
}
@@ -5196,96 +5000,82 @@ fail:
}
#endif
+
#ifdef HAVE_EXECV
-PyDoc_STRVAR(posix_execv__doc__,
-"execv(path, args)\n\n\
-Execute an executable path with arguments, replacing current process.\n\
-\n\
- path: path of executable file\n\
- args: tuple or list of strings");
+/*[clinic input]
+os.execv
+
+ path: FSConverter
+ 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 *
-posix_execv(PyObject *self, PyObject *args)
+os_execv_impl(PyModuleDef *module, PyObject *path, PyObject *argv)
+/*[clinic end generated code: output=9221f08143146fff input=96041559925e5229]*/
{
- PyObject *opath;
- char *path;
- PyObject *argv;
+ char *path_char;
char **argvlist;
Py_ssize_t argc;
/* execv has two arguments: (path, argv), where
argv is a list or tuple of strings. */
- if (!PyArg_ParseTuple(args, "O&O:execv",
- PyUnicode_FSConverter,
- &opath, &argv))
- return NULL;
- path = PyBytes_AsString(opath);
+ path_char = PyBytes_AsString(path);
if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
PyErr_SetString(PyExc_TypeError,
"execv() arg 2 must be a tuple or list");
- Py_DECREF(opath);
return NULL;
}
argc = PySequence_Size(argv);
if (argc < 1) {
PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
- Py_DECREF(opath);
return NULL;
}
argvlist = parse_arglist(argv, &argc);
if (argvlist == NULL) {
- Py_DECREF(opath);
return NULL;
}
- execv(path, argvlist);
+ execv(path_char, argvlist);
/* If we get here it's definitely an error */
free_string_array(argvlist, argc);
- Py_DECREF(opath);
return posix_error();
}
-PyDoc_STRVAR(posix_execve__doc__,
-"execve(path, args, env)\n\n\
-Execute a path with arguments and environment, replacing current process.\n\
-\n\
- path: path of executable file\n\
- args: tuple or list of arguments\n\
- env: dictionary of strings mapping to strings\n\
-\n\
-On some platforms, you may specify an open file descriptor for path;\n\
- execve will execute the program the file descriptor is open to.\n\
- If this functionality is unavailable, using it raises NotImplementedError.");
+
+/*[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 *
-posix_execve(PyObject *self, PyObject *args, PyObject *kwargs)
+os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, PyObject *env)
+/*[clinic end generated code: output=7758d4f230d8aac6 input=626804fa092606d9]*/
{
- path_t path;
- PyObject *argv, *env;
char **argvlist = NULL;
char **envlist;
Py_ssize_t argc, envc;
- static char *keywords[] = {"path", "argv", "environment", NULL};
/* execve has three arguments: (path, argv, env), where
argv is a list or tuple of strings and env is a dictionary
like posix.environ. */
- memset(&path, 0, sizeof(path));
- path.function_name = "execve";
-#ifdef HAVE_FEXECVE
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&OO:execve", keywords,
- path_converter, &path,
- &argv, &env
- ))
- return NULL;
-
if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
PyErr_SetString(PyExc_TypeError,
"execve: argv must be a tuple or list");
@@ -5308,15 +5098,15 @@ posix_execve(PyObject *self, PyObject *args, PyObject *kwargs)
goto fail;
#ifdef HAVE_FEXECVE
- if (path.fd > -1)
- fexecve(path.fd, argvlist, envlist);
+ if (path->fd > -1)
+ fexecve(path->fd, argvlist, envlist);
else
#endif
- execve(path.narrow, argvlist, envlist);
+ execve(path->narrow, argvlist, envlist);
/* If we get here it's definitely an error */
- path_error(&path);
+ path_error(path);
while (--envc >= 0)
PyMem_DEL(envlist[envc]);
@@ -5324,29 +5114,33 @@ posix_execve(PyObject *self, PyObject *args, PyObject *kwargs)
fail:
if (argvlist)
free_string_array(argvlist, argc);
- path_cleanup(&path);
return NULL;
}
#endif /* HAVE_EXECV */
#ifdef HAVE_SPAWNV
-PyDoc_STRVAR(posix_spawnv__doc__,
-"spawnv(mode, path, args)\n\n\
-Execute the program 'path' in a new process.\n\
-\n\
- mode: mode of process creation\n\
- path: path of executable file\n\
- args: tuple or list of strings");
+/*[clinic input]
+os.spawnv
+
+ mode: int
+ Mode of process creation.
+ path: FSConverter
+ 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 *
-posix_spawnv(PyObject *self, PyObject *args)
+os_spawnv_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv)
+/*[clinic end generated code: output=140a7945484c8cc5 input=042c91dfc1e6debc]*/
{
- PyObject *opath;
- char *path;
- PyObject *argv;
+ char *path_char;
char **argvlist;
- int mode, i;
+ int i;
Py_ssize_t argc;
Py_intptr_t spawnval;
PyObject *(*getitem)(PyObject *, Py_ssize_t);
@@ -5354,11 +5148,7 @@ posix_spawnv(PyObject *self, PyObject *args)
/* spawnv has three arguments: (mode, path, argv), where
argv is a list or tuple of strings. */
- if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode,
- PyUnicode_FSConverter,
- &opath, &argv))
- return NULL;
- path = PyBytes_AsString(opath);
+ path_char = PyBytes_AsString(path);
if (PyList_Check(argv)) {
argc = PyList_Size(argv);
getitem = PyList_GetItem;
@@ -5370,13 +5160,11 @@ posix_spawnv(PyObject *self, PyObject *args)
else {
PyErr_SetString(PyExc_TypeError,
"spawnv() arg 2 must be a tuple or list");
- Py_DECREF(opath);
return NULL;
}
argvlist = PyMem_NEW(char *, argc+1);
if (argvlist == NULL) {
- Py_DECREF(opath);
return PyErr_NoMemory();
}
for (i = 0; i < argc; i++) {
@@ -5386,7 +5174,6 @@ posix_spawnv(PyObject *self, PyObject *args)
PyErr_SetString(
PyExc_TypeError,
"spawnv() arg 2 must contain only strings");
- Py_DECREF(opath);
return NULL;
}
}
@@ -5396,11 +5183,10 @@ posix_spawnv(PyObject *self, PyObject *args)
mode = _P_OVERLAY;
Py_BEGIN_ALLOW_THREADS
- spawnval = _spawnv(mode, path, argvlist);
+ spawnval = _spawnv(mode, path_char, argvlist);
Py_END_ALLOW_THREADS
free_string_array(argvlist, argc);
- Py_DECREF(opath);
if (spawnval == -1)
return posix_error();
@@ -5409,25 +5195,30 @@ posix_spawnv(PyObject *self, PyObject *args)
}
-PyDoc_STRVAR(posix_spawnve__doc__,
-"spawnve(mode, path, args, env)\n\n\
-Execute the program 'path' in a new process.\n\
-\n\
- mode: mode of process creation\n\
- path: path of executable file\n\
- args: tuple or list of arguments\n\
- env: dictionary of strings mapping to strings");
+/*[clinic input]
+os.spawnve
+
+ mode: int
+ Mode of process creation.
+ path: FSConverter
+ 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 *
-posix_spawnve(PyObject *self, PyObject *args)
+os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv, PyObject *env)
+/*[clinic end generated code: output=1c52955789461be8 input=02362fd937963f8f]*/
{
- PyObject *opath;
- char *path;
- PyObject *argv, *env;
+ char *path_char;
char **argvlist;
char **envlist;
PyObject *res = NULL;
- int mode;
Py_ssize_t argc, i, envc;
Py_intptr_t spawnval;
PyObject *(*getitem)(PyObject *, Py_ssize_t);
@@ -5437,11 +5228,7 @@ posix_spawnve(PyObject *self, PyObject *args)
argv is a list or tuple of strings and env is a dictionary
like posix.environ. */
- if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode,
- PyUnicode_FSConverter,
- &opath, &argv, &env))
- return NULL;
- path = PyBytes_AsString(opath);
+ path_char = PyBytes_AsString(path);
if (PyList_Check(argv)) {
argc = PyList_Size(argv);
getitem = PyList_GetItem;
@@ -5485,7 +5272,7 @@ posix_spawnve(PyObject *self, PyObject *args)
mode = _P_OVERLAY;
Py_BEGIN_ALLOW_THREADS
- spawnval = _spawnve(mode, path, argvlist, envlist);
+ spawnval = _spawnve(mode, path_char, argvlist, envlist);
Py_END_ALLOW_THREADS
if (spawnval == -1)
@@ -5499,7 +5286,6 @@ posix_spawnve(PyObject *self, PyObject *args)
fail_1:
free_string_array(argvlist, lastarg);
fail_0:
- Py_DECREF(opath);
return res;
}
@@ -5507,14 +5293,17 @@ posix_spawnve(PyObject *self, PyObject *args)
#ifdef HAVE_FORK1
-PyDoc_STRVAR(posix_fork1__doc__,
-"fork1() -> pid\n\n\
-Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
-\n\
-Return 0 to child process and PID of child to parent process.");
+/*[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 *
-posix_fork1(PyObject *self, PyObject *noargs)
+os_fork1_impl(PyModuleDef *module)
+/*[clinic end generated code: output=e27b4f66419c9dcf input=12db02167893926e]*/
{
pid_t pid;
int result = 0;
@@ -5537,17 +5326,21 @@ posix_fork1(PyObject *self, PyObject *noargs)
}
return PyLong_FromPid(pid);
}
-#endif
+#endif /* HAVE_FORK1 */
#ifdef HAVE_FORK
-PyDoc_STRVAR(posix_fork__doc__,
-"fork() -> pid\n\n\
-Fork a child process.\n\
-Return 0 to child process and PID of child to parent process.");
+/*[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 *
-posix_fork(PyObject *self, PyObject *noargs)
+os_fork_impl(PyModuleDef *module)
+/*[clinic end generated code: output=898b1ecd3498ba12 input=13c956413110eeaa]*/
{
pid_t pid;
int result = 0;
@@ -5570,92 +5363,106 @@ posix_fork(PyObject *self, PyObject *noargs)
}
return PyLong_FromPid(pid);
}
-#endif
+#endif /* HAVE_FORK */
-#ifdef HAVE_SCHED_H
+#ifdef HAVE_SCHED_H
#ifdef HAVE_SCHED_GET_PRIORITY_MAX
+/*[clinic input]
+os.sched_get_priority_max
+
+ policy: int
-PyDoc_STRVAR(posix_sched_get_priority_max__doc__,
-"sched_get_priority_max(policy)\n\n\
-Get the maximum scheduling priority for *policy*.");
+Get the maximum scheduling priority for policy.
+[clinic start generated code]*/
static PyObject *
-posix_sched_get_priority_max(PyObject *self, PyObject *args)
+os_sched_get_priority_max_impl(PyModuleDef *module, int policy)
+/*[clinic end generated code: output=a6a30fa5071f2d81 input=2097b7998eca6874]*/
{
- int policy, max;
+ int max;
- if (!PyArg_ParseTuple(args, "i:sched_get_priority_max", &policy))
- return NULL;
max = sched_get_priority_max(policy);
if (max < 0)
return posix_error();
return PyLong_FromLong(max);
}
-PyDoc_STRVAR(posix_sched_get_priority_min__doc__,
-"sched_get_priority_min(policy)\n\n\
-Get the minimum scheduling priority for *policy*.");
+
+/*[clinic input]
+os.sched_get_priority_min
+
+ policy: int
+
+Get the minimum scheduling priority for policy.
+[clinic start generated code]*/
static PyObject *
-posix_sched_get_priority_min(PyObject *self, PyObject *args)
+os_sched_get_priority_min_impl(PyModuleDef *module, int policy)
+/*[clinic end generated code: output=5ca3ed6bc43e9b20 input=21bc8fa0d70983bf]*/
{
- int policy, min;
-
- if (!PyArg_ParseTuple(args, "i:sched_get_priority_min", &policy))
- return NULL;
- min = sched_get_priority_min(policy);
+ int min = sched_get_priority_min(policy);
if (min < 0)
return posix_error();
return PyLong_FromLong(min);
}
-
#endif /* HAVE_SCHED_GET_PRIORITY_MAX */
+
#ifdef HAVE_SCHED_SETSCHEDULER
+/*[clinic input]
+os.sched_getscheduler
+ pid: pid_t
+ /
-PyDoc_STRVAR(posix_sched_getscheduler__doc__,
-"sched_getscheduler(pid)\n\n\
-Get the scheduling policy for the process with a PID of *pid*.\n\
-Passing a PID of 0 returns the scheduling policy for the calling process.");
+Get the scheduling policy for the process identifiedy by pid.
+
+Passing 0 for pid returns the scheduling policy for the calling process.
+[clinic start generated code]*/
static PyObject *
-posix_sched_getscheduler(PyObject *self, PyObject *args)
+os_sched_getscheduler_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=8cd63c15caf54fa9 input=5f14cfd1f189e1a0]*/
{
- pid_t pid;
int policy;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getscheduler", &pid))
- return NULL;
policy = sched_getscheduler(pid);
if (policy < 0)
return posix_error();
return PyLong_FromLong(policy);
}
+#endif /* HAVE_SCHED_SETSCHEDULER */
-#endif
#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM)
+/*[clinic input]
+class os.sched_param "PyObject *" "&SchedParamType"
+
+@classmethod
+os.sched_param.__new__
+
+ sched_priority: object
+ A scheduling parameter.
+
+Current has only one field: sched_priority");
+[clinic start generated code]*/
static PyObject *
-sched_param_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
+/*[clinic end generated code: output=48f4067d60f48c13 input=73a4c22f7071fc62]*/
{
- PyObject *res, *priority;
- static char *kwlist[] = {"sched_priority", NULL};
+ PyObject *res;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:sched_param", kwlist, &priority))
- return NULL;
res = PyStructSequence_New(type);
if (!res)
return NULL;
- Py_INCREF(priority);
- PyStructSequence_SET_ITEM(res, 0, priority);
+ Py_INCREF(sched_priority);
+ PyStructSequence_SET_ITEM(res, 0, sched_priority);
return res;
}
-PyDoc_STRVAR(sched_param__doc__,
-"sched_param(sched_priority): A scheduling parameter.\n\n\
-Current has only one field: sched_priority");
+
+PyDoc_VAR(os_sched_param__doc__);
static PyStructSequence_Field sched_param_fields[] = {
{"sched_priority", "the scheduling priority"},
@@ -5664,7 +5471,7 @@ static PyStructSequence_Field sched_param_fields[] = {
static PyStructSequence_Desc sched_param_desc = {
"sched_param", /* name */
- sched_param__doc__, /* doc */
+ os_sched_param__doc__, /* doc */
sched_param_fields,
1
};
@@ -5688,118 +5495,132 @@ convert_sched_param(PyObject *param, struct sched_param *res)
res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
return 1;
}
+#endif /* defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) */
-#endif
#ifdef HAVE_SCHED_SETSCHEDULER
+/*[clinic input]
+os.sched_setscheduler
-PyDoc_STRVAR(posix_sched_setscheduler__doc__,
-"sched_setscheduler(pid, policy, param)\n\n\
-Set the scheduling policy, *policy*, for *pid*.\n\
-If *pid* is 0, the calling process is changed.\n\
-*param* is an instance of sched_param.");
+ pid: pid_t
+ policy: int
+ param: sched_param
+ /
-static PyObject *
-posix_sched_setscheduler(PyObject *self, PyObject *args)
-{
- pid_t pid;
- int policy;
- struct sched_param param;
+Set the scheduling policy for the process identified by pid.
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "iO&:sched_setscheduler",
- &pid, &policy, &convert_sched_param, &param))
- return NULL;
+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(PyModuleDef *module, pid_t pid, int policy, struct sched_param *param)
+/*[clinic end generated code: output=97f40f8384e554b0 input=c581f9469a5327dd]*/
+{
/*
** sched_setscheduler() returns 0 in Linux, but the previous
** scheduling policy under Solaris/Illumos, and others.
** On error, -1 is returned in all Operating Systems.
*/
- if (sched_setscheduler(pid, policy, &param) == -1)
+ if (sched_setscheduler(pid, policy, param) == -1)
return posix_error();
Py_RETURN_NONE;
}
+#endif /* HAVE_SCHED_SETSCHEDULER*/
-#endif
#ifdef HAVE_SCHED_SETPARAM
+/*[clinic input]
+os.sched_getparam
+ pid: pid_t
+ /
+
+Returns scheduling parameters for the process identified by pid.
-PyDoc_STRVAR(posix_sched_getparam__doc__,
-"sched_getparam(pid) -> sched_param\n\n\
-Returns scheduling parameters for the process with *pid* as an instance of the\n\
-sched_param class. A PID of 0 means the calling process.");
+If pid is 0, returns parameters for the calling process.
+Return value is an instance of sched_param.
+[clinic start generated code]*/
static PyObject *
-posix_sched_getparam(PyObject *self, PyObject *args)
+os_sched_getparam_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=f42c5bd2604ecd08 input=18a1ef9c2efae296]*/
{
- pid_t pid;
struct sched_param param;
- PyObject *res, *priority;
+ PyObject *result;
+ PyObject *priority;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getparam", &pid))
- return NULL;
if (sched_getparam(pid, &param))
return posix_error();
- res = PyStructSequence_New(&SchedParamType);
- if (!res)
+ result = PyStructSequence_New(&SchedParamType);
+ if (!result)
return NULL;
priority = PyLong_FromLong(param.sched_priority);
if (!priority) {
- Py_DECREF(res);
+ Py_DECREF(result);
return NULL;
}
- PyStructSequence_SET_ITEM(res, 0, priority);
- return res;
+ PyStructSequence_SET_ITEM(result, 0, priority);
+ return result;
}
-PyDoc_STRVAR(posix_sched_setparam__doc__,
-"sched_setparam(pid, param)\n\n\
-Set scheduling parameters for a process with PID *pid*.\n\
-A PID of 0 means the calling process.");
+
+/*[clinic input]
+os.sched_setparam
+ pid: pid_t
+ param: sched_param
+ /
+
+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 *
-posix_sched_setparam(PyObject *self, PyObject *args)
+os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param)
+/*[clinic end generated code: output=c6560b34395bb343 input=6b8d6dfcecdc21bd]*/
{
- pid_t pid;
- struct sched_param param;
-
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O&:sched_setparam",
- &pid, &convert_sched_param, &param))
- return NULL;
- if (sched_setparam(pid, &param))
+ if (sched_setparam(pid, param))
return posix_error();
Py_RETURN_NONE;
}
+#endif /* HAVE_SCHED_SETPARAM */
-#endif
#ifdef HAVE_SCHED_RR_GET_INTERVAL
+/*[clinic input]
+os.sched_rr_get_interval -> double
+ pid: pid_t
+ /
-PyDoc_STRVAR(posix_sched_rr_get_interval__doc__,
-"sched_rr_get_interval(pid) -> float\n\n\
-Return the round-robin quantum for the process with PID *pid* in seconds.");
+Return the round-robin quantum for the process identified by pid, in seconds.
-static PyObject *
-posix_sched_rr_get_interval(PyObject *self, PyObject *args)
+Value returned is a float.
+[clinic start generated code]*/
+
+static double
+os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=7adc137a86dea581 input=2a973da15cca6fae]*/
{
- pid_t pid;
struct timespec interval;
-
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_rr_get_interval", &pid))
- return NULL;
- if (sched_rr_get_interval(pid, &interval))
- return posix_error();
- return PyFloat_FromDouble((double)interval.tv_sec + 1e-9*interval.tv_nsec);
+ if (sched_rr_get_interval(pid, &interval)) {
+ posix_error();
+ return -1.0;
+ }
+ return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
}
+#endif /* HAVE_SCHED_RR_GET_INTERVAL */
-#endif
-PyDoc_STRVAR(posix_sched_yield__doc__,
-"sched_yield()\n\n\
-Voluntarily relinquish the CPU.");
+/*[clinic input]
+os.sched_yield
+
+Voluntarily relinquish the CPU.
+[clinic start generated code]*/
static PyObject *
-posix_sched_yield(PyObject *self, PyObject *noargs)
+os_sched_yield_impl(PyModuleDef *module)
+/*[clinic end generated code: output=d7bd51869c4cb6a8 input=e54d6f98189391d4]*/
{
if (sched_yield())
return posix_error();
@@ -5807,39 +5628,41 @@ posix_sched_yield(PyObject *self, PyObject *noargs)
}
#ifdef HAVE_SCHED_SETAFFINITY
-
/* The minimum number of CPUs allocated in a cpu_set_t */
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
-PyDoc_STRVAR(posix_sched_setaffinity__doc__,
-"sched_setaffinity(pid, cpu_set)\n\n\
-Set the affinity of the process with PID *pid* to *cpu_set*.");
+/*[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 *
-posix_sched_setaffinity(PyObject *self, PyObject *args)
+os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask)
+/*[clinic end generated code: output=582bcbf40d3253a9 input=a0791a597c7085ba]*/
{
- pid_t pid;
int ncpus;
size_t setsize;
- cpu_set_t *mask = NULL;
- PyObject *iterable, *iterator = NULL, *item;
+ cpu_set_t *cpu_set = NULL;
+ PyObject *iterator = NULL, *item;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity",
- &pid, &iterable))
- return NULL;
-
- iterator = PyObject_GetIter(iterable);
+ iterator = PyObject_GetIter(mask);
if (iterator == NULL)
return NULL;
ncpus = NCPUS_START;
setsize = CPU_ALLOC_SIZE(ncpus);
- mask = CPU_ALLOC(ncpus);
- if (mask == NULL) {
+ cpu_set = CPU_ALLOC(ncpus);
+ if (cpu_set == NULL) {
PyErr_NoMemory();
goto error;
}
- CPU_ZERO_S(setsize, mask);
+ CPU_ZERO_S(setsize, cpu_set);
while ((item = PyIter_Next(iterator))) {
long cpu;
@@ -5880,48 +5703,50 @@ posix_sched_setaffinity(PyObject *self, PyObject *args)
}
newsetsize = CPU_ALLOC_SIZE(newncpus);
CPU_ZERO_S(newsetsize, newmask);
- memcpy(newmask, mask, setsize);
- CPU_FREE(mask);
+ memcpy(newmask, cpu_set, setsize);
+ CPU_FREE(cpu_set);
setsize = newsetsize;
- mask = newmask;
+ cpu_set = newmask;
ncpus = newncpus;
}
- CPU_SET_S(cpu, setsize, mask);
+ CPU_SET_S(cpu, setsize, cpu_set);
}
Py_CLEAR(iterator);
- if (sched_setaffinity(pid, setsize, mask)) {
+ if (sched_setaffinity(pid, setsize, cpu_set)) {
posix_error();
goto error;
}
- CPU_FREE(mask);
+ CPU_FREE(cpu_set);
Py_RETURN_NONE;
error:
- if (mask)
- CPU_FREE(mask);
+ if (cpu_set)
+ CPU_FREE(cpu_set);
Py_XDECREF(iterator);
return NULL;
}
-PyDoc_STRVAR(posix_sched_getaffinity__doc__,
-"sched_getaffinity(pid, ncpus) -> cpu_set\n\n\
-Return the affinity of the process with PID *pid*.\n\
-The returned cpu_set will be of size *ncpus*.");
+
+/*[clinic input]
+os.sched_getaffinity
+ pid: pid_t
+ /
+
+Return the affinity of the process identified by pid.
+
+The affinity is returned as a set of CPU identifiers.
+[clinic start generated code]*/
static PyObject *
-posix_sched_getaffinity(PyObject *self, PyObject *args)
+os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=b431a8f310e369e7 input=eaf161936874b8a1]*/
{
- pid_t pid;
int cpu, ncpus, count;
size_t setsize;
cpu_set_t *mask = NULL;
PyObject *res = NULL;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity",
- &pid))
- return NULL;
-
ncpus = NCPUS_START;
while (1) {
setsize = CPU_ALLOC_SIZE(ncpus);
@@ -5971,6 +5796,7 @@ error:
#endif /* HAVE_SCHED_H */
+
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
@@ -5997,13 +5823,20 @@ error:
#endif
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
+
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
-PyDoc_STRVAR(posix_openpty__doc__,
-"openpty() -> (master_fd, slave_fd)\n\n\
-Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
+/*[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 *
-posix_openpty(PyObject *self, PyObject *noargs)
+os_openpty_impl(PyModuleDef *module)
+/*[clinic end generated code: output=358e571c1ba135ee input=f3d99fd99e762907]*/
{
int master_fd = -1, slave_fd = -1;
#ifndef HAVE_OPENPTY
@@ -6034,7 +5867,7 @@ posix_openpty(PyObject *self, PyObject *noargs)
slave_fd = _Py_open(slave_name, O_RDWR);
if (slave_fd < 0)
- goto posix_error;
+ goto error;
#else
master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
@@ -6062,8 +5895,8 @@ posix_openpty(PyObject *self, PyObject *noargs)
goto posix_error;
slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
- if (slave_fd < 0)
- goto posix_error;
+ if (slave_fd == -1)
+ goto error;
if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
goto posix_error;
@@ -6081,9 +5914,7 @@ posix_openpty(PyObject *self, PyObject *noargs)
posix_error:
posix_error();
-#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
error:
-#endif
if (master_fd != -1)
close(master_fd);
if (slave_fd != -1)
@@ -6092,15 +5923,22 @@ error:
}
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
+
#ifdef HAVE_FORKPTY
-PyDoc_STRVAR(posix_forkpty__doc__,
-"forkpty() -> (pid, master_fd)\n\n\
-Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
-Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
-To both, return fd of newly opened pseudo-terminal.\n");
+/*[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 *
-posix_forkpty(PyObject *self, PyObject *noargs)
+os_forkpty_impl(PyModuleDef *module)
+/*[clinic end generated code: output=a11b8391dce3cb57 input=f1f7f4bae3966010]*/
{
int master_fd = -1, result = 0;
pid_t pid;
@@ -6124,59 +5962,73 @@ posix_forkpty(PyObject *self, PyObject *noargs)
}
return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
}
-#endif
+#endif /* HAVE_FORKPTY */
#ifdef HAVE_GETEGID
-PyDoc_STRVAR(posix_getegid__doc__,
-"getegid() -> egid\n\n\
-Return the current process's effective group id.");
+/*[clinic input]
+os.getegid
+
+Return the current process's effective group id.
+[clinic start generated code]*/
static PyObject *
-posix_getegid(PyObject *self, PyObject *noargs)
+os_getegid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=90f433a8c0b1d919 input=1596f79ad1107d5d]*/
{
return _PyLong_FromGid(getegid());
}
-#endif
+#endif /* HAVE_GETEGID */
#ifdef HAVE_GETEUID
-PyDoc_STRVAR(posix_geteuid__doc__,
-"geteuid() -> euid\n\n\
-Return the current process's effective user id.");
+/*[clinic input]
+os.geteuid
+
+Return the current process's effective user id.
+[clinic start generated code]*/
static PyObject *
-posix_geteuid(PyObject *self, PyObject *noargs)
+os_geteuid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=1a532c4a66874357 input=4644c662d3bd9f19]*/
{
return _PyLong_FromUid(geteuid());
}
-#endif
+#endif /* HAVE_GETEUID */
#ifdef HAVE_GETGID
-PyDoc_STRVAR(posix_getgid__doc__,
-"getgid() -> gid\n\n\
-Return the current process's group id.");
+/*[clinic input]
+os.getgid
+
+Return the current process's group id.
+[clinic start generated code]*/
static PyObject *
-posix_getgid(PyObject *self, PyObject *noargs)
+os_getgid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=91a22021b74ea46b input=58796344cd87c0f6]*/
{
return _PyLong_FromGid(getgid());
}
-#endif
+#endif /* HAVE_GETGID */
-PyDoc_STRVAR(posix_getpid__doc__,
-"getpid() -> pid\n\n\
-Return the current process id");
+/*[clinic input]
+os.getpid
+
+Return the current process id.
+[clinic start generated code]*/
static PyObject *
-posix_getpid(PyObject *self, PyObject *noargs)
+os_getpid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=8fbf3a934ee09e62 input=5a9a00f0ab68aa00]*/
{
return PyLong_FromPid(getpid());
}
#ifdef HAVE_GETGROUPLIST
+
+/* AC 3.5: funny apple logic below */
PyDoc_STRVAR(posix_getgrouplist__doc__,
"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
Returns a list of groups to which a user belongs.\n\n\
@@ -6249,15 +6101,19 @@ posix_getgrouplist(PyObject *self, PyObject *args)
return list;
}
-#endif
+#endif /* HAVE_GETGROUPLIST */
+
#ifdef HAVE_GETGROUPS
-PyDoc_STRVAR(posix_getgroups__doc__,
-"getgroups() -> list of group IDs\n\n\
-Return list of supplemental group IDs for the process.");
+/*[clinic input]
+os.getgroups
+
+Return list of supplemental group IDs for the process.
+[clinic start generated code]*/
static PyObject *
-posix_getgroups(PyObject *self, PyObject *noargs)
+os_getgroups_impl(PyModuleDef *module)
+/*[clinic end generated code: output=6e7c4fd2db6d5c60 input=d3f109412e6a155c]*/
{
PyObject *result = NULL;
@@ -6356,7 +6212,7 @@ posix_getgroups(PyObject *self, PyObject *noargs)
return result;
}
-#endif
+#endif /* HAVE_GETGROUPS */
#ifdef HAVE_INITGROUPS
PyDoc_STRVAR(posix_initgroups__doc__,
@@ -6365,6 +6221,7 @@ Call the system initgroups() to initialize the group access list with all of\n\
the groups of which the specified username is a member, plus the specified\n\
group id.");
+/* AC 3.5: funny apple logic */
static PyObject *
posix_initgroups(PyObject *self, PyObject *args)
{
@@ -6397,20 +6254,23 @@ posix_initgroups(PyObject *self, PyObject *args)
Py_INCREF(Py_None);
return Py_None;
}
-#endif
+#endif /* HAVE_INITGROUPS */
+
#ifdef HAVE_GETPGID
-PyDoc_STRVAR(posix_getpgid__doc__,
-"getpgid(pid) -> pgid\n\n\
-Call the system call getpgid().");
+/*[clinic input]
+os.getpgid
+
+ pid: pid_t
+
+Call the system call getpgid(), and return the result.
+[clinic start generated code]*/
static PyObject *
-posix_getpgid(PyObject *self, PyObject *args)
+os_getpgid_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=70e713b4d54b7c61 input=39d710ae3baaf1c7]*/
{
- pid_t pid, pgid;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getpgid", &pid))
- return NULL;
- pgid = getpgid(pid);
+ pid_t pgid = getpgid(pid);
if (pgid < 0)
return posix_error();
return PyLong_FromPid(pgid);
@@ -6419,12 +6279,15 @@ posix_getpgid(PyObject *self, PyObject *args)
#ifdef HAVE_GETPGRP
-PyDoc_STRVAR(posix_getpgrp__doc__,
-"getpgrp() -> pgrp\n\n\
-Return the current process group id.");
+/*[clinic input]
+os.getpgrp
+
+Return the current process group id.
+[clinic start generated code]*/
static PyObject *
-posix_getpgrp(PyObject *self, PyObject *noargs)
+os_getpgrp_impl(PyModuleDef *module)
+/*[clinic end generated code: output=cf3403585846811f input=6846fb2bb9a3705e]*/
{
#ifdef GETPGRP_HAVE_ARG
return PyLong_FromPid(getpgrp(0));
@@ -6436,12 +6299,15 @@ posix_getpgrp(PyObject *self, PyObject *noargs)
#ifdef HAVE_SETPGRP
-PyDoc_STRVAR(posix_setpgrp__doc__,
-"setpgrp()\n\n\
-Make this process the process group leader.");
+/*[clinic input]
+os.setpgrp
+
+Make the current process the leader of its process group.
+[clinic start generated code]*/
static PyObject *
-posix_setpgrp(PyObject *self, PyObject *noargs)
+os_setpgrp_impl(PyModuleDef *module)
+/*[clinic end generated code: output=59650f55a963d7ac input=1f0619fcb5731e7e]*/
{
#ifdef SETPGRP_HAVE_ARG
if (setpgrp(0, 0) < 0)
@@ -6452,7 +6318,6 @@ posix_setpgrp(PyObject *self, PyObject *noargs)
Py_INCREF(Py_None);
return Py_None;
}
-
#endif /* HAVE_SETPGRP */
#ifdef HAVE_GETPPID
@@ -6499,14 +6364,19 @@ win32_getppid()
}
#endif /*MS_WINDOWS*/
-PyDoc_STRVAR(posix_getppid__doc__,
-"getppid() -> ppid\n\n\
-Return the parent's process id. If the parent process has already exited,\n\
-Windows machines will still return its id; others systems will return the id\n\
-of the 'init' process (1).");
+
+/*[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 *
-posix_getppid(PyObject *self, PyObject *noargs)
+os_getppid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=4e49c8e7a8738cd2 input=e637cb87539c030e]*/
{
#ifdef MS_WINDOWS
return win32_getppid();
@@ -6518,12 +6388,15 @@ posix_getppid(PyObject *self, PyObject *noargs)
#ifdef HAVE_GETLOGIN
-PyDoc_STRVAR(posix_getlogin__doc__,
-"getlogin() -> string\n\n\
-Return the actual login name.");
+/*[clinic input]
+os.getlogin
+
+Return the actual login name.
+[clinic start generated code]*/
static PyObject *
-posix_getlogin(PyObject *self, PyObject *noargs)
+os_getlogin_impl(PyModuleDef *module)
+/*[clinic end generated code: output=037ebdb3e4b5dac1 input=2a21ab1e917163df]*/
{
PyObject *result = NULL;
#ifdef MS_WINDOWS
@@ -6556,77 +6429,54 @@ posix_getlogin(PyObject *self, PyObject *noargs)
}
#endif /* HAVE_GETLOGIN */
+
#ifdef HAVE_GETUID
-PyDoc_STRVAR(posix_getuid__doc__,
-"getuid() -> uid\n\n\
-Return the current process's user id.");
+/*[clinic input]
+os.getuid
+
+Return the current process's user id.
+[clinic start generated code]*/
static PyObject *
-posix_getuid(PyObject *self, PyObject *noargs)
+os_getuid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=03a8b894cefb3fa5 input=b53c8b35f110a516]*/
{
return _PyLong_FromUid(getuid());
}
-#endif
+#endif /* HAVE_GETUID */
+
+#ifdef MS_WINDOWS
+#define HAVE_KILL
+#endif /* MS_WINDOWS */
#ifdef HAVE_KILL
-PyDoc_STRVAR(posix_kill__doc__,
-"kill(pid, sig)\n\n\
-Kill a process with a signal.");
+/*[clinic input]
+os.kill
-static PyObject *
-posix_kill(PyObject *self, PyObject *args)
-{
- pid_t pid;
- int sig;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:kill", &pid, &sig))
- return NULL;
- if (kill(pid, sig) == -1)
- return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
-}
-#endif
+ pid: pid_t
+ signal: Py_ssize_t
+ /
-#ifdef HAVE_KILLPG
-PyDoc_STRVAR(posix_killpg__doc__,
-"killpg(pgid, sig)\n\n\
-Kill a process group with a signal.");
+Kill a process with a signal.
+[clinic start generated code]*/
static PyObject *
-posix_killpg(PyObject *self, PyObject *args)
+os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal)
+/*[clinic end generated code: output=74f907dd00a83c26 input=61a36b86ca275ab9]*/
+#ifndef MS_WINDOWS
{
- int sig;
- pid_t pgid;
- /* XXX some man pages make the `pgid` parameter an int, others
- a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
- take the same type. Moreover, pid_t is always at least as wide as
- int (else compilation of this module fails), which is safe. */
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:killpg", &pgid, &sig))
- return NULL;
- if (killpg(pgid, sig) == -1)
+ if (kill(pid, (int)signal) == -1)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
-#endif
-
-#ifdef MS_WINDOWS
-PyDoc_STRVAR(win32_kill__doc__,
-"kill(pid, sig)\n\n\
-Kill a process with a signal.");
-
-static PyObject *
-win32_kill(PyObject *self, PyObject *args)
+#else /* !MS_WINDOWS */
{
PyObject *result;
- pid_t pid;
- DWORD sig, err;
+ DWORD sig = (DWORD)signal;
+ DWORD err;
HANDLE handle;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "k:kill", &pid, &sig))
- return NULL;
-
/* Console processes which share a common console can be sent CTRL+C or
CTRL+BREAK events, provided they handle said events. */
if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
@@ -6657,103 +6507,138 @@ win32_kill(PyObject *self, PyObject *args)
CloseHandle(handle);
return result;
}
-#endif /* MS_WINDOWS */
+#endif /* !MS_WINDOWS */
+#endif /* HAVE_KILL */
-#ifdef HAVE_PLOCK
+#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(PyModuleDef *module, pid_t pgid, int signal)
+/*[clinic end generated code: output=3434a766ef945f93 input=38b5449eb8faec19]*/
+{
+ /* XXX some man pages make the `pgid` parameter an int, others
+ a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
+ take the same type. Moreover, pid_t is always at least as wide as
+ int (else compilation of this module fails), which is safe. */
+ if (killpg(pgid, signal) == -1)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_KILLPG */
+
+
+#ifdef HAVE_PLOCK
#ifdef HAVE_SYS_LOCK_H
#include <sys/lock.h>
#endif
-PyDoc_STRVAR(posix_plock__doc__,
-"plock(op)\n\n\
+/*[clinic input]
+os.plock
+ op: int
+ /
+
Lock program segments into memory.");
+[clinic start generated code]*/
static PyObject *
-posix_plock(PyObject *self, PyObject *args)
+os_plock_impl(PyModuleDef *module, int op)
+/*[clinic end generated code: output=5cb851f81b914984 input=e6e5e348e1525f60]*/
{
- int op;
- if (!PyArg_ParseTuple(args, "i:plock", &op))
- return NULL;
if (plock(op) == -1)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_PLOCK */
+
#ifdef HAVE_SETUID
-PyDoc_STRVAR(posix_setuid__doc__,
-"setuid(uid)\n\n\
-Set the current process's user id.");
+/*[clinic input]
+os.setuid
+
+ uid: uid_t
+ /
+
+Set the current process's user id.
+[clinic start generated code]*/
static PyObject *
-posix_setuid(PyObject *self, PyObject *args)
+os_setuid_impl(PyModuleDef *module, uid_t uid)
+/*[clinic end generated code: output=941ea9a8d1e5d565 input=c921a3285aa22256]*/
{
- uid_t uid;
- if (!PyArg_ParseTuple(args, "O&:setuid", _Py_Uid_Converter, &uid))
- return NULL;
if (setuid(uid) < 0)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETUID */
#ifdef HAVE_SETEUID
-PyDoc_STRVAR(posix_seteuid__doc__,
-"seteuid(uid)\n\n\
-Set the current process's effective user id.");
+/*[clinic input]
+os.seteuid
+
+ euid: uid_t
+ /
+
+Set the current process's effective user id.
+[clinic start generated code]*/
static PyObject *
-posix_seteuid (PyObject *self, PyObject *args)
+os_seteuid_impl(PyModuleDef *module, uid_t euid)
+/*[clinic end generated code: output=66f4f6823a648d6d input=ba93d927e4781aa9]*/
{
- uid_t euid;
- if (!PyArg_ParseTuple(args, "O&:seteuid", _Py_Uid_Converter, &euid))
- return NULL;
- if (seteuid(euid) < 0) {
+ if (seteuid(euid) < 0)
return posix_error();
- } else {
- Py_INCREF(Py_None);
- return Py_None;
- }
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETEUID */
+
#ifdef HAVE_SETEGID
-PyDoc_STRVAR(posix_setegid__doc__,
-"setegid(gid)\n\n\
-Set the current process's effective group id.");
+/*[clinic input]
+os.setegid
+
+ egid: gid_t
+ /
+
+Set the current process's effective group id.
+[clinic start generated code]*/
static PyObject *
-posix_setegid (PyObject *self, PyObject *args)
+os_setegid_impl(PyModuleDef *module, gid_t egid)
+/*[clinic end generated code: output=ca094a69a081a60f input=4080526d0ccd6ce3]*/
{
- gid_t egid;
- if (!PyArg_ParseTuple(args, "O&:setegid", _Py_Gid_Converter, &egid))
- return NULL;
- if (setegid(egid) < 0) {
+ if (setegid(egid) < 0)
return posix_error();
- } else {
- Py_INCREF(Py_None);
- return Py_None;
- }
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETEGID */
+
#ifdef HAVE_SETREUID
-PyDoc_STRVAR(posix_setreuid__doc__,
-"setreuid(ruid, euid)\n\n\
-Set the current process's real and effective user ids.");
+/*[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 *
-posix_setreuid (PyObject *self, PyObject *args)
+os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid)
+/*[clinic end generated code: output=b2938c3e73d27ec7 input=0ca8978de663880c]*/
{
- uid_t ruid, euid;
- if (!PyArg_ParseTuple(args, "O&O&:setreuid",
- _Py_Uid_Converter, &ruid,
- _Py_Uid_Converter, &euid))
- return NULL;
if (setreuid(ruid, euid) < 0) {
return posix_error();
} else {
@@ -6763,53 +6648,62 @@ posix_setreuid (PyObject *self, PyObject *args)
}
#endif /* HAVE_SETREUID */
+
#ifdef HAVE_SETREGID
-PyDoc_STRVAR(posix_setregid__doc__,
-"setregid(rgid, egid)\n\n\
-Set the current process's real and effective group ids.");
+/*[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 *
-posix_setregid (PyObject *self, PyObject *args)
+os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid)
+/*[clinic end generated code: output=db18f1839ababe3d input=c59499f72846db78]*/
{
- gid_t rgid, egid;
- if (!PyArg_ParseTuple(args, "O&O&:setregid",
- _Py_Gid_Converter, &rgid,
- _Py_Gid_Converter, &egid))
- return NULL;
- if (setregid(rgid, egid) < 0) {
+ if (setregid(rgid, egid) < 0)
return posix_error();
- } else {
- Py_INCREF(Py_None);
- return Py_None;
- }
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETREGID */
+
#ifdef HAVE_SETGID
-PyDoc_STRVAR(posix_setgid__doc__,
-"setgid(gid)\n\n\
-Set the current process's group id.");
+/*[clinic input]
+os.setgid
+ gid: gid_t
+ /
+
+Set the current process's group id.
+[clinic start generated code]*/
static PyObject *
-posix_setgid(PyObject *self, PyObject *args)
+os_setgid_impl(PyModuleDef *module, gid_t gid)
+/*[clinic end generated code: output=756cb42c6abd9d87 input=27d30c4059045dc6]*/
{
- gid_t gid;
- if (!PyArg_ParseTuple(args, "O&:setgid", _Py_Gid_Converter, &gid))
- return NULL;
if (setgid(gid) < 0)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETGID */
+
#ifdef HAVE_SETGROUPS
-PyDoc_STRVAR(posix_setgroups__doc__,
-"setgroups(list)\n\n\
-Set the groups of the current process to list.");
+/*[clinic input]
+os.setgroups
+
+ groups: object
+ /
+
+Set the groups of the current process to list.
+[clinic start generated code]*/
static PyObject *
-posix_setgroups(PyObject *self, PyObject *groups)
+os_setgroups(PyModuleDef *module, PyObject *groups)
+/*[clinic end generated code: output=7945c2e3cc817c58 input=fa742ca3daf85a7e]*/
{
int i, len;
gid_t grouplist[MAX_GROUPS];
@@ -6910,83 +6804,114 @@ wait_helper(pid_t pid, int status, struct rusage *ru)
}
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
+
#ifdef HAVE_WAIT3
-PyDoc_STRVAR(posix_wait3__doc__,
-"wait3(options) -> (pid, status, rusage)\n\n\
-Wait for completion of a child process.");
+/*[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 *
-posix_wait3(PyObject *self, PyObject *args)
+os_wait3_impl(PyModuleDef *module, int options)
+/*[clinic end generated code: output=e18af4924dc54945 input=8ac4c56956b61710]*/
{
pid_t pid;
- int options;
struct rusage ru;
+ int async_err = 0;
WAIT_TYPE status;
WAIT_STATUS_INT(status) = 0;
- if (!PyArg_ParseTuple(args, "i:wait3", &options))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- pid = wait3(&status, options, &ru);
- Py_END_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ pid = wait3(&status, options, &ru);
+ Py_END_ALLOW_THREADS
+ } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (pid < 0)
+ return (!async_err) ? posix_error() : NULL;
return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
}
#endif /* HAVE_WAIT3 */
+
#ifdef HAVE_WAIT4
-PyDoc_STRVAR(posix_wait4__doc__,
-"wait4(pid, options) -> (pid, status, rusage)\n\n\
-Wait for completion of a given child process.");
+/*[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 *
-posix_wait4(PyObject *self, PyObject *args)
+os_wait4_impl(PyModuleDef *module, pid_t pid, int options)
+/*[clinic end generated code: output=714f19e6ff01e099 input=d11deed0750600ba]*/
{
- pid_t pid;
- int options;
+ pid_t res;
struct rusage ru;
+ int async_err = 0;
WAIT_TYPE status;
WAIT_STATUS_INT(status) = 0;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- pid = wait4(pid, &status, options, &ru);
- Py_END_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = wait4(pid, &status, options, &ru);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res < 0)
+ return (!async_err) ? posix_error() : NULL;
- return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
+ return wait_helper(res, WAIT_STATUS_INT(status), &ru);
}
#endif /* HAVE_WAIT4 */
+
#if defined(HAVE_WAITID) && !defined(__APPLE__)
-PyDoc_STRVAR(posix_waitid__doc__,
-"waitid(idtype, id, options) -> waitid_result\n\n\
-Wait for the completion of one or more child processes.\n\n\
-idtype can be P_PID, P_PGID or P_ALL.\n\
-id specifies the pid to wait on.\n\
-options is constructed from the ORing of one or more of WEXITED, WSTOPPED\n\
-or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n\
-Returns either waitid_result or None if WNOHANG is specified and there are\n\
-no children in a waitable state.");
+/*[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 *
-posix_waitid(PyObject *self, PyObject *args)
+os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options)
+/*[clinic end generated code: output=5c0192750e22fa2e input=d8e7f76e052b7920]*/
{
PyObject *result;
- idtype_t idtype;
- id_t id;
- int options, res;
+ int res;
+ int async_err = 0;
siginfo_t si;
si.si_pid = 0;
- if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID "i:waitid", &idtype, &id, &options))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = waitid(idtype, id, &si, options);
- Py_END_ALLOW_THREADS
- if (res == -1)
- return posix_error();
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = waitid(idtype, id, &si, options);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res < 0)
+ return (!async_err) ? posix_error() : NULL;
if (si.si_pid == 0)
Py_RETURN_NONE;
@@ -7007,79 +6932,111 @@ posix_waitid(PyObject *self, PyObject *args)
return result;
}
-#endif
+#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
+
+
+#if defined(HAVE_WAITPID)
+/*[clinic input]
+os.waitpid
+ pid: pid_t
+ options: int
+ /
-#ifdef HAVE_WAITPID
-PyDoc_STRVAR(posix_waitpid__doc__,
-"waitpid(pid, options) -> (pid, status)\n\n\
-Wait for completion of a given child process.");
+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 *
-posix_waitpid(PyObject *self, PyObject *args)
+os_waitpid_impl(PyModuleDef *module, pid_t pid, int options)
+/*[clinic end generated code: output=5e3593353d54b15b input=0bf1666b8758fda3]*/
{
- pid_t pid;
- int options;
+ pid_t res;
+ int async_err = 0;
WAIT_TYPE status;
WAIT_STATUS_INT(status) = 0;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- pid = waitpid(pid, &status, options);
- Py_END_ALLOW_THREADS
- if (pid == -1)
- return posix_error();
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = waitpid(pid, &status, options);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res < 0)
+ return (!async_err) ? posix_error() : NULL;
- return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
+ return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
}
-
#elif defined(HAVE_CWAIT)
-
/* MS C has a variant of waitpid() that's usable for most purposes. */
-PyDoc_STRVAR(posix_waitpid__doc__,
-"waitpid(pid, options) -> (pid, status << 8)\n\n"
-"Wait for completion of a given process. options is ignored on Windows.");
+/*[clinic input]
+os.waitpid
+ pid: Py_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 *
-posix_waitpid(PyObject *self, PyObject *args)
+os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options)
+/*[clinic end generated code: output=fc1d520db019625f input=444c8f51cca5b862]*/
{
- Py_intptr_t pid;
- int status, options;
+ int status;
+ Py_intptr_t res;
+ int async_err = 0;
- if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR "i:waitpid", &pid, &options))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- pid = _cwait(&status, pid, options);
- Py_END_ALLOW_THREADS
- if (pid == -1)
- return posix_error();
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = _cwait(&status, pid, options);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res != 0)
+ return (!async_err) ? posix_error() : NULL;
/* shift the status left a byte so this is more like the POSIX waitpid */
- return Py_BuildValue(_Py_PARSE_INTPTR "i", pid, status << 8);
+ return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8);
}
-#endif /* HAVE_WAITPID || HAVE_CWAIT */
+#endif
+
#ifdef HAVE_WAIT
-PyDoc_STRVAR(posix_wait__doc__,
-"wait() -> (pid, status)\n\n\
-Wait for completion of a child process.");
+/*[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 *
-posix_wait(PyObject *self, PyObject *noargs)
+os_wait_impl(PyModuleDef *module)
+/*[clinic end generated code: output=4a7f4978393e0654 input=03b0182d4a4700ce]*/
{
pid_t pid;
+ int async_err = 0;
WAIT_TYPE status;
WAIT_STATUS_INT(status) = 0;
- Py_BEGIN_ALLOW_THREADS
- pid = wait(&status);
- Py_END_ALLOW_THREADS
- if (pid == -1)
- return posix_error();
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ pid = wait(&status);
+ Py_END_ALLOW_THREADS
+ } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (pid < 0)
+ return (!async_err) ? posix_error() : NULL;
return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
}
-#endif
+#endif /* HAVE_WAIT */
#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
@@ -7095,6 +7052,7 @@ dir_fd may not be implemented on your platform.\n\
#ifdef HAVE_READLINK
+/* AC 3.5: merge win32 and not together */
static PyObject *
posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
{
@@ -7109,12 +7067,7 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
path.function_name = "readlink";
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
path_converter, &path,
-#ifdef HAVE_READLINKAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
+ READLINKAT_DIR_FD_CONVERTER, &dir_fd))
return NULL;
Py_BEGIN_ALLOW_THREADS
@@ -7140,23 +7093,86 @@ exit:
return return_value;
}
-
#endif /* HAVE_READLINK */
+#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
+
+static PyObject *
+win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ wchar_t *path;
+ DWORD n_bytes_returned;
+ DWORD io_result;
+ PyObject *po, *result;
+ int dir_fd;
+ HANDLE reparse_point_handle;
+
+ char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
+ wchar_t *print_name;
+
+ static char *keywords[] = {"path", "dir_fd", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
+ &po,
+ dir_fd_unavailable, &dir_fd
+ ))
+ return NULL;
+
+ path = PyUnicode_AsUnicode(po);
+ if (path == NULL)
+ return NULL;
+
+ /* First get a handle to the reparse point */
+ Py_BEGIN_ALLOW_THREADS
+ reparse_point_handle = CreateFileW(
+ path,
+ 0,
+ 0,
+ 0,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
+ Py_END_ALLOW_THREADS
+
+ if (reparse_point_handle==INVALID_HANDLE_VALUE)
+ return win32_error_object("readlink", po);
+
+ Py_BEGIN_ALLOW_THREADS
+ /* New call DeviceIoControl to read the reparse point */
+ io_result = DeviceIoControl(
+ reparse_point_handle,
+ FSCTL_GET_REPARSE_POINT,
+ 0, 0, /* in buffer */
+ target_buffer, sizeof(target_buffer),
+ &n_bytes_returned,
+ 0 /* we're not using OVERLAPPED_IO */
+ );
+ CloseHandle(reparse_point_handle);
+ Py_END_ALLOW_THREADS
+
+ if (io_result==0)
+ return win32_error_object("readlink", po);
+
+ if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "not a symbolic link");
+ return NULL;
+ }
+ print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
+ rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
+
+ result = PyUnicode_FromWideChar(print_name,
+ rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
+ return result;
+}
+
+#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
+
+
#ifdef HAVE_SYMLINK
-PyDoc_STRVAR(posix_symlink__doc__,
-"symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
-Create a symbolic link pointing to src named dst.\n\n\
-target_is_directory is required on Windows if the target is to be\n\
- interpreted as a directory. (On Windows, symlink requires\n\
- Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n\
- target_is_directory is ignored on non-Windows platforms.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
#if defined(MS_WINDOWS)
@@ -7302,189 +7318,101 @@ _check_dirA(char *src, char *dest)
&& 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 *
-posix_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
+os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd)
+/*[clinic end generated code: output=11aa03f278bb2c8a input=e820ec4472547bc3]*/
{
- path_t src;
- path_t dst;
- int dir_fd = DEFAULT_DIR_FD;
- int target_is_directory = 0;
- static char *keywords[] = {"src", "dst", "target_is_directory",
- "dir_fd", NULL};
- PyObject *return_value;
#ifdef MS_WINDOWS
DWORD result;
#else
int result;
#endif
- memset(&src, 0, sizeof(src));
- src.function_name = "symlink";
- src.argument_name = "src";
- memset(&dst, 0, sizeof(dst));
- dst.function_name = "symlink";
- dst.argument_name = "dst";
-
#ifdef MS_WINDOWS
if (!check_CreateSymbolicLink()) {
PyErr_SetString(PyExc_NotImplementedError,
"CreateSymbolicLink functions not found");
- return NULL;
+ return NULL;
}
if (!win32_can_symlink) {
PyErr_SetString(PyExc_OSError, "symbolic link privilege not held");
- return NULL;
+ return NULL;
}
#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|i$O&:symlink",
- keywords,
- path_converter, &src,
- path_converter, &dst,
- &target_is_directory,
-#ifdef HAVE_SYMLINKAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
-
- if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
+ if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
PyErr_SetString(PyExc_ValueError,
"symlink: src and dst must be the same type");
- return_value = NULL;
- goto exit;
+ return NULL;
}
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (dst.wide) {
+ if (dst->wide) {
/* if src is a directory, ensure target_is_directory==1 */
- target_is_directory |= _check_dirW(src.wide, dst.wide);
- result = Py_CreateSymbolicLinkW(dst.wide, src.wide,
+ target_is_directory |= _check_dirW(src->wide, dst->wide);
+ result = Py_CreateSymbolicLinkW(dst->wide, src->wide,
target_is_directory);
}
else {
/* if src is a directory, ensure target_is_directory==1 */
- target_is_directory |= _check_dirA(src.narrow, dst.narrow);
- result = Py_CreateSymbolicLinkA(dst.narrow, src.narrow,
+ target_is_directory |= _check_dirA(src->narrow, dst->narrow);
+ result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow,
target_is_directory);
}
Py_END_ALLOW_THREADS
- if (!result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (!result)
+ return path_error2(src, dst);
#else
Py_BEGIN_ALLOW_THREADS
#if HAVE_SYMLINKAT
if (dir_fd != DEFAULT_DIR_FD)
- result = symlinkat(src.narrow, dir_fd, dst.narrow);
+ result = symlinkat(src->narrow, dir_fd, dst->narrow);
else
#endif
- result = symlink(src.narrow, dst.narrow);
+ result = symlink(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (result)
+ return path_error2(src, dst);
#endif
- return_value = Py_None;
- Py_INCREF(Py_None);
- goto exit; /* silence "unused label" warning */
-exit:
- path_cleanup(&src);
- path_cleanup(&dst);
- return return_value;
+ Py_RETURN_NONE;
}
-
#endif /* HAVE_SYMLINK */
-#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
-
-static PyObject *
-win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- wchar_t *path;
- DWORD n_bytes_returned;
- DWORD io_result;
- PyObject *po, *result;
- int dir_fd;
- HANDLE reparse_point_handle;
-
- char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
- REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
- wchar_t *print_name;
-
- static char *keywords[] = {"path", "dir_fd", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
- &po,
- dir_fd_unavailable, &dir_fd
- ))
- return NULL;
-
- path = PyUnicode_AsUnicode(po);
- if (path == NULL)
- return NULL;
-
- /* First get a handle to the reparse point */
- Py_BEGIN_ALLOW_THREADS
- reparse_point_handle = CreateFileW(
- path,
- 0,
- 0,
- 0,
- OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
- 0);
- Py_END_ALLOW_THREADS
-
- if (reparse_point_handle==INVALID_HANDLE_VALUE)
- return win32_error_object("readlink", po);
-
- Py_BEGIN_ALLOW_THREADS
- /* New call DeviceIoControl to read the reparse point */
- io_result = DeviceIoControl(
- reparse_point_handle,
- FSCTL_GET_REPARSE_POINT,
- 0, 0, /* in buffer */
- target_buffer, sizeof(target_buffer),
- &n_bytes_returned,
- 0 /* we're not using OVERLAPPED_IO */
- );
- CloseHandle(reparse_point_handle);
- Py_END_ALLOW_THREADS
-
- if (io_result==0)
- return win32_error_object("readlink", po);
-
- if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
- {
- PyErr_SetString(PyExc_ValueError,
- "not a symbolic link");
- return NULL;
- }
- print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
- rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
-
- result = PyUnicode_FromWideChar(print_name,
- rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
- return result;
-}
-
-#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
static PyStructSequence_Field times_result_fields[] = {
@@ -7550,15 +7478,26 @@ build_times_result(double user, double system,
return value;
}
-PyDoc_STRVAR(posix_times__doc__,
-"times() -> times_result\n\n\
-Return an object containing floating point numbers indicating process\n\
-times. The object behaves like a named tuple with these fields:\n\
- (utime, stime, cutime, cstime, elapsed_time)");
-#if defined(MS_WINDOWS)
+#ifndef MS_WINDOWS
+#define NEED_TICKS_PER_SECOND
+static long ticks_per_second = -1;
+#endif /* MS_WINDOWS */
+
+/*[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 *
-posix_times(PyObject *self, PyObject *noargs)
+os_times_impl(PyModuleDef *module)
+/*[clinic end generated code: output=df0a63ebe6e6f091 input=2bf9df3d6ab2e48b]*/
+#ifdef MS_WINDOWS
{
FILETIME create, exit, kernel, user;
HANDLE hProc;
@@ -7578,12 +7517,10 @@ posix_times(PyObject *self, PyObject *noargs)
(double)0,
(double)0);
}
-#else /* Not Windows */
-#define NEED_TICKS_PER_SECOND
-static long ticks_per_second = -1;
-static PyObject *
-posix_times(PyObject *self, PyObject *noargs)
+#else /* MS_WINDOWS */
{
+
+
struct tms t;
clock_t c;
errno = 0;
@@ -7597,23 +7534,25 @@ posix_times(PyObject *self, PyObject *noargs)
(double)t.tms_cstime / ticks_per_second,
(double)c / ticks_per_second);
}
-#endif
-
+#endif /* MS_WINDOWS */
#endif /* HAVE_TIMES */
#ifdef HAVE_GETSID
-PyDoc_STRVAR(posix_getsid__doc__,
-"getsid(pid) -> sid\n\n\
-Call the system call getsid().");
+/*[clinic input]
+os.getsid
+
+ pid: pid_t
+ /
+
+Call the system call getsid(pid) and return the result.
+[clinic start generated code]*/
static PyObject *
-posix_getsid(PyObject *self, PyObject *args)
+os_getsid_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=a074f80c0e6bfb38 input=eeb2b923a30ce04e]*/
{
- pid_t pid;
int sid;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getsid", &pid))
- return NULL;
sid = getsid(pid);
if (sid < 0)
return posix_error();
@@ -7623,53 +7562,60 @@ posix_getsid(PyObject *self, PyObject *args)
#ifdef HAVE_SETSID
-PyDoc_STRVAR(posix_setsid__doc__,
-"setsid()\n\n\
-Call the system call setsid().");
+/*[clinic input]
+os.setsid
+
+Call the system call setsid().
+[clinic start generated code]*/
static PyObject *
-posix_setsid(PyObject *self, PyObject *noargs)
+os_setsid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=398fc152ae327330 input=5fff45858e2f0776]*/
{
if (setsid() < 0)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETSID */
+
#ifdef HAVE_SETPGID
-PyDoc_STRVAR(posix_setpgid__doc__,
-"setpgid(pid, pgrp)\n\n\
-Call the system call setpgid().");
+/*[clinic input]
+os.setpgid
+
+ pid: pid_t
+ pgrp: pid_t
+ /
+
+Call the system call setpgid(pid, pgrp).
+[clinic start generated code]*/
static PyObject *
-posix_setpgid(PyObject *self, PyObject *args)
+os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp)
+/*[clinic end generated code: output=7079a8e932912841 input=fceb395eca572e1a]*/
{
- pid_t pid;
- int pgrp;
- if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:setpgid", &pid, &pgrp))
- return NULL;
if (setpgid(pid, pgrp) < 0)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* HAVE_SETPGID */
#ifdef HAVE_TCGETPGRP
-PyDoc_STRVAR(posix_tcgetpgrp__doc__,
-"tcgetpgrp(fd) -> pgid\n\n\
-Return the process group associated with the terminal given by a fd.");
+/*[clinic input]
+os.tcgetpgrp
+
+ fd: int
+ /
+
+Return the process group associated with the terminal specified by fd.
+[clinic start generated code]*/
static PyObject *
-posix_tcgetpgrp(PyObject *self, PyObject *args)
+os_tcgetpgrp_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=ebb6dc5f111c7dc0 input=7f6c18eac10ada86]*/
{
- int fd;
- pid_t pgid;
- if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
- return NULL;
- pgid = tcgetpgrp(fd);
+ pid_t pgid = tcgetpgrp(fd);
if (pgid < 0)
return posix_error();
return PyLong_FromPid(pgid);
@@ -7678,21 +7624,23 @@ posix_tcgetpgrp(PyObject *self, PyObject *args)
#ifdef HAVE_TCSETPGRP
-PyDoc_STRVAR(posix_tcsetpgrp__doc__,
-"tcsetpgrp(fd, pgid)\n\n\
-Set the process group associated with the terminal given by a fd.");
+/*[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 *
-posix_tcsetpgrp(PyObject *self, PyObject *args)
+os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid)
+/*[clinic end generated code: output=3e4b05177462cd22 input=5bdc997c6a619020]*/
{
- int fd;
- pid_t pgid;
- if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid))
- return NULL;
if (tcsetpgrp(fd, pgid) < 0)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
#endif /* HAVE_TCSETPGRP */
@@ -7702,121 +7650,122 @@ posix_tcsetpgrp(PyObject *self, PyObject *args)
extern int _Py_open_cloexec_works;
#endif
-PyDoc_STRVAR(posix_open__doc__,
-"open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
-Open a file for low level IO. Returns a file handle (integer).\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
-static PyObject *
-posix_open(PyObject *self, PyObject *args, PyObject *kwargs)
+/*[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(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd)
+/*[clinic end generated code: output=c95a64f0e62f199b input=ad8623b29acd2934]*/
{
- path_t path;
- int flags;
- int mode = 0777;
- int dir_fd = DEFAULT_DIR_FD;
int fd;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
+ int async_err = 0;
+
#ifdef O_CLOEXEC
int *atomic_flag_works = &_Py_open_cloexec_works;
#elif !defined(MS_WINDOWS)
int *atomic_flag_works = NULL;
#endif
- memset(&path, 0, sizeof(path));
- path.function_name = "open";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|i$O&:open", keywords,
- path_converter, &path,
- &flags, &mode,
-#ifdef HAVE_OPENAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
-
#ifdef MS_WINDOWS
flags |= O_NOINHERIT;
#elif defined(O_CLOEXEC)
flags |= O_CLOEXEC;
#endif
- Py_BEGIN_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- if (path.wide)
- fd = _wopen(path.wide, flags, mode);
- else
+ if (path->wide)
+ fd = _wopen(path->wide, flags, mode);
+ else
#endif
#ifdef HAVE_OPENAT
- if (dir_fd != DEFAULT_DIR_FD)
- fd = openat(dir_fd, path.narrow, flags, mode);
- else
+ if (dir_fd != DEFAULT_DIR_FD)
+ fd = openat(dir_fd, path->narrow, flags, mode);
+ else
#endif
- fd = open(path.narrow, flags, mode);
- Py_END_ALLOW_THREADS
+ fd = open(path->narrow, flags, mode);
+ Py_END_ALLOW_THREADS
+ } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (fd == -1) {
- PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path.object);
- goto exit;
+ if (!async_err)
+ PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
+ return -1;
}
#ifndef MS_WINDOWS
if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
close(fd);
- goto exit;
+ return -1;
}
#endif
- return_value = PyLong_FromLong((long)fd);
-
-exit:
- path_cleanup(&path);
- return return_value;
+ return fd;
}
-PyDoc_STRVAR(posix_close__doc__,
-"close(fd)\n\n\
-Close a file descriptor (for low level IO).");
-/*
-The underscore at end of function name avoids a name clash with the libc
-function posix_close.
-*/
+/*[clinic input]
+os.close
+
+ fd: int
+
+Close a file descriptor.
+[clinic start generated code]*/
+
static PyObject *
-posix_close_(PyObject *self, PyObject *args)
+os_close_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=47bf2ea536445a26 input=2bc42451ca5c3223]*/
{
- int fd, res;
- if (!PyArg_ParseTuple(args, "i:close", &fd))
- return NULL;
+ int res;
if (!_PyVerify_fd(fd))
return posix_error();
+ /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
+ * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
+ * for more details.
+ */
Py_BEGIN_ALLOW_THREADS
res = close(fd);
Py_END_ALLOW_THREADS
if (res < 0)
return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
-PyDoc_STRVAR(posix_closerange__doc__,
-"closerange(fd_low, fd_high)\n\n\
-Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
+/*[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 *
-posix_closerange(PyObject *self, PyObject *args)
+os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high)
+/*[clinic end generated code: output=70e6adb95220ba96 input=5855a3d053ebd4ec]*/
{
- int fd_from, fd_to, i;
- if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
- return NULL;
+ int i;
Py_BEGIN_ALLOW_THREADS
- for (i = fd_from; i < fd_to; i++)
+ for (i = fd_low; i < fd_high; i++)
if (_PyVerify_fd(i))
close(i);
Py_END_ALLOW_THREADS
@@ -7824,36 +7773,36 @@ posix_closerange(PyObject *self, PyObject *args)
}
-PyDoc_STRVAR(posix_dup__doc__,
-"dup(fd) -> fd2\n\n\
-Return a duplicate of a file descriptor.");
-
-static PyObject *
-posix_dup(PyObject *self, PyObject *args)
-{
- int fd;
+/*[clinic input]
+os.dup -> int
- if (!PyArg_ParseTuple(args, "i:dup", &fd))
- return NULL;
+ fd: int
+ /
- fd = _Py_dup(fd);
- if (fd == -1)
- return NULL;
+Return a duplicate of a file descriptor.
+[clinic start generated code]*/
- return PyLong_FromLong((long)fd);
+static int
+os_dup_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=f4bbac8c7652d05e input=6f10f7ea97f7852a]*/
+{
+ return _Py_dup(fd);
}
-PyDoc_STRVAR(posix_dup2__doc__,
-"dup2(old_fd, new_fd)\n\n\
-Duplicate file descriptor.");
+/*[clinic input]
+os.dup2
+ fd: int
+ fd2: int
+ inheritable: bool=True
+
+Duplicate file descriptor.
+[clinic start generated code]*/
static PyObject *
-posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs)
+os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable)
+/*[clinic end generated code: output=9a099d95881a7923 input=76e96f511be0352f]*/
{
- static char *keywords[] = {"fd", "fd2", "inheritable", NULL};
- int fd, fd2;
- int inheritable = 1;
int res;
#if defined(HAVE_DUP3) && \
!(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
@@ -7861,13 +7810,13 @@ posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs)
int dup3_works = -1;
#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:dup2", keywords,
- &fd, &fd2, &inheritable))
- return NULL;
-
if (!_PyVerify_fd_dup2(fd, fd2))
return posix_error();
+ /* dup2() can fail with EINTR if the target FD is already open, because it
+ * then has to be closed. See os_close_impl() for why we don't handle EINTR
+ * upon close(), and therefore below.
+ */
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
res = dup2(fd, fd2);
@@ -7925,30 +7874,34 @@ posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs)
#endif
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
+
#ifdef HAVE_LOCKF
-PyDoc_STRVAR(posix_lockf__doc__,
-"lockf(fd, cmd, len)\n\n\
-Apply, test or remove a POSIX lock on an open file descriptor.\n\n\
-fd is an open file descriptor.\n\
-cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\
-F_TEST.\n\
-len specifies the section of the file to lock.");
+/*[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 *
-posix_lockf(PyObject *self, PyObject *args)
+os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length)
+/*[clinic end generated code: output=25ff778f9e2fbf1b input=65da41d2106e9b79]*/
{
- int fd, cmd, res;
- off_t len;
- if (!PyArg_ParseTuple(args, "iiO&:lockf",
- &fd, &cmd, _parse_off_t, &len))
- return NULL;
+ int res;
Py_BEGIN_ALLOW_THREADS
- res = lockf(fd, cmd, len);
+ res = lockf(fd, command, length);
Py_END_ALLOW_THREADS
if (res < 0)
@@ -7956,95 +7909,103 @@ posix_lockf(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_LOCKF */
-PyDoc_STRVAR(posix_lseek__doc__,
-"lseek(fd, pos, how) -> newpos\n\n\
-Set the current position of a file descriptor.\n\
-Return the new cursor position in bytes, starting from the beginning.");
+/*[clinic input]
+os.lseek -> Py_off_t
-static PyObject *
-posix_lseek(PyObject *self, PyObject *args)
+ fd: int
+ position: Py_off_t
+ how: int
+ /
+
+Set the position of a file descriptor. Return the new position.
+
+Return the new cursor position in number of bytes
+relative to the beginning of the file.
+[clinic start generated code]*/
+
+static Py_off_t
+os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how)
+/*[clinic end generated code: output=65d4ab96d664998c input=902654ad3f96a6d3]*/
{
- int fd, how;
-#ifdef MS_WINDOWS
- PY_LONG_LONG pos, res;
-#else
- off_t pos, res;
-#endif
- PyObject *posobj;
- if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
- return NULL;
+ Py_off_t result;
+
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return -1;
+ }
#ifdef SEEK_SET
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
switch (how) {
- case 0: how = SEEK_SET; break;
- case 1: how = SEEK_CUR; break;
- case 2: how = SEEK_END; break;
+ case 0: how = SEEK_SET; break;
+ case 1: how = SEEK_CUR; break;
+ case 2: how = SEEK_END; break;
}
#endif /* SEEK_END */
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- pos = PyLong_AsLong(posobj);
-#else
- pos = PyLong_AsLongLong(posobj);
-#endif
if (PyErr_Occurred())
- return NULL;
+ return -1;
- if (!_PyVerify_fd(fd))
- return posix_error();
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return -1;
+ }
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
- res = _lseeki64(fd, pos, how);
+ result = _lseeki64(fd, position, how);
#else
- res = lseek(fd, pos, how);
+ result = lseek(fd, position, how);
#endif
Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+ if (result < 0)
+ posix_error();
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- return PyLong_FromLong(res);
-#else
- return PyLong_FromLongLong(res);
-#endif
+ return result;
}
-PyDoc_STRVAR(posix_read__doc__,
-"read(fd, buffersize) -> bytes\n\n\
-Read a file descriptor.");
+/*[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 *
-posix_read(PyObject *self, PyObject *args)
+os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length)
+/*[clinic end generated code: output=be24f44178455e8b input=1df2eaa27c0bf1d3]*/
{
- int fd, size;
Py_ssize_t n;
PyObject *buffer;
- if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
- return NULL;
- if (size < 0) {
+
+ if (length < 0) {
errno = EINVAL;
return posix_error();
}
- buffer = PyBytes_FromStringAndSize((char *)NULL, size);
+
+#ifdef MS_WINDOWS
+ /* On Windows, the count parameter of read() is an int */
+ if (length > INT_MAX)
+ length = INT_MAX;
+#endif
+
+ buffer = PyBytes_FromStringAndSize((char *)NULL, length);
if (buffer == NULL)
return NULL;
- if (!_PyVerify_fd(fd)) {
- Py_DECREF(buffer);
- return posix_error();
- }
- Py_BEGIN_ALLOW_THREADS
- n = read(fd, PyBytes_AS_STRING(buffer), size);
- Py_END_ALLOW_THREADS
- if (n < 0) {
+
+ n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
+ if (n == -1) {
Py_DECREF(buffer);
- return posix_error();
+ return NULL;
}
- if (n != size)
+
+ if (n != length)
_PyBytes_Resize(&buffer, n);
+
return buffer;
}
@@ -8106,120 +8067,133 @@ iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
}
#endif
+
#ifdef HAVE_READV
-PyDoc_STRVAR(posix_readv__doc__,
-"readv(fd, buffers) -> bytesread\n\n\
-Read from a file descriptor fd into a number of mutable, bytes-like\n\
-objects (\"buffers\"). readv will transfer data into each buffer\n\
-until it is full and then move on to the next buffer in the sequence\n\
-to hold the rest of the data.\n\n\
-readv returns the total number of bytes read (which may be less than\n\
-the total capacity of all the buffers.");
+/*[clinic input]
+os.readv -> Py_ssize_t
-static PyObject *
-posix_readv(PyObject *self, PyObject *args)
+ 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(PyModuleDef *module, int fd, PyObject *buffers)
+/*[clinic end generated code: output=00fc56ff1800059f input=e679eb5dbfa0357d]*/
{
- int fd, cnt;
+ int cnt;
Py_ssize_t n;
- PyObject *seq;
+ int async_err = 0;
struct iovec *iov;
Py_buffer *buf;
- if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq))
- return NULL;
- if (!PySequence_Check(seq)) {
+ if (!PySequence_Check(buffers)) {
PyErr_SetString(PyExc_TypeError,
"readv() arg 2 must be a sequence");
- return NULL;
+ return -1;
}
- cnt = PySequence_Size(seq);
- if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0)
- return NULL;
+ cnt = PySequence_Size(buffers);
- Py_BEGIN_ALLOW_THREADS
- n = readv(fd, iov, cnt);
- Py_END_ALLOW_THREADS
+ if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
+ return -1;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ n = readv(fd, iov, cnt);
+ Py_END_ALLOW_THREADS
+ } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
iov_cleanup(iov, buf, cnt);
- if (n < 0)
- return posix_error();
+ if (n < 0) {
+ if (!async_err)
+ posix_error();
+ return -1;
+ }
- return PyLong_FromSsize_t(n);
+ return n;
}
-#endif
+#endif /* HAVE_READV */
+
#ifdef HAVE_PREAD
-PyDoc_STRVAR(posix_pread__doc__,
-"pread(fd, buffersize, offset) -> string\n\n\
-Read from a file descriptor, fd, at a position of offset. It will read up\n\
-to buffersize number of bytes. The file offset remains unchanged.");
+/*[clinic input]
+# TODO length should be size_t! but Python doesn't support parsing size_t yet.
+os.pread
+
+ fd: int
+ length: int
+ 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 *
-posix_pread(PyObject *self, PyObject *args)
+os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset)
+/*[clinic end generated code: output=90d1fed87f68fa33 input=084948dcbaa35d4c]*/
{
- int fd, size;
- off_t offset;
Py_ssize_t n;
+ int async_err = 0;
PyObject *buffer;
- if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset))
- return NULL;
- if (size < 0) {
+ if (length < 0) {
errno = EINVAL;
return posix_error();
}
- buffer = PyBytes_FromStringAndSize((char *)NULL, size);
+ buffer = PyBytes_FromStringAndSize((char *)NULL, length);
if (buffer == NULL)
return NULL;
if (!_PyVerify_fd(fd)) {
Py_DECREF(buffer);
return posix_error();
}
- Py_BEGIN_ALLOW_THREADS
- n = pread(fd, PyBytes_AS_STRING(buffer), size, offset);
- Py_END_ALLOW_THREADS
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
+ Py_END_ALLOW_THREADS
+ } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
if (n < 0) {
Py_DECREF(buffer);
- return posix_error();
+ return (!async_err) ? posix_error() : NULL;
}
- if (n != size)
+ if (n != length)
_PyBytes_Resize(&buffer, n);
return buffer;
}
-#endif
+#endif /* HAVE_PREAD */
-PyDoc_STRVAR(posix_write__doc__,
-"write(fd, data) -> byteswritten\n\n\
-Write bytes to a file descriptor.");
-static PyObject *
-posix_write(PyObject *self, PyObject *args)
-{
- Py_buffer pbuf;
- int fd;
- Py_ssize_t size, len;
+/*[clinic input]
+os.write -> Py_ssize_t
- if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
- return NULL;
- if (!_PyVerify_fd(fd)) {
- PyBuffer_Release(&pbuf);
- return posix_error();
- }
- len = pbuf.len;
- Py_BEGIN_ALLOW_THREADS
-#ifdef MS_WINDOWS
- if (len > INT_MAX)
- len = INT_MAX;
- size = write(fd, pbuf.buf, (int)len);
-#else
- size = write(fd, pbuf.buf, len);
-#endif
- Py_END_ALLOW_THREADS
- PyBuffer_Release(&pbuf);
- if (size < 0)
- return posix_error();
- return PyLong_FromSsize_t(size);
+ fd: int
+ data: Py_buffer
+ /
+
+Write a bytes object to a file descriptor.
+[clinic start generated code]*/
+
+static Py_ssize_t
+os_write_impl(PyModuleDef *module, int fd, Py_buffer *data)
+/*[clinic end generated code: output=58845c93c9ee1dda input=3207e28963234f3c]*/
+{
+ return _Py_write(fd, data->buf, data->len);
}
#ifdef HAVE_SENDFILE
@@ -8229,11 +8203,13 @@ sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
-> byteswritten\n\
Copy nbytes bytes from file descriptor in to file descriptor out.");
+/* AC 3.5: don't bother converting, has optional group*/
static PyObject *
posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
{
int in, out;
Py_ssize_t ret;
+ int async_err = 0;
off_t offset;
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
@@ -8254,10 +8230,10 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
#ifdef __APPLE__
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
- keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes,
+ keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
#else
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
- keywords, &out, &in, _parse_off_t, &offset, &len,
+ keywords, &out, &in, Py_off_t_converter, &offset, &len,
#endif
&headers, &trailers, &flags))
return NULL;
@@ -8296,13 +8272,15 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
}
}
- Py_BEGIN_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
#ifdef __APPLE__
- ret = sendfile(in, out, offset, &sbytes, &sf, flags);
+ ret = sendfile(in, out, offset, &sbytes, &sf, flags);
#else
- ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
+ ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
#endif
- Py_END_ALLOW_THREADS
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (sf.headers != NULL)
iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
@@ -8321,7 +8299,7 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
return posix_error();
}
}
- return posix_error();
+ return (!async_err) ? posix_error() : NULL;
}
goto done;
@@ -8342,76 +8320,102 @@ done:
return NULL;
#ifdef linux
if (offobj == Py_None) {
- Py_BEGIN_ALLOW_THREADS
- ret = sendfile(out, in, NULL, count);
- Py_END_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = sendfile(out, in, NULL, count);
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (ret < 0)
- return posix_error();
+ return (!async_err) ? posix_error() : NULL;
return Py_BuildValue("n", ret);
}
#endif
- if (!_parse_off_t(offobj, &offset))
+ if (!Py_off_t_converter(offobj, &offset))
return NULL;
- Py_BEGIN_ALLOW_THREADS
- ret = sendfile(out, in, &offset, count);
- Py_END_ALLOW_THREADS
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = sendfile(out, in, &offset, count);
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (ret < 0)
- return posix_error();
+ return (!async_err) ? posix_error() : NULL;
return Py_BuildValue("n", ret);
#endif
}
-#endif
+#endif /* HAVE_SENDFILE */
-PyDoc_STRVAR(posix_fstat__doc__,
-"fstat(fd) -> stat result\n\n\
-Like stat(), but for an open file descriptor.\n\
-Equivalent to stat(fd=fd).");
+
+/*[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 *
-posix_fstat(PyObject *self, PyObject *args)
+os_fstat_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=d71fe98bf042b626 input=27e0e0ebbe5600c9]*/
{
- int fd;
STRUCT_STAT st;
int res;
- if (!PyArg_ParseTuple(args, "i:fstat", &fd))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = FSTAT(fd, &st);
- Py_END_ALLOW_THREADS
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = FSTAT(fd, &st);
+ Py_END_ALLOW_THREADS
+ } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (res != 0) {
#ifdef MS_WINDOWS
return PyErr_SetFromWindowsErr(0);
#else
- return posix_error();
+ return (!async_err) ? posix_error() : NULL;
#endif
}
return _pystat_fromstructstat(&st);
}
-PyDoc_STRVAR(posix_isatty__doc__,
-"isatty(fd) -> bool\n\n\
-Return True if the file descriptor 'fd' is an open file descriptor\n\
-connected to the slave end of a terminal.");
-static PyObject *
-posix_isatty(PyObject *self, PyObject *args)
+/*[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(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=acec9d3c29d16d33 input=08ce94aa1eaf7b5e]*/
{
- int fd;
- if (!PyArg_ParseTuple(args, "i:isatty", &fd))
- return NULL;
if (!_PyVerify_fd(fd))
- return PyBool_FromLong(0);
- return PyBool_FromLong(isatty(fd));
+ return 0;
+ return isatty(fd);
}
+
#ifdef HAVE_PIPE
-PyDoc_STRVAR(posix_pipe__doc__,
-"pipe() -> (read_end, write_end)\n\n\
-Create a 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 *
-posix_pipe(PyObject *self, PyObject *noargs)
+os_pipe_impl(PyModuleDef *module)
+/*[clinic end generated code: output=6b0cd3f868ec3c40 input=02535e8c8fa6c4d4]*/
{
int fds[2];
#ifdef MS_WINDOWS
@@ -8479,25 +8483,30 @@ posix_pipe(PyObject *self, PyObject *noargs)
}
#endif /* HAVE_PIPE */
+
#ifdef HAVE_PIPE2
-PyDoc_STRVAR(posix_pipe2__doc__,
-"pipe2(flags) -> (read_end, write_end)\n\n\
-Create a pipe with flags set atomically.\n\
-flags can be constructed by ORing together one or more of these values:\n\
-O_NONBLOCK, O_CLOEXEC.\n\
-");
+/*[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 *
-posix_pipe2(PyObject *self, PyObject *arg)
+os_pipe2_impl(PyModuleDef *module, int flags)
+/*[clinic end generated code: output=c15b6075d0c6b2e7 input=f261b6e7e63c6817]*/
{
- int flags;
int fds[2];
int res;
- flags = _PyLong_AsInt(arg);
- if (flags == -1 && PyErr_Occurred())
- return NULL;
-
res = pipe2(fds, flags);
if (res != 0)
return posix_error();
@@ -8505,306 +8514,309 @@ posix_pipe2(PyObject *self, PyObject *arg)
}
#endif /* HAVE_PIPE2 */
+
#ifdef HAVE_WRITEV
-PyDoc_STRVAR(posix_writev__doc__,
-"writev(fd, buffers) -> byteswritten\n\n\
-Write the contents of *buffers* to file descriptor *fd*. *buffers*\n\
-must be a sequence of bytes-like objects.\n\n\
-writev writes the contents of each object to the file descriptor\n\
-and returns the total number of bytes written.");
+/*[clinic input]
+os.writev -> Py_ssize_t
+ fd: int
+ buffers: object
+ /
-static PyObject *
-posix_writev(PyObject *self, PyObject *args)
+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(PyModuleDef *module, int fd, PyObject *buffers)
+/*[clinic end generated code: output=a48925dbf2d5c238 input=5b8d17fe4189d2fe]*/
{
- int fd, cnt;
- Py_ssize_t res;
- PyObject *seq;
+ int cnt;
+ Py_ssize_t result;
+ int async_err = 0;
struct iovec *iov;
Py_buffer *buf;
- if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq))
- return NULL;
- if (!PySequence_Check(seq)) {
+
+ if (!PySequence_Check(buffers)) {
PyErr_SetString(PyExc_TypeError,
"writev() arg 2 must be a sequence");
- return NULL;
+ return -1;
}
- cnt = PySequence_Size(seq);
+ cnt = PySequence_Size(buffers);
- if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) {
- return NULL;
+ if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
+ return -1;
}
- Py_BEGIN_ALLOW_THREADS
- res = writev(fd, iov, cnt);
- Py_END_ALLOW_THREADS
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = writev(fd, iov, cnt);
+ Py_END_ALLOW_THREADS
+ } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
iov_cleanup(iov, buf, cnt);
- if (res < 0)
- return posix_error();
+ if (result < 0 && !async_err)
+ posix_error();
- return PyLong_FromSsize_t(res);
+ return result;
}
-#endif
+#endif /* HAVE_WRITEV */
+
#ifdef HAVE_PWRITE
-PyDoc_STRVAR(posix_pwrite__doc__,
-"pwrite(fd, string, offset) -> byteswritten\n\n\
-Write string to a file descriptor, fd, from offset, leaving the file\n\
-offset unchanged.");
+/*[clinic input]
+os.pwrite -> Py_ssize_t
-static PyObject *
-posix_pwrite(PyObject *self, PyObject *args)
+ 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 writte. Does not change the
+current file offset.
+[clinic start generated code]*/
+
+static Py_ssize_t
+os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset)
+/*[clinic end generated code: output=95225f3b496feaf3 input=19903f1b3dd26377]*/
{
- Py_buffer pbuf;
- int fd;
- off_t offset;
Py_ssize_t size;
-
- if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset))
- return NULL;
+ int async_err = 0;
if (!_PyVerify_fd(fd)) {
- PyBuffer_Release(&pbuf);
- return posix_error();
+ posix_error();
+ return -1;
}
- Py_BEGIN_ALLOW_THREADS
- size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset);
- Py_END_ALLOW_THREADS
- PyBuffer_Release(&pbuf);
- if (size < 0)
- return posix_error();
- return PyLong_FromSsize_t(size);
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
+ Py_END_ALLOW_THREADS
+ } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (size < 0 && !async_err)
+ posix_error();
+ return size;
}
-#endif
+#endif /* HAVE_PWRITE */
+
#ifdef HAVE_MKFIFO
-PyDoc_STRVAR(posix_mkfifo__doc__,
-"mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\
-Create a FIFO (a POSIX named pipe).\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
+/*[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 *
-posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs)
+os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd)
+/*[clinic end generated code: output=8f5f5e72c630049a input=73032e98a36e0e19]*/
{
- path_t path;
- int mode = 0666;
- int dir_fd = DEFAULT_DIR_FD;
int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "mode", "dir_fd", NULL};
+ int async_err = 0;
- memset(&path, 0, sizeof(path));
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords,
- path_converter, &path,
- &mode,
+ do {
+ Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_MKFIFOAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
+ if (dir_fd != DEFAULT_DIR_FD)
+ result = mkfifoat(dir_fd, path->narrow, mode);
+ else
#endif
- ))
- return NULL;
+ result = mkfifo(path->narrow, mode);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
- Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_MKFIFOAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = mkfifoat(dir_fd, path.narrow, mode);
- else
-#endif
- result = mkfifo(path.narrow, mode);
- Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_MKFIFO */
- if (result < 0) {
- return_value = posix_error();
- goto exit;
- }
- return_value = Py_None;
- Py_INCREF(Py_None);
+#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
+/*[clinic input]
+os.mknod
-exit:
- path_cleanup(&path);
- return return_value;
-}
-#endif
+ path: path_t
+ mode: int=0o600
+ device: dev_t=0
+ *
+ dir_fd: dir_fd(requires='mknodat')=None
-#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
-PyDoc_STRVAR(posix_mknod__doc__,
-"mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\
-Create a filesystem node (file, device special file or named pipe)\n\
-named filename. mode specifies both the permissions to use and the\n\
-type of node to be created, being combined (bitwise OR) with one of\n\
-S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
-device defines the newly created device special file (probably using\n\
-os.makedev()), otherwise it is ignored.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
+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 *
-posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs)
+os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd)
+/*[clinic end generated code: output=f7f813e8847de12f input=ee44531551a4d83b]*/
{
- path_t path;
- int mode = 0666;
- dev_t device = 0;
- int dir_fd = DEFAULT_DIR_FD;
int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL};
+ int async_err = 0;
- memset(&path, 0, sizeof(path));
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", keywords,
- path_converter, &path,
- &mode, _Py_Dev_Converter, &device,
+ do {
+ Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_MKNODAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
+ if (dir_fd != DEFAULT_DIR_FD)
+ result = mknodat(dir_fd, path->narrow, mode, device);
+ else
#endif
- ))
- return NULL;
+ result = mknod(path->narrow, mode, device);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
- Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_MKNODAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = mknodat(dir_fd, path.narrow, mode, device);
- else
-#endif
- result = mknod(path.narrow, mode, device);
- Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
- if (result < 0) {
- return_value = posix_error();
- goto exit;
- }
- return_value = Py_None;
- Py_INCREF(Py_None);
+#ifdef HAVE_DEVICE_MACROS
+/*[clinic input]
+os.major -> unsigned_int
-exit:
- path_cleanup(&path);
- return return_value;
-}
-#endif
+ device: dev_t
+ /
-#ifdef HAVE_DEVICE_MACROS
-PyDoc_STRVAR(posix_major__doc__,
-"major(device) -> major number\n\
-Extracts a device major number from a raw device number.");
+Extracts a device major number from a raw device number.
+[clinic start generated code]*/
-static PyObject *
-posix_major(PyObject *self, PyObject *args)
+static unsigned int
+os_major_impl(PyModuleDef *module, dev_t device)
+/*[clinic end generated code: output=ba55693ab49bac34 input=1e16a4d30c4d4462]*/
{
- dev_t device;
- if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device))
- return NULL;
- return PyLong_FromLong((long)major(device));
+ return major(device);
}
-PyDoc_STRVAR(posix_minor__doc__,
-"minor(device) -> minor number\n\
-Extracts a device minor number from a raw device number.");
-static PyObject *
-posix_minor(PyObject *self, PyObject *args)
+/*[clinic input]
+os.minor -> unsigned_int
+
+ device: dev_t
+ /
+
+Extracts a device minor number from a raw device number.
+[clinic start generated code]*/
+
+static unsigned int
+os_minor_impl(PyModuleDef *module, dev_t device)
+/*[clinic end generated code: output=2867219ebf274e27 input=0842c6d23f24c65e]*/
{
- dev_t device;
- if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device))
- return NULL;
- return PyLong_FromLong((long)minor(device));
+ return minor(device);
}
-PyDoc_STRVAR(posix_makedev__doc__,
-"makedev(major, minor) -> device number\n\
-Composes a raw device number from the major and minor device numbers.");
-static PyObject *
-posix_makedev(PyObject *self, PyObject *args)
+/*[clinic input]
+os.makedev -> dev_t
+
+ major: int
+ minor: int
+ /
+
+Composes a raw device number from the major and minor device numbers.
+[clinic start generated code]*/
+
+static dev_t
+os_makedev_impl(PyModuleDef *module, int major, int minor)
+/*[clinic end generated code: output=7cb6264352437660 input=4b9fd8fc73cbe48f]*/
{
- int major, minor;
- if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
- return NULL;
- return _PyLong_FromDev(makedev(major, minor));
+ return makedev(major, minor);
}
-#endif /* device macros */
+#endif /* HAVE_DEVICE_MACROS */
#ifdef HAVE_FTRUNCATE
-PyDoc_STRVAR(posix_ftruncate__doc__,
-"ftruncate(fd, length)\n\n\
-Truncate a file to a specified length.");
+/*[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 *
-posix_ftruncate(PyObject *self, PyObject *args)
+os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length)
+/*[clinic end generated code: output=3666f401d76bf834 input=63b43641e52818f2]*/
{
- int fd;
- off_t length;
- int res;
-
- if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length))
- return NULL;
+ int result;
+ int async_err = 0;
- Py_BEGIN_ALLOW_THREADS
- res = ftruncate(fd, length);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = ftruncate(fd, length);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+ Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_FTRUNCATE */
+
#ifdef HAVE_TRUNCATE
-PyDoc_STRVAR(posix_truncate__doc__,
-"truncate(path, length)\n\n\
-Truncate the file given by path to length bytes.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
+/*[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 *
-posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
+os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length)
+/*[clinic end generated code: output=f60a9e08370e9e2e input=77229cf0b50a9b77]*/
{
- path_t path;
- off_t length;
- int res;
- PyObject *result = NULL;
- static char *keywords[] = {"path", "length", NULL};
-
- memset(&path, 0, sizeof(path));
- path.function_name = "truncate";
-#ifdef HAVE_FTRUNCATE
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords,
- path_converter, &path,
- _parse_off_t, &length))
- return NULL;
+ int result;
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FTRUNCATE
- if (path.fd != -1)
- res = ftruncate(path.fd, length);
+ if (path->fd != -1)
+ result = ftruncate(path->fd, length);
else
#endif
- res = truncate(path.narrow, length);
+ result = truncate(path->narrow, length);
Py_END_ALLOW_THREADS
- if (res < 0)
- result = path_error(&path);
- else {
- Py_INCREF(Py_None);
- result = Py_None;
- }
- path_cleanup(&path);
- return result;
+ if (result < 0)
+ return path_error(path);
+
+ Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_TRUNCATE */
+
/* 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
@@ -8814,186 +8826,209 @@ posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
# define POSIX_FADVISE_AIX_BUG
#endif
+
#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
-PyDoc_STRVAR(posix_posix_fallocate__doc__,
-"posix_fallocate(fd, offset, len)\n\n\
-Ensures that enough disk space is allocated for the file specified by fd\n\
-starting from offset and continuing for len bytes.");
+/*[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 *
-posix_posix_fallocate(PyObject *self, PyObject *args)
+os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length)
+/*[clinic end generated code: output=8ae5f7837004d454 input=d7a2ef0ab2ca52fb]*/
{
- off_t len, offset;
- int res, fd;
-
- if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate",
- &fd, _parse_off_t, &offset, _parse_off_t, &len))
- return NULL;
+ int result;
+ int async_err = 0;
- Py_BEGIN_ALLOW_THREADS
- res = posix_fallocate(fd, offset, len);
- Py_END_ALLOW_THREADS
- if (res != 0) {
- errno = res;
- return posix_error();
- }
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = posix_fallocate(fd, offset, length);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
+
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
-PyDoc_STRVAR(posix_posix_fadvise__doc__,
-"posix_fadvise(fd, offset, len, advice)\n\n\
-Announces an intention to access data in a specific pattern thus allowing\n\
-the kernel to make optimizations.\n\
-The advice applies to the region of the file specified by fd starting at\n\
-offset and continuing for len bytes.\n\
-advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\
-POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\
-POSIX_FADV_DONTNEED.");
+/*[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 *
-posix_posix_fadvise(PyObject *self, PyObject *args)
+os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice)
+/*[clinic end generated code: output=0e3f09f651661257 input=0fbe554edc2f04b5]*/
{
- off_t len, offset;
- int res, fd, advice;
-
- if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise",
- &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice))
- return NULL;
+ int result;
+ int async_err = 0;
- Py_BEGIN_ALLOW_THREADS
- res = posix_fadvise(fd, offset, len, advice);
- Py_END_ALLOW_THREADS
- if (res != 0) {
- errno = res;
- return posix_error();
- }
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = posix_fadvise(fd, offset, length, advice);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
#ifdef HAVE_PUTENV
-PyDoc_STRVAR(posix_putenv__doc__,
-"putenv(key, value)\n\n\
-Change or add an environment variable.");
/* Save putenv() parameters as values here, so we can collect them when they
* get re-set with another call for the same key. */
static PyObject *posix_putenv_garbage;
-static PyObject *
-posix_putenv(PyObject *self, PyObject *args)
+static void
+posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
{
- PyObject *newstr = NULL;
+ /* Install the first arg and newstr in posix_putenv_garbage;
+ * this will cause previous value to be collected. This has to
+ * happen after the real putenv() call because the old value
+ * was still accessible until then. */
+ if (PyDict_SetItem(posix_putenv_garbage, name, value))
+ /* really not much we can do; just leak */
+ PyErr_Clear();
+ else
+ Py_DECREF(value);
+}
+
+
#ifdef MS_WINDOWS
- PyObject *os1, *os2;
- wchar_t *newenv;
+/*[clinic input]
+os.putenv
- if (!PyArg_ParseTuple(args,
- "UU:putenv",
- &os1, &os2))
- return NULL;
+ name: unicode
+ value: unicode
+ /
+
+Change or add an environment variable.
+[clinic start generated code]*/
+
+static PyObject *
+os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value)
+/*[clinic end generated code: output=a2438cf95e5a0c1c input=ba586581c2e6105f]*/
+{
+ wchar_t *env;
- newstr = PyUnicode_FromFormat("%U=%U", os1, os2);
- if (newstr == NULL) {
+ PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
+ if (unicode == NULL) {
PyErr_NoMemory();
- goto error;
+ return NULL;
}
- if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) {
+ if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) {
PyErr_Format(PyExc_ValueError,
"the environment variable is longer than %u characters",
_MAX_ENV);
goto error;
}
- newenv = PyUnicode_AsUnicode(newstr);
- if (newenv == NULL)
+ env = PyUnicode_AsUnicode(unicode);
+ if (env == NULL)
goto error;
- if (_wputenv(newenv)) {
+ if (_wputenv(env)) {
posix_error();
goto error;
}
-#else
- PyObject *os1, *os2;
- char *s1, *s2;
- char *newenv;
-
- if (!PyArg_ParseTuple(args,
- "O&O&:putenv",
- PyUnicode_FSConverter, &os1,
- PyUnicode_FSConverter, &os2))
- return NULL;
- s1 = PyBytes_AsString(os1);
- s2 = PyBytes_AsString(os2);
- newstr = PyBytes_FromFormat("%s=%s", s1, s2);
- if (newstr == NULL) {
- PyErr_NoMemory();
- goto error;
- }
+ posix_putenv_garbage_setitem(name, unicode);
+ Py_RETURN_NONE;
- newenv = PyBytes_AS_STRING(newstr);
- if (putenv(newenv)) {
- posix_error();
- goto error;
- }
-#endif
+error:
+ Py_DECREF(unicode);
+ return NULL;
+}
+#else /* MS_WINDOWS */
+/*[clinic input]
+os.putenv
- /* Install the first arg and newstr in posix_putenv_garbage;
- * this will cause previous value to be collected. This has to
- * happen after the real putenv() call because the old value
- * was still accessible until then. */
- if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) {
- /* really not much we can do; just leak */
- PyErr_Clear();
+ name: FSConverter
+ value: FSConverter
+ /
+
+Change or add an environment variable.
+[clinic start generated code]*/
+
+static PyObject *
+os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value)
+/*[clinic end generated code: output=a2438cf95e5a0c1c input=a97bc6152f688d31]*/
+{
+ PyObject *bytes = NULL;
+ char *env;
+ char *name_string = PyBytes_AsString(name);
+ char *value_string = PyBytes_AsString(value);
+
+ bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
+ if (bytes == NULL) {
+ PyErr_NoMemory();
+ return NULL;
}
- else {
- Py_DECREF(newstr);
+
+ env = PyBytes_AS_STRING(bytes);
+ if (putenv(env)) {
+ Py_DECREF(bytes);
+ return posix_error();
}
-#ifndef MS_WINDOWS
- Py_DECREF(os1);
- Py_DECREF(os2);
-#endif
+ posix_putenv_garbage_setitem(name, bytes);
Py_RETURN_NONE;
-
-error:
-#ifndef MS_WINDOWS
- Py_DECREF(os1);
- Py_DECREF(os2);
-#endif
- Py_XDECREF(newstr);
- return NULL;
}
-#endif /* putenv */
+#endif /* MS_WINDOWS */
+#endif /* HAVE_PUTENV */
+
#ifdef HAVE_UNSETENV
-PyDoc_STRVAR(posix_unsetenv__doc__,
-"unsetenv(key)\n\n\
-Delete an environment variable.");
+/*[clinic input]
+os.unsetenv
+ name: FSConverter
+ /
+
+Delete an environment variable.
+[clinic start generated code]*/
static PyObject *
-posix_unsetenv(PyObject *self, PyObject *args)
+os_unsetenv_impl(PyModuleDef *module, PyObject *name)
+/*[clinic end generated code: output=25994b57016a2dc9 input=2bb5288a599c7107]*/
{
- PyObject *name;
#ifndef HAVE_BROKEN_UNSETENV
int err;
#endif
- if (!PyArg_ParseTuple(args, "O&:unsetenv",
-
- PyUnicode_FSConverter, &name))
- return NULL;
-
#ifdef HAVE_BROKEN_UNSETENV
unsetenv(PyBytes_AS_STRING(name));
#else
err = unsetenv(PyBytes_AS_STRING(name));
- if (err) {
- Py_DECREF(name);
+ if (err)
return posix_error();
- }
#endif
/* Remove the key from posix_putenv_garbage;
@@ -9005,23 +9040,25 @@ posix_unsetenv(PyObject *self, PyObject *args)
/* really not much we can do; just leak */
PyErr_Clear();
}
- Py_DECREF(name);
Py_RETURN_NONE;
}
-#endif /* unsetenv */
+#endif /* HAVE_UNSETENV */
+
+
+/*[clinic input]
+os.strerror
+
+ code: int
+ /
-PyDoc_STRVAR(posix_strerror__doc__,
-"strerror(code) -> string\n\n\
-Translate an error code to a message string.");
+Translate an error code to a message string.
+[clinic start generated code]*/
static PyObject *
-posix_strerror(PyObject *self, PyObject *args)
+os_strerror_impl(PyModuleDef *module, int code)
+/*[clinic end generated code: output=0280c6af51e5c9fe input=75a8673d97915a91]*/
{
- int code;
- char *message;
- if (!PyArg_ParseTuple(args, "i:strerror", &code))
- return NULL;
- message = strerror(code);
+ char *message = strerror(code);
if (message == NULL) {
PyErr_SetString(PyExc_ValueError,
"strerror() argument out of range");
@@ -9032,155 +9069,168 @@ posix_strerror(PyObject *self, PyObject *args)
#ifdef HAVE_SYS_WAIT_H
-
#ifdef WCOREDUMP
-PyDoc_STRVAR(posix_WCOREDUMP__doc__,
-"WCOREDUMP(status) -> bool\n\n\
-Return True if the process returning 'status' was dumped to a core file.");
+/*[clinic input]
+os.WCOREDUMP -> bool
-static PyObject *
-posix_WCOREDUMP(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
+ /
- if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
- return NULL;
+Return True if the process returning status was dumped to a core file.
+[clinic start generated code]*/
- return PyBool_FromLong(WCOREDUMP(status));
+static int
+os_WCOREDUMP_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=134f70bbe63fbf41 input=8b05e7ab38528d04]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WCOREDUMP(wait_status);
}
#endif /* WCOREDUMP */
+
#ifdef WIFCONTINUED
-PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
-"WIFCONTINUED(status) -> bool\n\n\
-Return True if the process returning 'status' was continued from a\n\
-job control stop.");
+/*[clinic input]
+os.WIFCONTINUED -> bool
-static PyObject *
-posix_WIFCONTINUED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
- return NULL;
+Return True if a particular process was continued from a job control stop.
- return PyBool_FromLong(WIFCONTINUED(status));
+Return True if the process returning status was continued from a
+job control stop.
+[clinic start generated code]*/
+
+static int
+os_WIFCONTINUED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=9cdd26543ebb6dcd input=e777e7d38eb25bd9]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFCONTINUED(wait_status);
}
#endif /* WIFCONTINUED */
+
#ifdef WIFSTOPPED
-PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
-"WIFSTOPPED(status) -> bool\n\n\
-Return True if the process returning 'status' was stopped.");
+/*[clinic input]
+os.WIFSTOPPED -> bool
-static PyObject *
-posix_WIFSTOPPED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
- return NULL;
+Return True if the process returning status was stopped.
+[clinic start generated code]*/
- return PyBool_FromLong(WIFSTOPPED(status));
+static int
+os_WIFSTOPPED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=73bf35e44994a724 input=043cb7f1289ef904]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFSTOPPED(wait_status);
}
#endif /* WIFSTOPPED */
+
#ifdef WIFSIGNALED
-PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
-"WIFSIGNALED(status) -> bool\n\n\
-Return True if the process returning 'status' was terminated by a signal.");
+/*[clinic input]
+os.WIFSIGNALED -> bool
-static PyObject *
-posix_WIFSIGNALED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
- return NULL;
+Return True if the process returning status was terminated by a signal.
+[clinic start generated code]*/
- return PyBool_FromLong(WIFSIGNALED(status));
+static int
+os_WIFSIGNALED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=2697975771872420 input=d55ba7cc9ce5dc43]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFSIGNALED(wait_status);
}
#endif /* WIFSIGNALED */
+
#ifdef WIFEXITED
-PyDoc_STRVAR(posix_WIFEXITED__doc__,
-"WIFEXITED(status) -> bool\n\n\
-Return true if the process returning 'status' exited using the exit()\n\
-system call.");
+/*[clinic input]
+os.WIFEXITED -> bool
-static PyObject *
-posix_WIFEXITED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
- return NULL;
+Return True if the process returning status exited via the exit() system call.
+[clinic start generated code]*/
- return PyBool_FromLong(WIFEXITED(status));
+static int
+os_WIFEXITED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=ca8f8c61f0b8532e input=d63775a6791586c0]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFEXITED(wait_status);
}
#endif /* WIFEXITED */
+
#ifdef WEXITSTATUS
-PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
-"WEXITSTATUS(status) -> integer\n\n\
-Return the process return code from 'status'.");
+/*[clinic input]
+os.WEXITSTATUS -> int
-static PyObject *
-posix_WEXITSTATUS(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
- return NULL;
+Return the process return code from status.
+[clinic start generated code]*/
- return Py_BuildValue("i", WEXITSTATUS(status));
+static int
+os_WEXITSTATUS_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=ea54da23d9e0f6af input=e1fb4944e377585b]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WEXITSTATUS(wait_status);
}
#endif /* WEXITSTATUS */
+
#ifdef WTERMSIG
-PyDoc_STRVAR(posix_WTERMSIG__doc__,
-"WTERMSIG(status) -> integer\n\n\
-Return the signal that terminated the process that provided the 'status'\n\
-value.");
+/*[clinic input]
+os.WTERMSIG -> int
-static PyObject *
-posix_WTERMSIG(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
- return NULL;
+Return the signal that terminated the process that provided the status value.
+[clinic start generated code]*/
- return Py_BuildValue("i", WTERMSIG(status));
+static int
+os_WTERMSIG_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=4d25367026cb852c input=727fd7f84ec3f243]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WTERMSIG(wait_status);
}
#endif /* WTERMSIG */
+
#ifdef WSTOPSIG
-PyDoc_STRVAR(posix_WSTOPSIG__doc__,
-"WSTOPSIG(status) -> integer\n\n\
-Return the signal that stopped the process that provided\n\
-the 'status' value.");
+/*[clinic input]
+os.WSTOPSIG -> int
-static PyObject *
-posix_WSTOPSIG(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+ status: int
- if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
- return NULL;
+Return the signal that stopped the process that provided the status value.
+[clinic start generated code]*/
- return Py_BuildValue("i", WSTOPSIG(status));
+static int
+os_WSTOPSIG_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=54eb9c13b001adb4 input=46ebf1d1b293c5c1]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WSTOPSIG(wait_status);
}
#endif /* WSTOPSIG */
-
#endif /* HAVE_SYS_WAIT_H */
@@ -9235,104 +9285,101 @@ _pystatvfs_fromstructstatvfs(struct statvfs st) {
return v;
}
-PyDoc_STRVAR(posix_fstatvfs__doc__,
-"fstatvfs(fd) -> statvfs result\n\n\
-Perform an fstatvfs system call on the given fd.\n\
-Equivalent to statvfs(fd).");
+
+/*[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 *
-posix_fstatvfs(PyObject *self, PyObject *args)
+os_fstatvfs_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=584a94a754497ac0 input=d8122243ac50975e]*/
{
- int fd, res;
+ int result;
+ int async_err = 0;
struct statvfs st;
- if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = fstatvfs(fd, &st);
- Py_END_ALLOW_THREADS
- if (res != 0)
- return posix_error();
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = fstatvfs(fd, &st);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
return _pystatvfs_fromstructstatvfs(st);
}
-#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
+#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
-PyDoc_STRVAR(posix_statvfs__doc__,
-"statvfs(path)\n\n\
-Perform a statvfs system call on the given path.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
+ 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 *
-posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs)
+os_statvfs_impl(PyModuleDef *module, path_t *path)
+/*[clinic end generated code: output=5ced07a2cf931f41 input=3f5c35791c669bd9]*/
{
- static char *keywords[] = {"path", NULL};
- path_t path;
int result;
- PyObject *return_value = NULL;
struct statvfs st;
- memset(&path, 0, sizeof(path));
- path.function_name = "statvfs";
-#ifdef HAVE_FSTATVFS
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords,
- path_converter, &path
- ))
- return NULL;
-
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FSTATVFS
- if (path.fd != -1) {
+ if (path->fd != -1) {
#ifdef __APPLE__
/* handle weak-linking on Mac OS X 10.3 */
if (fstatvfs == NULL) {
- fd_specified("statvfs", path.fd);
- goto exit;
+ fd_specified("statvfs", path->fd);
+ return NULL;
}
#endif
- result = fstatvfs(path.fd, &st);
+ result = fstatvfs(path->fd, &st);
}
else
#endif
- result = statvfs(path.narrow, &st);
+ result = statvfs(path->narrow, &st);
Py_END_ALLOW_THREADS
if (result) {
- return_value = path_error(&path);
- goto exit;
+ return path_error(path);
}
- return_value = _pystatvfs_fromstructstatvfs(st);
-
-exit:
- path_cleanup(&path);
- return return_value;
+ return _pystatvfs_fromstructstatvfs(st);
}
-#endif /* HAVE_STATVFS */
+#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
+
#ifdef MS_WINDOWS
-PyDoc_STRVAR(win32__getdiskusage__doc__,
-"_getdiskusage(path) -> (total, free)\n\n\
-Return disk usage statistics about the given path as (total, free) tuple.");
+/*[clinic input]
+os._getdiskusage
+
+ path: Py_UNICODE
+
+Return disk usage statistics about the given path as a (total, free) tuple.
+[clinic start generated code]*/
static PyObject *
-win32__getdiskusage(PyObject *self, PyObject *args)
+os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path)
+/*[clinic end generated code: output=60a9cf33449db1dd input=6458133aed893c78]*/
{
BOOL retval;
ULARGE_INTEGER _, total, free;
- const wchar_t *path;
-
- if (! PyArg_ParseTuple(args, "u", &path))
- return NULL;
Py_BEGIN_ALLOW_THREADS
retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
@@ -9342,7 +9389,7 @@ win32__getdiskusage(PyObject *self, PyObject *args)
return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
}
-#endif
+#endif /* MS_WINDOWS */
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
@@ -9499,81 +9546,73 @@ conv_path_confname(PyObject *arg, int *valuep)
}
#endif
+
#ifdef HAVE_FPATHCONF
-PyDoc_STRVAR(posix_fpathconf__doc__,
-"fpathconf(fd, name) -> integer\n\n\
-Return the configuration limit name for the file descriptor fd.\n\
-If there is no limit, return -1.");
+/*[clinic input]
+os.fpathconf -> long
-static PyObject *
-posix_fpathconf(PyObject *self, PyObject *args)
+ fd: int
+ name: path_confname
+ /
+
+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(PyModuleDef *module, int fd, int name)
+/*[clinic end generated code: output=082b2922d4441de7 input=5942a024d3777810]*/
{
- PyObject *result = NULL;
- int name, fd;
+ long limit;
- if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
- conv_path_confname, &name)) {
- long limit;
+ errno = 0;
+ limit = fpathconf(fd, name);
+ if (limit == -1 && errno != 0)
+ posix_error();
- errno = 0;
- limit = fpathconf(fd, name);
- if (limit == -1 && errno != 0)
- posix_error();
- else
- result = PyLong_FromLong(limit);
- }
- return result;
+ return limit;
}
-#endif
+#endif /* HAVE_FPATHCONF */
#ifdef HAVE_PATHCONF
-PyDoc_STRVAR(posix_pathconf__doc__,
-"pathconf(path, name) -> integer\n\n\
-Return the configuration limit name for the file or directory path.\n\
-If there is no limit, return -1.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
+/*[clinic input]
+os.pathconf -> long
+ path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
+ name: path_confname
-static PyObject *
-posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- PyObject *result = NULL;
- int name;
- static char *keywords[] = {"path", "name", NULL};
+Return the configuration limit name for the file or directory path.
- memset(&path, 0, sizeof(path));
- path.function_name = "pathconf";
-#ifdef HAVE_FPATHCONF
- path.allow_fd = 1;
-#endif
- if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords,
- path_converter, &path,
- conv_path_confname, &name)) {
+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(PyModuleDef *module, path_t *path, int name)
+/*[clinic end generated code: output=3713029e9501f5ab input=bc3e2a985af27e5e]*/
+{
long limit;
errno = 0;
#ifdef HAVE_FPATHCONF
- if (path.fd != -1)
- limit = fpathconf(path.fd, name);
+ if (path->fd != -1)
+ limit = fpathconf(path->fd, name);
else
#endif
- limit = pathconf(path.narrow, name);
+ limit = pathconf(path->narrow, name);
if (limit == -1 && errno != 0) {
if (errno == EINVAL)
/* could be a path or name problem */
posix_error();
else
- result = path_error(&path);
- }
- else
- result = PyLong_FromLong(limit);
+ path_error(path);
}
- path_cleanup(&path);
- return result;
+
+ return limit;
}
-#endif
+#endif /* HAVE_PATHCONF */
#ifdef HAVE_CONFSTR
static struct constdef posix_constants_confstr[] = {
@@ -9737,21 +9776,24 @@ conv_confstr_confname(PyObject *arg, int *valuep)
/ sizeof(struct constdef));
}
-PyDoc_STRVAR(posix_confstr__doc__,
-"confstr(name) -> string\n\n\
-Return a string-valued system configuration variable.");
+
+/*[clinic input]
+os.confstr
+
+ name: confstr_confname
+ /
+
+Return a string-valued system configuration variable.
+[clinic start generated code]*/
static PyObject *
-posix_confstr(PyObject *self, PyObject *args)
+os_confstr_impl(PyModuleDef *module, int name)
+/*[clinic end generated code: output=6ff79c9eed8c2daf input=18fb4d0567242e65]*/
{
PyObject *result = NULL;
- int name;
char buffer[255];
size_t len;
- if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
- return NULL;
-
errno = 0;
len = confstr(name, buffer, sizeof(buffer));
if (len == 0) {
@@ -9765,10 +9807,12 @@ posix_confstr(PyObject *self, PyObject *args)
}
if (len >= sizeof(buffer)) {
+ size_t len2;
char *buf = PyMem_Malloc(len);
if (buf == NULL)
return PyErr_NoMemory();
- confstr(name, buf, len);
+ len2 = confstr(name, buf, len);
+ assert(len == len2);
result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
PyMem_Free(buf);
}
@@ -9776,7 +9820,7 @@ posix_confstr(PyObject *self, PyObject *args)
result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
return result;
}
-#endif
+#endif /* HAVE_CONFSTR */
#ifdef HAVE_SYSCONF
@@ -10283,29 +10327,28 @@ conv_sysconf_confname(PyObject *arg, int *valuep)
/ sizeof(struct constdef));
}
-PyDoc_STRVAR(posix_sysconf__doc__,
-"sysconf(name) -> integer\n\n\
-Return an integer-valued system configuration variable.");
-static PyObject *
-posix_sysconf(PyObject *self, PyObject *args)
-{
- PyObject *result = NULL;
- int name;
+/*[clinic input]
+os.sysconf -> long
+ name: sysconf_confname
+ /
+
+Return an integer-valued system configuration variable.
+[clinic start generated code]*/
- if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
- long value;
+static long
+os_sysconf_impl(PyModuleDef *module, int name)
+/*[clinic end generated code: output=ed567306f58d69c4 input=279e3430a33f29e4]*/
+{
+ long value;
- errno = 0;
- value = sysconf(name);
- if (value == -1 && errno != 0)
- posix_error();
- else
- result = PyLong_FromLong(value);
- }
- return result;
+ errno = 0;
+ value = sysconf(name);
+ if (value == -1 && errno != 0)
+ posix_error();
+ return value;
}
-#endif
+#endif /* HAVE_SYSCONF */
/* This code is used to ensure that the tables of configuration value names
@@ -10382,13 +10425,18 @@ setup_confname_tables(PyObject *module)
}
-PyDoc_STRVAR(posix_abort__doc__,
-"abort() -> does not return!\n\n\
-Abort the interpreter immediately. This 'dumps core' or otherwise fails\n\
-in the hardest way possible on the hosting operating system.");
+/*[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 *
-posix_abort(PyObject *self, PyObject *noargs)
+os_abort_impl(PyModuleDef *module)
+/*[clinic end generated code: output=486bb96647c299b3 input=cf2c7d98bc504047]*/
{
abort();
/*NOTREACHED*/
@@ -10397,9 +10445,11 @@ posix_abort(PyObject *self, PyObject *noargs)
}
#ifdef MS_WINDOWS
+/* AC 3.5: change to path_t? but that might change exceptions */
PyDoc_STRVAR(win32_startfile__doc__,
-"startfile(filepath [, operation]) - Start a file with its associated\n\
-application.\n\
+"startfile(filepath [, operation])\n\
+\n\
+Start a file with its associated application.\n\
\n\
When \"operation\" is not specified or \"open\", this acts like\n\
double-clicking the file in Explorer, or giving the file name as an\n\
@@ -10416,6 +10466,37 @@ The filepath is relative to the current directory. If you want to use\n\
an absolute path, make sure the first character is not a slash (\"/\");\n\
the underlying Win32 ShellExecute function doesn't work if it is.");
+/* Grab ShellExecute dynamically from shell32 */
+static int has_ShellExecute = -1;
+static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR,
+ LPCSTR, INT);
+static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
+ LPCWSTR, INT);
+static int
+check_ShellExecute()
+{
+ HINSTANCE hShell32;
+
+ /* only recheck */
+ if (-1 == has_ShellExecute) {
+ Py_BEGIN_ALLOW_THREADS
+ hShell32 = LoadLibraryW(L"SHELL32");
+ Py_END_ALLOW_THREADS
+ if (hShell32) {
+ *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32,
+ "ShellExecuteA");
+ *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
+ "ShellExecuteW");
+ has_ShellExecute = Py_ShellExecuteA &&
+ Py_ShellExecuteW;
+ } else {
+ has_ShellExecute = 0;
+ }
+ }
+ return has_ShellExecute;
+}
+
+
static PyObject *
win32_startfile(PyObject *self, PyObject *args)
{
@@ -10426,6 +10507,14 @@ win32_startfile(PyObject *self, PyObject *args)
HINSTANCE rc;
PyObject *unipath, *uoperation = NULL;
+
+ 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 (!PyArg_ParseTuple(args, "U|s:startfile",
&unipath, &operation)) {
PyErr_Clear();
@@ -10454,8 +10543,8 @@ win32_startfile(PyObject *self, PyObject *args)
woperation = NULL;
Py_BEGIN_ALLOW_THREADS
- rc = ShellExecuteW((HWND)0, woperation, wpath,
- NULL, NULL, SW_SHOWNORMAL);
+ rc = Py_ShellExecuteW((HWND)0, woperation, wpath,
+ NULL, NULL, SW_SHOWNORMAL);
Py_END_ALLOW_THREADS
Py_XDECREF(uoperation);
@@ -10477,8 +10566,8 @@ normal:
}
filepath = PyBytes_AsString(ofilepath);
Py_BEGIN_ALLOW_THREADS
- rc = ShellExecute((HWND)0, operation, filepath,
- NULL, NULL, SW_SHOWNORMAL);
+ rc = Py_ShellExecuteA((HWND)0, operation, filepath,
+ NULL, NULL, SW_SHOWNORMAL);
Py_END_ALLOW_THREADS
if (rc <= (HINSTANCE)32) {
PyObject *errval = win32_error("startfile", filepath);
@@ -10489,17 +10578,23 @@ normal:
Py_INCREF(Py_None);
return Py_None;
}
-#endif
+#endif /* MS_WINDOWS */
+
#ifdef HAVE_GETLOADAVG
-PyDoc_STRVAR(posix_getloadavg__doc__,
-"getloadavg() -> (float, float, float)\n\n\
-Return the number of processes in the system run queue averaged over\n\
-the last 1, 5, and 15 minutes or raises OSError if the load average\n\
-was unobtainable");
+/*[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 *
-posix_getloadavg(PyObject *self, PyObject *noargs)
+os_getloadavg_impl(PyModuleDef *module)
+/*[clinic end generated code: output=2b64c5b675d74c14 input=3d6d826b76d8a34e]*/
{
double loadavg[3];
if (getloadavg(loadavg, 3)!=3) {
@@ -10508,72 +10603,83 @@ posix_getloadavg(PyObject *self, PyObject *noargs)
} else
return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
}
-#endif
+#endif /* HAVE_GETLOADAVG */
-PyDoc_STRVAR(device_encoding__doc__,
-"device_encoding(fd) -> str\n\n\
-Return a string describing the encoding of the device\n\
-if the output is a terminal; else return None.");
-static PyObject *
-device_encoding(PyObject *self, PyObject *args)
-{
- int fd;
+/*[clinic input]
+os.device_encoding
+ fd: int
- if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
- return NULL;
+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(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=34f14e33468419c1 input=9e1d4a42b66df312]*/
+{
return _Py_device_encoding(fd);
}
+
#ifdef HAVE_SETRESUID
-PyDoc_STRVAR(posix_setresuid__doc__,
-"setresuid(ruid, euid, suid)\n\n\
-Set the current process's real, effective, and saved user ids.");
+/*[clinic input]
+os.setresuid
-static PyObject*
-posix_setresuid (PyObject *self, PyObject *args)
+ 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(PyModuleDef *module, uid_t ruid, uid_t euid, uid_t suid)
+/*[clinic end generated code: output=92cc330812c6ed0f input=9e33cb79a82792f3]*/
{
- /* We assume uid_t is no larger than a long. */
- uid_t ruid, euid, suid;
- if (!PyArg_ParseTuple(args, "O&O&O&:setresuid",
- _Py_Uid_Converter, &ruid,
- _Py_Uid_Converter, &euid,
- _Py_Uid_Converter, &suid))
- return NULL;
if (setresuid(ruid, euid, suid) < 0)
return posix_error();
Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_SETRESUID */
+
#ifdef HAVE_SETRESGID
-PyDoc_STRVAR(posix_setresgid__doc__,
-"setresgid(rgid, egid, sgid)\n\n\
-Set the current process's real, effective, and saved group ids.");
+/*[clinic input]
+os.setresgid
-static PyObject*
-posix_setresgid (PyObject *self, PyObject *args)
+ 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(PyModuleDef *module, gid_t rgid, gid_t egid, gid_t sgid)
+/*[clinic end generated code: output=e91dc4842a604429 input=33e9e0785ef426b1]*/
{
- gid_t rgid, egid, sgid;
- if (!PyArg_ParseTuple(args, "O&O&O&:setresgid",
- _Py_Gid_Converter, &rgid,
- _Py_Gid_Converter, &egid,
- _Py_Gid_Converter, &sgid))
- return NULL;
if (setresgid(rgid, egid, sgid) < 0)
return posix_error();
Py_RETURN_NONE;
}
-#endif
+#endif /* HAVE_SETRESGID */
+
#ifdef HAVE_GETRESUID
-PyDoc_STRVAR(posix_getresuid__doc__,
-"getresuid() -> (ruid, euid, suid)\n\n\
-Get tuple of the current process's real, effective, and saved user ids.");
+/*[clinic input]
+os.getresuid
-static PyObject*
-posix_getresuid (PyObject *self, PyObject *noargs)
+Return a tuple of the current process's real, effective, and saved user ids.
+[clinic start generated code]*/
+
+static PyObject *
+os_getresuid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=9ddef62faae8e477 input=41ccfa8e1f6517ad]*/
{
uid_t ruid, euid, suid;
if (getresuid(&ruid, &euid, &suid) < 0)
@@ -10582,90 +10688,87 @@ posix_getresuid (PyObject *self, PyObject *noargs)
_PyLong_FromUid(euid),
_PyLong_FromUid(suid));
}
-#endif
+#endif /* HAVE_GETRESUID */
+
#ifdef HAVE_GETRESGID
-PyDoc_STRVAR(posix_getresgid__doc__,
-"getresgid() -> (rgid, egid, sgid)\n\n\
-Get tuple of the current process's real, effective, and saved group ids.");
+/*[clinic input]
+os.getresgid
-static PyObject*
-posix_getresgid (PyObject *self, PyObject *noargs)
+Return a tuple of the current process's real, effective, and saved group ids.
+[clinic start generated code]*/
+
+static PyObject *
+os_getresgid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=e1a553cbcf16234c input=517e68db9ca32df6]*/
{
- uid_t rgid, egid, sgid;
+ gid_t rgid, egid, sgid;
if (getresgid(&rgid, &egid, &sgid) < 0)
return posix_error();
return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
_PyLong_FromGid(egid),
_PyLong_FromGid(sgid));
}
-#endif
+#endif /* HAVE_GETRESGID */
+
#ifdef USE_XATTRS
+/*[clinic input]
+os.getxattr
-PyDoc_STRVAR(posix_getxattr__doc__,
-"getxattr(path, attribute, *, follow_symlinks=True) -> value\n\n\
-Return the value of extended attribute attribute on path.\n\
-\n\
-path may be either a string or an open file descriptor.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, getxattr will examine the symbolic link itself instead of the file\n\
- the link points to.");
+ 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 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 *
-posix_getxattr(PyObject *self, PyObject *args, PyObject *kwargs)
+os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks)
+/*[clinic end generated code: output=d90086b314859f8b input=8c8ea3bab78d89c2]*/
{
- path_t path;
- path_t attribute;
- int follow_symlinks = 1;
+ Py_ssize_t i;
PyObject *buffer = NULL;
- int i;
- static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL};
- memset(&path, 0, sizeof(path));
- memset(&attribute, 0, sizeof(attribute));
- path.function_name = "getxattr";
- attribute.function_name = "getxattr";
- path.allow_fd = 1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:getxattr", keywords,
- path_converter, &path,
- path_converter, &attribute,
- &follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
return NULL;
- if (fd_and_follow_symlinks_invalid("getxattr", path.fd, follow_symlinks))
- goto exit;
-
for (i = 0; ; i++) {
void *ptr;
ssize_t result;
static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
Py_ssize_t buffer_size = buffer_sizes[i];
if (!buffer_size) {
- path_error(&path);
- goto exit;
+ path_error(path);
+ return NULL;
}
buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
if (!buffer)
- goto exit;
+ return NULL;
ptr = PyBytes_AS_STRING(buffer);
Py_BEGIN_ALLOW_THREADS;
- if (path.fd >= 0)
- result = fgetxattr(path.fd, attribute.narrow, ptr, buffer_size);
+ if (path->fd >= 0)
+ result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
else if (follow_symlinks)
- result = getxattr(path.narrow, attribute.narrow, ptr, buffer_size);
+ result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
else
- result = lgetxattr(path.narrow, attribute.narrow, ptr, buffer_size);
+ result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
Py_END_ALLOW_THREADS;
if (result < 0) {
Py_DECREF(buffer);
- buffer = NULL;
if (errno == ERANGE)
continue;
- path_error(&path);
- goto exit;
+ path_error(path);
+ return NULL;
}
if (result != buffer_size) {
@@ -10675,168 +10778,132 @@ posix_getxattr(PyObject *self, PyObject *args, PyObject *kwargs)
break;
}
-exit:
- path_cleanup(&path);
- path_cleanup(&attribute);
return buffer;
}
-PyDoc_STRVAR(posix_setxattr__doc__,
-"setxattr(path, attribute, value, flags=0, *, follow_symlinks=True)\n\n\
-Set extended attribute attribute on path to value.\n\
-path may be either a string or an open file descriptor.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, setxattr will modify the symbolic link itself instead of the file\n\
- the link points to.");
+
+/*[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 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 *
-posix_setxattr(PyObject *self, PyObject *args, PyObject *kwargs)
+os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks)
+/*[clinic end generated code: output=e3defa5c4b1ad0ae input=f0d26833992015c2]*/
{
- path_t path;
- path_t attribute;
- Py_buffer value;
- int flags = 0;
- int follow_symlinks = 1;
- int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "attribute", "value",
- "flags", "follow_symlinks", NULL};
+ ssize_t result;
- memset(&path, 0, sizeof(path));
- path.function_name = "setxattr";
- path.allow_fd = 1;
- memset(&attribute, 0, sizeof(attribute));
- memset(&value, 0, sizeof(value));
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&y*|i$p:setxattr",
- keywords,
- path_converter, &path,
- path_converter, &attribute,
- &value, &flags,
- &follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
return NULL;
- if (fd_and_follow_symlinks_invalid("setxattr", path.fd, follow_symlinks))
- goto exit;
-
Py_BEGIN_ALLOW_THREADS;
- if (path.fd > -1)
- result = fsetxattr(path.fd, attribute.narrow,
- value.buf, value.len, flags);
+ if (path->fd > -1)
+ result = fsetxattr(path->fd, attribute->narrow,
+ value->buf, value->len, flags);
else if (follow_symlinks)
- result = setxattr(path.narrow, attribute.narrow,
- value.buf, value.len, flags);
+ result = setxattr(path->narrow, attribute->narrow,
+ value->buf, value->len, flags);
else
- result = lsetxattr(path.narrow, attribute.narrow,
- value.buf, value.len, flags);
+ result = lsetxattr(path->narrow, attribute->narrow,
+ value->buf, value->len, flags);
Py_END_ALLOW_THREADS;
if (result) {
- return_value = path_error(&path);
- goto exit;
+ path_error(path);
+ return NULL;
}
- return_value = Py_None;
- Py_INCREF(return_value);
+ Py_RETURN_NONE;
+}
-exit:
- path_cleanup(&path);
- path_cleanup(&attribute);
- PyBuffer_Release(&value);
- return return_value;
-}
+/*[clinic input]
+os.removexattr
-PyDoc_STRVAR(posix_removexattr__doc__,
-"removexattr(path, attribute, *, follow_symlinks=True)\n\n\
-Remove extended attribute attribute on path.\n\
-path may be either a string or an open file descriptor.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, removexattr will modify the symbolic link itself instead of the file\n\
- the link points to.");
+ 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 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 *
-posix_removexattr(PyObject *self, PyObject *args, PyObject *kwargs)
+os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks)
+/*[clinic end generated code: output=4870ec90249af875 input=cdb54834161e3329]*/
{
- path_t path;
- path_t attribute;
- int follow_symlinks = 1;
- int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL};
+ ssize_t result;
- memset(&path, 0, sizeof(path));
- path.function_name = "removexattr";
- memset(&attribute, 0, sizeof(attribute));
- attribute.function_name = "removexattr";
- path.allow_fd = 1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:removexattr",
- keywords,
- path_converter, &path,
- path_converter, &attribute,
- &follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
return NULL;
- if (fd_and_follow_symlinks_invalid("removexattr", path.fd, follow_symlinks))
- goto exit;
-
Py_BEGIN_ALLOW_THREADS;
- if (path.fd > -1)
- result = fremovexattr(path.fd, attribute.narrow);
+ if (path->fd > -1)
+ result = fremovexattr(path->fd, attribute->narrow);
else if (follow_symlinks)
- result = removexattr(path.narrow, attribute.narrow);
+ result = removexattr(path->narrow, attribute->narrow);
else
- result = lremovexattr(path.narrow, attribute.narrow);
+ result = lremovexattr(path->narrow, attribute->narrow);
Py_END_ALLOW_THREADS;
if (result) {
- return_value = path_error(&path);
- goto exit;
+ return path_error(path);
}
- return_value = Py_None;
- Py_INCREF(return_value);
+ Py_RETURN_NONE;
+}
-exit:
- path_cleanup(&path);
- path_cleanup(&attribute);
- return return_value;
-}
+/*[clinic input]
+os.listxattr
-PyDoc_STRVAR(posix_listxattr__doc__,
-"listxattr(path='.', *, follow_symlinks=True)\n\n\
-Return a list of extended attributes on path.\n\
-\n\
-path may be either None, a string, or an open file descriptor.\n\
-if path is None, listxattr will examine the current directory.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, listxattr will examine the symbolic link itself instead of the file\n\
- the link points to.");
+ 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, 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 *
-posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
+os_listxattr_impl(PyModuleDef *module, path_t *path, int follow_symlinks)
+/*[clinic end generated code: output=a87ad6ce56e42a4f input=08cca53ac0b07c13]*/
{
- path_t path;
- int follow_symlinks = 1;
Py_ssize_t i;
PyObject *result = NULL;
+ const char *name;
char *buffer = NULL;
- char *name;
- static char *keywords[] = {"path", "follow_symlinks", NULL};
-
- memset(&path, 0, sizeof(path));
- path.function_name = "listxattr";
- path.allow_fd = 1;
- path.fd = -1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&$p:listxattr", keywords,
- path_converter, &path,
- &follow_symlinks))
- return NULL;
- if (fd_and_follow_symlinks_invalid("listxattr", path.fd, follow_symlinks))
+ if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
goto exit;
- name = path.narrow ? path.narrow : ".";
+ name = path->narrow ? path->narrow : ".";
+
for (i = 0; ; i++) {
char *start, *trace, *end;
ssize_t length;
@@ -10844,7 +10911,7 @@ posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
Py_ssize_t buffer_size = buffer_sizes[i];
if (!buffer_size) {
/* ERANGE */
- path_error(&path);
+ path_error(path);
break;
}
buffer = PyMem_MALLOC(buffer_size);
@@ -10854,8 +10921,8 @@ posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
}
Py_BEGIN_ALLOW_THREADS;
- if (path.fd > -1)
- length = flistxattr(path.fd, buffer, buffer_size);
+ if (path->fd > -1)
+ length = flistxattr(path->fd, buffer, buffer_size);
else if (follow_symlinks)
length = listxattr(name, buffer, buffer_size);
else
@@ -10868,7 +10935,7 @@ posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
buffer = NULL;
continue;
}
- path_error(&path);
+ path_error(path);
break;
}
@@ -10901,43 +10968,43 @@ posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
break;
}
exit:
- path_cleanup(&path);
if (buffer)
PyMem_FREE(buffer);
return result;
}
-
#endif /* USE_XATTRS */
-PyDoc_STRVAR(posix_urandom__doc__,
-"urandom(n) -> str\n\n\
-Return n random bytes suitable for cryptographic use.");
+/*[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 *
-posix_urandom(PyObject *self, PyObject *args)
+os_urandom_impl(PyModuleDef *module, Py_ssize_t size)
+/*[clinic end generated code: output=e0011f021501f03b input=4067cdb1b6776c29]*/
{
- Py_ssize_t size;
- PyObject *result;
- int ret;
+ PyObject *bytes;
+ int result;
- /* Read arguments */
- if (!PyArg_ParseTuple(args, "n:urandom", &size))
- return NULL;
if (size < 0)
return PyErr_Format(PyExc_ValueError,
"negative argument not allowed");
- result = PyBytes_FromStringAndSize(NULL, size);
- if (result == NULL)
+ bytes = PyBytes_FromStringAndSize(NULL, size);
+ if (bytes == NULL)
return NULL;
- ret = _PyOS_URandom(PyBytes_AS_STRING(result),
- PyBytes_GET_SIZE(result));
- if (ret == -1) {
- Py_DECREF(result);
+ result = _PyOS_URandom(PyBytes_AS_STRING(bytes),
+ PyBytes_GET_SIZE(bytes));
+ if (result == -1) {
+ Py_DECREF(bytes);
return NULL;
}
- return result;
+ return bytes;
}
/* Terminal size querying */
@@ -10961,6 +11028,7 @@ static PyStructSequence_Desc TerminalSize_desc = {
};
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
+/* AC 3.5: fd should accept None */
PyDoc_STRVAR(termsize__doc__,
"Return the size of the terminal window as (columns, lines).\n" \
"\n" \
@@ -11046,13 +11114,16 @@ get_terminal_size(PyObject *self, PyObject *args)
}
#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
-PyDoc_STRVAR(posix_cpu_count__doc__,
-"cpu_count() -> integer\n\n\
-Return the number of CPUs in the system, or None if this value cannot be\n\
-established.");
+
+/*[clinic input]
+os.cpu_count
+
+Return the number of CPUs in the system; return None if indeterminable.
+[clinic start generated code]*/
static PyObject *
-posix_cpu_count(PyObject *self)
+os_cpu_count_impl(PyModuleDef *module)
+/*[clinic end generated code: output=c59ee7f6bce832b8 input=d55e2f8f3823a628]*/
{
int ncpu = 0;
#ifdef MS_WINDOWS
@@ -11081,111 +11152,929 @@ posix_cpu_count(PyObject *self)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(get_inheritable__doc__,
- "get_inheritable(fd) -> bool\n" \
+
+/*[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(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=36110bb36efaa21e input=89ac008dc9ab6b95]*/
+{
+ if (!_PyVerify_fd(fd)){
+ posix_error();
+ return -1;
+ }
+
+ return _Py_get_inheritable(fd);
+}
+
+
+/*[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(PyModuleDef *module, int fd, int inheritable)
+/*[clinic end generated code: output=2ac5c6ce8623f045 input=9ceaead87a1e2402]*/
+{
+ if (!_PyVerify_fd(fd))
+ return posix_error();
+
+ if (_Py_set_inheritable(fd, inheritable, NULL) < 0)
+ return NULL;
+ Py_RETURN_NONE;
+}
+
+
+#ifdef MS_WINDOWS
+/*[clinic input]
+os.get_handle_inheritable -> bool
+ handle: Py_intptr_t
+ /
+
+Get the close-on-exe flag of the specified file descriptor.
+[clinic start generated code]*/
+
+static int
+os_get_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle)
+/*[clinic end generated code: output=3b7b3e1b43f312b6 input=5f7759443aae3dc5]*/
+{
+ DWORD flags;
+
+ if (!GetHandleInformation((HANDLE)handle, &flags)) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+
+ return flags & HANDLE_FLAG_INHERIT;
+}
+
+
+/*[clinic input]
+os.set_handle_inheritable
+ handle: Py_intptr_t
+ inheritable: bool
+ /
+
+Set the inheritable flag of the specified handle.
+[clinic start generated code]*/
+
+static PyObject *
+os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, int inheritable)
+/*[clinic end generated code: output=627aa5b158b69338 input=e64b2b2730469def]*/
+{
+ 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 */
+
+#ifndef MS_WINDOWS
+PyDoc_STRVAR(get_blocking__doc__,
+ "get_blocking(fd) -> bool\n" \
"\n" \
- "Get the close-on-exe flag of the specified file descriptor.");
+ "Get the blocking mode of the file descriptor:\n" \
+ "False if the O_NONBLOCK flag is set, True if the flag is cleared.");
static PyObject*
-posix_get_inheritable(PyObject *self, PyObject *args)
+posix_get_blocking(PyObject *self, PyObject *args)
{
int fd;
- int inheritable;
+ int blocking;
- if (!PyArg_ParseTuple(args, "i:get_inheritable", &fd))
+ if (!PyArg_ParseTuple(args, "i:get_blocking", &fd))
return NULL;
if (!_PyVerify_fd(fd))
return posix_error();
- inheritable = _Py_get_inheritable(fd);
- if (inheritable < 0)
+ blocking = _Py_get_blocking(fd);
+ if (blocking < 0)
return NULL;
- return PyBool_FromLong(inheritable);
+ return PyBool_FromLong(blocking);
}
-PyDoc_STRVAR(set_inheritable__doc__,
- "set_inheritable(fd, inheritable)\n" \
+PyDoc_STRVAR(set_blocking__doc__,
+ "set_blocking(fd, blocking)\n" \
"\n" \
- "Set the inheritable flag of the specified file descriptor.");
+ "Set the blocking mode of the specified file descriptor.\n" \
+ "Set the O_NONBLOCK flag if blocking is False,\n" \
+ "clear the O_NONBLOCK flag otherwise.");
static PyObject*
-posix_set_inheritable(PyObject *self, PyObject *args)
+posix_set_blocking(PyObject *self, PyObject *args)
{
- int fd, inheritable;
+ int fd, blocking;
- if (!PyArg_ParseTuple(args, "ii:set_inheritable", &fd, &inheritable))
+ if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking))
return NULL;
if (!_PyVerify_fd(fd))
return posix_error();
- if (_Py_set_inheritable(fd, inheritable, NULL) < 0)
+ if (_Py_set_blocking(fd, blocking) < 0)
return NULL;
Py_RETURN_NONE;
}
+#endif /* !MS_WINDOWS */
+
+
+PyDoc_STRVAR(posix_scandir__doc__,
+"scandir(path='.') -> iterator of DirEntry objects for given path");
+static char *follow_symlinks_keywords[] = {"follow_symlinks", NULL};
+typedef struct {
+ PyObject_HEAD
+ PyObject *name;
+ PyObject *path;
+ PyObject *stat;
+ PyObject *lstat;
#ifdef MS_WINDOWS
-PyDoc_STRVAR(get_handle_inheritable__doc__,
- "get_handle_inheritable(fd) -> bool\n" \
- "\n" \
- "Get the close-on-exe flag of the specified file descriptor.");
+ struct _Py_stat_struct win32_lstat;
+ __int64 win32_file_index;
+ int got_file_index;
+#else /* POSIX */
+#ifdef HAVE_DIRENT_D_TYPE
+ unsigned char d_type;
+#endif
+ ino_t d_ino;
+#endif
+} DirEntry;
-static PyObject*
-posix_get_handle_inheritable(PyObject *self, PyObject *args)
+static void
+DirEntry_dealloc(DirEntry *entry)
{
- Py_intptr_t handle;
- DWORD flags;
+ Py_XDECREF(entry->name);
+ Py_XDECREF(entry->path);
+ Py_XDECREF(entry->stat);
+ Py_XDECREF(entry->lstat);
+ Py_TYPE(entry)->tp_free((PyObject *)entry);
+}
+
+/* Forward reference */
+static int
+DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
+
+/* Set exception and return -1 on error, 0 for False, 1 for True */
+static int
+DirEntry_is_symlink(DirEntry *self)
+{
+#ifdef MS_WINDOWS
+ return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
+#elif defined(HAVE_DIRENT_D_TYPE)
+ /* POSIX */
+ if (self->d_type != DT_UNKNOWN)
+ return self->d_type == DT_LNK;
+ else
+ return DirEntry_test_mode(self, 0, S_IFLNK);
+#else
+ /* POSIX without d_type */
+ return DirEntry_test_mode(self, 0, S_IFLNK);
+#endif
+}
- if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR ":get_handle_inheritable", &handle))
+static PyObject *
+DirEntry_py_is_symlink(DirEntry *self)
+{
+ int result;
+
+ result = DirEntry_is_symlink(self);
+ if (result == -1)
return NULL;
+ return PyBool_FromLong(result);
+}
- if (!GetHandleInformation((HANDLE)handle, &flags)) {
- PyErr_SetFromWindowsErr(0);
+static PyObject *
+DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
+{
+ int result;
+ struct _Py_stat_struct st;
+
+#ifdef MS_WINDOWS
+ wchar_t *path;
+
+ path = PyUnicode_AsUnicode(self->path);
+ if (!path)
return NULL;
+
+ if (follow_symlinks)
+ result = win32_stat_w(path, &st);
+ else
+ result = win32_lstat_w(path, &st);
+
+ if (result != 0) {
+ return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError,
+ 0, self->path);
}
+#else /* POSIX */
+ PyObject *bytes;
+ char *path;
+
+ if (!PyUnicode_FSConverter(self->path, &bytes))
+ return NULL;
+ path = PyBytes_AS_STRING(bytes);
+
+ if (follow_symlinks)
+ result = STAT(path, &st);
+ else
+ result = LSTAT(path, &st);
+ Py_DECREF(bytes);
- return PyBool_FromLong(flags & HANDLE_FLAG_INHERIT);
+ if (result != 0)
+ return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, self->path);
+#endif
+
+ return _pystat_fromstructstat(&st);
}
-PyDoc_STRVAR(set_handle_inheritable__doc__,
- "set_handle_inheritable(fd, inheritable)\n" \
- "\n" \
- "Set the inheritable flag of the specified handle.");
+static PyObject *
+DirEntry_get_lstat(DirEntry *self)
+{
+ if (!self->lstat) {
+#ifdef MS_WINDOWS
+ self->lstat = _pystat_fromstructstat(&self->win32_lstat);
+#else /* POSIX */
+ self->lstat = DirEntry_fetch_stat(self, 0);
+#endif
+ }
+ Py_XINCREF(self->lstat);
+ return self->lstat;
+}
-static PyObject*
-posix_set_handle_inheritable(PyObject *self, PyObject *args)
+static PyObject *
+DirEntry_get_stat(DirEntry *self, int follow_symlinks)
{
- int inheritable = 1;
- Py_intptr_t handle;
- DWORD flags;
+ if (!follow_symlinks)
+ return DirEntry_get_lstat(self);
+
+ if (!self->stat) {
+ int result = DirEntry_is_symlink(self);
+ if (result == -1)
+ return NULL;
+ else if (result)
+ self->stat = DirEntry_fetch_stat(self, 1);
+ else
+ self->stat = DirEntry_get_lstat(self);
+ }
+
+ Py_XINCREF(self->stat);
+ return self->stat;
+}
- if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR "i:set_handle_inheritable",
- &handle, &inheritable))
+static PyObject *
+DirEntry_stat(DirEntry *self, PyObject *args, PyObject *kwargs)
+{
+ int follow_symlinks = 1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.stat",
+ follow_symlinks_keywords, &follow_symlinks))
return NULL;
- if (inheritable)
- flags = HANDLE_FLAG_INHERIT;
- else
- flags = 0;
- if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
- PyErr_SetFromWindowsErr(0);
+ return DirEntry_get_stat(self, follow_symlinks);
+}
+
+/* Set exception and return -1 on error, 0 for False, 1 for True */
+static int
+DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
+{
+ PyObject *stat = NULL;
+ PyObject *st_mode = NULL;
+ long mode;
+ int result;
+#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
+ int is_symlink;
+ int need_stat;
+#endif
+#ifdef MS_WINDOWS
+ unsigned long dir_bits;
+#endif
+ _Py_IDENTIFIER(st_mode);
+
+#ifdef MS_WINDOWS
+ is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
+ need_stat = follow_symlinks && is_symlink;
+#elif defined(HAVE_DIRENT_D_TYPE)
+ is_symlink = self->d_type == DT_LNK;
+ need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
+#endif
+
+#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
+ if (need_stat) {
+#endif
+ stat = DirEntry_get_stat(self, follow_symlinks);
+ if (!stat) {
+ if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
+ /* If file doesn't exist (anymore), then return False
+ (i.e., say it's not a file/directory) */
+ PyErr_Clear();
+ return 0;
+ }
+ goto error;
+ }
+ st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
+ if (!st_mode)
+ goto error;
+
+ mode = PyLong_AsLong(st_mode);
+ if (mode == -1 && PyErr_Occurred())
+ goto error;
+ Py_CLEAR(st_mode);
+ Py_CLEAR(stat);
+ result = (mode & S_IFMT) == mode_bits;
+#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
+ }
+ else if (is_symlink) {
+ assert(mode_bits != S_IFLNK);
+ result = 0;
+ }
+ else {
+ assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
+#ifdef MS_WINDOWS
+ dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
+ if (mode_bits == S_IFDIR)
+ result = dir_bits != 0;
+ else
+ result = dir_bits == 0;
+#else /* POSIX */
+ if (mode_bits == S_IFDIR)
+ result = self->d_type == DT_DIR;
+ else
+ result = self->d_type == DT_REG;
+#endif
+ }
+#endif
+
+ return result;
+
+error:
+ Py_XDECREF(st_mode);
+ Py_XDECREF(stat);
+ return -1;
+}
+
+static PyObject *
+DirEntry_py_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
+{
+ int result;
+
+ result = DirEntry_test_mode(self, follow_symlinks, mode_bits);
+ if (result == -1)
+ return NULL;
+ return PyBool_FromLong(result);
+}
+
+static PyObject *
+DirEntry_is_dir(DirEntry *self, PyObject *args, PyObject *kwargs)
+{
+ int follow_symlinks = 1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_dir",
+ follow_symlinks_keywords, &follow_symlinks))
+ return NULL;
+
+ return DirEntry_py_test_mode(self, follow_symlinks, S_IFDIR);
+}
+
+static PyObject *
+DirEntry_is_file(DirEntry *self, PyObject *args, PyObject *kwargs)
+{
+ int follow_symlinks = 1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_file",
+ follow_symlinks_keywords, &follow_symlinks))
return NULL;
+
+ return DirEntry_py_test_mode(self, follow_symlinks, S_IFREG);
+}
+
+static PyObject *
+DirEntry_inode(DirEntry *self)
+{
+#ifdef MS_WINDOWS
+ if (!self->got_file_index) {
+ wchar_t *path;
+ struct _Py_stat_struct stat;
+
+ path = PyUnicode_AsUnicode(self->path);
+ if (!path)
+ return NULL;
+
+ if (win32_lstat_w(path, &stat) != 0) {
+ return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError,
+ 0, self->path);
+ }
+
+ self->win32_file_index = stat.st_ino;
+ self->got_file_index = 1;
}
- Py_RETURN_NONE;
+ return PyLong_FromLongLong((PY_LONG_LONG)self->win32_file_index);
+#else /* POSIX */
+#ifdef HAVE_LARGEFILE_SUPPORT
+ return PyLong_FromLongLong((PY_LONG_LONG)self->d_ino);
+#else
+ return PyLong_FromLong((long)self->d_ino);
+#endif
+#endif
}
-#endif /* MS_WINDOWS */
+static PyObject *
+DirEntry_repr(DirEntry *self)
+{
+ return PyUnicode_FromFormat("<DirEntry %R>", self->name);
+}
+
+static PyMemberDef DirEntry_members[] = {
+ {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
+ "the entry's base filename, relative to scandir() \"path\" argument"},
+ {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
+ "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
+ {NULL}
+};
+
+static PyMethodDef DirEntry_methods[] = {
+ {"is_dir", (PyCFunction)DirEntry_is_dir, METH_VARARGS | METH_KEYWORDS,
+ "return True if the entry is a directory; cached per entry"
+ },
+ {"is_file", (PyCFunction)DirEntry_is_file, METH_VARARGS | METH_KEYWORDS,
+ "return True if the entry is a file; cached per entry"
+ },
+ {"is_symlink", (PyCFunction)DirEntry_py_is_symlink, METH_NOARGS,
+ "return True if the entry is a symbolic link; cached per entry"
+ },
+ {"stat", (PyCFunction)DirEntry_stat, METH_VARARGS | METH_KEYWORDS,
+ "return stat_result object for the entry; cached per entry"
+ },
+ {"inode", (PyCFunction)DirEntry_inode, METH_NOARGS,
+ "return inode of the entry; cached per entry",
+ },
+ {NULL}
+};
+
+PyTypeObject DirEntryType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ MODNAME ".DirEntry", /* tp_name */
+ sizeof(DirEntry), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)DirEntry_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)DirEntry_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ DirEntry_methods, /* tp_methods */
+ DirEntry_members, /* tp_members */
+};
+
+#ifdef MS_WINDOWS
+
+static wchar_t *
+join_path_filenameW(wchar_t *path_wide, 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(path_t *path, WIN32_FIND_DATAW *dataW)
+{
+ DirEntry *entry;
+ BY_HANDLE_FILE_INFORMATION file_info;
+ ULONG reparse_tag;
+ wchar_t *joined_path;
+
+ entry = PyObject_New(DirEntry, &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;
+
+ 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;
+
+ find_data_to_file_info_w(dataW, &file_info, &reparse_tag);
+ _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
+
+ return (PyObject *)entry;
+
+error:
+ Py_DECREF(entry);
+ return NULL;
+}
+
+#else /* POSIX */
+
+static char *
+join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len)
+{
+ Py_ssize_t path_len;
+ Py_ssize_t size;
+ char *result;
+
+ if (!path_narrow) { /* Default arg: "." */
+ path_narrow = ".";
+ path_len = 1;
+ }
+ else {
+ path_len = strlen(path_narrow);
+ }
+
+ if (filename_len == -1)
+ filename_len = strlen(filename);
+
+ /* The +1's are for the path separator and the NUL */
+ size = path_len + 1 + filename_len + 1;
+ result = PyMem_New(char, size);
+ if (!result) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ strcpy(result, path_narrow);
+ if (path_len > 0 && result[path_len - 1] != '/')
+ result[path_len++] = '/';
+ strcpy(result + path_len, filename);
+ return result;
+}
+
+static PyObject *
+DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len,
+ ino_t d_ino
+#ifdef HAVE_DIRENT_D_TYPE
+ , unsigned char d_type
+#endif
+ )
+{
+ DirEntry *entry;
+ char *joined_path;
+
+ entry = PyObject_New(DirEntry, &DirEntryType);
+ if (!entry)
+ return NULL;
+ entry->name = NULL;
+ entry->path = NULL;
+ entry->stat = NULL;
+ entry->lstat = NULL;
+
+ joined_path = join_path_filename(path->narrow, name, name_len);
+ if (!joined_path)
+ goto error;
+
+ if (!path->narrow || !PyBytes_Check(path->object)) {
+ entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
+ entry->path = PyUnicode_DecodeFSDefault(joined_path);
+ }
+ else {
+ entry->name = PyBytes_FromStringAndSize(name, name_len);
+ entry->path = PyBytes_FromString(joined_path);
+ }
+ PyMem_Free(joined_path);
+ if (!entry->name || !entry->path)
+ goto error;
+
+#ifdef HAVE_DIRENT_D_TYPE
+ entry->d_type = d_type;
+#endif
+ entry->d_ino = d_ino;
+
+ return (PyObject *)entry;
+
+error:
+ Py_XDECREF(entry);
+ return NULL;
+}
+
+#endif
+
+
+typedef struct {
+ PyObject_HEAD
+ path_t path;
+#ifdef MS_WINDOWS
+ HANDLE handle;
+ WIN32_FIND_DATAW file_data;
+ int first_time;
+#else /* POSIX */
+ DIR *dirp;
+#endif
+} ScandirIterator;
+
+#ifdef MS_WINDOWS
+
+static void
+ScandirIterator_close(ScandirIterator *iterator)
+{
+ if (iterator->handle == INVALID_HANDLE_VALUE)
+ return;
+
+ Py_BEGIN_ALLOW_THREADS
+ FindClose(iterator->handle);
+ Py_END_ALLOW_THREADS
+ iterator->handle = INVALID_HANDLE_VALUE;
+}
+
+static PyObject *
+ScandirIterator_iternext(ScandirIterator *iterator)
+{
+ WIN32_FIND_DATAW *file_data = &iterator->file_data;
+ BOOL success;
+
+ /* Happens if the iterator is iterated twice */
+ if (iterator->handle == INVALID_HANDLE_VALUE) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ while (1) {
+ if (!iterator->first_time) {
+ Py_BEGIN_ALLOW_THREADS
+ success = FindNextFileW(iterator->handle, file_data);
+ Py_END_ALLOW_THREADS
+ if (!success) {
+ if (GetLastError() != ERROR_NO_MORE_FILES)
+ return path_error(&iterator->path);
+ /* No more files found in directory, stop iterating */
+ break;
+ }
+ }
+ iterator->first_time = 0;
+
+ /* Skip over . and .. */
+ if (wcscmp(file_data->cFileName, L".") != 0 &&
+ wcscmp(file_data->cFileName, L"..") != 0)
+ return DirEntry_from_find_data(&iterator->path, file_data);
+
+ /* Loop till we get a non-dot directory or finish iterating */
+ }
+
+ ScandirIterator_close(iterator);
+
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+}
+
+#else /* POSIX */
+
+static void
+ScandirIterator_close(ScandirIterator *iterator)
+{
+ if (!iterator->dirp)
+ return;
+
+ Py_BEGIN_ALLOW_THREADS
+ closedir(iterator->dirp);
+ Py_END_ALLOW_THREADS
+ iterator->dirp = NULL;
+ return;
+}
+
+static PyObject *
+ScandirIterator_iternext(ScandirIterator *iterator)
+{
+ struct dirent *direntp;
+ Py_ssize_t name_len;
+ int is_dot;
+
+ /* Happens if the iterator is iterated twice */
+ if (!iterator->dirp) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ while (1) {
+ errno = 0;
+ Py_BEGIN_ALLOW_THREADS
+ direntp = readdir(iterator->dirp);
+ Py_END_ALLOW_THREADS
+
+ if (!direntp) {
+ if (errno != 0)
+ return path_error(&iterator->path);
+ /* No more files found in directory, stop iterating */
+ break;
+ }
+
+ /* Skip over . and .. */
+ name_len = NAMLEN(direntp);
+ is_dot = direntp->d_name[0] == '.' &&
+ (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
+ if (!is_dot) {
+ return DirEntry_from_posix_info(&iterator->path, direntp->d_name,
+ name_len, direntp->d_ino
+#ifdef HAVE_DIRENT_D_TYPE
+ , direntp->d_type
+#endif
+ );
+ }
+
+ /* Loop till we get a non-dot directory or finish iterating */
+ }
+
+ ScandirIterator_close(iterator);
+
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+}
+
+#endif
+
+static void
+ScandirIterator_dealloc(ScandirIterator *iterator)
+{
+ ScandirIterator_close(iterator);
+ Py_XDECREF(iterator->path.object);
+ path_cleanup(&iterator->path);
+ Py_TYPE(iterator)->tp_free((PyObject *)iterator);
+}
+
+PyTypeObject ScandirIteratorType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ MODNAME ".ScandirIterator", /* tp_name */
+ sizeof(ScandirIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)ScandirIterator_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)ScandirIterator_iternext, /* tp_iternext */
+};
+
+static PyObject *
+posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ ScandirIterator *iterator;
+ static char *keywords[] = {"path", NULL};
+#ifdef MS_WINDOWS
+ wchar_t *path_strW;
+#else
+ char *path;
+#endif
+
+ iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
+ if (!iterator)
+ return NULL;
+ memset(&iterator->path, 0, sizeof(path_t));
+ iterator->path.function_name = "scandir";
+ iterator->path.nullable = 1;
+
+#ifdef MS_WINDOWS
+ iterator->handle = INVALID_HANDLE_VALUE;
+#else
+ iterator->dirp = NULL;
+#endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:scandir", keywords,
+ path_converter, &iterator->path))
+ goto error;
+
+ /* path_converter doesn't keep path.object around, so do it
+ manually for the lifetime of the iterator here (the refcount
+ is decremented in ScandirIterator_dealloc)
+ */
+ Py_XINCREF(iterator->path.object);
+
+#ifdef MS_WINDOWS
+ if (iterator->path.narrow) {
+ PyErr_SetString(PyExc_TypeError,
+ "os.scandir() doesn't support bytes path on Windows, use Unicode instead");
+ goto error;
+ }
+ iterator->first_time = 1;
+
+ path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
+ if (!path_strW)
+ goto error;
+
+ Py_BEGIN_ALLOW_THREADS
+ iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
+ Py_END_ALLOW_THREADS
+
+ PyMem_Free(path_strW);
+
+ if (iterator->handle == INVALID_HANDLE_VALUE) {
+ path_error(&iterator->path);
+ goto error;
+ }
+#else /* POSIX */
+ if (iterator->path.narrow)
+ path = iterator->path.narrow;
+ else
+ path = ".";
+
+ errno = 0;
+ Py_BEGIN_ALLOW_THREADS
+ iterator->dirp = opendir(path);
+ Py_END_ALLOW_THREADS
+
+ if (!iterator->dirp) {
+ path_error(&iterator->path);
+ goto error;
+ }
+#endif
+
+ return (PyObject *)iterator;
+
+error:
+ Py_DECREF(iterator);
+ return NULL;
+}
+
+
+#include "clinic/posixmodule.c.h"
/*[clinic input]
dump buffer
[clinic start generated code]*/
-
-#ifndef OS_TTYNAME_METHODDEF
- #define OS_TTYNAME_METHODDEF
-#endif /* !defined(OS_TTYNAME_METHODDEF) */
-/*[clinic end generated code: output=5d071bbc8f49ea12 input=524ce2e021e4eba6]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
static PyMethodDef posix_methods[] = {
@@ -11193,71 +12082,26 @@ static PyMethodDef posix_methods[] = {
OS_STAT_METHODDEF
OS_ACCESS_METHODDEF
OS_TTYNAME_METHODDEF
-
- {"chdir", (PyCFunction)posix_chdir,
- METH_VARARGS | METH_KEYWORDS,
- posix_chdir__doc__},
-#ifdef HAVE_CHFLAGS
- {"chflags", (PyCFunction)posix_chflags,
- METH_VARARGS | METH_KEYWORDS,
- posix_chflags__doc__},
-#endif /* HAVE_CHFLAGS */
- {"chmod", (PyCFunction)posix_chmod,
- METH_VARARGS | METH_KEYWORDS,
- posix_chmod__doc__},
-#ifdef HAVE_FCHMOD
- {"fchmod", posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
-#endif /* HAVE_FCHMOD */
-#ifdef HAVE_CHOWN
- {"chown", (PyCFunction)posix_chown,
- METH_VARARGS | METH_KEYWORDS,
- posix_chown__doc__},
-#endif /* HAVE_CHOWN */
-#ifdef HAVE_LCHMOD
- {"lchmod", posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
-#endif /* HAVE_LCHMOD */
-#ifdef HAVE_FCHOWN
- {"fchown", posix_fchown, METH_VARARGS, posix_fchown__doc__},
-#endif /* HAVE_FCHOWN */
-#ifdef HAVE_LCHFLAGS
- {"lchflags", posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
-#endif /* HAVE_LCHFLAGS */
-#ifdef HAVE_LCHOWN
- {"lchown", posix_lchown, METH_VARARGS, posix_lchown__doc__},
-#endif /* HAVE_LCHOWN */
-#ifdef HAVE_CHROOT
- {"chroot", posix_chroot, METH_VARARGS, posix_chroot__doc__},
-#endif
-#ifdef HAVE_CTERMID
- {"ctermid", posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
-#endif
- {"getcwd", (PyCFunction)posix_getcwd_unicode,
- METH_NOARGS, posix_getcwd__doc__},
- {"getcwdb", (PyCFunction)posix_getcwd_bytes,
- METH_NOARGS, posix_getcwdb__doc__},
-#if defined(HAVE_LINK) || defined(MS_WINDOWS)
- {"link", (PyCFunction)posix_link,
- METH_VARARGS | METH_KEYWORDS,
- posix_link__doc__},
-#endif /* HAVE_LINK */
- {"listdir", (PyCFunction)posix_listdir,
- METH_VARARGS | METH_KEYWORDS,
- posix_listdir__doc__},
- {"lstat", (PyCFunction)posix_lstat,
- METH_VARARGS | METH_KEYWORDS,
- posix_lstat__doc__},
- {"mkdir", (PyCFunction)posix_mkdir,
- METH_VARARGS | METH_KEYWORDS,
- posix_mkdir__doc__},
-#ifdef HAVE_NICE
- {"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
-#endif /* HAVE_NICE */
-#ifdef HAVE_GETPRIORITY
- {"getpriority", posix_getpriority, METH_VARARGS, posix_getpriority__doc__},
-#endif /* HAVE_GETPRIORITY */
-#ifdef HAVE_SETPRIORITY
- {"setpriority", posix_setpriority, METH_VARARGS, posix_setpriority__doc__},
-#endif /* HAVE_SETPRIORITY */
+ OS_CHDIR_METHODDEF
+ OS_CHFLAGS_METHODDEF
+ OS_CHMOD_METHODDEF
+ OS_FCHMOD_METHODDEF
+ OS_LCHMOD_METHODDEF
+ OS_CHOWN_METHODDEF
+ OS_FCHOWN_METHODDEF
+ OS_LCHOWN_METHODDEF
+ OS_LCHFLAGS_METHODDEF
+ OS_CHROOT_METHODDEF
+ OS_CTERMID_METHODDEF
+ OS_GETCWD_METHODDEF
+ OS_GETCWDB_METHODDEF
+ OS_LINK_METHODDEF
+ OS_LISTDIR_METHODDEF
+ OS_LSTAT_METHODDEF
+ OS_MKDIR_METHODDEF
+ OS_NICE_METHODDEF
+ OS_GETPRIORITY_METHODDEF
+ OS_SETPRIORITY_METHODDEF
#ifdef HAVE_READLINK
{"readlink", (PyCFunction)posix_readlink,
METH_VARARGS | METH_KEYWORDS,
@@ -11268,376 +12112,164 @@ static PyMethodDef posix_methods[] = {
METH_VARARGS | METH_KEYWORDS,
readlink__doc__},
#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
- {"rename", (PyCFunction)posix_rename,
- METH_VARARGS | METH_KEYWORDS,
- posix_rename__doc__},
- {"replace", (PyCFunction)posix_replace,
- METH_VARARGS | METH_KEYWORDS,
- posix_replace__doc__},
- {"rmdir", (PyCFunction)posix_rmdir,
- METH_VARARGS | METH_KEYWORDS,
- posix_rmdir__doc__},
+ OS_RENAME_METHODDEF
+ OS_REPLACE_METHODDEF
+ OS_RMDIR_METHODDEF
{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
-#if defined(HAVE_SYMLINK)
- {"symlink", (PyCFunction)posix_symlink,
- METH_VARARGS | METH_KEYWORDS,
- posix_symlink__doc__},
-#endif /* HAVE_SYMLINK */
-#ifdef HAVE_SYSTEM
- {"system", posix_system, METH_VARARGS, posix_system__doc__},
-#endif
- {"umask", posix_umask, METH_VARARGS, posix_umask__doc__},
-#ifdef HAVE_UNAME
- {"uname", posix_uname, METH_NOARGS, posix_uname__doc__},
-#endif /* HAVE_UNAME */
- {"unlink", (PyCFunction)posix_unlink,
- METH_VARARGS | METH_KEYWORDS,
- posix_unlink__doc__},
- {"remove", (PyCFunction)posix_unlink,
- METH_VARARGS | METH_KEYWORDS,
- posix_remove__doc__},
- {"utime", (PyCFunction)posix_utime,
- METH_VARARGS | METH_KEYWORDS, posix_utime__doc__},
-#ifdef HAVE_TIMES
- {"times", posix_times, METH_NOARGS, posix_times__doc__},
-#endif /* HAVE_TIMES */
- {"_exit", posix__exit, METH_VARARGS, posix__exit__doc__},
-#ifdef HAVE_EXECV
- {"execv", posix_execv, METH_VARARGS, posix_execv__doc__},
- {"execve", (PyCFunction)posix_execve,
- METH_VARARGS | METH_KEYWORDS,
- posix_execve__doc__},
-#endif /* HAVE_EXECV */
-#ifdef HAVE_SPAWNV
- {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
- {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
-#endif /* HAVE_SPAWNV */
-#ifdef HAVE_FORK1
- {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__},
-#endif /* HAVE_FORK1 */
-#ifdef HAVE_FORK
- {"fork", posix_fork, METH_NOARGS, posix_fork__doc__},
-#endif /* HAVE_FORK */
-#ifdef HAVE_SCHED_H
-#ifdef HAVE_SCHED_GET_PRIORITY_MAX
- {"sched_get_priority_max", posix_sched_get_priority_max, METH_VARARGS, posix_sched_get_priority_max__doc__},
- {"sched_get_priority_min", posix_sched_get_priority_min, METH_VARARGS, posix_sched_get_priority_min__doc__},
-#endif
-#ifdef HAVE_SCHED_SETPARAM
- {"sched_getparam", posix_sched_getparam, METH_VARARGS, posix_sched_getparam__doc__},
-#endif
-#ifdef HAVE_SCHED_SETSCHEDULER
- {"sched_getscheduler", posix_sched_getscheduler, METH_VARARGS, posix_sched_getscheduler__doc__},
-#endif
-#ifdef HAVE_SCHED_RR_GET_INTERVAL
- {"sched_rr_get_interval", posix_sched_rr_get_interval, METH_VARARGS, posix_sched_rr_get_interval__doc__},
-#endif
-#ifdef HAVE_SCHED_SETPARAM
- {"sched_setparam", posix_sched_setparam, METH_VARARGS, posix_sched_setparam__doc__},
-#endif
-#ifdef HAVE_SCHED_SETSCHEDULER
- {"sched_setscheduler", posix_sched_setscheduler, METH_VARARGS, posix_sched_setscheduler__doc__},
-#endif
- {"sched_yield", posix_sched_yield, METH_NOARGS, posix_sched_yield__doc__},
-#ifdef HAVE_SCHED_SETAFFINITY
- {"sched_setaffinity", posix_sched_setaffinity, METH_VARARGS, posix_sched_setaffinity__doc__},
- {"sched_getaffinity", posix_sched_getaffinity, METH_VARARGS, posix_sched_getaffinity__doc__},
-#endif
-#endif /* HAVE_SCHED_H */
-#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
- {"openpty", posix_openpty, METH_NOARGS, posix_openpty__doc__},
-#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
-#ifdef HAVE_FORKPTY
- {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
-#endif /* HAVE_FORKPTY */
-#ifdef HAVE_GETEGID
- {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__},
-#endif /* HAVE_GETEGID */
-#ifdef HAVE_GETEUID
- {"geteuid", posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
-#endif /* HAVE_GETEUID */
-#ifdef HAVE_GETGID
- {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__},
-#endif /* HAVE_GETGID */
+ OS_SYMLINK_METHODDEF
+ OS_SYSTEM_METHODDEF
+ OS_UMASK_METHODDEF
+ OS_UNAME_METHODDEF
+ OS_UNLINK_METHODDEF
+ OS_REMOVE_METHODDEF
+ OS_UTIME_METHODDEF
+ OS_TIMES_METHODDEF
+ OS__EXIT_METHODDEF
+ OS_EXECV_METHODDEF
+ OS_EXECVE_METHODDEF
+ OS_SPAWNV_METHODDEF
+ OS_SPAWNVE_METHODDEF
+ OS_FORK1_METHODDEF
+ OS_FORK_METHODDEF
+ OS_SCHED_GET_PRIORITY_MAX_METHODDEF
+ OS_SCHED_GET_PRIORITY_MIN_METHODDEF
+ OS_SCHED_GETPARAM_METHODDEF
+ OS_SCHED_GETSCHEDULER_METHODDEF
+ OS_SCHED_RR_GET_INTERVAL_METHODDEF
+ OS_SCHED_SETPARAM_METHODDEF
+ OS_SCHED_SETSCHEDULER_METHODDEF
+ OS_SCHED_YIELD_METHODDEF
+ OS_SCHED_SETAFFINITY_METHODDEF
+ OS_SCHED_GETAFFINITY_METHODDEF
+ OS_OPENPTY_METHODDEF
+ OS_FORKPTY_METHODDEF
+ OS_GETEGID_METHODDEF
+ OS_GETEUID_METHODDEF
+ OS_GETGID_METHODDEF
#ifdef HAVE_GETGROUPLIST
{"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
#endif
-#ifdef HAVE_GETGROUPS
- {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
-#endif
- {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__},
-#ifdef HAVE_GETPGRP
- {"getpgrp", posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
-#endif /* HAVE_GETPGRP */
-#ifdef HAVE_GETPPID
- {"getppid", posix_getppid, METH_NOARGS, posix_getppid__doc__},
-#endif /* HAVE_GETPPID */
-#ifdef HAVE_GETUID
- {"getuid", posix_getuid, METH_NOARGS, posix_getuid__doc__},
-#endif /* HAVE_GETUID */
-#ifdef HAVE_GETLOGIN
- {"getlogin", posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
-#endif
-#ifdef HAVE_KILL
- {"kill", posix_kill, METH_VARARGS, posix_kill__doc__},
-#endif /* HAVE_KILL */
-#ifdef HAVE_KILLPG
- {"killpg", posix_killpg, METH_VARARGS, posix_killpg__doc__},
-#endif /* HAVE_KILLPG */
-#ifdef HAVE_PLOCK
- {"plock", posix_plock, METH_VARARGS, posix_plock__doc__},
-#endif /* HAVE_PLOCK */
+ OS_GETGROUPS_METHODDEF
+ OS_GETPID_METHODDEF
+ OS_GETPGRP_METHODDEF
+ OS_GETPPID_METHODDEF
+ OS_GETUID_METHODDEF
+ OS_GETLOGIN_METHODDEF
+ OS_KILL_METHODDEF
+ OS_KILLPG_METHODDEF
+ OS_PLOCK_METHODDEF
#ifdef MS_WINDOWS
{"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__},
- {"kill", win32_kill, METH_VARARGS, win32_kill__doc__},
#endif
-#ifdef HAVE_SETUID
- {"setuid", posix_setuid, METH_VARARGS, posix_setuid__doc__},
-#endif /* HAVE_SETUID */
-#ifdef HAVE_SETEUID
- {"seteuid", posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
-#endif /* HAVE_SETEUID */
-#ifdef HAVE_SETEGID
- {"setegid", posix_setegid, METH_VARARGS, posix_setegid__doc__},
-#endif /* HAVE_SETEGID */
-#ifdef HAVE_SETREUID
- {"setreuid", posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
-#endif /* HAVE_SETREUID */
-#ifdef HAVE_SETREGID
- {"setregid", posix_setregid, METH_VARARGS, posix_setregid__doc__},
-#endif /* HAVE_SETREGID */
-#ifdef HAVE_SETGID
- {"setgid", posix_setgid, METH_VARARGS, posix_setgid__doc__},
-#endif /* HAVE_SETGID */
-#ifdef HAVE_SETGROUPS
- {"setgroups", posix_setgroups, METH_O, posix_setgroups__doc__},
-#endif /* HAVE_SETGROUPS */
+ OS_SETUID_METHODDEF
+ OS_SETEUID_METHODDEF
+ OS_SETREUID_METHODDEF
+ OS_SETGID_METHODDEF
+ OS_SETEGID_METHODDEF
+ OS_SETREGID_METHODDEF
+ OS_SETGROUPS_METHODDEF
#ifdef HAVE_INITGROUPS
{"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
#endif /* HAVE_INITGROUPS */
-#ifdef HAVE_GETPGID
- {"getpgid", posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
-#endif /* HAVE_GETPGID */
-#ifdef HAVE_SETPGRP
- {"setpgrp", posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
-#endif /* HAVE_SETPGRP */
-#ifdef HAVE_WAIT
- {"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
-#endif /* HAVE_WAIT */
-#ifdef HAVE_WAIT3
- {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__},
-#endif /* HAVE_WAIT3 */
-#ifdef HAVE_WAIT4
- {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__},
-#endif /* HAVE_WAIT4 */
-#if defined(HAVE_WAITID) && !defined(__APPLE__)
- {"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__},
-#endif
-#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
- {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
-#endif /* HAVE_WAITPID */
-#ifdef HAVE_GETSID
- {"getsid", posix_getsid, METH_VARARGS, posix_getsid__doc__},
-#endif /* HAVE_GETSID */
-#ifdef HAVE_SETSID
- {"setsid", posix_setsid, METH_NOARGS, posix_setsid__doc__},
-#endif /* HAVE_SETSID */
-#ifdef HAVE_SETPGID
- {"setpgid", posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
-#endif /* HAVE_SETPGID */
-#ifdef HAVE_TCGETPGRP
- {"tcgetpgrp", posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
-#endif /* HAVE_TCGETPGRP */
-#ifdef HAVE_TCSETPGRP
- {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
-#endif /* HAVE_TCSETPGRP */
- {"open", (PyCFunction)posix_open,\
- METH_VARARGS | METH_KEYWORDS,
- posix_open__doc__},
- {"close", posix_close_, METH_VARARGS, posix_close__doc__},
- {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__},
- {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
- {"dup", posix_dup, METH_VARARGS, posix_dup__doc__},
- {"dup2", (PyCFunction)posix_dup2,
- METH_VARARGS | METH_KEYWORDS, posix_dup2__doc__},
-#ifdef HAVE_LOCKF
- {"lockf", posix_lockf, METH_VARARGS, posix_lockf__doc__},
-#endif
- {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__},
- {"read", posix_read, METH_VARARGS, posix_read__doc__},
-#ifdef HAVE_READV
- {"readv", posix_readv, METH_VARARGS, posix_readv__doc__},
-#endif
-#ifdef HAVE_PREAD
- {"pread", posix_pread, METH_VARARGS, posix_pread__doc__},
-#endif
- {"write", posix_write, METH_VARARGS, posix_write__doc__},
-#ifdef HAVE_WRITEV
- {"writev", posix_writev, METH_VARARGS, posix_writev__doc__},
-#endif
-#ifdef HAVE_PWRITE
- {"pwrite", posix_pwrite, METH_VARARGS, posix_pwrite__doc__},
-#endif
+ OS_GETPGID_METHODDEF
+ OS_SETPGRP_METHODDEF
+ OS_WAIT_METHODDEF
+ OS_WAIT3_METHODDEF
+ OS_WAIT4_METHODDEF
+ OS_WAITID_METHODDEF
+ OS_WAITPID_METHODDEF
+ OS_GETSID_METHODDEF
+ OS_SETSID_METHODDEF
+ OS_SETPGID_METHODDEF
+ OS_TCGETPGRP_METHODDEF
+ OS_TCSETPGRP_METHODDEF
+ OS_OPEN_METHODDEF
+ OS_CLOSE_METHODDEF
+ OS_CLOSERANGE_METHODDEF
+ OS_DEVICE_ENCODING_METHODDEF
+ OS_DUP_METHODDEF
+ OS_DUP2_METHODDEF
+ OS_LOCKF_METHODDEF
+ OS_LSEEK_METHODDEF
+ OS_READ_METHODDEF
+ OS_READV_METHODDEF
+ OS_PREAD_METHODDEF
+ OS_WRITE_METHODDEF
+ OS_WRITEV_METHODDEF
+ OS_PWRITE_METHODDEF
#ifdef HAVE_SENDFILE
{"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
posix_sendfile__doc__},
#endif
- {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__},
- {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
-#ifdef HAVE_PIPE
- {"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
-#endif
-#ifdef HAVE_PIPE2
- {"pipe2", posix_pipe2, METH_O, posix_pipe2__doc__},
-#endif
-#ifdef HAVE_MKFIFO
- {"mkfifo", (PyCFunction)posix_mkfifo,
- METH_VARARGS | METH_KEYWORDS,
- posix_mkfifo__doc__},
-#endif
-#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
- {"mknod", (PyCFunction)posix_mknod,
- METH_VARARGS | METH_KEYWORDS,
- posix_mknod__doc__},
-#endif
-#ifdef HAVE_DEVICE_MACROS
- {"major", posix_major, METH_VARARGS, posix_major__doc__},
- {"minor", posix_minor, METH_VARARGS, posix_minor__doc__},
- {"makedev", posix_makedev, METH_VARARGS, posix_makedev__doc__},
-#endif
-#ifdef HAVE_FTRUNCATE
- {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
-#endif
-#ifdef HAVE_TRUNCATE
- {"truncate", (PyCFunction)posix_truncate,
- METH_VARARGS | METH_KEYWORDS,
- posix_truncate__doc__},
-#endif
-#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
- {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__},
-#endif
-#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
- {"posix_fadvise", posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__},
-#endif
-#ifdef HAVE_PUTENV
- {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__},
-#endif
-#ifdef HAVE_UNSETENV
- {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
-#endif
- {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__},
-#ifdef HAVE_FCHDIR
- {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__},
-#endif
-#ifdef HAVE_FSYNC
- {"fsync", posix_fsync, METH_O, posix_fsync__doc__},
-#endif
-#ifdef HAVE_SYNC
- {"sync", posix_sync, METH_NOARGS, posix_sync__doc__},
-#endif
-#ifdef HAVE_FDATASYNC
- {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__},
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#ifdef WCOREDUMP
- {"WCOREDUMP", posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
-#endif /* WCOREDUMP */
-#ifdef WIFCONTINUED
- {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
-#endif /* WIFCONTINUED */
-#ifdef WIFSTOPPED
- {"WIFSTOPPED", posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
-#endif /* WIFSTOPPED */
-#ifdef WIFSIGNALED
- {"WIFSIGNALED", posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
-#endif /* WIFSIGNALED */
-#ifdef WIFEXITED
- {"WIFEXITED", posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
-#endif /* WIFEXITED */
-#ifdef WEXITSTATUS
- {"WEXITSTATUS", posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
-#endif /* WEXITSTATUS */
-#ifdef WTERMSIG
- {"WTERMSIG", posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
-#endif /* WTERMSIG */
-#ifdef WSTOPSIG
- {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
-#endif /* WSTOPSIG */
-#endif /* HAVE_SYS_WAIT_H */
-#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
- {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
-#endif
-#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
- {"statvfs", (PyCFunction)posix_statvfs,
- METH_VARARGS | METH_KEYWORDS,
- posix_statvfs__doc__},
-#endif
-#ifdef HAVE_CONFSTR
- {"confstr", posix_confstr, METH_VARARGS, posix_confstr__doc__},
-#endif
-#ifdef HAVE_SYSCONF
- {"sysconf", posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
-#endif
-#ifdef HAVE_FPATHCONF
- {"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
-#endif
-#ifdef HAVE_PATHCONF
- {"pathconf", (PyCFunction)posix_pathconf,
- METH_VARARGS | METH_KEYWORDS,
- posix_pathconf__doc__},
-#endif
- {"abort", posix_abort, METH_NOARGS, posix_abort__doc__},
+ OS_FSTAT_METHODDEF
+ OS_ISATTY_METHODDEF
+ OS_PIPE_METHODDEF
+ OS_PIPE2_METHODDEF
+ OS_MKFIFO_METHODDEF
+ OS_MKNOD_METHODDEF
+ OS_MAJOR_METHODDEF
+ OS_MINOR_METHODDEF
+ OS_MAKEDEV_METHODDEF
+ OS_FTRUNCATE_METHODDEF
+ OS_TRUNCATE_METHODDEF
+ OS_POSIX_FALLOCATE_METHODDEF
+ OS_POSIX_FADVISE_METHODDEF
+ OS_PUTENV_METHODDEF
+ OS_UNSETENV_METHODDEF
+ OS_STRERROR_METHODDEF
+ OS_FCHDIR_METHODDEF
+ OS_FSYNC_METHODDEF
+ OS_SYNC_METHODDEF
+ OS_FDATASYNC_METHODDEF
+ OS_WCOREDUMP_METHODDEF
+ OS_WIFCONTINUED_METHODDEF
+ OS_WIFSTOPPED_METHODDEF
+ OS_WIFSIGNALED_METHODDEF
+ OS_WIFEXITED_METHODDEF
+ OS_WEXITSTATUS_METHODDEF
+ OS_WTERMSIG_METHODDEF
+ OS_WSTOPSIG_METHODDEF
+ OS_FSTATVFS_METHODDEF
+ OS_STATVFS_METHODDEF
+ OS_CONFSTR_METHODDEF
+ OS_SYSCONF_METHODDEF
+ OS_FPATHCONF_METHODDEF
+ OS_PATHCONF_METHODDEF
+ OS_ABORT_METHODDEF
#ifdef MS_WINDOWS
{"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL},
- {"_getfinalpathname", posix__getfinalpathname, METH_VARARGS, NULL},
{"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__},
- {"_getdiskusage", win32__getdiskusage, METH_VARARGS, win32__getdiskusage__doc__},
- {"_getvolumepathname", posix__getvolumepathname, METH_VARARGS, posix__getvolumepathname__doc__},
-#endif
-#ifdef HAVE_GETLOADAVG
- {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
-#endif
- {"urandom", posix_urandom, METH_VARARGS, posix_urandom__doc__},
-#ifdef HAVE_SETRESUID
- {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
-#endif
-#ifdef HAVE_SETRESGID
- {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
-#endif
-#ifdef HAVE_GETRESUID
- {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
-#endif
-#ifdef HAVE_GETRESGID
- {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
#endif
+ OS__GETDISKUSAGE_METHODDEF
+ OS__GETFINALPATHNAME_METHODDEF
+ OS__GETVOLUMEPATHNAME_METHODDEF
+ OS_GETLOADAVG_METHODDEF
+ OS_URANDOM_METHODDEF
+ OS_SETRESUID_METHODDEF
+ OS_SETRESGID_METHODDEF
+ OS_GETRESUID_METHODDEF
+ OS_GETRESGID_METHODDEF
+
+ OS_GETXATTR_METHODDEF
+ OS_SETXATTR_METHODDEF
+ OS_REMOVEXATTR_METHODDEF
+ OS_LISTXATTR_METHODDEF
-#ifdef USE_XATTRS
- {"setxattr", (PyCFunction)posix_setxattr,
- METH_VARARGS | METH_KEYWORDS,
- posix_setxattr__doc__},
- {"getxattr", (PyCFunction)posix_getxattr,
- METH_VARARGS | METH_KEYWORDS,
- posix_getxattr__doc__},
- {"removexattr", (PyCFunction)posix_removexattr,
- METH_VARARGS | METH_KEYWORDS,
- posix_removexattr__doc__},
- {"listxattr", (PyCFunction)posix_listxattr,
- METH_VARARGS | METH_KEYWORDS,
- posix_listxattr__doc__},
-#endif
#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
{"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
#endif
- {"cpu_count", (PyCFunction)posix_cpu_count,
- METH_NOARGS, posix_cpu_count__doc__},
- {"get_inheritable", posix_get_inheritable, METH_VARARGS, get_inheritable__doc__},
- {"set_inheritable", posix_set_inheritable, METH_VARARGS, set_inheritable__doc__},
-#ifdef MS_WINDOWS
- {"get_handle_inheritable", posix_get_handle_inheritable,
- METH_VARARGS, get_handle_inheritable__doc__},
- {"set_handle_inheritable", posix_set_handle_inheritable,
- METH_VARARGS, set_handle_inheritable__doc__},
+ OS_CPU_COUNT_METHODDEF
+ OS_GET_INHERITABLE_METHODDEF
+ OS_SET_INHERITABLE_METHODDEF
+ OS_GET_HANDLE_INHERITABLE_METHODDEF
+ OS_SET_HANDLE_INHERITABLE_METHODDEF
+#ifndef MS_WINDOWS
+ {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__},
+ {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__},
#endif
+ {"scandir", (PyCFunction)posix_scandir,
+ METH_VARARGS | METH_KEYWORDS,
+ posix_scandir__doc__},
{NULL, NULL} /* Sentinel */
};
@@ -12080,15 +12712,6 @@ all_ins(PyObject *m)
}
-#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
-#define INITFUNC PyInit_nt
-#define MODNAME "nt"
-
-#else
-#define INITFUNC PyInit_posix
-#define MODNAME "posix"
-#endif
-
static struct PyModuleDef posixmodule = {
PyModuleDef_HEAD_INIT,
MODNAME,
@@ -12302,13 +12925,19 @@ INITFUNC(void)
sched_param_desc.name = MODNAME ".sched_param";
if (PyStructSequence_InitType2(&SchedParamType, &sched_param_desc) < 0)
return NULL;
- SchedParamType.tp_new = sched_param_new;
+ SchedParamType.tp_new = os_sched_param;
#endif
/* initialize TerminalSize_info */
if (PyStructSequence_InitType2(&TerminalSizeType,
&TerminalSize_desc) < 0)
return NULL;
+
+ /* initialize scandir types */
+ if (PyType_Ready(&ScandirIteratorType) < 0)
+ return NULL;
+ if (PyType_Ready(&DirEntryType) < 0)
+ return NULL;
}
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_INCREF((PyObject*) &WaitidResultType);