aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 796f08d3c58..a969d3b2c0f 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1871,8 +1871,6 @@ permissions. */)
1871 bool already_exists = false; 1871 bool already_exists = false;
1872 mode_t new_mask; 1872 mode_t new_mask;
1873 int ifd, ofd; 1873 int ifd, ofd;
1874 int n;
1875 char buf[16 * 1024];
1876 struct stat st; 1874 struct stat st;
1877#endif 1875#endif
1878 1876
@@ -1974,6 +1972,8 @@ permissions. */)
1974 1972
1975 record_unwind_protect_int (close_file_unwind, ofd); 1973 record_unwind_protect_int (close_file_unwind, ofd);
1976 1974
1975 off_t oldsize = 0, newsize = 0;
1976
1977 if (already_exists) 1977 if (already_exists)
1978 { 1978 {
1979 struct stat out_st; 1979 struct stat out_st;
@@ -1982,15 +1982,31 @@ permissions. */)
1982 if (st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) 1982 if (st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
1983 report_file_errno ("Input and output files are the same", 1983 report_file_errno ("Input and output files are the same",
1984 list2 (file, newname), 0); 1984 list2 (file, newname), 0);
1985 if (ftruncate (ofd, 0) != 0) 1985 if (S_ISREG (out_st.st_mode))
1986 report_file_error ("Truncating output file", newname); 1986 oldsize = out_st.st_size;
1987 } 1987 }
1988 1988
1989 immediate_quit = 1; 1989 immediate_quit = 1;
1990 QUIT; 1990 QUIT;
1991 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) 1991 while (true)
1992 if (emacs_write_sig (ofd, buf, n) != n) 1992 {
1993 report_file_error ("Write error", newname); 1993 char buf[MAX_ALLOCA];
1994 ptrdiff_t n = emacs_read (ifd, buf, sizeof buf);
1995 if (n < 0)
1996 report_file_error ("Read error", file);
1997 if (n == 0)
1998 break;
1999 if (emacs_write_sig (ofd, buf, n) != n)
2000 report_file_error ("Write error", newname);
2001 newsize += n;
2002 }
2003
2004 /* Truncate any existing output file after writing the data. This
2005 is more likely to work than truncation before writing, if the
2006 file system is out of space or the user is over disk quota. */
2007 if (newsize < oldsize && ftruncate (ofd, newsize) != 0)
2008 report_file_error ("Truncating output file", newname);
2009
1994 immediate_quit = 0; 2010 immediate_quit = 0;
1995 2011
1996#ifndef MSDOS 2012#ifndef MSDOS