Commit 6f766a00 authored by Chris Friedt's avatar Chris Friedt Committed by Henrik Brix Andersen
Browse files

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: default avatarChris Friedt <cfriedt@tenstorrent.com>
parent eac7e604
Loading
Loading
Loading
Loading
+34 −39
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018 Linaro Limited
 * Copyright (c) 2024 Tenstorrent AI ULC
 *
 * SPDX-License-Identifier: Apache-2.0
 */
@@ -301,7 +302,7 @@ int zvfs_alloc_fd(void *obj, const struct fd_op_vtable *vtable)
	return fd;
}

ssize_t zvfs_read(int fd, void *buf, size_t sz)
static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write)
{
	ssize_t res;

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

	(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
	res = fdtable[fd].vtable->read_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset);

	if (is_write) {
		if (fdtable[fd].vtable->write_offset == NULL) {
			res = -1;
			errno = EIO;
		} else {
			res = fdtable[fd].vtable->write_offset(fdtable[fd].obj, buf, sz,
							       fdtable[fd].offset);
		}
	} else {
		if (fdtable[fd].vtable->read == NULL) {
			res = -1;
			errno = EIO;
		} else {
			res = fdtable[fd].vtable->read_offset(fdtable[fd].obj, buf, sz,
							      fdtable[fd].offset);
		}
	}
	if (res > 0) {
		switch (fdtable[fd].mode & ZVFS_MODE_IFMT) {
		case ZVFS_MODE_IFDIR:
		case ZVFS_MODE_IFBLK:
		case ZVFS_MODE_IFSHM:
		case ZVFS_MODE_IFREG:
		fdtable[fd].offset += res;
			break;
		default:
			break;
		}
	}

unlock:
	k_mutex_unlock(&fdtable[fd].lock);

	return res;
}

ssize_t zvfs_write(int fd, const void *buf, size_t sz)
ssize_t zvfs_read(int fd, void *buf, size_t sz)
{
	ssize_t res;

	if (_check_fd(fd) < 0) {
		return -1;
	return zvfs_rw(fd, buf, sz, false);
}

	(void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER);
	res = fdtable[fd].vtable->write_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset);
	if (res > 0) {
		switch (fdtable[fd].mode & ZVFS_MODE_IFMT) {
		case ZVFS_MODE_IFDIR:
		case ZVFS_MODE_IFBLK:
		case ZVFS_MODE_IFSHM:
		case ZVFS_MODE_IFREG:
			fdtable[fd].offset += res;
			break;
		default:
			break;
		}
	}
	k_mutex_unlock(&fdtable[fd].lock);

	return res;
ssize_t zvfs_write(int fd, const void *buf, size_t sz)
{
	return zvfs_rw(fd, (void *)buf, sz, true);
}

int zvfs_close(int fd)
{
	int res;
	int res = 0;

	if (_check_fd(fd) < 0) {
		return -1;
	}

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

	if (fdtable[fd].vtable->close != NULL) {
		/* close() is optional - e.g. stdinout_fd_op_vtable */
		res = fdtable[fd].vtable->close(fdtable[fd].obj);

	}
	k_mutex_unlock(&fdtable[fd].lock);

	zvfs_free_fd(fd);