Subject: bug#36291: closed (Re: bug#36291: od --skip-bytes reads everything from the very beginning)

From: [email-masked] (GNU bug Tracking System)
Date: Thu, 20 Jun 2019 01:53:02 +0000

Your bug report

#36291: od --skip-bytes reads everything from the very beginning

which was filed against the coreutils package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
36291: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=36291
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#36291: od --skip-bytes reads everything from the very beginning
From: Paul Eggert <[email-masked]>
To: Pádraig Brady <[email-masked]>
Cc: [email-masked],Szőts Ákos <[email-masked]>
Date: Wed, 19 Jun 2019 18:52:01 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

On 6/19/19 12:42 PM, Pádraig Brady wrote:
> Maybe we should relax the cases we do read() for,
> and try to seek in block/character special files,
> falling back to read() where that fails?

Sure, that's easy enough. I installed the attached patch and am marking 
this bug report as done.

From ea353844d8642b5533cbc713e0cec46addbf3907 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Wed, 19 Jun 2019 18:46:57 -0700
Subject: [PATCH] od: use fseek on non-regular files
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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     | 3 +++
 src/od.c | 8 ++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index d30711bc6..fd0543351 100644
--- 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
diff --git a/src/od.c b/src/od.c
index 1a89542ee..75a402004 100644
--- 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.  */
-- 
2.21.0

Subject: od --skip-bytes reads everything from the very beginning
From: Szőts Ákos <[email-masked]>
To: [email-masked]
Date: Wed, 19 Jun 2019 10:20:10 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Dear List members,

I've recently discovered that od "--skip-bytes" feature doesn't
actually seek into the file but rather it reads everything from the
very beginning until the given offset is reached.

This can be problematic in two cases:
 - when speed matters, and
 - when parts of the file is read-protected (like in the case of
/dev/mem when CONFIG_STRICT_DEVMEM=y, which is usually the case). In
this example od will reach an area in /dev/mem which is read-protected
(even for root) and will report back EPERM before it could reach the
requested, and allowed, memory area. The error report will be
misleading since the resulting EPERM is not because the requested area
is protected (as suggested by the error message) but because of the
inner mechanics of the program.

In contrary, hexdump jumps to the address directly.

You can test it by running the following two commands:
- strace hexdump --skip 0xFE000124 --length 1 /dev/sda
- strace od --skip-bytes 0xFE000124 --read-bytes 1 /dev/sda

I don't know whether this behaviour is intended but if so, could you
please expand the documentation a little bit with this additional
information?

od version: od (GNU coreutils) 8.30, openSUSE Tumbleweed, x64

Thank you and all the best,

Ákos