fs: Add fchstat and chstat callback into mountpt_operations

and implement all status related change function. the individual
file system change will provide in other upcoming patchset.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: I8fde9db8eba9586e9c8da078b67e020c26623cf4
This commit is contained in:
Xiang Xiao 2021-07-09 13:43:26 +08:00 committed by Gustavo Henrique Nihei
parent 68a345e248
commit 307cc61893
27 changed files with 907 additions and 118 deletions

View file

@ -98,6 +98,7 @@ const struct mountpt_operations binfs_operations =
NULL, /* sync */
binfs_dup, /* dup */
binfs_fstat, /* fstat */
NULL, /* fchstat */
NULL, /* truncate */
binfs_opendir, /* opendir */
@ -113,7 +114,8 @@ const struct mountpt_operations binfs_operations =
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* rename */
binfs_stat /* stat */
binfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -179,6 +179,7 @@ const struct mountpt_operations cromfs_operations =
NULL, /* sync */
cromfs_dup, /* dup */
cromfs_fstat, /* fstat */
NULL, /* fchstat */
NULL, /* truncate */
cromfs_opendir, /* opendir */
@ -194,7 +195,8 @@ const struct mountpt_operations cromfs_operations =
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* rename */
cromfs_stat /* stat */
cromfs_stat, /* stat */
NULL /* chstat */
};
/* The CROMFS uses a global, in-memory instance of the file system image

View file

@ -117,6 +117,7 @@ const struct mountpt_operations fat_operations =
fat_sync, /* sync */
fat_dup, /* dup */
fat_fstat, /* fstat */
NULL, /* fchstat */
fat_truncate, /* truncate */
fat_opendir, /* opendir */
@ -132,7 +133,8 @@ const struct mountpt_operations fat_operations =
fat_mkdir, /* mkdir */
fat_rmdir, /* rmdir */
fat_rename, /* rename */
fat_stat /* stat */
fat_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -131,6 +131,7 @@ const struct mountpt_operations hostfs_operations =
hostfs_sync, /* sync */
hostfs_dup, /* dup */
hostfs_fstat, /* fstat */
NULL, /* fchstat */
hostfs_ftruncate, /* ftruncate */
hostfs_opendir, /* opendir */
@ -146,7 +147,8 @@ const struct mountpt_operations hostfs_operations =
hostfs_mkdir, /* mkdir */
hostfs_rmdir, /* rmdir */
hostfs_rename, /* rename */
hostfs_stat /* stat */
hostfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -242,9 +242,34 @@ int inode_find(FAR struct inode_search_s *desc);
*
****************************************************************************/
struct stat; /* Forward reference */
int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve);
/****************************************************************************
* Name: inode_chstat
*
* Description:
* The inode_chstat() function will change information about an 'inode'
* in the pseudo file system according the area pointed to by 'buf'.
*
* The 'buf' argument is a pointer to a stat structure, as defined in
* <sys/stat.h>, which information is placed concerning the file.
*
* Input Parameters:
* inode - The inode of interest
* buf - The caller provide location in which to apply information
* about the inode.
* flags - The vaild field in buf
* resolve - Whether to resolve the symbolic link
*
* Returned Value:
* Zero (OK) returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int inode_chstat(FAR struct inode *inode,
FAR const struct stat *buf, int flags, int resolve);
/****************************************************************************
* Name: inode_getpath
*

View file

@ -141,6 +141,7 @@ const struct mountpt_operations littlefs_operations =
littlefs_sync, /* sync */
littlefs_dup, /* dup */
littlefs_fstat, /* fstat */
NULL, /* fchstat */
littlefs_truncate, /* truncate */
littlefs_opendir, /* opendir */
@ -156,7 +157,8 @@ const struct mountpt_operations littlefs_operations =
littlefs_mkdir, /* mkdir */
littlefs_rmdir, /* rmdir */
littlefs_rename, /* rename */
littlefs_stat /* stat */
littlefs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -180,6 +180,7 @@ const struct mountpt_operations nfs_operations =
NULL, /* sync */
nfs_dup, /* dup */
nfs_fstat, /* fstat */
NULL, /* fchstat */
nfs_truncate, /* truncate */
nfs_opendir, /* opendir */
@ -195,7 +196,8 @@ const struct mountpt_operations nfs_operations =
nfs_mkdir, /* mkdir */
nfs_rmdir, /* rmdir */
nfs_rename, /* rename */
nfs_stat /* stat */
nfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -58,6 +58,7 @@ const struct mountpt_operations nxffs_operations =
NULL, /* sync -- No buffered data */
nxffs_dup, /* dup */
nxffs_fstat, /* fstat */
NULL, /* fchstat */
#ifdef __NO_TRUNCATE_SUPPORT__
nxffs_truncate, /* truncate */
#else
@ -77,7 +78,8 @@ const struct mountpt_operations nxffs_operations =
NULL, /* mkdir -- no directories */
NULL, /* rmdir -- no directories */
NULL, /* rename -- cannot rename in place if name is longer */
nxffs_stat /* stat */
nxffs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -249,6 +249,7 @@ const struct mountpt_operations procfs_operations =
NULL, /* sync */
procfs_dup, /* dup */
procfs_fstat, /* fstat */
NULL, /* fchstat */
NULL, /* truncate */
procfs_opendir, /* opendir */
@ -264,7 +265,8 @@ const struct mountpt_operations procfs_operations =
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* rename */
procfs_stat /* stat */
procfs_stat, /* stat */
NULL /* chstat */
};
/* Level 0 contains the directory of active tasks in addition to other

View file

@ -106,6 +106,7 @@ const struct mountpt_operations romfs_operations =
NULL, /* sync */
romfs_dup, /* dup */
romfs_fstat, /* fstat */
NULL, /* fchstat */
NULL, /* truncate */
romfs_opendir, /* opendir */
@ -121,7 +122,8 @@ const struct mountpt_operations romfs_operations =
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* rename */
romfs_stat /* stat */
romfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -130,6 +130,7 @@ const struct mountpt_operations smartfs_operations =
smartfs_sync, /* sync */
smartfs_dup, /* dup */
smartfs_fstat, /* fstat */
NULL, /* fchstat */
smartfs_truncate, /* truncate */
smartfs_opendir, /* opendir */
@ -145,7 +146,8 @@ const struct mountpt_operations smartfs_operations =
smartfs_mkdir, /* mkdir */
smartfs_rmdir, /* rmdir */
smartfs_rename, /* rename */
smartfs_stat /* stat */
smartfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -140,6 +140,7 @@ const struct mountpt_operations spiffs_operations =
spiffs_sync, /* sync */
spiffs_dup, /* dup */
spiffs_fstat, /* fstat */
NULL, /* fchstat */
spiffs_truncate, /* truncate */
spiffs_opendir, /* opendir */
@ -156,6 +157,7 @@ const struct mountpt_operations spiffs_operations =
spiffs_rmdir, /* rmdir */
spiffs_rename, /* rename */
spiffs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -168,6 +168,7 @@ const struct mountpt_operations tmpfs_operations =
NULL, /* sync */
tmpfs_dup, /* dup */
tmpfs_fstat, /* fstat */
NULL, /* fchstat */
tmpfs_truncate, /* truncate */
tmpfs_opendir, /* opendir */
@ -184,6 +185,7 @@ const struct mountpt_operations tmpfs_operations =
tmpfs_rmdir, /* rmdir */
tmpfs_rename, /* rename */
tmpfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -211,6 +211,7 @@ const struct mountpt_operations unionfs_operations =
unionfs_sync, /* sync */
unionfs_dup, /* dup */
unionfs_fstat, /* fstat */
NULL, /* fchstat */
unionfs_truncate, /* truncate */
unionfs_opendir, /* opendir */
@ -226,7 +227,8 @@ const struct mountpt_operations unionfs_operations =
unionfs_mkdir, /* mkdir */
unionfs_rmdir, /* rmdir */
unionfs_rename, /* rename */
unionfs_stat /* stat */
unionfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -153,6 +153,7 @@ const struct mountpt_operations userfs_operations =
userfs_sync, /* sync */
userfs_dup, /* dup */
userfs_fstat, /* fstat */
NULL, /* fchstat */
userfs_truncate, /* truncate */
userfs_opendir, /* opendir */
@ -168,7 +169,8 @@ const struct mountpt_operations userfs_operations =
userfs_mkdir, /* mkdir */
userfs_rmdir, /* rmdir */
userfs_rename, /* rename */
userfs_stat /* stat */
userfs_stat, /* stat */
NULL /* chstat */
};
/****************************************************************************

View file

@ -20,10 +20,11 @@
# Common file/socket descriptor support
CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_epoll.c fs_fstat.c
CSRCS += fs_fstatfs.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c
CSRCS += fs_pread.c fs_pwrite.c fs_read.c fs_rename.c fs_rmdir.c fs_select.c
CSRCS += fs_sendfile.c fs_stat.c fs_statfs.c fs_unlink.c fs_write.c
CSRCS += fs_chstat.c fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_epoll.c
CSRCS += fs_fchstat.c fs_fstat.c fs_fstatfs.c fs_ioctl.c fs_lseek.c
CSRCS += fs_mkdir.c fs_open.c fs_poll.c fs_pread.c fs_pwrite.c fs_read.c
CSRCS += fs_rename.c fs_rmdir.c fs_select.c fs_sendfile.c fs_stat.c
CSRCS += fs_statfs.c fs_unlink.c fs_write.c
# Certain interfaces are not available if there is no mountpoint support

480
fs/vfs/fs_chstat.c Normal file
View file

@ -0,0 +1,480 @@
/****************************************************************************
* fs/vfs/fs_chstat.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: chstat_recursive
****************************************************************************/
static int chstat_recursive(FAR const char *path,
FAR const struct stat *buf,
int flags, int resolve)
{
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.
*/
goto errout_with_search;
}
/* Get the search results */
inode = desc.node;
DEBUGASSERT(inode != NULL);
/* The way we handle the chstat 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 chstat() method
*/
if (inode->u.i_mops && inode->u.i_mops->chstat)
{
/* Perform the chstat() operation */
ret = inode->u.i_mops->chstat(inode, desc.relpath, buf, flags);
}
else
{
ret = -ENOSYS;
}
}
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_chstat(inode, buf, flags, resolve);
}
inode_release(inode);
errout_with_search:
RELEASE_SEARCH(&desc);
return ret;
}
/****************************************************************************
* Name: fchstat
****************************************************************************/
static int chstat(FAR const char *path,
FAR struct stat *buf, int flags, int resolve)
{
int ret = -EINVAL;
/* Adjust and check buf and flags */
if ((flags & CH_STAT_MODE) && (buf->st_mode & ~07777))
{
goto errout;
}
if ((flags & CH_STAT_UID) && buf->st_uid == -1)
{
flags &= ~CH_STAT_UID;
}
if ((flags & CH_STAT_GID) && buf->st_gid == -1)
{
flags &= ~CH_STAT_GID;
}
clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
if (flags & CH_STAT_ATIME)
{
if (buf->st_atim.tv_nsec == UTIME_OMIT)
{
flags &= ~CH_STAT_ATIME;
}
else if (buf->st_atim.tv_nsec == UTIME_NOW)
{
buf->st_atim = buf->st_ctim;
}
else if (buf->st_atim.tv_nsec >= 1000000000)
{
goto errout;
}
}
if (flags & CH_STAT_MTIME)
{
if (buf->st_mtim.tv_nsec == UTIME_OMIT)
{
flags &= ~CH_STAT_MTIME;
}
else if (buf->st_mtim.tv_nsec == UTIME_NOW)
{
buf->st_mtim = buf->st_ctim;
}
else if (buf->st_mtim.tv_nsec >= 1000000000)
{
goto errout;
}
}
/* Perform the chstat operation */
ret = chstat_recursive(path, buf, flags, resolve);
if (ret >= 0)
{
/* Successfully chstat'ed the file */
return OK;
}
errout:
set_errno(-ret);
return ERROR;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: chmod
*
* Description:
* The chmod() function changes S_ISUID, S_ISGID, S_ISVTX and the file
* permission bits of the file named by the pathname pointed to by the
* path argument to the corresponding bits in the mode argument. The
* effective user ID of the process must match the owner of the file or
* the process must have appropriate privileges in order to do this.
*
* Input Parameters:
* path - Specifies the file to be modified
* mode - Specifies the permission to set
*
* Returned Value:
* Upon successful completion, chmod() shall return 0.
* Otherwise, it shall return -1 and set errno to indicate the error.
*
****************************************************************************/
int chmod(FAR const char *path, mode_t mode)
{
struct stat buf;
buf.st_mode = mode;
return chstat(path, &buf, CH_STAT_MODE, 1);
}
/****************************************************************************
* Name: lchmod
*
* Description:
* The lchmod() system call is similar to chmod() but does not follow
* the symbolic links.
*
* Input Parameters:
* path - Specifies the file to be modified
* mode - Specifies the permission to set
*
* Returned Value:
* Upon successful completion, lchmod() shall return 0.
* Otherwise, it shall return -1 and set errno to indicate the error.
*
****************************************************************************/
int lchmod(FAR const char *path, mode_t mode)
{
struct stat buf;
buf.st_mode = mode;
return chstat(path, &buf, CH_STAT_MODE, 0);
}
/****************************************************************************
* Name: chown
*
* Description:
* The chown() function shall change the user and group ownership of a
* file. Only processes with an effective user ID equal to the user ID
* of the file or with appropriate privileges may change the ownership
* of a file.
*
* Input Parameters:
* path - Specifies the file to be modified
* owner - Specifies the owner to set
* group - Specifies the group to set
*
* Returned Value:
* Upon successful completion, chown() shall return 0.
* Otherwise, it shall return -1 and set errno to indicate the error.
*
****************************************************************************/
int chown(FAR const char *path, uid_t owner, gid_t group)
{
struct stat buf;
buf.st_uid = owner;
buf.st_gid = group;
return chstat(path, &buf, CH_STAT_UID | CH_STAT_GID, 1);
}
/****************************************************************************
* Name: lchown
*
* Description:
* The lchown() system call is similar to chown() but does not follow
* the symbolic links.
*
* Input Parameters:
* path - Specifies the file to be modified
* owner - Specifies the owner to set
* group - Specifies the group to set
*
* Returned Value:
* Upon successful completion, lchown() shall return 0.
* Otherwise, it shall return -1 and set errno to indicate the error.
*
****************************************************************************/
int lchown(FAR const char *path, uid_t owner, gid_t group)
{
struct stat buf;
buf.st_uid = owner;
buf.st_gid = group;
return chstat(path, &buf, CH_STAT_UID | CH_STAT_GID, 0);
}
/****************************************************************************
* Name: utimes
*
* Description:
* The utimes() function shall set the access and modification times of
* the file pointed to by the path argument to the value of the times
* argument. utimes() function allows time specifications accurate to
* the microsecond.
*
* For utimes(), the times argument is an array of timeval structures.
* The first array member represents the date and time of last access,
* and the second member represents the date and time of last
* modification. The times in the timeval structure are measured in
* seconds and microseconds since the Epoch, although rounding toward
* the nearest second may occur.
*
* If the times argument is a null pointer, the access and modification
* times of the file shall be set to the current time. The effective
* user ID of the process shall match the owner of the file, has write
* access to the file or appropriate privileges to use this call in this
* manner. Upon completion, utimes() shall mark the time of the last
* file status change, st_ctime, for update.
*
* Input Parameters:
* path - Specifies the file to be modified
* times - Specifies the time value to set
*
* Returned Value:
* Upon successful completion, 0 shall be returned. Otherwise, -1 shall
* be returned and errno shall be set to indicate the error, and the file
* times shall not be affected.
*
****************************************************************************/
int utimes(FAR const char *path, const struct timeval times[2])
{
struct stat buf;
if (times != NULL)
{
TIMEVAL_TO_TIMESPEC(&times[0], &buf.st_atim);
TIMEVAL_TO_TIMESPEC(&times[1], &buf.st_mtim);
}
else
{
buf.st_atim.tv_nsec = UTIME_NOW;
buf.st_mtim.tv_nsec = UTIME_NOW;
}
return chstat(path, &buf, CH_STAT_ATIME | CH_STAT_MTIME, 1);
}
/****************************************************************************
* Name: lutimes
*
* Description:
* The lutimes() system call is similar to utimes() but does not follow
* the symbolic links.
*
* Input Parameters:
* path - Specifies the file to be modified
* times - Specifies the time value to set
*
* Returned Value:
* Upon successful completion, 0 shall be returned. Otherwise, -1 shall
* be returned and errno shall be set to indicate the error, and the file
* times shall not be affected.
*
****************************************************************************/
int lutimes(FAR const char *path, const struct timeval times[2])
{
struct stat buf;
if (times != NULL)
{
TIMEVAL_TO_TIMESPEC(&times[0], &buf.st_atim);
TIMEVAL_TO_TIMESPEC(&times[1], &buf.st_mtim);
}
else
{
buf.st_atim.tv_nsec = UTIME_NOW;
buf.st_mtim.tv_nsec = UTIME_NOW;
}
return chstat(path, &buf, CH_STAT_ATIME | CH_STAT_MTIME, 0);
}
/****************************************************************************
* Name: inode_chstat
*
* Description:
* The inode_chstat() function will change information about an 'inode'
* in the pseudo file system according the area pointed to by 'buf'.
*
* The 'buf' argument is a pointer to a stat structure, as defined in
* <sys/stat.h>, which information is placed concerning the file.
*
* Input Parameters:
* inode - The inode of interest
* buf - The caller provide location in which to apply information
* about the inode.
* flags - The vaild field in buf
* resolve - Whether to resolve the symbolic link
*
* Returned Value:
* Zero (OK) returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int inode_chstat(FAR struct inode *inode,
FAR const struct stat *buf, int flags, int resolve)
{
DEBUGASSERT(inode != NULL && buf != NULL);
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
/* Handle softlinks differently. Just call chstat() recursively on the
* target of the softlink.
*/
if (INODE_IS_SOFTLINK(inode))
{
if (resolve)
{
/* Increment the link counter. This is necessary to avoid
* infinite recursion if loops are encountered in the
* traversal. If we encounter more SYMLOOP_MAX symbolic links
* at any time during the traversal, error out.
*
* NOTE: That inode_search() will automatically skip over
* consecutive, intermediate symbolic links. Those numbers
* will not be included in the total.
*/
if (resolve > SYMLOOP_MAX)
{
return -ELOOP;
}
/* chstat() the target of the soft link. */
return chstat_recursive(inode->u.i_link, buf, flags, ++resolve);
}
}
#endif
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
if (flags & CH_STAT_MODE)
{
inode->i_mode = buf->st_mode;
}
if (flags & CH_STAT_UID)
{
inode->i_owner = buf->st_uid;
}
if (flags & CH_STAT_GID)
{
inode->i_group = buf->st_gid;
}
if (flags & CH_STAT_ATIME)
{
inode->i_atime = buf->st_atim;
}
if (flags & CH_STAT_MTIME)
{
inode->i_mtime = buf->st_mtim;
}
inode->i_ctime = buf->st_ctim;
#endif
return OK;
}

287
fs/vfs/fs_fchstat.c Normal file
View file

@ -0,0 +1,287 @@
/****************************************************************************
* fs/vfs/fs_fchstat.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/stat.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: fchstat
****************************************************************************/
static int fchstat(int fd, FAR struct stat *buf, int flags)
{
FAR struct file *filep;
int ret;
/* First, get the file structure. Note that on failure,
* fs_getfilep() will return the errno.
*/
ret = fs_getfilep(fd, &filep);
if (ret < 0)
{
goto errout;
}
/* Perform the fchstat operation */
ret = file_fchstat(filep, buf, flags);
if (ret >= 0)
{
/* Successfully fchstat'ed the file */
return OK;
}
errout:
set_errno(-ret);
return ERROR;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: file_fchstat
*
* Description:
* file_fchstat() is an internal OS interface. It is functionally similar
* to the combination of fchmod/fchown/futimens standard interface except:
*
* - It does not modify the errno variable,
* - It is not a cancellation point,
* - It does not handle socket descriptors, and
* - It accepts a file structure instance instead of file descriptor.
*
* Input Parameters:
* filep - File structure instance
* buf - The stat to be modified
* flags - The vaild field in buf
*
* Returned Value:
* Upon successful completion, 0 shall be returned. Otherwise, the
* negative errno shall be returned to indicate the error.
*
****************************************************************************/
int file_fchstat(FAR struct file *filep, FAR struct stat *buf, int flags)
{
FAR struct inode *inode;
int ret;
DEBUGASSERT(filep != NULL);
/* Get the inode from the file structure */
inode = filep->f_inode;
DEBUGASSERT(inode != NULL);
/* Adjust and check buf and flags */
if ((flags & CH_STAT_MODE) && (buf->st_mode & ~07777))
{
return -EINVAL;
}
if ((flags & CH_STAT_UID) && buf->st_uid == -1)
{
flags &= ~CH_STAT_UID;
}
if ((flags & CH_STAT_GID) && buf->st_gid == -1)
{
flags &= ~CH_STAT_GID;
}
clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
if (flags & CH_STAT_ATIME)
{
if (buf->st_atim.tv_nsec == UTIME_OMIT)
{
flags &= ~CH_STAT_ATIME;
}
else if (buf->st_atim.tv_nsec == UTIME_NOW)
{
buf->st_atim = buf->st_ctim;
}
else if (buf->st_atim.tv_nsec >= 1000000000)
{
return -EINVAL;
}
}
if (flags & CH_STAT_MTIME)
{
if (buf->st_mtim.tv_nsec == UTIME_OMIT)
{
flags &= ~CH_STAT_MTIME;
}
else if (buf->st_mtim.tv_nsec == UTIME_NOW)
{
buf->st_mtim = buf->st_ctim;
}
else if (buf->st_mtim.tv_nsec >= 1000000000)
{
return -EINVAL;
}
}
/* The way we handle the chstat 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 mountpoint. Verify that the mountpoint
* supports the fchstat() method
*/
if (inode->u.i_mops && inode->u.i_mops->fchstat)
{
/* Perform the fchstat() operation */
ret = inode->u.i_mops->fchstat(filep, buf, flags);
}
else
{
ret = -ENOSYS;
}
}
else
#endif
{
/* The inode is part of the root pseudo file system. */
ret = inode_chstat(inode, buf, flags, 0);
}
return ret;
}
/****************************************************************************
* Name: fchmod
*
* Description:
* The fchmod() function shall be equivalent to chmod() except that the
* file whose permissions are changed is specified by the file descriptor.
*
* Input Parameters:
* fd - Specifies the fd to be modified
* mode - Specifies the permission to set
*
* Returned Value:
* Upon successful completion, fchmod() shall return 0.
* Otherwise, it shall return -1 and set errno to indicate the error.
*
****************************************************************************/
int fchmod(int fd, mode_t mode)
{
struct stat buf;
buf.st_mode = mode;
return fchstat(fd, &buf, CH_STAT_MODE);
}
/****************************************************************************
* Name: fchown
*
* Description:
* The fchown() function shall be equivalent to chown() except that the
* file whose owner and group are changed is specified by the file
* descriptor.
*
* Input Parameters:
* fd - Specifies the fd to be modified
* owner - Specifies the owner to set
* group - Specifies the group to set
*
* Returned Value:
* Upon successful completion, fchown() shall return 0.
* Otherwise, it shall return -1 and set errno to indicate the error.
*
****************************************************************************/
int fchown(int fd, uid_t owner, gid_t group)
{
struct stat buf;
buf.st_uid = owner;
buf.st_gid = group;
return fchstat(fd, &buf, CH_STAT_UID | CH_STAT_GID);
}
/****************************************************************************
* Name: futimens
*
* Description:
* futimens() update the timestamps of a file with nanosecond precision.
* This contrasts with the historical utime(2) and utimes(2), which permit
* only second and microsecond precision, respectively, when setting file
* timestamps.
*
* Input Parameters:
* fd - Specifies the fd to be modified
* times - Specifies the time value to set
*
* Returned Value:
* On success, futimens() return 0.
* On error, -1 is returned and errno is set to indicate the error.
*
****************************************************************************/
int futimens(int fd, FAR const struct timespec times[2])
{
struct stat buf;
if (times != NULL)
{
buf.st_atim = times[0];
buf.st_mtim = times[1];
}
else
{
buf.st_atim.tv_nsec = UTIME_NOW;
buf.st_mtim.tv_nsec = UTIME_NOW;
}
return fchstat(fd, &buf, CH_STAT_ATIME | CH_STAT_MTIME);
}

View file

@ -154,6 +154,16 @@
#define DIRENT_SETPSEUDONODE(f) do (f) |= DIRENTFLAGS_PSEUDONODE; while (0)
#define DIRENT_ISPSEUDONODE(f) (((f) & DIRENTFLAGS_PSEUDONODE) != 0)
/* The status change flags.
* These should be or-ed together to figure out what want to change.
*/
#define CH_STAT_MODE (1 << 0)
#define CH_STAT_UID (1 << 1)
#define CH_STAT_GID (1 << 2)
#define CH_STAT_ATIME (1 << 3)
#define CH_STAT_MTIME (1 << 4)
/* nx_umount() is equivalent to nx_umount2() with flags = 0 */
#define umount(t) umount2(t,0)
@ -276,6 +286,8 @@ 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);
int (*fchstat)(FAR const struct file *filep,
FAR const struct stat *buf, int flags);
int (*truncate)(FAR struct file *filep, off_t length);
/* Directory operations */
@ -307,10 +319,8 @@ struct mountpt_operations
FAR const char *newrelpath);
int (*stat)(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct stat *buf);
/* NOTE: More operations will be needed here to support: disk usage
* stats file stat(), file attributes, file truncation, etc.
*/
int (*chstat)(FAR struct inode *mountpt, FAR const char *relpath,
FAR const struct stat *buf, int flags);
};
#endif /* CONFIG_DISABLE_MOUNTPOINT */
@ -1358,6 +1368,31 @@ int file_fstat(FAR struct file *filep, FAR struct stat *buf);
int nx_stat(FAR const char *path, FAR struct stat *buf, int resolve);
/****************************************************************************
* Name: file_fchstat
*
* Description:
* file_fchstat() is an internal OS interface. It is functionally similar
* to the combination of fchmod/fchown/futimens standard interface except:
*
* - It does not modify the errno variable,
* - It is not a cancellation point,
* - It does not handle socket descriptors, and
* - It accepts a file structure instance instead of file descriptor.
*
* Input Parameters:
* filep - File structure instance
* buf - The stat to be modified
* flags - The vaild field in buf
*
* Returned Value:
* Upon successful completion, 0 shall be returned. Otherwise, the
* negative errno shall be returned to indicate the error.
*
****************************************************************************/
int file_fchstat(FAR struct file *filep, FAR struct stat *buf, int flags);
/****************************************************************************
* Name: nx_unlink
*

View file

@ -107,6 +107,11 @@
#define S_TYPEISMQ(buf) S_ISMQ((buf)->st_mode)
#define S_TYPEISSHM(buf) S_ISSHM((buf)->st_mode)
/* Special value for tv_nsec field of timespec */
#define UTIME_NOW ((1l << 30) - 1l)
#define UTIME_OMIT ((1l << 30) - 2l)
/* The following macros are required by POSIX to achieve backward
* compatibility with earlier versions of struct stat.
*/
@ -162,6 +167,7 @@ int stat(FAR const char *path, FAR struct stat *buf);
int lstat(FAR const char *path, FAR struct stat *buf);
int fstat(int fd, FAR struct stat *buf);
int chmod(FAR const char *path, mode_t mode);
int lchmod(FAR const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
int futimens(int fd, const struct timespec times[2]);

View file

@ -248,6 +248,15 @@ SYSCALL_LOOKUP(statfs, 2)
SYSCALL_LOOKUP(fstatfs, 2)
SYSCALL_LOOKUP(telldir, 1)
SYSCALL_LOOKUP(sendfile, 4)
SYSCALL_LOOKUP(chmod, 2)
SYSCALL_LOOKUP(lchmod, 2)
SYSCALL_LOOKUP(fchmod, 2)
SYSCALL_LOOKUP(chown, 3)
SYSCALL_LOOKUP(lchown, 3)
SYSCALL_LOOKUP(fchown, 3)
SYSCALL_LOOKUP(utimes, 2)
SYSCALL_LOOKUP(lutimes, 2)
SYSCALL_LOOKUP(futimens, 2)
#if defined(CONFIG_FS_RAMMAP)
SYSCALL_LOOKUP(munmap, 2)

View file

@ -372,6 +372,7 @@ int setitimer(int which, FAR const struct itimerval *value,
****************************************************************************/
int utimes(FAR const char *path, const struct timeval times[2]);
int lutimes(FAR const char *path, const struct timeval times[2]);
/****************************************************************************
* Name: futimes

View file

@ -317,6 +317,7 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes);
ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset);
ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset);
int ftruncate(int fd, off_t length);
int fchown(int fd, uid_t owner, gid_t group);
#ifdef CONFIG_SERIAL_TERMIOS
/* Check if a file descriptor corresponds to a terminal I/O file */
@ -356,6 +357,8 @@ int unlink(FAR const char *pathname);
int truncate(FAR const char *path, off_t length);
int symlink(FAR const char *path1, FAR const char *path2);
ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize);
int chown(FAR const char *path, uid_t owner, gid_t group);
int lchown(FAR const char *path, uid_t owner, gid_t group);
/* Execution of programs from files */

View file

@ -26,9 +26,9 @@ CSRCS += lib_getopt_longonly.c lib_getoptvars.c lib_getoptargp.c
CSRCS += lib_getopterrp.c lib_getoptindp.c lib_getoptoptp.c lib_times.c
CSRCS += lib_alarm.c lib_fstatvfs.c lib_statvfs.c lib_sleep.c lib_nice.c
CSRCS += lib_usleep.c lib_seteuid.c lib_setegid.c lib_geteuid.c lib_getegid.c
CSRCS += lib_setreuid.c lib_setregid.c lib_getrusage.c lib_utime.c lib_utimes.c
CSRCS += lib_setreuid.c lib_setregid.c lib_getrusage.c lib_utime.c
CSRCS += lib_setrlimit.c lib_getrlimit.c lib_setpriority.c lib_getpriority.c
CSRCS += lib_futimes.c lib_futimens.c lib_gethostname.c lib_sethostname.c
CSRCS += lib_futimes.c lib_gethostname.c lib_sethostname.c
ifneq ($(CONFIG_SCHED_USER_IDENTITY),y)
CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c

View file

@ -1,57 +0,0 @@
/****************************************************************************
* libs/libc/unistd/lib_futimens.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/stat.h>
#include <errno.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: futimens
*
* Description:
* futimens() update the timestamps of a file with nanosecond precision.
* This contrasts with the historical utime(2) and utimes(2), which permit
* only second and microsecond precision, respectively, when setting file
* timestamps.
*
* Input Parameters:
* fd - Specifies the fd to be modified
* times - Specifies the time value to set
*
* Returned Value:
* On success, futimens() return 0.
* On error, -1 is returned and errno is set to indicate the error.
*
****************************************************************************/
int futimens(int fd, const struct timespec times[2])
{
set_errno(ENOTSUP);
return ERROR;
}

View file

@ -1,38 +0,0 @@
/****************************************************************************
* libs/libc/unistd/lib_utimes.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/time.h>
#include <errno.h>
/****************************************************************************
* Public Functions
****************************************************************************/
int utimes(FAR const char *path, const struct timeval times[2])
{
set_errno(ENOTSUP);
return ERROR;
}

View file

@ -9,6 +9,8 @@
"atexit","stdlib.h","defined(CONFIG_SCHED_ATEXIT)","int","void (*)(void)"
"bind","sys/socket.h","defined(CONFIG_NET)","int","int","FAR const struct sockaddr *","socklen_t"
"boardctl","sys/boardctl.h","defined(CONFIG_LIB_BOARDCTL)","int","unsigned int","uintptr_t"
"chmod","sys/stat.h","","int","FAR const char *","mode_t"
"chown","unistd.h","","int","FAR const char *","uid_t","gid_t"
"clearenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int"
"clock","time.h","","clock_t"
"clock_getres","time.h","","int","clockid_t","FAR struct timespec *"
@ -24,12 +26,15 @@
"exec","nuttx/binfmt/binfmt.h","!defined(CONFIG_BINFMT_DISABLE) && !defined(CONFIG_BUILD_KERNEL)","int","FAR const char *","FAR char * const *","FAR const struct symtab_s *","int"
"execv","unistd.h","!defined(CONFIG_BINFMT_DISABLE) && defined(CONFIG_LIBC_EXECFUNCS)","int","FAR const char *","FAR char * const []|FAR char * const *"
"exit","stdlib.h","","noreturn","int"
"fchmod","sys/stat.h","","int","int","mode_t"
"fchown","unistd.h","","int","int","uid_t","gid_t"
"fcntl","fcntl.h","","int","int","int","...","int"
"fs_fdopen","nuttx/fs/fs.h","defined(CONFIG_FILE_STREAM)","int","int","int","FAR struct tcb_s *","FAR struct file_struct **"
"fstat","sys/stat.h","","int","int","FAR struct stat *"
"fstatfs","sys/statfs.h","","int","int","FAR struct statfs *"
"fsync","unistd.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","int"
"ftruncate","unistd.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","int","off_t"
"futimens","sys/stat.h","","int","int","const struct timespec [2]|FAR const struct timespec *"
"getenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","FAR char *","FAR const char *"
"getgid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","gid_t"
"gethostname","unistd.h","","int","FAR char *","size_t"
@ -46,9 +51,12 @@
"insmod","nuttx/module.h","defined(CONFIG_MODULE)","FAR void *","FAR const char *","FAR const char *"
"ioctl","sys/ioctl.h","","int","int","int","...","unsigned long"
"kill","signal.h","","int","pid_t","int"
"lchmod","sys/stat.h","","int","FAR const char *","mode_t"
"lchown","unistd.h","","int","FAR const char *","uid_t","gid_t"
"listen","sys/socket.h","defined(CONFIG_NET)","int","int","int"
"lseek","unistd.h","","off_t","int","off_t","int"
"lstat","sys/stat.h","","int","FAR const char *","FAR struct stat *"
"lutimes","sys/time.h","","int","FAR const char *","const struct timeval [2]|FAR const struct timeval *"
"mkdir","sys/stat.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *","mode_t"
"mmap","sys/mman.h","","FAR void *","FAR void *","size_t","int","int","int","off_t"
"modhandle","nuttx/module.h","defined(CONFIG_MODULE)","FAR void *","FAR const char *"
@ -181,6 +189,7 @@
"unlink","unistd.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *"
"unsetenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *"
"up_assert","nuttx/arch.h","","void","FAR const char *","int"
"utimes","sys/time.h","","int","FAR const char *","const struct timeval [2]|FAR const struct timeval *"
"vfork","unistd.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_ARCH_HAVE_VFORK)","pid_t"
"wait","sys/wait.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)","pid_t","FAR int *"
"waitid","sys/wait.h","defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)","int","idtype_t","id_t"," FAR siginfo_t *","int"

Can't render this file because it has a wrong number of fields in line 2.