mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
bpo-31368: Expose preadv and pwritev in the os module (#5239)
This commit is contained in:
parent
60da99b8e2
commit
4defba3b95
9 changed files with 470 additions and 79 deletions
|
|
@ -3705,6 +3705,61 @@ exit:
|
|||
|
||||
#endif /* defined(HAVE_PREAD) */
|
||||
|
||||
#if (defined(HAVE_PREADV) || defined (HAVE_PREADV2))
|
||||
|
||||
PyDoc_STRVAR(os_preadv__doc__,
|
||||
"preadv($module, fd, buffers, offset, flags=0, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Reads from a file descriptor into a number of mutable bytes-like objects.\n"
|
||||
"\n"
|
||||
"Combines the functionality of readv() and pread(). As readv(), it will\n"
|
||||
"transfer data into each buffer until it is full and then move on to the next\n"
|
||||
"buffer in the sequence to hold the rest of the data. Its fourth argument,\n"
|
||||
"specifies the file offset at which the input operation is to be performed. It\n"
|
||||
"will return the total number of bytes read (which can be less than the total\n"
|
||||
"capacity of all the objects).\n"
|
||||
"\n"
|
||||
"The flags argument contains a bitwise OR of zero or more of the following flags:\n"
|
||||
"\n"
|
||||
"- RWF_HIPRI\n"
|
||||
"- RWF_NOWAIT\n"
|
||||
"\n"
|
||||
"Using non-zero flags requires Linux 4.6 or newer.");
|
||||
|
||||
#define OS_PREADV_METHODDEF \
|
||||
{"preadv", (PyCFunction)os_preadv, METH_FASTCALL, os_preadv__doc__},
|
||||
|
||||
static Py_ssize_t
|
||||
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
|
||||
int flags);
|
||||
|
||||
static PyObject *
|
||||
os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int fd;
|
||||
PyObject *buffers;
|
||||
Py_off_t offset;
|
||||
int flags = 0;
|
||||
Py_ssize_t _return_value;
|
||||
|
||||
if (!_PyArg_ParseStack(args, nargs, "iOO&|i:preadv",
|
||||
&fd, &buffers, Py_off_t_converter, &offset, &flags)) {
|
||||
goto exit;
|
||||
}
|
||||
_return_value = os_preadv_impl(module, fd, buffers, offset, flags);
|
||||
if ((_return_value == -1) && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = PyLong_FromSsize_t(_return_value);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
#endif /* (defined(HAVE_PREADV) || defined (HAVE_PREADV2)) */
|
||||
|
||||
PyDoc_STRVAR(os_write__doc__,
|
||||
"write($module, fd, data, /)\n"
|
||||
"--\n"
|
||||
|
|
@ -3963,6 +4018,61 @@ exit:
|
|||
|
||||
#endif /* defined(HAVE_PWRITE) */
|
||||
|
||||
#if (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2))
|
||||
|
||||
PyDoc_STRVAR(os_pwritev__doc__,
|
||||
"pwritev($module, fd, buffers, offset, flags=0, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Writes the contents of bytes-like objects to a file descriptor at a given offset.\n"
|
||||
"\n"
|
||||
"Combines the functionality of writev() and pwrite(). All buffers must be a sequence\n"
|
||||
"of bytes-like objects. Buffers are processed in array order. Entire contents of first\n"
|
||||
"buffer is written before proceeding to second, and so on. The operating system may\n"
|
||||
"set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.\n"
|
||||
"This function writes the contents of each object to the file descriptor and returns\n"
|
||||
"the total number of bytes written.\n"
|
||||
"\n"
|
||||
"The flags argument contains a bitwise OR of zero or more of the following flags:\n"
|
||||
"\n"
|
||||
"- RWF_DSYNC\n"
|
||||
"- RWF_SYNC\n"
|
||||
"\n"
|
||||
"Using non-zero flags requires Linux 4.7 or newer.");
|
||||
|
||||
#define OS_PWRITEV_METHODDEF \
|
||||
{"pwritev", (PyCFunction)os_pwritev, METH_FASTCALL, os_pwritev__doc__},
|
||||
|
||||
static Py_ssize_t
|
||||
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
|
||||
int flags);
|
||||
|
||||
static PyObject *
|
||||
os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int fd;
|
||||
PyObject *buffers;
|
||||
Py_off_t offset;
|
||||
int flags = 0;
|
||||
Py_ssize_t _return_value;
|
||||
|
||||
if (!_PyArg_ParseStack(args, nargs, "iOO&|i:pwritev",
|
||||
&fd, &buffers, Py_off_t_converter, &offset, &flags)) {
|
||||
goto exit;
|
||||
}
|
||||
_return_value = os_pwritev_impl(module, fd, buffers, offset, flags);
|
||||
if ((_return_value == -1) && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = PyLong_FromSsize_t(_return_value);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
#endif /* (defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)) */
|
||||
|
||||
#if defined(HAVE_MKFIFO)
|
||||
|
||||
PyDoc_STRVAR(os_mkfifo__doc__,
|
||||
|
|
@ -6239,6 +6349,10 @@ exit:
|
|||
#define OS_PREAD_METHODDEF
|
||||
#endif /* !defined(OS_PREAD_METHODDEF) */
|
||||
|
||||
#ifndef OS_PREADV_METHODDEF
|
||||
#define OS_PREADV_METHODDEF
|
||||
#endif /* !defined(OS_PREADV_METHODDEF) */
|
||||
|
||||
#ifndef OS_PIPE_METHODDEF
|
||||
#define OS_PIPE_METHODDEF
|
||||
#endif /* !defined(OS_PIPE_METHODDEF) */
|
||||
|
|
@ -6255,6 +6369,10 @@ exit:
|
|||
#define OS_PWRITE_METHODDEF
|
||||
#endif /* !defined(OS_PWRITE_METHODDEF) */
|
||||
|
||||
#ifndef OS_PWRITEV_METHODDEF
|
||||
#define OS_PWRITEV_METHODDEF
|
||||
#endif /* !defined(OS_PWRITEV_METHODDEF) */
|
||||
|
||||
#ifndef OS_MKFIFO_METHODDEF
|
||||
#define OS_MKFIFO_METHODDEF
|
||||
#endif /* !defined(OS_MKFIFO_METHODDEF) */
|
||||
|
|
@ -6410,4 +6528,4 @@ exit:
|
|||
#ifndef OS_GETRANDOM_METHODDEF
|
||||
#define OS_GETRANDOM_METHODDEF
|
||||
#endif /* !defined(OS_GETRANDOM_METHODDEF) */
|
||||
/*[clinic end generated code: output=6345053cd5992caf input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=06ace805893aa10c input=a9049054013a1b77]*/
|
||||
|
|
|
|||
|
|
@ -8163,6 +8163,94 @@ os_pread_impl(PyObject *module, int fd, int length, Py_off_t offset)
|
|||
}
|
||||
#endif /* HAVE_PREAD */
|
||||
|
||||
#if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
|
||||
/*[clinic input]
|
||||
os.preadv -> Py_ssize_t
|
||||
|
||||
fd: int
|
||||
buffers: object
|
||||
offset: Py_off_t
|
||||
flags: int = 0
|
||||
/
|
||||
|
||||
Reads from a file descriptor into a number of mutable bytes-like objects.
|
||||
|
||||
Combines the functionality of readv() and pread(). As readv(), it will
|
||||
transfer data into each buffer until it is full and then move on to the next
|
||||
buffer in the sequence to hold the rest of the data. Its fourth argument,
|
||||
specifies the file offset at which the input operation is to be performed. It
|
||||
will return the total number of bytes read (which can be less than the total
|
||||
capacity of all the objects).
|
||||
|
||||
The flags argument contains a bitwise OR of zero or more of the following flags:
|
||||
|
||||
- RWF_HIPRI
|
||||
- RWF_NOWAIT
|
||||
|
||||
Using non-zero flags requires Linux 4.6 or newer.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static Py_ssize_t
|
||||
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
|
||||
int flags)
|
||||
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
|
||||
{
|
||||
Py_ssize_t cnt, n;
|
||||
int async_err = 0;
|
||||
struct iovec *iov;
|
||||
Py_buffer *buf;
|
||||
|
||||
if (!PySequence_Check(buffers)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"preadv2() arg 2 must be a sequence");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cnt = PySequence_Size(buffers);
|
||||
if (cnt < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef HAVE_PREADV2
|
||||
if(flags != 0) {
|
||||
argument_unavailable_error("preadv2", "flags");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_PREADV2
|
||||
do {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
_Py_BEGIN_SUPPRESS_IPH
|
||||
n = preadv2(fd, iov, cnt, offset, flags);
|
||||
_Py_END_SUPPRESS_IPH
|
||||
Py_END_ALLOW_THREADS
|
||||
} while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
#else
|
||||
do {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
_Py_BEGIN_SUPPRESS_IPH
|
||||
n = preadv(fd, iov, cnt, offset);
|
||||
_Py_END_SUPPRESS_IPH
|
||||
Py_END_ALLOW_THREADS
|
||||
} while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
#endif
|
||||
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
if (n < 0) {
|
||||
if (!async_err) {
|
||||
posix_error();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
#endif /* HAVE_PREADV */
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
os.write -> Py_ssize_t
|
||||
|
|
@ -8613,6 +8701,97 @@ os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
|
|||
}
|
||||
#endif /* HAVE_PWRITE */
|
||||
|
||||
#if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
|
||||
/*[clinic input]
|
||||
os.pwritev -> Py_ssize_t
|
||||
|
||||
fd: int
|
||||
buffers: object
|
||||
offset: Py_off_t
|
||||
flags: int = 0
|
||||
/
|
||||
|
||||
Writes the contents of bytes-like objects to a file descriptor at a given offset.
|
||||
|
||||
Combines the functionality of writev() and pwrite(). All buffers must be a sequence
|
||||
of bytes-like objects. Buffers are processed in array order. Entire contents of first
|
||||
buffer is written before proceeding to second, and so on. The operating system may
|
||||
set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
|
||||
This function writes the contents of each object to the file descriptor and returns
|
||||
the total number of bytes written.
|
||||
|
||||
The flags argument contains a bitwise OR of zero or more of the following flags:
|
||||
|
||||
- RWF_DSYNC
|
||||
- RWF_SYNC
|
||||
|
||||
Using non-zero flags requires Linux 4.7 or newer.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static Py_ssize_t
|
||||
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
|
||||
int flags)
|
||||
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/
|
||||
{
|
||||
Py_ssize_t cnt;
|
||||
Py_ssize_t result;
|
||||
int async_err = 0;
|
||||
struct iovec *iov;
|
||||
Py_buffer *buf;
|
||||
|
||||
if (!PySequence_Check(buffers)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"pwritev() arg 2 must be a sequence");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cnt = PySequence_Size(buffers);
|
||||
if (cnt < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef HAVE_PWRITEV2
|
||||
if(flags != 0) {
|
||||
argument_unavailable_error("pwritev2", "flags");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_PWRITEV2
|
||||
do {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
_Py_BEGIN_SUPPRESS_IPH
|
||||
result = pwritev2(fd, iov, cnt, offset, flags);
|
||||
_Py_END_SUPPRESS_IPH
|
||||
Py_END_ALLOW_THREADS
|
||||
} while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
#else
|
||||
do {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
_Py_BEGIN_SUPPRESS_IPH
|
||||
result = pwritev(fd, iov, cnt, offset);
|
||||
_Py_END_SUPPRESS_IPH
|
||||
Py_END_ALLOW_THREADS
|
||||
} while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
|
||||
#endif
|
||||
|
||||
iov_cleanup(iov, buf, cnt);
|
||||
if (result < 0) {
|
||||
if (!async_err) {
|
||||
posix_error();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_PWRITEV */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_MKFIFO
|
||||
/*[clinic input]
|
||||
|
|
@ -12506,9 +12685,11 @@ static PyMethodDef posix_methods[] = {
|
|||
OS_READ_METHODDEF
|
||||
OS_READV_METHODDEF
|
||||
OS_PREAD_METHODDEF
|
||||
OS_PREADV_METHODDEF
|
||||
OS_WRITE_METHODDEF
|
||||
OS_WRITEV_METHODDEF
|
||||
OS_PWRITE_METHODDEF
|
||||
OS_PWRITEV_METHODDEF
|
||||
#ifdef HAVE_SENDFILE
|
||||
{"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
|
||||
posix_sendfile__doc__},
|
||||
|
|
@ -12953,6 +13134,19 @@ all_ins(PyObject *m)
|
|||
if (PyModule_AddIntMacro(m, F_TEST)) return -1;
|
||||
#endif
|
||||
|
||||
#ifdef RWF_DSYNC
|
||||
if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
|
||||
#endif
|
||||
#ifdef RWF_HIPRI
|
||||
if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
|
||||
#endif
|
||||
#ifdef RWF_SYNC
|
||||
if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
|
||||
#endif
|
||||
#ifdef RWF_NOWAIT
|
||||
if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SPAWNV
|
||||
if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
|
||||
if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue