1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-20 18:56:39 +02:00

cat: don’t trust st_size on /proc files

* src/cat.c (main):
Improve test for when copying will exhaust the output device.
Do not rely on st_size, which is unreliable in /proc.
Use lseek instead; this is good enough here.
* tests/cat/cat-self.sh: Test the relaxation of the heuristic
for self-copying.
This commit is contained in:
Paul Eggert
2024-04-06 15:13:23 -07:00
parent 8f3989d586
commit 225cb8d747
2 changed files with 41 additions and 10 deletions

View File

@@ -645,9 +645,10 @@ main (int argc, char **argv)
/* Optimal size of i/o operations of output. */
idx_t outsize = io_blksize (&stat_buf);
/* Device and I-node number of the output. */
/* Device, I-node number and lazily-acquired flags of the output. */
dev_t out_dev = stat_buf.st_dev;
ino_t out_ino = stat_buf.st_ino;
int out_flags = -2;
/* True if the output is a regular file. */
bool out_isreg = S_ISREG (stat_buf.st_mode) != 0;
@@ -701,17 +702,27 @@ main (int argc, char **argv)
fdadvise (input_desc, 0, 0, FADVISE_SEQUENTIAL);
/* Don't copy a nonempty regular file to itself, as that would
merely exhaust the output device. It's better to catch this
error earlier rather than later. */
/* Don't copy a file to itself if that would merely exhaust the
output device. It's better to catch this error earlier
rather than later. */
if (out_isreg
&& stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino
&& lseek (input_desc, 0, SEEK_CUR) < stat_buf.st_size)
if (stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino)
{
error (0, 0, _("%s: input file is output file"), quotef (infile));
ok = false;
goto contin;
if (out_flags < -1)
out_flags = fcntl (STDOUT_FILENO, F_GETFL);
bool exhausting = 0 <= out_flags && out_flags & O_APPEND;
if (!exhausting)
{
off_t in_pos = lseek (input_desc, 0, SEEK_CUR);
if (0 <= in_pos)
exhausting = in_pos < lseek (STDOUT_FILENO, 0, SEEK_CUR);
}
if (exhausting)
{
error (0, 0, _("%s: input file is output file"), quotef (infile));
ok = false;
goto contin;
}
}
/* Pointer to the input buffer. */