forked from nuttx/nuttx-update
fs/nfs: Support fchstat and chstat callback
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
580de38832
commit
d7cb4567e6
1 changed files with 199 additions and 21 deletions
|
@ -97,6 +97,8 @@
|
|||
# error "Length of cookie verify in fs_dirent_s is incorrect"
|
||||
#endif
|
||||
|
||||
#define CH_STAT_SIZE (1 << 7)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -115,8 +117,9 @@ static void nfs_semgive(FAR struct nfsmount *nmp);
|
|||
static int nfs_filecreate(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, FAR const char *relpath,
|
||||
mode_t mode);
|
||||
static int nfs_filetruncate(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, off_t length);
|
||||
static int nfs_filechstat(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np,
|
||||
FAR const struct stat *buf, int flags);
|
||||
static int nfs_fileopen(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, FAR const char *relpath,
|
||||
int oflags, mode_t mode);
|
||||
|
@ -131,6 +134,8 @@ static ssize_t nfs_write(FAR struct file *filep, FAR const char *buffer,
|
|||
static int nfs_dup(FAR const struct file *oldp, FAR struct file *newp);
|
||||
static int nfs_fsinfo(FAR struct nfsmount *nmp);
|
||||
static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf);
|
||||
static int nfs_fchstat(FAR const struct file *filep,
|
||||
FAR const struct stat *buf, int flags);
|
||||
static int nfs_truncate(FAR struct file *filep, off_t length);
|
||||
static int nfs_opendir(FAR struct inode *mountpt,
|
||||
FAR const char *relpath, FAR struct fs_dirent_s *dir);
|
||||
|
@ -157,6 +162,8 @@ static int nfs_rename(FAR struct inode *mountpt,
|
|||
static mode_t nfs_stat_mode(unsigned int mode, unsigned int type);
|
||||
static int nfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR struct stat *buf);
|
||||
static int nfs_chstat(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR const struct stat *buf, int flags);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
|
@ -180,7 +187,7 @@ const struct mountpt_operations nfs_operations =
|
|||
NULL, /* sync */
|
||||
nfs_dup, /* dup */
|
||||
nfs_fstat, /* fstat */
|
||||
NULL, /* fchstat */
|
||||
nfs_fchstat, /* fchstat */
|
||||
nfs_truncate, /* truncate */
|
||||
|
||||
nfs_opendir, /* opendir */
|
||||
|
@ -197,7 +204,7 @@ const struct mountpt_operations nfs_operations =
|
|||
nfs_rmdir, /* rmdir */
|
||||
nfs_rename, /* rename */
|
||||
nfs_stat, /* stat */
|
||||
NULL /* chstat */
|
||||
nfs_chstat /* chstat */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -378,24 +385,24 @@ static int nfs_filecreate(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nfs_filetruncate
|
||||
* Name: nfs_filechstat
|
||||
*
|
||||
* Description:
|
||||
* Truncate an open file to length. This is part of the file open logic.
|
||||
* Change the status of an open file. This is part of the file open logic.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negative errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_filetruncate(FAR struct nfsmount *nmp,
|
||||
FAR struct nfsnode *np, off_t length)
|
||||
static int nfs_filechstat(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
|
||||
FAR const struct stat *buf, int flags)
|
||||
{
|
||||
FAR uint32_t *ptr;
|
||||
int reqlen;
|
||||
int ret;
|
||||
|
||||
finfo("Truncating file\n");
|
||||
finfo("Changing file status\n");
|
||||
|
||||
/* Create the SETATTR RPC call arguments */
|
||||
|
||||
|
@ -413,16 +420,83 @@ static int nfs_filetruncate(FAR struct nfsmount *nmp,
|
|||
|
||||
/* Copy the variable-length attributes */
|
||||
|
||||
*ptr++ = nfs_false; /* Don't change mode */
|
||||
*ptr++ = nfs_false; /* Don't change uid */
|
||||
*ptr++ = nfs_false; /* Don't change gid */
|
||||
*ptr++ = nfs_true; /* Use the following size */
|
||||
*ptr++ = txdr_unsigned(length >> 32); /* Truncate to the specified length */
|
||||
*ptr++ = txdr_unsigned(length);
|
||||
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
|
||||
*ptr++ = HTONL(NFSV3SATTRTIME_TOSERVER); /* Use the server's time */
|
||||
*ptr++ = nfs_false; /* No guard value */
|
||||
reqlen += 9 * sizeof(uint32_t);
|
||||
if (flags & CH_STAT_MODE)
|
||||
{
|
||||
*ptr++ = nfs_true;
|
||||
*ptr++ = txdr_unsigned(buf->st_mode);
|
||||
reqlen += 2 * sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = nfs_false;
|
||||
reqlen += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (flags & CH_STAT_UID)
|
||||
{
|
||||
*ptr++ = nfs_true;
|
||||
*ptr++ = txdr_unsigned(buf->st_uid);
|
||||
reqlen += 2 * sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = nfs_false;
|
||||
reqlen += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (flags & CH_STAT_GID)
|
||||
{
|
||||
*ptr++ = nfs_true;
|
||||
*ptr++ = txdr_unsigned(buf->st_gid);
|
||||
reqlen += 2 * sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = nfs_false;
|
||||
reqlen += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (flags & CH_STAT_SIZE)
|
||||
{
|
||||
*ptr++ = nfs_true;
|
||||
txdr_hyper(buf->st_size, ptr);
|
||||
ptr += 2;
|
||||
reqlen += 3 * sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = nfs_false;
|
||||
reqlen += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (flags & CH_STAT_ATIME)
|
||||
{
|
||||
*ptr++ = nfs_true;
|
||||
txdr_nfsv3time(&buf->st_atim, ptr);
|
||||
ptr += 2;
|
||||
reqlen += 3 * sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = nfs_false;
|
||||
reqlen += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (flags & CH_STAT_MTIME)
|
||||
{
|
||||
*ptr++ = nfs_true;
|
||||
txdr_nfsv3time(&buf->st_mtim, ptr);
|
||||
ptr += 2;
|
||||
reqlen += 3 * sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = nfs_false;
|
||||
reqlen += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
*ptr++ = nfs_false; /* No guard value */
|
||||
reqlen += sizeof(uint32_t);
|
||||
|
||||
/* Perform the SETATTR RPC */
|
||||
|
||||
|
@ -549,11 +623,14 @@ static int nfs_fileopen(FAR struct nfsmount *nmp, FAR struct nfsnode *np,
|
|||
|
||||
if ((oflags & (O_TRUNC | O_WRONLY)) == (O_TRUNC | O_WRONLY))
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
/* Truncate the file to zero length. I think we can do this with
|
||||
* the SETATTR call by setting the length to zero.
|
||||
*/
|
||||
|
||||
return nfs_filetruncate(nmp, np, 0);
|
||||
buf.st_size = 0;
|
||||
return nfs_filechstat(nmp, np, &buf, CH_STAT_SIZE);
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
@ -1235,6 +1312,47 @@ static int nfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
|||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nfs_fchstat
|
||||
*
|
||||
* Description:
|
||||
* Change information about an open file associated with the file
|
||||
* structure 'filep'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_fchstat(FAR const struct file *filep,
|
||||
FAR const struct stat *buf, int flags)
|
||||
{
|
||||
FAR struct nfsmount *nmp;
|
||||
FAR struct nfsnode *np;
|
||||
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);
|
||||
|
||||
ret = nfs_semtake(nmp);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Change the file mode, owner, group and time. */
|
||||
|
||||
ret = nfs_filechstat(nmp, np, buf, flags);
|
||||
|
||||
nfs_semgive(nmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nfs_truncate
|
||||
*
|
||||
|
@ -1263,9 +1381,12 @@ static int nfs_truncate(FAR struct file *filep, off_t length)
|
|||
ret = nfs_semtake(nmp);
|
||||
if (ret >= 0)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
/* Then perform the SETATTR RPC to set the new file size */
|
||||
|
||||
ret = nfs_filetruncate(nmp, np, length);
|
||||
buf.st_size = length;
|
||||
ret = nfs_filechstat(nmp, np, &buf, CH_STAT_SIZE);
|
||||
|
||||
nfs_semgive(nmp);
|
||||
}
|
||||
|
@ -2730,3 +2851,60 @@ errout_with_semaphore:
|
|||
nfs_semgive(nmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nfs_chstat
|
||||
*
|
||||
* Description:
|
||||
* Change information about the file system object at 'relpath'
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nfs_chstat(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR const struct stat *buf, int flags)
|
||||
{
|
||||
FAR struct nfsmount *nmp;
|
||||
struct file_handle fhandle;
|
||||
struct nfsnode np;
|
||||
int ret;
|
||||
|
||||
/* 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);
|
||||
|
||||
ret = nfs_semtake(nmp);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the file handle of the requested node */
|
||||
|
||||
ret = nfs_findnode(nmp, relpath, &fhandle, NULL, NULL);
|
||||
if (ret != OK)
|
||||
{
|
||||
ferr("ERROR: nfs_findnode failed: %d\n", ret);
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Initialize the nfs node */
|
||||
|
||||
np.n_fhsize = (uint8_t)fhandle.length;
|
||||
memcpy(&np.n_fhandle, &fhandle.handle, fhandle.length);
|
||||
|
||||
/* Change the file mode, owner, group and time. */
|
||||
|
||||
ret = nfs_filechstat(nmp, &np, buf, flags);
|
||||
|
||||
errout_with_semaphore:
|
||||
nfs_semgive(nmp);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue