summaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-rw-r--r--src/cat.c32
1 files changed, 24 insertions, 8 deletions
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;
}