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

Delta Between Two Patch Sets: Modules/posixmodule.c

Issue 26826: Expose new copy_file_range() syscal in os module and use it to improve shutils.copy()
Left Patch Set: Created 3 years, 8 months ago
Right Patch Set: Created 3 years, 7 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/test/test_os.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 8391 matching lines...) Expand 10 before | Expand all | Expand 10 after
8402 ret = sendfile(out, in, &offset, count); 8402 ret = sendfile(out, in, &offset, count);
8403 Py_END_ALLOW_THREADS 8403 Py_END_ALLOW_THREADS
8404 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8404 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8405 if (ret < 0) 8405 if (ret < 0)
8406 return (!async_err) ? posix_error() : NULL; 8406 return (!async_err) ? posix_error() : NULL;
8407 return Py_BuildValue("n", ret); 8407 return Py_BuildValue("n", ret);
8408 #endif 8408 #endif
8409 } 8409 }
8410 #endif /* HAVE_SENDFILE */ 8410 #endif /* HAVE_SENDFILE */
8411 8411
8412 #ifdef HAVE_COPY_FILE_RANGE
8413 /* modified example found in copy_file_range()'s man page: */
8414 /* changed the return type to ssize_t so it can return -1 */
8415 static ssize_t
8416 copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,
8417 size_t len, unsigned int flags)
8418 {
8419 return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out,
8420 len, flags);
8421 }
8422
8423 PyDoc_STRVAR(posix_copy_file_range__doc__,
8424 "copy_file_range(src, dst, count, offset_src=None, offset_dst=None, flags=0) -> \
8425 bytes_written\n\
8426 Copy count bytes from file descriptor src, starting from offset offset_src, \
8427 to file descriptor dst, starting from offset offset_dst. \
8428 If offset_src is None, then src is read from the current position; \
8429 respectively for offset_dst.");
8430
8431 static PyObject *
8432 posix_copy_file_range(PyObject *self, PyObject *args, PyObject *kwdict)
8433 {
8434 int src, dst;
8435 off_t offset_src, *p_offset_src, offset_dst, *p_offset_dst;
8436 Py_ssize_t count, ret;
8437 int async_err = 0;
8438 int flags = 0;
8439 PyObject *offset_src_obj = Py_None, *offset_dst_obj = Py_None;
8440 static char *keywords[] = {"src", "dst", "count",
8441 "offset_src", "offset_dst", "flags", NULL};
8442
8443 /* O types are used to handle offset_*_obj==None -> from current position */
8444 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iin|OOi:copy_file_range",
8445 keywords, &src, &dst, &count, &offset_src_obj, &offset_dst_obj, &flags))
8446 return NULL;
8447
8448 /* offset handling is complex. we convert the argument to a Python object.
8449 * if None, then the corresponding pointer is NULL.
8450 * otherwise, try to convert; if successful, use that
8451 * and point the pointer there.
8452 */
8453 if (offset_src_obj == Py_None)
8454 p_offset_src = NULL;
8455 else {
8456 if (!Py_off_t_converter(offset_src_obj, &offset_src))
8457 return NULL;
8458 p_offset_src = &offset_src;
8459 }
8460 if (offset_dst_obj == Py_None)
8461 p_offset_dst = NULL;
8462 else {
8463 if (!Py_off_t_converter(offset_dst_obj, &offset_dst))
8464 return NULL;
8465 p_offset_dst = &offset_dst;
8466 }
8467
8468 do {
8469 Py_BEGIN_ALLOW_THREADS
8470 ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags );
8471 Py_END_ALLOW_THREADS
8472 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8473
8474 if (ret < 0)
8475 return async_err ? NULL : posix_error();
8476
8477 /* we currently ignore the changes to the offsets */
8478 return Py_BuildValue("n", ret);
8479 }
8480 #endif /* HAVE_COPY_FILE_RANGE */
8481 8412
8482 /*[clinic input] 8413 /*[clinic input]
8483 os.fstat 8414 os.fstat
8484 8415
8485 fd : int 8416 fd : int
8486 8417
8487 Perform a stat system call on the given file descriptor. 8418 Perform a stat system call on the given file descriptor.
8488 8419
8489 Like stat(), but for an open file descriptor. 8420 Like stat(), but for an open file descriptor.
8490 Equivalent to os.stat(fd). 8421 Equivalent to os.stat(fd).
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
8737 _Py_END_SUPPRESS_IPH 8668 _Py_END_SUPPRESS_IPH
8738 Py_END_ALLOW_THREADS 8669 Py_END_ALLOW_THREADS
8739 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8670 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8740 8671
8741 if (size < 0 && !async_err) 8672 if (size < 0 && !async_err)
8742 posix_error(); 8673 posix_error();
8743 return size; 8674 return size;
8744 } 8675 }
8745 #endif /* HAVE_PWRITE */ 8676 #endif /* HAVE_PWRITE */
8746 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 */
8747 8747
8748 #ifdef HAVE_MKFIFO 8748 #ifdef HAVE_MKFIFO
8749 /*[clinic input] 8749 /*[clinic input]
8750 os.mkfifo 8750 os.mkfifo
8751 8751
8752 path: path_t 8752 path: path_t
8753 mode: int=0o666 8753 mode: int=0o666
8754 * 8754 *
8755 dir_fd: dir_fd(requires='mkfifoat')=None 8755 dir_fd: dir_fd(requires='mkfifoat')=None
8756 8756
(...skipping 4622 matching lines...) Expand 10 before | Expand all | Expand 10 after
13379 PyModule_AddObject(m, "_have_functions", list); 13379 PyModule_AddObject(m, "_have_functions", list);
13380 13380
13381 initialized = 1; 13381 initialized = 1;
13382 13382
13383 return m; 13383 return m;
13384 } 13384 }
13385 13385
13386 #ifdef __cplusplus 13386 #ifdef __cplusplus
13387 } 13387 }
13388 #endif 13388 #endif
LEFTRIGHT

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