From 86193c95caee67692f62f87e06d0ebc96add7b65 Mon Sep 17 00:00:00 2001 From: zhengyu16 Date: Tue, 25 Nov 2025 22:19:48 +0800 Subject: [PATCH] fs/hostfs: add link, symlink, readlink and lstat support Implemented link(), symlink(), readlink() and lstat() in hostfs. Signed-off-by: zhengyu16 --- arch/arm/src/common/arm_hostfs.c | 28 ++ arch/arm64/src/common/arm64_hostfs.c | 22 ++ arch/risc-v/src/common/riscv_hostfs.c | 22 ++ arch/sim/src/nuttx-names.in | 3 + arch/sim/src/sim/posix/sim_hostfs.c | 71 +++++ arch/sim/src/sim/win/sim_hostfs.c | 39 +++ arch/xtensa/src/common/xtensa_hostfs.c | 22 ++ fs/hostfs/hostfs.c | 372 +++++++++++++++++++++++-- include/nuttx/fs/hostfs.h | 13 + 9 files changed, 568 insertions(+), 24 deletions(-) diff --git a/arch/arm/src/common/arm_hostfs.c b/arch/arm/src/common/arm_hostfs.c index 8c47a46138c..682861cf442 100644 --- a/arch/arm/src/common/arm_hostfs.c +++ b/arch/arm/src/common/arm_hostfs.c @@ -370,3 +370,31 @@ int host_chstat(const char *path, const struct stat *buf, int flags) { return -ENOSYS; } + +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2) +{ + /* ARM semihosting doesn't support hard links */ + + return -ENOSYS; +} + +int host_symlink(const char *target, const char *linkpath) +{ + /* ARM semihosting doesn't support symbolic links */ + + return -ENOSYS; +} + +ssize_t host_readlink(const char *path, char *buf, size_t bufsize) +{ + /* ARM semihosting doesn't support symbolic links */ + + return -ENOSYS; +} + +int host_lstat(const char *path, struct stat *buf) +{ + return -ENOSYS; +} +#endif /* CONFIG_FS_LINKS */ diff --git a/arch/arm64/src/common/arm64_hostfs.c b/arch/arm64/src/common/arm64_hostfs.c index ff4419292c5..452268b10a6 100644 --- a/arch/arm64/src/common/arm64_hostfs.c +++ b/arch/arm64/src/common/arm64_hostfs.c @@ -370,3 +370,25 @@ int host_chstat(const char *path, const struct stat *buf, int flags) { return -ENOSYS; } + +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2) +{ + return -ENOSYS; +} + +int host_symlink(const char *target, const char *linkpath) +{ + return -ENOSYS; +} + +ssize_t host_readlink(const char *path, char *buf, size_t bufsize) +{ + return -ENOSYS; +} + +int host_lstat(const char *path, struct stat *buf) +{ + return -ENOSYS; +} +#endif /* CONFIG_FS_LINKS */ diff --git a/arch/risc-v/src/common/riscv_hostfs.c b/arch/risc-v/src/common/riscv_hostfs.c index 8a87c74afdf..cd319f941a2 100644 --- a/arch/risc-v/src/common/riscv_hostfs.c +++ b/arch/risc-v/src/common/riscv_hostfs.c @@ -368,3 +368,25 @@ int host_chstat(const char *path, const struct stat *buf, int flags) { return -ENOSYS; } + +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2) +{ + return -ENOSYS; +} + +int host_symlink(const char *target, const char *linkpath) +{ + return -ENOSYS; +} + +ssize_t host_readlink(const char *path, char *buf, size_t bufsize) +{ + return -ENOSYS; +} + +int host_lstat(const char *path, struct stat *buf) +{ + return -ENOSYS; +} +#endif /* CONFIG_FS_LINKS */ diff --git a/arch/sim/src/nuttx-names.in b/arch/sim/src/nuttx-names.in index 9a47af018a8..3c7f1caa744 100644 --- a/arch/sim/src/nuttx-names.in +++ b/arch/sim/src/nuttx-names.in @@ -75,9 +75,11 @@ NXSYMBOLS(getpid) NXSYMBOLS(getsockopt) NXSYMBOLS(if_nametoindex) NXSYMBOLS(ioctl) +NXSYMBOLS(link) NXSYMBOLS(listen) NXSYMBOLS(longjmp) NXSYMBOLS(lseek) +NXSYMBOLS(lstat) NXSYMBOLS(malloc) NXSYMBOLS(malloc_size) NXSYMBOLS(malloc_usable_size) @@ -154,6 +156,7 @@ NXSYMBOLS(strchr) NXSYMBOLS(strerror) NXSYMBOLS(strlen) NXSYMBOLS(strtol) +NXSYMBOLS(symlink) NXSYMBOLS(sysconf) NXSYMBOLS(syslog) NXSYMBOLS(system) diff --git a/arch/sim/src/sim/posix/sim_hostfs.c b/arch/sim/src/sim/posix/sim_hostfs.c index 67380d14038..d95f07ee992 100644 --- a/arch/sim/src/sim/posix/sim_hostfs.c +++ b/arch/sim/src/sim/posix/sim_hostfs.c @@ -820,3 +820,74 @@ int host_chstat(const char *path, const struct nuttx_stat_s *buf, int flags) return 0; } + +/**************************************************************************** + * Name: host_link + ****************************************************************************/ + +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2) +{ + int ret = link(path1, path2); + if (ret < 0) + { + ret = -errno; + } + + return ret; +} + +/**************************************************************************** + * Name: host_symlink + ****************************************************************************/ + +int host_symlink(const char *target, const char *linkpath) +{ + int ret = symlink(target, linkpath); + if (ret < 0) + { + ret = -errno; + } + + return ret; +} + +/**************************************************************************** + * Name: host_readlink + ****************************************************************************/ + +nuttx_ssize_t host_readlink(const char *path, char *buf, + nuttx_size_t bufsize) +{ + ssize_t ret = readlink(path, buf, bufsize); + if (ret < 0) + { + ret = -errno; + } + + return ret; +} + +/**************************************************************************** + * Name: host_lstat + ****************************************************************************/ + +int host_lstat(const char *path, struct nuttx_stat_s *buf) +{ + struct stat hostbuf; + int ret; + + /* Call the host's lstat routine */ + + ret = lstat(path, &hostbuf); + if (ret < 0) + { + ret = -errno; + } + + /* Map the return values */ + + host_stat_convert(&hostbuf, buf); + return ret; +} +#endif /* CONFIG_FS_LINKS */ diff --git a/arch/sim/src/sim/win/sim_hostfs.c b/arch/sim/src/sim/win/sim_hostfs.c index 65f3208f085..e20a5ff5b42 100644 --- a/arch/sim/src/sim/win/sim_hostfs.c +++ b/arch/sim/src/sim/win/sim_hostfs.c @@ -461,3 +461,42 @@ int host_chstat(const char *path, const struct nuttx_stat_s *buf, int flags) { return -ENOSYS; } + +/**************************************************************************** + * Name: host_link + ****************************************************************************/ + +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: host_symlink + ****************************************************************************/ + +int host_symlink(const char *target, const char *linkpath) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: host_readlink + ****************************************************************************/ + +nuttx_ssize_t host_readlink(const char *path, char *buf, + nuttx_size_t bufsize) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: host_lstat + ****************************************************************************/ + +int host_lstat(const char *path, struct nuttx_stat_s *buf) +{ + return -ENOSYS; +} +#endif /* CONFIG_FS_LINKS */ diff --git a/arch/xtensa/src/common/xtensa_hostfs.c b/arch/xtensa/src/common/xtensa_hostfs.c index d803bce9083..075b342bae1 100644 --- a/arch/xtensa/src/common/xtensa_hostfs.c +++ b/arch/xtensa/src/common/xtensa_hostfs.c @@ -256,3 +256,25 @@ int host_chstat(const char *path, const struct stat *buf, int flags) { return -ENOSYS; } + +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2) +{ + return -ENOSYS; +} + +int host_symlink(const char *target, const char *linkpath) +{ + return -ENOSYS; +} + +ssize_t host_readlink(const char *path, char *buf, size_t bufsize) +{ + return -ENOSYS; +} + +int host_lstat(const char *path, struct stat *buf) +{ + return -ENOSYS; +} +#endif /* CONFIG_FS_LINKS */ diff --git a/fs/hostfs/hostfs.c b/fs/hostfs/hostfs.c index c9f24b5fd4a..8d6f80f02b1 100644 --- a/fs/hostfs/hostfs.c +++ b/fs/hostfs/hostfs.c @@ -117,6 +117,21 @@ static int hostfs_chstat(FAR struct inode *mountpt, FAR const char *relpath, FAR const struct stat *buf, int flags); +#ifdef CONFIG_FS_LINKS +static int hostfs_link(FAR struct inode *mountpt, + FAR const char *relpath1, + FAR const char *relpath2); +static int hostfs_symlink(FAR struct inode *mountpt, + FAR const char *path1, + FAR const char *relpath2); +static ssize_t hostfs_readlink(FAR struct inode *mountpt, + FAR const char *relpath, + FAR char *buf, size_t bufsize); +static int hostfs_lstat(FAR struct inode *mountpt, + FAR const char *relpath, + FAR struct stat *buf); +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -160,6 +175,15 @@ const struct mountpt_operations g_hostfs_operations = hostfs_rename, /* rename */ hostfs_stat, /* stat */ hostfs_chstat, /* chstat */ + NULL, /* syncfs */ + NULL, /* ioctldir */ + NULL, /* permission */ +#ifdef CONFIG_FS_LINKS + hostfs_link, /* link */ + hostfs_symlink, /* symlink */ + hostfs_readlink, /* readlink */ + hostfs_lstat, /* lstat */ +#endif }; /**************************************************************************** @@ -237,7 +261,7 @@ static int hostfs_open(FAR struct file *filep, FAR const char *relpath, FAR struct inode *inode; FAR struct hostfs_mountpt_s *fs; FAR struct hostfs_ofile_s *hf; - char path[HOSTFS_MAX_PATH]; + FAR char *path; size_t len; int ret; @@ -254,12 +278,18 @@ static int hostfs_open(FAR struct file *filep, FAR const char *relpath, DEBUGASSERT(fs != NULL); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Take the lock */ ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_path; } /* Allocate memory for the open file */ @@ -274,7 +304,7 @@ static int hostfs_open(FAR struct file *filep, FAR const char *relpath, /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Try to open the file in the host file system */ @@ -328,6 +358,10 @@ errout_with_buffer: errout_with_lock: nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); + if (ret == -EINVAL) { ret = -EIO; @@ -839,20 +873,27 @@ static int hostfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, { FAR struct hostfs_mountpt_s *fs; FAR struct hostfs_dir_s *hdir; - char path[HOSTFS_MAX_PATH]; + FAR char *path; int ret; /* Sanity checks */ DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Recover our private data from the inode instance */ fs = mountpt->i_private; hdir = fs_heap_zalloc(sizeof(struct hostfs_dir_s)); if (hdir == NULL) { - return -ENOMEM; + ret = -ENOMEM; + goto errout_with_path; } /* Take the lock */ @@ -865,7 +906,7 @@ static int hostfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Call the host's opendir function */ @@ -878,6 +919,7 @@ static int hostfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, *dir = (FAR struct fs_dirent_s *)hdir; nxmutex_unlock(&fs->fs_lock); + lib_put_tempbuffer(path); return OK; errout_with_lock: @@ -885,6 +927,9 @@ errout_with_lock: errout_with_hdir: fs_heap_free(hdir); + +errout_with_path: + lib_put_tempbuffer(path); return ret; } @@ -1204,13 +1249,19 @@ static int hostfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf) static int hostfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) { FAR struct hostfs_mountpt_s *fs; - char path[HOSTFS_MAX_PATH]; + FAR char *path; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; @@ -1218,18 +1269,21 @@ static int hostfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_path; } /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Call the host fs to perform the unlink */ ret = host_unlink(path); nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); return ret; } @@ -1244,13 +1298,19 @@ static int hostfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, mode_t mode) { FAR struct hostfs_mountpt_s *fs; - char path[HOSTFS_MAX_PATH]; + FAR char *path; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; @@ -1258,18 +1318,21 @@ static int hostfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_path; } /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Call the host FS to do the mkdir */ ret = host_mkdir(path, mode); nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); return ret; } @@ -1283,13 +1346,19 @@ static int hostfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath, int hostfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) { FAR struct hostfs_mountpt_s *fs; - char path[HOSTFS_MAX_PATH]; + FAR char *path; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; @@ -1299,18 +1368,21 @@ int hostfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_path; } /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Call the host FS to do the mkdir */ ret = host_rmdir(path); nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); return ret; } @@ -1325,14 +1397,27 @@ int hostfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, FAR const char *newrelpath) { FAR struct hostfs_mountpt_s *fs; - char oldpath[HOSTFS_MAX_PATH]; - char newpath[HOSTFS_MAX_PATH]; + FAR char *oldpath; + FAR char *newpath; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); + oldpath = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (oldpath == NULL) + { + return -ENOMEM; + } + + newpath = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (newpath == NULL) + { + ret = -ENOMEM; + goto errout_with_oldpath; + } + /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; @@ -1340,7 +1425,7 @@ int hostfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_newpath; } /* Append to the host's root directory */ @@ -1355,6 +1440,12 @@ int hostfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath, ret = host_rename(oldpath, newpath); nxmutex_unlock(&fs->fs_lock); + +errout_with_newpath: + lib_put_tempbuffer(newpath); + +errout_with_oldpath: + lib_put_tempbuffer(oldpath); return ret; } @@ -1369,13 +1460,19 @@ static int hostfs_stat(FAR struct inode *mountpt, FAR const char *relpath, FAR struct stat *buf) { FAR struct hostfs_mountpt_s *fs; - char path[HOSTFS_MAX_PATH]; + FAR char *path; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; @@ -1383,18 +1480,21 @@ static int hostfs_stat(FAR struct inode *mountpt, FAR const char *relpath, ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_path; } /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Call the host FS to do the stat operation */ ret = host_stat(path, buf); nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); return ret; } @@ -1409,13 +1509,19 @@ static int hostfs_chstat(FAR struct inode *mountpt, FAR const char *relpath, FAR const struct stat *buf, int flags) { FAR struct hostfs_mountpt_s *fs; - char path[HOSTFS_MAX_PATH]; + FAR char *path; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; @@ -1423,21 +1529,239 @@ static int hostfs_chstat(FAR struct inode *mountpt, FAR const char *relpath, ret = nxmutex_lock(&fs->fs_lock); if (ret < 0) { - return ret; + goto errout_with_path; } /* Append to the host's root directory */ - hostfs_mkpath(fs, relpath, path, sizeof(path)); + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); /* Call the host FS to do the chstat operation */ ret = host_chstat(path, buf, flags); nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); + return ret; +} + +#ifdef CONFIG_FS_LINKS +/**************************************************************************** + * Name: hostfs_link + * + * Description: Create a hard link + * + ****************************************************************************/ + +static int hostfs_link(FAR struct inode *mountpt, FAR const char *relpath1, + FAR const char *relpath2) +{ + FAR struct hostfs_mountpt_s *fs; + FAR char *path1; + FAR char *path2; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + path1 = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path1 == NULL) + { + return -ENOMEM; + } + + path2 = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path2 == NULL) + { + ret = -ENOMEM; + goto errout_with_path1; + } + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = nxmutex_lock(&fs->fs_lock); + if (ret < 0) + { + goto errout_with_path2; + } + + /* Append to the host's root directory */ + + hostfs_mkpath(fs, relpath1, path1, HOSTFS_MAX_PATH); + hostfs_mkpath(fs, relpath2, path2, HOSTFS_MAX_PATH); + + /* Call the host FS to create the hard link */ + + ret = host_link(path1, path2); + + nxmutex_unlock(&fs->fs_lock); + +errout_with_path2: + lib_put_tempbuffer(path2); + +errout_with_path1: + lib_put_tempbuffer(path1); return ret; } +/**************************************************************************** + * Name: hostfs_symlink + * + * Description: Create a symbolic link + * + ****************************************************************************/ + +static int hostfs_symlink(FAR struct inode *mountpt, + FAR const char *path1, + FAR const char *relpath2) +{ + FAR struct hostfs_mountpt_s *fs; + FAR char *fullpath2; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + fullpath2 = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (fullpath2 == NULL) + { + return -ENOMEM; + } + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = nxmutex_lock(&fs->fs_lock); + if (ret < 0) + { + goto errout_with_path; + } + + /* Build the full path for the link location (relpath2) + * The target (path1) is used as-is, allowing relative or absolute paths + */ + + hostfs_mkpath(fs, relpath2, fullpath2, HOSTFS_MAX_PATH); + + /* Call the host FS to create the symbolic link */ + + ret = host_symlink(path1, fullpath2); + + nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(fullpath2); + return ret; +} + +/**************************************************************************** + * Name: hostfs_readlink + * + * Description: Read the target of a symbolic link + * + ****************************************************************************/ + +static ssize_t hostfs_readlink(FAR struct inode *mountpt, + FAR const char *relpath, + FAR char *buf, size_t bufsize) +{ + FAR struct hostfs_mountpt_s *fs; + FAR char *path; + ssize_t ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = nxmutex_lock(&fs->fs_lock); + if (ret < 0) + { + goto errout_with_path; + } + + /* Append to the host's root directory */ + + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); + + /* Call the host FS to read the symbolic link */ + + ret = host_readlink(path, buf, bufsize); + + nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); + return ret; +} + +/**************************************************************************** + * Name: hostfs_lstat + * + * Description: Return information about a file or directory (don't follow + * symbolic links) + * + ****************************************************************************/ + +static int hostfs_lstat(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct stat *buf) +{ + FAR struct hostfs_mountpt_s *fs; + FAR char *path; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + path = lib_get_tempbuffer(HOSTFS_MAX_PATH); + if (path == NULL) + { + return -ENOMEM; + } + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + ret = nxmutex_lock(&fs->fs_lock); + if (ret < 0) + { + goto errout_with_path; + } + + /* Append to the host's root directory */ + + hostfs_mkpath(fs, relpath, path, HOSTFS_MAX_PATH); + + /* Call the host FS to do the lstat operation */ + + ret = host_lstat(path, buf); + + nxmutex_unlock(&fs->fs_lock); + +errout_with_path: + lib_put_tempbuffer(path); + return ret; +} +#endif /* CONFIG_FS_LINKS */ + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/include/nuttx/fs/hostfs.h b/include/nuttx/fs/hostfs.h index 601b210db5a..e3e4aa6933c 100644 --- a/include/nuttx/fs/hostfs.h +++ b/include/nuttx/fs/hostfs.h @@ -256,6 +256,13 @@ int host_rename(const char *oldpath, const char *newpath); int host_stat(const char *path, struct nuttx_stat_s *buf); int host_chstat(const char *path, const struct nuttx_stat_s *buf, int flags); +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2); +int host_symlink(const char *target, const char *linkpath); +nuttx_ssize_t host_readlink(const char *path, char *buf, + nuttx_size_t bufsize); +int host_lstat(const char *path, struct nuttx_stat_s *buf); +#endif #else int host_open(const char *pathname, int flags, int mode); int host_close(int fd); @@ -280,6 +287,12 @@ int host_rename(const char *oldpath, const char *newpath); int host_stat(const char *path, struct stat *buf); int host_chstat(const char *path, const struct stat *buf, int flags); +#ifdef CONFIG_FS_LINKS +int host_link(const char *path1, const char *path2); +int host_symlink(const char *target, const char *linkpath); +ssize_t host_readlink(const char *path, char *buf, size_t bufsize); +int host_lstat(const char *path, struct stat *buf); +#endif #endif /* __SIM__ */ #endif /* __INCLUDE_NUTTX_FS_HOSTFS_H */