summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2006-06-08 20:13:37 +0000
committerJim Meyering <jim@meyering.net>2006-06-08 20:13:37 +0000
commit790892db657ac79b0ba5f7a69cc7e70eb4fed8e0 (patch)
tree6d768a6a1af6cab8a813c1173dddc93c352f4751
parentcad27cdc2ea46ec401b71b76a92fcf3bc1d094e0 (diff)
downloadcoreutils-790892db657ac79b0ba5f7a69cc7e70eb4fed8e0.tar.xz
Ensure that cat works with any of the options, -A -v -e -E -T,
when applied to files in /proc and /sys, even when the FIONREAD ioctl produces nonsensical results. Before this change, cat would produce no output (or truncated output), for some linux kernels. * src/cat.c (write_pending): New function, factored out of cat. (cat): Also interpret a negative ioctl/FIONREAD count as indicating that there are bytes to read. Some versions of linux-2.6.16 do that. Write any pending output before returning. Reported by Dan Jacobson in <http://bugs.debian.org/370583>. * NEWS: Mention this bug fix. * tests/misc/cat-proc: New file. Test for the above. * tests/misc/Makefile.am (TESTS): Add cat-proc.
-rw-r--r--ChangeLog18
-rw-r--r--NEWS4
-rw-r--r--src/cat.c32
-rw-r--r--tests/misc/Makefile.am1
-rwxr-xr-xtests/misc/cat-proc42
5 files changed, 88 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 0036b94b2..805965d75 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,23 @@
-2006-06-07 Paul Eggert <eggert@cs.ucla.edu>
+2006-06-08 Jim Meyering <jim@meyering.net>
* Version 6.0-cvs.
+ Ensure that cat works with any of the options, -A -v -e -E -T,
+ when applied to files in /proc and /sys, even when the FIONREAD
+ ioctl produces nonsensical results. Before this change, cat would
+ produce no output (or truncated output), for some linux kernels.
+
+ * src/cat.c (write_pending): New function, factored out of cat.
+ (cat): Also interpret a negative ioctl/FIONREAD count as indicating
+ that there are bytes to read. Some versions of linux-2.6.16 do that.
+ Write any pending output before returning.
+ Reported by Dan Jacobson in <http://bugs.debian.org/370583>.
+ * NEWS: Mention this bug fix.
+ * tests/misc/cat-proc: New file. Test for the above.
+ * tests/misc/Makefile.am (TESTS): Add cat-proc.
+
+2006-06-07 Paul Eggert <eggert@cs.ucla.edu>
+
* src/expr.c (eval4): Detect overflow properly when multiplying
INTMAX_MIN * -1.
diff --git a/NEWS b/NEWS
index be511eb25..fdca45225 100644
--- a/NEWS
+++ b/NEWS
@@ -138,6 +138,10 @@ GNU coreutils NEWS -*- outline -*-
** Bug fixes
+ cat with any of the options, -A -v -e -E -T, when applied to a
+ file in /proc or /sys (linux-specific), would truncate its output,
+ usually printing nothing.
+
cp -p would fail in a /proc-less chroot, on some systems
When `cp -RL' encounters the same directory more than once in the
diff --git a/src/cat.c b/src/cat.c
index b08e91e7d..ec2c52885 100644
--- a/src/cat.c
+++ b/src/cat.c
@@ -1,5 +1,5 @@
/* cat -- concatenate files and print on the standard output.
- Copyright (C) 88, 90, 91, 1995-2005 Free Software Foundation, Inc.
+ Copyright (C) 88, 90, 91, 1995-2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -195,6 +195,22 @@ simple_cat (
}
}
+/* Write any pending output to STDOUT_FILENO.
+ Pending is defined to be the *BPOUT - OUTBUF bytes starting at OUTBUF.
+ Then set *BPOUT to OUTPUT if it's not already that value. */
+
+static inline void
+write_pending (char *outbuf, char **bpout)
+{
+ size_t n_write = *bpout - outbuf;
+ if (0 < n_write)
+ {
+ if (full_write (STDOUT_FILENO, outbuf, n_write) != n_write)
+ error (EXIT_FAILURE, errno, _("write error"));
+ *bpout = outbuf;
+ }
+}
+
/* Cat the file behind INPUT_DESC to the file behind OUTPUT_DESC.
Return true if successful.
Called if any option more than -u was specified.
@@ -291,6 +307,7 @@ cat (
if (bpin > eob)
{
+ bool input_pending = false;
#ifdef FIONREAD
int n_to_read = 0;
@@ -318,15 +335,12 @@ cat (
return false;
}
}
- if (n_to_read == 0)
+ if (n_to_read != 0)
+ input_pending = true;
#endif
- {
- size_t n_write = bpout - outbuf;
- if (full_write (STDOUT_FILENO, outbuf, n_write) != n_write)
- error (EXIT_FAILURE, errno, _("write error"));
- bpout = outbuf;
- }
+ if (input_pending)
+ write_pending (outbuf, &bpout);
/* Read more input into INBUF. */
@@ -334,11 +348,13 @@ cat (
if (n_read == SAFE_READ_ERROR)
{
error (0, errno, "%s", infile);
+ write_pending (outbuf, &bpout);
newlines2 = newlines;
return false;
}
if (n_read == 0)
{
+ write_pending (outbuf, &bpout);
newlines2 = newlines;
return true;
}
diff --git a/tests/misc/Makefile.am b/tests/misc/Makefile.am
index 5f6b07a92..696b9fdc1 100644
--- a/tests/misc/Makefile.am
+++ b/tests/misc/Makefile.am
@@ -18,6 +18,7 @@ TESTS_ENVIRONMENT = \
# will execute the test script rather than the standard utility.
TESTS = \
+ cat-proc \
base64 \
basename \
close-stdout \
diff --git a/tests/misc/cat-proc b/tests/misc/cat-proc
new file mode 100755
index 000000000..69e206514
--- /dev/null
+++ b/tests/misc/cat-proc
@@ -0,0 +1,42 @@
+#!/bin/sh
+# Ensure that cat -E produces same output as cat, module `$'s,
+# even when applied to a file in /proc.
+
+if test "$VERBOSE" = yes; then
+ set -x
+ cat --version
+fi
+
+pwd=`pwd`
+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
+trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+framework_failure=0
+mkdir -p $tmp || framework_failure=1
+cd $tmp || framework_failure=1
+
+if test $framework_failure = 1; then
+ echo "$0: failure in testing framework" 1>&2
+ (exit 1); exit 1
+fi
+
+f=/proc/cpuinfo
+test -f $f \
+ || {
+ echo "$0: no $f skipping this test" 1>&2
+ (exit 77); exit 77
+ }
+
+fail=0
+
+# Yes, parts of /proc/cpuinfo might change between cat runs.
+# If that happens, consider choosing a file that's less likely to change,
+# or just filter out the changing lines.
+cat -E $f | tr -d '$' > out || fail=1
+cat $f | tr -d '$' > exp || fail=1
+
+cmp out exp || fail=1
+test $fail = 1 && diff out exp 2> /dev/null
+
+(exit $fail); exit $fail