summaryrefslogtreecommitdiff
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c1909
1 files changed, 1782 insertions, 127 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 89d3f2f2d0..8f17bf4134 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -59,6 +59,10 @@ corresponding Unix manual entries for more information on calls.");
#include "osdefs.h"
#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
@@ -95,6 +99,16 @@ corresponding Unix manual entries for more information on calls.");
#include <langinfo.h>
#endif
+#ifdef HAVE_SYS_SENDFILE_H
+#include <sys/sendfile.h>
+#endif
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#endif
+
/* Various compilers have only certain posix functions */
/* XXX Gosh I wish these were all moved into pyconfig.h */
#if defined(PYCC_VACPP) && defined(PYOS_OS2)
@@ -121,7 +135,7 @@ corresponding Unix manual entries for more information on calls.");
#ifdef _MSC_VER /* Microsoft compiler */
#define HAVE_GETCWD 1
#define HAVE_GETPPID 1
-#define HAVE_GETLOGIN 1
+#define HAVE_GETLOGIN 1
#define HAVE_SPAWNV 1
#define HAVE_EXECV 1
#define HAVE_PIPE 1
@@ -349,6 +363,19 @@ static int win32_can_symlink = 0;
#endif
#endif
+static int
+_parse_off_t(PyObject* arg, void* addr)
+{
+#if !defined(HAVE_LARGEFILE_SUPPORT)
+ *((off_t*)addr) = PyLong_AsLong(arg);
+#else
+ *((off_t*)addr) = PyLong_AsLongLong(arg);
+#endif
+ if (PyErr_Occurred())
+ return 0;
+ return 1;
+}
+
#if defined _MSC_VER && _MSC_VER >= 1400
/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
* valid and throw an assertion if it isn't.
@@ -1283,7 +1310,7 @@ 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
+static int
win32_lstat(const char* path, struct win32_stat *result)
{
return win32_xstat(path, result, FALSE);
@@ -1301,7 +1328,7 @@ win32_stat(const char* path, struct win32_stat *result)
return win32_xstat(path, result, TRUE);
}
-static int
+static int
win32_stat_w(const wchar_t* path, struct win32_stat *result)
{
return win32_xstat_w(path, result, TRUE);
@@ -1476,6 +1503,33 @@ static PyStructSequence_Desc statvfs_result_desc = {
10
};
+#if defined(HAVE_WAITID) && !defined(__APPLE__)
+PyDoc_STRVAR(waitid_result__doc__,
+"waitid_result: Result from waitid.\n\n\
+This object may be accessed either as a tuple of\n\
+ (si_pid, si_uid, si_signo, si_status, si_code),\n\
+or via the attributes si_pid, si_uid, and so on.\n\
+\n\
+See os.waitid for more information.");
+
+static PyStructSequence_Field waitid_result_fields[] = {
+ {"si_pid", },
+ {"si_uid", },
+ {"si_signo", },
+ {"si_status", },
+ {"si_code", },
+ {0}
+};
+
+static PyStructSequence_Desc waitid_result_desc = {
+ "waitid_result", /* name */
+ waitid_result__doc__, /* doc */
+ waitid_result_fields,
+ 5
+};
+static PyTypeObject WaitidResultType;
+#endif
+
static int initialized;
static PyTypeObject StatResultType;
static PyTypeObject StatVFSResultType;
@@ -2075,6 +2129,21 @@ posix_fsync(PyObject *self, PyObject *fdobj)
}
#endif /* HAVE_FSYNC */
+#ifdef HAVE_SYNC
+PyDoc_STRVAR(posix_sync__doc__,
+"sync()\n\n\
+Force write of everything to disk.");
+
+static PyObject *
+posix_sync(PyObject *self, PyObject *noargs)
+{
+ Py_BEGIN_ALLOW_THREADS
+ sync();
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+#endif
+
#ifdef HAVE_FDATASYNC
#ifdef __hpux
@@ -2339,7 +2408,7 @@ posix_listdir(PyObject *self, PyObject *args)
if (PyArg_ParseTuple(args, "|U:listdir", &po)) {
WIN32_FIND_DATAW wFileData;
Py_UNICODE *wnamebuf, *po_wchars;
-
+
if (po == NULL) { /* Default arg: "." */
po_wchars = L".";
len = 1;
@@ -2650,6 +2719,76 @@ posix_listdir(PyObject *self, PyObject *args)
#endif /* which OS */
} /* end of posix_listdir */
+#ifdef HAVE_FDOPENDIR
+PyDoc_STRVAR(posix_fdlistdir__doc__,
+"fdlistdir(fd) -> list_of_strings\n\n\
+Like listdir(), but uses a file descriptor instead.\n\
+After succesful execution of this function, fd will be closed.");
+
+static PyObject *
+posix_fdlistdir(PyObject *self, PyObject *args)
+{
+ PyObject *d, *v;
+ DIR *dirp;
+ struct dirent *ep;
+ int fd;
+
+ errno = 0;
+ if (!PyArg_ParseTuple(args, "i:fdlistdir", &fd))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ dirp = fdopendir(fd);
+ Py_END_ALLOW_THREADS
+ if (dirp == NULL) {
+ close(fd);
+ return posix_error();
+ }
+ if ((d = PyList_New(0)) == NULL) {
+ Py_BEGIN_ALLOW_THREADS
+ closedir(dirp);
+ Py_END_ALLOW_THREADS
+ return NULL;
+ }
+ for (;;) {
+ errno = 0;
+ Py_BEGIN_ALLOW_THREADS
+ ep = readdir(dirp);
+ Py_END_ALLOW_THREADS
+ if (ep == NULL) {
+ if (errno == 0) {
+ break;
+ } else {
+ Py_BEGIN_ALLOW_THREADS
+ closedir(dirp);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(d);
+ return posix_error();
+ }
+ }
+ if (ep->d_name[0] == '.' &&
+ (NAMLEN(ep) == 1 ||
+ (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
+ continue;
+ v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
+ if (v == NULL) {
+ Py_CLEAR(d);
+ break;
+ }
+ if (PyList_Append(d, v) != 0) {
+ Py_DECREF(v);
+ Py_CLEAR(d);
+ break;
+ }
+ Py_DECREF(v);
+ }
+ Py_BEGIN_ALLOW_THREADS
+ closedir(dirp);
+ Py_END_ALLOW_THREADS
+
+ return d;
+}
+#endif
+
#ifdef MS_WINDOWS
/* A helper function for abspath on win32 */
static PyObject *
@@ -2741,7 +2880,7 @@ posix__getfinalpathname(PyObject *self, PyObject *args)
int result_length;
PyObject *result;
wchar_t *path;
-
+
if (!PyArg_ParseTuple(args, "u|:_getfinalpathname", &path)) {
return NULL;
}
@@ -2762,7 +2901,7 @@ posix__getfinalpathname(PyObject *self, PyObject *args)
/* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
-
+
if(hFile == INVALID_HANDLE_VALUE) {
return win32_error_unicode("GetFinalPathNamyByHandle", path);
return PyErr_Format(PyExc_RuntimeError,
@@ -2930,6 +3069,52 @@ posix_nice(PyObject *self, PyObject *args)
}
#endif /* HAVE_NICE */
+
+#ifdef HAVE_GETPRIORITY
+PyDoc_STRVAR(posix_getpriority__doc__,
+"getpriority(which, who) -> current_priority\n\n\
+Get program scheduling priority.");
+
+static PyObject *
+posix_getpriority(PyObject *self, PyObject *args)
+{
+ int which, who, retval;
+
+ if (!PyArg_ParseTuple(args, "ii", &which, &who))
+ return NULL;
+ errno = 0;
+ Py_BEGIN_ALLOW_THREADS
+ retval = getpriority(which, who);
+ Py_END_ALLOW_THREADS
+ if (errno != 0)
+ return posix_error();
+ return PyLong_FromLong((long)retval);
+}
+#endif /* HAVE_GETPRIORITY */
+
+
+#ifdef HAVE_SETPRIORITY
+PyDoc_STRVAR(posix_setpriority__doc__,
+"setpriority(which, who, prio) -> None\n\n\
+Set program scheduling priority.");
+
+static PyObject *
+posix_setpriority(PyObject *self, PyObject *args)
+{
+ int which, who, prio, retval;
+
+ if (!PyArg_ParseTuple(args, "iii", &which, &who, &prio))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ retval = setpriority(which, who, prio);
+ Py_END_ALLOW_THREADS
+ if (retval == -1)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETPRIORITY */
+
+
PyDoc_STRVAR(posix_rename__doc__,
"rename(old, new)\n\n\
Rename a file or directory.");
@@ -3072,7 +3257,7 @@ BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
-
+
/* Get WIN32_FIND_DATA structure for the path to determine if
it is a symlink */
if(is_directory &&
@@ -3345,6 +3530,167 @@ done:
#endif /* MS_WINDOWS */
}
+#ifdef HAVE_FUTIMES
+PyDoc_STRVAR(posix_futimes__doc__,
+"futimes(fd, (atime, mtime))\n\
+futimes(fd, None)\n\n\
+Set the access and modified time of the file specified by the file\n\
+descriptor fd to the given values. If the second form is used, set the\n\
+access and modified times to the current time.");
+
+static PyObject *
+posix_futimes(PyObject *self, PyObject *args)
+{
+ int res, fd;
+ PyObject* arg;
+ struct timeval buf[2];
+ long ausec, musec;
+
+ if (!PyArg_ParseTuple(args, "iO:futimes", &fd, &arg))
+ return NULL;
+
+ if (arg == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = futimes(fd, NULL);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "futimes() arg 2 must be a tuple (atime, mtime)");
+ return NULL;
+ }
+ else {
+ if (extract_time(PyTuple_GET_ITEM(arg, 0),
+ &(buf[0].tv_sec), &ausec) == -1) {
+ return NULL;
+ }
+ if (extract_time(PyTuple_GET_ITEM(arg, 1),
+ &(buf[1].tv_sec), &musec) == -1) {
+ return NULL;
+ }
+ buf[0].tv_usec = ausec;
+ buf[1].tv_usec = musec;
+ Py_BEGIN_ALLOW_THREADS
+ res = futimes(fd, buf);
+ Py_END_ALLOW_THREADS
+ }
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_LUTIMES
+PyDoc_STRVAR(posix_lutimes__doc__,
+"lutimes(path, (atime, mtime))\n\
+lutimes(path, None)\n\n\
+Like utime(), but if path is a symbolic link, it is not dereferenced.");
+
+static PyObject *
+posix_lutimes(PyObject *self, PyObject *args)
+{
+ PyObject *opath, *arg;
+ const char *path;
+ int res;
+ struct timeval buf[2];
+ long ausec, musec;
+
+ if (!PyArg_ParseTuple(args, "O&O:lutimes",
+ PyUnicode_FSConverter, &opath, &arg))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ if (arg == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = lutimes(path, NULL);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "lutimes() arg 2 must be a tuple (atime, mtime)");
+ Py_DECREF(opath);
+ return NULL;
+ }
+ else {
+ if (extract_time(PyTuple_GET_ITEM(arg, 0),
+ &(buf[0].tv_sec), &ausec) == -1) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ if (extract_time(PyTuple_GET_ITEM(arg, 1),
+ &(buf[1].tv_sec), &musec) == -1) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ buf[0].tv_usec = ausec;
+ buf[1].tv_usec = musec;
+ Py_BEGIN_ALLOW_THREADS
+ res = lutimes(path, buf);
+ Py_END_ALLOW_THREADS
+ }
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_FUTIMENS
+PyDoc_STRVAR(posix_futimens__doc__,
+"futimens(fd, (atime_sec, atime_nsec), (mtime_sec, mtime_nsec))\n\
+futimens(fd, None, None)\n\n\
+Updates the timestamps of a file specified by the file descriptor fd, with\n\
+nanosecond precision.\n\
+The second form sets atime and mtime to the current time.\n\
+If *_nsec is specified as UTIME_NOW, the timestamp is updated to the\n\
+current time.\n\
+If *_nsec is specified as UTIME_OMIT, the timestamp is not updated.");
+
+static PyObject *
+posix_futimens(PyObject *self, PyObject *args)
+{
+ int res, fd;
+ PyObject *atime, *mtime;
+ struct timespec buf[2];
+
+ if (!PyArg_ParseTuple(args, "iOO:futimens",
+ &fd, &atime, &mtime))
+ return NULL;
+ if (atime == Py_None && mtime == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = futimens(fd, NULL);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(atime) || PyTuple_Size(atime) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "futimens() arg 2 must be a tuple (atime_sec, atime_nsec)");
+ return NULL;
+ }
+ else if (!PyTuple_Check(mtime) || PyTuple_Size(mtime) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "futimens() arg 3 must be a tuple (mtime_sec, mtime_nsec)");
+ return NULL;
+ }
+ else {
+ if (!PyArg_ParseTuple(atime, "ll:futimens",
+ &(buf[0].tv_sec), &(buf[0].tv_nsec))) {
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(mtime, "ll:futimens",
+ &(buf[1].tv_sec), &(buf[1].tv_nsec))) {
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ res = futimens(fd, buf);
+ Py_END_ALLOW_THREADS
+ }
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
/* Process operations */
@@ -3389,79 +3735,7 @@ int fsconvert_strdup(PyObject *o, char**out)
}
#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");
-
-static PyObject *
-posix_execv(PyObject *self, PyObject *args)
-{
- PyObject *opath;
- char *path;
- PyObject *argv;
- char **argvlist;
- Py_ssize_t i, argc;
- PyObject *(*getitem)(PyObject *, Py_ssize_t);
-
- /* 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);
- if (PyList_Check(argv)) {
- argc = PyList_Size(argv);
- getitem = PyList_GetItem;
- }
- else if (PyTuple_Check(argv)) {
- argc = PyTuple_Size(argv);
- getitem = PyTuple_GetItem;
- }
- else {
- PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
- Py_DECREF(opath);
- return NULL;
- }
- if (argc < 1) {
- PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
- 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++) {
- if (!fsconvert_strdup((*getitem)(argv, i),
- &argvlist[i])) {
- free_string_array(argvlist, i);
- PyErr_SetString(PyExc_TypeError,
- "execv() arg 2 must contain only strings");
- Py_DECREF(opath);
- return NULL;
-
- }
- }
- argvlist[argc] = NULL;
-
- execv(path, argvlist);
-
- /* If we get here it's definitely an error */
-
- free_string_array(argvlist, argc);
- Py_DECREF(opath);
- return posix_error();
-}
-
+#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE)
static char**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
{
@@ -3543,6 +3817,87 @@ error:
return NULL;
}
+static char**
+parse_arglist(PyObject* argv, Py_ssize_t *argc)
+{
+ int i;
+ char **argvlist = PyMem_NEW(char *, *argc+1);
+ if (argvlist == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ for (i = 0; i < *argc; i++) {
+ PyObject* item = PySequence_ITEM(argv, i);
+ if (item == NULL)
+ goto fail;
+ if (!fsconvert_strdup(item, &argvlist[i])) {
+ Py_DECREF(item);
+ goto fail;
+ }
+ Py_DECREF(item);
+ }
+ argvlist[*argc] = NULL;
+ return argvlist;
+fail:
+ *argc = i;
+ free_string_array(argvlist, *argc);
+ return NULL;
+}
+#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");
+
+static PyObject *
+posix_execv(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ PyObject *argv;
+ 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);
+ 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);
+
+ /* 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\
@@ -3559,9 +3914,7 @@ posix_execve(PyObject *self, PyObject *args)
PyObject *argv, *env;
char **argvlist;
char **envlist;
- Py_ssize_t i, argc, envc;
- PyObject *(*getitem)(PyObject *, Py_ssize_t);
- Py_ssize_t lastarg = 0;
+ Py_ssize_t argc, envc;
/* execve has three arguments: (path, argv, env), where
argv is a list or tuple of strings and env is a dictionary
@@ -3572,40 +3925,22 @@ posix_execve(PyObject *self, PyObject *args)
&opath, &argv, &env))
return NULL;
path = PyBytes_AsString(opath);
- if (PyList_Check(argv)) {
- argc = PyList_Size(argv);
- getitem = PyList_GetItem;
- }
- else if (PyTuple_Check(argv)) {
- argc = PyTuple_Size(argv);
- getitem = PyTuple_GetItem;
- }
- else {
+ if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
PyErr_SetString(PyExc_TypeError,
"execve() arg 2 must be a tuple or list");
goto fail_0;
}
+ argc = PySequence_Size(argv);
if (!PyMapping_Check(env)) {
PyErr_SetString(PyExc_TypeError,
"execve() arg 3 must be a mapping object");
goto fail_0;
}
- argvlist = PyMem_NEW(char *, argc+1);
+ argvlist = parse_arglist(argv, &argc);
if (argvlist == NULL) {
- PyErr_NoMemory();
goto fail_0;
}
- for (i = 0; i < argc; i++) {
- if (!fsconvert_strdup((*getitem)(argv, i),
- &argvlist[i]))
- {
- lastarg = i;
- goto fail_1;
- }
- }
- lastarg = argc;
- argvlist[argc] = NULL;
envlist = parse_envlist(env, &envc);
if (envlist == NULL)
@@ -3621,13 +3956,69 @@ posix_execve(PyObject *self, PyObject *args)
PyMem_DEL(envlist[envc]);
PyMem_DEL(envlist);
fail_1:
- free_string_array(argvlist, lastarg);
+ free_string_array(argvlist, argc);
fail_0:
Py_DECREF(opath);
return NULL;
}
#endif /* HAVE_EXECV */
+#ifdef HAVE_FEXECVE
+PyDoc_STRVAR(posix_fexecve__doc__,
+"fexecve(fd, args, env)\n\n\
+Execute the program specified by a file descriptor with arguments and\n\
+environment, replacing the current process.\n\
+\n\
+ fd: file descriptor of executable\n\
+ args: tuple or list of arguments\n\
+ env: dictionary of strings mapping to strings");
+
+static PyObject *
+posix_fexecve(PyObject *self, PyObject *args)
+{
+ int fd;
+ PyObject *argv, *env;
+ char **argvlist;
+ char **envlist;
+ Py_ssize_t argc, envc;
+
+ if (!PyArg_ParseTuple(args, "iOO:fexecve",
+ &fd, &argv, &env))
+ return NULL;
+ if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
+ PyErr_SetString(PyExc_TypeError,
+ "fexecve() arg 2 must be a tuple or list");
+ return NULL;
+ }
+ argc = PySequence_Size(argv);
+ if (!PyMapping_Check(env)) {
+ PyErr_SetString(PyExc_TypeError,
+ "fexecve() arg 3 must be a mapping object");
+ return NULL;
+ }
+
+ argvlist = parse_arglist(argv, &argc);
+ if (argvlist == NULL)
+ return NULL;
+
+ envlist = parse_envlist(env, &envc);
+ if (envlist == NULL)
+ goto fail;
+
+ fexecve(fd, argvlist, envlist);
+
+ /* If we get here it's definitely an error */
+
+ (void) posix_error();
+
+ while (--envc >= 0)
+ PyMem_DEL(envlist[envc]);
+ PyMem_DEL(envlist);
+ fail:
+ free_string_array(argvlist, argc);
+ return NULL;
+}
+#endif /* HAVE_FEXECVE */
#ifdef HAVE_SPAWNV
PyDoc_STRVAR(posix_spawnv__doc__,
@@ -4194,6 +4585,7 @@ posix_forkpty(PyObject *self, PyObject *noargs)
}
#endif
+
#ifdef HAVE_GETEGID
PyDoc_STRVAR(posix_getegid__doc__,
"getegid() -> egid\n\n\
@@ -4262,7 +4654,7 @@ posix_getgroups(PyObject *self, PyObject *noargs)
#endif
gid_t grouplist[MAX_GROUPS];
- /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
+ /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
* This is a helper variable to store the intermediate result when
* that happens.
*
@@ -4478,15 +4870,15 @@ static PyObject *
posix_getlogin(PyObject *self, PyObject *noargs)
{
PyObject *result = NULL;
-#ifdef MS_WINDOWS
+#ifdef MS_WINDOWS
wchar_t user_name[UNLEN + 1];
DWORD num_chars = sizeof(user_name)/sizeof(user_name[0]);
if (GetUserNameW(user_name, &num_chars)) {
/* num_chars is the number of unicode chars plus null terminator */
result = PyUnicode_FromWideChar(user_name, num_chars - 1);
- }
- else
+ }
+ else
result = PyErr_SetFromWindowsErr(GetLastError());
#else
char *name;
@@ -4984,6 +5376,55 @@ posix_wait4(PyObject *self, PyObject *args)
}
#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.");
+
+static PyObject *
+posix_waitid(PyObject *self, PyObject *args)
+{
+ PyObject *result;
+ idtype_t idtype;
+ id_t id;
+ int options, res;
+ 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();
+
+ if (si.si_pid == 0)
+ Py_RETURN_NONE;
+
+ result = PyStructSequence_New(&WaitidResultType);
+ if (!result)
+ return NULL;
+
+ PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
+ PyStructSequence_SET_ITEM(result, 1, PyLong_FromPid(si.si_uid));
+ PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
+ PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
+ PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
+ if (PyErr_Occurred()) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ return result;
+}
+#endif
+
#ifdef HAVE_WAITPID
PyDoc_STRVAR(posix_waitpid__doc__,
"waitpid(pid, options) -> (pid, status)\n\n\
@@ -5170,12 +5611,12 @@ win_readlink(PyObject *self, PyObject *args)
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
0);
Py_END_ALLOW_THREADS
-
+
if (reparse_point_handle==INVALID_HANDLE_VALUE)
{
return win32_error_unicode("readlink", path);
}
-
+
Py_BEGIN_ALLOW_THREADS
/* New call DeviceIoControl to read the reparse point */
io_result = DeviceIoControl(
@@ -5246,7 +5687,7 @@ win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
int target_is_directory = 0;
DWORD res;
WIN32_FILE_ATTRIBUTE_DATA src_info;
-
+
if (!check_CreateSymbolicLinkW())
{
/* raise NotImplementedError */
@@ -5265,7 +5706,7 @@ win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
Py_DECREF(src);
return NULL;
}
-
+
/* if src is a directory, ensure target_is_directory==1 */
if(
GetFileAttributesExW(
@@ -5288,7 +5729,7 @@ win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
{
return win32_error_unicode("symlink", PyUnicode_AsUnicode(src));
}
-
+
Py_INCREF(Py_None);
return Py_None;
}
@@ -5599,6 +6040,35 @@ posix_dup2(PyObject *self, PyObject *args)
return Py_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.");
+
+static PyObject *
+posix_lockf(PyObject *self, PyObject *args)
+{
+ int fd, cmd, res;
+ off_t len;
+ if (!PyArg_ParseTuple(args, "iiO&:lockf",
+ &fd, &cmd, _parse_off_t, &len))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = lockf(fd, cmd, len);
+ Py_END_ALLOW_THREADS
+
+ if (res < 0)
+ return posix_error();
+
+ Py_RETURN_NONE;
+}
+#endif
+
PyDoc_STRVAR(posix_lseek__doc__,
"lseek(fd, pos, how) -> newpos\n\n\
@@ -5628,8 +6098,7 @@ posix_lseek(PyObject *self, PyObject *args)
#if !defined(HAVE_LARGEFILE_SUPPORT)
pos = PyLong_AsLong(posobj);
#else
- pos = PyLong_Check(posobj) ?
- PyLong_AsLongLong(posobj) : PyLong_AsLong(posobj);
+ pos = PyLong_AsLongLong(posobj);
#endif
if (PyErr_Occurred())
return NULL;
@@ -5689,6 +6158,140 @@ posix_read(PyObject *self, PyObject *args)
return buffer;
}
+#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
+ || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
+static Py_ssize_t
+iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
+{
+ int i, j;
+ Py_ssize_t blen, total = 0;
+
+ *iov = PyMem_New(struct iovec, cnt);
+ if (*iov == NULL) {
+ PyErr_NoMemory();
+ return total;
+ }
+
+ *buf = PyMem_New(Py_buffer, cnt);
+ if (*buf == NULL) {
+ PyMem_Del(*iov);
+ PyErr_NoMemory();
+ return total;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (item == NULL)
+ goto fail;
+ if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
+ Py_DECREF(item);
+ goto fail;
+ }
+ Py_DECREF(item);
+ (*iov)[i].iov_base = (*buf)[i].buf;
+ blen = (*buf)[i].len;
+ (*iov)[i].iov_len = blen;
+ total += blen;
+ }
+ return total;
+
+fail:
+ PyMem_Del(*iov);
+ for (j = 0; j < i; j++) {
+ PyBuffer_Release(&(*buf)[j]);
+ }
+ PyMem_Del(*buf);
+ return 0;
+}
+
+static void
+iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
+{
+ int i;
+ PyMem_Del(iov);
+ for (i = 0; i < cnt; i++) {
+ PyBuffer_Release(&buf[i]);
+ }
+ PyMem_Del(buf);
+}
+#endif
+
+#ifdef HAVE_READV
+PyDoc_STRVAR(posix_readv__doc__,
+"readv(fd, buffers) -> bytesread\n\n\
+Read from a file descriptor into a number of writable buffers. buffers\n\
+is an arbitrary sequence of writable buffers.\n\
+Returns the total number of bytes read.");
+
+static PyObject *
+posix_readv(PyObject *self, PyObject *args)
+{
+ int fd, cnt;
+ Py_ssize_t n;
+ PyObject *seq;
+ struct iovec *iov;
+ Py_buffer *buf;
+
+ if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq))
+ return NULL;
+ if (!PySequence_Check(seq)) {
+ PyErr_SetString(PyExc_TypeError,
+ "readv() arg 2 must be a sequence");
+ return NULL;
+ }
+ cnt = PySequence_Size(seq);
+
+ if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ n = readv(fd, iov, cnt);
+ Py_END_ALLOW_THREADS
+
+ iov_cleanup(iov, buf, cnt);
+ return PyLong_FromSsize_t(n);
+}
+#endif
+
+#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.");
+
+static PyObject *
+posix_pread(PyObject *self, PyObject *args)
+{
+ int fd, size;
+ off_t offset;
+ Py_ssize_t n;
+ PyObject *buffer;
+ if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset))
+ return NULL;
+
+ if (size < 0) {
+ errno = EINVAL;
+ return posix_error();
+ }
+ buffer = PyBytes_FromStringAndSize((char *)NULL, size);
+ 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
+ if (n < 0) {
+ Py_DECREF(buffer);
+ return posix_error();
+ }
+ if (n != size)
+ _PyBytes_Resize(&buffer, n);
+ return buffer;
+}
+#endif
PyDoc_STRVAR(posix_write__doc__,
"write(fd, string) -> byteswritten\n\n\
@@ -5723,6 +6326,145 @@ posix_write(PyObject *self, PyObject *args)
return PyLong_FromSsize_t(size);
}
+#ifdef HAVE_SENDFILE
+PyDoc_STRVAR(posix_sendfile__doc__,
+"sendfile(out, in, offset, nbytes) -> byteswritten\n\
+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.");
+
+static PyObject *
+posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ int in, out;
+ Py_ssize_t ret;
+ off_t offset;
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#ifndef __APPLE__
+ Py_ssize_t len;
+#endif
+ PyObject *headers = NULL, *trailers = NULL;
+ Py_buffer *hbuf, *tbuf;
+ off_t sbytes;
+ struct sf_hdtr sf;
+ int flags = 0;
+ sf.headers = NULL;
+ sf.trailers = NULL;
+ static char *keywords[] = {"out", "in",
+ "offset", "count",
+ "headers", "trailers", "flags", NULL};
+
+#ifdef __APPLE__
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
+ keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes,
+#else
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
+ keywords, &out, &in, _parse_off_t, &offset, &len,
+#endif
+ &headers, &trailers, &flags))
+ return NULL;
+ if (headers != NULL) {
+ if (!PySequence_Check(headers)) {
+ PyErr_SetString(PyExc_TypeError,
+ "sendfile() headers must be a sequence or None");
+ return NULL;
+ } else {
+ Py_ssize_t i = 0; /* Avoid uninitialized warning */
+ sf.hdr_cnt = PySequence_Size(headers);
+ if (sf.hdr_cnt > 0 &&
+ !(i = iov_setup(&(sf.headers), &hbuf,
+ headers, sf.hdr_cnt, PyBUF_SIMPLE)))
+ return NULL;
+#ifdef __APPLE__
+ sbytes += i;
+#endif
+ }
+ }
+ if (trailers != NULL) {
+ if (!PySequence_Check(trailers)) {
+ PyErr_SetString(PyExc_TypeError,
+ "sendfile() trailers must be a sequence or None");
+ return NULL;
+ } else {
+ Py_ssize_t i = 0; /* Avoid uninitialized warning */
+ sf.trl_cnt = PySequence_Size(trailers);
+ if (sf.trl_cnt > 0 &&
+ !(i = iov_setup(&(sf.trailers), &tbuf,
+ trailers, sf.trl_cnt, PyBUF_SIMPLE)))
+ return NULL;
+#ifdef __APPLE__
+ sbytes += i;
+#endif
+ }
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+#ifdef __APPLE__
+ ret = sendfile(in, out, offset, &sbytes, &sf, flags);
+#else
+ ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
+#endif
+ Py_END_ALLOW_THREADS
+
+ if (sf.headers != NULL)
+ iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
+ if (sf.trailers != NULL)
+ iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
+
+ if (ret < 0) {
+ if ((errno == EAGAIN) || (errno == EBUSY)) {
+ if (sbytes != 0) {
+ // some data has been sent
+ goto done;
+ }
+ else {
+ // no data has been sent; upper application is supposed
+ // to retry on EAGAIN or EBUSY
+ return posix_error();
+ }
+ }
+ return posix_error();
+ }
+ goto done;
+
+done:
+ #if !defined(HAVE_LARGEFILE_SUPPORT)
+ return Py_BuildValue("l", sbytes);
+ #else
+ return Py_BuildValue("L", sbytes);
+ #endif
+
+#else
+ Py_ssize_t count;
+ PyObject *offobj;
+ static char *keywords[] = {"out", "in",
+ "offset", "count", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
+ keywords, &out, &in, &offobj, &count))
+ return NULL;
+#ifdef linux
+ if (offobj == Py_None) {
+ Py_BEGIN_ALLOW_THREADS
+ ret = sendfile(out, in, NULL, count);
+ Py_END_ALLOW_THREADS
+ if (ret < 0)
+ return posix_error();
+ Py_INCREF(Py_None);
+ return Py_BuildValue("nO", ret, Py_None);
+ }
+#endif
+ if (!_parse_off_t(offobj, &offset))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ ret = sendfile(out, in, &offset, count);
+ Py_END_ALLOW_THREADS
+ if (ret < 0)
+ return posix_error();
+ return Py_BuildValue("n", ret);
+#endif
+}
+#endif
PyDoc_STRVAR(posix_fstat__doc__,
"fstat(fd) -> stat result\n\n\
@@ -5818,6 +6560,73 @@ posix_pipe(PyObject *self, PyObject *noargs)
}
#endif /* HAVE_PIPE */
+#ifdef HAVE_WRITEV
+PyDoc_STRVAR(posix_writev__doc__,
+"writev(fd, buffers) -> byteswritten\n\n\
+Write the contents of buffers to a file descriptor, where buffers is an\n\
+arbitrary sequence of buffers.\n\
+Returns the total bytes written.");
+
+static PyObject *
+posix_writev(PyObject *self, PyObject *args)
+{
+ int fd, cnt;
+ Py_ssize_t res;
+ PyObject *seq;
+ struct iovec *iov;
+ Py_buffer *buf;
+ if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq))
+ return NULL;
+ if (!PySequence_Check(seq)) {
+ PyErr_SetString(PyExc_TypeError,
+ "writev() arg 2 must be a sequence");
+ return NULL;
+ }
+ cnt = PySequence_Size(seq);
+
+ if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) {
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ res = writev(fd, iov, cnt);
+ Py_END_ALLOW_THREADS
+
+ iov_cleanup(iov, buf, cnt);
+ return PyLong_FromSsize_t(res);
+}
+#endif
+
+#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.");
+
+static PyObject *
+posix_pwrite(PyObject *self, PyObject *args)
+{
+ 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;
+
+ if (!_PyVerify_fd(fd)) {
+ PyBuffer_Release(&pbuf);
+ return posix_error();
+ }
+ 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);
+}
+#endif
#ifdef HAVE_MKFIFO
PyDoc_STRVAR(posix_mkfifo__doc__,
@@ -5934,18 +6743,8 @@ posix_ftruncate(PyObject *self, PyObject *args)
int fd;
off_t length;
int res;
- PyObject *lenobj;
-
- if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
- return NULL;
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- length = PyLong_AsLong(lenobj);
-#else
- length = PyLong_Check(lenobj) ?
- PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj);
-#endif
- if (PyErr_Occurred())
+ if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length))
return NULL;
Py_BEGIN_ALLOW_THREADS
@@ -5958,6 +6757,93 @@ posix_ftruncate(PyObject *self, PyObject *args)
}
#endif
+#ifdef HAVE_TRUNCATE
+PyDoc_STRVAR(posix_truncate__doc__,
+"truncate(path, length)\n\n\
+Truncate the file given by path to length bytes.");
+
+static PyObject *
+posix_truncate(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ const char *path;
+ off_t length;
+ int res;
+
+ if (!PyArg_ParseTuple(args, "O&O&:truncate",
+ PyUnicode_FSConverter, &opath, _parse_off_t, &length))
+ return NULL;
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = truncate(path, length);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_POSIX_FALLOCATE
+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.");
+
+static PyObject *
+posix_posix_fallocate(PyObject *self, PyObject *args)
+{
+ 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;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = posix_fallocate(fd, offset, len);
+ Py_END_ALLOW_THREADS
+ if (res != 0) {
+ errno = res;
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_POSIX_FADVISE
+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.");
+
+static PyObject *
+posix_posix_fadvise(PyObject *self, PyObject *args)
+{
+ 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;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = posix_fadvise(fd, offset, len, advice);
+ Py_END_ALLOW_THREADS
+ if (res != 0) {
+ errno = res;
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
#ifdef HAVE_PUTENV
PyDoc_STRVAR(posix_putenv__doc__,
"putenv(key, value)\n\n\
@@ -7762,6 +8648,552 @@ posix_getresgid (PyObject *self, PyObject *noargs)
}
#endif
+/* Posix *at family of functions:
+ faccessat, fchmodat, fchownat, fstatat, futimesat,
+ linkat, mkdirat, mknodat, openat, readlinkat, renameat, symlinkat,
+ unlinkat, utimensat, mkfifoat */
+
+#ifdef HAVE_FACCESSAT
+PyDoc_STRVAR(posix_faccessat__doc__,
+"faccessat(dirfd, path, mode, flags=0) -> True if granted, False otherwise\n\n\
+Like access() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and can be constructed by ORing together zero or more\n\
+of these values: AT_SYMLINK_NOFOLLOW, AT_EACCESS.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_faccessat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ int mode;
+ int res;
+ int dirfd, flags = 0;
+ if (!PyArg_ParseTuple(args, "iO&i|i:faccessat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = faccessat(dirfd, path, mode, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ return PyBool_FromLong(res == 0);
+}
+#endif
+
+#ifdef HAVE_FCHMODAT
+PyDoc_STRVAR(posix_fchmodat__doc__,
+"fchmodat(dirfd, path, mode, flags=0)\n\n\
+Like chmod() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_fchmodat(PyObject *self, PyObject *args)
+{
+ int dirfd, mode, res;
+ int flags = 0;
+ PyObject *opath;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "iO&i|i:fchmodat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode, &flags))
+ return NULL;
+
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fchmodat(dirfd, path, mode, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_FCHMODAT */
+
+#ifdef HAVE_FCHOWNAT
+PyDoc_STRVAR(posix_fchownat__doc__,
+"fchownat(dirfd, path, uid, gid, flags=0)\n\n\
+Like chown() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_fchownat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ int dirfd, res;
+ long uid, gid;
+ int flags = 0;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "iO&ll|i:fchownat",
+ &dirfd, PyUnicode_FSConverter, &opath, &uid, &gid, &flags))
+ return NULL;
+
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fchownat(dirfd, path, (uid_t) uid, (gid_t) gid, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_FCHOWNAT */
+
+#ifdef HAVE_FSTATAT
+PyDoc_STRVAR(posix_fstatat__doc__,
+"fstatat(dirfd, path, flags=0) -> stat result\n\n\
+Like stat() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_fstatat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ STRUCT_STAT st;
+ int dirfd, res, flags = 0;
+
+ if (!PyArg_ParseTuple(args, "iO&|i:fstatat",
+ &dirfd, PyUnicode_FSConverter, &opath, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fstatat(dirfd, path, &st, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res != 0)
+ return posix_error();
+
+ return _pystat_fromstructstat(&st);
+}
+#endif
+
+#ifdef HAVE_FUTIMESAT
+PyDoc_STRVAR(posix_futimesat__doc__,
+"futimesat(dirfd, path, (atime, mtime))\n\
+futimesat(dirfd, path, None)\n\n\
+Like utime() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_futimesat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ int res, dirfd;
+ PyObject* arg;
+
+ struct timeval buf[2];
+
+ if (!PyArg_ParseTuple(args, "iO&O:futimesat",
+ &dirfd, PyUnicode_FSConverter, &opath, &arg))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ if (arg == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = futimesat(dirfd, path, NULL);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "futimesat() arg 3 must be a tuple (atime, mtime)");
+ Py_DECREF(opath);
+ return NULL;
+ }
+ else {
+ if (extract_time(PyTuple_GET_ITEM(arg, 0),
+ &(buf[0].tv_sec), &(buf[0].tv_usec)) == -1) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ if (extract_time(PyTuple_GET_ITEM(arg, 1),
+ &(buf[1].tv_sec), &(buf[1].tv_usec)) == -1) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ res = futimesat(dirfd, path, buf);
+ Py_END_ALLOW_THREADS
+ }
+ Py_DECREF(opath);
+ if (res < 0) {
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_LINKAT
+PyDoc_STRVAR(posix_linkat__doc__,
+"linkat(srcfd, srcpath, dstfd, dstpath, flags=0)\n\n\
+Like link() but if srcpath is relative, it is taken as relative to srcfd\n\
+and if dstpath is relative, it is taken as relative to dstfd.\n\
+flags is optional and may be 0 or AT_SYMLINK_FOLLOW.\n\
+If srcpath is relative and srcfd is the special value AT_FDCWD, then\n\
+srcpath is interpreted relative to the current working directory. This\n\
+also applies for dstpath.");
+
+static PyObject *
+posix_linkat(PyObject *self, PyObject *args)
+{
+ PyObject *osrc, *odst;
+ char *src, *dst;
+ int res, srcfd, dstfd;
+ int flags = 0;
+
+ if (!PyArg_ParseTuple(args, "iO&iO&|i:linkat",
+ &srcfd, PyUnicode_FSConverter, &osrc, &dstfd, PyUnicode_FSConverter, &odst, &flags))
+ return NULL;
+ src = PyBytes_AsString(osrc);
+ dst = PyBytes_AsString(odst);
+ Py_BEGIN_ALLOW_THREADS
+ res = linkat(srcfd, src, dstfd, dst, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(osrc);
+ Py_DECREF(odst);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_LINKAT */
+
+#ifdef HAVE_MKDIRAT
+PyDoc_STRVAR(posix_mkdirat__doc__,
+"mkdirat(dirfd, path, mode=0o777)\n\n\
+Like mkdir() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_mkdirat(PyObject *self, PyObject *args)
+{
+ int res, dirfd;
+ PyObject *opath;
+ char *path;
+ int mode = 0777;
+
+ if (!PyArg_ParseTuple(args, "iO&|i:mkdirat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = mkdirat(dirfd, path, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#if defined(HAVE_MKNODAT) && defined(HAVE_MAKEDEV)
+PyDoc_STRVAR(posix_mknodat__doc__,
+"mknodat(dirfd, path, mode=0o600, device=0)\n\n\
+Like mknod() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_mknodat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *filename;
+ int mode = 0600;
+ int device = 0;
+ int res, dirfd;
+ if (!PyArg_ParseTuple(args, "iO&|ii:mknodat", &dirfd,
+ PyUnicode_FSConverter, &opath, &mode, &device))
+ return NULL;
+ filename = PyBytes_AS_STRING(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = mknodat(dirfd, filename, mode, device);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_OPENAT
+PyDoc_STRVAR(posix_openat__doc__,
+"openat(dirfd, path, flag, mode=0o777) -> fd\n\n\
+Like open() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_openat(PyObject *self, PyObject *args)
+{
+ PyObject *ofile;
+ char *file;
+ int flag, dirfd, fd;
+ int mode = 0777;
+
+ if (!PyArg_ParseTuple(args, "iO&i|i:openat",
+ &dirfd, PyUnicode_FSConverter, &ofile,
+ &flag, &mode))
+ return NULL;
+ file = PyBytes_AsString(ofile);
+ Py_BEGIN_ALLOW_THREADS
+ fd = openat(dirfd, file, flag, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(ofile);
+ if (fd < 0)
+ return posix_error();
+ return PyLong_FromLong((long)fd);
+}
+#endif
+
+#ifdef HAVE_READLINKAT
+PyDoc_STRVAR(posix_readlinkat__doc__,
+"readlinkat(dirfd, path) -> path\n\n\
+Like readlink() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_readlinkat(PyObject *self, PyObject *args)
+{
+ PyObject *v, *opath;
+ char buf[MAXPATHLEN];
+ char *path;
+ int n, dirfd;
+ int arg_is_unicode = 0;
+
+ if (!PyArg_ParseTuple(args, "iO&:readlinkat",
+ &dirfd, PyUnicode_FSConverter, &opath))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ v = PySequence_GetItem(args, 1);
+ if (v == NULL) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+
+ if (PyUnicode_Check(v)) {
+ arg_is_unicode = 1;
+ }
+ Py_DECREF(v);
+
+ Py_BEGIN_ALLOW_THREADS
+ n = readlinkat(dirfd, path, buf, (int) sizeof buf);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (n < 0)
+ return posix_error();
+
+ if (arg_is_unicode)
+ return PyUnicode_DecodeFSDefaultAndSize(buf, n);
+ else
+ return PyBytes_FromStringAndSize(buf, n);
+}
+#endif /* HAVE_READLINKAT */
+
+#ifdef HAVE_RENAMEAT
+PyDoc_STRVAR(posix_renameat__doc__,
+"renameat(olddirfd, oldpath, newdirfd, newpath)\n\n\
+Like rename() but if oldpath is relative, it is taken as relative to\n\
+olddirfd and if newpath is relative, it is taken as relative to newdirfd.\n\
+If oldpath is relative and olddirfd is the special value AT_FDCWD, then\n\
+oldpath is interpreted relative to the current working directory. This\n\
+also applies for newpath.");
+
+static PyObject *
+posix_renameat(PyObject *self, PyObject *args)
+{
+ int res;
+ PyObject *opathold, *opathnew;
+ char *opath, *npath;
+ int oldfd, newfd;
+
+ if (!PyArg_ParseTuple(args, "iO&iO&:renameat",
+ &oldfd, PyUnicode_FSConverter, &opathold, &newfd, PyUnicode_FSConverter, &opathnew))
+ return NULL;
+ opath = PyBytes_AsString(opathold);
+ npath = PyBytes_AsString(opathnew);
+ Py_BEGIN_ALLOW_THREADS
+ res = renameat(oldfd, opath, newfd, npath);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opathold);
+ Py_DECREF(opathnew);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#if HAVE_SYMLINKAT
+PyDoc_STRVAR(posix_symlinkat__doc__,
+"symlinkat(src, dstfd, dst)\n\n\
+Like symlink() but if dst is relative, it is taken as relative to dstfd.\n\
+If dst is relative and dstfd is the special value AT_FDCWD, then dst\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_symlinkat(PyObject *self, PyObject *args)
+{
+ int res, dstfd;
+ PyObject *osrc, *odst;
+ char *src, *dst;
+
+ if (!PyArg_ParseTuple(args, "O&iO&:symlinkat",
+ PyUnicode_FSConverter, &osrc, &dstfd, PyUnicode_FSConverter, &odst))
+ return NULL;
+ src = PyBytes_AsString(osrc);
+ dst = PyBytes_AsString(odst);
+ Py_BEGIN_ALLOW_THREADS
+ res = symlinkat(src, dstfd, dst);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(osrc);
+ Py_DECREF(odst);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SYMLINKAT */
+
+#ifdef HAVE_UNLINKAT
+PyDoc_STRVAR(posix_unlinkat__doc__,
+"unlinkat(dirfd, path, flags=0)\n\n\
+Like unlink() but if path is relative, it is taken as relative to dirfd.\n\
+flags is optional and may be 0 or AT_REMOVEDIR. If AT_REMOVEDIR is\n\
+specified, unlinkat() behaves like rmdir().\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_unlinkat(PyObject *self, PyObject *args)
+{
+ int dirfd, res, flags = 0;
+ PyObject *opath;
+ char *path;
+
+ if (!PyArg_ParseTuple(args, "iO&|i:unlinkat",
+ &dirfd, PyUnicode_FSConverter, &opath, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = unlinkat(dirfd, path, flags);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_UTIMENSAT
+PyDoc_STRVAR(posix_utimensat__doc__,
+"utimensat(dirfd, path, (atime_sec, atime_nsec),\n\
+ (mtime_sec, mtime_nsec), flags)\n\
+utimensat(dirfd, path, None, None, flags)\n\n\
+Updates the timestamps of a file with nanosecond precision. If path is\n\
+relative, it is taken as relative to dirfd.\n\
+The second form sets atime and mtime to the current time.\n\
+flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.\n\
+If *_nsec is specified as UTIME_NOW, the timestamp is updated to the\n\
+current time.\n\
+If *_nsec is specified as UTIME_OMIT, the timestamp is not updated.");
+
+static PyObject *
+posix_utimensat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *path;
+ int res, dirfd, flags = 0;
+ PyObject *atime, *mtime;
+
+ struct timespec buf[2];
+
+ if (!PyArg_ParseTuple(args, "iO&OO|i:utimensat",
+ &dirfd, PyUnicode_FSConverter, &opath, &atime, &mtime, &flags))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ if (atime == Py_None && mtime == Py_None) {
+ /* optional time values not given */
+ Py_BEGIN_ALLOW_THREADS
+ res = utimensat(dirfd, path, NULL, flags);
+ Py_END_ALLOW_THREADS
+ }
+ else if (!PyTuple_Check(atime) || PyTuple_Size(atime) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "utimensat() arg 3 must be a tuple (atime_sec, atime_nsec)");
+ Py_DECREF(opath);
+ return NULL;
+ }
+ else if (!PyTuple_Check(mtime) || PyTuple_Size(mtime) != 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "utimensat() arg 4 must be a tuple (mtime_sec, mtime_nsec)");
+ Py_DECREF(opath);
+ return NULL;
+ }
+ else {
+ if (!PyArg_ParseTuple(atime, "ll:utimensat",
+ &(buf[0].tv_sec), &(buf[0].tv_nsec))) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(mtime, "ll:utimensat",
+ &(buf[1].tv_sec), &(buf[1].tv_nsec))) {
+ Py_DECREF(opath);
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ res = utimensat(dirfd, path, buf, flags);
+ Py_END_ALLOW_THREADS
+ }
+ Py_DECREF(opath);
+ if (res < 0) {
+ return posix_error();
+ }
+ Py_RETURN_NONE;
+}
+#endif
+
+#ifdef HAVE_MKFIFOAT
+PyDoc_STRVAR(posix_mkfifoat__doc__,
+"mkfifoat(dirfd, path, mode=0o666)\n\n\
+Like mkfifo() but if path is relative, it is taken as relative to dirfd.\n\
+If path is relative and dirfd is the special value AT_FDCWD, then path\n\
+is interpreted relative to the current working directory.");
+
+static PyObject *
+posix_mkfifoat(PyObject *self, PyObject *args)
+{
+ PyObject *opath;
+ char *filename;
+ int mode = 0666;
+ int res, dirfd;
+ if (!PyArg_ParseTuple(args, "iO&|i:mkfifoat",
+ &dirfd, PyUnicode_FSConverter, &opath, &mode))
+ return NULL;
+ filename = PyBytes_AS_STRING(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = mkfifoat(dirfd, filename, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif
+
static PyMethodDef posix_methods[] = {
{"access", posix_access, METH_VARARGS, posix_access__doc__},
#ifdef HAVE_TTYNAME
@@ -7806,11 +9238,20 @@ static PyMethodDef posix_methods[] = {
{"link", posix_link, METH_VARARGS, posix_link__doc__},
#endif /* HAVE_LINK */
{"listdir", posix_listdir, METH_VARARGS, posix_listdir__doc__},
+#ifdef HAVE_FDOPENDIR
+ {"fdlistdir", posix_fdlistdir, METH_VARARGS, posix_fdlistdir__doc__},
+#endif
{"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__},
{"mkdir", posix_mkdir, METH_VARARGS, 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 */
#ifdef HAVE_READLINK
{"readlink", posix_readlink, METH_VARARGS, posix_readlink__doc__},
#endif /* HAVE_READLINK */
@@ -7838,6 +9279,15 @@ static PyMethodDef posix_methods[] = {
{"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__},
{"remove", posix_unlink, METH_VARARGS, posix_remove__doc__},
{"utime", posix_utime, METH_VARARGS, posix_utime__doc__},
+#ifdef HAVE_FUTIMES
+ {"futimes", posix_futimes, METH_VARARGS, posix_futimes__doc__},
+#endif
+#ifdef HAVE_LUTIMES
+ {"lutimes", posix_lutimes, METH_VARARGS, posix_lutimes__doc__},
+#endif
+#ifdef HAVE_FUTIMENS
+ {"futimens", posix_futimens, METH_VARARGS, posix_futimens__doc__},
+#endif
#ifdef HAVE_TIMES
{"times", posix_times, METH_NOARGS, posix_times__doc__},
#endif /* HAVE_TIMES */
@@ -7846,6 +9296,9 @@ static PyMethodDef posix_methods[] = {
{"execv", posix_execv, METH_VARARGS, posix_execv__doc__},
{"execve", posix_execve, METH_VARARGS, posix_execve__doc__},
#endif /* HAVE_EXECV */
+#ifdef HAVE_FEXECVE
+ {"fexecve", posix_fexecve, METH_VARARGS, posix_fexecve__doc__},
+#endif
#ifdef HAVE_SPAWNV
{"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
{"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
@@ -7944,6 +9397,9 @@ static PyMethodDef posix_methods[] = {
#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 */
@@ -7968,9 +9424,28 @@ static PyMethodDef posix_methods[] = {
{"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
{"dup", posix_dup, METH_VARARGS, posix_dup__doc__},
{"dup2", posix_dup2, METH_VARARGS, 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
+#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
@@ -7990,6 +9465,15 @@ static PyMethodDef posix_methods[] = {
#ifdef HAVE_FTRUNCATE
{"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
#endif
+#ifdef HAVE_TRUNCATE
+ {"truncate", posix_truncate, METH_VARARGS, posix_truncate__doc__},
+#endif
+#ifdef HAVE_POSIX_FALLOCATE
+ {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__},
+#endif
+#ifdef HAVE_POSIX_FADVISE
+ {"posix_fadvise", posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__},
+#endif
#ifdef HAVE_PUTENV
{"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__},
#endif
@@ -8003,6 +9487,9 @@ static PyMethodDef posix_methods[] = {
#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
@@ -8078,6 +9565,52 @@ static PyMethodDef posix_methods[] = {
{"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
#endif
+/* posix *at family of functions */
+#ifdef HAVE_FACCESSAT
+ {"faccessat", posix_faccessat, METH_VARARGS, posix_faccessat__doc__},
+#endif
+#ifdef HAVE_FCHMODAT
+ {"fchmodat", posix_fchmodat, METH_VARARGS, posix_fchmodat__doc__},
+#endif /* HAVE_FCHMODAT */
+#ifdef HAVE_FCHOWNAT
+ {"fchownat", posix_fchownat, METH_VARARGS, posix_fchownat__doc__},
+#endif /* HAVE_FCHOWNAT */
+#ifdef HAVE_FSTATAT
+ {"fstatat", posix_fstatat, METH_VARARGS, posix_fstatat__doc__},
+#endif
+#ifdef HAVE_FUTIMESAT
+ {"futimesat", posix_futimesat, METH_VARARGS, posix_futimesat__doc__},
+#endif
+#ifdef HAVE_LINKAT
+ {"linkat", posix_linkat, METH_VARARGS, posix_linkat__doc__},
+#endif /* HAVE_LINKAT */
+#ifdef HAVE_MKDIRAT
+ {"mkdirat", posix_mkdirat, METH_VARARGS, posix_mkdirat__doc__},
+#endif
+#if defined(HAVE_MKNODAT) && defined(HAVE_MAKEDEV)
+ {"mknodat", posix_mknodat, METH_VARARGS, posix_mknodat__doc__},
+#endif
+#ifdef HAVE_OPENAT
+ {"openat", posix_openat, METH_VARARGS, posix_openat__doc__},
+#endif
+#ifdef HAVE_READLINKAT
+ {"readlinkat", posix_readlinkat, METH_VARARGS, posix_readlinkat__doc__},
+#endif /* HAVE_READLINKAT */
+#ifdef HAVE_RENAMEAT
+ {"renameat", posix_renameat, METH_VARARGS, posix_renameat__doc__},
+#endif
+#if HAVE_SYMLINKAT
+ {"symlinkat", posix_symlinkat, METH_VARARGS, posix_symlinkat__doc__},
+#endif /* HAVE_SYMLINKAT */
+#ifdef HAVE_UNLINKAT
+ {"unlinkat", posix_unlinkat, METH_VARARGS, posix_unlinkat__doc__},
+#endif
+#ifdef HAVE_UTIMENSAT
+ {"utimensat", posix_utimensat, METH_VARARGS, posix_utimensat__doc__},
+#endif
+#ifdef HAVE_MKFIFOAT
+ {"mkfifoat", posix_mkfifoat, METH_VARARGS, posix_mkfifoat__doc__},
+#endif
{NULL, NULL} /* Sentinel */
};
@@ -8254,6 +9787,38 @@ all_ins(PyObject *d)
#ifdef O_EXLOCK
if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
#endif
+#ifdef PRIO_PROCESS
+ if (ins(d, "PRIO_PROCESS", (long)PRIO_PROCESS)) return -1;
+#endif
+#ifdef PRIO_PGRP
+ if (ins(d, "PRIO_PGRP", (long)PRIO_PGRP)) return -1;
+#endif
+#ifdef PRIO_USER
+ if (ins(d, "PRIO_USER", (long)PRIO_USER)) return -1;
+#endif
+/* posix - constants for *at functions */
+#ifdef AT_SYMLINK_NOFOLLOW
+ if (ins(d, "AT_SYMLINK_NOFOLLOW", (long)AT_SYMLINK_NOFOLLOW)) return -1;
+#endif
+#ifdef AT_EACCESS
+ if (ins(d, "AT_EACCESS", (long)AT_EACCESS)) return -1;
+#endif
+#ifdef AT_FDCWD
+ if (ins(d, "AT_FDCWD", (long)AT_FDCWD)) return -1;
+#endif
+#ifdef AT_REMOVEDIR
+ if (ins(d, "AT_REMOVEDIR", (long)AT_REMOVEDIR)) return -1;
+#endif
+#ifdef AT_SYMLINK_FOLLOW
+ if (ins(d, "AT_SYMLINK_FOLLOW", (long)AT_SYMLINK_FOLLOW)) return -1;
+#endif
+#ifdef UTIME_NOW
+ if (ins(d, "UTIME_NOW", (long)UTIME_NOW)) return -1;
+#endif
+#ifdef UTIME_OMIT
+ if (ins(d, "UTIME_OMIT", (long)UTIME_OMIT)) return -1;
+#endif
+
/* MS Windows */
#ifdef O_NOINHERIT
@@ -8362,6 +9927,87 @@ all_ins(PyObject *d)
if (ins(d, "ST_NOSUID", (long)ST_NOSUID)) return -1;
#endif /* ST_NOSUID */
+ /* FreeBSD sendfile() constants */
+#ifdef SF_NODISKIO
+ if (ins(d, "SF_NODISKIO", (long)SF_NODISKIO)) return -1;
+#endif
+#ifdef SF_MNOWAIT
+ if (ins(d, "SF_MNOWAIT", (long)SF_MNOWAIT)) return -1;
+#endif
+#ifdef SF_SYNC
+ if (ins(d, "SF_SYNC", (long)SF_SYNC)) return -1;
+#endif
+
+ /* constants for posix_fadvise */
+#ifdef POSIX_FADV_NORMAL
+ if (ins(d, "POSIX_FADV_NORMAL", (long)POSIX_FADV_NORMAL)) return -1;
+#endif
+#ifdef POSIX_FADV_SEQUENTIAL
+ if (ins(d, "POSIX_FADV_SEQUENTIAL", (long)POSIX_FADV_SEQUENTIAL)) return -1;
+#endif
+#ifdef POSIX_FADV_RANDOM
+ if (ins(d, "POSIX_FADV_RANDOM", (long)POSIX_FADV_RANDOM)) return -1;
+#endif
+#ifdef POSIX_FADV_NOREUSE
+ if (ins(d, "POSIX_FADV_NOREUSE", (long)POSIX_FADV_NOREUSE)) return -1;
+#endif
+#ifdef POSIX_FADV_WILLNEED
+ if (ins(d, "POSIX_FADV_WILLNEED", (long)POSIX_FADV_WILLNEED)) return -1;
+#endif
+#ifdef POSIX_FADV_DONTNEED
+ if (ins(d, "POSIX_FADV_DONTNEED", (long)POSIX_FADV_DONTNEED)) return -1;
+#endif
+
+ /* constants for waitid */
+#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
+ if (ins(d, "P_PID", (long)P_PID)) return -1;
+ if (ins(d, "P_PGID", (long)P_PGID)) return -1;
+ if (ins(d, "P_ALL", (long)P_ALL)) return -1;
+#endif
+#ifdef WEXITED
+ if (ins(d, "WEXITED", (long)WEXITED)) return -1;
+#endif
+#ifdef WNOWAIT
+ if (ins(d, "WNOWAIT", (long)WNOWAIT)) return -1;
+#endif
+#ifdef WSTOPPED
+ if (ins(d, "WSTOPPED", (long)WSTOPPED)) return -1;
+#endif
+#ifdef CLD_EXITED
+ if (ins(d, "CLD_EXITED", (long)CLD_EXITED)) return -1;
+#endif
+#ifdef CLD_DUMPED
+ if (ins(d, "CLD_DUMPED", (long)CLD_DUMPED)) return -1;
+#endif
+#ifdef CLD_TRAPPED
+ if (ins(d, "CLD_TRAPPED", (long)CLD_TRAPPED)) return -1;
+#endif
+#ifdef CLD_CONTINUED
+ if (ins(d, "CLD_CONTINUED", (long)CLD_CONTINUED)) return -1;
+#endif
+
+ /* constants for lockf */
+#ifdef F_LOCK
+ if (ins(d, "F_LOCK", (long)F_LOCK)) return -1;
+#endif
+#ifdef F_TLOCK
+ if (ins(d, "F_TLOCK", (long)F_TLOCK)) return -1;
+#endif
+#ifdef F_ULOCK
+ if (ins(d, "F_ULOCK", (long)F_ULOCK)) return -1;
+#endif
+#ifdef F_TEST
+ if (ins(d, "F_TEST", (long)F_TEST)) return -1;
+#endif
+
+ /* constants for futimens */
+#ifdef UTIME_NOW
+ if (ins(d, "UTIME_NOW", (long)UTIME_NOW)) return -1;
+#endif
+#ifdef UTIME_OMIT
+ if (ins(d, "UTIME_OMIT", (long)UTIME_OMIT)) return -1;
+#endif
+
#ifdef HAVE_SPAWNV
#if defined(PYOS_OS2) && defined(PYCC_GCC)
if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
@@ -8461,6 +10107,11 @@ INITFUNC(void)
#endif
if (!initialized) {
+#if defined(HAVE_WAITID) && !defined(__APPLE__)
+ waitid_result_desc.name = MODNAME ".waitid_result";
+ PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc);
+#endif
+
stat_result_desc.name = MODNAME ".stat_result";
stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
@@ -8481,6 +10132,10 @@ INITFUNC(void)
# endif
#endif
}
+#if defined(HAVE_WAITID) && !defined(__APPLE__)
+ Py_INCREF((PyObject*) &WaitidResultType);
+ PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType);
+#endif
Py_INCREF((PyObject*) &StatResultType);
PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
Py_INCREF((PyObject*) &StatVFSResultType);