diff --git a/include/misc/fdtable.h b/include/misc/fdtable.h index 0770bb1b267..18e3536c1b8 100644 --- a/include/misc/fdtable.h +++ b/include/misc/fdtable.h @@ -6,6 +6,7 @@ #ifndef ZEPHYR_INCLUDE_POSIX_POSIX__FDTABLE_H_ #define ZEPHYR_INCLUDE_POSIX_POSIX__FDTABLE_H_ +#include #include /* FIXME: For native_posix ssize_t, off_t. */ #include @@ -21,7 +22,7 @@ extern "C" { struct fd_op_vtable { ssize_t (*read)(void *obj, void *buf, size_t sz); ssize_t (*write)(void *obj, const void *buf, size_t sz); - int (*ioctl)(void *obj, unsigned int request, ...); + int (*ioctl)(void *obj, unsigned int request, va_list args); }; /** @@ -99,6 +100,31 @@ void *z_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err); */ void *z_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable); +/** + * @brief Call ioctl vmethod on an object using varargs. + * + * We need this helper function because ioctl vmethod is declared to + * take va_list and the only portable way to construct va_list is from + * function's ... parameters. + * + * @param vtable vtable containing ioctl function pointer + * @param obj Object to call ioctl on + * @param request ioctl request number + * @param ... Variadic arguments to ioctl + */ +static inline int z_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *obj, + unsigned long request, ...) +{ + va_list args; + int res; + + va_start(args, request); + res = vtable->ioctl(obj, request, args); + va_end(args); + + return res; +} + /** * Request codes for fd_op_vtable.ioctl(). * diff --git a/lib/fdtable.c b/lib/fdtable.c index ce11f457584..8a39ba8e95e 100644 --- a/lib/fdtable.c +++ b/lib/fdtable.c @@ -14,6 +14,7 @@ */ #include +#include #include #include @@ -173,7 +174,7 @@ int close(int fd) return -1; } - res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, ZFD_IOCTL_CLOSE); + res = z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_CLOSE); z_free_fd(fd); return res; @@ -181,16 +182,11 @@ int close(int fd) int fsync(int fd) { - int res; - if (_check_fd(fd) < 0) { return -1; } - res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, ZFD_IOCTL_FSYNC); - z_free_fd(fd); - - return res; + return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_FSYNC); } off_t lseek(int fd, off_t offset, int whence) @@ -199,8 +195,8 @@ off_t lseek(int fd, off_t offset, int whence) return -1; } - return fdtable[fd].vtable->ioctl(fdtable[fd].obj, ZFD_IOCTL_LSEEK, - offset, whence); + return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_LSEEK, + offset, whence); } /* @@ -225,7 +221,7 @@ static ssize_t stdinout_write_vmeth(void *obj, const void *buffer, size_t count) #endif } -static int stdinout_ioctl_vmeth(void *obj, unsigned int request, ...) +static int stdinout_ioctl_vmeth(void *obj, unsigned int request, va_list args) { errno = EINVAL; return -1; diff --git a/lib/posix/fs.c b/lib/posix/fs.c index 6974f2bdf12..87efba07b50 100644 --- a/lib/posix/fs.c +++ b/lib/posix/fs.c @@ -94,7 +94,7 @@ int open(const char *name, int flags) return fd; } -static int fs_ioctl_vmeth(void *obj, unsigned int request, ...) +static int fs_ioctl_vmeth(void *obj, unsigned int request, va_list args) { int rc; struct posix_fs_desc *ptr = obj; @@ -105,14 +105,11 @@ static int fs_ioctl_vmeth(void *obj, unsigned int request, ...) break; case ZFD_IOCTL_LSEEK: { - va_list args; off_t offset; int whence; - va_start(args, request); offset = va_arg(args, off_t); whence = va_arg(args, int); - va_end(args); rc = fs_seek(&ptr->file, offset, whence); break; diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index 9101ee01ace..4f532bf1a4d 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -157,8 +157,8 @@ int zsock_close_ctx(struct net_context *ctx) int _impl_zsock_close(int sock) { - const struct socket_op_vtable *vtable; - void *ctx = get_sock_vtable(sock, &vtable); + const struct fd_op_vtable *vtable; + void *ctx = z_get_fd_obj_and_vtable(sock, &vtable); if (ctx == NULL) { return -1; @@ -166,7 +166,7 @@ int _impl_zsock_close(int sock) z_free_fd(sock); - return vtable->fd_vtable.ioctl(ctx, ZFD_IOCTL_CLOSE); + return z_fdtable_call_ioctl(vtable, ctx, ZFD_IOCTL_CLOSE); } #ifdef CONFIG_USERSPACE @@ -687,7 +687,15 @@ Z_SYSCALL_HANDLER(zsock_recvfrom, sock, buf, max_len, flags, src_addr, */ int _impl_zsock_fcntl(int sock, int cmd, int flags) { - VTABLE_CALL(fd_vtable.ioctl, sock, cmd, flags); + const struct fd_op_vtable *vtable; + void *obj; + + obj = z_get_fd_obj_and_vtable(sock, &vtable); + if (obj == NULL) { + return -1; + } + + return z_fdtable_call_ioctl(vtable, obj, cmd, flags); } #ifdef CONFIG_USERSPACE @@ -755,7 +763,7 @@ int _impl_zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout) struct k_poll_event poll_events[CONFIG_NET_SOCKETS_POLL_MAX]; struct k_poll_event *pev; struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events); - const struct socket_op_vtable *vtable; + const struct fd_op_vtable *vtable; u32_t entry_time = k_uptime_get_32(); if (timeout < 0) { @@ -771,14 +779,14 @@ int _impl_zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout) continue; } - ctx = get_sock_vtable(pfd->fd, &vtable); + ctx = z_get_fd_obj_and_vtable(pfd->fd, &vtable); if (ctx == NULL) { /* Will set POLLNVAL in return loop */ continue; } - if (vtable->fd_vtable.ioctl(ctx, ZFD_IOCTL_POLL_PREPARE, - pfd, &pev, pev_end) < 0) { + if (z_fdtable_call_ioctl(vtable, ctx, ZFD_IOCTL_POLL_PREPARE, + pfd, &pev, pev_end) < 0) { if (errno == EALREADY) { timeout = K_NO_WAIT; continue; @@ -811,15 +819,15 @@ int _impl_zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout) continue; } - ctx = get_sock_vtable(pfd->fd, &vtable); + ctx = z_get_fd_obj_and_vtable(pfd->fd, &vtable); if (ctx == NULL) { pfd->revents = ZSOCK_POLLNVAL; ret++; continue; } - if (vtable->fd_vtable.ioctl(ctx, ZFD_IOCTL_POLL_UPDATE, - pfd, &pev) < 0) { + if (z_fdtable_call_ioctl(vtable, ctx, ZFD_IOCTL_POLL_UPDATE, + pfd, &pev) < 0) { if (errno == EAGAIN) { retry = true; continue; @@ -958,7 +966,7 @@ static ssize_t sock_write_vmeth(void *obj, const void *buffer, size_t count) return zsock_sendto_ctx(obj, buffer, count, 0, NULL, 0); } -static int sock_ioctl_vmeth(void *obj, unsigned int request, ...) +static int sock_ioctl_vmeth(void *obj, unsigned int request, va_list args) { switch (request) { @@ -971,10 +979,8 @@ static int sock_ioctl_vmeth(void *obj, unsigned int request, ...) return 0; case F_SETFL: { - va_list args; int flags; - va_start(args, request); flags = va_arg(args, int); if (flags & O_NONBLOCK) { @@ -990,29 +996,23 @@ static int sock_ioctl_vmeth(void *obj, unsigned int request, ...) return zsock_close_ctx(obj); case ZFD_IOCTL_POLL_PREPARE: { - va_list args; struct zsock_pollfd *pfd; struct k_poll_event **pev; struct k_poll_event *pev_end; - va_start(args, request); pfd = va_arg(args, struct zsock_pollfd *); pev = va_arg(args, struct k_poll_event **); pev_end = va_arg(args, struct k_poll_event *); - va_end(args); return zsock_poll_prepare_ctx(obj, pfd, pev, pev_end); } case ZFD_IOCTL_POLL_UPDATE: { - va_list args; struct zsock_pollfd *pfd; struct k_poll_event **pev; - va_start(args, request); pfd = va_arg(args, struct zsock_pollfd *); pev = va_arg(args, struct k_poll_event **); - va_end(args); return zsock_poll_update_ctx(obj, pfd, pev); } diff --git a/subsys/net/lib/sockets/sockets_tls.c b/subsys/net/lib/sockets/sockets_tls.c index d36deca4cd9..0eedc097182 100644 --- a/subsys/net/lib/sockets/sockets_tls.c +++ b/subsys/net/lib/sockets/sockets_tls.c @@ -1180,7 +1180,7 @@ int ztls_close_ctx(struct net_context *ctx) err = -EBADF; } - ret = sock_fd_op_vtable.fd_vtable.ioctl(ctx, ZFD_IOCTL_CLOSE); + ret = z_fdtable_call_ioctl(&sock_fd_op_vtable.fd_vtable, ctx, ZFD_IOCTL_CLOSE); /* In case close fails, we propagate errno value set by close. * In case close succeeds, but tls_release fails, set errno @@ -1315,7 +1315,7 @@ error: __ASSERT(err == 0, "TLS context release failed"); } - err = sock_fd_op_vtable.fd_vtable.ioctl(child, ZFD_IOCTL_CLOSE); + err = z_fdtable_call_ioctl(&sock_fd_op_vtable.fd_vtable, child, ZFD_IOCTL_CLOSE); __ASSERT(err == 0, "Child socket close failed"); z_free_fd(fd); @@ -1849,51 +1849,37 @@ static ssize_t tls_sock_write_vmeth(void *obj, const void *buffer, return ztls_sendto_ctx(obj, buffer, count, 0, NULL, 0); } -static int tls_sock_ioctl_vmeth(void *obj, unsigned int request, ...) +static int tls_sock_ioctl_vmeth(void *obj, unsigned int request, va_list args) { switch (request) { /* fcntl() commands */ case F_GETFL: - case F_SETFL: { - va_list args; - int err; - + case F_SETFL: /* Pass the call to the core socket implementation. */ - va_start(args, request); - err = sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args); - va_end(args); - - return err; - } + return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args); case ZFD_IOCTL_CLOSE: return ztls_close_ctx(obj); case ZFD_IOCTL_POLL_PREPARE: { - va_list args; struct zsock_pollfd *pfd; struct k_poll_event **pev; struct k_poll_event *pev_end; - va_start(args, request); pfd = va_arg(args, struct zsock_pollfd *); pev = va_arg(args, struct k_poll_event **); pev_end = va_arg(args, struct k_poll_event *); - va_end(args); return ztls_poll_prepare_ctx(obj, pfd, pev, pev_end); } case ZFD_IOCTL_POLL_UPDATE: { - va_list args; struct zsock_pollfd *pfd; struct k_poll_event **pev; - va_start(args, request); pfd = va_arg(args, struct zsock_pollfd *); pev = va_arg(args, struct k_poll_event **); - va_end(args); return ztls_poll_update_ctx(obj, pfd, pev); }