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:
parent
b938348cdb
commit
b598ab43d7
@ -248,9 +248,10 @@ int inode_find(FAR struct inode_search_s *desc);
|
||||
* <sys/stat.h>, into which information is placed concerning the file.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - The indoe of interest
|
||||
* buf - The caller provide location in which to return information about
|
||||
* the inode.
|
||||
* inode - The inode of interest
|
||||
* buf - The caller provide location in which to return information
|
||||
* about the inode.
|
||||
* resolve - Whether to resolve the symbolic link
|
||||
*
|
||||
* Returned Value:
|
||||
* 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 */
|
||||
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
|
||||
|
@ -104,7 +104,7 @@ static int automount_interrupt(FAR const struct automount_lower_s *lower,
|
||||
*
|
||||
* Returned Value:
|
||||
* 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
|
||||
*
|
||||
****************************************************************************/
|
||||
|
@ -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. */
|
||||
|
||||
ret = inode_stat(inode, buf);
|
||||
ret = inode_stat(inode, buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
104
fs/vfs/fs_stat.c
104
fs/vfs/fs_stat.c
@ -58,7 +58,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);
|
||||
|
||||
/****************************************************************************
|
||||
* 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;
|
||||
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.
|
||||
*/
|
||||
|
||||
ret = inode_stat(inode, buf);
|
||||
ret = inode_stat(inode, buf, resolve);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
@ -199,7 +199,7 @@ int nx_stat(FAR const char *path, FAR struct stat *buf)
|
||||
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
|
||||
buf->st_count = 0;
|
||||
#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;
|
||||
|
||||
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)
|
||||
{
|
||||
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.
|
||||
*
|
||||
* Input Parameters:
|
||||
* inode - The indoe of interest
|
||||
* buf - The caller provide location in which to return information about
|
||||
* the inode.
|
||||
* inode - The inode of interest
|
||||
* buf - The caller provide location in which to return information
|
||||
* about the inode.
|
||||
* resolve - Whether to resolve the symbolic link
|
||||
*
|
||||
* Returned Value:
|
||||
* 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);
|
||||
|
||||
@ -321,42 +336,47 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf)
|
||||
|
||||
if (INODE_IS_SOFTLINK(inode))
|
||||
{
|
||||
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)
|
||||
if (resolve)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
else
|
||||
{
|
||||
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
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@
|
||||
# define _NX_WRITE(f,b,s) nx_write(f,b,s)
|
||||
# define _NX_SEEK(f,o,w) nx_seek(f,o,w)
|
||||
# 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_SETERRNO(r) set_errno(-(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
|
||||
#if defined(__cplusplus)
|
||||
|
@ -156,6 +156,7 @@ extern "C"
|
||||
int mkdir(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 lstat(FAR const char *path, FAR struct stat *buf);
|
||||
int fstat(int fd, FAR struct stat *buf);
|
||||
int chmod(FAR const char *path, mode_t mode);
|
||||
int fchmod(int fd, mode_t mode);
|
||||
|
@ -235,6 +235,7 @@ SYSCALL_LOOKUP(readdir, 1)
|
||||
SYSCALL_LOOKUP(rewinddir, 1)
|
||||
SYSCALL_LOOKUP(seekdir, 2)
|
||||
SYSCALL_LOOKUP(stat, 2)
|
||||
SYSCALL_LOOKUP(lstat, 2)
|
||||
SYSCALL_LOOKUP(fstat, 2)
|
||||
SYSCALL_LOOKUP(statfs, 2)
|
||||
SYSCALL_LOOKUP(fstatfs, 2)
|
||||
|
@ -45,6 +45,7 @@
|
||||
"link","unistd.h","defined(CONFIG_PSEUDOFS_SOFTLINKS)","int","FAR const char *","FAR const char *"
|
||||
"listen","sys/socket.h","defined(CONFIG_NET)","int","int","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"
|
||||
"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 *"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
Loading…
Reference in New Issue
Block a user