You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/12/04 07:04:30 UTC
[incubator-nuttx] 01/02: hosfs_rpmsg: merge hostfs_rpmsg to rpmsgfs
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 985cc4fc6d093fd8949856a0830c9d839f96e24b
Author: ligd <li...@xiaomi.com>
AuthorDate: Tue Nov 30 20:00:03 2021 +0800
hosfs_rpmsg: merge hostfs_rpmsg to rpmsgfs
Signed-off-by: ligd <li...@xiaomi.com>
---
fs/Kconfig | 1 +
fs/Makefile | 1 +
fs/hostfs/Kconfig | 20 -
fs/hostfs/Make.defs | 8 -
fs/hostfs/hostfs_rpmsg.c | 775 -------------
fs/hostfs/hostfs_rpmsg.h | 203 ----
fs/hostfs/hostfs_rpmsg_server.c | 883 --------------
fs/mount/fs_gettype.c | 6 +
fs/mount/fs_mount.c | 6 +
fs/rpmsgfs/Kconfig | 12 +
fs/{hostfs => rpmsgfs}/Make.defs | 20 +-
fs/rpmsgfs/rpmsgfs.c | 1456 ++++++++++++++++++++++++
fs/rpmsgfs/rpmsgfs.h | 246 ++++
fs/rpmsgfs/rpmsgfs_client.c | 819 +++++++++++++
fs/rpmsgfs/rpmsgfs_server.c | 883 ++++++++++++++
include/nuttx/fs/dirent.h | 14 +
include/nuttx/fs/{hostfs_rpmsg.h => rpmsgfs.h} | 10 +-
include/sys/statfs.h | 1 +
18 files changed, 3454 insertions(+), 1910 deletions(-)
diff --git a/fs/Kconfig b/fs/Kconfig
index 240f712..3bbda1f 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 90e1181..c09c0e3 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 0395f66..6ef25b8 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 5dc6a24..a18589c 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 4e5be7d..0000000
--- 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 <nuttx/config.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-
-#include <nuttx/kmalloc.h>
-#include <nuttx/fs/hostfs.h>
-#include <nuttx/fs/hostfs_rpmsg.h>
-#include <nuttx/rptun/openamp.h>
-#include <nuttx/semaphore.h>
-
-#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 9f11a1d..0000000
--- 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 <sys/stat.h>
-#include <sys/statfs.h>
-
-/****************************************************************************
- * 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 9e8a68b..0000000
--- 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 <nuttx/config.h>
-
-#include <dirent.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <nuttx/kmalloc.h>
-#include <nuttx/fs/fs.h>
-#include <nuttx/fs/hostfs_rpmsg.h>
-#include <nuttx/rptun/openamp.h>
-
-#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 326ce47..b5894a6 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 b0c7d2e..5450fcd 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[] =
{
@@ -208,6 +211,9 @@ static const struct fsmap_t g_nonbdfsmap[] =
#ifdef CONFIG_FS_UNIONFS
{ "unionfs", &unionfs_operations },
#endif
+#ifdef CONFIG_FS_RPMSGFS
+ { "rpmsgfs", &rpmsgfs_operations },
+#endif
{ NULL, NULL },
};
#endif /* NODFS_SUPPORT */
diff --git a/fs/rpmsgfs/Kconfig b/fs/rpmsgfs/Kconfig
new file mode 100644
index 0000000..30995a5
--- /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/hostfs/Make.defs b/fs/rpmsgfs/Make.defs
similarity index 76%
copy from fs/hostfs/Make.defs
copy to fs/rpmsgfs/Make.defs
index 5dc6a24..aea7bf0 100644
--- a/fs/hostfs/Make.defs
+++ b/fs/rpmsgfs/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# fs/hostfs/Make.defs
+# fs/rpmsgfs/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -18,19 +18,11 @@
#
############################################################################
-# Include HOSTFS build support
+# Include RPSMGFS build support
-DEPPATH += --dep-path hostfs
-VPATH += :hostfs
+DEPPATH += --dep-path rpmsgfs
+VPATH += :rpmsgfs
-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
+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 0000000..e096be4
--- /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 <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <debug.h>
+#include <limits.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/dirent.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/fs/rpmsgfs.h>
+
+#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 0000000..7f1014d
--- /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 <dirent.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+/****************************************************************************
+ * 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 0000000..430a2f4
--- /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 <nuttx/config.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/rpmsgfs.h>
+#include <nuttx/rptun/openamp.h>
+#include <nuttx/semaphore.h>
+
+#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 0000000..9a7b27b
--- /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 <nuttx/config.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/rpmsgfs.h>
+#include <nuttx/rptun/openamp.h>
+
+#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 a9a9675..0f19340 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 4154b8b..76de3de 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 6cbd254..1bb9bed 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