diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2019-05-31 18:39:47 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-31 18:39:47 (GMT) |
commit | aac4d0342c3e692731c189d003dbd73a8c681a34 (patch) | |
tree | b888c0e2423d1b3422765db1cea5f3e0cf5c97f4 /Modules/posixmodule.c | |
parent | 545a3b8814dbf2a5391e830d69e796fb1a1d62ec (diff) | |
download | cpython-aac4d0342c3e692731c189d003dbd73a8c681a34.zip cpython-aac4d0342c3e692731c189d003dbd73a8c681a34.tar.gz cpython-aac4d0342c3e692731c189d003dbd73a8c681a34.tar.bz2 |
bpo-26826: Expose copy_file_range in the os module (GH-7255)
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r-- | Modules/posixmodule.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 77a3700..8f6cfff 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -117,6 +117,10 @@ corresponding Unix manual entries for more information on calls."); #include <sched.h> #endif +#ifdef HAVE_COPY_FILE_RANGE +#include <unistd.h> +#endif + #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) #undef HAVE_SCHED_SETAFFINITY #endif @@ -9455,8 +9459,74 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, } #endif /* HAVE_PWRITEV */ +#ifdef HAVE_COPY_FILE_RANGE +/*[clinic input] + +os.copy_file_range + 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. + +Copy count bytes from one file descriptor to another. + +If offset_src is None, then src is read from the current position; +respectively for offset_dst. +[clinic start generated code]*/ + +static PyObject * +os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst) +/*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ +{ + 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; + /* The flags argument is provided to allow + * for future extensions and currently must be to 0. */ + int flags = 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 = 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) ? posix_error() : NULL; + } + + return PyLong_FromSsize_t(ret); +} +#endif /* HAVE_COPY_FILE_RANGE*/ #ifdef HAVE_MKFIFO /*[clinic input] @@ -13432,6 +13502,7 @@ static PyMethodDef posix_methods[] = { OS_POSIX_SPAWN_METHODDEF OS_POSIX_SPAWNP_METHODDEF OS_READLINK_METHODDEF + OS_COPY_FILE_RANGE_METHODDEF OS_RENAME_METHODDEF OS_REPLACE_METHODDEF OS_RMDIR_METHODDEF |