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 <egg...@cs.ucla.edu> 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