diff options
author | Jim Meyering <jim@meyering.net> | 2006-08-19 14:01:29 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2006-08-19 14:01:29 +0000 |
commit | b35bd50ce62fbb98984560177198b94a7de46d00 (patch) | |
tree | 9bab2c61e3f66c9d2589b99debcb979e88d68a12 /src | |
parent | 5f57935678613334bfa18ee547cb1f22a3a0a7dd (diff) | |
download | coreutils-b35bd50ce62fbb98984560177198b94a7de46d00.tar.xz |
* NEWS: Fix cp --sparse so that it preserves tail-end sparseness, even
when the file's apparent size is not a multiple of its block size.
* src/copy.c (copy_reg): Don't write a NUL before calling ftruncate.
For some file sizes, writing that single byte would unnecessarily
waste a few file blocks. That write may have been necessary in the
early days of Linux, but now, removing it should be safe.
Based on a patch by Alan Curry: <http://bugs.debian.org/370792>
* tests/cp/sparse: New test for the above.
* tests/cp/Makefile.am (TESTS): Add sparse.
* tests/sparse-file: New file, essence factored out of...
* tests/du/8gb: ... here. Use the new script.
Diffstat (limited to 'src')
-rw-r--r-- | src/copy.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/src/copy.c b/src/copy.c index 0a3f9e504..e11dd77f8 100644 --- a/src/copy.c +++ b/src/copy.c @@ -461,21 +461,21 @@ copy_reg (char const *src_name, char const *dst_name, } } - /* If the file ends with a `hole', something needs to be written at - the end. Otherwise the kernel would truncate the file at the end - of the last write operation. */ + /* If the file ends with a `hole', we need to do something to record + the length of the file. On modern systems, calling ftruncate does + the job. On systems without native ftruncate support, we have to + write a byte at the ending position. Otherwise the kernel would + truncate the file at the end of the last write operation. */ if (last_write_made_hole) { -#if HAVE_FTRUNCATE - /* Write a null character and truncate it again. */ - if (full_write (dest_desc, "", 1) != 1 - || ftruncate (dest_desc, n_read_total) < 0) -#else - /* Seek backwards one character and write a null. */ - if (lseek (dest_desc, (off_t) -1, SEEK_CUR) < 0L - || full_write (dest_desc, "", 1) != 1) -#endif + if (HAVE_FTRUNCATE + ? /* ftruncate sets the file size, + so there is no need for a write. */ + ftruncate (dest_desc, n_read_total) < 0 + : /* Seek backwards one character and write a null. */ + (lseek (dest_desc, (off_t) -1, SEEK_CUR) < 0L + || full_write (dest_desc, "", 1) != 1)) { error (0, errno, _("writing %s"), quote (dst_name)); return_val = false; |