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

Side by Side 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, 9 months ago
Left:
Right:
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 unified diff | Download patch
« no previous file with comments | « Lib/test/test_os.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* POSIX module implementation */ 2 /* POSIX module implementation */
3 3
4 /* This file is also used for Windows NT/MS-Win. In that case the 4 /* This file is also used for Windows NT/MS-Win. In that case the
5 module actually calls itself 'nt', not 'posix', and a few 5 module actually calls itself 'nt', not 'posix', and a few
6 functions are either unimplemented or implemented differently. The source 6 functions are either unimplemented or implemented differently. The source
7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8 of the compiler used. Different compilers define their own feature 8 of the compiler used. Different compilers define their own feature
9 test macro, e.g. '_MSC_VER'. */ 9 test macro, e.g. '_MSC_VER'. */
10 10
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 #ifdef HAVE_SYS_LOADAVG_H 86 #ifdef HAVE_SYS_LOADAVG_H
87 #include <sys/loadavg.h> 87 #include <sys/loadavg.h>
88 #endif 88 #endif
89 89
90 #ifdef HAVE_LANGINFO_H 90 #ifdef HAVE_LANGINFO_H
91 #include <langinfo.h> 91 #include <langinfo.h>
92 #endif 92 #endif
93 93
94 #ifdef HAVE_SYS_SENDFILE_H 94 #ifdef HAVE_SYS_SENDFILE_H
95 #include <sys/sendfile.h> 95 #include <sys/sendfile.h>
96 #endif
97
98 #ifdef HAVE_COPY_FILE_RANGE
99 #include <sys/syscall.h>
100 #include <unistd.h>
96 #endif 101 #endif
97 102
98 #ifdef HAVE_SCHED_H 103 #ifdef HAVE_SCHED_H
99 #include <sched.h> 104 #include <sched.h>
100 #endif 105 #endif
101 106
102 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) 107 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
103 #undef HAVE_SCHED_SETAFFINITY 108 #undef HAVE_SCHED_SETAFFINITY
104 #endif 109 #endif
105 110
(...skipping 8557 matching lines...) Expand 10 before | Expand all | Expand 10 after
8663 _Py_END_SUPPRESS_IPH 8668 _Py_END_SUPPRESS_IPH
8664 Py_END_ALLOW_THREADS 8669 Py_END_ALLOW_THREADS
8665 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8670 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8666 8671
8667 if (size < 0 && !async_err) 8672 if (size < 0 && !async_err)
8668 posix_error(); 8673 posix_error();
8669 return size; 8674 return size;
8670 } 8675 }
8671 #endif /* HAVE_PWRITE */ 8676 #endif /* HAVE_PWRITE */
8672 8677
8678 #ifdef HAVE_COPY_FILE_RANGE
8679 /* modified example found in copy_file_range()'s man page: */
8680 /* changed the return type to ssize_t so it can return -1 */
8681 static ssize_t
8682 copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,
8683 size_t len, unsigned int flags)
8684 {
8685 return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out,
8686 len, flags);
8687 }
8688
8689 PyDoc_STRVAR(posix_copy_file_range__doc__,
8690 "copy_file_range(src, dst, count, offset_src=None, offset_dst=None) -> \
8691 bytes_written\n\
8692 Copy count bytes from file descriptor src, starting from offset offset_src, \
8693 to file descriptor dst, starting from offset offset_dst. \
8694 If offset_src is None, then src is read from the current position; \
8695 respectively for offset_dst.");
8696
8697 static PyObject *
8698 posix_copy_file_range(PyObject *self, PyObject *args, PyObject *kwdict)
8699 {
8700 int src, dst;
8701 off_t offset_src, *p_offset_src, offset_dst, *p_offset_dst;
8702 Py_ssize_t count, ret;
8703 int async_err = 0;
8704 int flags = 0;
8705 PyObject *offset_src_obj = Py_None, *offset_dst_obj = Py_None;
8706 static char *keywords[] = {"src", "dst", "count",
8707 "offset_src", "offset_dst", NULL};
8708
8709 /* O types are used to handle offset_*_obj==None -> from current position */
8710 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iin|OO:copy_file_range",
8711 keywords, &src, &dst, &count, &offset_src_obj, &offset_dst_obj))
8712 return NULL;
8713
8714 /* offset handling is complex. we convert the argument to a Python object.
8715 * if None, then the corresponding pointer is NULL.
8716 * otherwise, try to convert; if successful, use that
8717 * and point the pointer there.
8718 */
8719 if (offset_src_obj == Py_None)
8720 p_offset_src = NULL;
8721 else {
8722 if (!Py_off_t_converter(offset_src_obj, &offset_src))
8723 return NULL;
8724 p_offset_src = &offset_src;
8725 }
8726 if (offset_dst_obj == Py_None)
8727 p_offset_dst = NULL;
8728 else {
8729 if (!Py_off_t_converter(offset_dst_obj, &offset_dst))
8730 return NULL;
8731 p_offset_dst = &offset_dst;
8732 }
8733
8734 do {
8735 Py_BEGIN_ALLOW_THREADS
8736 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags );
8737 Py_END_ALLOW_THREADS
8738 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8739
8740 if (ret < 0)
8741 return async_err ? NULL : posix_error();
8742
8743 /* we currently ignore the changes to the offsets */
8744 return Py_BuildValue("n", ret);
8745 }
8746 #endif /* HAVE_COPY_FILE_RANGE */
8673 8747
8674 #ifdef HAVE_MKFIFO 8748 #ifdef HAVE_MKFIFO
8675 /*[clinic input] 8749 /*[clinic input]
8676 os.mkfifo 8750 os.mkfifo
8677 8751
8678 path: path_t 8752 path: path_t
8679 mode: int=0o666 8753 mode: int=0o666
8680 * 8754 *
8681 dir_fd: dir_fd(requires='mkfifoat')=None 8755 dir_fd: dir_fd(requires='mkfifoat')=None
8682 8756
(...skipping 3776 matching lines...) Expand 10 before | Expand all | Expand 10 after
12459 OS_LSEEK_METHODDEF 12533 OS_LSEEK_METHODDEF
12460 OS_READ_METHODDEF 12534 OS_READ_METHODDEF
12461 OS_READV_METHODDEF 12535 OS_READV_METHODDEF
12462 OS_PREAD_METHODDEF 12536 OS_PREAD_METHODDEF
12463 OS_WRITE_METHODDEF 12537 OS_WRITE_METHODDEF
12464 OS_WRITEV_METHODDEF 12538 OS_WRITEV_METHODDEF
12465 OS_PWRITE_METHODDEF 12539 OS_PWRITE_METHODDEF
12466 #ifdef HAVE_SENDFILE 12540 #ifdef HAVE_SENDFILE
12467 {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORD S, 12541 {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORD S,
12468 posix_sendfile__doc__}, 12542 posix_sendfile__doc__},
12543 #endif
12544 #ifdef HAVE_COPY_FILE_RANGE
12545 {"copy_file_range", (PyCFunction)posix_copy_file_range, METH_VARARGS | METH_ KEYWORDS,
12546 posix_copy_file_range__doc__},
12469 #endif 12547 #endif
12470 OS_FSTAT_METHODDEF 12548 OS_FSTAT_METHODDEF
12471 OS_ISATTY_METHODDEF 12549 OS_ISATTY_METHODDEF
12472 OS_PIPE_METHODDEF 12550 OS_PIPE_METHODDEF
12473 OS_PIPE2_METHODDEF 12551 OS_PIPE2_METHODDEF
12474 OS_MKFIFO_METHODDEF 12552 OS_MKFIFO_METHODDEF
12475 OS_MKNOD_METHODDEF 12553 OS_MKNOD_METHODDEF
12476 OS_MAJOR_METHODDEF 12554 OS_MAJOR_METHODDEF
12477 OS_MINOR_METHODDEF 12555 OS_MINOR_METHODDEF
12478 OS_MAKEDEV_METHODDEF 12556 OS_MAKEDEV_METHODDEF
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after
13301 PyModule_AddObject(m, "_have_functions", list); 13379 PyModule_AddObject(m, "_have_functions", list);
13302 13380
13303 initialized = 1; 13381 initialized = 1;
13304 13382
13305 return m; 13383 return m;
13306 } 13384 }
13307 13385
13308 #ifdef __cplusplus 13386 #ifdef __cplusplus
13309 } 13387 }
13310 #endif 13388 #endif
OLDNEW
« 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+