Skip to content

Commit 2d72966

Browse files
cfriedtnashif
authored andcommitted
posix: device_io: implement pread() and pwrite()
Add pread() and pwrite() implementations, which are nearly identical to read() and write() but differ in that they do not update the file-descriptor offset and instead read from a specific file offset. Signed-off-by: Chris Friedt <[email protected]>
1 parent 86b9293 commit 2d72966

File tree

2 files changed

+69
-17
lines changed

2 files changed

+69
-17
lines changed

lib/os/fdtable.c

+41-13
Original file line numberDiff line numberDiff line change
@@ -308,34 +308,62 @@ int zvfs_alloc_fd(void *obj, const struct fd_op_vtable *vtable)
308308
return fd;
309309
}
310310

311-
static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write)
311+
static bool supports_pread_pwrite(uint32_t mode)
312312
{
313+
switch (mode & ZVFS_MODE_IFMT) {
314+
case ZVFS_MODE_IFSHM:
315+
return true;
316+
default:
317+
return false;
318+
}
319+
}
320+
321+
static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write, const size_t *from_offset)
322+
{
323+
bool prw;
313324
ssize_t res;
325+
const size_t *off;
314326

315327
if (_check_fd(fd) < 0) {
316328
return -1;
317329
}
318330

319331
(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
320332

333+
prw = supports_pread_pwrite(fdtable[fd].mode);
334+
if (from_offset != NULL && !prw) {
335+
/*
336+
* Seekable file types should support pread() / pwrite() and per-fd offset passing.
337+
* Otherwise, it's a bug.
338+
*/
339+
errno = ENOTSUP;
340+
res = -1;
341+
goto unlock;
342+
}
343+
344+
/* If there is no specified from_offset, then use the current offset of the fd */
345+
off = (from_offset == NULL) ? &fdtable[fd].offset : from_offset;
346+
321347
if (is_write) {
322-
if (fdtable[fd].vtable->write_offset == NULL) {
348+
if (fdtable[fd].vtable->write_offs == NULL) {
323349
res = -1;
324350
errno = EIO;
325351
} else {
326-
res = fdtable[fd].vtable->write_offset(fdtable[fd].obj, buf, sz,
327-
fdtable[fd].offset);
352+
res = fdtable[fd].vtable->write_offs(fdtable[fd].obj, buf, sz, *off);
328353
}
329354
} else {
330-
if (fdtable[fd].vtable->read == NULL) {
355+
if (fdtable[fd].vtable->read_offs == NULL) {
331356
res = -1;
332357
errno = EIO;
333358
} else {
334-
res = fdtable[fd].vtable->read_offset(fdtable[fd].obj, buf, sz,
335-
fdtable[fd].offset);
359+
res = fdtable[fd].vtable->read_offs(fdtable[fd].obj, buf, sz, *off);
336360
}
337361
}
338-
if (res > 0) {
362+
if (res > 0 && prw && from_offset == NULL) {
363+
/*
364+
* only update the fd offset when from_offset is not specified
365+
* See pread() / pwrite()
366+
*/
339367
fdtable[fd].offset += res;
340368
}
341369

@@ -345,14 +373,14 @@ static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write)
345373
return res;
346374
}
347375

348-
ssize_t zvfs_read(int fd, void *buf, size_t sz)
376+
ssize_t zvfs_read(int fd, void *buf, size_t sz, const size_t *from_offset)
349377
{
350-
return zvfs_rw(fd, buf, sz, false);
378+
return zvfs_rw(fd, buf, sz, false, from_offset);
351379
}
352380

353-
ssize_t zvfs_write(int fd, const void *buf, size_t sz)
381+
ssize_t zvfs_write(int fd, const void *buf, size_t sz, const size_t *from_offset)
354382
{
355-
return zvfs_rw(fd, (void *)buf, sz, true);
383+
return zvfs_rw(fd, (void *)buf, sz, true, from_offset);
356384
}
357385

358386
int zvfs_close(int fd)
@@ -494,7 +522,7 @@ static ssize_t stdinout_read_vmeth(void *obj, void *buffer, size_t count)
494522
static ssize_t stdinout_write_vmeth(void *obj, const void *buffer, size_t count)
495523
{
496524
#if defined(CONFIG_BOARD_NATIVE_POSIX)
497-
return zvfs_write(1, buffer, count);
525+
return zvfs_write(1, buffer, count, NULL);
498526
#elif defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_ARCMWDT_LIBC)
499527
return z_impl_zephyr_write_stdout(buffer, count);
500528
#else

lib/posix/options/device_io.c

+28-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
/* prototypes for external, not-yet-public, functions in fdtable.c or fs.c */
1616
int zvfs_close(int fd);
1717
int zvfs_open(const char *name, int flags);
18-
ssize_t zvfs_read(int fd, void *buf, size_t sz);
19-
ssize_t zvfs_write(int fd, const void *buf, size_t sz);
18+
ssize_t zvfs_read(int fd, void *buf, size_t sz, size_t *from_offset);
19+
ssize_t zvfs_write(int fd, const void *buf, size_t sz, size_t *from_offset);
2020

2121
int close(int fd)
2222
{
@@ -41,9 +41,33 @@ int poll(struct pollfd *fds, int nfds, int timeout)
4141
return zsock_poll(fds, nfds, timeout);
4242
}
4343

44+
ssize_t pread(int fd, void *buf, size_t count, off_t offset)
45+
{
46+
size_t off = (size_t)offset;
47+
48+
if (offset < 0) {
49+
errno = EINVAL;
50+
return -1;
51+
}
52+
53+
return zvfs_read(fd, buf, count, (size_t *)&off);
54+
}
55+
56+
ssize_t pwrite(int fd, void *buf, size_t count, off_t offset)
57+
{
58+
size_t off = (size_t)offset;
59+
60+
if (offset < 0) {
61+
errno = EINVAL;
62+
return -1;
63+
}
64+
65+
return zvfs_write(fd, buf, count, (size_t *)&off);
66+
}
67+
4468
ssize_t read(int fd, void *buf, size_t sz)
4569
{
46-
return zvfs_read(fd, buf, sz);
70+
return zvfs_read(fd, buf, sz, NULL);
4771
}
4872
#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_READ
4973
FUNC_ALIAS(read, _read, ssize_t);
@@ -57,7 +81,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
5781

5882
ssize_t write(int fd, const void *buf, size_t sz)
5983
{
60-
return zvfs_write(fd, buf, sz);
84+
return zvfs_write(fd, buf, sz, NULL);
6185
}
6286
#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_WRITE
6387
FUNC_ALIAS(write, _write, ssize_t);

0 commit comments

Comments
 (0)