Skip to content

Commit a9a909c

Browse files
cfriedtnashif
authored andcommitted
fdtable: read, write, close: only execute methods if non-NULL
Only invoke vtable methods read, write, and close if they are non-NULL. The close() vtable method is optional, so that should not return an error if zvfs_close() is called and that method is unimplemented. Otherwise, if zvfs_read() or zvfs_write() are called and the corresponding vtable method is unimplemented, fail setting errno to EIO. Signed-off-by: Chris Friedt <[email protected]>
1 parent d1eea36 commit a9a909c

File tree

1 file changed

+33
-39
lines changed

1 file changed

+33
-39
lines changed

lib/os/fdtable.c

+33-39
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ int zvfs_alloc_fd(void *obj, const struct fd_op_vtable *vtable)
301301
return fd;
302302
}
303303

304-
ssize_t zvfs_read(int fd, void *buf, size_t sz)
304+
static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write)
305305
{
306306
ssize_t res;
307307

@@ -310,63 +310,57 @@ ssize_t zvfs_read(int fd, void *buf, size_t sz)
310310
}
311311

312312
(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
313-
res = fdtable[fd].vtable->read_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset);
314-
if (res > 0) {
315-
switch (fdtable[fd].mode & ZVFS_MODE_IFMT) {
316-
case ZVFS_MODE_IFDIR:
317-
case ZVFS_MODE_IFBLK:
318-
case ZVFS_MODE_IFSHM:
319-
case ZVFS_MODE_IFREG:
320-
fdtable[fd].offset += res;
321-
break;
322-
default:
323-
break;
313+
314+
if (is_write) {
315+
if (fdtable[fd].vtable->write_offset == NULL) {
316+
res = -1;
317+
errno = EIO;
318+
} else {
319+
res = fdtable[fd].vtable->write_offset(fdtable[fd].obj, buf, sz,
320+
fdtable[fd].offset);
324321
}
322+
} else {
323+
if (fdtable[fd].vtable->read == NULL) {
324+
res = -1;
325+
errno = EIO;
326+
} else {
327+
res = fdtable[fd].vtable->read_offset(fdtable[fd].obj, buf, sz,
328+
fdtable[fd].offset);
329+
}
330+
}
331+
if (res > 0) {
332+
fdtable[fd].offset += res;
325333
}
334+
335+
unlock:
326336
k_mutex_unlock(&fdtable[fd].lock);
327337

328338
return res;
329339
}
330340

331-
ssize_t zvfs_write(int fd, const void *buf, size_t sz)
341+
ssize_t zvfs_read(int fd, void *buf, size_t sz)
332342
{
333-
ssize_t res;
334-
335-
if (_check_fd(fd) < 0) {
336-
return -1;
337-
}
338-
339-
(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
340-
res = fdtable[fd].vtable->write_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset);
341-
if (res > 0) {
342-
switch (fdtable[fd].mode & ZVFS_MODE_IFMT) {
343-
case ZVFS_MODE_IFDIR:
344-
case ZVFS_MODE_IFBLK:
345-
case ZVFS_MODE_IFSHM:
346-
case ZVFS_MODE_IFREG:
347-
fdtable[fd].offset += res;
348-
break;
349-
default:
350-
break;
351-
}
352-
}
353-
k_mutex_unlock(&fdtable[fd].lock);
343+
return zvfs_rw(fd, buf, sz, false);
344+
}
354345

355-
return res;
346+
ssize_t zvfs_write(int fd, const void *buf, size_t sz)
347+
{
348+
return zvfs_rw(fd, (void *)buf, sz, true);
356349
}
357350

358351
int zvfs_close(int fd)
359352
{
360-
int res;
353+
int res = 0;
361354

362355
if (_check_fd(fd) < 0) {
363356
return -1;
364357
}
365358

366359
(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
367-
368-
res = fdtable[fd].vtable->close(fdtable[fd].obj);
369-
360+
if (fdtable[fd].vtable->close != NULL) {
361+
/* close() is optional - e.g. stdinout_fd_op_vtable */
362+
res = fdtable[fd].vtable->close(fdtable[fd].obj);
363+
}
370364
k_mutex_unlock(&fdtable[fd].lock);
371365

372366
zvfs_free_fd(fd);

0 commit comments

Comments
 (0)