mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 17:48:54 +08:00
file_readv_compat/file_writev_compat: Fix partial success handling
The problem has been inherited from the original libc readv/writev implementation. However, now it's exposed in more situations because this implemenation is used to back read/write as well. I expect this fixes the regressions observed on the Espressif CI. https://github.com/apache/nuttx/pull/13498#issuecomment-2448031197 Note that, even with this fix, these "compat" readv/writev implementations are still inheritedly broken. (E.g. consider that a data boundary happens to match one of iovec boundaries) However, this fix is enough for read/write, where iovcnt is always 1.
This commit is contained in:
committed by
Xiang Xiao
parent
0fad2ee73f
commit
8241a10ebc
+28
-34
@@ -68,42 +68,36 @@ static ssize_t file_readv_compat(FAR struct file *filep,
|
|||||||
{
|
{
|
||||||
/* Ignore zero-length reads */
|
/* Ignore zero-length reads */
|
||||||
|
|
||||||
if (iov[i].iov_len > 0)
|
if (iov[i].iov_len == 0)
|
||||||
{
|
{
|
||||||
buffer = iov[i].iov_base;
|
continue;
|
||||||
remaining = iov[i].iov_len;
|
|
||||||
|
|
||||||
/* Read repeatedly as necessary to fill buffer */
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
nread = inode->u.i_ops->read(filep, (void *)buffer,
|
|
||||||
remaining);
|
|
||||||
|
|
||||||
/* Check for a read error */
|
|
||||||
|
|
||||||
if (nread < 0)
|
|
||||||
{
|
|
||||||
return ntotal ? ntotal : nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for an end-of-file condition */
|
|
||||||
|
|
||||||
else if (nread == 0)
|
|
||||||
{
|
|
||||||
return ntotal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update pointers and counts in order to handle partial
|
|
||||||
* buffer reads.
|
|
||||||
*/
|
|
||||||
|
|
||||||
buffer += nread;
|
|
||||||
remaining -= nread;
|
|
||||||
ntotal += nread;
|
|
||||||
}
|
|
||||||
while (remaining > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer = iov[i].iov_base;
|
||||||
|
remaining = iov[i].iov_len;
|
||||||
|
|
||||||
|
nread = inode->u.i_ops->read(filep, (void *)buffer, remaining);
|
||||||
|
|
||||||
|
/* Check for a read error */
|
||||||
|
|
||||||
|
if (nread < 0)
|
||||||
|
{
|
||||||
|
return ntotal ? ntotal : nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
ntotal += nread;
|
||||||
|
|
||||||
|
/* Check for a parital success condition, including an end-of-file */
|
||||||
|
|
||||||
|
if (nread < remaining)
|
||||||
|
{
|
||||||
|
return ntotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the pointer */
|
||||||
|
|
||||||
|
buffer += nread;
|
||||||
|
remaining -= nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ntotal;
|
return ntotal;
|
||||||
|
|||||||
+28
-27
@@ -68,35 +68,36 @@ static ssize_t file_writev_compat(FAR struct file *filep,
|
|||||||
{
|
{
|
||||||
/* Ignore zero-length writes */
|
/* Ignore zero-length writes */
|
||||||
|
|
||||||
if (iov[i].iov_len > 0)
|
if (iov[i].iov_len == 0)
|
||||||
{
|
{
|
||||||
buffer = iov[i].iov_base;
|
continue;
|
||||||
remaining = iov[i].iov_len;
|
|
||||||
|
|
||||||
/* Write repeatedly as necessary to write the entire buffer */
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
nwritten = inode->u.i_ops->write(filep, (void *)buffer,
|
|
||||||
remaining);
|
|
||||||
|
|
||||||
/* Check for a write error */
|
|
||||||
|
|
||||||
if (nwritten < 0)
|
|
||||||
{
|
|
||||||
return ntotal ? ntotal : nwritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update pointers and counts in order to handle partial
|
|
||||||
* buffer writes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
buffer += nwritten;
|
|
||||||
remaining -= nwritten;
|
|
||||||
ntotal += nwritten;
|
|
||||||
}
|
|
||||||
while (remaining > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer = iov[i].iov_base;
|
||||||
|
remaining = iov[i].iov_len;
|
||||||
|
|
||||||
|
nwritten = inode->u.i_ops->write(filep, (void *)buffer, remaining);
|
||||||
|
|
||||||
|
/* Check for a write error */
|
||||||
|
|
||||||
|
if (nwritten < 0)
|
||||||
|
{
|
||||||
|
return ntotal ? ntotal : nwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
ntotal += nwritten;
|
||||||
|
|
||||||
|
/* Check for a parital success condition */
|
||||||
|
|
||||||
|
if (nwritten < remaining)
|
||||||
|
{
|
||||||
|
return ntotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the pointer */
|
||||||
|
|
||||||
|
buffer += nwritten;
|
||||||
|
remaining -= nwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ntotal;
|
return ntotal;
|
||||||
|
|||||||
Reference in New Issue
Block a user