Merge branch 'fstat'

This commit is contained in:
Gregory Nutt
2017-02-13 12:58:56 -06:00
21 changed files with 1330 additions and 481 deletions
+35 -9
View File
@@ -1369,19 +1369,45 @@ o File system / Generic drivers (fs/, drivers/)
NOTE: The NXFFS file system has its own TODO list at nuttx/fs/nxffs/README.txt
Title: CHMOD(), TRUNCATE(), AND FSTAT()
Description: Implement chmod(), truncate(), and fstat().
Title: MISSING FILE SYSTEM FEATURES
Description: Implement missing file system features:
chmod() is probably not relevant since file modes are not
currently supported.
fstat() may be doable: Most file system implement stat() by
looking up the directory entry associated with the path
then generating the struct stat data. But most file
systems also keep the directory entry in the private data
associated withe open file. So it should possible to
implement fstat() as a file system method and use that
saved directory entry to generate the stat data.
File privileges would also be good to support. But this is
really a small part of a much larger feature. NuttX has no
user IDs, there are no groups, there are no privileges
associated with either. User's don't need credentials.
This is really a system wide issues of which chmod is only
a small part.
User privileges never seemed important to me since NuttX is
intended for deeply embedded environments where there are
not multiple users with varying levels of trust.
truncate - The standard way of setting a fixed file size.
Often used with random access, data base files. There is no
simple way of doing that now (other than just writing data
to the file).
fstat(): Currently in work. The unverified solution is on
the 'fstat' branch in the repository.
link, unlink, softlink, readlink - For symbolic links. Only
the ROMFS file system currently supports hard and soft links,
so this is not too important.
File locking
Special files - NuttX support special files only in the top-
level pseudo file system. Unix systems support many
different special files via mknod(). This would be
important only if it is an objective of NuttX to become a
true Unix OS. Again only supported by ROMFS.
True inodes - Standard Unix inodes. Currently only supported
by ROMFs.
The primary obstacle to all these is that each would require
changes to all existing file systems. That number is pretty
+25 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/binfs/fs_binfs.c
*
* Copyright (C) 2011-2013, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2013, 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,7 @@ static ssize_t binfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static int binfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int binfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int binfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
static int binfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
@@ -108,6 +109,7 @@ const struct mountpt_operations binfs_operations =
NULL, /* sync */
binfs_dup, /* dup */
binfs_fstat, /* fstat */
binfs_opendir, /* opendir */
NULL, /* closedir */
@@ -245,6 +247,28 @@ static int binfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return OK;
}
/****************************************************************************
* Name: binfs_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 binfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
DEBUGASSERT(filep != NULL && buf != NULL);
/* It's a execute-only file system */
buf->st_mode = S_IFREG | S_IXOTH | S_IXGRP | S_IXUSR;
buf->st_size = 0;
buf->st_blksize = 0;
buf->st_blocks = 0;
return OK;
}
/****************************************************************************
* Name: binfs_opendir
*
+206 -65
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fat/fs_fat32.c
*
* Copyright (C) 2007-2009, 2011-2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
@@ -84,6 +84,8 @@ static int fat_ioctl(FAR struct file *filep, int cmd,
static int fat_sync(FAR struct file *filep);
static int fat_dup(FAR const struct file *oldp, FAR struct file *newp);
static int fat_fstat(FAR const struct file *filep,
FAR struct stat *buf);
static int fat_opendir(FAR struct inode *mountpt,
FAR const char *relpath, FAR struct fs_dirent_s *dir);
@@ -106,6 +108,12 @@ static int fat_mkdir(FAR struct inode *mountpt, FAR const char *relpath,
static int fat_rmdir(FAR struct inode *mountpt, FAR const char *relpath);
static int fat_rename(FAR struct inode *mountpt,
FAR const char *oldrelpath, FAR const char *newrelpath);
static int fat_stat_common(FAR struct fat_mountpt_s *fs,
FAR uint8_t *direntry, FAR struct stat *buf);
static int fat_stat_file(FAR struct fat_mountpt_s *fs,
FAR uint8_t *direntry, FAR struct stat *buf);
static int fat_stat_root(FAR struct fat_mountpt_s *fs,
FAR uint8_t *direntry, FAR struct stat *buf);
static int fat_stat(struct inode *mountpt, const char *relpath,
FAR struct stat *buf);
@@ -129,6 +137,7 @@ const struct mountpt_operations fat_operations =
fat_sync, /* sync */
fat_dup, /* dup */
fat_fstat, /* fstat */
fat_opendir, /* opendir */
NULL, /* closedir */
@@ -1606,6 +1615,76 @@ errout_with_semaphore:
return ret;
}
/****************************************************************************
* Name: fat_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 fat_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct inode *inode;
FAR struct fat_mountpt_s *fs;
FAR struct fat_file_s *ff;
uint8_t *direntry;
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);
/* Check if the mount is still healthy */
fat_semtake(fs);
ret = fat_checkmount(fs);
if (ret != OK)
{
goto errout_with_semaphore;
}
/* Recover our private data from the struct file instance */
ff = filep->f_priv;
/* Update the directory entry. First read the directory
* entry into the fs_buffer (preserving the ff_buffer)
*/
ret = fat_fscacheread(fs, ff->ff_dirsector);
if (ret < 0)
{
goto errout_with_semaphore;
}
/* Recover a pointer to the specific directory entry in the sector using
* the saved directory index.
*/
direntry = &fs->fs_buffer[(ff->ff_dirindex & DIRSEC_NDXMASK(fs)) * DIR_SIZE];
/* Call fat_stat_file() to create the buf and to save information to
* it.
*/
ret = fat_stat_file(fs, direntry, buf);
errout_with_semaphore:
fat_semgive(fs);
return ret;
}
/****************************************************************************
* Name: fat_readdir
*
@@ -2487,6 +2566,123 @@ errout_with_semaphore:
return ret;
}
/****************************************************************************
* Name: fat_stat_common
*
* Description:
* Common logic used by fat_stat_file() and fat_fstat_root().
*
****************************************************************************/
static int fat_stat_common(FAR struct fat_mountpt_s *fs,
FAR uint8_t *direntry, FAR struct stat *buf)
{
uint16_t fatdate;
uint16_t date2;
uint16_t fattime;
/* Times */
fatdate = DIR_GETWRTDATE(direntry);
fattime = DIR_GETWRTTIME(direntry);
buf->st_mtime = fat_fattime2systime(fattime, fatdate);
date2 = DIR_GETLASTACCDATE(direntry);
if (fatdate == date2)
{
buf->st_atime = buf->st_mtime;
}
else
{
buf->st_atime = fat_fattime2systime(0, date2);
}
fatdate = DIR_GETCRDATE(direntry);
fattime = DIR_GETCRTIME(direntry);
buf->st_ctime = fat_fattime2systime(fattime, fatdate);
/* File/directory size, access block size */
buf->st_size = DIR_GETFILESIZE(direntry);
buf->st_blksize = fs->fs_fatsecperclus * fs->fs_hwsectorsize;
buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
return OK;
}
/****************************************************************************
* Name: fat_stat_file
*
* Description:
* Function to return the status associated with a file in the FAT file
* system. Used by fat_stat() and fat_fstat().
*
****************************************************************************/
static int fat_stat_file(FAR struct fat_mountpt_s *fs,
FAR uint8_t *direntry, FAR struct stat *buf)
{
uint8_t attribute;
/* Initialize the "struct stat" */
memset(buf, 0, sizeof(struct stat));
/* Get attribute from direntry */
attribute = DIR_GETATTRIBUTES(direntry);
if ((attribute & FATATTR_VOLUMEID) != 0)
{
return -ENOENT;
}
/* Set the access permissions. The file/directory is always readable
* by everyone but may be writeable by no-one.
*/
buf->st_mode = S_IROTH | S_IRGRP | S_IRUSR;
if ((attribute & FATATTR_READONLY) == 0)
{
buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR;
}
/* We will report only types file or directory */
if ((attribute & FATATTR_DIRECTORY) != 0)
{
buf->st_mode |= S_IFDIR;
}
else
{
buf->st_mode |= S_IFREG;
}
return fat_stat_common(fs, direntry, buf);
}
/****************************************************************************
* Name: fat_stat_root
*
* Description:
* Logic to stat the root directory. Used by fat_stat().
*
****************************************************************************/
static int fat_stat_root(FAR struct fat_mountpt_s *fs,
FAR uint8_t *direntry, FAR struct stat *buf)
{
/* Clear the "struct stat" */
memset(buf, 0, sizeof(struct stat));
/* It's directory name of the mount point */
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR | S_IWOTH |
S_IWGRP | S_IWUSR;
return fat_stat_common(fs, direntry, buf);
}
/****************************************************************************
* Name: fat_stat
*
@@ -2499,11 +2695,7 @@ static int fat_stat(FAR struct inode *mountpt, FAR const char *relpath,
{
FAR struct fat_mountpt_s *fs;
struct fat_dirinfo_s dirinfo;
uint16_t fatdate;
uint16_t date2;
uint16_t fattime;
FAR uint8_t *direntry;
uint8_t attribute;
int ret;
/* Sanity checks */
@@ -2534,76 +2726,25 @@ static int fat_stat(FAR struct inode *mountpt, FAR const char *relpath,
goto errout_with_semaphore;
}
memset(buf, 0, sizeof(struct stat));
if (dirinfo.fd_root)
{
/* It's directory name of the mount point */
/* Get a pointer to the directory entry */
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR | S_IWOTH |
S_IWGRP | S_IWUSR;
ret = OK;
goto errout_with_semaphore;
}
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
/* Get the FAT attribute and map it so some meaningful mode_t values */
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
attribute = DIR_GETATTRIBUTES(direntry);
if ((attribute & FATATTR_VOLUMEID) != 0)
if (dirinfo.fd_root)
{
ret = -ENOENT;
goto errout_with_semaphore;
}
/* Set the access permissions. The file/directory is always readable
* by everyone but may be writeable by no-one.
*/
buf->st_mode = S_IROTH | S_IRGRP | S_IRUSR;
if ((attribute & FATATTR_READONLY) == 0)
{
buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR;
}
/* We will report only types file or directory */
if ((attribute & FATATTR_DIRECTORY) != 0)
{
buf->st_mode |= S_IFDIR;
ret = fat_stat_root(fs, direntry, buf);
}
else
{
buf->st_mode |= S_IFREG;
/* Call fat_stat_file() to create the buf and to save information to
* the stat buffer.
*/
ret = fat_stat_file(fs, direntry, buf);
}
/* File/directory size, access block size */
buf->st_size = DIR_GETFILESIZE(direntry);
buf->st_blksize = fs->fs_fatsecperclus * fs->fs_hwsectorsize;
buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
/* Times */
fatdate = DIR_GETWRTDATE(direntry);
fattime = DIR_GETWRTTIME(direntry);
buf->st_mtime = fat_fattime2systime(fattime, fatdate);
date2 = DIR_GETLASTACCDATE(direntry);
if (fatdate == date2)
{
buf->st_atime = buf->st_mtime;
}
else
{
buf->st_atime = fat_fattime2systime(0, date2);
}
fatdate = DIR_GETCRDATE(direntry);
fattime = DIR_GETCRTIME(direntry);
buf->st_ctime = fat_fattime2systime(fattime, fatdate);
ret = OK;
errout_with_semaphore:
fat_semgive(fs);
return ret;
+18
View File
@@ -80,6 +80,8 @@ static int hostfs_ioctl(FAR struct file *filep, int cmd,
static int hostfs_sync(FAR struct file *filep);
static int hostfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int hostfs_fstat(FAR const struct file *filep,
FAR struct stat *buf);
static int hostfs_opendir(FAR struct inode *mountpt,
FAR const char *relpath,
@@ -136,6 +138,7 @@ const struct mountpt_operations hostfs_operations =
hostfs_sync, /* sync */
hostfs_dup, /* dup */
hostfs_fstat, /* fstat */
hostfs_opendir, /* opendir */
hostfs_closedir, /* closedir */
@@ -644,6 +647,21 @@ static int hostfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return OK;
}
/****************************************************************************
* Name: hostfs_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 hostfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
#warning Missing logic
return -ENOSYS;
}
/****************************************************************************
* Name: hostfs_opendir
*
+23
View File
@@ -240,6 +240,29 @@ int inode_search(FAR struct inode_search_s *desc);
int inode_find(FAR struct inode_search_s *desc);
/****************************************************************************
* Name: inode_stat
*
* Description:
* The inode_stat() function will obtain information about an 'inode' in
* the pseudo file system and will write it to the area pointed to by 'buf'.
*
* The 'buf' argument is a pointer to a stat structure, as defined in
* <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.
*
* Returned Value:
* Zero (OK) returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int inode_stat(FAR struct inode *inode, FAR struct stat *buf);
/****************************************************************************
* Name: inode_free
*
+5 -4
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_node.h
*
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012-2013, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -74,10 +74,11 @@ struct nfsnode
uint8_t n_type; /* File type */
uint8_t n_fhsize; /* Size in bytes of the file handle */
uint8_t n_flags; /* Node flags */
struct timespec n_mtime; /* File modification time (see NOTE) */
time_t n_ctime; /* File creation time (see NOTE) */
uint16_t n_mode; /* File mode for fstat() */
struct timespec n_mtime; /* File modification time */
time_t n_ctime; /* File creation time */
nfsfh_t n_fhandle; /* NFS File Handle */
uint64_t n_size; /* Current size of file (see NOTE) */
uint64_t n_size; /* Current size of file */
};
#endif /* __FS_NFS_NFS_NODE_H */
+11 -5
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_util.c
*
* Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2012-2013, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
#include <queue.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
@@ -577,10 +578,15 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath,
void nfs_attrupdate(FAR struct nfsnode *np, FAR struct nfs_fattr *attributes)
{
/* Save a few of the files attribute values in file structur (host order) */
struct timespec ts;
np->n_type = fxdr_unsigned(uint32_t, attributes->fa_type);
/* Save a few of the files attribute values in file structure (host order) */
np->n_type = fxdr_unsigned(uint8_t, attributes->fa_type);
np->n_mode = fxdr_unsigned(uint16_t, attributes->fa_mode);
np->n_size = fxdr_hyper(&attributes->fa_size);
fxdr_nfsv3time(&attributes->fa_mtime, &np->n_mtime)
np->n_ctime = fxdr_hyper(&attributes->fa_ctime);
fxdr_nfsv3time(&attributes->fa_mtime, &np->n_mtime);
fxdr_nfsv3time(&attributes->fa_ctime, &ts);
np->n_ctime = ts.tv_sec;
}
+197 -68
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nfs/nfs_vfsops.c
*
* Copyright (C) 2012-2013, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2012-2013, 2015, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
* Gregory Nutt <gnutt@nuttx.org>
@@ -47,10 +47,10 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/statfs.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
@@ -103,6 +103,22 @@
# error "Length of cookie verify in fs_dirent_s is incorrect"
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/* Use to pass file information to nfs_stat_common() */
struct nfs_statinfo_s
{
uint16_t ns_mode; /* File access mode */
uint8_t ns_type; /* File type */
uint64_t ns_size; /* File size */
time_t ns_atime; /* Time of last access */
time_t ns_mtime; /* Time of last modification */
time_t ns_ctime; /* Time of last status change */
};
/****************************************************************************
* Public Data
****************************************************************************/
@@ -131,6 +147,7 @@ static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static ssize_t nfs_write(FAR struct file *filep, const char *buffer,
size_t buflen);
static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
static int nfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
static int nfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
@@ -142,15 +159,20 @@ static int nfs_bind(FAR struct inode *blkdriver, const void *data,
void **handle);
static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
unsigned int flags);
static int nfs_statfs(struct inode *mountpt, struct statfs *buf);
static int nfs_remove(struct inode *mountpt, const char *relpath);
static int nfs_mkdir(struct inode *mountpt, const char *relpath,
mode_t mode);
static int nfs_rmdir(struct inode *mountpt, const char *relpath);
static int nfs_rename(struct inode *mountpt, const char *oldrelpath,
const char *newrelpath);
static int nfs_stat(struct inode *mountpt, const char *relpath,
struct stat *buf);
static int nfs_statfs(FAR struct inode *mountpt,
FAR struct statfs *buf);
static int nfs_remove(FAR struct inode *mountpt,
FAR const char *relpath);
static int nfs_mkdir(FAR struct inode *mountpt,
FAR const char *relpath, mode_t mode);
static int nfs_rmdir(FAR struct inode *mountpt,
FAR const char *relpath);
static int nfs_rename(FAR struct inode *mountpt,
FAR const char *oldrelpath, FAR const char *newrelpath);
static void nfs_stat_common(FAR struct nfs_statinfo_s *info,
FAR struct stat *buf);
static int nfs_stat(struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
/****************************************************************************
* Public Data
@@ -168,6 +190,7 @@ const struct mountpt_operations nfs_operations =
NULL, /* sync */
nfs_dup, /* dup */
nfs_fstat, /* fstat */
nfs_opendir, /* opendir */
NULL, /* closedir */
@@ -1114,7 +1137,7 @@ errout_with_semaphore:
}
/****************************************************************************
* Name: binfs_dup
* Name: nfs_dup
*
* Description:
* Duplicate open file data in the new file structure.
@@ -1173,6 +1196,80 @@ static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return OK;
}
/****************************************************************************
* Name: nfs_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 nfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct nfsmount *nmp;
FAR struct nfsnode *np;
struct nfs_statinfo_s info;
struct timespec ts;
int error;
int ret;
finfo("Buf %p\n", buf);
DEBUGASSERT(filep != NULL && buf != NULL);
/* Recover our private data from the struct file instance */
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
np = (FAR struct nfsnode *)filep->f_priv;
nmp = (FAR struct nfsmount *)filep->f_inode->i_private;
DEBUGASSERT(nmp != NULL);
/* Make sure that the mount is still healthy */
nfs_semtake(nmp);
error = nfs_checkmount(nmp);
if (error != OK)
{
ferr("ERROR: nfs_checkmount failed: %d\n", error);
goto errout_with_semaphore;
}
/* Extract the file mode, file type, and file size from the nfsnode
* structure.
*/
info.ns_mode = np->n_mode;
info.ns_type = np->n_type;
info.ns_size = (off_t)np->n_size;
/* Extract time values as type time_t in units of seconds. */
info.ns_mtime = np->n_mtime.tv_sec;
info.ns_ctime = np->n_ctime;
/* Use the current time for the time of last access. */
ret = clock_gettime(CLOCK_REALTIME, &ts);
if (ret < 0)
{
error = -get_errno();
ferr("ERROR: clock_gettime failed: %d\n", error);
goto errout_with_semaphore;
}
info.ns_atime = ts.tv_sec;
/* Then update the stat buffer with this information */
nfs_stat_common(&info, buf);
ret = OK;
errout_with_semaphore:
nfs_semgive(nmp);
return -error;
}
/****************************************************************************
* Name: nfs_opendir
*
@@ -2503,84 +2600,45 @@ errout_with_semaphore:
}
/****************************************************************************
* Name: nfs_stat
* Name: nfs_stat_common
*
* Description:
* Return information about the file system object at 'relpath'
* Return information about the file system object described by 'info'
*
* Returned Value:
* 0 on success; a negated errno value on failure.
* None
*
****************************************************************************/
static int nfs_stat(struct inode *mountpt, const char *relpath,
struct stat *buf)
static void nfs_stat_common(FAR struct nfs_statinfo_s *info,
FAR struct stat *buf)
{
struct nfsmount *nmp;
struct file_handle fhandle;
struct nfs_fattr obj_attributes;
uint32_t tmp;
uint32_t mode;
int error;
/* Sanity checks */
DEBUGASSERT(mountpt && mountpt->i_private);
/* Get the mountpoint private data from the inode structure */
nmp = (FAR struct nfsmount *)mountpt->i_private;
DEBUGASSERT(nmp && buf);
/* Check if the mount is still healthy */
nfs_semtake(nmp);
error = nfs_checkmount(nmp);
if (error != OK)
{
ferr("ERROR: nfs_checkmount failed: %d\n", error);
goto errout_with_semaphore;
}
/* Get the file handle attributes of the requested node */
error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL);
if (error != OK)
{
ferr("ERROR: nfs_findnode failed: %d\n", error);
goto errout_with_semaphore;
}
/* Construct the file mode. This is a 32-bit, encoded value containing
* both the access mode and the file type.
*/
tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_mode);
mode_t mode;
/* Here we exploit the fact that most mode bits are the same in NuttX
* as in the NFSv3 spec.
*/
mode = tmp & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
mode = info->ns_mode &
(NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
/* Handle the cases that are not the same */
if ((mode & NFSMODE_ISGID) != 0)
if ((info->ns_mode & NFSMODE_ISGID) != 0)
{
mode |= S_ISGID;
}
if ((mode & NFSMODE_ISUID) != 0)
if ((info->ns_mode & NFSMODE_ISUID) != 0)
{
mode |= S_ISUID;
}
/* Now OR in the file type */
tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type);
switch (tmp)
switch (info->ns_mode)
{
default:
case NFNON: /* Unknown type */
@@ -2616,12 +2674,83 @@ static int nfs_stat(struct inode *mountpt, const char *relpath,
}
buf->st_mode = mode;
buf->st_size = fxdr_hyper(&obj_attributes.fa_size);
buf->st_size = (off_t)info->ns_size;
buf->st_blksize = 0;
buf->st_blocks = 0;
buf->st_mtime = fxdr_hyper(&obj_attributes.fa_mtime);
buf->st_atime = fxdr_hyper(&obj_attributes.fa_atime);
buf->st_ctime = fxdr_hyper(&obj_attributes.fa_ctime);
buf->st_mtime = info->ns_mtime;
buf->st_atime = info->ns_atime;
buf->st_ctime = info->ns_ctime;
}
/****************************************************************************
* Name: nfs_stat
*
* Description:
* Return information about the file system object at 'relpath'
*
* Returned Value:
* 0 on success; a negated errno value on failure.
*
****************************************************************************/
static int nfs_stat(struct inode *mountpt, const char *relpath,
struct stat *buf)
{
struct nfsmount *nmp;
struct file_handle fhandle;
struct nfs_fattr obj_attributes;
struct nfs_statinfo_s info;
struct timespec ts;
int error;
/* Sanity checks */
DEBUGASSERT(mountpt && mountpt->i_private);
/* Get the mountpoint private data from the inode structure */
nmp = (FAR struct nfsmount *)mountpt->i_private;
DEBUGASSERT(nmp && buf);
/* Check if the mount is still healthy */
nfs_semtake(nmp);
error = nfs_checkmount(nmp);
if (error != OK)
{
ferr("ERROR: nfs_checkmount failed: %d\n", error);
goto errout_with_semaphore;
}
/* Get the file handle attributes of the requested node */
error = nfs_findnode(nmp, relpath, &fhandle, &obj_attributes, NULL);
if (error != OK)
{
ferr("ERROR: nfs_findnode failed: %d\n", error);
goto errout_with_semaphore;
}
/* Extract the file mode, file type, and file size. */
info.ns_mode = fxdr_unsigned(uint16_t, obj_attributes.fa_mode);
info.ns_type = fxdr_unsigned(uint8_t, obj_attributes.fa_type);
info.ns_size = fxdr_hyper(&obj_attributes.fa_size);
/* Extract time values as type time_t in units of seconds */
fxdr_nfsv3time(&obj_attributes.fa_mtime, &ts);
info.ns_mtime = ts.tv_sec;
fxdr_nfsv3time(&obj_attributes.fa_atime, &ts);
info.ns_atime = ts.tv_sec;
fxdr_nfsv3time(&obj_attributes.fa_ctime, &ts);
info.ns_ctime = ts.tv_sec;
/* Then update the stat buffer with this information */
nfs_stat_common(&info, buf);
errout_with_semaphore:
nfs_semgive(nmp);
+2 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs.h
*
* Copyright (C) 2011, 2013, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2011, 2013, 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -1092,6 +1092,7 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
int nxffs_dup(FAR const struct file *oldp, FAR struct file *newp);
int nxffs_fstat(FAR const struct file *filep, FAR struct stat *buf);
int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct fs_dirent_s *dir);
int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir);
+2 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs_initialize.c
*
* Copyright (C) 2011, 2013, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2011, 2013, 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -73,6 +73,7 @@ const struct mountpt_operations nxffs_operations =
NULL, /* sync -- No buffered data */
nxffs_dup, /* dup */
nxffs_fstat, /* fstat */
nxffs_opendir, /* opendir */
NULL, /* closedir */
+59 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/nxffs/nxffs_stat.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -47,6 +47,7 @@
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/fs/fs.h>
@@ -149,6 +150,8 @@ int nxffs_stat(FAR struct inode *mountpt, FAR const char *relpath,
goto errout_with_semaphore;
}
/* Return status information based on the directory entry */
buf->st_blocks = entry.datlen / (volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR);
buf->st_mode = S_IFREG | S_IXOTH | S_IXGRP | S_IXUSR;
buf->st_size = entry.datlen;
@@ -175,3 +178,58 @@ errout_with_semaphore:
errout:
return ret;
}
/****************************************************************************
* Name: nxffs_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'.
*
****************************************************************************/
int nxffs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct nxffs_volume_s *volume;
FAR struct nxffs_ofile_s *ofile;
int ret;
finfo("Buf %s\n", buf);
DEBUGASSERT(filep != NULL && buf != NULL);
/* Recover the open file state from the struct file instance */
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
ofile = (FAR struct nxffs_ofile_s *)filep->f_priv;
/* Recover the volume state from the open file */
volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private;
DEBUGASSERT(volume != NULL);
/* Get exclusive access to the volume. Note that the volume exclsem
* protects the open file list.
*/
ret = sem_wait(&volume->exclsem);
if (ret != OK)
{
int errcode = get_errno();
ferr("ERROR: sem_wait failed: %d\n", errcode);
return -errcode;
}
/* Return status information based on the directory entry */
buf->st_blocks = ofile->entry.datlen /
(volume->geo.blocksize - SIZEOF_NXFFS_BLOCK_HDR);
buf->st_mode = S_IFREG | S_IXOTH | S_IXGRP | S_IXUSR;
buf->st_size = ofile->entry.datlen;
buf->st_atime = ofile->entry.utc;
buf->st_mtime = ofile->entry.utc;
buf->st_ctime = ofile->entry.utc;
sem_post(&volume->exclsem);
return OK;
}
+19 -1
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/procfs/fs_procfs.c
*
* Copyright (C) 2013-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2013-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -183,6 +183,8 @@ static int procfs_ioctl(FAR struct file *filep, int cmd,
static int procfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int procfs_fstat(FAR const struct file *filep,
FAR struct stat *buf);
static int procfs_opendir(FAR struct inode *mountpt, const char *relpath,
FAR struct fs_dirent_s *dir);
@@ -235,6 +237,7 @@ const struct mountpt_operations procfs_operations =
NULL, /* sync */
procfs_dup, /* dup */
procfs_fstat, /* fstat */
procfs_opendir, /* opendir */
procfs_closedir, /* closedir */
@@ -460,6 +463,21 @@ static int procfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return oldattr->procfsentry->ops->dup(oldp, newp);
}
/****************************************************************************
* Name: procfs_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 procfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
#warning Missing logic
return -ENOSYS;
}
/****************************************************************************
* Name: procfs_opendir
*
+124 -39
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* rm/romfs/fs_romfs.h
*
* Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2008-2009, 2011, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References: Linux/Documentation/filesystems/romfs.txt
@@ -76,7 +76,10 @@ static off_t romfs_seek(FAR struct file *filep, off_t offset, int whence);
static int romfs_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
static int romfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int romfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int romfs_fstat(FAR const struct file *filep,
FAR struct stat *buf);
static int romfs_opendir(FAR struct inode *mountpt,
FAR const char *relpath,
@@ -93,6 +96,8 @@ static int romfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
static int romfs_statfs(FAR struct inode *mountpt,
FAR struct statfs *buf);
static int romfs_stat_common(uint8_t type, uint32_t size,
uint16_t sectorsize, FAR struct stat *buf);
static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
@@ -116,6 +121,7 @@ const struct mountpt_operations romfs_operations =
NULL, /* sync */
romfs_dup, /* dup */
romfs_fstat, /* fstat */
romfs_opendir, /* opendir */
NULL, /* closedir */
@@ -199,7 +205,11 @@ static int romfs_open(FAR struct file *filep, FAR const char *relpath,
}
/* The full path exists -- but is the final component a file
* or a directory?
* or a directory? Or some other Unix file type that is not
* appropriate in this contex.
*
* REVISIT: This logic should follow hard/soft link file
* types. At present, it returns the ENXIO.
*/
if (IS_DIRECTORY(dirinfo.rd_next))
@@ -210,6 +220,20 @@ static int romfs_open(FAR struct file *filep, FAR const char *relpath,
ferr("ERROR: '%s' is a directory\n", relpath);
goto errout_with_semaphore;
}
else if (!IS_FILE(dirinfo.rd_next))
{
/* ENXIO indicates "The named file is a character special or
* block special file, and the device associated with this
* special file does not exist."
*
* Here we also return ENXIO if the file is not a directory
* or a regular file.
*/
ret = -ENXIO;
ferr("ERROR: '%s' is a special file\n", relpath);
goto errout_with_semaphore;
}
#ifdef CONFIG_FILE_MODE
# warning "Missing check for privileges based on inode->i_mode"
@@ -676,6 +700,51 @@ errout_with_semaphore:
return ret;
}
/****************************************************************************
* Name: romfs_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 romfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct romfs_mountpt_s *rm;
FAR struct romfs_file_s *rf;
int ret;
finfo("fstat\n");
/* Sanity checks */
DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL);
/* Get mountpoint private data from the inode reference from the file
* structure
*/
rf = filep->f_priv;
rm = (FAR struct romfs_mountpt_s *)filep->f_inode->i_private;
DEBUGASSERT(rm != NULL);
/* Check if the mount is still healthy */
romfs_semtake(rm);
ret = romfs_checkmount(rm);
if (ret >= 0)
{
/* Return information about the directory entry */
ret = romfs_stat_common(RFNEXT_FILE, rf->rf_size,
rm->rm_hwsectorsize, buf);
}
romfs_semgive(rm);
return ret;
}
/****************************************************************************
* Name: romfs_opendir
*
@@ -1100,6 +1169,54 @@ errout_with_semaphore:
return ret;
}
/****************************************************************************
* Name: romfs_stat_common
*
* Description:
* Return information about a file or directory
*
****************************************************************************/
static int romfs_stat_common(uint8_t type, uint32_t size,
uint16_t sectorsize, FAR struct stat *buf)
{
memset(buf, 0, sizeof(struct stat));
if (IS_DIRECTORY(type))
{
/* It's a read-only directory name */
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
if (IS_EXECUTABLE(type))
{
buf->st_mode |= S_IXOTH | S_IXGRP | S_IXUSR;
}
}
else if (IS_FILE(type))
{
/* It's a read-only file name */
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
if (IS_EXECUTABLE(type))
{
buf->st_mode |= S_IXOTH | S_IXGRP | S_IXUSR;
}
}
else
{
/* Otherwise, pretend like the unsupported type does not exist */
finfo("Unsupported type: %d\n", type);
return -ENOENT;
}
/* File/directory size, access block size */
buf->st_size = size;
buf->st_blksize = sectorsize;
buf->st_blocks = (buf->st_size + sectorsize - 1) / sectorsize;
return OK;
}
/****************************************************************************
* Name: romfs_stat
*
@@ -1112,6 +1229,7 @@ static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
{
FAR struct romfs_mountpt_s *rm;
FAR struct romfs_dirinfo_s dirinfo;
uint8_t type;
int ret;
finfo("Entry\n");
@@ -1146,43 +1264,10 @@ static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
goto errout_with_semaphore;
}
memset(buf, 0, sizeof(struct stat));
if (IS_DIRECTORY(dirinfo.rd_next))
{
/* It's a read-only directory name */
/* Return information about the directory entry */
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
if (IS_EXECUTABLE(dirinfo.rd_next))
{
buf->st_mode |= S_IXOTH | S_IXGRP | S_IXUSR;
}
}
else if (IS_FILE(dirinfo.rd_next))
{
/* It's a read-only file name */
buf->st_mode = S_IFREG | S_IROTH | S_IRGRP | S_IRUSR;
if (IS_EXECUTABLE(dirinfo.rd_next))
{
buf->st_mode |= S_IXOTH | S_IXGRP | S_IXUSR;
}
}
else
{
/* Otherwise, pretend like the unsupported node does not exist */
finfo("Unsupported inode: %d\n", dirinfo.rd_next);
ret = -ENOENT;
goto errout_with_semaphore;
}
/* File/directory size, access block size */
buf->st_size = dirinfo.rd_size;
buf->st_blksize = rm->rm_hwsectorsize;
buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
ret = OK;
type = (uint8_t)(dirinfo.rd_next & RFNEXT_ALLMODEMASK);
ret = romfs_stat_common(type, dirinfo.rd_size, rm->rm_hwsectorsize, buf);
errout_with_semaphore:
romfs_semgive(rm);
+51 -17
View File
@@ -69,33 +69,50 @@
static int smartfs_open(FAR struct file *filep, const char *relpath,
int oflags, mode_t mode);
static int smartfs_close(FAR struct file *filep);
static ssize_t smartfs_read(FAR struct file *filep, char *buffer, size_t buflen);
static ssize_t smartfs_read(FAR struct file *filep, char *buffer,
size_t buflen);
static ssize_t smartfs_write(FAR struct file *filep, const char *buffer,
size_t buflen);
static off_t smartfs_seek(FAR struct file *filep, off_t offset, int whence);
static int smartfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static off_t smartfs_seek(FAR struct file *filep, off_t offset,
int whence);
static int smartfs_ioctl(FAR struct file *filep, int cmd,
unsigned long arg);
static int smartfs_sync(FAR struct file *filep);
static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int smartfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int smartfs_fstat(FAR const struct file *filep,
FAR struct stat *buf);
static int smartfs_opendir(struct inode *mountpt, const char *relpath,
struct fs_dirent_s *dir);
static int smartfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir);
static int smartfs_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir);
static int smartfs_opendir(FAR struct inode *mountpt,
FAR const char *relpath,
FAR struct fs_dirent_s *dir);
static int smartfs_readdir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int smartfs_rewinddir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int smartfs_bind(FAR struct inode *blkdriver, const void *data,
void **handle);
static int smartfs_bind(FAR struct inode *blkdriver,
FAR const void *data,
FAR void **handle);
static int smartfs_unbind(void *handle, FAR struct inode **blkdriver,
unsigned int flags);
static int smartfs_statfs(struct inode *mountpt, struct statfs *buf);
static int smartfs_statfs(FAR struct inode *mountpt,
FAR struct statfs *buf);
static int smartfs_unlink(struct inode *mountpt, const char *relpath);
static int smartfs_mkdir(struct inode *mountpt, const char *relpath,
static int smartfs_unlink(FAR struct inode *mountpt,
FAR const char *relpath);
static int smartfs_mkdir(FAR struct inode *mountpt,
FAR const char *relpath,
mode_t mode);
static int smartfs_rmdir(struct inode *mountpt, const char *relpath);
static int smartfs_rename(struct inode *mountpt, const char *oldrelpath,
static int smartfs_rmdir(FAR struct inode *mountpt,
FAR const char *relpath);
static int smartfs_rename(FAR struct inode *mountpt,
FAR const char *oldrelpath,
const char *newrelpath);
static int smartfs_stat(struct inode *mountpt, const char *relpath, struct stat *buf);
static int smartfs_stat(FAR struct inode *mountpt,
FAR const char *relpath,
FAR struct stat *buf);
static off_t smartfs_seek_internal(struct smartfs_mountpt_s *fs,
struct smartfs_ofile_s *sf,
@@ -128,6 +145,7 @@ const struct mountpt_operations smartfs_operations =
smartfs_sync, /* sync */
smartfs_dup, /* dup */
smartfs_fstat, /* fstat */
smartfs_opendir, /* opendir */
NULL, /* closedir */
@@ -1249,6 +1267,21 @@ static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return OK;
}
/****************************************************************************
* Name: smartfs_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 smartfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
#warning Missing logic
return -ENOSYS;
}
/****************************************************************************
* Name: smartfs_opendir
*
@@ -1256,7 +1289,8 @@ static int smartfs_dup(FAR const struct file *oldp, FAR struct file *newp)
*
****************************************************************************/
static int smartfs_opendir(struct inode *mountpt, const char *relpath, struct fs_dirent_s *dir)
static int smartfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct fs_dirent_s *dir)
{
struct smartfs_mountpt_s *fs;
int ret;
+147 -91
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/tmpfs/fs_tmpfs.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -91,75 +91,79 @@ static void tmpfs_unlock_reentrant(FAR struct tmpfs_sem_s *sem);
static void tmpfs_unlock(FAR struct tmpfs_s *fs);
static void tmpfs_lock_object(FAR struct tmpfs_object_s *to);
static void tmpfs_unlock_object(FAR struct tmpfs_object_s *to);
static int tmpfs_realloc_directory(FAR struct tmpfs_directory_s **tdo,
unsigned int nentries);
static int tmpfs_realloc_file(FAR struct tmpfs_file_s **tfo,
size_t newsize);
static int tmpfs_realloc_directory(FAR struct tmpfs_directory_s **tdo,
unsigned int nentries);
static int tmpfs_realloc_file(FAR struct tmpfs_file_s **tfo,
size_t newsize);
static void tmpfs_release_lockedobject(FAR struct tmpfs_object_s *to);
static void tmpfs_release_lockedfile(FAR struct tmpfs_file_s *tfo);
static int tmpfs_find_dirent(FAR struct tmpfs_directory_s *tdo,
FAR const char *name);
static int tmpfs_remove_dirent(FAR struct tmpfs_directory_s *tdo,
FAR const char *name);
static int tmpfs_add_dirent(FAR struct tmpfs_directory_s **tdo,
FAR struct tmpfs_object_s *to, FAR const char *name);
static int tmpfs_find_dirent(FAR struct tmpfs_directory_s *tdo,
FAR const char *name);
static int tmpfs_remove_dirent(FAR struct tmpfs_directory_s *tdo,
FAR const char *name);
static int tmpfs_add_dirent(FAR struct tmpfs_directory_s **tdo,
FAR struct tmpfs_object_s *to, FAR const char *name);
static FAR struct tmpfs_file_s *tmpfs_alloc_file(void);
static int tmpfs_create_file(FAR struct tmpfs_s *fs,
FAR const char *relpath, FAR struct tmpfs_file_s **tfo);
static int tmpfs_create_file(FAR struct tmpfs_s *fs,
FAR const char *relpath, FAR struct tmpfs_file_s **tfo);
static FAR struct tmpfs_directory_s *tmpfs_alloc_directory(void);
static int tmpfs_create_directory(FAR struct tmpfs_s *fs,
FAR const char *relpath, FAR struct tmpfs_directory_s **tdo);
static int tmpfs_find_object(FAR struct tmpfs_s *fs,
FAR const char *relpath, FAR struct tmpfs_object_s **object,
FAR struct tmpfs_directory_s **parent);
static int tmpfs_find_file(FAR struct tmpfs_s *fs,
FAR const char *relpath,
FAR struct tmpfs_file_s **tfo,
FAR struct tmpfs_directory_s **parent);
static int tmpfs_find_directory(FAR struct tmpfs_s *fs,
FAR const char *relpath,
FAR struct tmpfs_directory_s **tdo,
FAR struct tmpfs_directory_s **parent);
static int tmpfs_statfs_callout(FAR struct tmpfs_directory_s *tdo,
unsigned int index, FAR void *arg);
static int tmpfs_free_callout(FAR struct tmpfs_directory_s *tdo,
unsigned int index, FAR void *arg);
static int tmpfs_foreach(FAR struct tmpfs_directory_s *tdo,
tmpfs_foreach_t callout, FAR void *arg);
static int tmpfs_create_directory(FAR struct tmpfs_s *fs,
FAR const char *relpath, FAR struct tmpfs_directory_s **tdo);
static int tmpfs_find_object(FAR struct tmpfs_s *fs,
FAR const char *relpath, FAR struct tmpfs_object_s **object,
FAR struct tmpfs_directory_s **parent);
static int tmpfs_find_file(FAR struct tmpfs_s *fs,
FAR const char *relpath,
FAR struct tmpfs_file_s **tfo,
FAR struct tmpfs_directory_s **parent);
static int tmpfs_find_directory(FAR struct tmpfs_s *fs,
FAR const char *relpath,
FAR struct tmpfs_directory_s **tdo,
FAR struct tmpfs_directory_s **parent);
static int tmpfs_statfs_callout(FAR struct tmpfs_directory_s *tdo,
unsigned int index, FAR void *arg);
static int tmpfs_free_callout(FAR struct tmpfs_directory_s *tdo,
unsigned int index, FAR void *arg);
static int tmpfs_foreach(FAR struct tmpfs_directory_s *tdo,
tmpfs_foreach_t callout, FAR void *arg);
/* File system operations */
static int tmpfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int tmpfs_close(FAR struct file *filep);
static int tmpfs_open(FAR struct file *filep, FAR const char *relpath,
int oflags, mode_t mode);
static int tmpfs_close(FAR struct file *filep);
static ssize_t tmpfs_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
size_t buflen);
static ssize_t tmpfs_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
size_t buflen);
static off_t tmpfs_seek(FAR struct file *filep, off_t offset, int whence);
static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct fs_dirent_s *dir);
static int tmpfs_closedir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int tmpfs_readdir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int tmpfs_rewinddir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data,
FAR void **handle);
static int tmpfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
unsigned int flags);
static int tmpfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
static int tmpfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath,
mode_t mode);
static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath);
static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath,
FAR const char *newrelpath);
static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
static int tmpfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp);
static int tmpfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct fs_dirent_s *dir);
static int tmpfs_closedir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int tmpfs_readdir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int tmpfs_rewinddir(FAR struct inode *mountpt,
FAR struct fs_dirent_s *dir);
static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data,
FAR void **handle);
static int tmpfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
unsigned int flags);
static int tmpfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf);
static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath);
static int tmpfs_mkdir(FAR struct inode *mountpt, FAR const char *relpath,
mode_t mode);
static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath);
static int tmpfs_rename(FAR struct inode *mountpt, FAR const char *oldrelpath,
FAR const char *newrelpath);
static void tmpfs_stat_common(FAR struct tmpfs_object_s *to,
FAR struct stat *buf);
static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
/****************************************************************************
* Public Data
@@ -175,6 +179,7 @@ const struct mountpt_operations tmpfs_operations =
tmpfs_ioctl, /* ioctl */
NULL, /* sync */
tmpfs_dup, /* dup */
tmpfs_fstat, /* fstat */
tmpfs_opendir, /* opendir */
tmpfs_closedir, /* closedir */
tmpfs_readdir, /* readdir */
@@ -1769,6 +1774,41 @@ static int tmpfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return OK;
}
/****************************************************************************
* Name: tmpfs_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 tmpfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct tmpfs_file_s *tfo;
finfo("Fstat %p\n", buf);
DEBUGASSERT(filep != NULL && buf != NULL);
/* Recover our private data from the struct file instance */
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
tfo = filep->f_priv;
/* Get exclusive access to the file */
tmpfs_lock_file(tfo);
/* Return information about the file in the stat buffer.*/
tmpfs_stat_common((FAR struct tmpfs_object_s *)tfo, buf);
/* Release the lock on the file and return success. */
tmpfs_unlock_file(tfo);
return OK;
}
/****************************************************************************
* Name: tmpfs_opendir
****************************************************************************/
@@ -2459,41 +2499,15 @@ errout_with_lock:
}
/****************************************************************************
* Name: tmpfs_stat
* Name: tmpfs_stat_common
****************************************************************************/
static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf)
static void tmpfs_stat_common(FAR struct tmpfs_object_s *to,
FAR struct stat *buf)
{
FAR struct tmpfs_s *fs;
FAR struct tmpfs_object_s *to;
size_t objsize;
int ret;
finfo("mountpt=%p relpath=%s buf=%p\n", mountpt, relpath, buf);
DEBUGASSERT(mountpt != NULL && relpath != NULL && buf != NULL);
/* Get the file system structure from the inode reference. */
fs = mountpt->i_private;
DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
/* Get exclusive access to the file system */
tmpfs_lock(fs);
/* Find the tmpfs object at the relpath. If successful,
* tmpfs_find_object() will lock the object and increment the
* reference count on the object.
*/
ret = tmpfs_find_object(fs, relpath, &to, NULL);
if (ret < 0)
{
goto errout_with_fslock;
}
/* We found it... Is the object a regular file? */
/* Is the tmpfs object a regular file? */
memset(buf, 0, sizeof(struct stat));
@@ -2530,8 +2544,50 @@ static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
buf->st_blksize = CONFIG_FS_TMPFS_BLOCKSIZE;
buf->st_blocks = (objsize + CONFIG_FS_TMPFS_BLOCKSIZE - 1) /
CONFIG_FS_TMPFS_BLOCKSIZE;
}
/* No... unlock the object and return success */
/****************************************************************************
* Name: tmpfs_stat
****************************************************************************/
static int tmpfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf)
{
FAR struct tmpfs_s *fs;
FAR struct tmpfs_object_s *to;
int ret;
finfo("mountpt=%p relpath=%s buf=%p\n", mountpt, relpath, buf);
DEBUGASSERT(mountpt != NULL && relpath != NULL && buf != NULL);
/* Get the file system structure from the inode reference. */
fs = mountpt->i_private;
DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL);
/* Get exclusive access to the file system */
tmpfs_lock(fs);
/* Find the tmpfs object at the relpath. If successful,
* tmpfs_find_object() will lock the object and increment the
* reference count on the object.
*/
ret = tmpfs_find_object(fs, relpath, &to, NULL);
if (ret < 0)
{
goto errout_with_fslock;
}
/* We found it... Return information about the file object in the stat
* buffer.
*/
DEBUGASSERT(to != NULL);
tmpfs_stat_common(to, buf);
/* Unlock the object and return success */
tmpfs_release_lockedobject(to);
ret = OK;
+56 -1
View File
@@ -160,6 +160,8 @@ static int unionfs_ioctl(FAR struct file *filep, int cmd,
static int unionfs_sync(FAR struct file *filep);
static int unionfs_dup(FAR const struct file *oldp,
FAR struct file *newp);
static int unionfs_fstat(FAR const struct file *filep,
FAR struct stat *buf);
/* Operations on directories */
@@ -215,6 +217,7 @@ static const struct mountpt_operations g_unionfs_mops =
unionfs_sync, /* sync */
unionfs_dup, /* dup */
unionfs_fstat, /* fstat */
unionfs_opendir, /* opendir */
unionfs_closedir, /* closedir */
@@ -489,7 +492,7 @@ static int unionfs_trymkdir(FAR struct inode *inode, FAR const char *relpath,
}
/****************************************************************************
* Name: unionfs_trystat
* Name: unionfs_tryrename
****************************************************************************/
static int unionfs_tryrename(FAR struct inode *mountpt,
@@ -1309,6 +1312,58 @@ static int unionfs_dup(FAR const struct file *oldp, FAR struct file *newp)
return ret;
}
/****************************************************************************
* Name: unionfs_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 unionfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
{
FAR struct unionfs_inode_s *ui;
FAR struct unionfs_file_s *uf;
FAR struct unionfs_mountpt_s *um;
FAR const struct mountpt_operations *ops;
int ret = -EPERM;
finfo("Entry\n");
/* Recover the open file data from the struct file instance */
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
ui = (FAR struct unionfs_inode_s *)filep->f_inode->i_private;
/* Get exclusive access to the file system data structures */
ret = unionfs_semtake(ui, false);
if (ret < 0)
{
return ret;
}
DEBUGASSERT(ui != NULL && filep->f_priv != NULL);
uf = (FAR struct unionfs_file_s *)filep->f_priv;
DEBUGASSERT(uf->uf_ndx == 0 || uf->uf_ndx == 1);
um = &ui->ui_fs[uf->uf_ndx];
DEBUGASSERT(um != NULL && um->um_node != NULL && um->um_node->u.i_mops != NULL);
ops = um->um_node->u.i_mops;
/* Perform the lower level write operation */
if (ops->fstat)
{
ret = ops->fstat(&uf->uf_file, buf);
}
unionfs_semgive(ui);
return ret;
}
/****************************************************************************
* Name: unionfs_opendir
****************************************************************************/
+3 -3
View File
@@ -72,9 +72,9 @@ else
# Common file/socket descriptor support
CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_dupfd.c fs_dupfd2.c
CSRCS += fs_epoll.c fs_getfilep.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c
CSRCS += fs_poll.c fs_read.c fs_rename.c fs_rmdir.c fs_stat.c fs_statfs.c
CSRCS += fs_select.c fs_unlink.c fs_write.c
CSRCS += fs_epoll.c fs_fstat.c fs_getfilep.c fs_ioctl.c fs_lseek.c
CSRCS += fs_mkdir.c fs_open.c fs_poll.c fs_read.c fs_rename.c fs_rmdir.c fs_statfs.c
CSRCS += fs_stat.c fs_select.c fs_unlink.c fs_write.c
# Certain interfaces are not available if there is no mountpoint support
+156
View File
@@ -0,0 +1,156 @@
/****************************************************************************
* fs/vfs/fs_fstat.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fstat
*
* Description:
* The fstat() function will obtain information about an open file
* associated with the file descriptor 'fd', and will write it to the area
* pointed to by 'buf'.
*
* The 'buf' argument is a pointer to a stat structure, as defined in
* <sys/stat.h>, into which information is placed concerning the file.
*
* Input Parameters:
* fd - The file descriptor associated with the open file of interest
* buf - The caller provide location in which to return information about
* the open file.
*
* Returned Value:
* Upon successful completion, 0 shall be returned. Otherwise, -1 shall be
* returned and errno set to indicate the error.
*
****************************************************************************/
int fstat(int fd, FAR struct stat *buf)
{
FAR struct file *filep;
FAR struct inode *inode;
int ret;
/* Did we get a valid file descriptor? */
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
{
/* No networking... it is a bad descriptor in any event */
set_errno(EBADF);
return ERROR;
}
/* The descriptor is in a valid range to file descriptor... do the
* read. First, get the file structure. Note that on failure,
* fs_getfilep() will set the errno variable.
*/
filep = fs_getfilep(fd);
if (filep == NULL)
{
/* The errno value has already been set */
return ERROR;
}
/* Get the inode from the file structure */
inode = filep->f_inode;
DEBUGASSERT(inode != NULL);
/* The way we handle the stat depends on the type of inode that we
* are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* The inode is a file system mointpoint. Verify that the mountpoint
* supports the fstat() method
*/
ret = OK;
if (inode->u.i_mops && inode->u.i_mops->fstat)
{
/* Perform the fstat() operation */
ret = inode->u.i_mops->fstat(filep, buf);
}
}
else
#endif
{
/* The inode is part of the root pseudo file system. */
ret = inode_stat(inode, buf);
}
/* Check if the fstat operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully fstat'ed the file */
inode_release(inode);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
set_errno(ret);
return ERROR;
}
+188 -170
View File
@@ -70,7 +70,6 @@
* Private Function Prototypes
****************************************************************************/
static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf);
static inline int statroot(FAR struct stat *buf);
int stat_recursive(FAR const char *path, FAR struct stat *buf);
@@ -79,11 +78,197 @@ int stat_recursive(FAR const char *path, FAR struct stat *buf);
****************************************************************************/
/****************************************************************************
* Name: statpseudo
* Name: statroot
****************************************************************************/
static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf)
static inline int statroot(FAR struct stat *buf)
{
/* There is no inode associated with the fake root directory */
RESET_BUF(buf);
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
return OK;
}
/****************************************************************************
* Name: stat_recursive
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
*
****************************************************************************/
int stat_recursive(FAR const char *path, FAR struct stat *buf)
{
struct inode_search_s desc;
FAR struct inode *inode;
int ret;
/* Get an inode for this path */
SETUP_SEARCH(&desc, path, true);
ret = inode_find(&desc);
if (ret < 0)
{
/* This name does not refer to an inode in the pseudo file system and
* there is no mountpoint that includes in this path.
*/
ret = -ret;
goto errout_with_search;
}
/* Get the search results */
inode = desc.node;
DEBUGASSERT(inode != NULL);
/* The way we handle the stat depends on the type of inode that we
* are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the stat() method
*/
if (inode->u.i_mops && inode->u.i_mops->stat)
{
/* Perform the stat() operation */
ret = inode->u.i_mops->stat(inode, desc.relpath, buf);
}
}
else
#endif
{
/* The node is part of the root pseudo file system. This path may
* recurse if soft links are supported in the pseudo file system.
*/
ret = inode_stat(inode, buf);
}
/* Check if the stat operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully stat'ed the file */
inode_release(inode);
RELEASE_SEARCH(&desc);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
errout_with_search:
RELEASE_SEARCH(&desc);
set_errno(ret);
return ERROR;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stat
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
*
****************************************************************************/
int stat(FAR const char *path, FAR struct stat *buf)
{
int ret;
/* Sanity checks */
if (path == NULL || buf == NULL)
{
ret = EFAULT;
goto errout;
}
if (*path == '\0')
{
ret = ENOENT;
goto errout;
}
/* Check for the fake root directory (which has no inode) */
if (strcmp(path, "/") == 0)
{
return statroot(buf);
}
/* The perform the stat() operation on the path. This is potentially
* recursive if soft link support is enabled.
*/
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
buf->st_count = 0;
#endif
return stat_recursive(path, buf);
errout:
set_errno(ret);
return ERROR;
}
/****************************************************************************
* Name: inode_stat
*
* Description:
* The inode_stat() function will obtain information about an 'inode' in
* the pseudo file system and will write it to the area pointed to by 'buf'.
*
* The 'buf' argument is a pointer to a stat structure, as defined in
* <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.
*
* Returned Value:
* Zero (OK) returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int inode_stat(FAR struct inode *inode, FAR struct stat *buf)
{
DEBUGASSERT(inode != NULL && buf != NULL);
/* Most of the stat entries just do not apply */
RESET_BUF(buf);
@@ -210,170 +395,3 @@ static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf)
return OK;
}
/****************************************************************************
* Name: statroot
****************************************************************************/
static inline int statroot(FAR struct stat *buf)
{
/* There is no inode associated with the fake root directory */
RESET_BUF(buf);
buf->st_mode = S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
return OK;
}
/****************************************************************************
* Name: stat_recursive
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
*
****************************************************************************/
int stat_recursive(FAR const char *path, FAR struct stat *buf)
{
struct inode_search_s desc;
FAR struct inode *inode;
int ret;
/* Get an inode for this path */
SETUP_SEARCH(&desc, path, true);
ret = inode_find(&desc);
if (ret < 0)
{
/* This name does not refer to a psudeo-inode and there is no
* mountpoint that includes in this path.
*/
ret = -ret;
goto errout_with_search;
}
/* Get the search results */
inode = desc.node;
DEBUGASSERT(inode != NULL);
/* The way we handle the stat depends on the type of inode that we
* are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
if (INODE_IS_MOUNTPT(inode))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the stat() method
*/
if (inode->u.i_mops && inode->u.i_mops->stat)
{
/* Perform the stat() operation */
ret = inode->u.i_mops->stat(inode, desc.relpath, buf);
}
}
else
#endif
{
/* The node is part of the root pseudo file system. This path may
* recurse if soft links are supported in the pseudo file system.
*/
ret = statpseudo(inode, buf);
}
/* Check if the stat operation was successful */
if (ret < 0)
{
ret = -ret;
goto errout_with_inode;
}
/* Successfully stat'ed the file */
inode_release(inode);
RELEASE_SEARCH(&desc);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
errout_with_search:
RELEASE_SEARCH(&desc);
set_errno(ret);
return ERROR;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stat
*
* Returned Value:
* Zero on success; -1 on failure with errno set:
*
* EACCES Search permission is denied for one of the directories in the
* path prefix of path.
* EFAULT Bad address.
* ENOENT A component of the path path does not exist, or the path is an
* empty string.
* ENOMEM Out of memory
* ENOTDIR A component of the path is not a directory.
*
****************************************************************************/
int stat(FAR const char *path, FAR struct stat *buf)
{
int ret;
/* Sanity checks */
if (path == NULL || buf == NULL)
{
ret = EFAULT;
goto errout;
}
if (*path == '\0')
{
ret = ENOENT;
goto errout;
}
/* Check for the fake root directory (which has no inode) */
if (strcmp(path, "/") == 0)
{
return statroot(buf);
}
/* The perform the stat() operation on the path. This is potentially
* recursive if soft link support is enabled.
*/
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
buf->st_count = 0;
#endif
return stat_recursive(path, buf);
errout:
set_errno(ret);
return ERROR;
}
+1
View File
@@ -265,6 +265,7 @@ struct mountpt_operations
int (*sync)(FAR struct file *filep);
int (*dup)(FAR const struct file *oldp, FAR struct file *newp);
int (*fstat)(FAR const struct file *filep, FAR struct stat *buf);
/* Directory operations */
+2 -4
View File
@@ -130,8 +130,8 @@ struct stat
time_t st_mtime; /* Time of last modification */
time_t st_ctime; /* Time of last status change */
/* Internal fields. These are part this specifi instance and should not
* referenced by application code for portability reasons.
/* Internal fields. These are part this specific implementation and
* should not referenced by application code for portability reasons.
*/
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
@@ -155,9 +155,7 @@ extern "C"
int mkdir(FAR const char *pathname, mode_t mode);
int mkfifo(FAR const char *pathname, mode_t mode);
int stat(const char *path, FAR struct stat *buf);
#if 0 /* Not yet supported */
int fstat(int fd, FAR struct stat *buf);
#endif
#undef EXTERN
#if defined(__cplusplus)