summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2010-05-28 19:25:23 +0100
committerPádraig Brady <P@draigBrady.com>2010-05-29 10:45:13 +0100
commit200501052edde61747a16cd0af60fa925ef87bfb (patch)
treea492c23081935c681ca94757e6c64424efa7c851
parent81b7585ad19e1ee0a1a43dda44dd21f11bfd6e86 (diff)
downloadcoreutils-200501052edde61747a16cd0af60fa925ef87bfb.tar.xz
truncate: improve handling of non regular files
Previously we copied `dd` and suppressed error messages when truncating neither regular files or shared mem objects. This was valid for `dd`, as truncation is ancillary to copying it may also do, but for `truncate` we should display all errors. Also we used the st_size from non regular files which is undefined, so we display an error when the user tries this. * src/truncate (do_truncate): Error when referencing the size of non regular files or non shared memory objects. Display all errors returned by ftruncate(). (main): Error when referencing the size of non regular files or non shared memory objects. Don't suppress error messages for any file types that can't be opened for writing. * tests/misc/truncate-dir-fail: Check that referencing the size of a directory is not supported. * tests/misc/truncate-fifo: Ensure the test doesn't hang by using the `timeout` command. Don't test the return from running ftruncate on the fifo as it's system dependent as to whether this fails or not. NEWS: Mention the change in behavior. Reported by Jim Meyering.
-rw-r--r--NEWS2
-rw-r--r--src/truncate.c59
-rwxr-xr-xtests/misc/truncate-dir-fail3
-rwxr-xr-xtests/misc/truncate-fifo8
4 files changed, 27 insertions, 45 deletions
diff --git a/NEWS b/NEWS
index 7a294f4a2..7d3343ba6 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ GNU coreutils NEWS -*- outline -*-
sort -g now uses long doubles for greater range and precision.
truncate now supports setting file sizes relative to a reference file.
+ Also errors are no longer suppressed for unsupported file types, and
+ relative sizes are restricted to supported file types.
* Noteworthy changes in release 8.5 (2010-04-23) [stable]
diff --git a/src/truncate.c b/src/truncate.c
index 08090ab20..493f7f791 100644
--- a/src/truncate.c
+++ b/src/truncate.c
@@ -160,21 +160,21 @@ do_ftruncate (int fd, char const *fname, off_t ssize, off_t rsize,
{
uintmax_t const fsize = rsize < 0 ? sb.st_size : rsize;
- if (rsize < 0 && sb.st_size < 0)
+ if (rsize < 0) /* fstat used above to get size. */
{
- /* Complain only for a regular file, a directory,
- or a shared memory object, as POSIX 1003.1-2004 specifies
- ftruncate's behavior only for these file types. */
- if (S_ISREG (sb.st_mode) || S_ISDIR (sb.st_mode)
- || S_TYPEISSHM (&sb))
+ if (!S_ISREG (sb.st_mode) && !S_TYPEISSHM (&sb))
{
- /* overflow is the only reason I can think
- this would ever go negative for the above types */
+ error (0, 0, _("cannot get the size of %s"), quote (fname));
+ return 1;
+ }
+ if (sb.st_size < 0)
+ {
+ /* Sanity check. Overflow is the only reason I can think
+ this would ever go negative. */
error (0, 0, _("%s has unusable, apparently negative size"),
quote (fname));
return 1;
}
- return 0;
}
if (rel_mode == rm_min)
@@ -215,26 +215,10 @@ do_ftruncate (int fd, char const *fname, off_t ssize, off_t rsize,
if (ftruncate (fd, nsize) == -1) /* note updates mtime & ctime */
{
- /* Complain only when ftruncate fails on a regular file, a
- directory, or a shared memory object, as POSIX 1003.1-2004
- specifies ftruncate's behavior only for these file types.
- For example, do not complain when Linux kernel 2.4 ftruncate
- fails on /dev/fd0. */
- int const ftruncate_errno = errno;
- if (fstat (fd, &sb) != 0)
- {
- error (0, errno, _("cannot fstat %s"), quote (fname));
- return 1;
- }
- else if (S_ISREG (sb.st_mode) || S_ISDIR (sb.st_mode)
- || S_TYPEISSHM (&sb))
- {
- error (0, ftruncate_errno,
- _("truncating %s at %" PRIdMAX " bytes"), quote (fname),
- (intmax_t) nsize);
- return 1;
- }
- return 0;
+ error (0, errno,
+ _("failed to truncate %s at %" PRIdMAX " bytes"), quote (fname),
+ (intmax_t) nsize);
+ return 1;
}
return 0;
@@ -362,9 +346,13 @@ main (int argc, char **argv)
if (ref_file)
{
+ /* FIXME: Maybe support getting size of block devices. */
struct stat sb;
if (stat (ref_file, &sb) != 0)
error (EXIT_FAILURE, errno, _("cannot stat %s"), quote (ref_file));
+ if (!S_ISREG (sb.st_mode) && !S_TYPEISSHM (&sb))
+ error (EXIT_FAILURE, 0, _("cannot get the size of %s"),
+ quote (ref_file));
if (!got_size)
size = sb.st_size;
else
@@ -384,18 +372,7 @@ main (int argc, char **argv)
`truncate -s0 .` should gen EISDIR error */
if (!(no_create && errno == ENOENT))
{
- int const open_errno = errno;
- struct stat sb;
- if (stat (fname, &sb) == 0)
- {
- /* Complain only for a regular file, a directory,
- or a shared memory object, as POSIX 1003.1-2004 specifies
- ftruncate's behavior only for these file types. */
- if (!S_ISREG (sb.st_mode) && !S_ISDIR (sb.st_mode)
- && !S_TYPEISSHM (&sb))
- continue;
- }
- error (0, open_errno, _("cannot open %s for writing"),
+ error (0, errno, _("cannot open %s for writing"),
quote (fname));
errors++;
}
diff --git a/tests/misc/truncate-dir-fail b/tests/misc/truncate-dir-fail
index d2ecf2fe6..fe33857a2 100755
--- a/tests/misc/truncate-dir-fail
+++ b/tests/misc/truncate-dir-fail
@@ -26,4 +26,7 @@ fi
# truncate on dir not allowed
truncate -s+0 . && fail=1
+# getting the size of a dir is not allowed
+truncate -r. file && fail=1
+
Exit $fail
diff --git a/tests/misc/truncate-fifo b/tests/misc/truncate-fifo
index 8e2276dab..a4c36cb90 100755
--- a/tests/misc/truncate-fifo
+++ b/tests/misc/truncate-fifo
@@ -1,5 +1,5 @@
#!/bin/sh
-# Make sure truncate works on fifos without hanging or errors
+# Make sure truncate works on fifos without hanging
# Copyright (C) 2008-2010 Free Software Foundation, Inc.
@@ -23,9 +23,9 @@ fi
. $srcdir/test-lib.sh
-mkfifo_or_skip_ "fifo"
+mkfifo_or_skip_ fifo
-
-truncate -s0 "fifo" || fail=1
+timeout 10 truncate -s0 fifo
+test "$?" = 124 && fail=1
Exit $fail