This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 73c14db2052dad87585396159f8ffb724698d0a4
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Oct 29 19:58:17 2026 +0100

    fs/vfs: Fail lseek() of a pipe, a FIFO or a socket with ESPIPE.
    
    The pipe, FIFO and socket drivers have no seek method, so lseek() set
    the common file position and returned it: lseek(fd, 10, SEEK_CUR) of a
    pipe returned 10, and SEEK_END failed with ENOSYS.  POSIX specifies
    ESPIPE for a pipe, a FIFO or a socket.  A program that skips data in a
    stream with lseek() and reads it only when lseek() fails took the skip
    for done and lost the data.
    
    Return -ESPIPE for these inodes (INODE_IS_NOSEEK()) before the seek
    method or the common file position.  pread(), pwrite() and sendfile()
    with an offset then also fail with ESPIPE for them, as POSIX and Linux
    specify.
    
    The sendfile() path of a TCP socket (CONFIG_NET_SENDFILE) seeks its input
    to send data again.  For an input that cannot seek, sendfile() does not
    use that path: it uses the read and write copy.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 fs/vfs/fs_lseek.c    | 11 +++++++++++
 fs/vfs/fs_sendfile.c |  7 ++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/fs/vfs/fs_lseek.c b/fs/vfs/fs_lseek.c
index 2d1ceeb549b..0b6061e35bf 100644
--- a/fs/vfs/fs_lseek.c
+++ b/fs/vfs/fs_lseek.c
@@ -64,6 +64,17 @@ off_t file_seek(FAR struct file *filep, off_t offset, int 
whence)
   DEBUGASSERT(filep);
   inode =  filep->f_inode;
 
+  /* A pipe, a FIFO or a socket has no file position (POSIX: ESPIPE).
+   * Without this, the common file position below took any offset, and a
+   * program that skips data with lseek() and reads only when it fails
+   * lost the data.
+   */
+
+  if (inode != NULL && INODE_IS_NOSEEK(inode))
+    {
+      return -ESPIPE;
+    }
+
   /* Invoke the file seek method if available */
 
   if (inode && inode->u.i_ops && inode->u.i_ops->seek)
diff --git a/fs/vfs/fs_sendfile.c b/fs/vfs/fs_sendfile.c
index ea14c03dbda..397d0341afd 100644
--- a/fs/vfs/fs_sendfile.c
+++ b/fs/vfs/fs_sendfile.c
@@ -264,7 +264,12 @@ ssize_t file_sendfile(FAR struct file *outfile, FAR struct 
file *infile,
   FAR struct socket *psock;
 
   psock = file_socket(outfile);
-  if (psock != NULL)
+
+  /* psock_sendfile() seeks the input to send its data again: an input that
+   * cannot seek (a pipe, a FIFO or a socket) uses the slow path.
+   */
+
+  if (psock != NULL && !INODE_IS_NOSEEK(infile->f_inode))
     {
       /* Then let psock_sendfile do the work. */
 

Reply via email to