diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 30 |
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 |