mirror of
https://github.com/apache/nuttx.git
synced 2026-05-23 06:39:01 +08:00
Merge branch 'fstat'
This commit is contained in:
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user