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

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

commit 4cec5015847f8f6edde9eb35fa585d3e5421af3e
Author: Xiang Xiao <[email protected]>
AuthorDate: Fri Sep 11 02:22:19 2026 +0800

    fs/aio: fix aio_read/aio_write return values per POSIX
    
    Per POSIX, aio_read() and aio_write() must return -1 and set errno to
    EINVAL when the request cannot be queued (aio_reqprio < 0,
    aio_offset < 0), and the error must also be retrievable via
    aio_error().  Conversely, when queuing fails with a bad file
    descriptor, the error belongs to the asynchronous operation: the
    functions must return 0 and report EBADF through aio_error().
    
    - Merge the offset/reqprio checks and return ERROR with errno set,
      after storing the result in aio_result for aio_error().
    - Drop the aio_fildes < 0 early return: a closed descriptor is now
      caught by fcntl()/aio_queue() and reported through aio_result with
      the function returning OK.
    - aio_error(): report -EINVAL (failed validation) through errno
      instead of returning it as an error value.
    
    Signed-off-by: tengshuangshuang <[email protected]>
---
 fs/aio/aio_read.c         | 27 ++++++---------------------
 fs/aio/aio_write.c        | 26 +++++---------------------
 libs/libc/aio/aio_error.c | 11 +++++++++++
 3 files changed, 22 insertions(+), 42 deletions(-)

diff --git a/fs/aio/aio_read.c b/fs/aio/aio_read.c
index 88d541556c7..670784d4301 100644
--- a/fs/aio/aio_read.c
+++ b/fs/aio/aio_read.c
@@ -222,32 +222,17 @@ int aio_read(FAR struct aiocb *aiocbp)
 
   DEBUGASSERT(aiocbp);
 
-  if (aiocbp->aio_reqprio < 0)
-    {
-      set_errno(EINVAL);
-      return ERROR;
-    }
-
-  if (aiocbp->aio_fildes < 0)
-    {
-      /* the EBADF should be collected by aio_error(), we need return OK at
-       * here
-       */
-
-      aiocbp->aio_result = -EBADF;
-      return OK;
-    }
-
   /* for aio_read, the aio_offset should be large or equal than 0 */
 
-  if (aiocbp->aio_offset < 0)
+  if (aiocbp->aio_offset < 0 || aiocbp->aio_reqprio < 0)
     {
-      /* the EINVAL should be collected by aio_error(), we need to return OK
-       * here
+      /* the EINVAL should be collected by aio_error(), we need to return
+       * ERROR here
        */
 
       aiocbp->aio_result = -EINVAL;
-      return OK;
+      set_errno(EINVAL);
+      return ERROR;
     }
 
   /* The result -EINPROGRESS means that the transfer has not yet completed */
@@ -265,7 +250,7 @@ int aio_read(FAR struct aiocb *aiocbp)
       /* The errno has already been set (probably EBADF) */
 
       aiocbp->aio_result = -get_errno();
-      return ERROR;
+      return OK;
     }
 
   /* Defer the work to the worker thread */
diff --git a/fs/aio/aio_write.c b/fs/aio/aio_write.c
index 6c5b3f37dcf..7c2b425a125 100644
--- a/fs/aio/aio_write.c
+++ b/fs/aio/aio_write.c
@@ -253,35 +253,19 @@ int aio_write(FAR struct aiocb *aiocbp)
 
   DEBUGASSERT(aiocbp);
 
-  if (aiocbp->aio_reqprio < 0)
+  if (aiocbp->aio_offset < 0 || aiocbp->aio_reqprio < 0)
     {
+      aiocbp->aio_result = -EINVAL;
       set_errno(EINVAL);
       return ERROR;
     }
 
-  if (aiocbp->aio_offset < 0)
-    {
-      aiocbp->aio_result = -EINVAL;
-      return OK;
-    }
-
-  if (aiocbp->aio_fildes < 0)
-    {
-      /* for EBADF, the aio_write do not return error directly, but using
-       * aio_error to return this error code
-       */
-
-      aiocbp->aio_result = -EBADF;
-      return OK;
-    }
-
   /* the aio_fildes that transferred in may be opened with O_RDONLY, for this
-   * case, we need to return OK directly, and using the aio_error to collect
-   * the EBADF error code
+   * case, we need to return OK directly, and set the EBADF error code
    */
 
   flags = fcntl(aiocbp->aio_fildes, F_GETFL);
-  if ((flags & O_ACCMODE) == O_RDONLY)
+  if (flags == ERROR || (flags & O_ACCMODE) == O_RDONLY)
     {
       aiocbp->aio_result = -EBADF;
       return OK;
@@ -302,7 +286,7 @@ int aio_write(FAR struct aiocb *aiocbp)
       /* The errno has already been set (probably EBADF) */
 
       aiocbp->aio_result = -get_errno();
-      return ERROR;
+      return OK;
     }
 
   /* Defer the work to the worker thread */
diff --git a/libs/libc/aio/aio_error.c b/libs/libc/aio/aio_error.c
index 8f3a856b22e..dced059ba87 100644
--- a/libs/libc/aio/aio_error.c
+++ b/libs/libc/aio/aio_error.c
@@ -98,6 +98,17 @@ int aio_error(FAR const struct aiocb *aiocbp)
       return EINVAL;
     }
 
+  if (aiocbp->aio_offset < 0)
+    {
+      return -aiocbp->aio_result;
+    }
+
+  if (aiocbp->aio_result == -EINVAL)
+    {
+      set_errno(EINVAL);
+      return ERROR;
+    }
+
   if (aiocbp->aio_result < 0)
     {
       return -aiocbp->aio_result;

Reply via email to