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.
This commit is contained in:
Jim Meyering
2006-06-08 20:13:37 +00:00
parent cad27cdc2e
commit 790892db65
5 changed files with 88 additions and 9 deletions

View File

@@ -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.

4
NEWS
View File

@@ -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

View File

@@ -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;
}

View File

@@ -18,6 +18,7 @@ TESTS_ENVIRONMENT = \
# will execute the test script rather than the standard utility.
TESTS = \
cat-proc \
base64 \
basename \
close-stdout \

42
tests/misc/cat-proc Executable file
View File

@@ -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