summaryrefslogtreecommitdiff
path: root/components/dfs
diff options
context:
space:
mode:
authorShell <[email protected]>2024-03-28 23:42:56 +0800
committerGitHub <[email protected]>2024-03-28 23:42:56 +0800
commit83e95bdff4c48c661b50e1eec56d5fd293b28fbb (patch)
tree9e0c2065950f0804e5009da71c8e0f590224cade /components/dfs
parent40e26f4909fa61ada775ba86b44d8300aaf5d250 (diff)
sync smart & dfs (#8672)
Signed-off-by: xqyjlj <[email protected]> Signed-off-by: Shell <[email protected]> Co-authored-by: xqyjlj <[email protected]>
Diffstat (limited to 'components/dfs')
-rw-r--r--components/dfs/Kconfig8
-rw-r--r--components/dfs/dfs_v2/filesystems/devfs/devfs.c797
-rw-r--r--components/dfs/dfs_v2/filesystems/devfs/devfs.h5
-rw-r--r--components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c678
-rw-r--r--components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c2
-rw-r--r--components/dfs/dfs_v2/filesystems/ptyfs/README.md5
-rw-r--r--components/dfs/dfs_v2/filesystems/ptyfs/SConscript11
-rw-r--r--components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c658
-rw-r--r--components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h22
-rw-r--r--components/dfs/dfs_v2/filesystems/romfs/romfs.c3
-rw-r--r--components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c38
-rw-r--r--components/dfs/dfs_v2/include/dfs.h12
-rw-r--r--components/dfs/dfs_v2/include/dfs_file.h11
-rw-r--r--components/dfs/dfs_v2/include/dfs_fs.h4
-rw-r--r--components/dfs/dfs_v2/include/dfs_pcache.h5
-rw-r--r--components/dfs/dfs_v2/src/dfs.c111
-rw-r--r--components/dfs/dfs_v2/src/dfs_file.c307
-rw-r--r--components/dfs/dfs_v2/src/dfs_pcache.c50
18 files changed, 2055 insertions, 672 deletions
diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig
index 6af2555a14..2c822cf779 100644
--- a/components/dfs/Kconfig
+++ b/components/dfs/Kconfig
@@ -45,6 +45,7 @@ endif
config RT_USING_DFS_V2
bool "DFS v2.0"
+ select RT_USING_DEVICE_OPS
endchoice
if RT_USING_DFS_V1
@@ -170,6 +171,13 @@ endif
depends on RT_USING_DFS_ROMFS
default n
+if RT_USING_SMART
+ config RT_USING_DFS_PTYFS
+ bool "Using Pseudo-Teletype Filesystem (UNIX98 PTY)"
+ depends on RT_USING_DFS_DEVFS
+ default y
+endif
+
config RT_USING_DFS_CROMFS
bool "Enable ReadOnly compressed file system on flash"
default n
diff --git a/components/dfs/dfs_v2/filesystems/devfs/devfs.c b/components/dfs/dfs_v2/filesystems/devfs/devfs.c
index 7ebac59868..7818ae19be 100644
--- a/components/dfs/dfs_v2/filesystems/devfs/devfs.c
+++ b/components/dfs/dfs_v2/filesystems/devfs/devfs.c
@@ -13,6 +13,7 @@
#include <fcntl.h>
#include <errno.h>
+#include <sys/unistd.h>
#include <dfs.h>
#include <dfs_fs.h>
@@ -20,663 +21,501 @@
#include <dfs_dentry.h>
#include <dfs_mnt.h>
-#include "devfs.h"
-
-struct device_dirent
-{
- struct rt_device **devices;
- uint32_t device_count;
-};
-
-int dfs_devfs_open(struct dfs_file *file);
-int dfs_devfs_close(struct dfs_file *file);
-off_t generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence);
-ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos);
-ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos);
-int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args);
-int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count);
-static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req);
-int dfs_devfs_flush(struct dfs_file *file);
-off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece);
-int dfs_devfs_truncate(struct dfs_file *file, off_t offset);
-int dfs_devfs_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap);
-int dfs_devfs_lock(struct dfs_file *file, struct file_lock *flock);
-int dfs_devfs_flock(struct dfs_file *file, int operation, struct file_lock *flock);
-
-int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data);
-int dfs_devfs_umount(struct dfs_mnt *mnt);
-int dfs_devfs_unlink(struct dfs_dentry *dentry);
-int dfs_devfs_stat(struct dfs_dentry *dentry, struct stat *st);
-int dfs_devfs_statfs(struct dfs_mnt *mnt, struct statfs *buf);
-static struct dfs_vnode *dfs_devfs_lookup(struct dfs_dentry *dentry);
-struct dfs_vnode *dfs_devfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode);
-static int dfs_devfs_free_vnode(struct dfs_vnode *vnode);
-
-static const struct dfs_file_ops _dev_fops =
-{
- .open = dfs_devfs_open,
- .close = dfs_devfs_close,
- .lseek = generic_dfs_lseek,
- .read = dfs_devfs_read,
- .write = dfs_devfs_write,
- .ioctl = dfs_devfs_ioctl,
- .getdents = dfs_devfs_getdents,
- .poll = dfs_devfs_poll,
-
- .flush = dfs_devfs_flush,
- .lseek = dfs_devfs_lseek,
- .truncate = dfs_devfs_truncate,
- .mmap = dfs_devfs_mmap,
- .lock = dfs_devfs_lock,
- .flock = dfs_devfs_flock,
-};
-
-static const struct dfs_filesystem_ops _devfs_ops =
-{
- .name = "devfs",
-
- .default_fops = &_dev_fops,
- .mount = dfs_devfs_mount,
- .umount = dfs_devfs_umount,
- .unlink = dfs_devfs_unlink,
- .stat = dfs_devfs_stat,
- .statfs = dfs_devfs_statfs,
- .lookup = dfs_devfs_lookup,
- .create_vnode = dfs_devfs_create_vnode,
- .free_vnode = dfs_devfs_free_vnode,
-};
-
-static struct dfs_filesystem_type _devfs =
+static int dfs_devfs_open(struct dfs_file *file)
{
- .fs_ops = &_devfs_ops,
-};
+ int ret = RT_EOK;
-static int _device_to_mode(struct rt_device *device)
-{
- int mode = 0;
+ RT_ASSERT(file != RT_NULL);
+ RT_ASSERT(file->vnode->ref_count > 0);
- switch (device->type)
+ if (file->vnode->ref_count > 1)
{
- case RT_Device_Class_Char:
- mode = S_IFCHR | 0777;
- break;
- case RT_Device_Class_Block:
- mode = S_IFBLK | 0777;
- break;
- case RT_Device_Class_Pipe:
- mode = S_IFIFO | 0777;
- break;
- default:
- mode = S_IFCHR | 0777;
- break;
+ if (file->vnode->type == FT_DIRECTORY
+ && !(file->flags & O_DIRECTORY))
+ {
+ return -ENOENT;
+ }
+ file->fpos = 0;
}
- return mode;
-}
-
-static int _devfs_root_dirent_update(struct dfs_vnode *vnode)
-{
- rt_err_t result = RT_EOK;
-
- if (vnode)
+ if (!S_ISDIR(file->vnode->mode))
{
- // result = rt_mutex_take(&vnode->lock, RT_WAITING_FOREVER);
- result = dfs_file_lock();
- if (result == RT_EOK)
+ rt_device_t device = RT_NULL;
+ struct dfs_dentry *de = file->dentry;
+ char *device_name = rt_malloc(DFS_PATH_MAX);
+
+ if (!device_name)
{
- rt_uint32_t count = 0;
- struct device_dirent *root_dirent = (struct device_dirent*) vnode->data;
- if (root_dirent) rt_free(root_dirent);
+ return -ENOMEM;
+ }
- count = rt_object_get_length(RT_Object_Class_Device);
- root_dirent = (struct device_dirent *)rt_malloc(sizeof(struct device_dirent) + count * sizeof(rt_device_t));
- if (root_dirent != RT_NULL)
+ /* skip `/dev` */
+ rt_snprintf(device_name, DFS_PATH_MAX, "%s%s", de->mnt->fullpath + sizeof("/dev") - 1, de->pathname);
+
+ device = rt_device_find(device_name + 1);
+ if (device)
+ {
+ file->vnode->data = device;
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->open)
{
- root_dirent->device_count = count;
- if (count != 0)
+ ret = device->fops->open(file);
+ if (ret == RT_EOK || ret == -RT_ENOSYS)
{
- root_dirent->devices = (rt_device_t *)(root_dirent + 1);
- rt_object_get_pointers(RT_Object_Class_Device, (rt_object_t *)root_dirent->devices, count);
+ ret = RT_EOK;
}
- else
+ }
+ else if (device->ops && file->vnode->ref_count == 1)
+#else
+ if (device->ops && file->vnode->ref_count == 1)
+#endif /* RT_USING_POSIX_DEVIO */
+ {
+ ret = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
+ if (ret == RT_EOK || ret == -RT_ENOSYS)
{
- root_dirent->devices = RT_NULL;
+ ret = RT_EOK;
}
}
-
- vnode->data = root_dirent;
- result = count;
- dfs_file_unlock();
}
}
- return result;
+ return ret;
}
-static struct dfs_vnode *dfs_devfs_lookup(struct dfs_dentry *dentry)
+static int dfs_devfs_close(struct dfs_file *file)
{
- rt_device_t device = RT_NULL;
- struct dfs_vnode *vnode = RT_NULL;
- const char *pathname = dentry->pathname;
+ int ret = RT_EOK;
+ rt_device_t device;
- DLOG(msg, "devfs", "vnode", DLOG_MSG, "dfs_vnode_create");
- vnode = dfs_vnode_create();
- if (vnode)
+ RT_ASSERT(file != RT_NULL);
+ RT_ASSERT(file->vnode->ref_count > 0);
+
+ if (file->vnode && file->vnode->data)
{
- if (pathname[0] == '/' && pathname[1] == '\0')
- {
- int count = _devfs_root_dirent_update(vnode);
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
- vnode->mode = S_IFDIR | 0644;
- vnode->size = count;
- vnode->nlink = 1;
- vnode->fops = &_dev_fops;
- vnode->mnt = dentry->mnt;
- vnode->type = FT_DIRECTORY;
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->close)
+ {
+ ret = device->fops->close(file);
}
- else
+ else if (file->vnode->ref_count == 1)
+#else
+ if (device->ops && file->vnode->ref_count == 1)
+#endif /* RT_USING_POSIX_DEVIO */
{
- device = rt_device_find(&pathname[1]);
- if (!device)
- {
- DLOG(msg, "devfs", "vnode", DLOG_MSG, "dfs_vnode_destroy(vnode), no-device");
- dfs_vnode_destroy(vnode);
- vnode = RT_NULL;
- }
- else
- {
- vnode->mode = _device_to_mode(device);
- vnode->size = device->ref_count;
- vnode->nlink = 1;
- vnode->fops = &_dev_fops;
- vnode->data = device;
- vnode->mnt = dentry->mnt;
- vnode->type = FT_DEVICE;
- }
+ /* close device handler */
+ ret = rt_device_close(device);
}
}
- return vnode;
+ return ret;
}
-struct dfs_vnode *dfs_devfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
+static ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
-#ifdef RT_USING_DEV_BUS
- if (dentry && type == FT_DIRECTORY)
+ ssize_t ret = -RT_EIO;
+ rt_device_t device;
+
+ RT_ASSERT(file != RT_NULL);
+
+ if (file->vnode && file->vnode->data)
{
- /* regester bus device */
- if (rt_device_bus_create(&dentry->pathname[1], 0))
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
+
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->read)
{
- return dfs_devfs_lookup(dentry);
+ ret = device->fops->read(file, buf, count, pos);
+ }
+ else
+#else
+ if (device->ops)
+#endif /* RT_USING_POSIX_DEVIO */
+ {
+ /* read device data */
+ ret = rt_device_read(device, *pos, buf, count);
+ *pos += ret;
}
}
-#endif
- return RT_NULL;
+ return ret;
}
-int dfs_devfs_free_vnode(struct dfs_vnode *vnode)
+static ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
{
- if (S_ISDIR(vnode->mode))
+ ssize_t ret = -RT_EIO;
+ rt_device_t device;
+
+ RT_ASSERT(file != RT_NULL);
+
+ if(file->vnode->data)
{
- struct device_dirent *root_dirent;
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
- root_dirent = (struct device_dirent *)vnode->data;
- RT_ASSERT(root_dirent != RT_NULL);
+ if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
+ return -RT_ENOSYS;
- /* release dirent */
- DLOG(msg, "devfs", "devfs", DLOG_MSG, "free root_dirent");
- rt_free(root_dirent);
- return RT_EOK;
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->write)
+ {
+ ret = device->fops->write(file, buf, count, pos);
+ }
+ else
+#else
+ if (device->ops)
+#endif /* RT_USING_POSIX_DEVIO */
+ {
+ /* read device data */
+ ret = rt_device_write(device, *pos, buf, count);
+ *pos += ret;
+ }
}
- /* which is a device */
- vnode->data = RT_NULL;
- return 0;
+ return ret;
}
-int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
+static int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args)
{
- RT_ASSERT(mnt != RT_NULL);
+ int ret = RT_EOK;
+ rt_device_t device;
- rt_atomic_add(&(mnt->ref_count), 1);
- mnt->flags |= MNT_IS_LOCKED;
+ RT_ASSERT(file != RT_NULL);
- return RT_EOK;
-}
+ if (file->vnode && file->vnode->data)
+ {
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
-int dfs_devfs_umount(struct dfs_mnt *mnt)
-{
- return RT_EOK;
+ if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
+ return -RT_ENOSYS;
+
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->ioctl)
+ {
+ ret = device->fops->ioctl(file, cmd, args);
+ }
+ else
+#endif /* RT_USING_POSIX_DEVIO */
+ {
+ ret = rt_device_control(device, cmd, args);
+ }
+ }
+
+ return ret;
}
-int dfs_devfs_statfs(struct dfs_mnt *mnt, struct statfs *buf)
+static int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
{
- if (mnt && buf)
- {
- buf->f_bsize = 512;
- buf->f_blocks = 2048 * 64; // 64M
- buf->f_bfree = buf->f_blocks;
- buf->f_bavail = buf->f_bfree;
- }
+ int ret = -RT_ENOSYS;
- return RT_EOK;
+ RT_ASSERT(file != RT_NULL);
+
+ return ret;
}
-int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args)
+static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req)
{
- rt_err_t result = RT_EOK;
+ int mask = 0;
rt_device_t device;
RT_ASSERT(file != RT_NULL);
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
-
- if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
- return -RT_ENOSYS;
+ if (file->vnode && file->vnode->data)
+ {
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->ioctl)
- {
- result = device->fops->ioctl(file, cmd, args);
- }
- else
+ if (device->fops && device->fops->poll)
+ {
+ mask = device->fops->poll(file, req);
+ }
#endif /* RT_USING_POSIX_DEVIO */
- {
- result = rt_device_control(device, cmd, args);
}
- return result;
+ return mask;
}
-ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
+static int dfs_devfs_flush(struct dfs_file *file)
{
- int result = -RT_EIO;
+ int ret = RT_EOK;
rt_device_t device;
RT_ASSERT(file != RT_NULL);
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
-
- if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
- return -RT_ENOSYS;
+ if (file->vnode && file->vnode->data)
+ {
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->read)
- {
- result = device->fops->read(file, buf, count, pos);
- }
- else
+ if (device->fops && device->fops->flush)
+ {
+ ret = device->fops->flush(file);
+ }
#endif /* RT_USING_POSIX_DEVIO */
- {
- /* read device data */
- result = rt_device_read(device, *pos, buf, count);
- *pos += result;
}
- return result;
+ return ret;
}
-ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
+static off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece)
{
- int result = -RT_EIO;
+ off_t ret = 0;
rt_device_t device;
RT_ASSERT(file != RT_NULL);
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
-
- if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
- return -RT_ENOSYS;
+ if (file->vnode && file->vnode->data)
+ {
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->write)
- {
- result = device->fops->write(file, buf, count, pos);
- }
- else
+ if (device->fops && device->fops->lseek)
+ {
+ ret = device->fops->lseek(file, offset, wherece);
+ }
#endif /* RT_USING_POSIX_DEVIO */
- {
- /* read device data */
- result = rt_device_write(device, *pos, buf, count);
- *pos += result;
}
- return result;
+ return ret;
}
-int dfs_devfs_close(struct dfs_file *file)
+static int dfs_devfs_truncate(struct dfs_file *file, off_t offset)
{
- rt_err_t result = RT_EOK;
+ int ret = RT_EOK;
rt_device_t device;
RT_ASSERT(file != RT_NULL);
- if (!S_ISDIR(file->vnode->mode))
+ if (file->vnode && file->vnode->data)
{
/* get device handler */
device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->close)
+ if (device->fops && device->fops->truncate)
{
- result = device->fops->close(file);
+ ret = device->fops->truncate(file, offset);
}
- else
#endif /* RT_USING_POSIX_DEVIO */
- {
- /* close device handler */
- result = rt_device_close(device);
- }
}
- return result;
+ return ret;
}
-int dfs_devfs_open(struct dfs_file *file)
+static int dfs_devfs_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap)
{
- rt_err_t result = RT_EOK;
+ int ret = RT_EOK;
+ rt_device_t device;
- /* open root directory */
- if ((file->dentry->pathname[0] == '/' && file->dentry->pathname[1] == '\0') ||
- (S_ISDIR(file->vnode->mode)))
- {
- /* re-open the root directory for re-scan devices */
- _devfs_root_dirent_update(file->vnode);
- return RT_EOK;
- }
- else
+ RT_ASSERT(file != RT_NULL);
+
+ if (file->vnode && file->vnode->data)
{
- rt_device_t device = RT_NULL;
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
- device = (struct rt_device *)file->vnode->data;
- if (device)
- {
#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->open)
- {
- result = device->fops->open(file);
- if (result == RT_EOK || result == -RT_ENOSYS)
- {
- file->fops = &_dev_fops;
- return RT_EOK;
- }
- }
- else
-#endif /* RT_USING_POSIX_DEVIO */
- {
- result = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
- if (result == RT_EOK || result == -RT_ENOSYS)
- {
- file->fops = &_dev_fops;
- return RT_EOK;
- }
- }
+ if (device->fops && device->fops->mmap)
+ {
+ ret = device->fops->mmap(file, mmap);
}
+#endif /* RT_USING_POSIX_DEVIO */
}
- /* open device failed. */
- return -EIO;
+ return ret;
}
-int dfs_devfs_unlink(struct dfs_dentry *dentry)
+static int dfs_devfs_lock(struct dfs_file *file, struct file_lock *flock)
{
-#ifdef RT_USING_DEV_BUS
+ int ret = RT_EOK;
rt_device_t device;
- device = rt_device_find(&dentry->pathname[1]);
- if (device == RT_NULL)
- {
- return -1;
- }
- if (device->type != RT_Device_Class_Bus)
- {
- return -1;
- }
- rt_device_bus_destroy(device);
-#endif
- return RT_EOK;
-}
-
-int dfs_devfs_stat(struct dfs_dentry *dentry, struct stat *st)
-{
- int ret = RT_EOK;
- const char *path = RT_NULL;
- struct dfs_vnode *vnode = RT_NULL;
+ RT_ASSERT(file != RT_NULL);
- if (dentry && dentry->vnode)
+ if (file->vnode && file->vnode->data)
{
- path = dentry->pathname;
- vnode = dentry->vnode;
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
- /* stat root directory */
- if ((path[0] == '/') && (path[1] == '\0'))
- {
- st->st_dev = 0;
- st->st_gid = vnode->gid;
- st->st_uid = vnode->uid;
- st->st_ino = 0;
- st->st_mode = vnode->mode;
- st->st_nlink = vnode->nlink;
- st->st_size = vnode->size;
- st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
- st->st_mtim.tv_sec = vnode->mtime.tv_sec;
- st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
- st->st_ctim.tv_sec = vnode->ctime.tv_sec;
- st->st_atim.tv_nsec = vnode->atime.tv_nsec;
- st->st_atim.tv_sec = vnode->atime.tv_sec;
- }
- else
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->lock)
{
- rt_device_t device;
-
- device = rt_device_find(&path[1]);
- if (device != RT_NULL)
- {
- st->st_dev = 0;
- st->st_gid = vnode->gid;
- st->st_uid = vnode->uid;
- st->st_ino = 0;
- st->st_mode = vnode->mode;
- st->st_nlink = vnode->nlink;
- st->st_size = vnode->size;
- st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
- st->st_mtim.tv_sec = vnode->mtime.tv_sec;
- st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
- st->st_ctim.tv_sec = vnode->ctime.tv_sec;
- st->st_atim.tv_nsec = vnode->atime.tv_nsec;
- st->st_atim.tv_sec = vnode->atime.tv_sec;
- }
- else
- {
- ret = -ENOENT;
- }
+ ret = device->fops->lock(file, flock);
}
+#endif /* RT_USING_POSIX_DEVIO */
}
return ret;
}
-int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
+static int dfs_devfs_flock(struct dfs_file *file, int operation, struct file_lock *flock)
{
- rt_uint32_t index;
- rt_object_t object;
- struct dirent *d;
- struct device_dirent *root_dirent;
-
- root_dirent = (struct device_dirent *)file->vnode->data;
- RT_ASSERT(root_dirent != RT_NULL);
+ int ret = RT_EOK;
+ rt_device_t device;
- /* make integer count */
- count = (count / sizeof(struct dirent));
- if (count == 0)
- return -EINVAL;
+ RT_ASSERT(file != RT_NULL);
- for (index = 0; index < count && index + file->fpos < root_dirent->device_count; index ++)
+ if (file->vnode && file->vnode->data)
{
- object = (rt_object_t)root_dirent->devices[file->fpos + index];
+ /* get device handler */
+ device = (rt_device_t)file->vnode->data;
- d = dirp + index;
- d->d_type = DT_REG;
- d->d_namlen = RT_NAME_MAX;
- d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
- rt_strncpy(d->d_name, object->name, RT_NAME_MAX);
- d->d_name[RT_NAME_MAX] = '\0';
+#ifdef RT_USING_POSIX_DEVIO
+ if (device->fops && device->fops->flock)
+ {
+ ret = device->fops->flock(file, operation, flock);
+ }
+#endif /* RT_USING_POSIX_DEVIO */
}
- file->fpos += index;
-
- return index * sizeof(struct dirent);
+ return ret;
}
-static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req)
+static const struct dfs_file_ops _dev_fops =
{
- int mask = 0;
- rt_device_t device;
+ .open = dfs_devfs_open,
+ .close = dfs_devfs_close,
+ .lseek = generic_dfs_lseek,
+ .read = dfs_devfs_read,
+ .write = dfs_devfs_write,
+ .ioctl = dfs_devfs_ioctl,
+ .getdents = dfs_devfs_getdents,
+ .poll = dfs_devfs_poll,
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
-
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->poll)
- {
- mask = device->fops->poll(file, req);
- }
-#endif /* RT_USING_POSIX_DEVIO */
+ .flush = dfs_devfs_flush,
+ .lseek = dfs_devfs_lseek,
+ .truncate = dfs_devfs_truncate,
+ .mmap = dfs_devfs_mmap,
+ .lock = dfs_devfs_lock,
+ .flock = dfs_devfs_flock,
+};
- return mask;
+const struct dfs_file_ops *dfs_devfs_fops(void)
+{
+ return &_dev_fops;
}
-int dfs_devfs_flush(struct dfs_file *file)
+mode_t dfs_devfs_device_to_mode(struct rt_device *device)
{
- int ret = 0;
- rt_device_t device;
+ mode_t mode = 0;
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
-
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->flush)
+ switch (device->type)
{
- ret = device->fops->flush(file);
+ case RT_Device_Class_Char:
+ mode = S_IFCHR | 0777;
+ break;
+ case RT_Device_Class_Block:
+ mode = S_IFBLK | 0777;
+ break;
+ case RT_Device_Class_Pipe:
+ mode = S_IFIFO | 0777;
+ break;
+ default:
+ mode = S_IFCHR | 0777;
+ break;
}
-#endif /* RT_USING_POSIX_DEVIO */
- return ret;
+ return mode;
}
-off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece)
+static void dfs_devfs_mkdir(const char *fullpath, mode_t mode)
{
- off_t ret = 0;
- rt_device_t device;
+ int len = rt_strlen(fullpath);
+ char *path = (char *)rt_malloc(len);
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
-
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->lseek)
+ if (path)
{
- ret = device->fops->lseek(file, offset, wherece);
- }
-#endif /* RT_USING_POSIX_DEVIO */
+ int index = len - 1;
- return ret;
-}
+ rt_strcpy(path, fullpath);
-int dfs_devfs_truncate(struct dfs_file *file, off_t offset)
-{
- int ret = 0;
- rt_device_t device;
+ if (path[index] == '/')
+ {
+ path[index] = '\0';
+ index --;
+ }
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
+ while (path[index] != '/' && index >= 0)
+ {
+ index --;
+ }
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->truncate)
- {
- ret = device->fops->truncate(file, offset);
- }
-#endif /* RT_USING_POSIX_DEVIO */
+ path[index] = '\0';
- return ret;
-}
+ if (index > 0 && access(path, 0) != 0)
+ {
+ int i = 0;
-int dfs_devfs_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap)
-{
- int ret = 0;
- rt_device_t device;
+ if (path[i] == '/')
+ {
+ i ++;
+ }
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
+ while (index > i)
+ {
+ if (path[i] == '/')
+ {
+ path[i] = '\0';
+ mkdir(path, mode);
+ path[i] = '/';
+ }
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->mmap)
- {
- ret = device->fops->mmap(file, mmap);
- }
-#endif /* RT_USING_POSIX_DEVIO */
+ i ++;
+ }
- return ret;
+ mkdir(path, mode);
+ }
+ }
}
-int dfs_devfs_lock(struct dfs_file *file, struct file_lock *flock)
+void dfs_devfs_device_add(rt_device_t device)
{
- int ret = 0;
- rt_device_t device;
-
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
+ int fd;
+ char path[512];
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->lock)
+ if (device)
{
- ret = device->fops->lock(file, flock);
- }
-#endif /* RT_USING_POSIX_DEVIO */
+ rt_snprintf(path, 512, "/dev/%s", device->parent.name);
- return ret;
-}
-
-int dfs_devfs_flock(struct dfs_file *file, int operation, struct file_lock *flock)
-{
- int ret = 0;
- rt_device_t device;
+ if (access(path, 0) != 0)
+ {
+ mode_t mode = dfs_devfs_device_to_mode(device);
- /* get device handler */
- device = (rt_device_t)file->vnode->data;
- RT_ASSERT(device != RT_NULL);
+ dfs_devfs_mkdir(path, mode);
-#ifdef RT_USING_POSIX_DEVIO
- if (device->fops && device->fops->flock)
- {
- ret = device->fops->flock(file, operation, flock);
+ fd = open(path, O_RDWR | O_CREAT, mode);
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ }
}
-#endif /* RT_USING_POSIX_DEVIO */
-
- return ret;
}
-int dfs_devfs_init(void)
+int dfs_devfs_update(void)
{
- /* register devfs file system */
- dfs_register(&_devfs);
+ int count = rt_object_get_length(RT_Object_Class_Device);
+ if (count > 0)
+ {
+ rt_device_t *devices = rt_malloc(count * sizeof(rt_device_t));
+ if (devices)
+ {
+ rt_object_get_pointers(RT_Object_Class_Device, (rt_object_t *)devices, count);
- dfs_mount(RT_NULL, "/dev", "devfs", 0, RT_NULL);
+ for (int index = 0; index < count; index ++)
+ {
+ dfs_devfs_device_add(devices[index]);
+ }
+ rt_free(devices);
+ }
+ }
- return 0;
+ return count;
}
-INIT_COMPONENT_EXPORT(dfs_devfs_init);
-
diff --git a/components/dfs/dfs_v2/filesystems/devfs/devfs.h b/components/dfs/dfs_v2/filesystems/devfs/devfs.h
index acaae11f2f..e80b44ee09 100644
--- a/components/dfs/dfs_v2/filesystems/devfs/devfs.h
+++ b/components/dfs/dfs_v2/filesystems/devfs/devfs.h
@@ -10,6 +10,9 @@
#ifndef __DEVICE_FS_H__
#define __DEVICE_FS_H__
-int dfs_devfs_init(void);
+const struct dfs_file_ops *dfs_devfs_fops(void);
+mode_t dfs_devfs_device_to_mode(struct rt_device *device);
+void dfs_devfs_device_add(rt_device_t device);
+int dfs_devfs_update(void);
#endif
diff --git a/components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c b/components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c
new file mode 100644
index 0000000000..3bea0c16df
--- /dev/null
+++ b/components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-10-24 flybreak the first version
+ * 2023-02-01 xqyjlj fix cannot open the same file repeatedly in 'w' mode
+ * 2023-09-20 zmq810150896 adds truncate functionality and standardized unlink adaptations
+ * 2023-12-02 Shell Support of dynamic device
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <dfs.h>
+#include <dfs_fs.h>
+#include <dfs_dentry.h>
+#include <dfs_file.h>
+#include <dfs_mnt.h>
+#include <devfs.h>
+#include <unistd.h>
+
+
+#define TMPFS_MAGIC 0x0B0B0B0B
+#define TMPFS_TYPE_FILE 0x00
+#define TMPFS_TYPE_DIR 0x01
+#define TMPFS_TYPE_DYN_DEV 0x02 /* dynamic device */
+
+struct devtmpfs_sb;
+
+struct devtmpfs_file
+{
+ char name[DIRENT_NAME_MAX]; /* file name */
+
+ rt_uint32_t type; /* file type */
+ rt_list_t subdirs; /* file subdir list */
+ rt_list_t sibling; /* file sibling list */
+
+ struct devtmpfs_sb *sb; /* superblock ptr */
+
+ rt_uint32_t mode;
+ char *link;
+};
+
+struct devtmpfs_sb
+{
+ rt_uint32_t magic; /* TMPFS_MAGIC */
+ struct devtmpfs_file root; /* root dir */
+ rt_size_t df_size; /* df size */
+ rt_list_t sibling; /* sb sibling list */
+ struct rt_spinlock lock; /* tmpfs lock */
+};
+
+static struct dfs_file_ops _default_fops = { 0 };
+
+static int _path_separate(const char *path, char *parent_path, char *file_name)
+{
+ const char *path_p, *path_q;
+
+ RT_ASSERT(path[0] == '/');
+
+ file_name[0] = '\0';
+ path_p = path_q = &path[1];
+__next_dir:
+ while (*path_q != '/' && *path_q != '\0')
+ {
+ path_q++;
+ }
+ if (path_q != path_p) /*sub dir*/
+ {
+ if (*path_q != '\0')
+ {
+ path_q++;
+ path_p = path_q;
+ goto __next_dir;
+ }
+ else /* Last level dir */
+ {
+ rt_memcpy(parent_path, path, path_p - path - 1);
+ parent_path[path_p - path - 1] = '\0';
+ rt_memcpy(file_name, path_p, path_q - path_p);
+ file_name[path_q - path_p] = '\0';
+ }
+ }
+ if (parent_path[0] == 0)
+ {
+ parent_path[0] = '/';
+ parent_path[1] = '\0';
+ }
+ //LOG_D("parent_path: %s", parent_path);
+ //LOG_D("file_name: %s", file_name);
+
+ return 0;
+}
+
+static int _get_subdir(const char *path, char *name)
+{
+ const char *subpath = path;
+ while (*subpath == '/' && *subpath)
+ subpath ++;
+ while (*subpath != '/' && *subpath)
+ {
+ *name = *subpath;
+ name ++;
+ subpath ++;
+ }
+ return 0;
+}
+
+#if 0
+static int _free_subdir(struct devtmpfs_file *dfile)
+{
+ struct devtmpfs_file *file;
+ rt_list_t *list, *temp_list;
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(dfile->type == TMPFS_TYPE_DIR);
+
+ rt_list_for_each_safe(list, temp_list, &dfile->subdirs)
+ {
+ file = rt_list_entry(list, struct devtmpfs_file, sibling);
+ if (file->type == TMPFS_TYPE_DIR)
+ {
+ _free_subdir(file);
+ }
+
+ if (file->link)
+ {
+ rt_free(file->link);
+ }
+
+ superblock = file->sb;
+ RT_ASSERT(superblock);
+
+ rt_spin_lock(&superblock->lock);
+ rt_list_remove(&(file->sibling));
+ rt_spin_unlock(&superblock->lock);
+
+ rt_free(file);
+ }
+ return 0;
+}
+#endif
+
+static int devtmpfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
+{
+ struct devtmpfs_sb *superblock;
+
+ superblock = rt_calloc(1, sizeof(struct devtmpfs_sb));
+ if (superblock)
+ {
+ superblock->df_size = sizeof(struct devtmpfs_sb);
+ superblock->magic = TMPFS_MAGIC;
+ rt_list_init(&superblock->sibling);
+
+ superblock->root.name[0] = '/';
+ superblock->root.sb = superblock;
+ superblock->root.type = TMPFS_TYPE_DIR;
+ superblock->root.mode = S_IFDIR | (S_IRUSR | S_IRGRP | S_IROTH) | (S_IXUSR | S_IXGRP | S_IXOTH);
+ rt_list_init(&superblock->root.sibling);
+ rt_list_init(&superblock->root.subdirs);
+
+ rt_spin_lock_init(&superblock->lock);
+
+ mnt->data = superblock;
+ }
+ else
+ {
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+static int devtmpfs_unmount(struct dfs_mnt *mnt)
+{
+#if 0
+ struct devtmpfs_sb *superblock;
+
+ /* FIXME: don't unmount on busy. */
+ superblock = (struct devtmpfs_sb *)mnt->data;
+ RT_ASSERT(superblock != NULL);
+
+ mnt->data = NULL;
+ _free_subdir(&(superblock->root));
+ rt_free(superblock);
+#endif
+ return -RT_ERROR;
+}
+
+static struct devtmpfs_file *devtmpfs_file_lookup(struct devtmpfs_sb *superblock, const char *path)
+{
+ const char *subpath, *curpath, *filename = RT_NULL;
+ char subdir_name[DIRENT_NAME_MAX];
+ struct devtmpfs_file *file, *curfile;
+ rt_list_t *list;
+
+ subpath = path;
+ while (*subpath == '/' && *subpath)
+ subpath ++;
+
+ if (! *subpath) /* is root directory */
+ {
+ return &(superblock->root);
+ }
+
+ curpath = subpath;
+ curfile = &superblock->root;
+
+find_subpath:
+ while (*subpath != '/' && *subpath)
+ subpath ++;
+
+ if (! *subpath) /* is last directory */
+ filename = curpath;
+ else
+ subpath ++; /* skip '/' */
+
+ memset(subdir_name, 0, DIRENT_NAME_MAX);
+ _get_subdir(curpath, subdir_name);
+
+ rt_spin_lock(&superblock->lock);
+
+ rt_list_for_each(list, &curfile->subdirs)
+ {
+ file = rt_list_entry(list, struct devtmpfs_file, sibling);
+ if (filename) /* find file */
+ {
+ if (rt_strcmp(file->name, filename) == 0)
+ {
+ rt_spin_unlock(&superblock->lock);
+ return file;
+ }
+ }
+ else if (rt_strcmp(file->name, subdir_name) == 0)
+ {
+ curpath = subpath;
+ curfile = file;
+ rt_spin_unlock(&superblock->lock);
+ goto find_subpath;
+ }
+ }
+ rt_spin_unlock(&superblock->lock);
+ /* not found */
+ return NULL;
+}
+
+static int devtmpfs_statfs(struct dfs_mnt *mnt, struct statfs *buf)
+{
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(mnt != NULL);
+ RT_ASSERT(buf != NULL);
+
+ superblock = (struct devtmpfs_sb *)mnt->data;
+ RT_ASSERT(superblock != NULL);
+
+ buf->f_bsize = 512;
+ buf->f_blocks = (superblock->df_size + 511) / 512;
+ buf->f_bfree = 1;
+ buf->f_bavail = buf->f_bfree;
+
+ return RT_EOK;
+}
+
+static int devtmpfs_stat(struct dfs_dentry *dentry, struct stat *st)
+{
+ struct dfs_vnode *vnode;
+
+ if (dentry && dentry->vnode)
+ {
+ vnode = dentry->vnode;
+
+ st->st_dev = (dev_t)(long)(dentry->mnt->dev_id);
+ st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry);
+
+ st->st_gid = vnode->gid;
+ st->st_uid = vnode->uid;
+ st->st_mode = vnode->mode;
+ st->st_nlink = vnode->nlink;
+ st->st_size = vnode->size;
+ st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
+ st->st_mtim.tv_sec = vnode->mtime.tv_sec;
+ st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
+ st->st_ctim.tv_sec = vnode->ctime.tv_sec;
+ st->st_atim.tv_nsec = vnode->atime.tv_nsec;
+ st->st_atim.tv_sec = vnode->atime.tv_sec;
+ }
+
+ return RT_EOK;
+}
+
+static int devtmpfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
+{
+ struct devtmpfs_file *d_file;
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(file);
+ RT_ASSERT(file->dentry);
+ RT_ASSERT(file->dentry->mnt);
+
+ superblock = (struct devtmpfs_sb *)file->dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ d_file = devtmpfs_file_lookup(superblock, file->dentry->pathname);
+ if (d_file)
+ {
+ rt_size_t index, end;
+ struct dirent *d;
+ struct devtmpfs_file *n_file;
+ rt_list_t *list;
+
+ /* make integer count */
+ count = (count / sizeof(struct dirent));
+ if (count == 0)
+ {
+ return -EINVAL;
+ }
+
+ end = file->fpos + count;
+ index = 0;
+ count = 0;
+
+ rt_list_for_each(list, &d_file->subdirs)
+ {
+ if (index >= (rt_size_t)file->fpos)
+ {
+ n_file = rt_list_entry(list, struct devtmpfs_file, sibling);
+
+ d = dirp + count;
+ if (n_file->type == TMPFS_TYPE_FILE)
+ {
+ d->d_type = DT_REG;
+ }
+ if (n_file->type == TMPFS_TYPE_DIR)
+ {
+ d->d_type = DT_DIR;
+ }
+
+ d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
+ rt_strncpy(d->d_name, n_file->name, DIRENT_NAME_MAX);
+ d->d_namlen = rt_strlen(d->d_name);
+
+ count += 1;
+ file->fpos += 1;
+ }
+ index += 1;
+ if (index >= end)
+ {
+ break;
+ }
+ }
+ }
+
+ return count * sizeof(struct dirent);
+}
+
+static int devtmpfs_symlink(struct dfs_dentry *parent_dentry, const char *target, const char *linkpath)
+{
+ int ret = RT_EOK;
+ struct devtmpfs_file *p_file, *l_file;
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(parent_dentry);
+ RT_ASSERT(parent_dentry->mnt);
+
+ superblock = (struct devtmpfs_sb *)parent_dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ p_file = devtmpfs_file_lookup(superblock, parent_dentry->pathname);
+ if (p_file)
+ {
+ l_file = (struct devtmpfs_file *)rt_calloc(1, sizeof(struct devtmpfs_file));
+ if (l_file)
+ {
+ superblock->df_size += sizeof(struct devtmpfs_file);
+
+ strncpy(l_file->name, linkpath, DIRENT_NAME_MAX - 1);
+
+ rt_list_init(&(l_file->subdirs));
+ rt_list_init(&(l_file->sibling));
+ l_file->sb = superblock;
+ l_file->type = TMPFS_TYPE_FILE;
+ l_file->mode = p_file->mode;
+ l_file->mode &= ~S_IFMT;
+ l_file->mode |= S_IFLNK;
+ l_file->link = rt_strdup(target);
+
+ rt_spin_lock(&superblock->lock);
+ rt_list_insert_after(&(p_file->subdirs), &(l_file->sibling));
+ rt_spin_unlock(&superblock->lock);
+ }
+ }
+
+ return ret;
+}
+
+static int devtmpfs_readlink(struct dfs_dentry *dentry, char *buf, int len)
+{
+ int ret = 0;
+ struct devtmpfs_file *d_file;
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(dentry);
+ RT_ASSERT(dentry->mnt);
+
+ superblock = (struct devtmpfs_sb *)dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ d_file = devtmpfs_file_lookup(superblock, dentry->pathname);
+ if (d_file)
+ {
+ if (d_file->link)
+ {
+ if (d_file->type == TMPFS_TYPE_DYN_DEV)
+ {
+ rt_device_t device = (void *)d_file->link;
+ buf[0] = '\0';
+ ret = device->readlink(device, buf, len);
+ if (ret == 0)
+ {
+ buf[len - 1] = '\0';
+ ret = rt_strlen(buf);
+ }
+ else
+ {
+ ret = 0;
+ }
+ }
+ else
+ {
+ rt_strncpy(buf, (const char *)d_file->link, len);
+ buf[len - 1] = '\0';
+ ret = rt_strlen(buf);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int devtmpfs_unlink(struct dfs_dentry *dentry)
+{
+ struct devtmpfs_file *d_file;
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(dentry);
+ RT_ASSERT(dentry->mnt);
+
+ superblock = (struct devtmpfs_sb *)dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ d_file = devtmpfs_file_lookup(superblock, dentry->pathname);
+ if (d_file)
+ {
+ if (d_file->link && d_file->type != TMPFS_TYPE_DYN_DEV)
+ {
+ rt_free(d_file->link);
+ }
+
+ rt_spin_lock(&superblock->lock);
+ rt_list_remove(&(d_file->sibling));
+ rt_spin_unlock(&superblock->lock);
+
+ rt_free(d_file);
+ }
+
+ return RT_EOK;
+}
+
+static int devtmpfs_setattr(struct dfs_dentry *dentry, struct dfs_attr *attr)
+{
+ struct devtmpfs_file *d_file;
+ struct devtmpfs_sb *superblock;
+
+ RT_ASSERT(dentry);
+ RT_ASSERT(dentry->mnt);
+
+ superblock = (struct devtmpfs_sb *)dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ d_file = devtmpfs_file_lookup(superblock, dentry->pathname);
+ if (d_file)
+ {
+ d_file->mode &= ~0xFFF;
+ d_file->mode |= attr->st_mode & 0xFFF;
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+
+static struct dfs_vnode *devtmpfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
+{
+ struct dfs_vnode *vnode = RT_NULL;
+ struct devtmpfs_sb *superblock;
+ struct devtmpfs_file *d_file, *p_file;
+ char parent_path[DFS_PATH_MAX], file_name[DIRENT_NAME_MAX];
+
+ if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
+ {
+ return NULL;
+ }
+
+ superblock = (struct devtmpfs_sb *)dentry->mnt->data;
+ RT_ASSERT(superblock != NULL);
+
+ vnode = dfs_vnode_create();
+ if (vnode)
+ {
+ /* find parent file */
+ _path_separate(dentry->pathname, parent_path, file_name);
+ if (file_name[0] == '\0') /* it's root dir */
+ {
+ dfs_vnode_destroy(vnode);
+ return NULL;
+ }
+
+ /* open parent directory */
+ p_file = devtmpfs_file_lookup(superblock, parent_path);
+ if (p_file == NULL)
+ {
+ dfs_vnode_destroy(vnode);
+ return NULL;
+ }
+
+ /* create a file entry */
+ d_file = (struct devtmpfs_file *)rt_calloc(1, sizeof(struct devtmpfs_file));
+ if (d_file == NULL)
+ {
+ dfs_vnode_destroy(vnode);
+ return NULL;
+ }
+
+ superblock->df_size += sizeof(struct devtmpfs_file);
+
+ strncpy(d_file->name, file_name, DIRENT_NAME_MAX);
+
+ rt_list_init(&(d_file->subdirs));
+ rt_list_init(&(d_file->sibling));
+ d_file->sb = superblock;
+
+ vnode->nlink = 1;
+ vnode->size = 0;
+ vnode->mode = mode;
+ vnode->mnt = dentry->mnt;
+ vnode->fops = &_default_fops;
+
+ if (type == FT_DIRECTORY)
+ {
+ d_file->type = TMPFS_TYPE_DIR;
+ vnode->type = FT_DIRECTORY;
+ vnode->mode &= ~S_IFMT;
+ vnode->mode |= S_IFDIR;
+ }
+ else
+ {
+ d_file->type = TMPFS_TYPE_FILE;
+ vnode->type = FT_DEVICE;
+ }
+
+ d_file->mode = vnode->mode;
+
+ rt_spin_lock(&superblock->lock);
+ rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
+ rt_spin_unlock(&superblock->lock);
+ }
+
+ return vnode;
+}
+
+static struct dfs_vnode *devtmpfs_lookup(struct dfs_dentry *dentry)
+{
+ struct dfs_vnode *vnode = RT_NULL;
+ struct devtmpfs_sb *superblock;
+ struct devtmpfs_file *d_file;
+
+ if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
+ {
+ return NULL;
+ }
+
+ superblock = (struct devtmpfs_sb *)dentry->mnt->data;
+
+ d_file = devtmpfs_file_lookup(superblock, dentry->pathname);
+ if (d_file)
+ {
+ vnode = dfs_vnode_create();
+ if (vnode)
+ {
+ vnode->nlink = 1;
+ vnode->size = 0;
+ vnode->mnt = dentry->mnt;
+ vnode->fops = &_default_fops;
+ vnode->mode = d_file->mode;
+
+ if (d_file->type == TMPFS_TYPE_DIR)
+ {
+ vnode->type = FT_DIRECTORY;
+ }
+ else if (d_file->link)
+ {
+ vnode->type = FT_SYMLINK;
+ }
+ else
+ {
+ vnode->type = FT_DEVICE;
+ }
+ }
+ }
+ else
+ {
+ rt_device_t device = RT_NULL;
+
+ device = rt_device_find(&dentry->pathname[1]);
+ if (device)
+ {
+ vnode = devtmpfs_create_vnode(dentry, FT_REGULAR, dfs_devfs_device_to_mode(device));
+ if (device->flag & RT_DEVICE_FLAG_DYNAMIC)
+ {
+ d_file = devtmpfs_file_lookup(superblock, dentry->pathname);
+ d_file->type = TMPFS_TYPE_DYN_DEV;
+ d_file->link = (char *)device;
+ }
+ }
+ }
+
+ return vnode;
+}
+
+static int devtmpfs_free_vnode(struct dfs_vnode *vnode)
+{
+ return RT_EOK;
+}
+
+static const struct dfs_filesystem_ops _devtmpfs_ops =
+{
+ .name = "devtmpfs",
+ .flags = DFS_FS_FLAG_DEFAULT,
+ .default_fops = &_default_fops,
+
+ .mount = devtmpfs_mount,
+ .umount = devtmpfs_unmount,
+
+ .symlink = devtmpfs_symlink,
+ .readlink = devtmpfs_readlink,
+
+ .unlink = devtmpfs_unlink,
+ .setattr = devtmpfs_setattr,
+
+ .statfs = devtmpfs_statfs,
+ .stat = devtmpfs_stat,
+
+ .lookup = devtmpfs_lookup,
+ .create_vnode = devtmpfs_create_vnode,
+ .free_vnode = devtmpfs_free_vnode
+};
+
+static struct dfs_filesystem_type _devtmpfs =
+{
+ .fs_ops = &_devtmpfs_ops,
+};
+
+int dfs_devtmpfs_init(void)
+{
+ _default_fops = *dfs_devfs_fops();
+ _default_fops.getdents = devtmpfs_getdents;
+
+ /* register file system */
+ dfs_register(&_devtmpfs);
+
+ dfs_mount(RT_NULL, "/dev", "devtmpfs", 0, RT_NULL);
+ dfs_devfs_update();
+
+ return 0;
+}
+INIT_COMPONENT_EXPORT(dfs_devtmpfs_init);
diff --git a/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c b/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c
index 70b34ef3cb..4546455a31 100644
--- a/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c
+++ b/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c
@@ -145,7 +145,7 @@ static struct dfs_vnode *dfs_mqueue_create_vnode(struct dfs_dentry *dentry, int
}
mq_file->msg_size = 8192;
mq_file->max_msgs = 10;
- strncpy(mq_file->name, dentry->pathname + 1, RT_NAME_MAX);
+ strncpy(mq_file->name, dentry->pathname + 1, RT_NAME_MAX - 1);
dfs_mqueue_insert_after(&(mq_file->list));
}
diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/README.md b/components/dfs/dfs_v2/filesystems/ptyfs/README.md
new file mode 100644
index 0000000000..1f805df80c
--- /dev/null
+++ b/components/dfs/dfs_v2/filesystems/ptyfs/README.md
@@ -0,0 +1,5 @@
+# The Pseudo Terminal Filesystem
+
+The device register on ptyfs is also registered in device frameworks with `rt_device_register()`.
+
+It's possible to mount a new ptyfs instance on another path. Each instance is isolated to each other. And they don't share the id system. But generally speaking, you have to mount the ptyfs on `/dev` root, since all the file nodes in ptyfs are devices.
diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/SConscript b/components/dfs/dfs_v2/filesystems/ptyfs/SConscript
new file mode 100644
index 0000000000..c0f8f39587
--- /dev/null
+++ b/components/dfs/dfs_v2/filesystems/ptyfs/SConscript
@@ -0,0 +1,11 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_PTYFS'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c
new file mode 100644
index 0000000000..c6f4f3d52d
--- /dev/null
+++ b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-12-02 Shell init ver.
+ */
+#define DBG_TAG "filesystem.ptyfs"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include "ptyfs.h"
+
+#include <dfs.h>
+#include <dfs_fs.h>
+#include <dfs_dentry.h>
+#include <dfs_file.h>
+#include <dfs_mnt.h>
+#include <devfs.h>
+#include <rid_bitmap.h>
+#include <rthw.h>
+#include <rtthread.h>
+#include <terminal/terminal.h>
+
+#include <dirent.h>
+#include <unistd.h>
+
+#ifndef S_IRWXUGO
+#define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
+#endif /* S_IRWXUGO */
+#ifndef S_IALLUGO
+#define S_IALLUGO (S_ISUID | S_ISGID | S_ISVTX | S_IRWXUGO)
+#endif /* S_IALLUGO */
+#ifndef S_IRUGO
+#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
+#endif /* S_IRUGO */
+#ifndef S_IWUGO
+#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
+#endif /* S_IWUGO */
+#ifndef S_IXUGO
+#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+#endif /* S_IXUGO */
+
+#define PTYFS_MAGIC 0x9D94A07D
+#define PTYFS_TYPE_DIR 0x00
+#define PTYFS_TYPE_FILE_PTMX 0x01
+#define PTYFS_TYPE_FILE_SLAVE 0x02
+
+/* TODO: using Symbolic permission, but not ours */
+#define PTMX_DEFAULT_FILE_MODE (S_IFCHR | 0666)
+#define PTS_DEFAULT_FILE_MODE (S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP)
+#define ROOT_DEFUALT_FILE_MODE (S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR)
+
+struct ptyfs_sb;
+
+struct ptyfs_file
+{
+ char basename[DIRENT_NAME_MAX]; /* file name */
+ rt_uint32_t mode; /* file modes allowed */
+ rt_uint32_t type; /* file type */
+ rt_list_t subdirs; /* file subdir list */
+ rt_list_t ent_node; /* entry node in subdir list */
+ struct ptyfs_sb *sb; /* superblock ptr */
+ rt_device_t device; /* device binding on this file */
+};
+
+struct ptyfs_sb
+{
+ struct rt_device ptmx_device; /* ptmx device */
+ struct rt_mutex lock; /* tmpfs lock */
+ struct ptyfs_file root_file; /* root dir */
+ struct ptyfs_file ptmx_file; /* `/ptmx` file */
+ struct rid_bitmap ptsno_pool; /* pts number pool */
+ rt_uint32_t magic; /* PTYFS_MAGIC */
+ rt_size_t df_size; /* df size */
+ rt_list_t sibling; /* sb sibling list */
+ struct dfs_mnt *mount; /* mount data */
+
+ /**
+ * Note: This upper limit is set to protect kernel memory from draining
+ * out by the application if it keeps allocating pty devices.
+ *
+ * Still, current implementation of bitmap can not efficiently use the
+ * memory
+ */
+ rt_bitmap_t
+ ptsno_pool_bitset[LWP_PTY_MAX_PARIS_LIMIT / (sizeof(rt_bitmap_t) * 8)];
+};
+
+static struct dfs_file_ops _default_fops;
+
+static int _split_out_subdir(const char *path, char *name)
+{
+ const char *subpath = path;
+
+ while (*subpath == '/' && *subpath)
+ {
+ subpath++;
+ }
+
+ while (*subpath != '/' && *subpath)
+ {
+ *name++ = *subpath++;
+ }
+
+ *name = '\0';
+ return 0;
+}
+
+static rt_err_t ptyfile_init(struct ptyfs_file *file, struct ptyfs_sb *sb,
+ const char *name, rt_uint32_t type,
+ rt_uint32_t mode, rt_device_t device)
+{
+ if (name)
+ strncpy(file->basename, name, sizeof(file->basename));
+
+ file->type = type;
+ file->mode = mode;
+ rt_list_init(&file->subdirs);
+ rt_list_init(&file->ent_node);
+ file->sb = sb;
+ file->device = device;
+
+ return 0;
+}
+
+static rt_err_t ptyfile_add_to_root(struct ptyfs_sb *sb,
+ struct ptyfs_file *new_file)
+{
+ struct ptyfs_file *root_file = &sb->root_file;
+
+ /* update super block */
+ sb->df_size += sizeof(struct ptyfs_file);
+
+ rt_mutex_take(&sb->lock, RT_WAITING_FOREVER);
+ rt_list_insert_after(&(root_file->subdirs), &(new_file->ent_node));
+ rt_mutex_release(&sb->lock);
+
+ return 0;
+}
+
+static rt_err_t ptyfile_remove_from_root(struct ptyfs_sb *sb,
+ struct ptyfs_file *rm_file)
+{
+ /* update super block */
+ sb->df_size -= sizeof(struct ptyfs_file);
+
+ rt_mutex_take(&sb->lock, RT_WAITING_FOREVER);
+ rt_list_remove(&(rm_file->ent_node));
+ rt_mutex_release(&sb->lock);
+
+ return 0;
+}
+
+static struct ptyfs_file *ptyfile_lookup(struct ptyfs_sb *superblock,
+ const char *path)
+{
+ const char *subpath_iter, *curpath_iter, *basename = RT_NULL;
+ char subdir_name[DIRENT_NAME_MAX];
+ struct ptyfs_file *curfile, *found_file = RT_NULL;
+ rt_list_t *list;
+ int do_path_resolve = 1;
+
+ subpath_iter = path;
+
+ /* skip starting "/" */
+ while (*subpath_iter == '/') subpath_iter++;
+ if (!*subpath_iter)
+ {
+ return &(superblock->root_file);
+ }
+
+ curpath_iter = subpath_iter;
+ curfile = &superblock->root_file;
+
+ /* resolve chain of files splited from path one by one */
+ while (do_path_resolve)
+ {
+ do_path_resolve = 0;
+
+ /* splitout sub-directory or basename */
+ while (*subpath_iter != '/' && *subpath_iter) subpath_iter++;
+ if (!*subpath_iter)
+ {
+ basename = curpath_iter;
+ }
+ else
+ {
+ _split_out_subdir(curpath_iter, subdir_name);
+
+ /* skip "/" for next search */
+ subpath_iter++;
+ }
+
+ rt_mutex_take(&superblock->lock, RT_WAITING_FOREVER);
+ rt_list_for_each(list, &curfile->subdirs)
+ {
+ struct ptyfs_file *file_iter;
+ file_iter = rt_list_entry(list, struct ptyfs_file, ent_node);
+ if (basename)
+ {
+ if (strcmp(file_iter->basename, basename) == 0)
+ {
+ found_file = file_iter;
+ break;
+ }
+ }
+ else if (strcmp(file_iter->basename, subdir_name) == 0)
+ {
+ curpath_iter = subpath_iter;
+ curfile = file_iter;
+ do_path_resolve = 1;
+ break;
+ }
+ }
+ rt_mutex_release(&superblock->lock);
+ }
+
+ return found_file;
+}
+
+const char *ptyfs_get_rootpath(rt_device_t ptmx)
+{
+ const char *rc;
+ struct ptyfs_sb *sb;
+ /* allocate id for it and register file */
+ sb = rt_container_of(ptmx, struct ptyfs_sb, ptmx_device);
+ if (sb->magic != PTYFS_MAGIC)
+ {
+ rc = 0;
+ }
+ else
+ {
+ /* fullpath is always started with /dev/ */
+ return sb->mount->fullpath + 5;
+ }
+
+ return rc;
+}
+
+ptsno_t ptyfs_register_pts(rt_device_t ptmx, rt_device_t pts)
+{
+ ptsno_t rc;
+ struct ptyfs_sb *sb;
+ struct ptyfs_file *pts_file;
+ struct rid_bitmap *ptsno_pool;
+
+ /* allocate id for it and register file */
+ sb = rt_container_of(ptmx, struct ptyfs_sb, ptmx_device);
+ if (sb->magic != PTYFS_MAGIC)
+ {
+ rc = -1;
+ }
+ else
+ {
+ ptsno_pool = &sb->ptsno_pool;
+ rc = rid_bitmap_get(ptsno_pool);
+ if (rc >= 0)
+ {
+ pts_file = rt_calloc(1, sizeof(struct ptyfs_file));
+ if (pts_file)
+ {
+ snprintf(pts_file->basename, DIRENT_NAME_MAX, "%lu", rc);
+ ptyfile_init(pts_file, sb, 0, PTYFS_TYPE_FILE_SLAVE,
+ PTS_DEFAULT_FILE_MODE, pts);
+ ptyfile_add_to_root(sb, pts_file);
+ }
+ else
+ {
+ rid_bitmap_put(ptsno_pool, rc);
+ rc = -1;
+ }
+ }
+ /* else rc == -1 */
+ }
+
+ return rc;
+}
+
+rt_err_t ptyfs_unregister_pts(rt_device_t ptmx, ptsno_t ptsno)
+{
+ ptsno_t rc;
+ struct ptyfs_sb *sb;
+ struct ptyfs_file *pts_file;
+ struct rid_bitmap *ptsno_pool;
+ char path_buf[DIRENT_NAME_MAX];
+
+ /* allocate id for it and register file */
+ sb = rt_container_of(ptmx, struct ptyfs_sb, ptmx_device);
+ if (sb->magic != PTYFS_MAGIC || ptsno < 0)
+ {
+ rc = -EINVAL;
+ }
+ else
+ {
+ /* get path and findout device */
+ snprintf(path_buf, sizeof(path_buf), "%lu", ptsno);
+ pts_file = ptyfile_lookup(sb, path_buf);
+ if (pts_file)
+ {
+ ptyfile_remove_from_root(sb, pts_file);
+ ptsno_pool = &sb->ptsno_pool;
+ rid_bitmap_put(ptsno_pool, ptsno);
+ rc = 0;
+ }
+ else
+ {
+ rc = -ENOENT;
+ }
+ }
+
+ return rc;
+}
+
+#define DEVFS_PREFIX "/dev/"
+#define DEVFS_PREFIX_LEN (sizeof(DEVFS_PREFIX) - 1)
+
+/**
+ * Create an new instance of ptyfs, and mount on target point
+ * 2 basic files are created: root, ptmx.
+ *
+ * todo: support of mount options?
+ */
+static int ptyfs_ops_mount(struct dfs_mnt *mnt, unsigned long rwflag,
+ const void *data)
+{
+ struct ptyfs_sb *sb;
+ rt_device_t ptmx_device;
+ rt_err_t rc;
+
+ if (strncmp(mnt->fullpath, DEVFS_PREFIX, DEVFS_PREFIX_LEN) != 0)
+ {
+ LOG_I("%s() Not mounted on `/dev/'", __func__);
+ return -EINVAL;
+ }
+
+ sb = rt_calloc(1, sizeof(struct ptyfs_sb));
+ if (sb)
+ {
+ rt_mutex_init(&sb->lock, "ptyfs", RT_IPC_FLAG_PRIO);
+
+ /* setup the ptmx device */
+ ptmx_device = &sb->ptmx_device;
+ rc = lwp_ptmx_init(ptmx_device, mnt->fullpath + DEVFS_PREFIX_LEN);
+ if (rc == RT_EOK)
+ {
+ /* setup 2 basic files */
+ ptyfile_init(&sb->root_file, sb, "/", PTYFS_TYPE_DIR,
+ ROOT_DEFUALT_FILE_MODE, 0);
+ ptyfile_init(&sb->ptmx_file, sb, "ptmx", PTYFS_TYPE_FILE_PTMX,
+ PTMX_DEFAULT_FILE_MODE, ptmx_device);
+ ptyfile_add_to_root(sb, &sb->ptmx_file);
+
+ /* setup rid */
+ rid_bitmap_init(&sb->ptsno_pool, 0, LWP_PTY_MAX_PARIS_LIMIT,
+ sb->ptsno_pool_bitset, &sb->lock);
+
+ /* setup properties and members */
+ sb->magic = PTYFS_MAGIC;
+
+ sb->df_size = sizeof(struct ptyfs_sb);
+ rt_list_init(&sb->sibling);
+
+ /* binding superblocks and mount point */
+ mnt->data = sb;
+ sb->mount = mnt;
+ rc = 0;
+ }
+ /* else just return rc */
+ }
+ else
+ {
+ rc = -ENOMEM;
+ }
+
+ return rc;
+}
+
+static int ptyfs_ops_umount(struct dfs_mnt *mnt)
+{
+ /* Not supported yet */
+ return -1;
+}
+
+static int ptyfs_ops_setattr(struct dfs_dentry *dentry, struct dfs_attr *attr)
+{
+ struct ptyfs_file *pty_file;
+ struct ptyfs_sb *superblock;
+
+ RT_ASSERT(dentry);
+ RT_ASSERT(dentry->mnt);
+
+ superblock = (struct ptyfs_sb *)dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ /* find the device related to current pts slave device */
+ pty_file = ptyfile_lookup(superblock, dentry->pathname);
+ if (pty_file && pty_file->type == PTYFS_TYPE_FILE_SLAVE)
+ {
+ pty_file->mode &= ~0xFFF;
+ pty_file->mode |= attr->st_mode & 0xFFF;
+ return 0;
+ }
+
+ return -1;
+}
+
+#define OPTIMAL_BSIZE 1024
+
+static int ptyfs_ops_statfs(struct dfs_mnt *mnt, struct statfs *buf)
+{
+ struct ptyfs_sb *superblock;
+
+ RT_ASSERT(mnt != NULL);
+ RT_ASSERT(buf != NULL);
+
+ superblock = (struct ptyfs_sb *)mnt->data;
+ RT_ASSERT(superblock != NULL);
+
+ buf->f_bsize = OPTIMAL_BSIZE;
+ buf->f_blocks = (superblock->df_size + OPTIMAL_BSIZE - 1) / OPTIMAL_BSIZE;
+ buf->f_bfree = 1;
+ buf->f_bavail = buf->f_bfree;
+
+ return RT_EOK;
+}
+
+static int ptyfs_ops_stat(struct dfs_dentry *dentry, struct stat *st)
+{
+ struct dfs_vnode *vnode;
+
+ if (dentry && dentry->vnode)
+ {
+ vnode = dentry->vnode;
+
+ /* device id ? */
+ st->st_dev = (dev_t)(long)(dentry->mnt->dev_id);
+ st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry);
+
+ st->st_gid = vnode->gid;
+ st->st_uid = vnode->uid;
+ st->st_mode = vnode->mode;
+ st->st_nlink = vnode->nlink;
+ st->st_size = vnode->size;
+ st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
+ st->st_mtim.tv_sec = vnode->mtime.tv_sec;
+ st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
+ st->st_ctim.tv_sec = vnode->ctime.tv_sec;
+ st->st_atim.tv_nsec = vnode->atime.tv_nsec;
+ st->st_atim.tv_sec = vnode->atime.tv_sec;
+ }
+
+ return 0;
+}
+
+static struct dfs_vnode *ptyfs_ops_lookup(struct dfs_dentry *dentry)
+{
+ struct dfs_vnode *vnode = RT_NULL;
+ struct ptyfs_sb *superblock;
+ struct ptyfs_file *pty_file;
+
+ if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
+ {
+ return NULL;
+ }
+
+ superblock = (struct ptyfs_sb *)dentry->mnt->data;
+
+ pty_file = ptyfile_lookup(superblock, dentry->pathname);
+ if (pty_file)
+ {
+ vnode = dfs_vnode_create();
+ if (vnode)
+ {
+ vnode->data = pty_file->device;
+ vnode->nlink = 1;
+ vnode->size = 0;
+ vnode->mnt = dentry->mnt;
+ /* if it's root directory */
+ vnode->fops = &_default_fops;
+ vnode->mode = pty_file->mode;
+ vnode->type = pty_file->type == PTYFS_TYPE_DIR ? FT_DIRECTORY : FT_DEVICE;
+ }
+ }
+
+ return vnode;
+}
+
+static struct dfs_vnode *ptyfs_ops_create_vnode(struct dfs_dentry *dentry,
+ int type, mode_t mode)
+{
+ struct dfs_vnode *vnode = RT_NULL;
+ struct ptyfs_sb *sb;
+ struct ptyfs_file *pty_file;
+ char *vnode_path;
+
+ if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
+ {
+ return NULL;
+ }
+
+ sb = (struct ptyfs_sb *)dentry->mnt->data;
+ RT_ASSERT(sb != NULL);
+
+ vnode = dfs_vnode_create();
+ if (vnode)
+ {
+ vnode_path = dentry->pathname;
+
+ /* Query if file existed. Filter out illegal open modes */
+ pty_file = ptyfile_lookup(sb, vnode_path);
+ if (!pty_file || (~pty_file->mode & mode))
+ {
+ dfs_vnode_destroy(vnode);
+ return NULL;
+ }
+
+ vnode->data = pty_file->device;
+ vnode->nlink = 1;
+ vnode->size = 0;
+ vnode->mnt = dentry->mnt;
+ vnode->fops = pty_file->device ? pty_file->device->fops : RT_NULL;
+ vnode->mode &= pty_file->mode;
+
+ if (type == FT_DIRECTORY)
+ {
+ vnode->mode |= S_IFDIR;
+ vnode->type = FT_DIRECTORY;
+ LOG_I("%s: S_IFDIR created", __func__);
+ }
+ else if (type == FT_REGULAR)
+ {
+ vnode->mode |= S_IFCHR;
+ vnode->type = FT_DEVICE;
+ LOG_I("%s: S_IFDIR created", __func__);
+ }
+ else
+ {
+ /* unsupported types */
+ dfs_vnode_destroy(vnode);
+ return NULL;
+ }
+ }
+
+ return vnode;
+}
+
+static int ptyfs_ops_free_vnode(struct dfs_vnode *vnode)
+{
+ return RT_EOK;
+}
+
+static int devpty_deffops_getdents(struct dfs_file *file, struct dirent *dirp,
+ uint32_t count)
+{
+ struct ptyfs_file *d_file;
+ struct ptyfs_sb *superblock;
+
+ RT_ASSERT(file);
+ RT_ASSERT(file->dentry);
+ RT_ASSERT(file->dentry->mnt);
+
+ superblock = (struct ptyfs_sb *)file->dentry->mnt->data;
+ RT_ASSERT(superblock);
+
+ d_file = ptyfile_lookup(superblock, file->dentry->pathname);
+ if (d_file)
+ {
+ rt_size_t index, end;
+ struct dirent *d;
+ struct ptyfs_file *n_file;
+ rt_list_t *list;
+
+ /* make integer count */
+ count = (count / sizeof(struct dirent));
+ if (count == 0)
+ {
+ return -EINVAL;
+ }
+
+ end = file->fpos + count;
+ index = 0;
+ count = 0;
+
+ rt_list_for_each(list, &d_file->subdirs)
+ {
+ if (index >= (rt_size_t)file->fpos)
+ {
+ n_file = rt_list_entry(list, struct ptyfs_file, ent_node);
+
+ d = dirp + count;
+ if (n_file->type == PTYFS_TYPE_DIR)
+ {
+ d->d_type = DT_DIR;
+ }
+ else
+ {
+ /* ptmx(5,2) or slave(136,[0,1048575]) device, on Linux */
+ d->d_type = DT_CHR;
+ }
+
+ d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
+ rt_strncpy(d->d_name, n_file->basename, DIRENT_NAME_MAX);
+ d->d_namlen = rt_strlen(d->d_name);
+
+ count += 1;
+ file->fpos += 1;
+ }
+ index += 1;
+ if (index >= end)
+ {
+ break;
+ }
+ }
+ }
+
+ return count * sizeof(struct dirent);
+}
+
+static const struct dfs_filesystem_ops _ptyfs_ops = {
+ .name = "ptyfs",
+ .flags = DFS_FS_FLAG_DEFAULT,
+ .default_fops = &_default_fops,
+
+ .mount = ptyfs_ops_mount,
+ .umount = ptyfs_ops_umount,
+
+ /* don't allow to create symbolic link */
+ .symlink = RT_NULL,
+ .readlink = RT_NULL,
+ .unlink = RT_NULL,
+
+ .setattr = ptyfs_ops_setattr,
+ .statfs = ptyfs_ops_statfs,
+ .stat = ptyfs_ops_stat,
+
+ .lookup = ptyfs_ops_lookup,
+ .create_vnode = ptyfs_ops_create_vnode,
+ .free_vnode = ptyfs_ops_free_vnode,
+};
+
+static struct dfs_filesystem_type _devptyfs = {
+ .fs_ops = &_ptyfs_ops,
+};
+
+static int _ptyfs_init(void)
+{
+ _default_fops = *dfs_devfs_fops();
+ _default_fops.getdents = devpty_deffops_getdents;
+
+ /* register file system */
+ dfs_register(&_devptyfs);
+
+ return 0;
+}
+INIT_COMPONENT_EXPORT(_ptyfs_init);
diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h
new file mode 100644
index 0000000000..69b2fb66fd
--- /dev/null
+++ b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-12-02 Shell init ver.
+ */
+#ifndef __FS_PTYFS_H__
+#define __FS_PTYFS_H__
+#include <rtthread.h>
+
+typedef rt_base_t ptsno_t;
+
+ptsno_t ptyfs_register_pts(rt_device_t ptmx, rt_device_t pts);
+
+rt_err_t ptyfs_unregister_pts(rt_device_t ptmx, ptsno_t ptsno);
+
+const char *ptyfs_get_rootpath(rt_device_t ptmx);
+
+#endif /* __FS_PTYFS_H__ */
diff --git a/components/dfs/dfs_v2/filesystems/romfs/romfs.c b/components/dfs/dfs_v2/filesystems/romfs/romfs.c
index 91465116b3..45279bcb83 100644
--- a/components/dfs/dfs_v2/filesystems/romfs/romfs.c
+++ b/components/dfs/dfs_v2/filesystems/romfs/romfs.c
@@ -29,6 +29,9 @@ rt_weak const struct romfs_dirent _root_dirent[] =
{
{ROMFS_DIRENT_DIR, "dev", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0},
+ {ROMFS_DIRENT_DIR, "proc", RT_NULL, 0},
+ {ROMFS_DIRENT_DIR, "etc", RT_NULL, 0},
+ {ROMFS_DIRENT_DIR, "bin", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "dummy", (rt_uint8_t *)_dummy, sizeof(_dummy) / sizeof(_dummy[0])},
{ROMFS_DIRENT_FILE, "dummy.txt", _dummy_txt, sizeof(_dummy_txt)},
};
diff --git a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c
index f289fc4419..8644f51c26 100644
--- a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c
+++ b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c
@@ -202,6 +202,7 @@ int dfs_tmpfs_ioctl(struct dfs_file *file, int cmd, void *args)
superblock = d_file->sb;
RT_ASSERT(superblock != NULL);
+ RT_UNUSED(superblock);
switch (cmd)
{
@@ -317,26 +318,21 @@ static ssize_t dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count, of
return length;
}
-static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
+static ssize_t _dfs_tmpfs_write(struct tmpfs_file *d_file, const void *buf, size_t count, off_t *pos)
{
- struct tmpfs_file *d_file;
struct tmpfs_sb *superblock;
- d_file = (struct tmpfs_file *)file->vnode->data;
RT_ASSERT(d_file != NULL);
superblock = d_file->sb;
RT_ASSERT(superblock != NULL);
- rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER);
-
- if (count + *pos > file->vnode->size)
+ if (count + *pos > d_file->size)
{
rt_uint8_t *ptr;
ptr = rt_realloc(d_file->data, *pos + count);
if (ptr == NULL)
{
- rt_mutex_release(&file->vnode->lock);
rt_set_errno(-ENOMEM);
return 0;
}
@@ -347,7 +343,6 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co
/* update d_file and file size */
d_file->data = ptr;
d_file->size = *pos + count;
- file->vnode->size = d_file->size;
LOG_D("tmpfile ptr:%x, size:%d", ptr, d_file->size);
}
@@ -356,6 +351,21 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co
/* update file current position */
*pos += count;
+
+ return count;
+}
+
+static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
+{
+ struct tmpfs_file *d_file;
+
+ d_file = (struct tmpfs_file *)file->vnode->data;
+ RT_ASSERT(d_file != NULL);
+
+ rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER);
+
+ count = _dfs_tmpfs_write(d_file, buf, count, pos);
+
rt_mutex_release(&file->vnode->lock);
return count;
@@ -504,6 +514,7 @@ static int dfs_tmpfs_getdents(struct dfs_file *file,
superblock = d_file->sb;
RT_ASSERT(superblock != RT_NULL);
+ RT_UNUSED(superblock);
/* make integer count */
count = (count / sizeof(struct dirent));
@@ -797,6 +808,8 @@ static ssize_t dfs_tmp_page_read(struct dfs_file *file, struct dfs_page *page)
ssize_t dfs_tmp_page_write(struct dfs_page *page)
{
+ off_t pos;
+ size_t count = 0;
struct tmpfs_file *d_file;
if (page->aspace->vnode->type == FT_DIRECTORY)
@@ -806,13 +819,16 @@ ssize_t dfs_tmp_page_write(struct dfs_page *page)
d_file = (struct tmpfs_file *)(page->aspace->vnode->data);
RT_ASSERT(d_file != RT_NULL);
+
rt_mutex_take(&page->aspace->vnode->lock, RT_WAITING_FOREVER);
if (page->len > 0)
- memcpy(d_file->data + page->fpos, page->page, page->len);
-
+ {
+ pos = page->fpos;
+ count = _dfs_tmpfs_write(d_file, page->page, page->len, &pos);
+ }
rt_mutex_release(&page->aspace->vnode->lock);
- return F_OK;
+ return count;
}
#endif
diff --git a/components/dfs/dfs_v2/include/dfs.h b/components/dfs/dfs_v2/include/dfs.h
index 6815f5e0ab..8b8c80188f 100644
--- a/components/dfs/dfs_v2/include/dfs.h
+++ b/components/dfs/dfs_v2/include/dfs.h
@@ -25,6 +25,10 @@
#include <rtatomic.h>
#include <rtdevice.h>
+#ifndef ATTR_MODE_SET
+#define ATTR_MODE_SET (1 << 6)
+#endif
+
#ifndef ATTR_ATIME_SET
#define ATTR_ATIME_SET (1 << 7)
#endif
@@ -33,6 +37,14 @@
#define ATTR_MTIME_SET (1 << 8)
#endif
+#ifndef ATTR_UID_SET
+#define ATTR_UID_SET (1 << 9)
+#endif
+
+#ifndef ATTR_GID_SET
+#define ATTR_GID_SET (1 << 10)
+#endif
+
#ifndef AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_NOFOLLOW 0x100
#endif
diff --git a/components/dfs/dfs_v2/include/dfs_file.h b/components/dfs/dfs_v2/include/dfs_file.h
index d62aec1e89..72539f3bbe 100644
--- a/components/dfs/dfs_v2/include/dfs_file.h
+++ b/components/dfs/dfs_v2/include/dfs_file.h
@@ -175,20 +175,25 @@ int dfs_file_isdir(const char *path);
int dfs_file_access(const char *path, mode_t mode);
int dfs_file_chdir(const char *path);
char *dfs_file_getcwd(char *buf, size_t size);
-char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode);
+
#ifdef RT_USING_SMART
int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2);
int dfs_file_mmap(struct dfs_file *file, struct dfs_mmap2_args *mmap2);
#endif
-char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode);
-
/* 0x5254 is just a magic number to make these relatively unique ("RT") */
#define RT_FIOFTRUNCATE 0x52540000U
#define RT_FIOGETADDR 0x52540001U
#define RT_FIOMMAP2 0x52540002U
+/* dfs_file_realpath mode */
+#define DFS_REALPATH_EXCEPT_LAST 0
+#define DFS_REALPATH_EXCEPT_NONE 1
+#define DFS_REALPATH_ONLY_LAST 3
+
+char *dfs_file_realpath(struct dfs_mnt **mnt, const char *fullpath, int mode);
+
#ifdef __cplusplus
}
#endif
diff --git a/components/dfs/dfs_v2/include/dfs_fs.h b/components/dfs/dfs_v2/include/dfs_fs.h
index 9dc99ee367..d30967aac5 100644
--- a/components/dfs/dfs_v2/include/dfs_fs.h
+++ b/components/dfs/dfs_v2/include/dfs_fs.h
@@ -32,7 +32,9 @@ struct dfs_partition
struct dfs_attr
{
unsigned int ia_valid;
- mode_t st_mode;
+ uid_t st_uid;
+ gid_t st_gid;
+ mode_t st_mode;
struct timespec ia_atime;
struct timespec ia_mtime;
};
diff --git a/components/dfs/dfs_v2/include/dfs_pcache.h b/components/dfs/dfs_v2/include/dfs_pcache.h
index 356df6c4f9..01abfe3150 100644
--- a/components/dfs/dfs_v2/include/dfs_pcache.h
+++ b/components/dfs/dfs_v2/include/dfs_pcache.h
@@ -23,6 +23,8 @@ extern "C"
{
#endif
+struct rt_varea;
+struct rt_aspace;
struct dfs_vnode;
struct dfs_dentry;
struct dfs_aspace;
@@ -30,7 +32,8 @@ struct dfs_aspace;
struct dfs_mmap
{
rt_list_t mmap_node;
- struct rt_varea *varea;
+ struct rt_aspace *aspace;
+ void *vaddr;
};
struct dfs_page
diff --git a/components/dfs/dfs_v2/src/dfs.c b/components/dfs/dfs_v2/src/dfs.c
index ad90822b93..939e4dd66e 100644
--- a/components/dfs/dfs_v2/src/dfs.c
+++ b/components/dfs/dfs_v2/src/dfs.c
@@ -557,6 +557,111 @@ exit:
return newfd;
}
+/**
+ * @brief The fd in the current process dup to designate fd table.
+ *
+ * @param oldfd is the fd in current process.
+ *
+ * @param fdtab is the fd table to dup, if empty, use global (_fdtab).
+ *
+ * @return -1 on failed or the allocated file descriptor.
+ */
+int dfs_dup_to(int oldfd, struct dfs_fdtable *fdtab)
+{
+ int newfd = -1;
+ struct dfs_fdtable *fdt = NULL;
+
+ if (dfs_file_lock() != RT_EOK)
+ {
+ return -RT_ENOSYS;
+ }
+
+ if (fdtab == NULL)
+ {
+ fdtab = &_fdtab;
+ }
+
+ /* check old fd */
+ fdt = dfs_fdtable_get();
+ if ((oldfd < 0) || (oldfd >= fdt->maxfd))
+ {
+ goto exit;
+ }
+ if (!fdt->fds[oldfd])
+ {
+ goto exit;
+ }
+ /* get a new fd*/
+ newfd = _fdt_slot_alloc(fdtab, DFS_STDIO_OFFSET);
+ if (newfd >= 0)
+ {
+ fdtab->fds[newfd] = fdt->fds[oldfd];
+
+ /* inc ref_count */
+ rt_atomic_add(&(fdtab->fds[newfd]->ref_count), 1);
+ }
+exit:
+ dfs_file_unlock();
+
+ return newfd;
+}
+
+/**
+ * @brief The fd in the designate fd table dup to current process.
+ *
+ * @param oldfd is the fd in the designate fd table.
+ *
+ * @param fdtab is the fd table for oldfd, if empty, use global (_fdtab).
+ *
+ * @return -1 on failed or the allocated file descriptor.
+ */
+int dfs_dup_from(int oldfd, struct dfs_fdtable *fdtab)
+{
+ int newfd = -1;
+ struct dfs_file *file;
+
+ if (dfs_file_lock() != RT_EOK)
+ {
+ return -RT_ENOSYS;
+ }
+
+ if (fdtab == NULL)
+ {
+ fdtab = &_fdtab;
+ }
+
+ /* check old fd */
+ if ((oldfd < 0) || (oldfd >= fdtab->maxfd))
+ {
+ goto exit;
+ }
+ if (!fdtab->fds[oldfd])
+ {
+ goto exit;
+ }
+ /* get a new fd*/
+ newfd = fd_new();
+ file = fd_get(newfd);
+ if (newfd >= 0 && file)
+ {
+ file->mode = fdtab->fds[oldfd]->mode;
+ file->flags = fdtab->fds[oldfd]->flags;
+ file->fops = fdtab->fds[oldfd]->fops;
+ file->dentry = dfs_dentry_ref(fdtab->fds[oldfd]->dentry);
+ file->vnode = fdtab->fds[oldfd]->vnode;
+ file->mmap_context = RT_NULL;
+ file->data = fdtab->fds[oldfd]->data;
+ }
+
+ dfs_file_close(fdtab->fds[oldfd]);
+
+exit:
+ fdt_fd_release(fdtab, oldfd);
+ dfs_file_unlock();
+
+ return newfd;
+}
+
#ifdef RT_USING_SMART
sysret_t sys_dup(int oldfd)
#else
@@ -856,7 +961,11 @@ int dfs_fd_dump(int argc, char** argv)
{
int index;
- dfs_file_lock();
+ if (dfs_file_lock() != RT_EOK)
+ {
+ return -RT_ENOSYS;
+ }
+
for (index = 0; index < _fdtab.maxfd; index++)
{
struct dfs_file *file = _fdtab.fds[index];
diff --git a/components/dfs/dfs_v2/src/dfs_file.c b/components/dfs/dfs_v2/src/dfs_file.c
index 5f55eaaba1..c51208a5f2 100644
--- a/components/dfs/dfs_v2/src/dfs_file.c
+++ b/components/dfs/dfs_v2/src/dfs_file.c
@@ -29,22 +29,86 @@
#define MAX_RW_COUNT 0xfffc0000
-rt_inline int _find_path_node(const char *path)
+rt_inline int _first_path_len(const char *path)
{
int i = 0;
- while (path[i] != '\0')
+ if (path[i] == '/')
{
- if ('/' == path[i++])
+ i++;
+ while (path[i] != '\0' && path[i] != '/')
{
- break;
+ i++;
}
}
- /* return path-note length */
return i;
}
+static int _get_parent_path(const char *fullpath, char *path)
+{
+ int len = 0;
+ char *str = 0;
+
+ str = strrchr(fullpath, '/');
+ if (str)
+ {
+ len = str - fullpath;
+ if (len > 0)
+ {
+ rt_memcpy(path, fullpath, len);
+ path[len] = '\0';
+ }
+ }
+
+ return len;
+}
+
+static int _try_readlink(const char *path, struct dfs_mnt *mnt, char *link)
+{
+ int ret = -1;
+ struct dfs_dentry *dentry = dfs_dentry_lookup(mnt, path, 0);
+
+ if (dentry && dentry->vnode->type == FT_SYMLINK)
+ {
+ if (mnt->fs_ops->readlink)
+ {
+ if (dfs_is_mounted(mnt) == 0)
+ {
+ ret = mnt->fs_ops->readlink(dentry, link, DFS_PATH_MAX);
+ }
+ }
+ }
+ dfs_dentry_unref(dentry);
+
+ return ret;
+}
+
+static int _insert_link_path(const char *link_fn, int link_len, char *tmp_path, int *index)
+{
+ int ret = -1;
+
+ if (link_fn[0] != '/')
+ {
+ if (link_len + 1 <= *index)
+ {
+ *index -= link_len;
+ rt_memcpy(tmp_path + *index, link_fn, link_len);
+ *index -= 1;
+ tmp_path[*index] = '/';
+ ret = 0;
+ }
+ }
+ else if (link_len <= *index)
+ {
+ *index -= link_len;
+ rt_memcpy(tmp_path + *index, link_fn, link_len);
+ ret = 1;
+ }
+
+ return ret;
+}
+
/*
* rw_verify_area doesn't like huge counts. We limit
* them to something that fits in "int" so that others
@@ -149,166 +213,97 @@ static void dfs_file_unref(struct dfs_file *file)
}
}
-struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry)
-{
- int ret = 0;
- struct dfs_dentry *tmp = dfs_dentry_ref(dentry);
-
- if (dentry && dentry->vnode && dentry->vnode->type == FT_SYMLINK)
- {
- char *buf = NULL;
-
- buf = (char *)rt_malloc(DFS_PATH_MAX);
- if (buf)
- {
- do
- {
- if (dfs_is_mounted(tmp->mnt) == 0)
- {
- ret = tmp->mnt->fs_ops->readlink(tmp, buf, DFS_PATH_MAX);
- }
-
- if (ret > 0)
- {
- struct dfs_mnt *mnt = NULL;
-
- if (buf[0] != '/')
- {
- char *dir = dfs_dentry_pathname(tmp);
-
- /* is the relative directory */
- if (dir)
- {
- char *fullpath = dfs_normalize_path(dir, buf);
- if (fullpath)
- {
- strncpy(buf, fullpath, DFS_PATH_MAX);
-
- rt_free(fullpath);
- }
- rt_free(dir);
- }
- }
-
- mnt = dfs_mnt_lookup(buf);
- if (mnt)
- {
- struct dfs_dentry *de = dfs_dentry_lookup(mnt, buf, 0);
-
- /* release the old dentry */
- dfs_dentry_unref(tmp);
- tmp = de;
- }
- }
- else
- {
- break;
- }
- } while (tmp && tmp->vnode->type == FT_SYMLINK);
- }
-
- rt_free(buf);
- }
-
- return tmp;
-}
-
/*
* this function is creat a nolink path.
*
* @param mnt
* @param fullpath
- * @param mode 0 middle path nolink; 1 all path nolink.
+ * @param mode
*
* @return new path.
*/
-char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
+char *dfs_file_realpath(struct dfs_mnt **mnt, const char *fullpath, int mode)
{
- int index = 0;
- char *path = RT_NULL;
- char *link_fn;
- struct dfs_dentry *dentry = RT_NULL;
-
- path = (char *)rt_malloc((DFS_PATH_MAX * 2) + 2); // path + \0 + link_fn + \0
- if (!path)
- {
- return path;
- }
- link_fn = path + DFS_PATH_MAX + 1;
+ int path_len = 0, index = 0;
+ char *path = RT_NULL, *link_fn, *tmp_path;
+ struct dfs_mnt *tmp_mnt;
if (*mnt && fullpath)
{
- int i = 0;
- char *fp = fullpath;
+ int len, link_len;
+
+ path = (char *)rt_malloc((DFS_PATH_MAX * 3) + 3); // path + \0 + link_fn + \0 + tmp_path + \0
+ if (!path)
+ {
+ return RT_NULL;
+ }
+
+ link_fn = path + DFS_PATH_MAX + 1;
+ tmp_path = link_fn + (DFS_PATH_MAX + 1);
+
+ len = rt_strlen(fullpath);
+ if (len > DFS_PATH_MAX)
+ {
+ goto _ERR_RET;
+ }
+
+ index = (DFS_PATH_MAX - len);
+ rt_strcpy(tmp_path + index, fullpath);
+
+ if (mode == DFS_REALPATH_ONLY_LAST)
+ {
+ path_len = _get_parent_path(fullpath, path);
+ index += path_len;
+ }
- while ((i = _find_path_node(fp)) > 0)
+ while ((len = _first_path_len(tmp_path + index)) > 0)
{
- if (i + index > DFS_PATH_MAX)
+ if (len + path_len > DFS_PATH_MAX)
{
goto _ERR_RET;
}
- rt_memcpy(path + index, fp, i);
- path[index + i] = '\0';
+ rt_memcpy(path + path_len, tmp_path + index, len);
+ path[path_len + len] = '\0';
+ index += len;
- /* the last should by mode process. */
- if ((fp[i] == '\0') && (!mode))
+ tmp_mnt = dfs_mnt_lookup(path);
+ if (tmp_mnt == RT_NULL)
{
- break;
+ goto _ERR_RET;
}
- fp += i;
+ *mnt = tmp_mnt;
- dentry = dfs_dentry_lookup(*mnt, path, 0);
- if (dentry && dentry->vnode->type == FT_SYMLINK)
+ /* the last should by mode process. */
+ if ((tmp_path[index] == '\0') && (mode == DFS_REALPATH_EXCEPT_LAST))
{
- int ret = -1;
+ break;
+ }
- if ((*mnt)->fs_ops->readlink)
- {
- if (dfs_is_mounted((*mnt)) == 0)
- {
- ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
- }
- }
+ link_len = _try_readlink(path, *mnt, link_fn);
+ if (link_len > 0)
+ {
+ int ret = _insert_link_path(link_fn, link_len, tmp_path, &index);
- if (ret > 0)
+ if (ret == 1)
{
- int len = rt_strlen(link_fn);
-
- if (link_fn[0] != '/')
- {
- path[index] = '/';
- }
- else
- {
- index = 0;
- }
-
- if (len + index + 1 >= DFS_PATH_MAX)
- {
- goto _ERR_RET;
- }
-
- rt_memcpy(path + index, link_fn, len);
- index += len;
- path[index] = '\0';
- *mnt = dfs_mnt_lookup(path);
+ /* link_fn[0] == '/' */
+ path_len = 0;
}
- else
+ else if (ret < 0)
{
goto _ERR_RET;
}
}
else
{
- index += i;
+ path_len += len;
}
- dfs_dentry_unref(dentry);
}
- }
- else
- {
+
+ return path;
+
_ERR_RET:
rt_free(path);
path = RT_NULL;
@@ -349,7 +344,7 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(fullpath);
@@ -370,9 +365,12 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo
else
{
struct dfs_dentry *target_dentry = RT_NULL;
-
- /* follow symbol link */
- target_dentry = dfs_file_follow_link(dentry);
+ char *path = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_ONLY_LAST);
+ if (path)
+ {
+ target_dentry = dfs_dentry_lookup(mnt, path, oflags);
+ rt_free(path);
+ }
dfs_dentry_unref(dentry);
dentry = target_dentry;
}
@@ -507,7 +505,7 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo
if (ret < 0)
{
- LOG_E("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name);
+ LOG_I("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name);
DLOG(msg, mnt->fs_ops->name, "dfs_file", DLOG_MSG_RET, "open failed.");
dfs_file_unref(file);
}
@@ -791,7 +789,7 @@ int dfs_file_stat(const char *path, struct stat *buf)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 1);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_NONE);
if (tmp)
{
rt_free(fullpath);
@@ -845,7 +843,7 @@ int dfs_file_lstat(const char *path, struct stat *buf)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(fullpath);
@@ -924,7 +922,7 @@ int dfs_file_setattr(const char *path, struct dfs_attr *attr)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(fullpath);
@@ -1097,7 +1095,7 @@ int dfs_file_unlink(const char *path)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(fullpath);
@@ -1199,7 +1197,7 @@ int dfs_file_link(const char *oldname, const char *newname)
return -1;
}
- char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, old_fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(old_fullpath);
@@ -1210,7 +1208,7 @@ int dfs_file_link(const char *oldname, const char *newname)
new_fullpath = dfs_normalize_path(NULL, newname);
if (new_fullpath)
{
- char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, new_fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(new_fullpath);
@@ -1310,7 +1308,7 @@ int dfs_file_symlink(const char *target, const char *linkpath)
mnt = dfs_mnt_lookup(parent);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, parent, 0);
+ char *tmp = dfs_file_realpath(&mnt, parent, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(parent);
@@ -1318,7 +1316,7 @@ int dfs_file_symlink(const char *target, const char *linkpath)
}
DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, parent, 0);
+ dentry = dfs_dentry_lookup(mnt, parent, DFS_REALPATH_EXCEPT_LAST);
if (dentry)
{
if (dentry->mnt->fs_ops->symlink)
@@ -1326,17 +1324,6 @@ int dfs_file_symlink(const char *target, const char *linkpath)
char *path = dfs_normalize_path(parent, target);
if (path)
{
- char *tmp = dfs_nolink_path(&mnt, path, 0);
- if (tmp)
- {
- rt_free(path);
- path = tmp;
- }
- else
- {
- tmp = path;
- }
-
ret = rt_strncmp(parent, path, strlen(parent));
if (ret == 0)
{
@@ -1346,6 +1333,10 @@ int dfs_file_symlink(const char *target, const char *linkpath)
tmp ++;
}
}
+ else
+ {
+ tmp = path;
+ }
if (dfs_is_mounted(mnt) == 0)
{
@@ -1401,7 +1392,7 @@ int dfs_file_readlink(const char *path, char *buf, int bufsize)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(fullpath);
@@ -1466,7 +1457,7 @@ int dfs_file_rename(const char *old_file, const char *new_file)
return -1;
}
- char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, old_fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(old_fullpath);
@@ -1477,7 +1468,7 @@ int dfs_file_rename(const char *old_file, const char *new_file)
new_fullpath = dfs_normalize_path(NULL, new_file);
if (new_fullpath)
{
- char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, new_fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
rt_free(new_fullpath);
@@ -1652,7 +1643,7 @@ int dfs_file_isdir(const char *path)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 1);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_NONE);
if (tmp)
{
rt_free(fullpath);
@@ -1853,7 +1844,7 @@ void ls(const char *pathname)
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
+ char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST);
if (tmp)
{
char *index;
diff --git a/components/dfs/dfs_v2/src/dfs_pcache.c b/components/dfs/dfs_v2/src/dfs_pcache.c
index 11f6172d08..57f4510e93 100644
--- a/components/dfs/dfs_v2/src/dfs_pcache.c
+++ b/components/dfs/dfs_v2/src/dfs_pcache.c
@@ -269,7 +269,6 @@ static void dfs_pcache_thread(void *parameter)
{
page->len = page->size;
}
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
if (aspace->ops->write)
{
aspace->ops->write(page);
@@ -676,9 +675,14 @@ static int dfs_page_unmap(struct dfs_page *page)
if (map)
{
- void *vaddr = dfs_aspace_vaddr(map->varea, page->fpos);
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE);
- rt_varea_unmap_page(map->varea, vaddr);
+ rt_varea_t varea;
+ void *vaddr;
+
+ varea = rt_aspace_query(map->aspace, map->vaddr);
+ RT_ASSERT(varea);
+ vaddr = dfs_aspace_vaddr(varea, page->fpos);
+
+ rt_varea_unmap_page(varea, vaddr);
rt_free(map);
}
@@ -741,7 +745,6 @@ static void dfs_page_release(struct dfs_page *page)
{
page->len = page->size;
}
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
if (aspace->ops->write)
{
aspace->ops->write(page);
@@ -995,7 +998,6 @@ static struct dfs_page *dfs_aspace_load_page(struct dfs_file *file, off_t pos)
page->size = ARCH_PAGE_SIZE;
page->fpos = pos / ARCH_PAGE_SIZE * ARCH_PAGE_SIZE;
aspace->ops->read(file, page);
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
page->ref_count ++;
dfs_page_insert(page);
@@ -1105,7 +1107,6 @@ int dfs_aspace_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
len = count > len ? len : count;
if (len)
{
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
rt_memcpy(ptr, page->page + *pos - page->fpos, len);
ptr += len;
*pos += len;
@@ -1158,7 +1159,6 @@ int dfs_aspace_write(struct dfs_file *file, const void *buf, size_t count, off_t
len = page->fpos + ARCH_PAGE_SIZE - *pos;
len = count > len ? len : count;
rt_memcpy(page->page + *pos - page->fpos, ptr, len);
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
ptr += len;
*pos += len;
count -= len;
@@ -1225,7 +1225,7 @@ int dfs_aspace_flush(struct dfs_aspace *aspace)
{
page->len = page->size;
}
- //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
+
if (aspace->ops->write)
{
aspace->ops->write(page);
@@ -1277,6 +1277,7 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr
void *ret = RT_NULL;
struct dfs_page *page;
struct dfs_aspace *aspace = file->vnode->aspace;
+ rt_aspace_t target_aspace = varea->aspace;
page = dfs_page_lookup(file, dfs_aspace_fpos(varea, vaddr));
if (page)
@@ -1284,7 +1285,8 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr
struct dfs_mmap *map = (struct dfs_mmap *)rt_calloc(1, sizeof(struct dfs_mmap));
if (map)
{
- void *pg_paddr = rt_kmem_v2p(page->page);
+ void *pg_vaddr = page->page;
+ void *pg_paddr = rt_kmem_v2p(pg_vaddr);
int err = rt_varea_map_range(varea, vaddr, pg_paddr, page->size);
if (err == RT_EOK)
{
@@ -1301,10 +1303,12 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr
* fetching of the next instruction can see the coherent data with the data cache,
* TLB, MMU, main memory, and all the other observers in the computer system.
*/
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE);
rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, vaddr, ARCH_PAGE_SIZE);
- ret = page->page;
- map->varea = varea;
+ ret = pg_vaddr;
+ map->aspace = target_aspace;
+ map->vaddr = vaddr;
dfs_aspace_lock(aspace);
rt_list_insert_after(&page->mmap_head, &map->mmap_node);
dfs_page_release(page);
@@ -1329,6 +1333,8 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea)
{
struct dfs_vnode *vnode = file->vnode;
struct dfs_aspace *aspace = vnode->aspace;
+ void *unmap_start = varea->start;
+ void *unmap_end = (char *)unmap_start + varea->size;
if (aspace)
{
@@ -1347,20 +1353,32 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea)
{
rt_list_t *node, *tmp;
struct dfs_mmap *map;
+ rt_varea_t map_varea = RT_NULL;
node = page->mmap_head.next;
while (node != &page->mmap_head)
{
+ rt_aspace_t map_aspace;
map = rt_list_entry(node, struct dfs_mmap, mmap_node);
tmp = node;
node = node->next;
- if (map && varea == map->varea)
+ if (map && varea->aspace == map->aspace
+ && map->vaddr >= unmap_start && map->vaddr < unmap_end)
{
- void *vaddr = dfs_aspace_vaddr(map->varea, page->fpos);
+ void *vaddr = map->vaddr;
+ map_aspace = map->aspace;
+
+ if (!map_varea || map_varea->aspace != map_aspace ||
+ vaddr < map_varea->start ||
+ vaddr >= map_varea->start + map_varea->size)
+ {
+ /* lock the tree so we don't access uncompleted data */
+ map_varea = rt_aspace_query(map_aspace, vaddr);
+ }
- rt_varea_unmap_page(map->varea, vaddr);
+ rt_varea_unmap_page(map_varea, vaddr);
if (varea->attr == MMU_MAP_U_RWCB && page->fpos < page->aspace->vnode->size)
{
@@ -1405,7 +1423,7 @@ int dfs_aspace_page_unmap(struct dfs_file *file, struct rt_varea *varea, void *v
tmp = node;
node = node->next;
- if (map && varea == map->varea)
+ if (map && varea->aspace == map->aspace && vaddr == map->vaddr)
{
if (varea->attr == MMU_MAP_U_RWCB)
{