diff --git a/fs/Kconfig b/fs/Kconfig index 240f712b20..3bbda1fa5d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -134,3 +134,4 @@ source "fs/littlefs/Kconfig" source "fs/unionfs/Kconfig" source "fs/userfs/Kconfig" source "fs/hostfs/Kconfig" +source "fs/rpmsgfs/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index 90e1181f14..c09c0e3e89 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -56,6 +56,7 @@ include unionfs/Make.defs include userfs/Make.defs include hostfs/Make.defs include littlefs/Make.defs +include rpmsgfs/Make.defs endif diff --git a/fs/hostfs/Kconfig b/fs/hostfs/Kconfig index 0395f6642a..6ef25b8dae 100644 --- a/fs/hostfs/Kconfig +++ b/fs/hostfs/Kconfig @@ -36,23 +36,3 @@ config FS_HOSTFS option to enable the handling of the trap. Theoretically, it can work for other environments as well. E.g. a real hardware + JTAG + OpenOCD. - -config FS_HOSTFS_RPMSG - bool "Host File System Rpmsg" - default n - depends on FS_HOSTFS - depends on OPENAMP - ---help--- - Use Host file system to mount directories through rpmsg. - This is the driver that sending the message. - - This effectively replaces the ordinary hostfs backend. - Right now, there is no way to enable both backends. - -config FS_HOSTFS_RPMSG_SERVER - bool "Host File System Rpmsg Server" - default n - depends on OPENAMP - ---help--- - Use Host file system to mount directories through rpmsg. - This is the driver that receiving the message. diff --git a/fs/hostfs/Make.defs b/fs/hostfs/Make.defs index 5dc6a24a9c..a18589c6bf 100644 --- a/fs/hostfs/Make.defs +++ b/fs/hostfs/Make.defs @@ -26,11 +26,3 @@ VPATH += :hostfs ifeq ($(CONFIG_FS_HOSTFS),y) CSRCS += hostfs.c endif - -ifeq ($(CONFIG_FS_HOSTFS_RPMSG),y) -CSRCS += hostfs_rpmsg.c -endif - -ifeq ($(CONFIG_FS_HOSTFS_RPMSG_SERVER),y) -CSRCS += hostfs_rpmsg_server.c -endif diff --git a/fs/hostfs/hostfs_rpmsg.c b/fs/hostfs/hostfs_rpmsg.c deleted file mode 100644 index 4e5be7d863..0000000000 --- a/fs/hostfs/hostfs_rpmsg.c +++ /dev/null @@ -1,775 +0,0 @@ -/**************************************************************************** - * fs/hostfs/hostfs_rpmsg.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 - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "hostfs_rpmsg.h" - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct hostfs_rpmsg_s -{ - struct rpmsg_endpoint ept; - FAR const char *cpuname; -}; - -struct hostfs_rpmsg_cookie_s -{ - sem_t sem; - int result; - FAR void *data; -}; - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static int hostfs_rpmsg_default_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static void hostfs_rpmsg_device_created(struct rpmsg_device *rdev, - FAR void *priv_); -static void hostfs_rpmsg_device_destroy(struct rpmsg_device *rdev, - FAR void *priv_); -static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, uint32_t src, - FAR void *priv); -static int hostfs_rpmsg_send_recv(uint32_t command, bool copy, - FAR struct hostfs_rpmsg_header_s *msg, - int len, FAR void *data); - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static struct hostfs_rpmsg_s g_hostfs_rpmsg; - -static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] = -{ - [HOSTFS_RPMSG_OPEN] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_CLOSE] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_READ] = hostfs_rpmsg_read_handler, - [HOSTFS_RPMSG_WRITE] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_LSEEK] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_IOCTL] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_SYNC] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_DUP] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_FSTAT] = hostfs_rpmsg_stat_handler, - [HOSTFS_RPMSG_FTRUNCATE] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_OPENDIR] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_READDIR] = hostfs_rpmsg_readdir_handler, - [HOSTFS_RPMSG_REWINDDIR] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_CLOSEDIR] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_STATFS] = hostfs_rpmsg_statfs_handler, - [HOSTFS_RPMSG_UNLINK] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_MKDIR] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler, - [HOSTFS_RPMSG_FCHSTAT] = hostfs_rpmsg_default_handler, - [HOSTFS_RPMSG_CHSTAT] = hostfs_rpmsg_default_handler, -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static int hostfs_rpmsg_default_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_header_s *header = data; - FAR struct hostfs_rpmsg_cookie_s *cookie = - (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; - - cookie->result = header->result; - if (cookie->result >= 0 && cookie->data) - { - memcpy(cookie->data, data, len); - } - - nxsem_post(&cookie->sem); - - return 0; -} - -static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_header_s *header = data; - FAR struct hostfs_rpmsg_cookie_s *cookie = - (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; - FAR struct hostfs_rpmsg_read_s *rsp = data; - - cookie->result = header->result; - if (cookie->result > 0) - { - memcpy(cookie->data, rsp->buf, B2C(cookie->result)); - } - - nxsem_post(&cookie->sem); - - return 0; -} - -static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_header_s *header = data; - FAR struct hostfs_rpmsg_cookie_s *cookie = - (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; - FAR struct hostfs_rpmsg_readdir_s *rsp = data; - FAR struct dirent *entry = cookie->data; - - cookie->result = header->result; - if (cookie->result >= 0) - { - nbstr2cstr(entry->d_name, rsp->name, NAME_MAX); - entry->d_name[NAME_MAX] = '\0'; - entry->d_type = rsp->type; - } - - nxsem_post(&cookie->sem); - - return 0; -} - -static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_header_s *header = data; - FAR struct hostfs_rpmsg_cookie_s *cookie = - (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; - FAR struct hostfs_rpmsg_statfs_s *rsp = data; - FAR struct statfs *buf = cookie->data; - - cookie->result = header->result; - if (cookie->result >= 0) - { - buf->f_type = rsp->buf.f_type; - buf->f_namelen = rsp->buf.f_namelen; - buf->f_bsize = B2C(rsp->buf.f_bsize); - buf->f_blocks = rsp->buf.f_blocks; - buf->f_bfree = rsp->buf.f_bfree; - buf->f_bavail = rsp->buf.f_bavail; - buf->f_files = rsp->buf.f_files; - buf->f_ffree = rsp->buf.f_ffree; - } - - nxsem_post(&cookie->sem); - - return 0; -} - -static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_header_s *header = data; - FAR struct hostfs_rpmsg_cookie_s *cookie = - (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; - FAR struct hostfs_rpmsg_stat_s *rsp = data; - FAR struct stat *buf = cookie->data; - - cookie->result = header->result; - if (cookie->result >= 0) - { - buf->st_dev = rsp->buf.st_dev; - buf->st_ino = rsp->buf.st_ino; - buf->st_mode = rsp->buf.st_mode; - buf->st_nlink = rsp->buf.st_nlink; - buf->st_uid = rsp->buf.st_uid; - buf->st_gid = rsp->buf.st_gid; - buf->st_rdev = rsp->buf.st_rdev; - buf->st_size = B2C(rsp->buf.st_size); - buf->st_atime = rsp->buf.st_atime; - buf->st_mtime = rsp->buf.st_mtime; - buf->st_ctime = rsp->buf.st_ctime; - buf->st_blksize = B2C(rsp->buf.st_blksize); - buf->st_blocks = rsp->buf.st_blocks; - } - - nxsem_post(&cookie->sem); - - return 0; -} - -static void hostfs_rpmsg_device_created(FAR struct rpmsg_device *rdev, - FAR void *priv_) -{ - FAR struct hostfs_rpmsg_s *priv = priv_; - - if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) - { - priv->ept.priv = priv; - rpmsg_create_ept(&priv->ept, rdev, HOSTFS_RPMSG_EPT_NAME, - RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, - hostfs_rpmsg_ept_cb, NULL); - } -} - -static void hostfs_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, - FAR void *priv_) -{ - struct hostfs_rpmsg_s *priv = priv_; - - if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) - { - rpmsg_destroy_ept(&priv->ept); - } -} - -static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, uint32_t src, - FAR void *priv) -{ - FAR struct hostfs_rpmsg_header_s *header = data; - uint32_t command = header->command; - - if (command < ARRAY_SIZE(g_hostfs_rpmsg_handler)) - { - return g_hostfs_rpmsg_handler[command](ept, data, len, src, priv); - } - - return -EINVAL; -} - -static int hostfs_rpmsg_send_recv(uint32_t command, bool copy, - FAR struct hostfs_rpmsg_header_s *msg, - int len, FAR void *data) -{ - FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - FAR struct hostfs_rpmsg_cookie_s cookie; - int ret; - - memset(&cookie, 0, sizeof(cookie)); - nxsem_init(&cookie.sem, 0, 0); - nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE); - - if (data) - { - cookie.data = data; - } - else if (copy) - { - cookie.data = msg; - } - - msg->command = command; - msg->result = -ENXIO; - msg->cookie = (uintptr_t)&cookie; - - if (copy) - { - ret = rpmsg_send(&priv->ept, msg, len); - } - else - { - ret = rpmsg_send_nocopy(&priv->ept, msg, len); - } - - if (ret < 0) - { - goto fail; - } - - ret = nxsem_wait_uninterruptible(&cookie.sem); - if (ret == 0) - { - ret = cookie.result; - } - -fail: - nxsem_destroy(&cookie.sem); - return ret; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -int host_open(FAR const char *pathname, int flags, int mode) -{ - FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - FAR struct hostfs_rpmsg_open_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(pathname) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - msg->flags = flags; - msg->mode = mode; - cstr2bstr(msg->pathname, pathname); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_OPEN, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); -} - -int host_close(int fd) -{ - struct hostfs_rpmsg_close_s msg = - { - .fd = fd, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CLOSE, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -ssize_t host_read(int fd, FAR void *buf, size_t count) -{ - size_t read = 0; - int ret = 0; - - while (read < count) - { - struct hostfs_rpmsg_read_s msg = - { - .fd = fd, - .count = C2B(count - read), - }; - - ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_READ, true, - (FAR struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), buf); - if (ret <= 0) - { - break; - } - - read += B2C(ret); - buf += B2C(ret); - } - - return read ? read : ret; -} - -ssize_t host_write(int fd, FAR const void *buf, size_t count) -{ - FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - size_t written = 0; - int ret = 0; - - while (written < count) - { - FAR struct hostfs_rpmsg_write_s *msg; - uint32_t space; - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - ret = -ENOMEM; - break; - } - - space -= sizeof(*msg); - if (space > count - written) - { - space = count - written; - } - - msg->fd = fd; - msg->count = C2B(space); - memcpy(msg->buf, buf + written, space); - - ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_WRITE, false, - (FAR struct hostfs_rpmsg_header_s *)msg, - sizeof(*msg) + space, NULL); - if (ret <= 0) - { - break; - } - - written += B2C(ret); - } - - return written ? written : ret; -} - -off_t host_lseek(int fd, off_t offset, int whence) -{ - struct hostfs_rpmsg_lseek_s msg = - { - .fd = fd, - .offset = C2B(offset), - .whence = whence, - }; - - int ret; - - ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_LSEEK, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); - - return ret < 0 ? ret : B2C(ret); -} - -int host_ioctl(int fd, int request, unsigned long arg) -{ - struct hostfs_rpmsg_ioctl_s msg = - { - .fd = fd, - .request = request, - .arg = arg, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_IOCTL, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -void host_sync(int fd) -{ - struct hostfs_rpmsg_sync_s msg = - { - .fd = fd, - }; - - hostfs_rpmsg_send_recv(HOSTFS_RPMSG_SYNC, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -int host_dup(int fd) -{ - struct hostfs_rpmsg_dup_s msg = - { - .fd = fd, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_DUP, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -int host_fstat(int fd, struct stat *buf) -{ - struct hostfs_rpmsg_fstat_s msg = - { - .fd = fd, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FSTAT, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), buf); -} - -int host_ftruncate(int fd, off_t length) -{ - struct hostfs_rpmsg_ftruncate_s msg = - { - .fd = fd, - .length = length, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FTRUNCATE, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -FAR void *host_opendir(FAR const char *name) -{ - FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - FAR struct hostfs_rpmsg_opendir_s *msg; - uint32_t space; - size_t len; - int ret; - - len = sizeof(*msg); - len += B2C(strlen(name) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return NULL; - } - - DEBUGASSERT(len <= space); - - cstr2bstr(msg->pathname, name); - - ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_OPENDIR, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); - - return ret < 0 ? NULL : (FAR void *)((uintptr_t)ret); -} - -int host_readdir(FAR void *dirp, FAR struct dirent *entry) -{ - struct hostfs_rpmsg_readdir_s msg = - { - .fd = (uintptr_t)dirp, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_READDIR, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), entry); -} - -void host_rewinddir(FAR void *dirp) -{ - struct hostfs_rpmsg_rewinddir_s msg = - { - .fd = (uintptr_t)dirp, - }; - - hostfs_rpmsg_send_recv(HOSTFS_RPMSG_REWINDDIR, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -int host_closedir(FAR void *dirp) -{ - struct hostfs_rpmsg_closedir_s msg = - { - .fd = (uintptr_t)dirp, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CLOSEDIR, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -int host_statfs(FAR const char *path, FAR struct statfs *buf) -{ - struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - struct hostfs_rpmsg_statfs_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(path) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - cstr2bstr(msg->pathname, path); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_STATFS, false, - (struct hostfs_rpmsg_header_s *)msg, len, buf); -} - -int host_unlink(FAR const char *pathname) -{ - struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - struct hostfs_rpmsg_unlink_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(pathname) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - cstr2bstr(msg->pathname, pathname); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_UNLINK, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); -} - -int host_mkdir(FAR const char *pathname, mode_t mode) -{ - struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - struct hostfs_rpmsg_mkdir_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(pathname) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - msg->mode = mode; - cstr2bstr(msg->pathname, pathname); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_MKDIR, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); -} - -int host_rmdir(FAR const char *pathname) -{ - struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - struct hostfs_rpmsg_rmdir_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(pathname) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - cstr2bstr(msg->pathname, pathname); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_RMDIR, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); -} - -int host_rename(FAR const char *oldpath, FAR const char *newpath) -{ - struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - struct hostfs_rpmsg_rename_s *msg; - size_t len; - size_t oldlen; - uint32_t space; - - len = sizeof(*msg); - oldlen = B2C((strlen(oldpath) + 1 + 0x7) & ~0x7); - len += oldlen + B2C(strlen(newpath) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - cstr2bstr(msg->pathname, oldpath); - cstr2bstr(msg->pathname + oldlen, newpath); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_RENAME, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); -} - -int host_stat(FAR const char *path, FAR struct stat *buf) -{ - FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - FAR struct hostfs_rpmsg_stat_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(path) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - cstr2bstr(msg->pathname, path); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_STAT, false, - (struct hostfs_rpmsg_header_s *)msg, len, buf); -} - -int host_fchstat(int fd, const struct stat *buf, int flags) -{ - struct hostfs_rpmsg_fchstat_s msg = - { - .flags = flags, - .buf = *buf, - .fd = fd, - }; - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FCHSTAT, true, - (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); -} - -int host_chstat(FAR const char *path, const FAR struct stat *buf, int flags) -{ - FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - FAR struct hostfs_rpmsg_chstat_s *msg; - uint32_t space; - size_t len; - - len = sizeof(*msg); - len += B2C(strlen(path) + 1); - - msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); - if (!msg) - { - return -ENOMEM; - } - - DEBUGASSERT(len <= space); - - msg->flags = flags; - memcpy(&msg->buf, buf, sizeof(*buf)); - cstr2bstr(msg->pathname, path); - - return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CHSTAT, false, - (struct hostfs_rpmsg_header_s *)msg, len, NULL); -} - -int hostfs_rpmsg_init(FAR const char *cpuname) -{ - struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; - - priv->cpuname = cpuname; - - return rpmsg_register_callback(priv, - hostfs_rpmsg_device_created, - hostfs_rpmsg_device_destroy, - NULL); -} diff --git a/fs/hostfs/hostfs_rpmsg.h b/fs/hostfs/hostfs_rpmsg.h deleted file mode 100644 index 9f11a1d499..0000000000 --- a/fs/hostfs/hostfs_rpmsg.h +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************************** - * fs/hostfs/hostfs_rpmsg.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 __FS_HOSTFS_HOSTFS_RPMSG_H -#define __FS_HOSTFS_HOSTFS_RPMSG_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include -#include - -/**************************************************************************** - * Pre-processor definitions - ****************************************************************************/ - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - -#define HOSTFS_RPMSG_EPT_NAME "rpmsg-hostfs" - -#define HOSTFS_RPMSG_OPEN 1 -#define HOSTFS_RPMSG_CLOSE 2 -#define HOSTFS_RPMSG_READ 3 -#define HOSTFS_RPMSG_WRITE 4 -#define HOSTFS_RPMSG_LSEEK 5 -#define HOSTFS_RPMSG_IOCTL 6 -#define HOSTFS_RPMSG_SYNC 7 -#define HOSTFS_RPMSG_DUP 8 -#define HOSTFS_RPMSG_FSTAT 9 -#define HOSTFS_RPMSG_FTRUNCATE 10 -#define HOSTFS_RPMSG_OPENDIR 11 -#define HOSTFS_RPMSG_READDIR 12 -#define HOSTFS_RPMSG_REWINDDIR 13 -#define HOSTFS_RPMSG_CLOSEDIR 14 -#define HOSTFS_RPMSG_STATFS 15 -#define HOSTFS_RPMSG_UNLINK 16 -#define HOSTFS_RPMSG_MKDIR 17 -#define HOSTFS_RPMSG_RMDIR 18 -#define HOSTFS_RPMSG_RENAME 19 -#define HOSTFS_RPMSG_STAT 20 -#define HOSTFS_RPMSG_FCHSTAT 21 -#define HOSTFS_RPMSG_CHSTAT 22 - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -begin_packed_struct struct hostfs_rpmsg_header_s -{ - uint32_t command; - int32_t result; - uint64_t cookie; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_open_s -{ - struct hostfs_rpmsg_header_s header; - int32_t flags; - int32_t mode; - char pathname[0]; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_close_s -{ - struct hostfs_rpmsg_header_s header; - int32_t fd; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_read_s -{ - struct hostfs_rpmsg_header_s header; - int32_t fd; - uint32_t count; - char buf[0]; -} end_packed_struct; - -#define hostfs_rpmsg_write_s hostfs_rpmsg_read_s - -begin_packed_struct struct hostfs_rpmsg_lseek_s -{ - struct hostfs_rpmsg_header_s header; - int32_t fd; - int32_t whence; - int32_t offset; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_ioctl_s -{ - struct hostfs_rpmsg_header_s header; - int32_t fd; - int32_t request; - int32_t arg; -} end_packed_struct; - -#define hostfs_rpmsg_sync_s hostfs_rpmsg_close_s -#define hostfs_rpmsg_dup_s hostfs_rpmsg_close_s - -begin_packed_struct struct hostfs_rpmsg_fstat_s -{ - struct hostfs_rpmsg_header_s header; - union - { - struct stat buf; - uint32_t reserved[16]; - }; - - union - { - int32_t fd; - char pathname[0]; - }; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_ftruncate_s -{ - struct hostfs_rpmsg_header_s header; - int32_t fd; - int32_t length; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_opendir_s -{ - struct hostfs_rpmsg_header_s header; - char pathname[0]; -} end_packed_struct; - -begin_packed_struct struct hostfs_rpmsg_readdir_s -{ - struct hostfs_rpmsg_header_s header; - int32_t fd; - uint32_t type; - char name[0]; -} end_packed_struct; - -#define hostfs_rpmsg_rewinddir_s hostfs_rpmsg_close_s -#define hostfs_rpmsg_closedir_s hostfs_rpmsg_close_s - -begin_packed_struct struct hostfs_rpmsg_statfs_s -{ - struct hostfs_rpmsg_header_s header; - union - { - struct statfs buf; - uint32_t reserved[16]; - }; - - char pathname[0]; -} end_packed_struct; - -#define hostfs_rpmsg_unlink_s hostfs_rpmsg_opendir_s - -begin_packed_struct struct hostfs_rpmsg_mkdir_s -{ - struct hostfs_rpmsg_header_s header; - int32_t mode; - uint32_t reserved; - char pathname[0]; -} end_packed_struct; - -#define hostfs_rpmsg_rmdir_s hostfs_rpmsg_opendir_s -#define hostfs_rpmsg_rename_s hostfs_rpmsg_opendir_s -#define hostfs_rpmsg_stat_s hostfs_rpmsg_fstat_s - -begin_packed_struct struct hostfs_rpmsg_fchstat_s -{ - struct hostfs_rpmsg_header_s header; - int32_t flags; - union - { - struct stat buf; - uint32_t reserved[16]; - }; - - union - { - int32_t fd; - char pathname[0]; - }; -} end_packed_struct; - -#define hostfs_rpmsg_chstat_s hostfs_rpmsg_fchstat_s - -#endif /* __FS_HOSTFS_HOSTFS_RPMSG_H */ diff --git a/fs/hostfs/hostfs_rpmsg_server.c b/fs/hostfs/hostfs_rpmsg_server.c deleted file mode 100644 index 9e8a68b8d4..0000000000 --- a/fs/hostfs/hostfs_rpmsg_server.c +++ /dev/null @@ -1,883 +0,0 @@ -/**************************************************************************** - * fs/hostfs/hostfs_rpmsg_server.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 - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "hostfs_rpmsg.h" - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct hostfs_rpmsg_server_s -{ - struct rpmsg_endpoint ept; - FAR struct file **files; - FAR void **dirs; - int file_rows; - int dir_nums; - sem_t sem; -}; - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_unlink_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_mkdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_rmdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_fchstat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int hostfs_rpmsg_chstat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); - -static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, - FAR void *priv_, FAR const char *name, - uint32_t dest); -static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept); -static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, uint32_t src, - FAR void *priv); - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] = -{ - [HOSTFS_RPMSG_OPEN] = hostfs_rpmsg_open_handler, - [HOSTFS_RPMSG_CLOSE] = hostfs_rpmsg_close_handler, - [HOSTFS_RPMSG_READ] = hostfs_rpmsg_read_handler, - [HOSTFS_RPMSG_WRITE] = hostfs_rpmsg_write_handler, - [HOSTFS_RPMSG_LSEEK] = hostfs_rpmsg_lseek_handler, - [HOSTFS_RPMSG_IOCTL] = hostfs_rpmsg_ioctl_handler, - [HOSTFS_RPMSG_SYNC] = hostfs_rpmsg_sync_handler, - [HOSTFS_RPMSG_DUP] = hostfs_rpmsg_dup_handler, - [HOSTFS_RPMSG_FSTAT] = hostfs_rpmsg_fstat_handler, - [HOSTFS_RPMSG_FTRUNCATE] = hostfs_rpmsg_ftruncate_handler, - [HOSTFS_RPMSG_OPENDIR] = hostfs_rpmsg_opendir_handler, - [HOSTFS_RPMSG_READDIR] = hostfs_rpmsg_readdir_handler, - [HOSTFS_RPMSG_REWINDDIR] = hostfs_rpmsg_rewinddir_handler, - [HOSTFS_RPMSG_CLOSEDIR] = hostfs_rpmsg_closedir_handler, - [HOSTFS_RPMSG_STATFS] = hostfs_rpmsg_statfs_handler, - [HOSTFS_RPMSG_UNLINK] = hostfs_rpmsg_unlink_handler, - [HOSTFS_RPMSG_MKDIR] = hostfs_rpmsg_mkdir_handler, - [HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_rmdir_handler, - [HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_rename_handler, - [HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler, - [HOSTFS_RPMSG_FCHSTAT] = hostfs_rpmsg_fchstat_handler, - [HOSTFS_RPMSG_CHSTAT] = hostfs_rpmsg_chstat_handler, -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static int hostfs_rpmsg_attach_file(FAR struct hostfs_rpmsg_server_s *priv, - FAR struct file *filep) -{ - FAR struct file **tmp; - int ret; - int i; - int j; - - nxsem_wait(&priv->sem); - - for (i = 0; i < priv->file_rows; i++) - { - for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) - { - if (priv->files[i][j].f_inode == NULL) - { - memcpy(&priv->files[i][j], filep, sizeof(*filep)); - ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j; - goto out; - } - } - } - - tmp = kmm_realloc(priv->files, sizeof(FAR struct file *) * (i + 1)); - DEBUGASSERT(tmp); - if (tmp == NULL) - { - ret = -ENFILE; - goto out; - } - - tmp[i] = kmm_zalloc(sizeof(struct file) * - CONFIG_NFILE_DESCRIPTORS_PER_BLOCK); - DEBUGASSERT(tmp[i]); - if (tmp[i] == NULL) - { - kmm_free(tmp); - ret = -ENFILE; - goto out; - } - - priv->files = tmp; - priv->file_rows++; - - memcpy(&priv->files[i][0], filep, sizeof(*filep)); - ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; - -out: - nxsem_post(&priv->sem); - return ret; -} - -static int hostfs_rpmsg_detach_file(FAR struct hostfs_rpmsg_server_s *priv, - int fd, FAR struct file *filep) -{ - struct file *tfilep; - - if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) - { - return -EBADF; - } - - nxsem_wait(&priv->sem); - tfilep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] - [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; - memcpy(filep, tfilep, sizeof(*filep)); - memset(tfilep, 0, sizeof(*tfilep)); - nxsem_post(&priv->sem); - - return 0; -} - -static FAR struct file *hostfs_rpmsg_get_file( - FAR struct hostfs_rpmsg_server_s *priv, - int fd) -{ - FAR struct file *filep; - - if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) - { - return NULL; - } - - nxsem_wait(&priv->sem); - filep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] - [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; - nxsem_post(&priv->sem); - - return filep; -} - -static int hostfs_rpmsg_attach_dir(FAR struct hostfs_rpmsg_server_s *priv, - FAR void *dir) -{ - FAR void **tmp; - int i; - - nxsem_wait(&priv->sem); - for (i = 1; i < priv->dir_nums; i++) - { - if (priv->dirs[i] == NULL) - { - priv->dirs[i] = dir; - nxsem_post(&priv->sem); - return i; - } - } - - tmp = kmm_realloc(priv->dirs, sizeof(FAR void *) * - (priv->dir_nums + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)); - DEBUGASSERT(tmp); - if (tmp == NULL) - { - nxsem_post(&priv->sem); - return -ENOMEM; - } - - priv->dirs = tmp; - priv->dir_nums += CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; - - priv->dirs[i] = dir; - nxsem_post(&priv->sem); - return i; -} - -static void *hostfs_rpmsg_detach_dir(FAR struct hostfs_rpmsg_server_s *priv, - int fd) -{ - FAR void *dir = NULL; - - if (fd >= 1 && fd < priv->dir_nums) - { - nxsem_wait(&priv->sem); - dir = priv->dirs[fd]; - priv->dirs[fd] = NULL; - nxsem_post(&priv->sem); - } - - return dir; -} - -static FAR void *hostfs_rpmsg_get_dir( - FAR struct hostfs_rpmsg_server_s *priv, - int fd) -{ - FAR void *dir = NULL; - - if (fd >= 1 && fd < priv->dir_nums) - { - nxsem_wait(&priv->sem); - dir = priv->dirs[fd]; - nxsem_post(&priv->sem); - } - - return dir; -} - -static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_open_s *msg = data; - struct file file; - int ret; - - ret = file_open(&file, msg->pathname, msg->flags, msg->mode); - if (ret >= 0) - { - ret = hostfs_rpmsg_attach_file(priv, &file); - if (ret < 0) - { - file_close(&file); - } - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_close_s *msg = data; - struct file file; - int ret; - - ret = hostfs_rpmsg_detach_file(priv, msg->fd, &file); - if (ret >= 0) - { - ret = file_close(&file); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_read_s *msg = data; - FAR struct hostfs_rpmsg_read_s *rsp; - FAR struct file *filep; - int ret = -ENOENT; - uint32_t space; - - rsp = rpmsg_get_tx_payload_buffer(ept, &space, true); - if (!rsp) - { - return -ENOMEM; - } - - *rsp = *msg; - - space -= sizeof(*msg); - if (space > msg->count) - { - space = msg->count; - } - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_read(filep, rsp->buf, space); - } - - rsp->header.result = ret; - return rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp)); -} - -static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_write_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_write(filep, msg->buf, msg->count); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_lseek_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_seek(filep, msg->offset, msg->whence); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_ioctl_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_ioctl(filep, msg->request, msg->arg); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_sync_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_fsync(filep); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_dup_s *msg = data; - FAR struct file *filep; - struct file newfile; - int ret = -ENOENT; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_dup2(filep, &newfile); - if (ret >= 0) - { - ret = hostfs_rpmsg_attach_file(priv, &newfile); - if (ret < 0) - { - file_close(&newfile); - } - } - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_fstat_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - struct stat buf; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_fstat(filep, &buf); - if (ret >= 0) - { - msg->buf = buf; - } - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_ftruncate_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - ret = file_truncate(filep, msg->length); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_opendir_s *msg = data; - FAR void *dir; - int ret = -ENOENT; - - dir = opendir(msg->pathname); - if (dir) - { - ret = hostfs_rpmsg_attach_dir(priv, dir); - if (ret < 0) - { - closedir(dir); - } - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_readdir_s *msg = data; - FAR struct dirent *entry; - int ret = -ENOENT; - FAR void *dir; - - dir = hostfs_rpmsg_get_dir(priv, msg->fd); - if (dir) - { - entry = readdir(dir); - if (entry) - { - msg->type = entry->d_type; - strcpy(msg->name, entry->d_name); - len += strlen(entry->d_name) + 1; - ret = 0; - } - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, len); -} - -static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_rewinddir_s *msg = data; - int ret = -ENOENT; - FAR void *dir; - - dir = hostfs_rpmsg_get_dir(priv, msg->fd); - if (dir) - { - rewinddir(dir); - ret = 0; - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_closedir_s *msg = data; - int ret = -ENOENT; - FAR void *dir; - - dir = hostfs_rpmsg_detach_dir(priv, msg->fd); - if (dir) - { - ret = closedir(dir) ? -get_errno() : 0; - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_statfs_s *msg = data; - struct statfs buf; - int ret; - - ret = statfs(msg->pathname, &buf); - if (ret) - { - ret = -get_errno(); - } - else - { - msg->buf = buf; - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_unlink_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_unlink_s *msg = data; - - msg->header.result = nx_unlink(msg->pathname); - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_mkdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_mkdir_s *msg = data; - int ret; - - ret = mkdir(msg->pathname, msg->mode); - msg->header.result = ret ? -get_errno() : 0; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_rmdir_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_rmdir_s *msg = data; - int ret; - - ret = rmdir(msg->pathname); - msg->header.result = ret ? -get_errno() : 0; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_rename_s *msg = data; - FAR char *newpath; - size_t oldlen; - int ret; - - oldlen = (strlen(msg->pathname) + 1 + 0x7) & ~0x7; - newpath = msg->pathname + oldlen; - - ret = rename(msg->pathname, newpath); - msg->header.result = ret ? -get_errno() : 0; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_stat_s *msg = data; - struct stat buf; - int ret; - - ret = nx_stat(msg->pathname, &buf, 1); - if (ret >= 0) - { - msg->buf = buf; - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_fchstat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_fchstat_s *msg = data; - FAR struct file *filep; - int ret = -ENOENT; - struct stat buf; - - filep = hostfs_rpmsg_get_file(priv, msg->fd); - if (filep != NULL) - { - buf = msg->buf; - ret = file_fchstat(filep, &buf, msg->flags); - } - - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static int hostfs_rpmsg_chstat_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv) -{ - FAR struct hostfs_rpmsg_chstat_s *msg = data; - struct timespec times[2]; - int ret = 0; - - if (msg->flags & CH_STAT_MODE) - { - ret = chmod(msg->pathname, msg->buf.st_mode); - if (ret < 0) - { - ret = -get_errno(); - goto out; - } - } - - if (msg->flags & (CH_STAT_UID | CH_STAT_GID)) - { - ret = chown(msg->pathname, msg->buf.st_uid, msg->buf.st_gid); - if (ret < 0) - { - ret = -get_errno(); - goto out; - } - } - - if (msg->flags & (CH_STAT_ATIME | CH_STAT_MTIME)) - { - if (msg->flags & CH_STAT_ATIME) - { - times[0] = msg->buf.st_atim; - } - else - { - times[0].tv_nsec = UTIME_OMIT; - } - - if (msg->flags & CH_STAT_MTIME) - { - times[1] = msg->buf.st_mtim; - } - else - { - times[1].tv_nsec = UTIME_OMIT; - } - - ret = utimens(msg->pathname, times); - if (ret < 0) - { - ret = -get_errno(); - goto out; - } - } - -out: - msg->header.result = ret; - return rpmsg_send(ept, msg, sizeof(*msg)); -} - -static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, - FAR void *priv_, FAR const char *name, - uint32_t dest) -{ - FAR struct hostfs_rpmsg_server_s *priv; - int ret; - - if (strcmp(name, HOSTFS_RPMSG_EPT_NAME)) - { - return; - } - - priv = kmm_zalloc(sizeof(*priv)); - if (!priv) - { - return; - } - - priv->ept.priv = priv; - nxsem_init(&priv->sem, 0, 1); - - ret = rpmsg_create_ept(&priv->ept, rdev, HOSTFS_RPMSG_EPT_NAME, - RPMSG_ADDR_ANY, dest, - hostfs_rpmsg_ept_cb, hostfs_rpmsg_ns_unbind); - if (ret) - { - nxsem_destroy(&priv->sem); - kmm_free(priv); - } -} - -static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept) -{ - FAR struct hostfs_rpmsg_server_s *priv = ept->priv; - int i; - int j; - - for (i = 0; i < priv->file_rows; i++) - { - for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) - { - if (priv->files[i][j].f_inode) - { - file_close(&priv->files[i][j]); - } - } - - kmm_free(priv->files[i]); - } - - for (i = 0; i < priv->dir_nums; i++) - { - if (priv->dirs[i]) - { - closedir(priv->dirs[i]); - } - } - - rpmsg_destroy_ept(&priv->ept); - nxsem_destroy(&priv->sem); - - kmm_free(priv->files); - kmm_free(priv->dirs); - kmm_free(priv); -} - -static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, uint32_t src, - FAR void *priv) -{ - struct hostfs_rpmsg_header_s *header = data; - uint32_t command = header->command; - - if (command < ARRAY_SIZE(g_hostfs_rpmsg_handler)) - { - return g_hostfs_rpmsg_handler[command](ept, data, len, src, priv); - } - - return -EINVAL; -} - -int hostfs_rpmsg_server_init(void) -{ - return rpmsg_register_callback(NULL, - NULL, - NULL, - hostfs_rpmsg_ns_bind); -} diff --git a/fs/mount/fs_gettype.c b/fs/mount/fs_gettype.c index 326ce478fe..b5894a698f 100644 --- a/fs/mount/fs_gettype.c +++ b/fs/mount/fs_gettype.c @@ -135,6 +135,12 @@ FAR const char *fs_gettype(FAR struct statfs *statbuf) break; #endif +#ifdef CONFIG_FS_RPMSGFS + case RPMSGFS_MAGIC: + fstype = "rpmsgfs"; + break; +#endif + #ifdef CONFIG_FS_USERFS case USERFS_MAGIC: fstype = "userfs"; diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index b0c7d2eb54..5450fcdbbd 100644 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -178,6 +178,9 @@ extern const struct mountpt_operations cromfs_operations; #ifdef CONFIG_FS_UNIONFS extern const struct mountpt_operations unionfs_operations; #endif +#ifdef CONFIG_FS_RPMSGFS +extern const struct mountpt_operations rpmsgfs_operations; +#endif static const struct fsmap_t g_nonbdfsmap[] = { @@ -207,6 +210,9 @@ static const struct fsmap_t g_nonbdfsmap[] = #endif #ifdef CONFIG_FS_UNIONFS { "unionfs", &unionfs_operations }, +#endif +#ifdef CONFIG_FS_RPMSGFS + { "rpmsgfs", &rpmsgfs_operations }, #endif { NULL, NULL }, }; diff --git a/fs/rpmsgfs/Kconfig b/fs/rpmsgfs/Kconfig new file mode 100644 index 0000000000..30995a5f2d --- /dev/null +++ b/fs/rpmsgfs/Kconfig @@ -0,0 +1,12 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config FS_RPMSGFS + bool "RPMSG File System" + default n + depends on OPENAMP + ---help--- + Use rpmsg file system to mount remote directories to local. + This the method for user to use remote file like own core. diff --git a/fs/rpmsgfs/Make.defs b/fs/rpmsgfs/Make.defs new file mode 100644 index 0000000000..aea7bf0022 --- /dev/null +++ b/fs/rpmsgfs/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# fs/rpmsgfs/Make.defs +# +# 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. +# +############################################################################ + +# Include RPSMGFS build support + +DEPPATH += --dep-path rpmsgfs +VPATH += :rpmsgfs + +ifeq ($(CONFIG_FS_RPMSGFS),y) +CSRCS += rpmsgfs.c rpmsgfs_client.c rpmsgfs_server.c +endif diff --git a/fs/rpmsgfs/rpmsgfs.c b/fs/rpmsgfs/rpmsgfs.c new file mode 100644 index 0000000000..e096be4671 --- /dev/null +++ b/fs/rpmsgfs/rpmsgfs.c @@ -0,0 +1,1456 @@ +/**************************************************************************** + * fs/rpmsgfs/rpmsgfs.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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "rpmsgfs.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of one open file. This structure + * is protected by the volume semaphore. + */ + +struct rpmsgfs_ofile_s +{ + struct rpmsgfs_ofile_s *fnext; /* Supports a singly linked list */ + int16_t crefs; /* Reference count */ + mode_t oflags; /* Open mode */ + int fd; +}; + +/* This structure represents the overall mountpoint state. An instance of + * this structure is retained as inode private data on each mountpoint that + * is mounted with a rpmsgfs filesystem. + */ + +struct rpmsgfs_mountpt_s +{ + sem_t fs_sem; /* Assure thread-safe access */ + FAR struct rpmsgfs_ofile_s *fs_head; /* Singly-linked list of open files */ + char fs_root[PATH_MAX]; + void *handle; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rpmsgfs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int rpmsgfs_close(FAR struct file *filep); +static ssize_t rpmsgfs_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t rpmsgfs_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static off_t rpmsgfs_seek(FAR struct file *filep, off_t offset, + int whence); +static int rpmsgfs_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +static int rpmsgfs_sync(FAR struct file *filep); +static int rpmsgfs_dup(FAR const struct file *oldp, + FAR struct file *newp); +static int rpmsgfs_fstat(FAR const struct file *filep, + FAR struct stat *buf); +static int rpmsgfs_fchstat(FAR const struct file *filep, + FAR const struct stat *buf, int flags); +static int rpmsgfs_ftruncate(FAR struct file *filep, + off_t length); + +static int rpmsgfs_opendir(FAR struct inode *mountpt, + FAR const char *relpath, + FAR struct fs_dirent_s *dir); +static int rpmsgfs_closedir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir); +static int rpmsgfs_readdir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir); +static int rpmsgfs_rewinddir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir); + +static int rpmsgfs_bind(FAR struct inode *blkdriver, + FAR const void *data, FAR void **handle); +static int rpmsgfs_unbind(FAR void *handle, FAR struct inode **blkdriver, + unsigned int flags); +static int rpmsgfs_statfs(FAR struct inode *mountpt, + FAR struct statfs *buf); + +static int rpmsgfs_unlink(FAR struct inode *mountpt, + FAR const char *relpath); +static int rpmsgfs_mkdir(FAR struct inode *mountpt, + FAR const char *relpath, mode_t mode); +static int rpmsgfs_rmdir(FAR struct inode *mountpt, const char *relpath); +static int rpmsgfs_rename(FAR struct inode *mountpt, + FAR const char *oldrelpath, + FAR const char *newrelpath); +static int rpmsgfs_stat(FAR struct inode *mountpt, + FAR const char *relpath, FAR struct stat *buf); +static int rpmsgfs_chstat(FAR struct inode *mountpt, + FAR const char *relpath, + FAR const struct stat *buf, int flags); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* See fs_mount.c -- this structure is explicitly externed there. + * We use the old-fashioned kind of initializers so that this will compile + * with any compiler. + */ + +const struct mountpt_operations rpmsgfs_operations = +{ + rpmsgfs_open, /* open */ + rpmsgfs_close, /* close */ + rpmsgfs_read, /* read */ + rpmsgfs_write, /* write */ + rpmsgfs_seek, /* seek */ + rpmsgfs_ioctl, /* ioctl */ + + rpmsgfs_sync, /* sync */ + rpmsgfs_dup, /* dup */ + rpmsgfs_fstat, /* fstat */ + rpmsgfs_fchstat, /* fchstat */ + rpmsgfs_ftruncate, /* ftruncate */ + + rpmsgfs_opendir, /* opendir */ + rpmsgfs_closedir, /* closedir */ + rpmsgfs_readdir, /* readdir */ + rpmsgfs_rewinddir, /* rewinddir */ + + rpmsgfs_bind, /* bind */ + rpmsgfs_unbind, /* unbind */ + rpmsgfs_statfs, /* statfs */ + + rpmsgfs_unlink, /* unlink */ + rpmsgfs_mkdir, /* mkdir */ + rpmsgfs_rmdir, /* rmdir */ + rpmsgfs_rename, /* rename */ + rpmsgfs_stat, /* stat */ + rpmsgfs_chstat, /* chstat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rpmsgfs_semtake + ****************************************************************************/ + +static int rpmsgfs_semtake(FAR struct rpmsgfs_mountpt_s *fs) +{ + return nxsem_wait_uninterruptible(&fs->fs_sem); +} + +/**************************************************************************** + * Name: rpmsgfs_semgive + ****************************************************************************/ + +static void rpmsgfs_semgive(FAR struct rpmsgfs_mountpt_s *fs) +{ + nxsem_post(&fs->fs_sem); +} + +/**************************************************************************** + * Name: rpmsgfs_mkpath + * + * Description: Build absolute host path from relative NuttX path. + * + ****************************************************************************/ + +static void rpmsgfs_mkpath(FAR struct rpmsgfs_mountpt_s *fs, + FAR const char *relpath, + FAR char *path, int pathlen) +{ + int depth = 0; + int first; + int x; + + /* Copy base host path to output */ + + strncpy(path, fs->fs_root, pathlen); + + /* Be sure we aren't trying to use ".." to display outside of our + * mounted path. + */ + + x = 0; + while (relpath[x] == '/') + { + x++; + } + + first = x; + + while (relpath[x] != '\0') + { + /* Test for ".." occurrence */ + + if (strncmp(&relpath[x], "..", 2) == 0) + { + /* Reduce depth by 1 */ + + depth--; + x += 2; + } + + else if (relpath[x] == '/' && relpath[x + 1] != '/' && + relpath[x + 1] != '\0') + { + depth++; + x++; + } + else + { + x++; + } + } + + if (depth >= 0) + { + strncat(path, &relpath[first], pathlen - strlen(path) - 1); + } +} + +/**************************************************************************** + * Name: rpmsgfs_open + ****************************************************************************/ + +static int rpmsgfs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT((filep->f_priv == NULL) && (filep->f_inode != NULL)); + + /* Get the mountpoint inode reference from the file structure and the + * mountpoint private data from the inode structure + */ + + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Allocate memory for the open file */ + + hf = (struct rpmsgfs_ofile_s *) kmm_malloc(sizeof *hf); + if (hf == NULL) + { + ret = -ENOMEM; + goto errout_with_semaphore; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Try to open the file in the host file system */ + + hf->fd = rpmsgfs_client_open(fs->handle, path, oflags, mode); + if (hf->fd < 0) + { + /* Error opening file */ + + ret = -EBADF; + goto errout_with_buffer; + } + + /* In write/append mode, we need to set the file pointer to the end of the + * file. + */ + + if ((oflags & (O_APPEND | O_WRONLY)) == (O_APPEND | O_WRONLY)) + { + ret = rpmsgfs_client_lseek(fs->handle, hf->fd, 0, SEEK_END); + if (ret >= 0) + { + filep->f_pos = ret; + } + else + { + goto errout_with_buffer; + } + } + + /* Attach the private date to the struct file instance */ + + filep->f_priv = hf; + + /* Then insert the new instance into the mountpoint structure. + * It needs to be there (1) to handle error conditions that effect + * all files, and (2) to inform the umount logic that we are busy + * (but a simple reference count could have done that). + */ + + hf->fnext = fs->fs_head; + hf->crefs = 1; + hf->oflags = oflags; + fs->fs_head = hf; + + ret = OK; + goto errout_with_semaphore; + +errout_with_buffer: + kmm_free(hf); + +errout_with_semaphore: + rpmsgfs_semgive(fs); + if (ret == -EINVAL) + { + ret = -EIO; + } + + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_close + ****************************************************************************/ + +static int rpmsgfs_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + FAR struct rpmsgfs_ofile_s *nextfile; + FAR struct rpmsgfs_ofile_s *prevfile; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + inode = filep->f_inode; + fs = inode->i_private; + hf = filep->f_priv; + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Check if we are the last one with a reference to the file and + * only close if we are. + */ + + if (hf->crefs > 1) + { + /* The file is opened more than once. Just decrement the + * reference count and return. + */ + + hf->crefs--; + goto okout; + } + + /* Remove ourselves from the linked list */ + + nextfile = fs->fs_head; + prevfile = nextfile; + while ((nextfile != hf) && (nextfile != NULL)) + { + /* Save the previous file pointer too */ + + prevfile = nextfile; + nextfile = nextfile->fnext; + } + + if (nextfile != NULL) + { + /* Test if we were the first entry */ + + if (nextfile == fs->fs_head) + { + /* Assign a new head */ + + fs->fs_head = nextfile->fnext; + } + else + { + /* Take ourselves out of the list */ + + prevfile->fnext = nextfile->fnext; + } + } + + /* Close the host file */ + + rpmsgfs_client_close(fs->handle, hf->fd); + + /* Now free the pointer */ + + filep->f_priv = NULL; + kmm_free(hf); + +okout: + rpmsgfs_semgive(fs); + return OK; +} + +/**************************************************************************** + * Name: rpmsgfs_read + ****************************************************************************/ + +static ssize_t rpmsgfs_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + ssize_t ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + hf = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host to perform the read */ + + ret = rpmsgfs_client_read(fs->handle, hf->fd, buffer, buflen); + if (ret > 0) + { + filep->f_pos += ret; + } + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_write + ****************************************************************************/ + +static ssize_t rpmsgfs_write(FAR struct file *filep, const char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + ssize_t ret; + + /* Sanity checks. I have seen the following assertion misfire if + * CONFIG_DEBUG_MM is enabled while re-directing output to a + * file. In this case, the debug output can get generated while + * the file is being opened, FAT data structures are being allocated, + * and things are generally in a perverse state. + */ + +#ifdef CONFIG_DEBUG_MM + if (filep->f_priv == NULL || filep->f_inode == NULL) + { + return -ENXIO; + } +#else + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); +#endif + + /* Recover our private data from the struct file instance */ + + hf = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Test the permissions. Only allow write if the file was opened with + * write flags. + */ + + if ((hf->oflags & O_WROK) == 0) + { + ret = -EACCES; + goto errout_with_semaphore; + } + + /* Call the host to perform the write */ + + ret = rpmsgfs_client_write(fs->handle, hf->fd, buffer, buflen); + if (ret > 0) + { + filep->f_pos += ret; + } + +errout_with_semaphore: + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_seek + ****************************************************************************/ + +static off_t rpmsgfs_seek(FAR struct file *filep, off_t offset, int whence) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + off_t ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + hf = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call our internal routine to perform the seek */ + + ret = rpmsgfs_client_lseek(fs->handle, hf->fd, offset, whence); + if (ret >= 0) + { + filep->f_pos = ret; + } + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_ioctl + ****************************************************************************/ + +static int rpmsgfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + hf = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call our internal routine to perform the ioctl */ + + ret = rpmsgfs_client_ioctl(fs->handle, hf->fd, cmd, arg); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_sync + * + * Description: Synchronize the file state on disk to match internal, in- + * memory state. + * + ****************************************************************************/ + +static int rpmsgfs_sync(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + hf = filep->f_priv; + inode = filep->f_inode; + fs = inode->i_private; + + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + rpmsgfs_client_sync(fs->handle, hf->fd); + + rpmsgfs_semgive(fs); + return OK; +} + +/**************************************************************************** + * Name: rpmsgfs_dup + * + * Description: Duplicate open file data in the new file structure. + * + ****************************************************************************/ + +static int rpmsgfs_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct rpmsgfs_ofile_s *sf; + + /* Sanity checks */ + + DEBUGASSERT(oldp->f_priv != NULL && + newp->f_priv == NULL && + newp->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + sf = oldp->f_priv; + + DEBUGASSERT(sf != NULL); + + /* Just increment the reference count on the ofile */ + + sf->crefs++; + newp->f_priv = (FAR void *)sf; + + return OK; +} + +/**************************************************************************** + * Name: rpmsgfs_fstat + * + * Description: + * Obtain information about an open file associated with the file + * descriptor 'fd', and will write it to the area pointed to by 'buf'. + * + ****************************************************************************/ + +static int rpmsgfs_fstat(FAR const struct file *filep, FAR struct stat *buf) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + int ret = OK; + + /* Sanity checks */ + + DEBUGASSERT(filep != NULL && buf != NULL); + + /* Recover our private data from the struct file instance */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + hf = filep->f_priv; + inode = filep->f_inode; + + fs = inode->i_private; + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host to perform the read */ + + ret = rpmsgfs_client_fstat(fs->handle, hf->fd, buf); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_fchstat + * + * Description: + * Change information about an open file associated with the file + * descriptor 'fd'. + * + ****************************************************************************/ + +static int rpmsgfs_fchstat(FAR const struct file *filep, + FAR const struct stat *buf, int flags) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + int ret = OK; + + /* Sanity checks */ + + DEBUGASSERT(filep != NULL && buf != NULL); + + /* Recover our private data from the struct file instance */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + hf = filep->f_priv; + inode = filep->f_inode; + + fs = inode->i_private; + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host to perform the change */ + + ret = rpmsgfs_client_fchstat(fs->handle, hf->fd, buf, flags); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_ftruncate + * + * Description: + * Set the length of the open, regular file associated with the file + * structure 'filep' to 'length'. + * + ****************************************************************************/ + +static int rpmsgfs_ftruncate(FAR struct file *filep, off_t length) +{ + FAR struct inode *inode; + FAR struct rpmsgfs_mountpt_s *fs; + FAR struct rpmsgfs_ofile_s *hf; + int ret = OK; + + /* Sanity checks */ + + DEBUGASSERT(filep != NULL); + + /* Recover our private data from the struct file instance */ + + DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL); + hf = filep->f_priv; + inode = filep->f_inode; + + fs = inode->i_private; + DEBUGASSERT(fs != NULL); + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host to perform the truncate */ + + ret = rpmsgfs_client_ftruncate(fs->handle, hf->fd, length); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_opendir + * + * Description: Open a directory for read access + * + ****************************************************************************/ + +static int rpmsgfs_opendir(FAR struct inode *mountpt, + FAR const char *relpath, + FAR struct fs_dirent_s *dir) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Call the host's opendir function */ + + dir->u.rpmsgfs.fs_dir = rpmsgfs_client_opendir(fs->handle, path); + if (dir->u.rpmsgfs.fs_dir == NULL) + { + ret = -ENOENT; + goto errout_with_semaphore; + } + + ret = OK; + +errout_with_semaphore: + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_closedir + * + * Description: Open a directory for read access + * + ****************************************************************************/ + +static int rpmsgfs_closedir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir) +{ + struct rpmsgfs_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host's closedir function */ + + rpmsgfs_client_closedir(fs->handle, dir->u.rpmsgfs.fs_dir); + + rpmsgfs_semgive(fs); + return OK; +} + +/**************************************************************************** + * Name: rpmsgfs_readdir + * + * Description: Read the next directory entry + * + ****************************************************************************/ + +static int rpmsgfs_readdir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir) +{ + FAR struct rpmsgfs_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host OS's readdir function */ + + ret = rpmsgfs_client_readdir(fs->handle, + dir->u.rpmsgfs.fs_dir, &dir->fd_dir); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_rewindir + * + * Description: Reset directory read to the first entry + * + ****************************************************************************/ + +static int rpmsgfs_rewinddir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir) +{ + FAR struct rpmsgfs_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + + /* Recover our private data from the inode instance */ + + fs = mountpt->i_private; + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host and let it do all the work */ + + rpmsgfs_client_rewinddir(fs->handle, dir->u.rpmsgfs.fs_dir); + + rpmsgfs_semgive(fs); + return OK; +} + +/**************************************************************************** + * Name: rpmsgfs_bind + * + * Description: This implements a portion of the mount operation. This + * function allocates and initializes the mountpoint private data and + * binds the blockdriver inode to the filesystem private data. The final + * binding of the private data (containing the blockdriver) to the + * mountpoint is performed by mount(). + * + ****************************************************************************/ + +static int rpmsgfs_bind(FAR struct inode *blkdriver, FAR const void *data, + FAR void **handle) +{ + FAR struct rpmsgfs_mountpt_s *fs; + FAR const char *cpuname = NULL; + FAR char *options; + char *saveptr; + char *ptr; + int len; + int ret; + + /* Validate the block driver is NULL */ + + if (blkdriver || !data) + { + return -ENODEV; + } + + /* Create an instance of the mountpt state structure */ + + fs = (FAR struct rpmsgfs_mountpt_s *) + kmm_zalloc(sizeof(struct rpmsgfs_mountpt_s)); + + if (fs == NULL) + { + return -ENOMEM; + } + + /* The options we support are: + * "fs=whatever,cpu=cpuname", remote dir + */ + + options = strdup(data); + if (!options) + { + kmm_free(fs); + return -ENOMEM; + } + + ptr = strtok_r(options, ",", &saveptr); + while (ptr != NULL) + { + if ((strncmp(ptr, "fs=", 3) == 0)) + { + strncpy(fs->fs_root, &ptr[3], sizeof(fs->fs_root)); + } + else if ((strncmp(ptr, "cpu=", 4) == 0)) + { + cpuname = &ptr[4]; + } + + ptr = strtok_r(NULL, ",", &saveptr); + } + + ret = rpmsgfs_client_bind(&fs->handle, cpuname); + kmm_free(options); + if (ret < 0) + { + kmm_free(fs); + return ret; + } + + /* If the global semaphore hasn't been initialized, then + * initialized it now. + */ + + /* Initialize the semaphore that controls access */ + + nxsem_init(&fs->fs_sem, 0, 1); + + /* Initialize the allocated mountpt state structure. The filesystem is + * responsible for one reference ont the blkdriver inode and does not + * have to addref() here (but does have to release in ubind(). + */ + + fs->fs_head = NULL; + + /* Now perform the mount. */ + + len = strlen(fs->fs_root); + if (len > 1 && fs->fs_root[len - 1] == '/') + { + /* Remove trailing '/' */ + + fs->fs_root[len - 1] = '\0'; + } + + /* Append a '/' to the name now */ + + if (fs->fs_root[len - 1] != '/') + { + strcat(fs->fs_root, "/"); + } + + *handle = (FAR void *)fs; + return OK; +} + +/**************************************************************************** + * Name: rpmsgfs_unbind + * + * Description: This implements the filesystem portion of the umount + * operation. + * + ****************************************************************************/ + +static int rpmsgfs_unbind(FAR void *handle, FAR struct inode **blkdriver, + unsigned int flags) +{ + FAR struct rpmsgfs_mountpt_s *fs = (FAR struct rpmsgfs_mountpt_s *)handle; + int ret; + + if (!fs) + { + return -EINVAL; + } + + /* Check if there are sill any files opened on the filesystem. */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + if (fs->fs_head != NULL) + { + /* We cannot unmount now.. there are open files */ + + rpmsgfs_semgive(fs); + + /* This implementation currently only supports unmounting if there are + * no open file references. + */ + + return (flags != 0) ? -ENOSYS : -EBUSY; + } + + ret = rpmsgfs_client_unbind(fs->handle); + rpmsgfs_semgive(fs); + if (ret < 0) + { + return ret; + } + + nxsem_destroy(&fs->fs_sem); + kmm_free(fs); + return 0; +} + +/**************************************************************************** + * Name: rpmsgfs_statfs + * + * Description: Return filesystem statistics + * + ****************************************************************************/ + +static int rpmsgfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf) +{ + FAR struct rpmsgfs_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Call the host fs to perform the statfs */ + + memset(buf, 0, sizeof(struct statfs)); + ret = rpmsgfs_client_statfs(fs->handle, fs->fs_root, buf); + buf->f_type = RPMSGFS_MAGIC; + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_unlink + * + * Description: Remove a file + * + ****************************************************************************/ + +static int rpmsgfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Call the host fs to perform the unlink */ + + ret = rpmsgfs_client_unlink(fs->handle, path); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_mkdir + * + * Description: Create a directory + * + ****************************************************************************/ + +static int rpmsgfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, + mode_t mode) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Call the host FS to do the mkdir */ + + ret = rpmsgfs_client_mkdir(fs->handle, path, mode); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_rmdir + * + * Description: Remove a directory + * + ****************************************************************************/ + +int rpmsgfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Take the semaphore */ + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Call the host FS to do the mkdir */ + + ret = rpmsgfs_client_rmdir(fs->handle, path); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_rename + * + * Description: Rename a file or directory + * + ****************************************************************************/ + +int rpmsgfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, + FAR const char *newrelpath) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char oldpath[PATH_MAX]; + char newpath[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + strncpy(oldpath, fs->fs_root, sizeof(oldpath)); + strncat(oldpath, oldrelpath, sizeof(oldpath)-strlen(oldpath)-1); + strncpy(newpath, fs->fs_root, sizeof(newpath)); + strncat(newpath, newrelpath, sizeof(newpath)-strlen(newpath)-1); + + /* Call the host FS to do the mkdir */ + + ret = rpmsgfs_client_rename(fs->handle, oldpath, newpath); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_stat + * + * Description: Return information about a file or directory + * + ****************************************************************************/ + +static int rpmsgfs_stat(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct stat *buf) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Call the host FS to do the stat operation */ + + ret = rpmsgfs_client_stat(fs->handle, path, buf); + + rpmsgfs_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: rpmsgfs_chstat + * + * Description: Change information about a file or directory + * + ****************************************************************************/ + +static int rpmsgfs_chstat(FAR struct inode *mountpt, FAR const char *relpath, + FAR const struct stat *buf, int flags) +{ + FAR struct rpmsgfs_mountpt_s *fs; + char path[PATH_MAX]; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = rpmsgfs_semtake(fs); + if (ret < 0) + { + return ret; + } + + /* Append to the host's root directory */ + + rpmsgfs_mkpath(fs, relpath, path, sizeof(path)); + + /* Call the host FS to do the chstat operation */ + + ret = rpmsgfs_client_chstat(fs->handle, path, buf, flags); + + rpmsgfs_semgive(fs); + return ret; +} diff --git a/fs/rpmsgfs/rpmsgfs.h b/fs/rpmsgfs/rpmsgfs.h new file mode 100644 index 0000000000..7f1014dc66 --- /dev/null +++ b/fs/rpmsgfs/rpmsgfs.h @@ -0,0 +1,246 @@ +/**************************************************************************** + * fs/rpmsgfs/rpmsgfs.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 __FS_RPMSGFS_H +#define __FS_RPMSGFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#define RPMSGFS_NAME_PREFIX "rpmsgfs-" + +#define RPMSGFS_OPEN 1 +#define RPMSGFS_CLOSE 2 +#define RPMSGFS_READ 3 +#define RPMSGFS_WRITE 4 +#define RPMSGFS_LSEEK 5 +#define RPMSGFS_IOCTL 6 +#define RPMSGFS_SYNC 7 +#define RPMSGFS_DUP 8 +#define RPMSGFS_FSTAT 9 +#define RPMSGFS_FTRUNCATE 10 +#define RPMSGFS_OPENDIR 11 +#define RPMSGFS_READDIR 12 +#define RPMSGFS_REWINDDIR 13 +#define RPMSGFS_CLOSEDIR 14 +#define RPMSGFS_STATFS 15 +#define RPMSGFS_UNLINK 16 +#define RPMSGFS_MKDIR 17 +#define RPMSGFS_RMDIR 18 +#define RPMSGFS_RENAME 19 +#define RPMSGFS_STAT 20 +#define RPMSGFS_FCHSTAT 21 +#define RPMSGFS_CHSTAT 22 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +begin_packed_struct struct rpmsgfs_header_s +{ + uint32_t command; + int32_t result; + uint64_t cookie; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_open_s +{ + struct rpmsgfs_header_s header; + int32_t flags; + int32_t mode; + char pathname[0]; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_close_s +{ + struct rpmsgfs_header_s header; + int32_t fd; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_read_s +{ + struct rpmsgfs_header_s header; + int32_t fd; + uint32_t count; + char buf[0]; +} end_packed_struct; + +#define rpmsgfs_write_s rpmsgfs_read_s + +begin_packed_struct struct rpmsgfs_lseek_s +{ + struct rpmsgfs_header_s header; + int32_t fd; + int32_t whence; + int32_t offset; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_ioctl_s +{ + struct rpmsgfs_header_s header; + int32_t fd; + int32_t request; + int32_t arg; +} end_packed_struct; + +#define rpmsgfs_sync_s rpmsgfs_close_s +#define rpmsgfs_dup_s rpmsgfs_close_s + +begin_packed_struct struct rpmsgfs_fstat_s +{ + struct rpmsgfs_header_s header; + union + { + struct stat buf; + uint32_t reserved[16]; + }; + + union + { + int32_t fd; + char pathname[0]; + }; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_ftruncate_s +{ + struct rpmsgfs_header_s header; + int32_t fd; + int32_t length; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_opendir_s +{ + struct rpmsgfs_header_s header; + char pathname[0]; +} end_packed_struct; + +begin_packed_struct struct rpmsgfs_readdir_s +{ + struct rpmsgfs_header_s header; + int32_t fd; + uint32_t type; + char name[0]; +} end_packed_struct; + +#define rpmsgfs_rewinddir_s rpmsgfs_close_s +#define rpmsgfs_closedir_s rpmsgfs_close_s + +begin_packed_struct struct rpmsgfs_statfs_s +{ + struct rpmsgfs_header_s header; + union + { + struct statfs buf; + uint32_t reserved[16]; + }; + + char pathname[0]; +} end_packed_struct; + +#define rpmsgfs_unlink_s rpmsgfs_opendir_s + +begin_packed_struct struct rpmsgfs_mkdir_s +{ + struct rpmsgfs_header_s header; + int32_t mode; + uint32_t reserved; + char pathname[0]; +} end_packed_struct; + +#define rpmsgfs_rmdir_s rpmsgfs_opendir_s +#define rpmsgfs_rename_s rpmsgfs_opendir_s +#define rpmsgfs_stat_s rpmsgfs_fstat_s + +begin_packed_struct struct rpmsgfs_fchstat_s +{ + struct rpmsgfs_header_s header; + int32_t flags; + union + { + struct stat buf; + uint32_t reserved[16]; + }; + + union + { + int32_t fd; + char pathname[0]; + }; +} end_packed_struct; + +#define rpmsgfs_chstat_s rpmsgfs_fchstat_s + +/**************************************************************************** + * Internal function prototypes + ****************************************************************************/ + +int rpmsgfs_client_open(FAR void *handle, + FAR const char *pathname, int flags, int mode); +int rpmsgfs_client_close(FAR void *handle, int fd); +ssize_t rpmsgfs_client_read(FAR void *handle, int fd, + FAR void *buf, size_t count); +ssize_t rpmsgfs_client_write(FAR void *handle, int fd, + FAR const void *buf, size_t count); +off_t rpmsgfs_client_lseek(FAR void *handle, int fd, + off_t offset, int whence); +int rpmsgfs_client_ioctl(FAR void *handle, int fd, + int request, unsigned long arg); +void rpmsgfs_client_sync(FAR void *handle, int fd); +int rpmsgfs_client_dup(FAR void *handle, int fd); +int rpmsgfs_client_fstat(FAR void *handle, int fd, + FAR struct stat *buf); +int rpmsgfs_client_fchstat(FAR void *handle, int fd, + FAR const struct stat *buf, int flags); +int rpmsgfs_client_ftruncate(FAR void *handle, int fd, off_t length); +FAR void *rpmsgfs_client_opendir(FAR void *handle, FAR const char *name); +int rpmsgfs_client_readdir(FAR void *handle, FAR void *dirp, + FAR struct dirent *entry); +void rpmsgfs_client_rewinddir(FAR void *handle, FAR void *dirp); +int rpmsgfs_client_bind(FAR void **handle, FAR const char *cpuname); +int rpmsgfs_client_unbind(FAR void *handle); +int rpmsgfs_client_closedir(FAR void *handle, FAR void *dirp); +int rpmsgfs_client_statfs(FAR void *handle, FAR const char *path, + FAR struct statfs *buf); +int rpmsgfs_client_unlink(FAR void *handle, FAR const char *pathname); +int rpmsgfs_client_mkdir(FAR void *handle, FAR const char *pathname, + mode_t mode); +int rpmsgfs_client_rmdir(FAR void *handle, FAR const char *pathname); +int rpmsgfs_client_rename(FAR void *handle, FAR const char *oldpath, + FAR const char *newpath); +int rpmsgfs_client_stat(FAR void *handle, FAR const char *path, + FAR struct stat *buf); +int rpmsgfs_client_chstat(FAR void *handle, FAR const char *path, + FAR const struct stat *buf, int flags); + +#endif /* __FS_RPMSGFS_H */ diff --git a/fs/rpmsgfs/rpmsgfs_client.c b/fs/rpmsgfs/rpmsgfs_client.c new file mode 100644 index 0000000000..430a2f44d3 --- /dev/null +++ b/fs/rpmsgfs/rpmsgfs_client.c @@ -0,0 +1,819 @@ +/**************************************************************************** + * fs/rpmsgfs/rpmsgfs_client.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 + +#include +#include + +#include +#include +#include +#include + +#include "rpmsgfs.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rpmsgfs_s +{ + struct rpmsg_endpoint ept; + char cpuname[RPMSG_NAME_SIZE]; +}; + +struct rpmsgfs_cookie_s +{ + sem_t sem; + int result; + FAR void *data; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rpmsgfs_default_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static void rpmsgfs_device_created(struct rpmsg_device *rdev, + FAR void *priv_); +static void rpmsgfs_device_destroy(struct rpmsg_device *rdev, + FAR void *priv_); +static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv); +static int rpmsgfs_send_recv(FAR struct rpmsgfs_s *priv, + uint32_t command, bool copy, + FAR struct rpmsgfs_header_s *msg, + int len, FAR void *data); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const rpmsg_ept_cb g_rpmsgfs_handler[] = +{ + [RPMSGFS_OPEN] = rpmsgfs_default_handler, + [RPMSGFS_CLOSE] = rpmsgfs_default_handler, + [RPMSGFS_READ] = rpmsgfs_read_handler, + [RPMSGFS_WRITE] = rpmsgfs_default_handler, + [RPMSGFS_LSEEK] = rpmsgfs_default_handler, + [RPMSGFS_IOCTL] = rpmsgfs_default_handler, + [RPMSGFS_SYNC] = rpmsgfs_default_handler, + [RPMSGFS_DUP] = rpmsgfs_default_handler, + [RPMSGFS_FSTAT] = rpmsgfs_stat_handler, + [RPMSGFS_FTRUNCATE] = rpmsgfs_default_handler, + [RPMSGFS_OPENDIR] = rpmsgfs_default_handler, + [RPMSGFS_READDIR] = rpmsgfs_readdir_handler, + [RPMSGFS_REWINDDIR] = rpmsgfs_default_handler, + [RPMSGFS_CLOSEDIR] = rpmsgfs_default_handler, + [RPMSGFS_STATFS] = rpmsgfs_statfs_handler, + [RPMSGFS_UNLINK] = rpmsgfs_default_handler, + [RPMSGFS_MKDIR] = rpmsgfs_default_handler, + [RPMSGFS_RMDIR] = rpmsgfs_default_handler, + [RPMSGFS_RENAME] = rpmsgfs_default_handler, + [RPMSGFS_STAT] = rpmsgfs_stat_handler, + [RPMSGFS_FCHSTAT] = rpmsgfs_default_handler, + [RPMSGFS_CHSTAT] = rpmsgfs_default_handler, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int rpmsgfs_default_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + FAR struct rpmsgfs_cookie_s *cookie = + (struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie; + + cookie->result = header->result; + if (cookie->result >= 0 && cookie->data) + { + memcpy(cookie->data, data, len); + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + FAR struct rpmsgfs_cookie_s *cookie = + (struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie; + FAR struct rpmsgfs_read_s *rsp = data; + + cookie->result = header->result; + if (cookie->result > 0) + { + memcpy(cookie->data, rsp->buf, B2C(cookie->result)); + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + FAR struct rpmsgfs_cookie_s *cookie = + (struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie; + FAR struct rpmsgfs_readdir_s *rsp = data; + FAR struct dirent *entry = cookie->data; + + cookie->result = header->result; + if (cookie->result >= 0) + { + nbstr2cstr(entry->d_name, rsp->name, NAME_MAX); + entry->d_name[NAME_MAX] = '\0'; + entry->d_type = rsp->type; + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + FAR struct rpmsgfs_cookie_s *cookie = + (struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie; + FAR struct rpmsgfs_statfs_s *rsp = data; + FAR struct statfs *buf = cookie->data; + + cookie->result = header->result; + if (cookie->result >= 0) + { + buf->f_type = rsp->buf.f_type; + buf->f_namelen = rsp->buf.f_namelen; + buf->f_bsize = B2C(rsp->buf.f_bsize); + buf->f_blocks = rsp->buf.f_blocks; + buf->f_bfree = rsp->buf.f_bfree; + buf->f_bavail = rsp->buf.f_bavail; + buf->f_files = rsp->buf.f_files; + buf->f_ffree = rsp->buf.f_ffree; + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + FAR struct rpmsgfs_cookie_s *cookie = + (struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie; + FAR struct rpmsgfs_stat_s *rsp = data; + FAR struct stat *buf = cookie->data; + + cookie->result = header->result; + if (cookie->result >= 0) + { + buf->st_dev = rsp->buf.st_dev; + buf->st_ino = rsp->buf.st_ino; + buf->st_mode = rsp->buf.st_mode; + buf->st_nlink = rsp->buf.st_nlink; + buf->st_uid = rsp->buf.st_uid; + buf->st_gid = rsp->buf.st_gid; + buf->st_rdev = rsp->buf.st_rdev; + buf->st_size = B2C(rsp->buf.st_size); + buf->st_atime = rsp->buf.st_atime; + buf->st_mtime = rsp->buf.st_mtime; + buf->st_ctime = rsp->buf.st_ctime; + buf->st_blksize = B2C(rsp->buf.st_blksize); + buf->st_blocks = rsp->buf.st_blocks; + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static void rpmsgfs_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct rpmsgfs_s *priv = priv_; + char buf[RPMSG_NAME_SIZE]; + + if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + priv->ept.priv = priv; + snprintf(buf, sizeof(buf), "%s%p", RPMSGFS_NAME_PREFIX, priv); + rpmsg_create_ept(&priv->ept, rdev, buf, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + rpmsgfs_ept_cb, NULL); + } +} + +static void rpmsgfs_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + struct rpmsgfs_s *priv = priv_; + + if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + rpmsg_destroy_ept(&priv->ept); + } +} + +static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + uint32_t command = header->command; + + if (command < ARRAY_SIZE(g_rpmsgfs_handler)) + { + return g_rpmsgfs_handler[command](ept, data, len, src, priv); + } + + return -EINVAL; +} + +static int rpmsgfs_send_recv(FAR struct rpmsgfs_s *priv, + uint32_t command, bool copy, + FAR struct rpmsgfs_header_s *msg, + int len, FAR void *data) +{ + FAR struct rpmsgfs_cookie_s cookie; + int ret; + + memset(&cookie, 0, sizeof(cookie)); + nxsem_init(&cookie.sem, 0, 0); + nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE); + + if (data) + { + cookie.data = data; + } + else if (copy) + { + cookie.data = msg; + } + + msg->command = command; + msg->result = -ENXIO; + msg->cookie = (uintptr_t)&cookie; + + if (copy) + { + ret = rpmsg_send(&priv->ept, msg, len); + } + else + { + ret = rpmsg_send_nocopy(&priv->ept, msg, len); + } + + if (ret < 0) + { + goto fail; + } + + ret = nxsem_wait_uninterruptible(&cookie.sem); + if (ret == 0) + { + ret = cookie.result; + } + +fail: + nxsem_destroy(&cookie.sem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int rpmsgfs_client_open(FAR void *handle, FAR const char *pathname, + int flags, int mode) +{ + FAR struct rpmsgfs_s *priv = handle; + FAR struct rpmsgfs_open_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + msg->flags = flags; + msg->mode = mode; + cstr2bstr(msg->pathname, pathname); + + return rpmsgfs_send_recv(priv, RPMSGFS_OPEN, false, + (struct rpmsgfs_header_s *)msg, len, NULL); +} + +int rpmsgfs_client_close(FAR void *handle, int fd) +{ + struct rpmsgfs_close_s msg = + { + .fd = fd, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_CLOSE, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +ssize_t rpmsgfs_client_read(FAR void *handle, int fd, + FAR void *buf, size_t count) +{ + size_t read = 0; + int ret = 0; + + while (read < count) + { + struct rpmsgfs_read_s msg = + { + .fd = fd, + .count = C2B(count - read), + }; + + ret = rpmsgfs_send_recv(handle, RPMSGFS_READ, true, + (FAR struct rpmsgfs_header_s *)&msg, sizeof(msg), buf); + if (ret <= 0) + { + break; + } + + read += B2C(ret); + buf += B2C(ret); + } + + return read ? read : ret; +} + +ssize_t rpmsgfs_client_write(FAR void *handle, int fd, + FAR const void *buf, size_t count) +{ + FAR struct rpmsgfs_s *priv = handle; + size_t written = 0; + int ret = 0; + + while (written < count) + { + FAR struct rpmsgfs_write_s *msg; + uint32_t space; + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + ret = -ENOMEM; + break; + } + + space -= sizeof(*msg); + if (space > count - written) + { + space = count - written; + } + + msg->fd = fd; + msg->count = C2B(space); + memcpy(msg->buf, buf + written, space); + + ret = rpmsgfs_send_recv(priv, RPMSGFS_WRITE, false, + (FAR struct rpmsgfs_header_s *)msg, + sizeof(*msg) + space, NULL); + if (ret <= 0) + { + break; + } + + written += B2C(ret); + } + + return written ? written : ret; +} + +off_t rpmsgfs_client_lseek(FAR void *handle, int fd, + off_t offset, int whence) +{ + struct rpmsgfs_lseek_s msg = + { + .fd = fd, + .offset = C2B(offset), + .whence = whence, + }; + + int ret; + + ret = rpmsgfs_send_recv(handle, RPMSGFS_LSEEK, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); + + return ret < 0 ? ret : B2C(ret); +} + +int rpmsgfs_client_ioctl(FAR void *handle, int fd, + int request, unsigned long arg) +{ + struct rpmsgfs_ioctl_s msg = + { + .fd = fd, + .request = request, + .arg = arg, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_IOCTL, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +void rpmsgfs_client_sync(FAR void *handle, int fd) +{ + struct rpmsgfs_sync_s msg = + { + .fd = fd, + }; + + rpmsgfs_send_recv(handle, RPMSGFS_SYNC, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +int rpmsgfs_client_dup(FAR void *handle, int fd) +{ + struct rpmsgfs_dup_s msg = + { + .fd = fd, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_DUP, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +int rpmsgfs_client_fstat(FAR void *handle, int fd, struct stat *buf) +{ + struct rpmsgfs_fstat_s msg = + { + .fd = fd, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_FSTAT, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), buf); +} + +int rpmsgfs_client_ftruncate(FAR void *handle, int fd, off_t length) +{ + struct rpmsgfs_ftruncate_s msg = + { + .fd = fd, + .length = length, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_FTRUNCATE, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +FAR void *rpmsgfs_client_opendir(FAR void *handle, FAR const char *name) +{ + FAR struct rpmsgfs_s *priv = handle; + FAR struct rpmsgfs_opendir_s *msg; + uint32_t space; + size_t len; + int ret; + + len = sizeof(*msg); + len += B2C(strlen(name) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return NULL; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, name); + + ret = rpmsgfs_send_recv(priv, RPMSGFS_OPENDIR, false, + (struct rpmsgfs_header_s *)msg, len, NULL); + + return ret < 0 ? NULL : (FAR void *)((uintptr_t)ret); +} + +int rpmsgfs_client_readdir(FAR void *handle, FAR void *dirp, + FAR struct dirent *entry) +{ + struct rpmsgfs_readdir_s msg = + { + .fd = (uintptr_t)dirp, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_READDIR, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), entry); +} + +void rpmsgfs_client_rewinddir(FAR void *handle, FAR void *dirp) +{ + struct rpmsgfs_rewinddir_s msg = + { + .fd = (uintptr_t)dirp, + }; + + rpmsgfs_send_recv(handle, RPMSGFS_REWINDDIR, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +int rpmsgfs_client_bind(FAR void **handle, FAR const char *cpuname) +{ + struct rpmsgfs_s *priv; + int ret; + + if (!cpuname) + { + return -EINVAL; + } + + priv = kmm_zalloc(sizeof(struct rpmsgfs_s)); + if (!priv) + { + return -ENOMEM; + } + + strncpy(priv->cpuname, cpuname, RPMSG_NAME_SIZE); + ret = rpmsg_register_callback(priv, + rpmsgfs_device_created, + rpmsgfs_device_destroy, + NULL); + if (ret < 0) + { + kmm_free(priv); + return ret; + } + + *handle = priv; + + return 0; +} + +int rpmsgfs_client_unbind(FAR void *handle) +{ + struct rpmsgfs_s *priv = handle; + + rpmsg_unregister_callback(priv, + rpmsgfs_device_created, + rpmsgfs_device_destroy, + NULL); + + kmm_free(priv); + return 0; +} + +int rpmsgfs_client_closedir(FAR void *handle, FAR void *dirp) +{ + struct rpmsgfs_closedir_s msg = + { + .fd = (uintptr_t)dirp, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_CLOSEDIR, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +int rpmsgfs_client_statfs(FAR void *handle, FAR const char *path, + FAR struct statfs *buf) +{ + struct rpmsgfs_s *priv = handle; + struct rpmsgfs_statfs_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(path) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, path); + + return rpmsgfs_send_recv(priv, RPMSGFS_STATFS, false, + (struct rpmsgfs_header_s *)msg, len, buf); +} + +int rpmsgfs_client_unlink(FAR void *handle, FAR const char *pathname) +{ + struct rpmsgfs_s *priv = handle; + struct rpmsgfs_unlink_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, pathname); + + return rpmsgfs_send_recv(priv, RPMSGFS_UNLINK, false, + (struct rpmsgfs_header_s *)msg, len, NULL); +} + +int rpmsgfs_client_mkdir(FAR void *handle, FAR const char *pathname, + mode_t mode) +{ + struct rpmsgfs_s *priv = handle; + struct rpmsgfs_mkdir_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + msg->mode = mode; + cstr2bstr(msg->pathname, pathname); + + return rpmsgfs_send_recv(priv, RPMSGFS_MKDIR, false, + (struct rpmsgfs_header_s *)msg, len, NULL); +} + +int rpmsgfs_client_rmdir(FAR void *handle, FAR const char *pathname) +{ + struct rpmsgfs_s *priv = handle; + struct rpmsgfs_rmdir_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, pathname); + + return rpmsgfs_send_recv(priv, RPMSGFS_RMDIR, false, + (struct rpmsgfs_header_s *)msg, len, NULL); +} + +int rpmsgfs_client_rename(FAR void *handle, FAR const char *oldpath, + FAR const char *newpath) +{ + struct rpmsgfs_s *priv = handle; + struct rpmsgfs_rename_s *msg; + size_t len; + size_t oldlen; + uint32_t space; + + len = sizeof(*msg); + oldlen = B2C((strlen(oldpath) + 1 + 0x7) & ~0x7); + len += oldlen + B2C(strlen(newpath) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, oldpath); + cstr2bstr(msg->pathname + oldlen, newpath); + + return rpmsgfs_send_recv(priv, RPMSGFS_RENAME, false, + (struct rpmsgfs_header_s *)msg, len, NULL); +} + +int rpmsgfs_client_stat(FAR void *handle, FAR const char *path, + FAR struct stat *buf) +{ + FAR struct rpmsgfs_s *priv = handle; + FAR struct rpmsgfs_stat_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(path) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, path); + + return rpmsgfs_send_recv(priv, RPMSGFS_STAT, false, + (struct rpmsgfs_header_s *)msg, len, buf); +} + +int rpmsgfs_client_fchstat(FAR void *handle, int fd, + const struct stat *buf, int flags) +{ + struct rpmsgfs_fchstat_s msg = + { + .flags = flags, + .buf = *buf, + .fd = fd, + }; + + return rpmsgfs_send_recv(handle, RPMSGFS_FCHSTAT, true, + (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); +} + +int rpmsgfs_client_chstat(FAR void *handle, FAR const char *path, + const FAR struct stat *buf, int flags) +{ + FAR struct rpmsgfs_s *priv = handle; + FAR struct rpmsgfs_chstat_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(path) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + msg->flags = flags; + memcpy(&msg->buf, buf, sizeof(*buf)); + cstr2bstr(msg->pathname, path); + + return rpmsgfs_send_recv(priv, RPMSGFS_CHSTAT, false, + (struct rpmsgfs_header_s *)msg, len, NULL); +} diff --git a/fs/rpmsgfs/rpmsgfs_server.c b/fs/rpmsgfs/rpmsgfs_server.c new file mode 100644 index 0000000000..9a7b27b5a8 --- /dev/null +++ b/fs/rpmsgfs/rpmsgfs_server.c @@ -0,0 +1,883 @@ +/**************************************************************************** + * fs/rpmsgfs/rpmsgfs_server.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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "rpmsgfs.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rpmsgfs_server_s +{ + struct rpmsg_endpoint ept; + FAR struct file **files; + FAR void **dirs; + int file_rows; + int dir_nums; + sem_t sem; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int rpmsgfs_open_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_close_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_write_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_lseek_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_sync_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_dup_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_fstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_ftruncate_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_opendir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_rewinddir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_closedir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_unlink_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_mkdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_rmdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_rename_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_fchstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgfs_chstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static void rpmsgfs_ns_bind(FAR struct rpmsg_device *rdev, + FAR void *priv_, FAR const char *name, + uint32_t dest); +static void rpmsgfs_ns_unbind(FAR struct rpmsg_endpoint *ept); +static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const rpmsg_ept_cb g_rpmsgfs_handler[] = +{ + [RPMSGFS_OPEN] = rpmsgfs_open_handler, + [RPMSGFS_CLOSE] = rpmsgfs_close_handler, + [RPMSGFS_READ] = rpmsgfs_read_handler, + [RPMSGFS_WRITE] = rpmsgfs_write_handler, + [RPMSGFS_LSEEK] = rpmsgfs_lseek_handler, + [RPMSGFS_IOCTL] = rpmsgfs_ioctl_handler, + [RPMSGFS_SYNC] = rpmsgfs_sync_handler, + [RPMSGFS_DUP] = rpmsgfs_dup_handler, + [RPMSGFS_FSTAT] = rpmsgfs_fstat_handler, + [RPMSGFS_FTRUNCATE] = rpmsgfs_ftruncate_handler, + [RPMSGFS_OPENDIR] = rpmsgfs_opendir_handler, + [RPMSGFS_READDIR] = rpmsgfs_readdir_handler, + [RPMSGFS_REWINDDIR] = rpmsgfs_rewinddir_handler, + [RPMSGFS_CLOSEDIR] = rpmsgfs_closedir_handler, + [RPMSGFS_STATFS] = rpmsgfs_statfs_handler, + [RPMSGFS_UNLINK] = rpmsgfs_unlink_handler, + [RPMSGFS_MKDIR] = rpmsgfs_mkdir_handler, + [RPMSGFS_RMDIR] = rpmsgfs_rmdir_handler, + [RPMSGFS_RENAME] = rpmsgfs_rename_handler, + [RPMSGFS_STAT] = rpmsgfs_stat_handler, + [RPMSGFS_FCHSTAT] = rpmsgfs_fchstat_handler, + [RPMSGFS_CHSTAT] = rpmsgfs_chstat_handler, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int rpmsgfs_attach_file(FAR struct rpmsgfs_server_s *priv, + FAR struct file *filep) +{ + FAR struct file **tmp; + int ret; + int i; + int j; + + nxsem_wait(&priv->sem); + + for (i = 0; i < priv->file_rows; i++) + { + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) + { + if (priv->files[i][j].f_inode == NULL) + { + memcpy(&priv->files[i][j], filep, sizeof(*filep)); + ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j; + goto out; + } + } + } + + tmp = kmm_realloc(priv->files, sizeof(FAR struct file *) * (i + 1)); + DEBUGASSERT(tmp); + if (tmp == NULL) + { + ret = -ENFILE; + goto out; + } + + tmp[i] = kmm_zalloc(sizeof(struct file) * + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK); + DEBUGASSERT(tmp[i]); + if (tmp[i] == NULL) + { + kmm_free(tmp); + ret = -ENFILE; + goto out; + } + + priv->files = tmp; + priv->file_rows++; + + memcpy(&priv->files[i][0], filep, sizeof(*filep)); + ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + +out: + nxsem_post(&priv->sem); + return ret; +} + +static int rpmsgfs_detach_file(FAR struct rpmsgfs_server_s *priv, + int fd, FAR struct file *filep) +{ + struct file *tfilep; + + if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) + { + return -EBADF; + } + + nxsem_wait(&priv->sem); + tfilep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; + memcpy(filep, tfilep, sizeof(*filep)); + memset(tfilep, 0, sizeof(*tfilep)); + nxsem_post(&priv->sem); + + return 0; +} + +static FAR struct file *rpmsgfs_get_file( + FAR struct rpmsgfs_server_s *priv, + int fd) +{ + FAR struct file *filep; + + if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) + { + return NULL; + } + + nxsem_wait(&priv->sem); + filep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; + nxsem_post(&priv->sem); + + return filep; +} + +static int rpmsgfs_attach_dir(FAR struct rpmsgfs_server_s *priv, + FAR void *dir) +{ + FAR void **tmp; + int i; + + nxsem_wait(&priv->sem); + for (i = 1; i < priv->dir_nums; i++) + { + if (priv->dirs[i] == NULL) + { + priv->dirs[i] = dir; + nxsem_post(&priv->sem); + return i; + } + } + + tmp = kmm_realloc(priv->dirs, sizeof(FAR void *) * + (priv->dir_nums + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)); + DEBUGASSERT(tmp); + if (tmp == NULL) + { + nxsem_post(&priv->sem); + return -ENOMEM; + } + + priv->dirs = tmp; + priv->dir_nums += CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + + priv->dirs[i] = dir; + nxsem_post(&priv->sem); + return i; +} + +static void *rpmsgfs_detach_dir(FAR struct rpmsgfs_server_s *priv, + int fd) +{ + FAR void *dir = NULL; + + if (fd >= 1 && fd < priv->dir_nums) + { + nxsem_wait(&priv->sem); + dir = priv->dirs[fd]; + priv->dirs[fd] = NULL; + nxsem_post(&priv->sem); + } + + return dir; +} + +static FAR void *rpmsgfs_get_dir( + FAR struct rpmsgfs_server_s *priv, + int fd) +{ + FAR void *dir = NULL; + + if (fd >= 1 && fd < priv->dir_nums) + { + nxsem_wait(&priv->sem); + dir = priv->dirs[fd]; + nxsem_post(&priv->sem); + } + + return dir; +} + +static int rpmsgfs_open_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_open_s *msg = data; + struct file file; + int ret; + + ret = file_open(&file, msg->pathname, msg->flags, msg->mode); + if (ret >= 0) + { + ret = rpmsgfs_attach_file(priv, &file); + if (ret < 0) + { + file_close(&file); + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_close_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_close_s *msg = data; + struct file file; + int ret; + + ret = rpmsgfs_detach_file(priv, msg->fd, &file); + if (ret >= 0) + { + ret = file_close(&file); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_read_s *msg = data; + FAR struct rpmsgfs_read_s *rsp; + FAR struct file *filep; + int ret = -ENOENT; + uint32_t space; + + rsp = rpmsg_get_tx_payload_buffer(ept, &space, true); + if (!rsp) + { + return -ENOMEM; + } + + *rsp = *msg; + + space -= sizeof(*msg); + if (space > msg->count) + { + space = msg->count; + } + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_read(filep, rsp->buf, space); + } + + rsp->header.result = ret; + return rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp)); +} + +static int rpmsgfs_write_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_write_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_write(filep, msg->buf, msg->count); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_lseek_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_lseek_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_seek(filep, msg->offset, msg->whence); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_ioctl_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_ioctl(filep, msg->request, msg->arg); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_sync_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_sync_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_fsync(filep); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_dup_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_dup_s *msg = data; + FAR struct file *filep; + struct file newfile; + int ret = -ENOENT; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_dup2(filep, &newfile); + if (ret >= 0) + { + ret = rpmsgfs_attach_file(priv, &newfile); + if (ret < 0) + { + file_close(&newfile); + } + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_fstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_fstat_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + struct stat buf; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_fstat(filep, &buf); + if (ret >= 0) + { + msg->buf = buf; + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_ftruncate_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_ftruncate_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + ret = file_truncate(filep, msg->length); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_opendir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_opendir_s *msg = data; + FAR void *dir; + int ret = -ENOENT; + + dir = opendir(msg->pathname); + if (dir) + { + ret = rpmsgfs_attach_dir(priv, dir); + if (ret < 0) + { + closedir(dir); + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_readdir_s *msg = data; + FAR struct dirent *entry; + int ret = -ENOENT; + FAR void *dir; + + dir = rpmsgfs_get_dir(priv, msg->fd); + if (dir) + { + entry = readdir(dir); + if (entry) + { + msg->type = entry->d_type; + strcpy(msg->name, entry->d_name); + len += strlen(entry->d_name) + 1; + ret = 0; + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, len); +} + +static int rpmsgfs_rewinddir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_rewinddir_s *msg = data; + int ret = -ENOENT; + FAR void *dir; + + dir = rpmsgfs_get_dir(priv, msg->fd); + if (dir) + { + rewinddir(dir); + ret = 0; + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_closedir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_closedir_s *msg = data; + int ret = -ENOENT; + FAR void *dir; + + dir = rpmsgfs_detach_dir(priv, msg->fd); + if (dir) + { + ret = closedir(dir) ? -get_errno() : 0; + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_statfs_s *msg = data; + struct statfs buf; + int ret; + + ret = statfs(msg->pathname, &buf); + if (ret) + { + ret = -get_errno(); + } + else + { + msg->buf = buf; + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_unlink_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_unlink_s *msg = data; + + msg->header.result = nx_unlink(msg->pathname); + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_mkdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_mkdir_s *msg = data; + int ret; + + ret = mkdir(msg->pathname, msg->mode); + msg->header.result = ret ? -get_errno() : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_rmdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_rmdir_s *msg = data; + int ret; + + ret = rmdir(msg->pathname); + msg->header.result = ret ? -get_errno() : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_rename_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_rename_s *msg = data; + FAR char *newpath; + size_t oldlen; + int ret; + + oldlen = (strlen(msg->pathname) + 1 + 0x7) & ~0x7; + newpath = msg->pathname + oldlen; + + ret = rename(msg->pathname, newpath); + msg->header.result = ret ? -get_errno() : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_stat_s *msg = data; + struct stat buf; + int ret; + + ret = nx_stat(msg->pathname, &buf, 1); + if (ret >= 0) + { + msg->buf = buf; + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_fchstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_fchstat_s *msg = data; + FAR struct file *filep; + int ret = -ENOENT; + struct stat buf; + + filep = rpmsgfs_get_file(priv, msg->fd); + if (filep != NULL) + { + buf = msg->buf; + ret = file_fchstat(filep, &buf, msg->flags); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int rpmsgfs_chstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_chstat_s *msg = data; + struct timespec times[2]; + int ret = 0; + + if (msg->flags & CH_STAT_MODE) + { + ret = chmod(msg->pathname, msg->buf.st_mode); + if (ret < 0) + { + ret = -get_errno(); + goto out; + } + } + + if (msg->flags & (CH_STAT_UID | CH_STAT_GID)) + { + ret = chown(msg->pathname, msg->buf.st_uid, msg->buf.st_gid); + if (ret < 0) + { + ret = -get_errno(); + goto out; + } + } + + if (msg->flags & (CH_STAT_ATIME | CH_STAT_MTIME)) + { + if (msg->flags & CH_STAT_ATIME) + { + times[0] = msg->buf.st_atim; + } + else + { + times[0].tv_nsec = UTIME_OMIT; + } + + if (msg->flags & CH_STAT_MTIME) + { + times[1] = msg->buf.st_mtim; + } + else + { + times[1].tv_nsec = UTIME_OMIT; + } + + ret = utimens(msg->pathname, times); + if (ret < 0) + { + ret = -get_errno(); + goto out; + } + } + +out: + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static void rpmsgfs_ns_bind(FAR struct rpmsg_device *rdev, + FAR void *priv_, FAR const char *name, + uint32_t dest) +{ + FAR struct rpmsgfs_server_s *priv; + int ret; + + if (strncmp(name, RPMSGFS_NAME_PREFIX, strlen(RPMSGFS_NAME_PREFIX))) + { + return; + } + + priv = kmm_zalloc(sizeof(*priv)); + if (!priv) + { + return; + } + + priv->ept.priv = priv; + nxsem_init(&priv->sem, 0, 1); + + ret = rpmsg_create_ept(&priv->ept, rdev, name, + RPMSG_ADDR_ANY, dest, + rpmsgfs_ept_cb, rpmsgfs_ns_unbind); + if (ret) + { + nxsem_destroy(&priv->sem); + kmm_free(priv); + } +} + +static void rpmsgfs_ns_unbind(FAR struct rpmsg_endpoint *ept) +{ + FAR struct rpmsgfs_server_s *priv = ept->priv; + int i; + int j; + + for (i = 0; i < priv->file_rows; i++) + { + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) + { + if (priv->files[i][j].f_inode) + { + file_close(&priv->files[i][j]); + } + } + + kmm_free(priv->files[i]); + } + + for (i = 0; i < priv->dir_nums; i++) + { + if (priv->dirs[i]) + { + closedir(priv->dirs[i]); + } + } + + rpmsg_destroy_ept(&priv->ept); + nxsem_destroy(&priv->sem); + + kmm_free(priv->files); + kmm_free(priv->dirs); + kmm_free(priv); +} + +static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv) +{ + struct rpmsgfs_header_s *header = data; + uint32_t command = header->command; + + if (command < ARRAY_SIZE(g_rpmsgfs_handler)) + { + return g_rpmsgfs_handler[command](ept, data, len, src, priv); + } + + return -EINVAL; +} + +int rpmsgfs_server_init(void) +{ + return rpmsg_register_callback(NULL, + NULL, + NULL, + rpmsgfs_ns_bind); +} diff --git a/include/nuttx/fs/dirent.h b/include/nuttx/fs/dirent.h index a9a9675469..0f19340b9d 100644 --- a/include/nuttx/fs/dirent.h +++ b/include/nuttx/fs/dirent.h @@ -207,6 +207,17 @@ struct fs_hostfsdir_s }; #endif +#ifdef CONFIG_FS_RPMSGFS +/* RPMSGFS provides mapping to directories on the host machine in the + * sim environment. + */ + +struct fs_rpmsgfsdir_s +{ + FAR void *fs_dir; /* Opaque pointer to remote DIR */ +}; +#endif + #endif /* CONFIG_DISABLE_MOUNTPOINT */ struct fs_dirent_s @@ -288,6 +299,9 @@ struct fs_dirent_s #ifdef CONFIG_FS_HOSTFS struct fs_hostfsdir_s hostfs; #endif +#ifdef CONFIG_FS_RPMSGFS + struct fs_rpmsgfsdir_s rpmsgfs; +#endif #endif /* !CONFIG_DISABLE_MOUNTPOINT */ } u; diff --git a/include/nuttx/fs/hostfs_rpmsg.h b/include/nuttx/fs/rpmsgfs.h similarity index 87% rename from include/nuttx/fs/hostfs_rpmsg.h rename to include/nuttx/fs/rpmsgfs.h index 4154b8b69f..76de3de524 100644 --- a/include/nuttx/fs/hostfs_rpmsg.h +++ b/include/nuttx/fs/rpmsgfs.h @@ -1,5 +1,5 @@ /**************************************************************************** - * include/nuttx/fs/hostfs_rpmsg.h + * include/nuttx/fs/rpmsgfs.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -33,12 +33,8 @@ extern "C" #define EXTERN extern #endif -#ifdef CONFIG_FS_HOSTFS_RPMSG -int hostfs_rpmsg_init(FAR const char *cpu_name); -#endif - -#ifdef CONFIG_FS_HOSTFS_RPMSG_SERVER -int hostfs_rpmsg_server_init(void); +#ifdef CONFIG_FS_RPMSGFS +int rpmsgfs_server_init(void); #endif #undef EXTERN diff --git a/include/sys/statfs.h b/include/sys/statfs.h index 6cbd2543f7..1bb9bed657 100644 --- a/include/sys/statfs.h +++ b/include/sys/statfs.h @@ -93,6 +93,7 @@ #define HOSTFS_MAGIC 0x54534f48 #define USERFS_MAGIC 0x52455355 #define CROMFS_MAGIC 0x4d4f5243 +#define RPMSGFS_MAGIC 0x54534f47 #if defined(CONFIG_FS_LARGEFILE) && defined(CONFIG_HAVE_LONG_LONG) # define statfs64 statfs