From: Paul Eggert Date: Thu, 20 Jun 2019 01:46:57 +0000 (-0700) Subject: od: use fseek on non-regular files X-Git-Tag: v8.32~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ae38a5995c8e8cd01a5410767db6078bef0afb5;p=thirdparty%2Fcoreutils.git od: use fseek on non-regular files 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. --- diff --git a/NEWS b/NEWS index d30711bc69..fd0543351e 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 1a89542eec..75a4020047 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. */