fs/userfs: Support fchstat and chstat callback
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
9d96c54b1b
commit
a09f262f1e
|
@ -131,6 +131,11 @@ static int userfs_rename(FAR struct inode *mountpt,
|
|||
FAR const char *oldrelpath, FAR const char *newrelpath);
|
||||
static int userfs_stat(FAR struct inode *mountpt,
|
||||
FAR const char *relpath, FAR struct stat *buf);
|
||||
static int userfs_fchstat(FAR const struct file *filep,
|
||||
FAR const struct stat *buf, int flags);
|
||||
static int userfs_chstat(FAR struct inode *mountpt,
|
||||
FAR const char *relpath,
|
||||
FAR const struct stat *buf, int flags);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
|
@ -153,7 +158,7 @@ const struct mountpt_operations userfs_operations =
|
|||
userfs_sync, /* sync */
|
||||
userfs_dup, /* dup */
|
||||
userfs_fstat, /* fstat */
|
||||
NULL, /* fchstat */
|
||||
userfs_fchstat, /* fchstat */
|
||||
userfs_truncate, /* truncate */
|
||||
|
||||
userfs_opendir, /* opendir */
|
||||
|
@ -170,7 +175,7 @@ const struct mountpt_operations userfs_operations =
|
|||
userfs_rmdir, /* rmdir */
|
||||
userfs_rename, /* rename */
|
||||
userfs_stat, /* stat */
|
||||
NULL /* chstat */
|
||||
userfs_chstat /* chstat */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -899,6 +904,85 @@ static int userfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
|
|||
return resp->ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: userfs_fchstat
|
||||
*
|
||||
* Description:
|
||||
* Change information about an open file associated with the file
|
||||
* descriptor 'filep'.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int userfs_fchstat(FAR const struct file *filep,
|
||||
FAR const struct stat *buf, int flags)
|
||||
{
|
||||
FAR struct userfs_state_s *priv;
|
||||
FAR struct userfs_fchstat_request_s *req;
|
||||
FAR struct userfs_fchstat_response_s *resp;
|
||||
ssize_t nsent;
|
||||
ssize_t nrecvd;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(filep != NULL &&
|
||||
filep->f_inode != NULL &&
|
||||
filep->f_inode->i_private != NULL);
|
||||
priv = filep->f_inode->i_private;
|
||||
|
||||
/* Get exclusive access */
|
||||
|
||||
ret = nxsem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Construct and send the request to the server */
|
||||
|
||||
req = (FAR struct userfs_fchstat_request_s *)priv->iobuffer;
|
||||
req->req = USERFS_REQ_FCHSTAT;
|
||||
req->openinfo = filep->f_priv;
|
||||
req->buf = *buf;
|
||||
req->flags = flags;
|
||||
|
||||
nsent = psock_sendto(&priv->psock, priv->iobuffer,
|
||||
sizeof(struct userfs_fchstat_request_s), 0,
|
||||
(FAR struct sockaddr *)&priv->server,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (nsent < 0)
|
||||
{
|
||||
ferr("ERROR: psock_sendto failed: %zd\n", nsent);
|
||||
nxsem_post(&priv->exclsem);
|
||||
return (int)nsent;
|
||||
}
|
||||
|
||||
/* Then get the response from the server */
|
||||
|
||||
nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
|
||||
0, NULL, NULL);
|
||||
nxsem_post(&priv->exclsem);
|
||||
|
||||
if (nrecvd < 0)
|
||||
{
|
||||
ferr("ERROR: psock_recvfrom failed: %zd\n", nrecvd);
|
||||
return (int)nrecvd;
|
||||
}
|
||||
|
||||
if (nrecvd != sizeof(struct userfs_fchstat_response_s))
|
||||
{
|
||||
ferr("ERROR: Response size incorrect: %zd\n", nrecvd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
resp = (FAR struct userfs_fchstat_response_s *)priv->iobuffer;
|
||||
if (resp->resp != USERFS_RESP_FCHSTAT)
|
||||
{
|
||||
ferr("ERROR: Incorrect response: %u\n", resp->resp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return resp->ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: userfs_truncate
|
||||
*
|
||||
|
@ -1986,6 +2070,94 @@ static int userfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
|
|||
return resp->ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: userfs_chstat
|
||||
*
|
||||
* Description:
|
||||
* Change information about a file or directory
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int userfs_chstat(FAR struct inode *mountpt, FAR const char *relpath,
|
||||
FAR const struct stat *buf, int flags)
|
||||
{
|
||||
FAR struct userfs_state_s *priv;
|
||||
FAR struct userfs_chstat_request_s *req;
|
||||
FAR struct userfs_chstat_response_s *resp;
|
||||
ssize_t nsent;
|
||||
ssize_t nrecvd;
|
||||
int pathlen;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(mountpt != NULL &&
|
||||
mountpt->i_private != NULL);
|
||||
priv = mountpt->i_private;
|
||||
|
||||
/* Check the path length */
|
||||
|
||||
DEBUGASSERT(relpath != NULL);
|
||||
pathlen = strlen(relpath);
|
||||
if (pathlen > priv->mxwrite)
|
||||
{
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
/* Get exclusive access */
|
||||
|
||||
ret = nxsem_wait(&priv->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Construct and send the request to the server */
|
||||
|
||||
req = (FAR struct userfs_chstat_request_s *)priv->iobuffer;
|
||||
req->req = USERFS_REQ_CHSTAT;
|
||||
req->buf = *buf;
|
||||
req->flags = flags;
|
||||
|
||||
strncpy(req->relpath, relpath, priv->mxwrite);
|
||||
|
||||
nsent = psock_sendto(&priv->psock, priv->iobuffer,
|
||||
SIZEOF_USERFS_CHSTAT_REQUEST_S(pathlen + 1), 0,
|
||||
(FAR struct sockaddr *)&priv->server,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (nsent < 0)
|
||||
{
|
||||
ferr("ERROR: psock_sendto failed: %zd\n", nsent);
|
||||
nxsem_post(&priv->exclsem);
|
||||
return (int)nsent;
|
||||
}
|
||||
|
||||
/* Then get the response from the server */
|
||||
|
||||
nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
|
||||
0, NULL, NULL);
|
||||
nxsem_post(&priv->exclsem);
|
||||
|
||||
if (nrecvd < 0)
|
||||
{
|
||||
ferr("ERROR: psock_recvfrom failed: %zd\n", nrecvd);
|
||||
return (int)nrecvd;
|
||||
}
|
||||
|
||||
if (nrecvd != sizeof(struct userfs_chstat_response_s))
|
||||
{
|
||||
ferr("ERROR: Response size incorrect: %zd\n", nrecvd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
resp = (FAR struct userfs_chstat_response_s *)priv->iobuffer;
|
||||
if (resp->resp != USERFS_RESP_STAT)
|
||||
{
|
||||
ferr("ERROR: Incorrect response: %u\n", resp->resp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return resp->ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
|
@ -136,7 +136,9 @@ enum userfs_req_e
|
|||
USERFS_REQ_RMDIR,
|
||||
USERFS_REQ_RENAME,
|
||||
USERFS_REQ_STAT,
|
||||
USERFS_REQ_DESTROY
|
||||
USERFS_REQ_DESTROY,
|
||||
USERFS_REQ_FCHSTAT,
|
||||
USERFS_REQ_CHSTAT
|
||||
};
|
||||
|
||||
/* This enumeration provides the type of each response returned from the
|
||||
|
@ -164,7 +166,9 @@ enum userfs_resp_e
|
|||
USERFS_RESP_RMDIR,
|
||||
USERFS_RESP_RENAME,
|
||||
USERFS_RESP_STAT,
|
||||
USERFS_RESP_DESTROY
|
||||
USERFS_RESP_DESTROY,
|
||||
USERFS_RESP_FCHSTAT,
|
||||
USERFS_RESP_CHSTAT
|
||||
};
|
||||
|
||||
/* These structures are used by internal UserFS implementation and should not
|
||||
|
@ -218,6 +222,10 @@ struct userfs_operations_s
|
|||
int (*stat)(FAR void *volinfo, FAR const char *relpath,
|
||||
FAR struct stat *buf);
|
||||
int (*destroy)(FAR void *volinfo);
|
||||
int (*fchstat)(FAR void *volinfo, FAR void *openinfo,
|
||||
FAR const struct stat *buf, int flags);
|
||||
int (*chstat)(FAR void *volinfo, FAR const char *relpath,
|
||||
FAR const struct stat *buf, int flags);
|
||||
};
|
||||
|
||||
/* The following structures describe the header on the marshaled data sent
|
||||
|
@ -513,6 +521,36 @@ struct userfs_destroy_response_s
|
|||
int ret; /* Result of the operation */
|
||||
};
|
||||
|
||||
struct userfs_fchstat_request_s
|
||||
{
|
||||
uint8_t req; /* Must be USERFS_REQ_FCHSTAT */
|
||||
FAR void *openinfo; /* Open file info as returned by open() */
|
||||
struct stat buf; /* File system status */
|
||||
int flags; /* The status to be change */
|
||||
};
|
||||
|
||||
struct userfs_fchstat_response_s
|
||||
{
|
||||
uint8_t resp; /* Must be USERFS_RESP_FCHSTAT */
|
||||
int ret; /* Result of the operation */
|
||||
};
|
||||
|
||||
struct userfs_chstat_request_s
|
||||
{
|
||||
uint8_t req; /* Must be USERFS_REQ_CHSTAT */
|
||||
struct stat buf; /* File system status */
|
||||
int flags; /* The status to be change */
|
||||
char relpath[1]; /* Relative path to the directory entry to be changed */
|
||||
};
|
||||
|
||||
#define SIZEOF_USERFS_CHSTAT_REQUEST_S(n) (sizeof(struct userfs_chstat_request_s) + (n) - 1)
|
||||
|
||||
struct userfs_chstat_response_s
|
||||
{
|
||||
uint8_t resp; /* Must be USERFS_RESP_CHSTAT */
|
||||
int ret; /* Result of the operation */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
|
|
@ -864,6 +864,78 @@ static inline int userfs_destroy_dispatch(FAR struct userfs_info_s *info,
|
|||
return resp.ret < 0 ? OK : -ENOTCONN;
|
||||
}
|
||||
|
||||
static inline int userfs_fchstat_dispatch(FAR struct userfs_info_s *info,
|
||||
FAR struct userfs_fchstat_request_s *req, size_t reqlen)
|
||||
{
|
||||
struct userfs_fchstat_response_s resp;
|
||||
ssize_t nsent;
|
||||
|
||||
/* Verify the request size */
|
||||
|
||||
if (reqlen != sizeof(struct userfs_fchstat_request_s))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->fchstat != NULL);
|
||||
resp.ret = info->userops->fchstat(info->volinfo, req->openinfo,
|
||||
&req->buf, req->flags);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_FCHSTAT;
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_fchstat_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
static inline int userfs_chstat_dispatch(FAR struct userfs_info_s *info,
|
||||
FAR struct userfs_chstat_request_s *req, size_t reqlen)
|
||||
{
|
||||
struct userfs_chstat_response_s resp;
|
||||
int pathlen;
|
||||
size_t expected;
|
||||
ssize_t nsent;
|
||||
|
||||
/* Verify the request size */
|
||||
|
||||
if (reqlen < SIZEOF_USERFS_CHSTAT_REQUEST_S(0))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pathlen = strlen(req->relpath);
|
||||
if (pathlen > info->mxwrite)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
expected = SIZEOF_USERFS_CHSTAT_REQUEST_S(pathlen);
|
||||
if (expected >= reqlen)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Dispatch the request */
|
||||
|
||||
DEBUGASSERT(info->userops != NULL && info->userops->chstat != NULL);
|
||||
resp.ret = info->userops->chstat(info->volinfo, req->relpath,
|
||||
&req->buf, req->flags);
|
||||
|
||||
/* Send the response */
|
||||
|
||||
resp.resp = USERFS_RESP_CHSTAT;
|
||||
nsent = sendto(info->sockfd, &resp,
|
||||
sizeof(struct userfs_chstat_response_s),
|
||||
0, (FAR struct sockaddr *)&info->client,
|
||||
sizeof(struct sockaddr_in));
|
||||
return nsent < 0 ? nsent : OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -1136,6 +1208,18 @@ int userfs_run(FAR const char *mountpt,
|
|||
nread);
|
||||
break;
|
||||
|
||||
case USERFS_REQ_FCHSTAT:
|
||||
ret = userfs_fchstat_dispatch(info,
|
||||
(FAR struct userfs_fchstat_request_s *)info->iobuffer,
|
||||
nread);
|
||||
break;
|
||||
|
||||
case USERFS_REQ_CHSTAT:
|
||||
ret = userfs_chstat_dispatch(info,
|
||||
(FAR struct userfs_chstat_request_s *)info->iobuffer,
|
||||
nread);
|
||||
break;
|
||||
|
||||
default:
|
||||
ferr("ERROR: Unrecognized request received: %u\n",
|
||||
*info->iobuffer);
|
||||
|
|
Loading…
Reference in New Issue