aboutsummaryrefslogtreecommitdiff
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2020-11-17 00:00:38 +0000
committerGitHub <noreply@github.com>2020-11-17 00:00:38 +0000
commita57b3d30f66c90f42da751bf82256b9b22961ed0 (patch)
tree04ec1f393ebfe891fda48a164829bdee76911c0b /Modules/posixmodule.c
parentcce3f0b0c88eba98bc11abe703a444bee7880ff8 (diff)
downloadcpython3-a57b3d30f66c90f42da751bf82256b9b22961ed0.tar.gz
bpo-41625: Expose the splice() system call in the os module (GH-21947)
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 0764453f41..ecab147d2f 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -6521,7 +6521,6 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
#endif /* HAVE_SPAWNV */
-
#ifdef HAVE_FORK
/* Helper function to validate arguments.
@@ -10370,6 +10369,75 @@ os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
}
#endif /* HAVE_COPY_FILE_RANGE*/
+#ifdef HAVE_SPLICE
+/*[clinic input]
+
+os.splice
+ src: int
+ Source file descriptor.
+ dst: int
+ Destination file descriptor.
+ count: Py_ssize_t
+ Number of bytes to copy.
+ offset_src: object = None
+ Starting offset in src.
+ offset_dst: object = None
+ Starting offset in dst.
+ flags: unsigned_int = 0
+ Flags to modify the semantics of the call.
+
+Transfer count bytes from one pipe to a descriptor or vice versa.
+
+If offset_src is None, then src is read from the current position;
+respectively for offset_dst. The offset associated to the file
+descriptor that refers to a pipe must be None.
+[clinic start generated code]*/
+
+static PyObject *
+os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
+ PyObject *offset_src, PyObject *offset_dst,
+ unsigned int flags)
+/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
+{
+ off_t offset_src_val, offset_dst_val;
+ off_t *p_offset_src = NULL;
+ off_t *p_offset_dst = NULL;
+ Py_ssize_t ret;
+ int async_err = 0;
+
+ if (count < 0) {
+ PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
+ return NULL;
+ }
+
+ if (offset_src != Py_None) {
+ if (!Py_off_t_converter(offset_src, &offset_src_val)) {
+ return NULL;
+ }
+ p_offset_src = &offset_src_val;
+ }
+
+ if (offset_dst != Py_None) {
+ if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
+ return NULL;
+ }
+ p_offset_dst = &offset_dst_val;
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (ret < 0) {
+ return (!async_err) ? posix_error() : NULL;
+ }
+
+ return PyLong_FromSsize_t(ret);
+}
+#endif /* HAVE_SPLICE*/
+
#ifdef HAVE_MKFIFO
/*[clinic input]
os.mkfifo
@@ -14550,6 +14618,7 @@ static PyMethodDef posix_methods[] = {
OS_POSIX_SPAWNP_METHODDEF
OS_READLINK_METHODDEF
OS_COPY_FILE_RANGE_METHODDEF
+ OS_SPLICE_METHODDEF
OS_RENAME_METHODDEF
OS_REPLACE_METHODDEF
OS_RMDIR_METHODDEF
@@ -15072,6 +15141,13 @@ all_ins(PyObject *m)
if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
#endif
+/* constants for splice */
+#ifdef HAVE_SPLICE
+ if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
+ if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
+ if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
+#endif
+
/* constants for posix_spawn */
#ifdef HAVE_POSIX_SPAWN
if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;