aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-09-10 12:51:27 -0700
committerPaul Eggert2016-09-10 19:14:44 -0700
commit9b21d9f9110445846dce25c3505c4ee04572fade (patch)
treee133e7d94a10ae19a7f8a4d44974a99151b0ca20 /src
parent0fca290ddff9eabcd2e866b1361cd5b5ba868281 (diff)
downloademacs-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.c33
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. */
1838static bool
1839clone_file (int dest, int source)
1840{
1841#ifdef FICLONE
1842 return ioctl (dest, FICLONE, source) == 0;
1843#endif
1844 return false;
1845}
1846
1832DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, 1847DEFUN ("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