git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15459 27425a3e-05d8-49a3-a47f-9c15f0e5edd8

This commit is contained in:
Giovanni Di Sirio 2022-02-11 14:23:33 +00:00
parent f3d3d9fcf7
commit 31a000e670
9 changed files with 223 additions and 26 deletions

View File

@ -69,6 +69,7 @@
#define SB_POSIX_RENAME 13
#define SB_POSIX_MKDIR 14
#define SB_POSIX_RMDIR 15
#define SB_POSIX_STAT 16
/** @} */
/*===========================================================================*/

View File

@ -70,6 +70,30 @@ static msg_t create_descriptor(sb_ioblock_t *iop,
/* Module exported functions. */
/*===========================================================================*/
int sb_posix_stat(const char *path, struct stat *statbuf) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
msg_t ret;
vfs_stat_t vstat;
if (sb_check_string(sbp, (void *)path, VFS_CFG_PATHLEN_MAX + 1) == (size_t)0) {
return CH_RET_EFAULT;
}
if (!sb_is_valid_write_range(sbp, (void *)statbuf, sizeof (struct stat))) {
return CH_RET_EFAULT;
}
ret = (int)vfsDrvStat(sbp->config->vfs_driver, path, &vstat);
if (!CH_RET_IS_ERROR(ret)) {
memset((void *)statbuf, 0, sizeof (struct stat));
statbuf->st_mode = (mode_t)vstat.mode;
statbuf->st_size = (off_t)vstat.size;
statbuf->st_nlink = 1;
}
return ret;
}
int sb_posix_open(const char *path, int flags) {
sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
vfs_node_c *np = NULL;

View File

@ -209,6 +209,19 @@ extern "C" {
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Posix-style file status.
*
* @param[in] pathname file to be examined
* @param[in] statbuf pointer to a @p stat structure
* @return Operation result.
*/
static inline int sbStat(const char *pathname, struct stat *statbuf) {
__syscall3r(0, SB_POSIX_STAT, pathname, statbuf);
return (int)r0;
}
/**
* @brief Posix-style file open.
*
@ -260,11 +273,10 @@ static inline int sbDup2(int oldfd, int newfd) {
}
/**
* @brief Posix-style file file status.
* @brief Posix-style file status.
*
* @param[in] fd file descriptor
* @param[in] statbuf pointer to a @p stat structure
* @param[in] whence operation mode
* @return Operation result.
*/
static inline int sbFstat(int fd, struct stat *statbuf) {

View File

@ -112,6 +112,7 @@ typedef struct vfs_fatfs_file_node {
static msg_t drv_set_cwd(void *instance, const char *path);
static msg_t drv_get_cwd(void *instance, char *buf, size_t size);
static msg_t drv_stat(void *instance, const char *path, vfs_stat_t *sp);
static msg_t drv_open_dir(void *instance,
const char *path,
vfs_directory_node_c **vdnpp);
@ -127,6 +128,7 @@ msg_t drv_rmdir(void *instance, const char *path);
static const struct vfs_fatfs_driver_vmt driver_vmt = {
.set_cwd = drv_set_cwd,
.get_cwd = drv_get_cwd,
.stat = drv_stat,
.open_dir = drv_open_dir,
.open_file = drv_open_file,
.unlink = drv_unlink,
@ -350,10 +352,46 @@ static msg_t drv_get_cwd(void *instance, char *buf, size_t size) {
#endif
}
static msg_t drv_stat(void *instance, const char *path, vfs_stat_t *sp) {
msg_t ret;
(void)instance;
do {
FRESULT res;
FILINFO *fip;
fip = (FILINFO *)chPoolAlloc(&vfs_fatfs_driver_static.info_nodes_pool);
if (fip != NULL) {
res = f_stat((const TCHAR *)path, fip);
if (res == FR_OK) {
sp->mode = translate_mode(fip->fattrib);
sp->size = (vfs_offset_t)fip->fsize;
ret = CH_RET_SUCCESS;
}
else {
ret = translate_error(res);
}
chPoolFree(&vfs_fatfs_driver_static.info_nodes_pool, (void *)fip);
}
else {
ret = CH_RET_ENOMEM;
break;
}
}
while (false);
return ret;
}
static msg_t drv_open_dir(void *instance,
const char *path,
vfs_directory_node_c **vdnpp) {
msg_t err;
msg_t ret;
do {
vfs_fatfs_driver_c *drvp = (vfs_fatfs_driver_c *)instance;
@ -363,7 +401,7 @@ static msg_t drv_open_dir(void *instance,
ffdnp = chPoolAlloc(&vfs_fatfs_driver_static.dir_nodes_pool);
if (ffdnp != NULL) {
res = f_opendir(&ffdnp->dir, (TCHAR *)path);
res = f_opendir(&ffdnp->dir, (const TCHAR *)path);
if (res == FR_OK) {
/* Node object initialization.*/
@ -372,25 +410,29 @@ static msg_t drv_open_dir(void *instance,
ffdnp->mode = translate_mode(ffdnp->dir.obj.attr);
*vdnpp = (vfs_directory_node_c *)ffdnp;
err = CH_RET_SUCCESS;
ret = CH_RET_SUCCESS;
break;
}
chPoolFree(&vfs_fatfs_driver_static.dir_nodes_pool, (void *)ffdnp);
}
else {
ret = CH_RET_ENOMEM;
break;
}
err = translate_error(res);
ret = translate_error(res);
}
while (false);
return err;
return ret;
}
static msg_t drv_open_file(void *instance,
const char *path,
int flags,
vfs_file_node_c **vfnpp) {
msg_t err;
msg_t ret;
do {
vfs_fatfs_driver_c *drvp = (vfs_fatfs_driver_c *)instance;
@ -400,14 +442,14 @@ static msg_t drv_open_file(void *instance,
mode = translate_oflag(flags);
if (mode == (BYTE)0) {
err = CH_RET_EINVAL;
ret = CH_RET_EINVAL;
break;
}
fffnp = chPoolAlloc(&vfs_fatfs_driver_static.file_nodes_pool);
if (fffnp != NULL) {
res = f_open(&fffnp->file, (TCHAR *)path, mode);
res = f_open(&fffnp->file, (const TCHAR *)path, mode);
if (res == FR_OK) {
/* Node object initialization.*/
@ -417,32 +459,37 @@ static msg_t drv_open_file(void *instance,
fffnp->stream.vmt = &file_stream_vmt;
*vfnpp = (vfs_file_node_c *)fffnp;
err = CH_RET_SUCCESS;
ret = CH_RET_SUCCESS;
break;
}
chPoolFree(&vfs_fatfs_driver_static.file_nodes_pool, (void *)fffnp);
}
else {
ret = CH_RET_ENOMEM;
break;
}
err = translate_error(res);
ret = translate_error(res);
}
while (false);
return err;
return ret;
}
msg_t drv_unlink(void *instance, const char *path) {
(void)instance;
return translate_error(f_unlink(path));
return translate_error(f_unlink((const TCHAR *)path));
}
msg_t drv_rename(void *instance, const char *oldpath, const char *newpath) {
(void)instance;
return translate_error(f_rename(oldpath, newpath));
return translate_error(f_rename((const TCHAR *)oldpath,
(const TCHAR *)newpath));
}
msg_t drv_mkdir(void *instance, const char *path, vfs_mode_t mode) {
@ -450,14 +497,14 @@ msg_t drv_mkdir(void *instance, const char *path, vfs_mode_t mode) {
(void)instance;
(void)mode; /* Not handled by FatFS.*/
return translate_error(f_mkdir(path));
return translate_error(f_mkdir((const TCHAR *)path));
}
msg_t drv_rmdir(void *instance, const char *path) {
(void)instance;
return translate_error(f_rmdir(path));
return translate_error(f_rmdir((const TCHAR *)path));
}
static void *node_dir_addref(void *instance) {
@ -486,22 +533,22 @@ static msg_t node_dir_stat(void *instance, vfs_stat_t *sp) {
static msg_t node_dir_first(void *instance, vfs_direntry_info_t *dip) {
vfs_fatfs_dir_node_c *ffdnp = (vfs_fatfs_dir_node_c *)instance;
msg_t err;
msg_t ret;
FRESULT res;
res = f_rewinddir(&ffdnp->dir);
if (res == FR_OK) {
err = node_dir_next(instance, dip);
ret = node_dir_next(instance, dip);
}
else {
err = translate_error(res);
ret = translate_error(res);
}
return err;
return ret;
}
static msg_t node_dir_next(void *instance, vfs_direntry_info_t *dip) {
msg_t err;
msg_t ret;
do {
vfs_fatfs_dir_node_c *ffdnp = (vfs_fatfs_dir_node_c *)instance;
@ -514,26 +561,30 @@ static msg_t node_dir_next(void *instance, vfs_direntry_info_t *dip) {
res = f_readdir(&ffdnp->dir, fip);
if (res == FR_OK) {
if (fip->fname[0] == '\0') {
err = (msg_t)0;
ret = (msg_t)0;
}
else {
dip->mode = translate_mode(fip->fattrib);
dip->size = (vfs_offset_t)fip->fsize;
strncpy(dip->name, fip->fname, VFS_CFG_NAMELEN_MAX);
dip->name[VFS_CFG_NAMELEN_MAX] = '\0';
err = (msg_t)1;
ret = (msg_t)1;
}
}
else {
err = translate_error(res);
ret = translate_error(res);
}
chPoolFree(&vfs_fatfs_driver_static.info_nodes_pool, (void *)fip);
}
else {
ret = CH_RET_ENOMEM;
break;
}
}
while (false);
return err;
return ret;
}
static void *node_file_addref(void *instance) {

View File

@ -47,6 +47,7 @@
static msg_t drv_set_cwd(void *instance, const char *path);
static msg_t drv_get_cwd(void *instance, char *buf, size_t size);
static msg_t drv_stat(void *instance, const char *path, vfs_stat_t *sp);
static msg_t drv_open_dir(void *instance, const char *path,
vfs_directory_node_c **vdnpp);
static msg_t drv_open_file(void *instance, const char *path,
@ -59,6 +60,7 @@ static msg_t drv_rmdir(void *instance, const char *path);
static const struct vfs_overlay_driver_vmt driver_vmt = {
.set_cwd = drv_set_cwd,
.get_cwd = drv_get_cwd,
.stat = drv_stat,
.open_dir = drv_open_dir,
.open_file = drv_open_file,
.unlink = drv_unlink,
@ -213,6 +215,10 @@ static msg_t open_absolute_dir(vfs_overlay_driver_c *drvp,
ret = CH_RET_SUCCESS;
break;
}
else {
ret = CH_RET_ENOMEM;
break;
}
}
else { /* Not the root.*/
vfs_driver_c *dp;
@ -374,6 +380,65 @@ static msg_t drv_get_cwd(void *instance, char *buf, size_t size) {
return CH_RET_SUCCESS;
}
static msg_t drv_stat(void *instance, const char *path, vfs_stat_t *sp) {
msg_t ret;
char *buf;
/* Taking a path buffer from the pool.*/
buf = vfs_buffer_take();
do {
vfs_overlay_driver_c *drvp = (vfs_overlay_driver_c *)instance;
const char *scanpath;
/* Building the absolute path based on current directory.*/
ret = build_absolute_path(drvp, buf, path);
CH_BREAK_ON_ERROR(ret);
/* Skipping the root separator.*/
scanpath = buf + 1;
/* If it is not root checking among mounted drivers.*/
if (*scanpath != '\0') {
vfs_driver_c *dp;
/* Searching for a match among registered overlays.*/
ret = match_driver(drvp, &scanpath, &dp);
if (!CH_RET_IS_ERROR(ret)) {
/* Delegating directory creation to a registered driver.*/
ret = dp->vmt->stat((void *)dp, scanpath, sp);
}
break;
}
/* Is there an overlaid driver? if so we need to pass request
processing there.*/
if (drvp->overlaid_drv != NULL) {
/* Processing the prefix, if defined.*/
if (drvp->path_prefix != NULL) {
if (path_prepend(buf,
drvp->path_prefix,
VFS_CFG_PATHLEN_MAX + 1) == (size_t)0) {
ret = CH_RET_ENAMETOOLONG;
break;
}
}
/* Passing the combined path to the overlaid driver.*/
ret = drvp->overlaid_drv->vmt->stat((void *)drvp->overlaid_drv, buf, sp);
}
else {
ret = CH_RET_ENOENT;
}
} while (false);
/* Buffer returned.*/
vfs_buffer_release(buf);
return ret;
}
static msg_t drv_open_dir(void *instance,
const char *path,
vfs_directory_node_c **vdnpp) {

View File

@ -131,6 +131,7 @@ extern "C" {
void vfsInit(void);
msg_t vfsChangeCurrentDirectory(const char *path);
msg_t vfsGetCurrentDirectory(char *buf, size_t size);
msg_t vfsStat(const char *path, vfs_stat_t *sp);
msg_t vfsOpen(const char *path, int flags, vfs_node_c **vnpp);
msg_t vfsOpenDirectory(const char *name, vfs_directory_node_c **vdnpp);
msg_t vfsOpenFile(const char *name, int flags, vfs_file_node_c **vfnpp);

View File

@ -69,6 +69,9 @@
__base_object_methods \
msg_t (*set_cwd)(void *instance, const char *path); \
msg_t (*get_cwd)(void *instance, char *buf, size_t size); \
msg_t (*stat)(void *instance, \
const char *path, \
vfs_stat_t *sp); \
msg_t (*open_dir)(void *instance, \
const char *path, \
vfs_directory_node_c **vdnpp); \
@ -120,6 +123,7 @@ extern "C" {
const char *path,
int flags,
vfs_node_c **vnpp);
msg_t drv_stat_unimpl(void *instance, vfs_stat_t *sp);
msg_t drv_unlink_unimpl(void *instance, const char *path);
msg_t drv_rename_unimpl(void *instance,
const char *oldpath,
@ -167,6 +171,23 @@ static inline msg_t vfsDrvGetCurrentDirectory(vfs_driver_c *drvp,
return drvp->vmt->get_cwd(drvp, buf, size);
}
/**
* @brief Returns file or directory information.
*.
* @param[in] drvp Pointer to the @p vfs_driver_c object.
* @param[in] path Absolute path of the node to be examined.
* @param[out] sp Pointer to a @p vfs_stat_t structure.
* @return The operation result.
*
* @api
*/
static inline msg_t vfsDrvStat(vfs_driver_c *drvp,
const char *path,
vfs_stat_t *sp) {
return drvp->vmt->stat(drvp, path, sp);
}
/**
* @brief Opens a VFS directory.
*

View File

@ -101,6 +101,20 @@ msg_t vfsGetCurrentDirectory(char *buf, size_t size) {
return vfsDrvGetCurrentDirectory(vfs_root, buf, size);
}
/**
* @brief Returns file or directory information.
*.
* @param[in] path Absolute path of the node to be examined.
* @param[out] sp Pointer to a @p vfs_stat_t structure.
* @return The operation result.
*
* @api
*/
msg_t vfsStat(const char *path, vfs_stat_t *sp) {
return vfsDrvStat(vfs_root, path, sp);
}
/**
* @brief Opens a VFS file or directory.
*

View File

@ -83,6 +83,14 @@ msg_t vfsDrvOpen(vfs_driver_c *drvp,
return ret;
}
msg_t drv_stat_unimpl(void *instance, vfs_stat_t *sp) {
(void)instance;
(void)sp;
return CH_RET_ENOSYS;
}
msg_t drv_unlink_unimpl(void *instance, const char *path) {
(void)instance;