292 lines
7.7 KiB
C
292 lines
7.7 KiB
C
/****************************************************************************
|
|
* 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 "notify/notify.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);
|
|
fs_putfilep(filep);
|
|
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 valid 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_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);
|
|
}
|
|
|
|
#ifdef CONFIG_FS_NOTIFY
|
|
if (ret >= 0)
|
|
{
|
|
notify_chstat(filep);
|
|
}
|
|
#endif
|
|
|
|
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 & 0777;
|
|
|
|
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);
|
|
}
|