mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
fs: Implement lstat function
specified here: https://pubs.opengroup.org/onlinepubs/009695399/functions/lstat.html Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com> Change-Id: Iefc23a02d425ff84fa4027aea7da1181b01eced7
This commit is contained in:
+5
-4
@@ -248,9 +248,10 @@ int inode_find(FAR struct inode_search_s *desc);
|
|||||||
* <sys/stat.h>, into which information is placed concerning the file.
|
* <sys/stat.h>, into which information is placed concerning the file.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* inode - The indoe of interest
|
* inode - The inode of interest
|
||||||
* buf - The caller provide location in which to return information about
|
* buf - The caller provide location in which to return information
|
||||||
* the inode.
|
* about the inode.
|
||||||
|
* resolve - Whether to resolve the symbolic link
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero (OK) returned on success. Otherwise, a negated errno value is
|
* Zero (OK) returned on success. Otherwise, a negated errno value is
|
||||||
@@ -259,7 +260,7 @@ int inode_find(FAR struct inode_search_s *desc);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct stat; /* Forward reference */
|
struct stat; /* Forward reference */
|
||||||
int inode_stat(FAR struct inode *inode, FAR struct stat *buf);
|
int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: inode_free
|
* Name: inode_free
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ static int automount_interrupt(FAR const struct automount_lower_s *lower,
|
|||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* OK_EXIST if the inode exists
|
* OK_EXIST if the inode exists
|
||||||
* OK_NOENT if the indoe does not exist
|
* OK_NOENT if the inode does not exist
|
||||||
* Negated errno if some failure occurs
|
* Negated errno if some failure occurs
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
+1
-1
@@ -199,7 +199,7 @@ int file_fstat(FAR struct file *filep, FAR struct stat *buf)
|
|||||||
{
|
{
|
||||||
/* The inode is part of the root pseudo file system. */
|
/* The inode is part of the root pseudo file system. */
|
||||||
|
|
||||||
ret = inode_stat(inode, buf);
|
ret = inode_stat(inode, buf, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+62
-42
@@ -58,7 +58,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int statroot(FAR struct stat *buf);
|
static inline int statroot(FAR struct stat *buf);
|
||||||
int stat_recursive(FAR const char *path, FAR struct stat *buf);
|
int stat_recursive(FAR const char *path, FAR struct stat *buf, int resolve);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@@ -93,7 +93,7 @@ static inline int statroot(FAR struct stat *buf)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int stat_recursive(FAR const char *path, FAR struct stat *buf)
|
int stat_recursive(FAR const char *path, FAR struct stat *buf, int resolve)
|
||||||
{
|
{
|
||||||
struct inode_search_s desc;
|
struct inode_search_s desc;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
@@ -143,7 +143,7 @@ int stat_recursive(FAR const char *path, FAR struct stat *buf)
|
|||||||
* recurse if soft links are supported in the pseudo file system.
|
* recurse if soft links are supported in the pseudo file system.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = inode_stat(inode, buf);
|
ret = inode_stat(inode, buf, resolve);
|
||||||
}
|
}
|
||||||
|
|
||||||
inode_release(inode);
|
inode_release(inode);
|
||||||
@@ -171,7 +171,7 @@ errout_with_search:
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nx_stat(FAR const char *path, FAR struct stat *buf)
|
int nx_stat(FAR const char *path, FAR struct stat *buf, int resolve)
|
||||||
{
|
{
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ int nx_stat(FAR const char *path, FAR struct stat *buf)
|
|||||||
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
|
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
|
||||||
buf->st_count = 0;
|
buf->st_count = 0;
|
||||||
#endif
|
#endif
|
||||||
return stat_recursive(path, buf);
|
return stat_recursive(path, buf, resolve);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -222,7 +222,21 @@ int stat(FAR const char *path, FAR struct stat *buf)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nx_stat(path, buf);
|
ret = nx_stat(path, buf, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
set_errno(-ret);
|
||||||
|
ret = ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lstat(FAR const char *path, FAR struct stat *buf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nx_stat(path, buf, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
set_errno(-ret);
|
set_errno(-ret);
|
||||||
@@ -243,9 +257,10 @@ int stat(FAR const char *path, FAR struct stat *buf)
|
|||||||
* <sys/stat.h>, into which information is placed concerning the file.
|
* <sys/stat.h>, into which information is placed concerning the file.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* inode - The indoe of interest
|
* inode - The inode of interest
|
||||||
* buf - The caller provide location in which to return information about
|
* buf - The caller provide location in which to return information
|
||||||
* the inode.
|
* about the inode.
|
||||||
|
* resolve - Whether to resolve the symbolic link
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero (OK) returned on success. Otherwise, a negated errno value is
|
* Zero (OK) returned on success. Otherwise, a negated errno value is
|
||||||
@@ -253,7 +268,7 @@ int stat(FAR const char *path, FAR struct stat *buf)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int inode_stat(FAR struct inode *inode, FAR struct stat *buf)
|
int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(inode != NULL && buf != NULL);
|
DEBUGASSERT(inode != NULL && buf != NULL);
|
||||||
|
|
||||||
@@ -321,42 +336,47 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf)
|
|||||||
|
|
||||||
if (INODE_IS_SOFTLINK(inode))
|
if (INODE_IS_SOFTLINK(inode))
|
||||||
{
|
{
|
||||||
int ret;
|
if (resolve)
|
||||||
|
|
||||||
/* Increment the link counter. This is necessary to avoid
|
|
||||||
* infinite recursion if loops are encountered in the traversal.
|
|
||||||
* If we encounter more SYMLOOP_MAX symbolic links at any time
|
|
||||||
* during the traversal, error out.
|
|
||||||
*
|
|
||||||
* NOTE: That inode_search() will automatically skip over
|
|
||||||
* consecutive, intermediate symbolic links. Those numbers will
|
|
||||||
* not be included in the total.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (++buf->st_count > SYMLOOP_MAX)
|
|
||||||
{
|
{
|
||||||
return -ELOOP;
|
int ret;
|
||||||
|
|
||||||
|
/* Increment the link counter. This is necessary to avoid
|
||||||
|
* infinite recursion if loops are encountered in the
|
||||||
|
* traversal. If we encounter more SYMLOOP_MAX symbolic links
|
||||||
|
* at any time during the traversal, error out.
|
||||||
|
*
|
||||||
|
* NOTE: That inode_search() will automatically skip over
|
||||||
|
* consecutive, intermediate symbolic links. Those numbers
|
||||||
|
* will not be included in the total.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (++buf->st_count > SYMLOOP_MAX)
|
||||||
|
{
|
||||||
|
return -ELOOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGASSERT(buf->st_count > 0); /* Check for unsigned integer overflow */
|
||||||
|
|
||||||
|
/* stat() the target of the soft link. */
|
||||||
|
|
||||||
|
ret = stat_recursive(inode->u.i_link, buf, 1);
|
||||||
|
|
||||||
|
/* If stat() fails, then there is a problem with the target of
|
||||||
|
* the symbolic link, but not with the symbolic link itself.
|
||||||
|
* We should still report success, just with less information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
RESET_BUF(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
DEBUGASSERT(buf->st_count > 0); /* Check for unsigned integer overflow */
|
|
||||||
|
|
||||||
/* stat() the target of the soft link. */
|
|
||||||
|
|
||||||
ret = stat_recursive((FAR const char *)inode->u.i_link, buf);
|
|
||||||
|
|
||||||
/* If stat() fails, then there is a problem with the target of the
|
|
||||||
* symbolic link, but not with the symbolic link itself. We should
|
|
||||||
* still report success, just with less information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
{
|
||||||
RESET_BUF(buf);
|
/* Make sure the caller knows that this is a symbolic link. */
|
||||||
|
|
||||||
|
buf->st_mode |= S_IFLNK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the caller knows that this really a symbolic link. */
|
|
||||||
|
|
||||||
buf->st_mode |= S_IFLNK;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
# define _NX_WRITE(f,b,s) nx_write(f,b,s)
|
# define _NX_WRITE(f,b,s) nx_write(f,b,s)
|
||||||
# define _NX_SEEK(f,o,w) nx_seek(f,o,w)
|
# define _NX_SEEK(f,o,w) nx_seek(f,o,w)
|
||||||
# define _NX_IOCTL(f,r,a) nx_ioctl(f,r,a)
|
# define _NX_IOCTL(f,r,a) nx_ioctl(f,r,a)
|
||||||
# define _NX_STAT(p,s) nx_stat(p,s)
|
# define _NX_STAT(p,s) nx_stat(p,s,1)
|
||||||
# define _NX_GETERRNO(r) (-(r))
|
# define _NX_GETERRNO(r) (-(r))
|
||||||
# define _NX_SETERRNO(r) set_errno(-(r))
|
# define _NX_SETERRNO(r) set_errno(-(r))
|
||||||
# define _NX_GETERRVAL(r) (r)
|
# define _NX_GETERRVAL(r) (r)
|
||||||
@@ -1450,7 +1450,7 @@ int file_fstat(FAR struct file *filep, FAR struct stat *buf);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nx_stat(FAR const char *path, FAR struct stat *buf);
|
int nx_stat(FAR const char *path, FAR struct stat *buf, int resolve);
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ extern "C"
|
|||||||
int mkdir(FAR const char *pathname, mode_t mode);
|
int mkdir(FAR const char *pathname, mode_t mode);
|
||||||
int mkfifo(FAR const char *pathname, mode_t mode);
|
int mkfifo(FAR const char *pathname, mode_t mode);
|
||||||
int stat(FAR const char *path, FAR struct stat *buf);
|
int stat(FAR const char *path, FAR struct stat *buf);
|
||||||
|
int lstat(FAR const char *path, FAR struct stat *buf);
|
||||||
int fstat(int fd, FAR struct stat *buf);
|
int fstat(int fd, FAR struct stat *buf);
|
||||||
int chmod(FAR const char *path, mode_t mode);
|
int chmod(FAR const char *path, mode_t mode);
|
||||||
int fchmod(int fd, mode_t mode);
|
int fchmod(int fd, mode_t mode);
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ SYSCALL_LOOKUP(readdir, 1)
|
|||||||
SYSCALL_LOOKUP(rewinddir, 1)
|
SYSCALL_LOOKUP(rewinddir, 1)
|
||||||
SYSCALL_LOOKUP(seekdir, 2)
|
SYSCALL_LOOKUP(seekdir, 2)
|
||||||
SYSCALL_LOOKUP(stat, 2)
|
SYSCALL_LOOKUP(stat, 2)
|
||||||
|
SYSCALL_LOOKUP(lstat, 2)
|
||||||
SYSCALL_LOOKUP(fstat, 2)
|
SYSCALL_LOOKUP(fstat, 2)
|
||||||
SYSCALL_LOOKUP(statfs, 2)
|
SYSCALL_LOOKUP(statfs, 2)
|
||||||
SYSCALL_LOOKUP(fstatfs, 2)
|
SYSCALL_LOOKUP(fstatfs, 2)
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"link","unistd.h","defined(CONFIG_PSEUDOFS_SOFTLINKS)","int","FAR const char *","FAR const char *"
|
"link","unistd.h","defined(CONFIG_PSEUDOFS_SOFTLINKS)","int","FAR const char *","FAR const char *"
|
||||||
"listen","sys/socket.h","defined(CONFIG_NET)","int","int","int"
|
"listen","sys/socket.h","defined(CONFIG_NET)","int","int","int"
|
||||||
"lseek","unistd.h","","off_t","int","off_t","int"
|
"lseek","unistd.h","","off_t","int","off_t","int"
|
||||||
|
"lstat","sys/stat.h","","int","FAR const char *","FAR struct stat *"
|
||||||
"mkdir","sys/stat.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *","mode_t"
|
"mkdir","sys/stat.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *","mode_t"
|
||||||
"mmap","sys/mman.h","","FAR void *","FAR void *","size_t","int","int","int","off_t"
|
"mmap","sys/mman.h","","FAR void *","FAR void *","size_t","int","int","int","off_t"
|
||||||
"modhandle","nuttx/module.h","defined(CONFIG_MODULE)","FAR void *","FAR const char *"
|
"modhandle","nuttx/module.h","defined(CONFIG_MODULE)","FAR void *","FAR const char *"
|
||||||
|
|||||||
|
Reference in New Issue
Block a user