summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2016-11-28 17:11:18 +0000
committerPádraig Brady <P@draigBrady.com>2016-11-28 18:36:32 +0000
commit0655b86a6ebc6f1324810d504a71803aa708d162 (patch)
tree457a99f6d50d5c5f8b4a0ce13b6394503914f260
parentd8104265f229ababd5a68a46eeccbccc07e72cdc (diff)
downloadcoreutils-0655b86a6ebc6f1324810d504a71803aa708d162.tar.xz
head: fix processing of non-seekable input as seekable
* src/head.c (elide_tail_bytes_file): Ensure we don't use st_size unless we've previously used seek() to determine the CURRENT_POS in the seekable file. This was seen to cause issue on FreeBSD 11 when the pipe buffer was filled with `yes | head --lines=-0`, in which case st_size was 64KiB while ST_BLKSIZE() was 4KiB. Reported by Assaf Gordon.
-rw-r--r--NEWS4
-rw-r--r--src/head.c4
2 files changed, 6 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index e88e93214..ea84a4dba 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,10 @@ GNU coreutils NEWS -*- outline -*-
factor again outputs immediately when numbers are input interactively.
[bug introduced in coreutils-8.24]
+ head no longer tries to process non-seekable input as seekable,
+ which resulted in failures on FreeBSD 11 at least.
+ [bug introduced in coreutils-8.24]
+
install -DZ and mkdir -pZ now set default SELinux context correctly even if
two or more directories nested in each other are created and each of them
defaults to a different SELinux context.
diff --git a/src/head.c b/src/head.c
index 21ace70b4..756c978c6 100644
--- a/src/head.c
+++ b/src/head.c
@@ -465,7 +465,7 @@ elide_tail_bytes_file (const char *filename, int fd, uintmax_t n_elide,
struct stat const *st, off_t current_pos)
{
off_t size = st->st_size;
- if (presume_input_pipe || size <= ST_BLKSIZE (*st))
+ if (presume_input_pipe || current_pos < 0 || size <= ST_BLKSIZE (*st))
return elide_tail_bytes_pipe (filename, fd, n_elide, current_pos);
else
{
@@ -754,7 +754,7 @@ elide_tail_lines_file (const char *filename, int fd, uintmax_t n_elide,
struct stat const *st, off_t current_pos)
{
off_t size = st->st_size;
- if (presume_input_pipe || size <= ST_BLKSIZE (*st))
+ if (presume_input_pipe || current_pos < 0 || size <= ST_BLKSIZE (*st))
return elide_tail_lines_pipe (filename, fd, n_elide, current_pos);
else
{