mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 05:08:41 +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:
parent
0fad2ee73f
commit
8241a10ebc
2 changed files with 56 additions and 61 deletions
|
@ -68,42 +68,36 @@ static ssize_t file_readv_compat(FAR struct file *filep,
|
|||
{
|
||||
/* Ignore zero-length reads */
|
||||
|
||||
if (iov[i].iov_len > 0)
|
||||
if (iov[i].iov_len == 0)
|
||||
{
|
||||
buffer = iov[i].iov_base;
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -68,35 +68,36 @@ static ssize_t file_writev_compat(FAR struct file *filep,
|
|||
{
|
||||
/* Ignore zero-length writes */
|
||||
|
||||
if (iov[i].iov_len > 0)
|
||||
if (iov[i].iov_len == 0)
|
||||
{
|
||||
buffer = iov[i].iov_base;
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue