]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
maint: don’t lseek memory objects
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 14 Jul 2025 23:41:05 +0000 (16:41 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 4 Aug 2025 02:48:04 +0000 (19:48 -0700)
This affects behavior only on memory objects, which are not in Linux.
Formerly the code would use lseek on these objects,
but POSIX says the result of lseek is unspecified on them,
and in QNX lseek has undefined behavior on typed memory objects.
* src/head.c (elide_tail_bytes_file, elide_tail_lines_file):
Omit unnecessary uses of presume_input_pipe.
Improve some out-of-date comments.
(head): Do not assume a file is seekable merely because its
st_size is usable.  Instead, seek only on regular files.
* src/od.c (skip): Do not seek on memory objects.

src/head.c
src/od.c

index 21ff87df62eaa30b99628b81325a361b0d6f6803..1d83d2f1fcd37af788975ae94066319fd60829ab 100644 (file)
@@ -452,8 +452,8 @@ elide_tail_bytes_pipe (char const *filename, int fd, uintmax_t n_elide,
 }
 
 /* For the file FILENAME with descriptor FD, output all but the last N_ELIDE
-   bytes.  If SIZE is nonnegative, this is a regular file positioned
-   at CURRENT_POS with SIZE bytes.  Return true on success.
+   bytes.  If CURRENT_POS is nonnegative, this is a regular file positioned
+   at CURRENT_POS.  The file's status is ST.  Return true on success.
    Give a diagnostic and return false upon error.  */
 
 /* NOTE: if the input file shrinks by more than N_ELIDE bytes between
@@ -464,7 +464,7 @@ elide_tail_bytes_file (char const *filename, int fd, uintmax_t n_elide,
                        struct stat const *st, off_t current_pos)
 {
   off_t size = st->st_size;
-  if (presume_input_pipe || current_pos < 0 || size <= STP_BLKSIZE (st))
+  if (current_pos < 0 || size <= STP_BLKSIZE (st))
     return elide_tail_bytes_pipe (filename, fd, n_elide, current_pos);
   else
     {
@@ -745,16 +745,16 @@ elide_tail_lines_seekable (char const *pretty_filename, int fd,
 }
 
 /* For the file FILENAME with descriptor FD, output all but the last N_ELIDE
-   lines.  If SIZE is nonnegative, this is a regular file positioned
-   at START_POS with SIZE bytes.  Return true on success.
-   Give a diagnostic and return nonzero upon error.  */
+   lines.  If CURRENT_POS is nonnegative, this is a regular file positioned
+   at CURRENT_POS.  The file's status is ST.  Return true on success.
+   Give a diagnostic and return false upon error.  */
 
 static bool
 elide_tail_lines_file (char const *filename, int fd, uintmax_t n_elide,
                        struct stat const *st, off_t current_pos)
 {
   off_t size = st->st_size;
-  if (presume_input_pipe || current_pos < 0 || size <= STP_BLKSIZE (st))
+  if (current_pos < 0 || size <= STP_BLKSIZE (st))
     return elide_tail_lines_pipe (filename, fd, n_elide, current_pos);
   else
     {
@@ -838,7 +838,7 @@ head (char const *filename, int fd, uintmax_t n_units, bool count_lines,
                  quoteaf (filename));
           return false;
         }
-      if (! presume_input_pipe && usable_st_size (&st))
+      if (! presume_input_pipe && S_ISREG (st.st_mode))
         {
           current_pos = elseek (fd, 0, SEEK_CUR, filename);
           if (current_pos < 0)
index be7d0675192b37bcd0dc1e538915e444436bcc8f..d38a4c38035a2de58aad7b72505d4d9d34b3665a 100644 (file)
--- a/src/od.c
+++ b/src/od.c
@@ -1109,8 +1109,6 @@ skip (intmax_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
@@ -1118,7 +1116,8 @@ skip (intmax_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_size && STP_BLKSIZE (&file_stats) < file_stats.st_size)
+          if (S_ISREG (file_stats.st_mode)
+              && STP_BLKSIZE (&file_stats) < file_stats.st_size)
             {
               if (file_stats.st_size < n_skip)
                 n_skip -= file_stats.st_size;
@@ -1133,11 +1132,14 @@ skip (intmax_t n_skip)
                 }
             }
 
-          else if (!usable_size && fseeko (in_stream, n_skip, SEEK_CUR) == 0)
+          else if (! (S_ISREG (file_stats.st_mode)
+                      || S_TYPEISSHM (&file_stats)
+                      || S_TYPEISTMO (&file_stats))
+                   && 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,
+          /* If it's neither a seekable file with unusable size, nor a
+             regular file so large it can't be in a proc-like file system,
              position the file pointer by reading.  */
 
           else