fs/hostfs: Support fchstat and chstat callback

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2021-08-09 16:33:05 +08:00 committed by Gustavo Henrique Nihei
parent 6c61d032db
commit 776458143c
9 changed files with 403 additions and 7 deletions

View File

@ -221,6 +221,11 @@ int host_fstat(int fd, struct stat *buf)
return buf->st_size < 0 ? buf->st_size : 0; return buf->st_size < 0 ? buf->st_size : 0;
} }
int host_fchstat(int fd, const struct stat *buf, int flags)
{
return -ENOSYS;
}
int host_ftruncate(int fd, off_t length) int host_ftruncate(int fd, off_t length)
{ {
return -ENOSYS; return -ENOSYS;
@ -315,3 +320,8 @@ int host_stat(const char *path, struct stat *buf)
return ret; return ret;
} }
int host_chstat(const char *path, const struct stat *buf, int flags)
{
return -ENOSYS;
}

View File

@ -34,6 +34,8 @@ NXSYMBOLS(__cxa_atexit)
NXSYMBOLS(atexit) NXSYMBOLS(atexit)
NXSYMBOLS(bind) NXSYMBOLS(bind)
NXSYMBOLS(calloc) NXSYMBOLS(calloc)
NXSYMBOLS(chmod)
NXSYMBOLS(chown)
NXSYMBOLS(clock_gettime) NXSYMBOLS(clock_gettime)
NXSYMBOLS(close) NXSYMBOLS(close)
NXSYMBOLS(closedir) NXSYMBOLS(closedir)
@ -41,10 +43,13 @@ NXSYMBOLS(connect)
NXSYMBOLS(dlsym) NXSYMBOLS(dlsym)
NXSYMBOLS(dup) NXSYMBOLS(dup)
NXSYMBOLS(exit) NXSYMBOLS(exit)
NXSYMBOLS(fchmod)
NXSYMBOLS(fchown)
NXSYMBOLS(free) NXSYMBOLS(free)
NXSYMBOLS(fstat) NXSYMBOLS(fstat)
NXSYMBOLS(fsync) NXSYMBOLS(fsync)
NXSYMBOLS(ftruncate) NXSYMBOLS(ftruncate)
NXSYMBOLS(futimens)
NXSYMBOLS(if_nametoindex) NXSYMBOLS(if_nametoindex)
NXSYMBOLS(ioctl) NXSYMBOLS(ioctl)
NXSYMBOLS(longjmp) NXSYMBOLS(longjmp)
@ -105,5 +110,6 @@ NXSYMBOLS(tcgetattr)
NXSYMBOLS(tcsetattr) NXSYMBOLS(tcsetattr)
NXSYMBOLS(unlink) NXSYMBOLS(unlink)
NXSYMBOLS(usleep) NXSYMBOLS(usleep)
NXSYMBOLS(utimensat)
NXSYMBOLS(write) NXSYMBOLS(write)
NXSYMBOLS(writev) NXSYMBOLS(writev)

View File

@ -312,6 +312,65 @@ int host_fstat(int fd, struct nuttx_stat_s *buf)
return ret; return ret;
} }
/****************************************************************************
* Name: host_fchstat
****************************************************************************/
int host_fchstat(int fd, const struct nuttx_stat_s *buf, int flags)
{
struct timespec times[2];
int ret;
if (flags & NUTTX_CH_STAT_MODE)
{
ret = fchmod(fd, buf->st_mode);
if (ret < 0)
{
return -errno;
}
}
if (flags & (NUTTX_CH_STAT_UID | NUTTX_CH_STAT_GID))
{
ret = fchown(fd, buf->st_uid, buf->st_gid);
if (ret < 0)
{
return -errno;
}
}
if (flags & (NUTTX_CH_STAT_ATIME | NUTTX_CH_STAT_MTIME))
{
if (flags & NUTTX_CH_STAT_ATIME)
{
times[0].tv_sec = buf->st_atim.tv_sec;
times[0].tv_nsec = buf->st_atim.tv_nsec;
}
else
{
times[0].tv_nsec = UTIME_OMIT;
}
if (flags & NUTTX_CH_STAT_MTIME)
{
times[1].tv_sec = buf->st_mtim.tv_sec;
times[1].tv_nsec = buf->st_mtim.tv_nsec;
}
else
{
times[1].tv_nsec = UTIME_OMIT;
}
ret = futimens(fd, times);
if (ret < 0)
{
return -errno;
}
}
return 0;
}
/**************************************************************************** /****************************************************************************
* Name: host_truncate * Name: host_truncate
****************************************************************************/ ****************************************************************************/
@ -538,3 +597,62 @@ int host_stat(const char *path, struct nuttx_stat_s *buf)
host_stat_convert(&hostbuf, buf); host_stat_convert(&hostbuf, buf);
return ret; return ret;
} }
/****************************************************************************
* Name: host_chstat
****************************************************************************/
int host_chstat(const char *path, const struct nuttx_stat_s *buf, int flags)
{
struct timespec times[2];
int ret;
if (flags & NUTTX_CH_STAT_MODE)
{
ret = chmod(path, buf->st_mode);
if (ret < 0)
{
return -errno;
}
}
if (flags & (NUTTX_CH_STAT_UID | NUTTX_CH_STAT_GID))
{
ret = chown(path, buf->st_uid, buf->st_gid);
if (ret < 0)
{
return -errno;
}
}
if (flags & (NUTTX_CH_STAT_ATIME | NUTTX_CH_STAT_MTIME))
{
if (flags & NUTTX_CH_STAT_ATIME)
{
times[0].tv_sec = buf->st_atim.tv_sec;
times[0].tv_nsec = buf->st_atim.tv_nsec;
}
else
{
times[0].tv_nsec = UTIME_OMIT;
}
if (flags & NUTTX_CH_STAT_MTIME)
{
times[1].tv_sec = buf->st_mtim.tv_sec;
times[1].tv_nsec = buf->st_mtim.tv_nsec;
}
else
{
times[1].tv_nsec = UTIME_OMIT;
}
ret = utimensat(AT_FDCWD, path, times, 0);
if (ret < 0)
{
return -errno;
}
}
return 0;
}

View File

@ -153,6 +153,11 @@ int host_fstat(int fd, struct stat *buf)
return 0; return 0;
} }
int host_fchstat(int fd, const struct stat *buf, int flags)
{
return -ENOSYS;
}
int host_ftruncate(int fd, off_t length) int host_ftruncate(int fd, off_t length)
{ {
return -ENOSYS; return -ENOSYS;
@ -225,3 +230,8 @@ int host_stat(const char *path, struct stat *buf)
return ret; return ret;
} }
int host_chstat(const char *path, const struct stat *buf, int flags)
{
return -ENOSYS;
}

View File

@ -72,6 +72,8 @@ static int hostfs_dup(FAR const struct file *oldp,
FAR struct file *newp); FAR struct file *newp);
static int hostfs_fstat(FAR const struct file *filep, static int hostfs_fstat(FAR const struct file *filep,
FAR struct stat *buf); FAR struct stat *buf);
static int hostfs_fchstat(FAR const struct file *filep,
FAR const struct stat *buf, int flags);
static int hostfs_ftruncate(FAR struct file *filep, static int hostfs_ftruncate(FAR struct file *filep,
off_t length); off_t length);
@ -102,6 +104,9 @@ static int hostfs_rename(FAR struct inode *mountpt,
FAR const char *newrelpath); FAR const char *newrelpath);
static int hostfs_stat(FAR struct inode *mountpt, static int hostfs_stat(FAR struct inode *mountpt,
FAR const char *relpath, FAR struct stat *buf); FAR const char *relpath, FAR struct stat *buf);
static int hostfs_chstat(FAR struct inode *mountpt,
FAR const char *relpath,
FAR const struct stat *buf, int flags);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@ -131,7 +136,7 @@ const struct mountpt_operations hostfs_operations =
hostfs_sync, /* sync */ hostfs_sync, /* sync */
hostfs_dup, /* dup */ hostfs_dup, /* dup */
hostfs_fstat, /* fstat */ hostfs_fstat, /* fstat */
NULL, /* fchstat */ hostfs_fchstat, /* fchstat */
hostfs_ftruncate, /* ftruncate */ hostfs_ftruncate, /* ftruncate */
hostfs_opendir, /* opendir */ hostfs_opendir, /* opendir */
@ -148,7 +153,7 @@ const struct mountpt_operations hostfs_operations =
hostfs_rmdir, /* rmdir */ hostfs_rmdir, /* rmdir */
hostfs_rename, /* rename */ hostfs_rename, /* rename */
hostfs_stat, /* stat */ hostfs_stat, /* stat */
NULL /* chstat */ hostfs_chstat, /* chstat */
}; };
/**************************************************************************** /****************************************************************************
@ -739,6 +744,52 @@ static int hostfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
return ret; return ret;
} }
/****************************************************************************
* Name: hostfs_fchstat
*
* Description:
* Change information about an open file associated with the file
* descriptor 'fd'.
*
****************************************************************************/
static int hostfs_fchstat(FAR const struct file *filep,
FAR const struct stat *buf, int flags)
{
FAR struct inode *inode;
FAR struct hostfs_mountpt_s *fs;
FAR struct hostfs_ofile_s *hf;
int ret = OK;
/* Sanity checks */
DEBUGASSERT(filep != NULL && buf != NULL);
/* Recover our private data from the struct file instance */
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
hf = filep->f_priv;
inode = filep->f_inode;
fs = inode->i_private;
DEBUGASSERT(fs != NULL);
/* Take the semaphore */
ret = hostfs_semtake(fs);
if (ret < 0)
{
return ret;
}
/* Call the host to perform the change */
ret = host_fchstat(hf->fd, buf, flags);
hostfs_semgive(fs);
return ret;
}
/**************************************************************************** /****************************************************************************
* Name: hostfs_ftruncate * Name: hostfs_ftruncate
* *
@ -1329,6 +1380,46 @@ static int hostfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
return ret; return ret;
} }
/****************************************************************************
* Name: hostfs_chstat
*
* Description: Change information about a file or directory
*
****************************************************************************/
static int hostfs_chstat(FAR struct inode *mountpt, FAR const char *relpath,
FAR const struct stat *buf, int flags)
{
FAR struct hostfs_mountpt_s *fs;
char path[HOSTFS_MAX_PATH];
int ret;
/* Sanity checks */
DEBUGASSERT(mountpt && mountpt->i_private);
/* Get the mountpoint private data from the inode structure */
fs = mountpt->i_private;
ret = hostfs_semtake(fs);
if (ret < 0)
{
return ret;
}
/* Append to the host's root directory */
hostfs_mkpath(fs, relpath, path, sizeof(path));
/* Call the host FS to do the chstat operation */
ret = host_chstat(path, buf, flags);
hostfs_semgive(fs);
return ret;
}
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/

View File

@ -111,6 +111,8 @@ static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] =
[HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_default_handler, [HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_default_handler,
[HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_default_handler, [HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_default_handler,
[HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler, [HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler,
[HOSTFS_RPMSG_FCHSTAT] = hostfs_rpmsg_default_handler,
[HOSTFS_RPMSG_CHSTAT] = hostfs_rpmsg_default_handler,
}; };
/**************************************************************************** /****************************************************************************
@ -721,6 +723,45 @@ int host_stat(FAR const char *path, FAR struct stat *buf)
(struct hostfs_rpmsg_header_s *)msg, len, buf); (struct hostfs_rpmsg_header_s *)msg, len, buf);
} }
int host_fchstat(int fd, const struct stat *buf, int flags)
{
struct hostfs_rpmsg_fchstat_s msg =
{
.flags = flags,
.buf = *buf,
.fd = fd,
};
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FCHSTAT, true,
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
}
int host_chstat(FAR const char *path, const FAR struct stat *buf, int flags)
{
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
FAR struct hostfs_rpmsg_chstat_s *msg;
uint32_t space;
size_t len;
len = sizeof(*msg);
len += B2C(strlen(path) + 1);
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
if (!msg)
{
return -ENOMEM;
}
DEBUGASSERT(len <= space);
msg->flags = flags;
memcpy(&msg->buf, buf, sizeof(*buf));
cstr2bstr(msg->pathname, path);
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CHSTAT, false,
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
}
int hostfs_rpmsg_init(FAR const char *cpuname) int hostfs_rpmsg_init(FAR const char *cpuname)
{ {
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;

View File

@ -58,6 +58,8 @@
#define HOSTFS_RPMSG_RMDIR 18 #define HOSTFS_RPMSG_RMDIR 18
#define HOSTFS_RPMSG_RENAME 19 #define HOSTFS_RPMSG_RENAME 19
#define HOSTFS_RPMSG_STAT 20 #define HOSTFS_RPMSG_STAT 20
#define HOSTFS_RPMSG_FCHSTAT 21
#define HOSTFS_RPMSG_CHSTAT 22
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
@ -179,4 +181,23 @@ begin_packed_struct struct hostfs_rpmsg_mkdir_s
#define hostfs_rpmsg_rename_s hostfs_rpmsg_opendir_s #define hostfs_rpmsg_rename_s hostfs_rpmsg_opendir_s
#define hostfs_rpmsg_stat_s hostfs_rpmsg_fstat_s #define hostfs_rpmsg_stat_s hostfs_rpmsg_fstat_s
begin_packed_struct struct hostfs_rpmsg_fchstat_s
{
struct hostfs_rpmsg_header_s header;
int32_t flags;
union
{
struct stat buf;
uint32_t reserved[16];
};
union
{
int32_t fd;
char pathname[0];
};
} end_packed_struct;
#define hostfs_rpmsg_chstat_s hostfs_rpmsg_fchstat_s
#endif /* __FS_HOSTFS_HOSTFS_RPMSG_H */ #endif /* __FS_HOSTFS_HOSTFS_RPMSG_H */

View File

@ -116,6 +116,12 @@ static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept,
static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len, FAR void *data, size_t len,
uint32_t src, FAR void *priv); uint32_t src, FAR void *priv);
static int hostfs_rpmsg_fchstat_handler(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len,
uint32_t src, FAR void *priv);
static int hostfs_rpmsg_chstat_handler(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len,
uint32_t src, FAR void *priv);
static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev,
FAR void *priv_, FAR const char *name, FAR void *priv_, FAR const char *name,
@ -151,6 +157,8 @@ static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] =
[HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_rmdir_handler, [HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_rmdir_handler,
[HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_rename_handler, [HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_rename_handler,
[HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler, [HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler,
[HOSTFS_RPMSG_FCHSTAT] = hostfs_rpmsg_fchstat_handler,
[HOSTFS_RPMSG_CHSTAT] = hostfs_rpmsg_chstat_handler,
}; };
/**************************************************************************** /****************************************************************************
@ -704,6 +712,87 @@ static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept,
return rpmsg_send(ept, msg, sizeof(*msg)); return rpmsg_send(ept, msg, sizeof(*msg));
} }
static int hostfs_rpmsg_fchstat_handler(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len,
uint32_t src, FAR void *priv)
{
FAR struct hostfs_rpmsg_fchstat_s *msg = data;
FAR struct file *filep;
int ret = -ENOENT;
struct stat buf;
filep = hostfs_rpmsg_get_file(priv, msg->fd);
if (filep != NULL)
{
buf = msg->buf;
ret = file_fchstat(filep, &buf, msg->flags);
}
msg->header.result = ret;
return rpmsg_send(ept, msg, sizeof(*msg));
}
static int hostfs_rpmsg_chstat_handler(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len,
uint32_t src, FAR void *priv)
{
FAR struct hostfs_rpmsg_chstat_s *msg = data;
struct timespec times[2];
int ret = 0;
if (msg->flags & CH_STAT_MODE)
{
ret = chmod(msg->pathname, msg->buf.st_mode);
if (ret < 0)
{
ret = -get_errno();
goto out;
}
}
if (msg->flags & (CH_STAT_UID | CH_STAT_GID))
{
ret = chown(msg->pathname, msg->buf.st_uid, msg->buf.st_gid);
if (ret < 0)
{
ret = -get_errno();
goto out;
}
}
if (msg->flags & (CH_STAT_ATIME | CH_STAT_MTIME))
{
if (msg->flags & CH_STAT_ATIME)
{
times[0] = msg->buf.st_atim;
}
else
{
times[0].tv_nsec = UTIME_OMIT;
}
if (msg->flags & CH_STAT_MTIME)
{
times[1] = msg->buf.st_mtim;
}
else
{
times[1].tv_nsec = UTIME_OMIT;
}
ret = utimens(msg->pathname, times);
if (ret < 0)
{
ret = -get_errno();
goto out;
}
}
out:
msg->header.result = ret;
return rpmsg_send(ept, msg, sizeof(*msg));
}
static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev,
FAR void *priv_, FAR const char *name, FAR void *priv_, FAR const char *name,
uint32_t dest) uint32_t dest)

View File

@ -87,9 +87,13 @@
#define NUTTX_O_RDWR (NUTTX_O_RDONLY | NUTTX_O_WRONLY) #define NUTTX_O_RDWR (NUTTX_O_RDONLY | NUTTX_O_WRONLY)
/* Should match definition in include/limits.h */ /* Should match definition in include/nuttx/fs/fs.h */
#define NUTTX_NAME_MAX CONFIG_NAME_MAX #define NUTTX_CH_STAT_MODE (1 << 0)
#define NUTTX_CH_STAT_UID (1 << 1)
#define NUTTX_CH_STAT_GID (1 << 2)
#define NUTTX_CH_STAT_ATIME (1 << 3)
#define NUTTX_CH_STAT_MTIME (1 << 4)
#endif /* __SIM__ */ #endif /* __SIM__ */
@ -132,8 +136,8 @@ struct nuttx_timespec
struct nuttx_dirent_s struct nuttx_dirent_s
{ {
uint8_t d_type; /* type of file */ uint8_t d_type; /* type of file */
char d_name[NUTTX_NAME_MAX + 1]; /* filename */ char d_name[CONFIG_NAME_MAX + 1]; /* filename */
}; };
/* These must exactly match the definition from include/sys/statfs.h: */ /* These must exactly match the definition from include/sys/statfs.h: */
@ -185,6 +189,8 @@ int host_ioctl(int fd, int request, unsigned long arg);
void host_sync(int fd); void host_sync(int fd);
int host_dup(int fd); int host_dup(int fd);
int host_fstat(int fd, struct nuttx_stat_s *buf); int host_fstat(int fd, struct nuttx_stat_s *buf);
int host_fchstat(int fd, const struct nuttx_stat_s *buf,
int flags);
int host_ftruncate(int fd, nuttx_off_t length); int host_ftruncate(int fd, nuttx_off_t length);
void *host_opendir(const char *name); void *host_opendir(const char *name);
int host_readdir(void *dirp, struct nuttx_dirent_s *entry); int host_readdir(void *dirp, struct nuttx_dirent_s *entry);
@ -196,6 +202,8 @@ int host_mkdir(const char *pathname, mode_t mode);
int host_rmdir(const char *pathname); int host_rmdir(const char *pathname);
int host_rename(const char *oldpath, const char *newpath); int host_rename(const char *oldpath, const char *newpath);
int host_stat(const char *path, struct nuttx_stat_s *buf); int host_stat(const char *path, struct nuttx_stat_s *buf);
int host_chstat(const char *path,
const struct nuttx_stat_s *buf, int flags);
#else #else
int host_open(const char *pathname, int flags, int mode); int host_open(const char *pathname, int flags, int mode);
int host_close(int fd); int host_close(int fd);
@ -206,6 +214,7 @@ int host_ioctl(int fd, int request, unsigned long arg);
void host_sync(int fd); void host_sync(int fd);
int host_dup(int fd); int host_dup(int fd);
int host_fstat(int fd, struct stat *buf); int host_fstat(int fd, struct stat *buf);
int host_fchstat(int fd, const struct stat *buf, int flags);
int host_ftruncate(int fd, off_t length); int host_ftruncate(int fd, off_t length);
void *host_opendir(const char *name); void *host_opendir(const char *name);
int host_readdir(void *dirp, struct dirent *entry); int host_readdir(void *dirp, struct dirent *entry);
@ -217,7 +226,8 @@ int host_mkdir(const char *pathname, mode_t mode);
int host_rmdir(const char *pathname); int host_rmdir(const char *pathname);
int host_rename(const char *oldpath, const char *newpath); int host_rename(const char *oldpath, const char *newpath);
int host_stat(const char *path, struct stat *buf); int host_stat(const char *path, struct stat *buf);
int host_chstat(const char *path,
const struct stat *buf, int flags);
#endif /* __SIM__ */ #endif /* __SIM__ */
#endif /* __INCLUDE_NUTTX_FS_HOSTFS_H */ #endif /* __INCLUDE_NUTTX_FS_HOSTFS_H */