bpo-26826: Expose copy_file_range in the os module (GH-7255)

This commit is contained in:
Pablo Galindo 2019-05-31 19:39:47 +01:00 committed by GitHub
parent 545a3b8814
commit aac4d0342c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 363 additions and 19 deletions

View file

@ -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