diff --git a/drivers/loop/loop.c b/drivers/loop/loop.c index 889040d7d7743..2b2a412b5bdae 100644 --- a/drivers/loop/loop.c +++ b/drivers/loop/loop.c @@ -40,10 +40,8 @@ * Private Function Prototypes ****************************************************************************/ -static ssize_t loop_readv(FAR struct file *filep, - FAR const struct uio *uio); -static ssize_t loop_writev(FAR struct file *filep, - FAR const struct uio *uio); +static ssize_t loop_readv(FAR struct file *filep, FAR struct uio *uio); +static ssize_t loop_writev(FAR struct file *filep, FAR struct uio *uio); static int loop_ioctl(FAR struct file *filep, int cmd, unsigned long arg); @@ -71,23 +69,26 @@ static const struct file_operations g_loop_fops = ****************************************************************************/ /**************************************************************************** - * Name: loop_read + * Name: loop_readv ****************************************************************************/ -static ssize_t loop_readv(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t loop_readv(FAR struct file *filep, FAR struct uio *uio) { return 0; /* Return EOF */ } /**************************************************************************** - * Name: loop_write + * Name: loop_writev ****************************************************************************/ -static ssize_t loop_writev(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t loop_writev(FAR struct file *filep, FAR 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; } /**************************************************************************** diff --git a/drivers/misc/dev_null.c b/drivers/misc/dev_null.c index 1c8c2f0a102bb..0c196fc7c71d8 100644 --- a/drivers/misc/dev_null.c +++ b/drivers/misc/dev_null.c @@ -40,10 +40,8 @@ * Private Function Prototypes ****************************************************************************/ -static ssize_t devnull_readv(FAR struct file *filep, - FAR const struct uio *uio); -static ssize_t devnull_writev(FAR struct file *filep, - FAR const struct uio *uio); +static ssize_t devnull_readv(FAR struct file *filep, FAR struct uio *uio); +static ssize_t devnull_writev(FAR struct file *filep, FAR struct uio *uio); static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); @@ -71,11 +69,10 @@ static const struct file_operations g_devnull_fops = ****************************************************************************/ /**************************************************************************** - * Name: devnull_read + * Name: devnull_readv ****************************************************************************/ -static ssize_t devnull_readv(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t devnull_readv(FAR struct file *filep, FAR struct uio *uio) { UNUSED(filep); UNUSED(uio); @@ -84,15 +81,19 @@ static ssize_t devnull_readv(FAR struct file *filep, } /**************************************************************************** - * Name: devnull_write + * Name: devnull_writev ****************************************************************************/ -static ssize_t devnull_writev(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t devnull_writev(FAR struct file *filep, FAR struct uio *uio) { 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; } /**************************************************************************** diff --git a/drivers/misc/dev_zero.c b/drivers/misc/dev_zero.c index 0b5a41712edb1..38be2fd9fcc09 100644 --- a/drivers/misc/dev_zero.c +++ b/drivers/misc/dev_zero.c @@ -40,10 +40,8 @@ * Private Function Prototypes ****************************************************************************/ -static ssize_t devzero_readv(FAR struct file *filep, - FAR const struct uio *uio); -static ssize_t devzero_writev(FAR struct file *filep, - FAR const struct uio *uio); +static ssize_t devzero_readv(FAR struct file *filep, FAR struct uio *uio); +static ssize_t devzero_writev(FAR struct file *filep, FAR struct uio *uio); static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup); @@ -71,42 +69,41 @@ static const struct file_operations g_devzero_fops = ****************************************************************************/ /**************************************************************************** - * Name: devzero_read + * Name: devzero_readv ****************************************************************************/ -static ssize_t devzero_readv(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t devzero_readv(FAR struct file *filep, FAR struct uio *uio) { - ssize_t total = uio_total_len(uio); + size_t total = uio->uio_resid; FAR const struct iovec *iov = uio->uio_iov; int iovcnt = uio->uio_iovcnt; int i; UNUSED(filep); - if (total < 0) - { - return total; - } - for (i = 0; i < iovcnt; i++) { memset(iov[i].iov_base, 0, iov[i].iov_len); } + uio_advance(uio, total); + return total; } /**************************************************************************** - * Name: devzero_write + * Name: devzero_writev ****************************************************************************/ -static ssize_t devzero_writev(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t devzero_writev(FAR struct file *filep, FAR struct uio *uio) { + size_t total; UNUSED(filep); - return uio_total_len(uio); + total = uio->uio_resid; + + uio_advance(uio, total); + return total; } /**************************************************************************** diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index d475f44d12075..e29d09add3a29 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -99,6 +99,8 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev, FAR const char *buffer, size_t buflen); +static inline ssize_t uart_irqwritev(FAR uart_dev_t *dev, + FAR struct uio *uio); static int uart_tcdrain(FAR uart_dev_t *dev, bool cancelable, clock_t timeout); @@ -110,11 +112,8 @@ static int uart_tcsendbreak(FAR uart_dev_t *dev, static int uart_open(FAR struct file *filep); static int uart_close(FAR struct file *filep); -static ssize_t uart_read(FAR struct file *filep, - FAR char *buffer, size_t buflen); -static ssize_t uart_write(FAR struct file *filep, - FAR const char *buffer, - size_t buflen); +static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio); +static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio); static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg); static int uart_poll(FAR struct file *filep, @@ -141,15 +140,15 @@ static const struct file_operations g_serialops = { uart_open, /* open */ uart_close, /* close */ - uart_read, /* read */ - uart_write, /* write */ + NULL, /* read */ + NULL, /* write */ NULL, /* seek */ uart_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* truncate */ uart_poll, /* poll */ - NULL, /* readv */ - NULL /* writev */ + uart_readv, /* readv */ + uart_writev /* writev */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS , uart_unlink /* unlink */ #endif @@ -441,6 +440,50 @@ static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev, return buflen; } +/**************************************************************************** + * Name: uart_irqwritev + ****************************************************************************/ + +static inline ssize_t uart_irqwritev(FAR uart_dev_t *dev, + FAR struct uio *uio) +{ + ssize_t error = 0; + ssize_t total = 0; + int iovcnt = uio->uio_iovcnt; + int i; + + for (i = 0; i < iovcnt; i++) + { + const struct iovec *iov = &uio->uio_iov[i]; + if (iov->iov_len == 0) + { + continue; + } + + ssize_t written = uart_irqwrite(dev, iov->iov_base, iov->iov_len); + if (written < 0) + { + error = written; + break; + } + + if (SSIZE_MAX - total < written) + { + error = -EOVERFLOW; + break; + } + + total += written; + } + + if (error != 0 && total == 0) + { + return error; + } + + return total; +} + /**************************************************************************** * Name: uart_tcdrain * @@ -847,11 +890,10 @@ static int uart_close(FAR struct file *filep) } /**************************************************************************** - * Name: uart_read + * Name: uart_readv ****************************************************************************/ -static ssize_t uart_read(FAR struct file *filep, - FAR char *buffer, size_t buflen) +static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) { FAR struct inode *inode = filep->f_inode; FAR uart_dev_t *dev = inode->i_private; @@ -862,6 +904,7 @@ static ssize_t uart_read(FAR struct file *filep, #endif irqstate_t flags; ssize_t recvd = 0; + ssize_t buflen; bool echoed = false; int16_t tail; char ch; @@ -885,7 +928,8 @@ static ssize_t uart_read(FAR struct file *filep, * data from the end of the buffer. */ - while ((size_t)recvd < buflen) + buflen = uio->uio_resid; + while (recvd < buflen) { #ifdef CONFIG_SERIAL_REMOVABLE /* If the removable device is no longer connected, refuse to read any @@ -961,7 +1005,8 @@ static ssize_t uart_read(FAR struct file *filep, { if (recvd > 0) { - *buffer-- = '\0'; + static const char zero = '\0'; + uio_copyfrom(uio, recvd, &zero, 1); recvd--; if (dev->tc_lflag & ECHO) { @@ -990,7 +1035,7 @@ static ssize_t uart_read(FAR struct file *filep, /* Store the received character */ - *buffer++ = ch; + uio_copyfrom(uio, recvd, &ch, 1); recvd++; if (dev->tc_lflag & ECHO) @@ -1325,19 +1370,24 @@ static ssize_t uart_read(FAR struct file *filep, #endif nxmutex_unlock(&dev->recv.lock); + if (recvd >= 0) + { + uio_advance(uio, recvd); + } + return recvd; } /**************************************************************************** - * Name: uart_write + * Name: uart_writev ****************************************************************************/ -static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, - size_t buflen) +static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio) { FAR struct inode *inode = filep->f_inode; FAR uart_dev_t *dev = inode->i_private; - ssize_t nwritten = buflen; + ssize_t nwritten; + ssize_t buflen; bool oktoblock; int ret; char ch; @@ -1363,12 +1413,14 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, #endif flags = enter_critical_section(); - ret = uart_irqwrite(dev, buffer, buflen); + ret = uart_irqwritev(dev, uio); leave_critical_section(flags); return ret; } + buflen = nwritten = uio->uio_resid; + /* Only one user can access dev->xmit.head at a time */ ret = nxmutex_lock(&dev->xmit.lock); @@ -1408,9 +1460,9 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, */ uart_disabletxint(dev); - for (; buflen; buflen--) + for (; buflen; uio_advance(uio, 1), buflen--) { - ch = *buffer++; + uio_copyto(uio, 0, &ch, 1); ret = OK; /* Do output post-processing */ diff --git a/fs/vfs/fs_read.c b/fs/vfs/fs_read.c index fce68e0d68b2a..1d93af0e04bf1 100644 --- a/fs/vfs/fs_read.c +++ b/fs/vfs/fs_read.c @@ -50,8 +50,7 @@ * ****************************************************************************/ -static ssize_t file_readv_compat(FAR struct file *filep, - FAR const struct uio *uio) +static ssize_t file_readv_compat(FAR struct file *filep, FAR struct uio *uio) { FAR const struct iovec *iov = uio->uio_iov; int iovcnt = uio->uio_iovcnt; @@ -102,6 +101,11 @@ static ssize_t file_readv_compat(FAR struct file *filep, remaining -= nread; } + if (ntotal >= 0) + { + uio_advance(uio, 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; 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 uio uio; + ssize_t ret; iov.iov_base = buf; iov.iov_len = nbytes; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; + ret = uio_init(&uio, &iov, 1); + if (ret != 0) + { + return ret; + } + 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. */ - uio.uio_iov = iov; - uio.uio_iovcnt = iovcnt; - ret = file_readv(filep, &uio); + ret = uio_init(&uio, iov, iovcnt); + if (ret == 0) + { + ret = file_readv(filep, &uio); + } + fs_putfilep(filep); return ret; } diff --git a/fs/vfs/fs_uio.c b/fs/vfs/fs_uio.c index 5c6e260d5599f..4c3482f9bb585 100644 --- a/fs/vfs/fs_uio.c +++ b/fs/vfs/fs_uio.c @@ -35,19 +35,19 @@ #include /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: uio_total_len + * Name: uio_calc_resid * * Description: - * Return the total length of data in bytes. - * Or -EOVERFLOW. + * Return the remaining length of data in bytes. + * 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; 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) { - return -EOVERFLOW; + return -EINVAL; } len += iov[i].iov_len; @@ -66,3 +66,165 @@ ssize_t uio_total_len(FAR const struct uio *uio) 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; + DEBUGASSERT((uio->uio_resid == 0) == (uio->uio_iovcnt == 0)); + 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; + } +} diff --git a/fs/vfs/fs_write.c b/fs/vfs/fs_write.c index 39f49517bea2b..16be9ea957f38 100644 --- a/fs/vfs/fs_write.c +++ b/fs/vfs/fs_write.c @@ -51,7 +51,7 @@ ****************************************************************************/ 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; int iovcnt = uio->uio_iovcnt; @@ -102,6 +102,11 @@ static ssize_t file_writev_compat(FAR struct file *filep, remaining -= nwritten; } + if (ntotal >= 0) + { + uio_advance(uio, 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; ssize_t ret = -EBADF; @@ -202,11 +207,16 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, { struct iovec iov; struct uio uio; + ssize_t ret; iov.iov_base = (FAR void *)buf; iov.iov_len = nbytes; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; + ret = uio_init(&uio, &iov, 1); + if (ret != 0) + { + return ret; + } + 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. */ - uio.uio_iov = iov; - uio.uio_iovcnt = iovcnt; - ret = file_writev(filep, &uio); + ret = uio_init(&uio, iov, iovcnt); + if (ret == 0) + { + ret = file_writev(filep, &uio); + } + fs_putfilep(filep); } diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index dd3ff754037bf..44319e2ab9644 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -241,8 +241,8 @@ struct file_operations CODE int (*poll)(FAR struct file *filep, FAR struct pollfd *fds, bool setup); - CODE ssize_t (*readv)(FAR struct file *filep, FAR const struct uio *uio); - CODE ssize_t (*writev)(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 struct uio *uio); /* The two structures need not be common after this point */ @@ -312,8 +312,8 @@ struct mountpt_operations CODE int (*truncate)(FAR struct file *filep, off_t length); CODE int (*poll)(FAR struct file *filep, FAR struct pollfd *fds, bool setup); - CODE ssize_t (*readv)(FAR struct file *filep, FAR const struct uio *uio); - CODE ssize_t (*writev)(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 struct uio *uio); /* The two structures need not be common after this point. The following * are extended methods needed to deal with the unique needs of mounted @@ -1420,7 +1420,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_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 @@ -1474,7 +1474,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, 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 diff --git a/include/nuttx/fs/uio.h b/include/nuttx/fs/uio.h index e864745a18cf6..91e84a7a6c278 100644 --- a/include/nuttx/fs/uio.h +++ b/include/nuttx/fs/uio.h @@ -45,6 +45,12 @@ struct uio { FAR const struct iovec *uio_iov; 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: + * Advance the pointer/offset in uio by the specified amount. + * + ****************************************************************************/ + +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: - * Return the total length of data in bytes. - * Or -EOVERFLOW. + * Copy data to the linear buffer from uio. * ****************************************************************************/ -ssize_t uio_total_len(FAR const struct uio *uio); +void uio_copyto(FAR struct uio *uio, size_t offset, FAR void *buf, + size_t len); #endif /* __INCLUDE_NUTTX_FS_UIO_H */