od --skip (-j) works even on files in /proc, when the kernel lies

* src/od.c (skip): Don't let kernel misinformation (nonempty files
in /proc with stat.st_size == 0) make "od -j N" misbehave.
Patch by Paul Eggert.
* NEWS: Document this work-around.
* tests/misc/od-zero-len: New file, test for the above.
This commit is contained in:
Jim Meyering 2007-08-15 22:44:45 +02:00
parent 9ee7933b5c
commit 535a9fe512
4 changed files with 69 additions and 3 deletions

View File

@ -1,5 +1,12 @@
2007-08-15 Jim Meyering <jim@meyering.net>
od --skip (-j) works even on files in /proc, when the kernel lies
* src/od.c (skip): Don't let kernel misinformation (nonempty files
in /proc with stat.st_size == 0) make "od -j N" misbehave.
Patch by Paul Eggert.
* NEWS: Document this work-around.
* tests/misc/od-zero-len: New file, test for the above.
* src/printf.c (usage): Adjust summary to also mention OPTIONs.
From Karl Berry.

4
NEWS
View File

@ -98,6 +98,10 @@ GNU coreutils NEWS -*- outline -*-
ln=target attribute) would mistakenly output the string "target"
before the name of each symlink. [introduced in coreutils-6.0]
od's --skip (-j) option now works even when the kernel says that a
nonempty regular file has stat.st_size = 0. This happens at least
with files in /proc and linux-2.6.22.
"od -j L FILE" had a bug: when the number of bytes to skip, L, is exactly
the same as the length of FILE, od would skip *no* bytes. When the number
of bytes to skip is exactly the sum of the lengths of the first N files,

View File

@ -1035,9 +1035,11 @@ skip (uintmax_t n_skip)
/* The st_size field is valid only for regular files
(and for symbolic links, which cannot occur here).
If the number of bytes left to skip is larger than
the size of the current file, we can decrement
n_skip and go on to the next file. */
if (S_ISREG (file_stats.st_mode) && 0 <= file_stats.st_size)
the size of the current file, we can decrement n_skip
and go on to the next file. Skip this optimization also
when st_size is 0, because some kernels report that
nonempty files in /proc have st_size == 0. */
if (S_ISREG (file_stats.st_mode) && 0 < file_stats.st_size)
{
if ((uintmax_t) file_stats.st_size < n_skip)
n_skip -= file_stats.st_size;

53
tests/misc/od-zero-len Executable file
View File

@ -0,0 +1,53 @@
#!/bin/sh
# ensure that od -j doesn't improperly fseek across a nonempty file in /proc
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test "$VERBOSE" = yes; then
set -x
od --version
fi
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
printf e > f2 || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
# Use a file in /proc whose size is not likely to
# change between the wc and od invocations.
f=/proc/version
test -r $f || f=empty
fail=0
n=`wc -c < $f` || fail=1
od -An -c -j $n $f f2 > out || fail=1
echo ' e' > exp || fail=1
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail