diff options
| author | Paul Eggert | 2016-09-10 12:51:27 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-09-10 19:14:44 -0700 |
| commit | 9b21d9f9110445846dce25c3505c4ee04572fade (patch) | |
| tree | e133e7d94a10ae19a7f8a4d44974a99151b0ca20 /src | |
| parent | 0fca290ddff9eabcd2e866b1361cd5b5ba868281 (diff) | |
| download | emacs-9b21d9f9110445846dce25c3505c4ee04572fade.tar.gz emacs-9b21d9f9110445846dce25c3505c4ee04572fade.zip | |
copy-file now uses GNU/Linux file cloning
From a suggestion by Kieran Colford (see Bug#23904).
* configure.ac: Check for linux/fs.h.
* src/fileio.c [HAVE_LINUX_FS_H]: Include sys/ioctl.h and linux/fs.h.
(clone_file): New function.
(Fcopy_file): Use it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/src/fileio.c b/src/fileio.c index bf6bf622abf..b4316b3da98 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -52,6 +52,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 52 | #include "region-cache.h" | 52 | #include "region-cache.h" |
| 53 | #include "frame.h" | 53 | #include "frame.h" |
| 54 | 54 | ||
| 55 | #ifdef HAVE_LINUX_FS_H | ||
| 56 | # include <sys/ioctl.h> | ||
| 57 | # include <linux/fs.h> | ||
| 58 | #endif | ||
| 59 | |||
| 55 | #ifdef WINDOWSNT | 60 | #ifdef WINDOWSNT |
| 56 | #define NOMINMAX 1 | 61 | #define NOMINMAX 1 |
| 57 | #include <windows.h> | 62 | #include <windows.h> |
| @@ -1829,6 +1834,16 @@ barf_or_query_if_file_exists (Lisp_Object absname, bool known_to_exist, | |||
| 1829 | } | 1834 | } |
| 1830 | } | 1835 | } |
| 1831 | 1836 | ||
| 1837 | /* Copy data to DEST from SOURCE if possible. Return true if OK. */ | ||
| 1838 | static bool | ||
| 1839 | clone_file (int dest, int source) | ||
| 1840 | { | ||
| 1841 | #ifdef FICLONE | ||
| 1842 | return ioctl (dest, FICLONE, source) == 0; | ||
| 1843 | #endif | ||
| 1844 | return false; | ||
| 1845 | } | ||
| 1846 | |||
| 1832 | DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, | 1847 | DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, |
| 1833 | "fCopy file: \nGCopy %s to file: \np\nP", | 1848 | "fCopy file: \nGCopy %s to file: \np\nP", |
| 1834 | doc: /* Copy FILE to NEWNAME. Both args must be strings. | 1849 | doc: /* Copy FILE to NEWNAME. Both args must be strings. |
| @@ -1975,7 +1990,7 @@ permissions. */) | |||
| 1975 | 1990 | ||
| 1976 | record_unwind_protect_int (close_file_unwind, ofd); | 1991 | record_unwind_protect_int (close_file_unwind, ofd); |
| 1977 | 1992 | ||
| 1978 | off_t oldsize = 0, newsize = 0; | 1993 | off_t oldsize = 0, newsize; |
| 1979 | 1994 | ||
| 1980 | if (already_exists) | 1995 | if (already_exists) |
| 1981 | { | 1996 | { |
| @@ -1991,17 +2006,19 @@ permissions. */) | |||
| 1991 | 2006 | ||
| 1992 | immediate_quit = 1; | 2007 | immediate_quit = 1; |
| 1993 | QUIT; | 2008 | QUIT; |
| 1994 | while (true) | 2009 | |
| 2010 | if (clone_file (ofd, ifd)) | ||
| 2011 | newsize = st.st_size; | ||
| 2012 | else | ||
| 1995 | { | 2013 | { |
| 1996 | char buf[MAX_ALLOCA]; | 2014 | char buf[MAX_ALLOCA]; |
| 1997 | ptrdiff_t n = emacs_read (ifd, buf, sizeof buf); | 2015 | ptrdiff_t n; |
| 2016 | for (newsize = 0; 0 < (n = emacs_read (ifd, buf, sizeof buf)); | ||
| 2017 | newsize += n) | ||
| 2018 | if (emacs_write_sig (ofd, buf, n) != n) | ||
| 2019 | report_file_error ("Write error", newname); | ||
| 1998 | if (n < 0) | 2020 | if (n < 0) |
| 1999 | report_file_error ("Read error", file); | 2021 | report_file_error ("Read error", file); |
| 2000 | if (n == 0) | ||
| 2001 | break; | ||
| 2002 | if (emacs_write_sig (ofd, buf, n) != n) | ||
| 2003 | report_file_error ("Write error", newname); | ||
| 2004 | newsize += n; | ||
| 2005 | } | 2022 | } |
| 2006 | 2023 | ||
| 2007 | /* Truncate any existing output file after writing the data. This | 2024 | /* Truncate any existing output file after writing the data. This |