move readv/writev to the kernel

currently, nuttx implements readv/writev on the top of read/write.
while it might work for the simplest cases, it's broken by design.
for example, it's impossible to make it work correctly for files
which need to preserve data boundaries without allocating a single
contiguous buffer. (udp socket, some character devices, etc)

this change is a start of the migration to a better design.
that is, implement read/write on the top of readv/writev.

to avoid a single huge change, following things will NOT be done in
this commit:

* fix actual bugs caused by the original readv-based-on-read design.
  (cf. https://github.com/apache/nuttx/pull/12674)

* adapt filesystems/drivers to actually benefit from the new interface.
  (except a few trivial examples)

* eventually retire the old interface.

* retire read/write syscalls. implement them in libc instead.

* pread/pwrite/preadv/pwritev (except the introduction of struct uio,
  which is a preparation to back these variations with the new
  interface.)
This commit is contained in:
YAMAMOTO Takashi 2024-09-17 15:23:07 +09:00 committed by Xiang Xiao
parent e3d7d23618
commit 761ee81956
68 changed files with 836 additions and 452 deletions

View File

@ -147,7 +147,9 @@ static const struct file_operations g_hif_fops =
hif_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
hif_poll /* poll */
hif_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, hif_unlink /* unlink */
#endif

View File

@ -80,7 +80,9 @@ const struct file_operations g_bch_fops =
bch_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
bch_poll /* poll */
bch_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, bch_unlink /* unlink */
#endif

View File

@ -99,7 +99,9 @@ static const struct file_operations g_i2cdrvr_fops =
i2cdrvr_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, i2cdrvr_unlink /* unlink */
#endif

View File

@ -134,7 +134,9 @@ static const struct file_operations g_i2cslavefops =
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
i2c_slave_poll /* poll */
i2c_slave_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, i2c_slave_unlink /* unlink */
#endif

View File

@ -96,7 +96,9 @@ static const struct file_operations g_i3cdrvr_fops =
i3cdrvr_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, i3cdrvr_unlink /* unlink */
#endif

View File

@ -124,7 +124,9 @@ static const struct file_operations g_gt9xx_fileops =
NULL, /* ioctl */
NULL, /* truncate */
NULL, /* mmap */
gt9xx_poll /* poll */
gt9xx_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif

View File

@ -136,7 +136,9 @@ static const struct file_operations g_ft80x_fops =
ft80x_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, ft80x_unlink /* unlink */
#endif

View File

@ -119,7 +119,9 @@ static const struct file_operations g_pcf8574_lcd_fops =
pcf8574_lcd_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
pcf8574_lcd_poll /* poll */
pcf8574_lcd_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, pcf8574_lcd_unlink /* unlink */
#endif

View File

@ -173,7 +173,9 @@ static const struct file_operations g_tda19988_fops =
tda19988_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
tda19988_poll /* poll */
tda19988_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, tda19988_unlink /* unlink */
#endif

View File

@ -38,10 +38,10 @@
* Private Function Prototypes
****************************************************************************/
static ssize_t loop_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t loop_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
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 int loop_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
@ -53,10 +53,15 @@ static const struct file_operations g_loop_fops =
{
NULL, /* open */
NULL, /* close */
loop_read, /* read */
loop_write, /* write */
NULL, /* read */
NULL, /* write */
NULL, /* seek */
loop_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL, /* poll */
loop_readv, /* readv */
loop_writev /* writev */
};
/****************************************************************************
@ -67,8 +72,8 @@ static const struct file_operations g_loop_fops =
* Name: loop_read
****************************************************************************/
static ssize_t loop_read(FAR struct file *filep, FAR char *buffer,
size_t len)
static ssize_t loop_readv(FAR struct file *filep,
FAR const struct uio *uio)
{
return 0; /* Return EOF */
}
@ -77,10 +82,10 @@ static ssize_t loop_read(FAR struct file *filep, FAR char *buffer,
* Name: loop_write
****************************************************************************/
static ssize_t loop_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
static ssize_t loop_writev(FAR struct file *filep,
FAR const struct uio *uio)
{
return len; /* Say that everything was written */
return uio_total_len(uio); /* Say that everything was written */
}
/****************************************************************************

View File

@ -38,10 +38,10 @@
* Private Function Prototypes
****************************************************************************/
static ssize_t devnull_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t devnull_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
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 int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
@ -51,15 +51,17 @@ static int devnull_poll(FAR struct file *filep, FAR struct pollfd *fds,
static const struct file_operations g_devnull_fops =
{
NULL, /* open */
NULL, /* close */
devnull_read, /* read */
devnull_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
devnull_poll /* poll */
NULL, /* open */
NULL, /* close */
NULL, /* read */
NULL, /* writev */
NULL, /* seek */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
devnull_poll, /* poll */
devnull_readv, /* readv */
devnull_writev /* writev */
};
/****************************************************************************
@ -70,12 +72,11 @@ static const struct file_operations g_devnull_fops =
* Name: devnull_read
****************************************************************************/
static ssize_t devnull_read(FAR struct file *filep, FAR char *buffer,
size_t len)
static ssize_t devnull_readv(FAR struct file *filep,
FAR const struct uio *uio)
{
UNUSED(filep);
UNUSED(buffer);
UNUSED(len);
UNUSED(uio);
return 0; /* Return EOF */
}
@ -84,13 +85,12 @@ static ssize_t devnull_read(FAR struct file *filep, FAR char *buffer,
* Name: devnull_write
****************************************************************************/
static ssize_t devnull_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
static ssize_t devnull_writev(FAR struct file *filep,
FAR const struct uio *uio)
{
UNUSED(filep);
UNUSED(buffer);
return len; /* Say that everything was written */
return uio_total_len(uio); /* Say that everything was written */
}
/****************************************************************************

View File

@ -38,10 +38,10 @@
* Private Function Prototypes
****************************************************************************/
static ssize_t devzero_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t devzero_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
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 int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
@ -51,15 +51,17 @@ static int devzero_poll(FAR struct file *filep, FAR struct pollfd *fds,
static const struct file_operations g_devzero_fops =
{
NULL, /* open */
NULL, /* close */
devzero_read, /* read */
devzero_write, /* write */
NULL, /* seek */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
devzero_poll /* poll */
NULL, /* open */
NULL, /* close */
NULL, /* read */
NULL, /* write */
NULL, /* seek */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
devzero_poll, /* poll */
devzero_readv, /* readv */
devzero_writev /* writev */
};
/****************************************************************************
@ -70,26 +72,39 @@ static const struct file_operations g_devzero_fops =
* Name: devzero_read
****************************************************************************/
static ssize_t devzero_read(FAR struct file *filep, FAR char *buffer,
size_t len)
static ssize_t devzero_readv(FAR struct file *filep,
FAR const struct uio *uio)
{
ssize_t total = uio_total_len(uio);
FAR const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
int i;
UNUSED(filep);
memset(buffer, 0, len);
return len;
if (total < 0)
{
return total;
}
for (i = 0; i < iovcnt; i++)
{
memset(iov[i].iov_base, 0, iov[i].iov_len);
}
return total;
}
/****************************************************************************
* Name: devzero_write
****************************************************************************/
static ssize_t devzero_write(FAR struct file *filep, FAR const char *buffer,
size_t len)
static ssize_t devzero_writev(FAR struct file *filep,
FAR const struct uio *uio)
{
UNUSED(filep);
UNUSED(buffer);
return len;
return uio_total_len(uio);
}
/****************************************************************************

View File

@ -120,7 +120,9 @@ static const struct file_operations g_uio_ivshmem_fops =
NULL, /* ioctl */
uio_ivshmem_mmap, /* mmap */
NULL, /* truncate */
uio_ivshmem_poll /* poll */
uio_ivshmem_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
#endif

View File

@ -49,7 +49,9 @@ static const struct file_operations g_fifo_fops =
pipecommon_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
pipecommon_poll /* poll */
pipecommon_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, pipecommon_unlink /* unlink */
#endif

View File

@ -118,7 +118,9 @@ static const struct file_operations g_aht10fops =
aht10_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, aht10_unlink /* unlink */
#endif

View File

@ -163,7 +163,9 @@ static const struct file_operations g_hdc1008fops =
hdc1008_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, hdc1008_unlink /* unlink */
#endif

View File

@ -184,7 +184,9 @@ static const struct file_operations g_scd30fops =
scd30_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, scd30_unlink /* unlink */
#endif

View File

@ -192,7 +192,9 @@ static const struct file_operations g_scd41fops =
scd41_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, scd41_unlink /* unlink */
#endif

View File

@ -161,7 +161,9 @@ static const struct file_operations g_sgp30fops =
sgp30_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, sgp30_unlink /* unlink */
#endif

View File

@ -133,7 +133,9 @@ static const struct file_operations g_sht21fops =
sht21_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, sht21_unlink /* unlink */
#endif

View File

@ -172,7 +172,9 @@ static const struct file_operations g_sht3xfops =
sht3x_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, sht3x_unlink /* unlink */
#endif

View File

@ -177,7 +177,9 @@ static const struct file_operations g_sps30fops =
sps30_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, sps30_unlink /* unlink */
#endif

View File

@ -136,7 +136,9 @@ static const struct file_operations g_pty_fops =
pty_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
pty_poll /* poll */
pty_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, pty_unlink /* unlink */
#endif

View File

@ -145,7 +145,9 @@ static const struct file_operations g_serialops =
uart_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
uart_poll /* poll */
uart_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, uart_unlink /* unlink */
#endif

View File

@ -99,7 +99,9 @@ static const struct file_operations g_spidrvr_fops =
spidrvr_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, spidrvr_unlink /* unlink */
#endif

View File

@ -138,7 +138,9 @@ static const struct file_operations g_spislavefops =
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
spi_slave_poll /* poll */
spi_slave_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, spi_slave_unlink /* unlink */
#endif

View File

@ -131,7 +131,9 @@ static const struct file_operations g_rtc_fops =
rtc_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, rtc_unlink /* unlink */
#endif

View File

@ -351,6 +351,8 @@ static const struct file_operations g_capture_fops =
capture_mmap, /* mmap */
NULL, /* truncate */
capture_poll, /* poll */
NULL, /* readv */
NULL, /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
capture_unlink, /* unlink */
#endif

View File

@ -65,6 +65,8 @@ static const struct file_operations g_v4l2_fops =
v4l2_mmap, /* mmap */
NULL, /* truncate */
v4l2_poll, /* poll */
NULL, /* readv */
NULL, /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
v4l2_unlink, /* unlink */
#endif

View File

@ -91,6 +91,8 @@ static const struct file_operations g_virtio_rng_ops =
NULL, /* mmap */
NULL, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
NULL, /* unlink */
#endif

View File

@ -90,6 +90,8 @@ static const struct file_operations g_virtio_rpmb_ops =
NULL, /* mmap */
NULL, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
NULL, /* unlink */
#endif

View File

@ -112,6 +112,8 @@ const struct mountpt_operations g_binfs_operations =
NULL, /* mmap */
NULL, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
NULL, /* sync */
binfs_dup, /* dup */

View File

@ -192,6 +192,8 @@ const struct mountpt_operations g_cromfs_operations =
NULL, /* mmap */
NULL, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
NULL, /* sync */
cromfs_dup, /* dup */

View File

@ -132,6 +132,9 @@ const struct mountpt_operations g_fat_operations =
NULL, /* mmap */
fat_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
fat_sync, /* sync */
fat_dup, /* dup */
fat_fstat, /* fstat */

View File

@ -148,6 +148,8 @@ const struct mountpt_operations g_hostfs_operations =
NULL, /* mmap */
hostfs_ftruncate, /* ftruncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
hostfs_sync, /* sync */
hostfs_dup, /* dup */

View File

@ -170,6 +170,8 @@ const struct mountpt_operations g_littlefs_operations =
NULL, /* mmap */
littlefs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
littlefs_sync, /* sync */
littlefs_dup, /* dup */

View File

@ -188,6 +188,8 @@ const struct mountpt_operations g_mnemofs_operations =
NULL, /* mmap */
mnemofs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
mnemofs_sync, /* sync */
mnemofs_dup, /* dup */

View File

@ -203,6 +203,8 @@ const struct mountpt_operations g_nfs_operations =
NULL, /* mmap */
nfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
nfs_sync, /* sync */
nfs_dup, /* dup */

View File

@ -62,6 +62,8 @@ const struct mountpt_operations g_nxffs_operations =
NULL, /* truncate */
#endif
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
NULL, /* sync -- No buffered data */
nxffs_dup, /* dup */

View File

@ -287,6 +287,8 @@ const struct mountpt_operations g_procfs_operations =
NULL, /* mmap */
NULL, /* truncate */
procfs_poll, /* poll */
NULL, /* readv */
NULL, /* writev */
NULL, /* sync */
procfs_dup, /* dup */

View File

@ -125,6 +125,8 @@ const struct mountpt_operations g_romfs_operations =
romfs_mmap, /* mmap */
NULL, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
NULL, /* sync */
romfs_dup, /* dup */

View File

@ -165,6 +165,8 @@ const struct mountpt_operations g_rpmsgfs_operations =
NULL, /* mmap */
rpmsgfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
rpmsgfs_sync, /* sync */
rpmsgfs_dup, /* dup */

View File

@ -74,6 +74,8 @@ const struct file_operations g_shmfs_operations =
shmfs_mmap, /* mmap */
shmfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
shmfs_unlink /* unlink */
#endif

View File

@ -145,6 +145,8 @@ const struct mountpt_operations g_smartfs_operations =
NULL, /* mmap */
smartfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
smartfs_sync, /* sync */
smartfs_dup, /* dup */

View File

@ -145,6 +145,8 @@ const struct mountpt_operations g_spiffs_operations =
NULL, /* mmap */
spiffs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
spiffs_sync, /* sync */
spiffs_dup, /* dup */

View File

@ -187,6 +187,8 @@ const struct mountpt_operations g_tmpfs_operations =
tmpfs_mmap, /* mmap */
tmpfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
tmpfs_sync, /* sync */
tmpfs_dup, /* dup */

View File

@ -230,7 +230,9 @@ const struct mountpt_operations g_unionfs_operations =
unionfs_ioctl, /* ioctl */
NULL, /* mmap */
unionfs_truncate, /* truncate */
NULL, /* pool */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
unionfs_sync, /* sync */
unionfs_dup, /* dup */

View File

@ -165,6 +165,8 @@ const struct mountpt_operations g_userfs_operations =
NULL, /* mmap */
userfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
userfs_sync, /* sync */
userfs_dup, /* dup */

View File

@ -126,6 +126,8 @@ const struct mountpt_operations g_v9fs_operations =
NULL, /* mmap */
v9fs_vfs_truncate, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
v9fs_vfs_sync, /* sync */
v9fs_vfs_dup, /* dup */

View File

@ -42,6 +42,7 @@ set(SRCS
fs_stat.c
fs_sendfile.c
fs_statfs.c
fs_uio.c
fs_unlink.c
fs_write.c
fs_dir.c

View File

@ -24,7 +24,7 @@ CSRCS += fs_chstat.c fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_epoll.c
CSRCS += fs_fchstat.c fs_fstat.c fs_fstatfs.c fs_ioctl.c fs_lseek.c
CSRCS += fs_mkdir.c fs_open.c fs_poll.c fs_pread.c fs_pwrite.c fs_read.c
CSRCS += fs_rename.c fs_rmdir.c fs_select.c fs_sendfile.c fs_stat.c
CSRCS += fs_statfs.c fs_unlink.c fs_write.c fs_dir.c fs_fsync.c
CSRCS += fs_statfs.c fs_uio.c fs_unlink.c fs_write.c fs_dir.c fs_fsync.c
CSRCS += fs_syncfs.c fs_truncate.c
# Certain interfaces are not available if there is no mountpoint support

View File

@ -109,12 +109,12 @@ static int proxy_fstat(FAR struct file *filep, FAR struct inode *inode,
{
memset(buf, 0, sizeof(struct stat));
buf->st_mode = S_IFBLK;
if (inode->u.i_ops->read)
if (inode->u.i_ops->readv || inode->u.i_ops->read)
{
buf->st_mode |= S_IROTH | S_IRGRP | S_IRUSR;
}
if (inode->u.i_ops->write)
if (inode->u.i_ops->writev || inode->u.i_ops->read)
{
buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR;
}

View File

@ -78,8 +78,8 @@ static int inode_checkflags(FAR struct inode *inode, int oflags)
return -ENXIO;
}
if (((oflags & O_RDOK) != 0 && !ops->read && !ops->ioctl) ||
((oflags & O_WROK) != 0 && !ops->write && !ops->ioctl))
if (((oflags & O_RDOK) != 0 && !ops->readv && !ops->read && !ops->ioctl) ||
((oflags & O_WROK) != 0 && !ops->writev && !ops->write && !ops->ioctl))
{
return -EACCES;
}

View File

@ -36,10 +36,152 @@
#include "notify/notify.h"
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: file_readv_compat
*
* Description:
* Emulate readv using file_operation::read.
*
****************************************************************************/
static ssize_t file_readv_compat(FAR struct file *filep,
FAR const struct uio *uio)
{
FAR const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
FAR struct inode *inode = filep->f_inode;
ssize_t ntotal;
ssize_t nread;
size_t remaining;
FAR uint8_t *buffer;
int i;
DEBUGASSERT(inode->u.i_ops->read != NULL);
/* Process each entry in the struct iovec array */
for (i = 0, ntotal = 0; i < iovcnt; i++)
{
/* Ignore zero-length reads */
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);
}
}
return ntotal;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_readv
*
* Description:
* file_readv() is an internal OS interface. It is functionally similar to
* the standard readv() interface except:
*
* - It does not modify the errno variable,
* - It is not a cancellation point,
* - It accepts a file structure instance instead of file descriptor.
*
* Input Parameters:
* filep - File structure instance
* uio - User buffer information
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or a negated errno value on any failure.
*
****************************************************************************/
ssize_t file_readv(FAR struct file *filep, FAR const struct uio *uio)
{
FAR struct inode *inode;
ssize_t ret = -EBADF;
DEBUGASSERT(filep);
inode = filep->f_inode;
/* Was this file opened for read access? */
if ((filep->f_oflags & O_RDOK) == 0)
{
/* No.. File is not read-able */
ret = -EACCES;
}
/* Is a driver or mountpoint registered? If so, does it support the read
* method?
* If yes, then let it perform the read. NOTE that for the case of the
* mountpoint, we depend on the read methods being identical in
* signature and position in the operations vtable.
*/
else if (inode != NULL && inode->u.i_ops)
{
if (inode->u.i_ops->readv)
{
ret = inode->u.i_ops->readv(filep, uio);
}
else if (inode->u.i_ops->read)
{
ret = file_readv_compat(filep, uio);
}
}
/* Return the number of bytes read (or possibly an error code) */
#ifdef CONFIG_FS_NOTIFY
if (ret > 0)
{
notify_read(filep);
}
#endif
return ret;
}
/****************************************************************************
* Name: file_read
*
@ -64,46 +206,59 @@
ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
{
FAR struct inode *inode;
ssize_t ret = -EBADF;
struct iovec iov;
struct uio uio;
DEBUGASSERT(filep);
inode = filep->f_inode;
iov.iov_base = buf;
iov.iov_len = nbytes;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
return file_readv(filep, &uio);
}
/* Was this file opened for read access? */
/****************************************************************************
* Name: nx_readv
*
* Description:
* nx_readv() is an internal OS interface. It is functionally similar to
* the standard readv() interface except:
*
* - It does not modify the errno variable, and
* - It is not a cancellation point.
*
* Input Parameters:
* fd - File descriptor to read from
* iov - User-provided iovec to save the data
* iovcnt - The number of iovec
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or a negated errno value on any failure.
*
****************************************************************************/
if ((filep->f_oflags & O_RDOK) == 0)
{
/* No.. File is not read-able */
ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt)
{
struct uio uio;
FAR struct file *filep;
ssize_t ret;
ret = -EACCES;
}
/* Is a driver or mountpoint registered? If so, does it support the read
* method?
/* First, get the file structure. Note that on failure,
* fs_getfilep() will return the errno.
*/
else if (inode != NULL && inode->u.i_ops && inode->u.i_ops->read)
ret = (ssize_t)fs_getfilep(fd, &filep);
if (ret < 0)
{
/* Yes.. then let it perform the read. NOTE that for the case of the
* mountpoint, we depend on the read methods being identical in
* signature and position in the operations vtable.
*/
ret = inode->u.i_ops->read(filep,
(FAR char *)buf,
(size_t)nbytes);
return ret;
}
/* Return the number of bytes read (or possibly an error code) */
#ifdef CONFIG_FS_NOTIFY
if (ret > 0)
{
notify_read(filep);
}
#endif
/* Then let file_read do all of the work. */
uio.uio_iov = iov;
uio.uio_iovcnt = iovcnt;
ret = file_readv(filep, &uio);
fs_putfilep(filep);
return ret;
}
@ -130,23 +285,48 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes)
ssize_t nx_read(int fd, FAR void *buf, size_t nbytes)
{
FAR struct file *filep;
struct iovec iov;
iov.iov_base = buf;
iov.iov_len = nbytes;
return nx_readv(fd, &iov, 1);
}
/****************************************************************************
* Name: readv
*
* Description:
* The standard, POSIX read interface.
*
* Input Parameters:
* fd - File descriptor to read from
* iov - User-provided iovec to save the data
* iovcnt - The number of iovec
*
* Returned Value:
* The positive non-zero number of bytes read on success, 0 on if an
* end-of-file condition, or -1 on failure with errno set appropriately.
*
****************************************************************************/
ssize_t readv(int fd, FAR const struct iovec *iov, int iovcnt)
{
ssize_t ret;
/* First, get the file structure. Note that on failure,
* fs_getfilep() will return the errno.
*/
/* readv() is a cancellation point */
ret = (ssize_t)fs_getfilep(fd, &filep);
enter_cancellation_point();
/* Let nx_readv() do the real work */
ret = nx_readv(fd, iov, iovcnt);
if (ret < 0)
{
return ret;
set_errno(-ret);
ret = ERROR;
}
/* Then let file_read do all of the work. */
ret = file_read(filep, buf, nbytes);
fs_putfilep(filep);
leave_cancellation_point();
return ret;
}
@ -169,21 +349,9 @@ ssize_t nx_read(int fd, FAR void *buf, size_t nbytes)
ssize_t read(int fd, FAR void *buf, size_t nbytes)
{
ssize_t ret;
struct iovec iov;
/* read() is a cancellation point */
enter_cancellation_point();
/* Let nx_read() do the real work */
ret = nx_read(fd, buf, nbytes);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
leave_cancellation_point();
return ret;
iov.iov_base = buf;
iov.iov_len = nbytes;
return readv(fd, &iov, 1);
}

View File

@ -379,12 +379,12 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve)
* and write methods.
*/
if (inode->u.i_ops->read)
if (inode->u.i_ops->readv || inode->u.i_ops->read)
{
buf->st_mode = S_IROTH | S_IRGRP | S_IRUSR;
}
if (inode->u.i_ops->write)
if (inode->u.i_ops->writev || inode->u.i_ops->write)
{
buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR;
}

View File

@ -82,7 +82,7 @@ int file_truncate(FAR struct file *filep, off_t length)
* possible not the only indicator -- sufficient, but not necessary")
*/
if (inode->u.i_ops->write == NULL)
if (inode->u.i_ops->writev == NULL && inode->u.i_ops->write == NULL)
{
fwarn("WARNING: File system is read-only\n");
return -EROFS;

66
fs/vfs/fs_uio.c Normal file
View File

@ -0,0 +1,66 @@
/****************************************************************************
* fs/vfs/fs_uio.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <nuttx/fs/fs.h>
#include <assert.h>
#include <errno.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: uio_total_len
*
* Description:
* Return the total length of data in bytes.
* Or -EOVERFLOW.
*
****************************************************************************/
ssize_t uio_total_len(FAR const struct uio *uio)
{
const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
size_t len = 0;
int i;
for (i = 0; i < iovcnt; i++)
{
if (SSIZE_MAX - len < iov[i].iov_len)
{
return -EOVERFLOW;
}
len += iov[i].iov_len;
}
return len;
}

View File

@ -36,10 +36,139 @@
#include "notify/notify.h"
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: file_writev_compat
*
* Description:
* Emulate writev using file_operation::write.
*
****************************************************************************/
static ssize_t file_writev_compat(FAR struct file *filep,
FAR const struct uio *uio)
{
FAR const struct iovec *iov = uio->uio_iov;
int iovcnt = uio->uio_iovcnt;
FAR struct inode *inode = filep->f_inode;
ssize_t ntotal;
ssize_t nwritten;
size_t remaining;
FAR uint8_t *buffer;
int i;
DEBUGASSERT(inode->u.i_ops->write != NULL);
/* Process each entry in the struct iovec array */
for (i = 0, ntotal = 0; i < iovcnt; i++)
{
/* Ignore zero-length writes */
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);
}
}
return ntotal;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_writev
*
* Description:
* Equivalent to the standard writev() function except that is accepts a
* struct file instance instead of a file descriptor. It is functionally
* equivalent to writev() except that in addition to the differences in
* input parameters:
*
* - It does not modify the errno variable,
* - It is not a cancellation point, and
*
* Input Parameters:
* filep - Instance of struct file to use with the write
* uio - User buffer information
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On any failure, a negated errno value is returned
* (see comments withwrite() for a description of the appropriate errno
* values).
*
****************************************************************************/
ssize_t file_writev(FAR struct file *filep, FAR const struct uio *uio)
{
FAR struct inode *inode;
ssize_t ret = -EBADF;
/* Was this file opened for write access? */
if ((filep->f_oflags & O_WROK) == 0)
{
return -EACCES;
}
/* Is a driver registered? Does it support the write method?
* If yes, then let the driver perform the write.
*/
inode = filep->f_inode;
if (inode != NULL && inode->u.i_ops)
{
if (inode->u.i_ops->writev)
{
ret = inode->u.i_ops->writev(filep, uio);
}
else if (inode->u.i_ops->write)
{
ret = file_writev_compat(filep, uio);
}
}
#ifdef CONFIG_FS_NOTIFY
if (ret > 0)
{
notify_write(filep);
}
#endif
return ret;
}
/****************************************************************************
* Name: file_write
*
@ -68,34 +197,64 @@
ssize_t file_write(FAR struct file *filep, FAR const void *buf,
size_t nbytes)
{
FAR struct inode *inode;
struct iovec iov;
struct uio uio;
iov.iov_base = (FAR void *)buf;
iov.iov_len = nbytes;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
return file_writev(filep, &uio);
}
/****************************************************************************
* Name: nx_writev
*
* Description:
* nx_writev() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf. nx_writev() is an
* internal OS function. It is functionally equivalent to writev() except
* that:
*
* - It does not modify the errno variable, and
* - It is not a cancellation point.
*
* Input Parameters:
* fd - file descriptor to write to
* iov - Data to write
* iovcnt - The number of vectors
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On any failure, a negated errno value is returned
* (see comments withwrite() for a description of the appropriate errno
* values).
*
****************************************************************************/
ssize_t nx_writev(int fd, FAR const struct iovec *iov, int iovcnt)
{
struct uio uio;
FAR struct file *filep;
ssize_t ret;
/* Was this file opened for write access? */
/* First, get the file structure.
* Note that fs_getfilep() will return the errno on failure.
*/
if ((filep->f_oflags & O_WROK) == 0)
ret = (ssize_t)fs_getfilep(fd, &filep);
if (ret >= 0)
{
return -EACCES;
/* Perform the write operation using the file descriptor as an
* index. Note that file_write() will return the errno on failure.
*/
uio.uio_iov = iov;
uio.uio_iovcnt = iovcnt;
ret = file_writev(filep, &uio);
fs_putfilep(filep);
}
/* Is a driver registered? Does it support the write method? */
inode = filep->f_inode;
if (!inode || !inode->u.i_ops || !inode->u.i_ops->write)
{
return -EBADF;
}
/* Yes, then let the driver perform the write */
ret = inode->u.i_ops->write(filep, buf, nbytes);
#ifdef CONFIG_FS_NOTIFY
if (ret > 0)
{
notify_write(filep);
}
#endif
return ret;
}
@ -126,29 +285,79 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf,
ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes)
{
FAR struct file *filep;
struct iovec iov;
iov.iov_base = (void *)buf;
iov.iov_len = nbytes;
return nx_writev(fd, &iov, 1);
}
/****************************************************************************
* Name: writev
*
* Description:
* writev() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf.
*
* Input Parameters:
* fd - file descriptor to write to
* iov - Data to write
* iovcnt - The number of vectors
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On error, -1 is returned, and errno is set appro-
* priately:
*
* EAGAIN
* Non-blocking I/O has been selected using O_NONBLOCK and the write
* would block.
* EBADF
* fd is not a valid file descriptor or is not open for writing.
* EFAULT
* buf is outside your accessible address space.
* EFBIG
* An attempt was made to write a file that exceeds the implementation
* defined maximum file size or the process's file size limit, or
* to write at a position past the maximum allowed offset.
* EINTR
* The call was interrupted by a signal before any data was written.
* EINVAL
* fd is attached to an object which is unsuitable for writing; or
* the file was opened with the O_DIRECT flag, and either the address
* specified in buf, the value specified in count, or the current
* file offset is not suitably aligned.
* EIO
* A low-level I/O error occurred while modifying the inode.
* ENOSPC
* The device containing the file referred to by fd has no room for
* the data.
* EPIPE
* fd is connected to a pipe or socket whose reading end is closed.
* When this happens the writing process will also receive a SIGPIPE
* signal. (Thus, the write return value is seen only if the program
* catches, blocks or ignores this signal.)
*
****************************************************************************/
ssize_t writev(int fd, FAR const struct iovec *iov, int iovcnt)
{
ssize_t ret;
if (buf == NULL)
/* write() is a cancellation point */
enter_cancellation_point();
/* Let nx_write() do all of the work */
ret = nx_writev(fd, iov, iovcnt);
if (ret < 0)
{
return -EINVAL;
}
/* First, get the file structure.
* Note that fs_getfilep() will return the errno on failure.
*/
ret = (ssize_t)fs_getfilep(fd, &filep);
if (ret >= 0)
{
/* Perform the write operation using the file descriptor as an
* index. Note that file_write() will return the errno on failure.
*/
ret = file_write(filep, buf, nbytes);
fs_putfilep(filep);
set_errno(-ret);
ret = ERROR;
}
leave_cancellation_point();
return ret;
}
@ -202,21 +411,9 @@ ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes)
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
{
ssize_t ret;
struct iovec iov;
/* write() is a cancellation point */
enter_cancellation_point();
/* Let nx_write() do all of the work */
ret = nx_write(fd, buf, nbytes);
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
leave_cancellation_point();
return ret;
iov.iov_base = (void *)buf;
iov.iov_len = nbytes;
return writev(fd, &iov, 1);
}

View File

@ -137,6 +137,8 @@ const struct mountpt_operations g_zipfs_operations =
NULL, /* mmap */
NULL, /* truncate */
NULL, /* poll */
NULL, /* readv */
NULL, /* writev */
NULL, /* sync */
zipfs_dup, /* dup */

View File

@ -70,7 +70,9 @@ const struct file_operations g_nxterm_drvrops =
nxterm_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
nxterm_poll /* poll */
nxterm_poll, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, nxterm_unlink /* unlink */
#endif
@ -88,7 +90,9 @@ const struct file_operations g_nxterm_drvrops =
nxterm_ioctl, /* ioctl */
NULL, /* mmap */
NULL, /* truncate */
NULL /* poll */
NULL, /* poll */
NULL, /* readv */
NULL /* writev */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, nxterm_unlink /* unlink */
#endif

View File

@ -28,9 +28,13 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <nuttx/compiler.h>
#include <nuttx/fs/uio.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
@ -183,6 +187,7 @@ struct statfs;
struct pollfd;
struct mtd_dev_s;
struct tcb_s;
struct uio;
/* The internal representation of type DIR is just a container for an inode
* reference, and the path of directory.
@ -233,6 +238,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);
/* The two structures need not be common after this point */
@ -329,6 +336,9 @@ 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);
/* The two structures need not be common after this point. The following
* are extended methods needed to deal with the unique needs of mounted
* file systems.
@ -1416,6 +1426,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);
/****************************************************************************
* Name: nx_read
@ -1439,6 +1450,7 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
****************************************************************************/
ssize_t nx_read(int fd, FAR void *buf, size_t nbytes);
ssize_t nx_readv(int fd, FAR const struct iovec *iov, int iovcnt);
/****************************************************************************
* Name: file_write
@ -1468,6 +1480,7 @@ ssize_t nx_read(int fd, FAR void *buf, size_t nbytes);
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);
/****************************************************************************
* Name: nx_write
@ -1495,6 +1508,7 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf,
****************************************************************************/
ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes);
ssize_t nx_writev(int fd, FAR const struct iovec *iov, int iovcnt);
/****************************************************************************
* Name: file_pread

65
include/nuttx/fs/uio.h Normal file
View File

@ -0,0 +1,65 @@
/****************************************************************************
* include/nuttx/fs/uio.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_FS_UIO_H
#define __INCLUDE_NUTTX_FS_UIO_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/* The structure to describe an user I/O operation.
*
* At this point, this is a bare minimum for readv/writev.
* In the future, we might extend this for other things like
* the file offset for pread/pwrite.
*
* This structure was inspired by BSDs.
* (Thus it doesn't have the NuttX-style "_s" suffix.)
*/
struct uio
{
FAR const struct iovec *uio_iov;
int uio_iovcnt;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: uio_total_len
*
* Description:
* Return the total length of data in bytes.
* Or -EOVERFLOW.
*
****************************************************************************/
ssize_t uio_total_len(FAR const struct uio *uio);
#endif /* __INCLUDE_NUTTX_FS_UIO_H */

View File

@ -200,6 +200,8 @@ SYSCALL_LOOKUP(close, 1)
SYSCALL_LOOKUP(ioctl, 3)
SYSCALL_LOOKUP(read, 3)
SYSCALL_LOOKUP(write, 3)
SYSCALL_LOOKUP(readv, 3)
SYSCALL_LOOKUP(writev, 3)
SYSCALL_LOOKUP(pread, 4)
SYSCALL_LOOKUP(pwrite, 4)
#ifdef CONFIG_FS_AIO

View File

@ -20,4 +20,4 @@
#
# ##############################################################################
target_sources(c PRIVATE lib_readv.c lib_writev.c lib_preadv.c lib_pwritev.c)
target_sources(c PRIVATE lib_preadv.c lib_pwritev.c)

View File

@ -22,7 +22,6 @@
# Add the uio.h C files to the build
CSRCS += lib_readv.c lib_writev.c
CSRCS += lib_preadv.c lib_pwritev.c
# Add the uio.h directory to the build

View File

@ -1,125 +0,0 @@
/****************************************************************************
* libs/libc/uio/lib_readv.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: readv()
*
* Description:
* The readv() function is equivalent to read(), except as described below.
* The readv() function places the input data into the 'iovcnt' buffers
* specified by the members of the 'iov' array: iov[0], iov[1], ...,
* iov['iovcnt'-1]. The 'iovcnt' argument is valid if greater than 0 and
* less than or equal to IOV_MAX as defined in limits.h.
*
* Each iovec entry specifies the base address and length of an area in
* memory where data should be placed. The readv() function will always
* fill an area completely before proceeding to the next.
*
* TODO: pon successful completion, readv() will mark for update the
* st_atime field of the file.
*
* Input Parameters:
* filedes - The open file descriptor for the file to be read
* iov - Array of read buffer descriptors
* iovcnt - Number of elements in iov[]
*
* Returned Value:
* Upon successful completion, readv() will return a non-negative integer
* indicating the number of bytes actually read. Otherwise, the functions
* will return -1 and set errno to indicate the error. See read() for the
* list of returned errno values. In addition, the readv() function will
* fail if:
*
* EINVAL.
* The sum of the iov_len values in the iov array overflowed an ssize_t
* or The 'iovcnt' argument was less than or equal to 0, or greater than
* IOV_MAX (Not implemented).
*
****************************************************************************/
ssize_t readv(int fildes, FAR const struct iovec *iov, int iovcnt)
{
ssize_t ntotal;
ssize_t nread;
size_t remaining;
FAR uint8_t *buffer;
int i;
/* Process each entry in the struct iovec array */
for (i = 0, ntotal = 0; i < iovcnt; i++)
{
/* Ignore zero-length reads */
if (iov[i].iov_len > 0)
{
buffer = iov[i].iov_base;
remaining = iov[i].iov_len;
/* Read repeatedly as necessary to fill buffer */
do
{
/* NOTE: read() is a cancellation point */
nread = read(fildes, buffer, remaining);
/* Check for a read error */
if (nread < 0)
{
return 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);
}
}
return ntotal;
}

View File

@ -1,124 +0,0 @@
/****************************************************************************
* libs/libc/uio/lib_writev.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: writev()
*
* Description:
* The writev() function is equivalent to write(), except as described
* below. The writev() function will gather output data from the 'iovcnt'
* buffers specified by the members of the 'iov' array:
* iov[0], iov[1], ..., iov[iovcnt-1].
* The 'iovcnt' argument is valid if greater than 0 and less than or equal
* to IOV_MAX, as defined in limits.h.
*
* Each iovec entry specifies the base address and length of an area in
* memory from which data should be written. The writev() function always
* writes a complete area before proceeding to the next.
*
* If 'filedes' refers to a regular file and all of the iov_len members in
* the array pointed to by iov are 0, writev() will return 0 and have no
* other effect. For other file types, the behavior is unspecified.
*
* TODO: If the sum of the iov_len values is greater than SSIZE_MAX, the
* operation will fail and no data will be transferred.
*
* Input Parameters:
* filedes - The open file descriptor for the file to be write
* iov - Array of write buffer descriptors
* iovcnt - Number of elements in iov[]
*
* Returned Value:
* Upon successful completion, writev() shall return the number of bytes
* actually written. Otherwise, it shall return a value of -1, the file-
* pointer shall remain unchanged, and errno shall be set to indicate an
* error. See write for the list of returned errno values. In addition,
* the writev() function will fail if:
*
* EINVAL.
* The sum of the iov_len values in the iov array overflowed an ssize_t
* or The 'iovcnt' argument was less than or equal to 0, or greater than
* IOV_MAX (Not implemented).
*
****************************************************************************/
ssize_t writev(int fildes, FAR const struct iovec *iov, int iovcnt)
{
ssize_t ntotal;
ssize_t nwritten;
size_t remaining;
FAR uint8_t *buffer;
int i;
/* Process each entry in the struct iovec array */
for (i = 0, ntotal = 0; i < iovcnt; i++)
{
/* Ignore zero-length writes */
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
{
/* NOTE: write() is a cancellation point */
nwritten = write(fildes, buffer, remaining);
/* Check for a write error */
if (nwritten < 0)
{
return ntotal ? ntotal : ERROR;
}
/* Update pointers and counts in order to handle partial
* buffer writes.
*/
buffer += nwritten;
remaining -= nwritten;
ntotal += nwritten;
}
while (remaining > 0);
}
}
return ntotal;
}

View File

@ -128,6 +128,7 @@
"putenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *"
"pwrite","unistd.h","","ssize_t","int","FAR const void *","size_t","off_t"
"read","unistd.h","","ssize_t","int","FAR void *","size_t"
"readv","sys/uio.h","","ssize_t","int","FAR const struct iovec *","int"
"readlink","unistd.h","defined(CONFIG_PSEUDOFS_SOFTLINKS)","ssize_t","FAR const char *","FAR char *","size_t"
"recv","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR void *","size_t","int"
"recvfrom","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR void*","size_t","int","FAR struct sockaddr*","FAR socklen_t*"
@ -208,3 +209,4 @@
"waitid","sys/wait.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)","int","idtype_t","id_t"," FAR siginfo_t *","int"
"waitpid","sys/wait.h","defined(CONFIG_SCHED_WAITPID)","pid_t","pid_t","FAR int *","int"
"write","unistd.h","","ssize_t","int","FAR const void *","size_t"
"writev","sys/uio.h","","ssize_t","int","FAR const struct iovec *","int"

Can't render this file because it has a wrong number of fields in line 2.