]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
od: use fseek on non-regular files
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 20 Jun 2019 01:46:57 +0000 (18:46 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 20 Jun 2019 01:48:54 +0000 (18:48 -0700)
Problem reported by Szőts Ákos (Bug#36291).
* NEWS: Mention this.
* src/od.c (skip): Try fseek even on files that do not have usable
sizes, falling back on fread if fseek fails.

NEWS
src/od.c

diff --git a/NEWS b/NEWS
index d30711bc69dc130ec5fef0544e360101cb82adc3..fd0543351ecdd8cbddcb1663946f94eb3bd7d848 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,9 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** New Features
 
+  od --skip-bytes now can use lseek even if the input is not a regular
+  file, greatly improving performance in some cases.
+
   stat(1) now uses the statx() system call where available, which can
   operate more efficiently by only retrieving requested attributes.
   stat(1) also supports a new --cached= option to control cache
index 1a89542eecfb848caf276e7f59e5eafe34a314c4..75a4020047bf7831806396b971e2cf1caca2b900 100644 (file)
--- a/src/od.c
+++ b/src/od.c
@@ -1033,6 +1033,8 @@ skip (uintmax_t n_skip)
 
       if (fstat (fileno (in_stream), &file_stats) == 0)
         {
+          bool usable_size = usable_st_size (&file_stats);
+
           /* The st_size field is valid for regular files.
              If the number of bytes left to skip is larger than
              the size of the current file, we can decrement n_skip
@@ -1040,8 +1042,7 @@ skip (uintmax_t n_skip)
              when st_size is no greater than the block size, because
              some kernels report nonsense small file sizes for
              proc-like file systems.  */
-          if (usable_st_size (&file_stats)
-              && ST_BLKSIZE (file_stats) < file_stats.st_size)
+          if (usable_size && ST_BLKSIZE (file_stats) < file_stats.st_size)
             {
               if ((uintmax_t) file_stats.st_size < n_skip)
                 n_skip -= file_stats.st_size;
@@ -1056,6 +1057,9 @@ skip (uintmax_t n_skip)
                 }
             }
 
+          else if (!usable_size && fseeko (in_stream, n_skip, SEEK_CUR) == 0)
+            n_skip = 0;
+
           /* If it's not a regular file with nonnegative size,
              or if it's so small that it might be in a proc-like file system,
              position the file pointer by reading.  */