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:
Xiang Xiao 2020-06-22 16:44:32 +08:00 committed by patacongo
parent b938348cdb
commit b598ab43d7
8 changed files with 74 additions and 50 deletions

View File

@ -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

View File

@ -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
*
****************************************************************************/

View File

@ -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);
}
}

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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.