Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3)

Unified Diff: Modules/posixmodule.c

Issue 26826: Expose new copy_file_range() syscal in os module and use it to improve shutils.copy()
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Lib/test/test_os.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
--- a/Modules/posixmodule.c Wed Jun 08 13:32:49 2016 +0000
+++ b/Modules/posixmodule.c Wed Jul 06 12:59:50 2016 +0200
@@ -95,6 +95,11 @@
#include <sys/sendfile.h>
#endif
+#ifdef HAVE_COPY_FILE_RANGE
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
#ifdef HAVE_SCHED_H
#include <sched.h>
#endif
@@ -8670,6 +8675,75 @@
}
#endif /* HAVE_PWRITE */
+#ifdef HAVE_COPY_FILE_RANGE
+/* modified example found in copy_file_range()'s man page: */
+/* changed the return type to ssize_t so it can return -1 */
+static ssize_t
+copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,
+ size_t len, unsigned int flags)
+{
+ return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out,
+ len, flags);
+}
+
+PyDoc_STRVAR(posix_copy_file_range__doc__,
+"copy_file_range(src, dst, count, offset_src=None, offset_dst=None) -> \
+bytes_written\n\
+Copy count bytes from file descriptor src, starting from offset offset_src, \
+to file descriptor dst, starting from offset offset_dst. \
+If offset_src is None, then src is read from the current position; \
+respectively for offset_dst.");
+
+static PyObject *
+posix_copy_file_range(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ int src, dst;
+ off_t offset_src, *p_offset_src, offset_dst, *p_offset_dst;
+ Py_ssize_t count, ret;
+ int async_err = 0;
+ int flags = 0;
+ PyObject *offset_src_obj = Py_None, *offset_dst_obj = Py_None;
+ static char *keywords[] = {"src", "dst", "count",
+ "offset_src", "offset_dst", NULL};
+
+ /* O types are used to handle offset_*_obj==None -> from current position */
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iin|OO:copy_file_range",
+ keywords, &src, &dst, &count, &offset_src_obj, &offset_dst_obj))
+ return NULL;
+
+ /* offset handling is complex. we convert the argument to a Python object.
+ * if None, then the corresponding pointer is NULL.
+ * otherwise, try to convert; if successful, use that
+ * and point the pointer there.
+ */
+ if (offset_src_obj == Py_None)
+ p_offset_src = NULL;
+ else {
+ if (!Py_off_t_converter(offset_src_obj, &offset_src))
+ return NULL;
+ p_offset_src = &offset_src;
+ }
+ if (offset_dst_obj == Py_None)
+ p_offset_dst = NULL;
+ else {
+ if (!Py_off_t_converter(offset_dst_obj, &offset_dst))
+ return NULL;
+ p_offset_dst = &offset_dst;
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = copy_file_range(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 ? NULL : posix_error();
+
+ /* we currently ignore the changes to the offsets */
+ return Py_BuildValue("n", ret);
+}
+#endif /* HAVE_COPY_FILE_RANGE */
#ifdef HAVE_MKFIFO
/*[clinic input]
@@ -12467,6 +12541,10 @@
{"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
posix_sendfile__doc__},
#endif
+#ifdef HAVE_COPY_FILE_RANGE
+ {"copy_file_range", (PyCFunction)posix_copy_file_range, METH_VARARGS | METH_KEYWORDS,
+ posix_copy_file_range__doc__},
+#endif
OS_FSTAT_METHODDEF
OS_ISATTY_METHODDEF
OS_PIPE_METHODDEF
« no previous file with comments | « Lib/test/test_os.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+