summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2006-08-19 14:01:29 +0000
committerJim Meyering <jim@meyering.net>2006-08-19 14:01:29 +0000
commitb35bd50ce62fbb98984560177198b94a7de46d00 (patch)
tree9bab2c61e3f66c9d2589b99debcb979e88d68a12 /src
parent5f57935678613334bfa18ee547cb1f22a3a0a7dd (diff)
downloadcoreutils-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.c24
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;