Thanks for reporting that, I forgot that the code defaulted SEEK_HOLE
but not SEEK_DATA. The first attached patch should fix it. The second
one should improve performance further on Solaris for files that end in
holes.
>From 78497a2aaaaeae439f9546223b45b3b553146f36 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Wed, 17 Sep 2014 12:33:55 -0700
Subject: [PATCH 1/2] grep: port to platforms lacking SEEK_DATA
Reported by Norihiro Tanaka in: http://bugs.gnu.org/18454#38
* src/grep.c (SEEK_DATA): Default to SEEK_SET if not defined.
(SEEK_HOLE): Move to top level, and default it to SEEK_SET.
(file_textbin): Adjust to new default.
(fillbuf): Don't bother with SEEK_DATA if it defaults to SEEK_SET.
---
src/grep.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/grep.c b/src/grep.c
index 3e94804..a08fa41 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -415,6 +415,15 @@ usable_st_size (struct stat const *st)
return S_ISREG (st->st_mode) || S_TYPEISSHM (st) || S_TYPEISTMO (st);
}
+/* Lame substitutes for SEEK_DATA and SEEK_HOLE on platforms lacking them.
+ Do not rely on these finding data or holes if they equal SEEK_SET. */
+#ifndef SEEK_DATA
+enum { SEEK_DATA = SEEK_SET };
+#endif
+#ifndef SEEK_HOLE
+enum { SEEK_HOLE = SEEK_SET };
+#endif
+
/* Functions we'll use to search. */
typedef void (*compile_fp_t) (char const *, size_t);
typedef size_t (*execute_fp_t) (char const *, size_t, size_t *, char const *);
@@ -474,10 +483,6 @@ buffer_textbin (char const *buf, size_t size)
static enum textbin
file_textbin (char const *buf, size_t bufsize, int fd, struct stat const *st)
{
- #ifndef SEEK_HOLE
- enum { SEEK_HOLE = SEEK_END };
- #endif
-
enum textbin textbin = buffer_textbin (buf, bufsize);
if (textbin_is_binary (textbin))
return textbin;
@@ -488,7 +493,7 @@ file_textbin (char const *buf, size_t bufsize, int fd, struct stat const *st)
return textbin == TEXTBIN_UNKNOWN ? TEXTBIN_BINARY : textbin;
/* If the file has holes, it must contain a null byte somewhere. */
- if (SEEK_HOLE != SEEK_END && eolbyte)
+ if (SEEK_HOLE != SEEK_SET && eolbyte)
{
off_t cur = bufsize;
if (O_BINARY || fd == STDIN_FILENO)
@@ -713,7 +718,7 @@ fillbuf (size_t save, struct stat const *st)
break;
totalnl = add_count (totalnl, fillsize);
- if (!seek_data_failed)
+ if (SEEK_DATA != SEEK_SET && !seek_data_failed)
{
off_t data_start = lseek (bufdesc, bufoffset, SEEK_DATA);
if (data_start < 0)
--
1.9.3
>From 0d6febac38c03391d7eecb5335620a0ec5ba8278 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Wed, 17 Sep 2014 12:53:17 -0700
Subject: [PATCH 2/2] grep: speed up processing of holes before EOF on Solaris
* src/grep.c (fillbuf): If SEEK_DATA fails with errno == ENXIO,
skip over the hole at EOF.
---
src/grep.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/grep.c b/src/grep.c
index a08fa41..35d3358 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -720,7 +720,12 @@ fillbuf (size_t save, struct stat const *st)
if (SEEK_DATA != SEEK_SET && !seek_data_failed)
{
+ /* Solaris SEEK_DATA fails with errno == ENXIO in a hole at EOF. */
off_t data_start = lseek (bufdesc, bufoffset, SEEK_DATA);
+ if (data_start < 0 && errno == ENXIO
+ && usable_st_size (st) && bufoffset < st->st_size)
+ data_start = lseek (bufdesc, 0, SEEK_END);
+
if (data_start < 0)
seek_data_failed = true;
else
--
1.9.3