mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 05:55:46 +08:00
uio api tweaks
* Make readv/writev implementations update struct uio This can simplify partial result handling. * change the error number on the overflow from EOVERFLOW to EINVAL to match NetBSD * add a commented out uio_offset field. I used "#if 0" here as C comments can't nest. * add a few helper functions Note on uio_copyfrom/uio_copyto: although i'm not quite happy with the "offset" functionality, it's necessary to simplify the adaptation of some drivers like drivers/serial/serial.c, which (ab)uses the user-supplied buffer as a line-buffer.
This commit is contained in:
committed by
Xiang Xiao
parent
2749510413
commit
30ad31e9d7
+10
-9
@@ -40,10 +40,8 @@
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t loop_readv(FAR struct file *filep,
|
static ssize_t loop_readv(FAR struct file *filep, FAR struct uio *uio);
|
||||||
FAR const struct uio *uio);
|
static ssize_t loop_writev(FAR struct file *filep, FAR struct uio *uio);
|
||||||
static ssize_t loop_writev(FAR struct file *filep,
|
|
||||||
FAR const struct uio *uio);
|
|
||||||
static int loop_ioctl(FAR struct file *filep, int cmd,
|
static int loop_ioctl(FAR struct file *filep, int cmd,
|
||||||
unsigned long arg);
|
unsigned long arg);
|
||||||
|
|
||||||
@@ -74,8 +72,7 @@ static const struct file_operations g_loop_fops =
|
|||||||
* Name: loop_readv
|
* Name: loop_readv
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t loop_readv(FAR struct file *filep,
|
static ssize_t loop_readv(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
return 0; /* Return EOF */
|
return 0; /* Return EOF */
|
||||||
}
|
}
|
||||||
@@ -84,10 +81,14 @@ static ssize_t loop_readv(FAR struct file *filep,
|
|||||||
* Name: loop_writev
|
* Name: loop_writev
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t loop_writev(FAR struct file *filep,
|
static ssize_t loop_writev(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
return uio_total_len(uio); /* Say that everything was written */
|
/* Say that everything was written */
|
||||||
|
|
||||||
|
size_t ret = uio->uio_resid;
|
||||||
|
|
||||||
|
uio_advance(uio, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+10
-9
@@ -40,10 +40,8 @@
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devnull_readv(FAR struct file *filep,
|
static ssize_t devnull_readv(FAR struct file *filep, FAR struct uio *uio);
|
||||||
FAR const struct uio *uio);
|
static ssize_t devnull_writev(FAR struct file *filep, FAR struct uio *uio);
|
||||||
static ssize_t devnull_writev(FAR struct file *filep,
|
|
||||||
FAR const struct uio *uio);
|
|
||||||
static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||||
bool setup);
|
bool setup);
|
||||||
|
|
||||||
@@ -74,8 +72,7 @@ static const struct file_operations g_devnull_fops =
|
|||||||
* Name: devnull_readv
|
* Name: devnull_readv
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devnull_readv(FAR struct file *filep,
|
static ssize_t devnull_readv(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
UNUSED(filep);
|
UNUSED(filep);
|
||||||
UNUSED(uio);
|
UNUSED(uio);
|
||||||
@@ -87,12 +84,16 @@ static ssize_t devnull_readv(FAR struct file *filep,
|
|||||||
* Name: devnull_writev
|
* Name: devnull_writev
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devnull_writev(FAR struct file *filep,
|
static ssize_t devnull_writev(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
UNUSED(filep);
|
UNUSED(filep);
|
||||||
|
|
||||||
return uio_total_len(uio); /* Say that everything was written */
|
/* Say that everything was written */
|
||||||
|
|
||||||
|
size_t ret = uio->uio_resid;
|
||||||
|
|
||||||
|
uio_advance(uio, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+12
-15
@@ -40,10 +40,8 @@
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devzero_readv(FAR struct file *filep,
|
static ssize_t devzero_readv(FAR struct file *filep, FAR struct uio *uio);
|
||||||
FAR const struct uio *uio);
|
static ssize_t devzero_writev(FAR struct file *filep, FAR struct uio *uio);
|
||||||
static ssize_t devzero_writev(FAR struct file *filep,
|
|
||||||
FAR const struct uio *uio);
|
|
||||||
static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||||
bool setup);
|
bool setup);
|
||||||
|
|
||||||
@@ -74,26 +72,22 @@ static const struct file_operations g_devzero_fops =
|
|||||||
* Name: devzero_readv
|
* Name: devzero_readv
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devzero_readv(FAR struct file *filep,
|
static ssize_t devzero_readv(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
ssize_t total = uio_total_len(uio);
|
size_t total = uio->uio_resid;
|
||||||
FAR const struct iovec *iov = uio->uio_iov;
|
FAR const struct iovec *iov = uio->uio_iov;
|
||||||
int iovcnt = uio->uio_iovcnt;
|
int iovcnt = uio->uio_iovcnt;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
UNUSED(filep);
|
UNUSED(filep);
|
||||||
|
|
||||||
if (total < 0)
|
|
||||||
{
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < iovcnt; i++)
|
for (i = 0; i < iovcnt; i++)
|
||||||
{
|
{
|
||||||
memset(iov[i].iov_base, 0, iov[i].iov_len);
|
memset(iov[i].iov_base, 0, iov[i].iov_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uio_advance(uio, total);
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +95,15 @@ static ssize_t devzero_readv(FAR struct file *filep,
|
|||||||
* Name: devzero_writev
|
* Name: devzero_writev
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devzero_writev(FAR struct file *filep,
|
static ssize_t devzero_writev(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
|
size_t total;
|
||||||
UNUSED(filep);
|
UNUSED(filep);
|
||||||
|
|
||||||
return uio_total_len(uio);
|
total = uio->uio_resid;
|
||||||
|
|
||||||
|
uio_advance(uio, total);
|
||||||
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+20
-8
@@ -50,8 +50,7 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t file_readv_compat(FAR struct file *filep,
|
static ssize_t file_readv_compat(FAR struct file *filep, FAR struct uio *uio)
|
||||||
FAR const struct uio *uio)
|
|
||||||
{
|
{
|
||||||
FAR const struct iovec *iov = uio->uio_iov;
|
FAR const struct iovec *iov = uio->uio_iov;
|
||||||
int iovcnt = uio->uio_iovcnt;
|
int iovcnt = uio->uio_iovcnt;
|
||||||
@@ -102,6 +101,11 @@ static ssize_t file_readv_compat(FAR struct file *filep,
|
|||||||
remaining -= nread;
|
remaining -= nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ntotal >= 0)
|
||||||
|
{
|
||||||
|
uio_advance(uio, ntotal);
|
||||||
|
}
|
||||||
|
|
||||||
return ntotal;
|
return ntotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +134,7 @@ static ssize_t file_readv_compat(FAR struct file *filep,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
ssize_t file_readv(FAR struct file *filep, FAR const struct uio *uio)
|
ssize_t file_readv(FAR struct file *filep, FAR struct uio *uio)
|
||||||
{
|
{
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
@@ -204,11 +208,16 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
|
|||||||
{
|
{
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct uio uio;
|
struct uio uio;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
iov.iov_base = buf;
|
iov.iov_base = buf;
|
||||||
iov.iov_len = nbytes;
|
iov.iov_len = nbytes;
|
||||||
uio.uio_iov = &iov;
|
ret = uio_init(&uio, &iov, 1);
|
||||||
uio.uio_iovcnt = 1;
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return file_readv(filep, &uio);
|
return file_readv(filep, &uio);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,9 +260,12 @@ ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt)
|
|||||||
|
|
||||||
/* Then let file_readv do all of the work. */
|
/* Then let file_readv do all of the work. */
|
||||||
|
|
||||||
uio.uio_iov = iov;
|
ret = uio_init(&uio, iov, iovcnt);
|
||||||
uio.uio_iovcnt = iovcnt;
|
if (ret == 0)
|
||||||
ret = file_readv(filep, &uio);
|
{
|
||||||
|
ret = file_readv(filep, &uio);
|
||||||
|
}
|
||||||
|
|
||||||
fs_putfilep(filep);
|
fs_putfilep(filep);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
+167
-6
@@ -35,19 +35,19 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: uio_total_len
|
* Name: uio_calc_resid
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Return the total length of data in bytes.
|
* Return the remaining length of data in bytes.
|
||||||
* Or -EOVERFLOW.
|
* Or -EINVAL.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
ssize_t uio_total_len(FAR const struct uio *uio)
|
ssize_t uio_calc_resid(FAR const struct uio *uio)
|
||||||
{
|
{
|
||||||
const struct iovec *iov = uio->uio_iov;
|
const struct iovec *iov = uio->uio_iov;
|
||||||
int iovcnt = uio->uio_iovcnt;
|
int iovcnt = uio->uio_iovcnt;
|
||||||
@@ -58,7 +58,7 @@ ssize_t uio_total_len(FAR const struct uio *uio)
|
|||||||
{
|
{
|
||||||
if (SSIZE_MAX - len < iov[i].iov_len)
|
if (SSIZE_MAX - len < iov[i].iov_len)
|
||||||
{
|
{
|
||||||
return -EOVERFLOW;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
len += iov[i].iov_len;
|
len += iov[i].iov_len;
|
||||||
@@ -66,3 +66,164 @@ ssize_t uio_total_len(FAR const struct uio *uio)
|
|||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_advance
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Advance the pointer/offset in uio by the specified amount.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void uio_advance(FAR struct uio *uio, size_t sz)
|
||||||
|
{
|
||||||
|
FAR const struct iovec *iov = uio->uio_iov;
|
||||||
|
int iovcnt = uio->uio_iovcnt;
|
||||||
|
size_t offset_in_iov = uio->uio_offset_in_iov;
|
||||||
|
|
||||||
|
DEBUGASSERT(sz <= SSIZE_MAX);
|
||||||
|
DEBUGASSERT(uio->uio_resid <= SSIZE_MAX);
|
||||||
|
DEBUGASSERT(sz <= uio->uio_resid);
|
||||||
|
DEBUGASSERT(uio->uio_offset_in_iov + uio->uio_resid ==
|
||||||
|
uio_calc_resid(uio));
|
||||||
|
uio->uio_resid -= sz;
|
||||||
|
while (iovcnt > 0)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(offset_in_iov <= iov->iov_len);
|
||||||
|
if (sz < iov->iov_len - offset_in_iov)
|
||||||
|
{
|
||||||
|
offset_in_iov += sz;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sz -= iov->iov_len - offset_in_iov;
|
||||||
|
iov++;
|
||||||
|
iovcnt--;
|
||||||
|
offset_in_iov = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uio->uio_iov = iov;
|
||||||
|
uio->uio_iovcnt = iovcnt;
|
||||||
|
uio->uio_offset_in_iov = offset_in_iov;
|
||||||
|
DEBUGASSERT(uio->uio_offset_in_iov + uio->uio_resid ==
|
||||||
|
uio_calc_resid(uio));
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize the uio structure with reasonable default values.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt)
|
||||||
|
{
|
||||||
|
ssize_t resid;
|
||||||
|
|
||||||
|
memset(uio, 0, sizeof(*uio));
|
||||||
|
uio->uio_iov = iov;
|
||||||
|
uio->uio_iovcnt = iovcnt;
|
||||||
|
resid = uio_calc_resid(uio);
|
||||||
|
if (resid < 0)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uio->uio_resid = resid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_copyfrom
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Copy data from the linear buffer to uio.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void uio_copyfrom(FAR struct uio *uio, size_t offset, FAR const void *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
FAR const struct iovec *iov = uio->uio_iov;
|
||||||
|
|
||||||
|
DEBUGASSERT(uio->uio_resid >= 0);
|
||||||
|
DEBUGASSERT(uio->uio_resid <= SSIZE_MAX);
|
||||||
|
DEBUGASSERT(len <= uio->uio_resid);
|
||||||
|
DEBUGASSERT(offset <= uio->uio_resid - len);
|
||||||
|
DEBUGASSERT(SSIZE_MAX - offset >= uio->uio_offset_in_iov);
|
||||||
|
DEBUGASSERT(uio->uio_offset_in_iov + uio->uio_resid ==
|
||||||
|
uio_calc_resid(uio));
|
||||||
|
|
||||||
|
offset += uio->uio_offset_in_iov;
|
||||||
|
while (offset > iov->iov_len)
|
||||||
|
{
|
||||||
|
offset -= iov->iov_len;
|
||||||
|
iov++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
size_t blen = len;
|
||||||
|
if (blen > iov->iov_len - offset)
|
||||||
|
{
|
||||||
|
blen = iov->iov_len - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((FAR uint8_t *)iov->iov_base + offset, buf, blen);
|
||||||
|
|
||||||
|
len -= blen;
|
||||||
|
buf = (const uint8_t *)buf + blen;
|
||||||
|
iov++;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_copyto
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Copy data to the linear buffer from uio.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void uio_copyto(FAR struct uio *uio, size_t offset, FAR void *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
FAR const struct iovec *iov = uio->uio_iov;
|
||||||
|
|
||||||
|
DEBUGASSERT(uio->uio_resid >= 0);
|
||||||
|
DEBUGASSERT(uio->uio_resid <= SSIZE_MAX);
|
||||||
|
DEBUGASSERT(len <= uio->uio_resid);
|
||||||
|
DEBUGASSERT(offset <= uio->uio_resid - len);
|
||||||
|
DEBUGASSERT(SSIZE_MAX - offset >= uio->uio_offset_in_iov);
|
||||||
|
DEBUGASSERT(uio->uio_offset_in_iov + uio->uio_resid ==
|
||||||
|
uio_calc_resid(uio));
|
||||||
|
|
||||||
|
offset += uio->uio_offset_in_iov;
|
||||||
|
while (offset > iov->iov_len)
|
||||||
|
{
|
||||||
|
offset -= iov->iov_len;
|
||||||
|
iov++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
size_t blen = len;
|
||||||
|
if (blen > iov->iov_len - offset)
|
||||||
|
{
|
||||||
|
blen = iov->iov_len - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, (FAR const uint8_t *)iov->iov_base + offset, blen);
|
||||||
|
|
||||||
|
len -= blen;
|
||||||
|
buf = (uint8_t *)buf + blen;
|
||||||
|
iov++;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+20
-7
@@ -51,7 +51,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t file_writev_compat(FAR struct file *filep,
|
static ssize_t file_writev_compat(FAR struct file *filep,
|
||||||
FAR const struct uio *uio)
|
FAR struct uio *uio)
|
||||||
{
|
{
|
||||||
FAR const struct iovec *iov = uio->uio_iov;
|
FAR const struct iovec *iov = uio->uio_iov;
|
||||||
int iovcnt = uio->uio_iovcnt;
|
int iovcnt = uio->uio_iovcnt;
|
||||||
@@ -102,6 +102,11 @@ static ssize_t file_writev_compat(FAR struct file *filep,
|
|||||||
remaining -= nwritten;
|
remaining -= nwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ntotal >= 0)
|
||||||
|
{
|
||||||
|
uio_advance(uio, ntotal);
|
||||||
|
}
|
||||||
|
|
||||||
return ntotal;
|
return ntotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +138,7 @@ static ssize_t file_writev_compat(FAR struct file *filep,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
ssize_t file_writev(FAR struct file *filep, FAR const struct uio *uio)
|
ssize_t file_writev(FAR struct file *filep, FAR struct uio *uio)
|
||||||
{
|
{
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
@@ -202,11 +207,16 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf,
|
|||||||
{
|
{
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct uio uio;
|
struct uio uio;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
iov.iov_base = (FAR void *)buf;
|
iov.iov_base = (FAR void *)buf;
|
||||||
iov.iov_len = nbytes;
|
iov.iov_len = nbytes;
|
||||||
uio.uio_iov = &iov;
|
ret = uio_init(&uio, &iov, 1);
|
||||||
uio.uio_iovcnt = 1;
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return file_writev(filep, &uio);
|
return file_writev(filep, &uio);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,9 +262,12 @@ ssize_t nx_writev(int fd, FAR const struct iovec *iov, int iovcnt)
|
|||||||
* index. Note that file_writev() will return the errno on failure.
|
* index. Note that file_writev() will return the errno on failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uio.uio_iov = iov;
|
ret = uio_init(&uio, iov, iovcnt);
|
||||||
uio.uio_iovcnt = iovcnt;
|
if (ret == 0)
|
||||||
ret = file_writev(filep, &uio);
|
{
|
||||||
|
ret = file_writev(filep, &uio);
|
||||||
|
}
|
||||||
|
|
||||||
fs_putfilep(filep);
|
fs_putfilep(filep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -240,8 +240,8 @@ struct file_operations
|
|||||||
|
|
||||||
CODE int (*poll)(FAR struct file *filep, FAR struct pollfd *fds,
|
CODE int (*poll)(FAR struct file *filep, FAR struct pollfd *fds,
|
||||||
bool setup);
|
bool setup);
|
||||||
CODE ssize_t (*readv)(FAR struct file *filep, FAR const struct uio *uio);
|
CODE ssize_t (*readv)(FAR struct file *filep, FAR struct uio *uio);
|
||||||
CODE ssize_t (*writev)(FAR struct file *filep, FAR const struct uio *uio);
|
CODE ssize_t (*writev)(FAR struct file *filep, FAR struct uio *uio);
|
||||||
|
|
||||||
/* The two structures need not be common after this point */
|
/* The two structures need not be common after this point */
|
||||||
|
|
||||||
@@ -311,8 +311,8 @@ struct mountpt_operations
|
|||||||
CODE int (*truncate)(FAR struct file *filep, off_t length);
|
CODE int (*truncate)(FAR struct file *filep, off_t length);
|
||||||
CODE int (*poll)(FAR struct file *filep, FAR struct pollfd *fds,
|
CODE int (*poll)(FAR struct file *filep, FAR struct pollfd *fds,
|
||||||
bool setup);
|
bool setup);
|
||||||
CODE ssize_t (*readv)(FAR struct file *filep, FAR const struct uio *uio);
|
CODE ssize_t (*readv)(FAR struct file *filep, FAR struct uio *uio);
|
||||||
CODE ssize_t (*writev)(FAR struct file *filep, FAR const struct uio *uio);
|
CODE ssize_t (*writev)(FAR struct file *filep, FAR struct uio *uio);
|
||||||
|
|
||||||
/* The two structures need not be common after this point. The following
|
/* The two structures need not be common after this point. The following
|
||||||
* are extended methods needed to deal with the unique needs of mounted
|
* are extended methods needed to deal with the unique needs of mounted
|
||||||
@@ -1419,7 +1419,7 @@ int close_mtddriver(FAR struct inode *pinode);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
|
||||||
ssize_t file_readv(FAR struct file *filep, FAR const struct uio *uio);
|
ssize_t file_readv(FAR struct file *filep, FAR struct uio *uio);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nx_read
|
* Name: nx_read
|
||||||
@@ -1473,7 +1473,7 @@ ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt);
|
|||||||
|
|
||||||
ssize_t file_write(FAR struct file *filep, FAR const void *buf,
|
ssize_t file_write(FAR struct file *filep, FAR const void *buf,
|
||||||
size_t nbytes);
|
size_t nbytes);
|
||||||
ssize_t file_writev(FAR struct file *filep, FAR const struct uio *uio);
|
ssize_t file_writev(FAR struct file *filep, FAR struct uio *uio);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nx_write
|
* Name: nx_write
|
||||||
|
|||||||
+48
-4
@@ -45,6 +45,12 @@ struct uio
|
|||||||
{
|
{
|
||||||
FAR const struct iovec *uio_iov;
|
FAR const struct iovec *uio_iov;
|
||||||
int uio_iovcnt;
|
int uio_iovcnt;
|
||||||
|
size_t uio_resid; /* the remaining bytes in the request */
|
||||||
|
size_t uio_offset_in_iov; /* offset in uio_iov[0].iov_base */
|
||||||
|
|
||||||
|
#if 0 /* notyet; planned for pread/pwrite */
|
||||||
|
off_t uio_offset; /* offset in the file */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -52,14 +58,52 @@ struct uio
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: uio_total_len
|
* Name: uio_advance
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Return the total length of data in bytes.
|
* Advance the pointer/offset in uio by the specified amount.
|
||||||
* Or -EOVERFLOW.
|
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
ssize_t uio_total_len(FAR const struct uio *uio);
|
void uio_advance(FAR struct uio *uio, size_t sz);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize the uio structure with reasonable default values.
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* 0 on success. A negative error number on an error.
|
||||||
|
*
|
||||||
|
* -EINVAL: The total size of the given iovec is too large.
|
||||||
|
* (Note: NetBSD's readv returns EINVAL in that case.
|
||||||
|
* I (yamamoto) couldn't find the specification in POSIX.)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int uio_init(FAR struct uio *uio, FAR const struct iovec *iov, int iovcnt);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_copyto
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Copy data to the linear buffer from uio.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void uio_copyfrom(FAR struct uio *uio, size_t offset, FAR const void *buf,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: uio_copyto
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Copy data to the linear buffer from uio.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void uio_copyto(FAR struct uio *uio, size_t offset, FAR void *buf,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
#endif /* __INCLUDE_NUTTX_FS_UIO_H */
|
#endif /* __INCLUDE_NUTTX_FS_UIO_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user