From 9da01f0d46fafa233767305d657ebb5746dcf8de Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 9 Jan 2020 15:10:22 +0200 Subject: [PATCH] Merge devfs into dev.c, add stat() --- etc/make/conf.mk | 1 - include/sys/amd64/sys_file.h | 1 + include/sys/fs/vfs.h | 2 +- include/sys/syscall.h | 1 + sys/amd64/sys_file.c | 9 ++- sys/amd64/syscall.c | 1 + sys/dev.c | 121 +++++++++++++++++++++++++++++++++++ sys/vfs/devfs.c | 84 ------------------------ sys/vfs/vfs.c | 13 ++-- 9 files changed, 141 insertions(+), 92 deletions(-) delete mode 100644 sys/vfs/devfs.c diff --git a/etc/make/conf.mk b/etc/make/conf.mk index 5f4be87..e65e69c 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -67,7 +67,6 @@ OBJS+=$(O)/sys/debug.o \ $(O)/sys/net/arp.o \ $(O)/sys/net/in.o \ $(O)/sys/net/netdev.o \ - $(O)/sys/vfs/devfs.o \ $(O)/sys/vfs/pseudo.o \ $(O)/sys/vfs/pty.o \ $(O)/sys/reboot.o diff --git a/include/sys/amd64/sys_file.h b/include/sys/amd64/sys_file.h index 09fcc69..0a0cecf 100644 --- a/include/sys/amd64/sys_file.h +++ b/include/sys/amd64/sys_file.h @@ -15,6 +15,7 @@ int sys_chdir(const char *filename); int sys_mkdir(const char *pathname, int mode); int sys_unlink(const char *pathname); +int sys_rmdir(const char *pathname); int sys_stat(const char *filename, struct stat *st); int sys_access(const char *path, int mode); diff --git a/include/sys/fs/vfs.h b/include/sys/fs/vfs.h index 945084a..5131b6e 100644 --- a/include/sys/fs/vfs.h +++ b/include/sys/fs/vfs.h @@ -137,7 +137,7 @@ int vfs_open_node(struct vfs_ioctx *ctx, struct ofile *fd, vnode_t *vn, int opt) void vfs_close(struct vfs_ioctx *ctx, struct ofile *fd); ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t count); ssize_t vfs_write(struct vfs_ioctx *ctx, struct ofile *fd, const void *buf, size_t count); -int vfs_unlink(struct vfs_ioctx *ctx, const char *path); +int vfs_unlink(struct vfs_ioctx *ctx, const char *path, int is_rmdir); int vfs_stat(struct vfs_ioctx *ctx, const char *path, struct stat *st); int vfs_statat(struct vfs_ioctx *ctx, vnode_t *at, const char *path, struct stat *st); diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 3f1ee0e..5bcc902 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -9,6 +9,7 @@ #define SYSCALL_NR_GETCWD 79 #define SYSCALL_NR_CHDIR 80 #define SYSCALL_NR_MKDIR 83 +#define SYSCALL_NR_RMDIR 84 #define SYSCALL_NR_CREAT 85 #define SYSCALL_NR_UNLINK 87 #define SYSCALL_NR_READDIR 89 diff --git a/sys/amd64/sys_file.c b/sys/amd64/sys_file.c index f6a0031..04d2e2e 100644 --- a/sys/amd64/sys_file.c +++ b/sys/amd64/sys_file.c @@ -81,7 +81,14 @@ int sys_unlink(const char *pathname) { struct thread *thr = get_cpu()->thread; _assert(thr); - return vfs_unlink(&thr->ioctx, pathname); + return vfs_unlink(&thr->ioctx, pathname, 0); +} + +int sys_rmdir(const char *pathname) { + struct thread *thr = get_cpu()->thread; + _assert(thr); + + return vfs_unlink(&thr->ioctx, pathname, 1); } int sys_chdir(const char *filename) { diff --git a/sys/amd64/syscall.c b/sys/amd64/syscall.c index be6862b..c47b10e 100644 --- a/sys/amd64/syscall.c +++ b/sys/amd64/syscall.c @@ -25,6 +25,7 @@ const void *amd64_syscall_jmp_table[256] = { [SYSCALL_NR_UNLINK] = sys_unlink, [SYSCALL_NR_MKDIR] = sys_mkdir, [SYSCALL_NR_CREAT] = sys_creat, + [SYSCALL_NR_RMDIR] = sys_rmdir, // Process [SYSCALL_NR_EXIT] = sys_exit, diff --git a/sys/dev.c b/sys/dev.c index 8fa837f..dc4c5b5 100644 --- a/sys/dev.c +++ b/sys/dev.c @@ -4,6 +4,14 @@ #include "sys/panic.h" #include "sys/debug.h" #include "sys/string.h" +#include "sys/fs/devfs.h" +#include "sys/fs/vfs.h" +#include "sys/string.h" +#include "sys/fs/fs.h" +#include "sys/attr.h" +#include "sys/heap.h" + +static struct vfs_node *devfs_root_node = NULL; static struct dev_entry *dev_begin = NULL; static struct dev_entry *dev_end = NULL; @@ -81,3 +89,116 @@ void dev_entry_add(struct dev_entry *ent) { struct dev_entry *dev_iter(void) { return dev_begin; } + +static int devfs_node_mapper(fs_t *devfs, struct vfs_node **root); +static int devfs_node_stat(vnode_t *node, struct stat *st); + +static struct fs_class _devfs = { + .name = "devfs", + .opt = FS_NODE_MAPPER, + .mapper = devfs_node_mapper +}; + +static struct vnode_operations _devfs_vnode_op = { + .stat = devfs_node_stat +}; + +static int devfs_node_stat(vnode_t *node, struct stat *st) { + // TODO: device modes (permissions) + + st->st_size = 0; + st->st_blocks = 0; + st->st_blksize = 0; + + st->st_atime = 0; + st->st_mtime = 0; + st->st_ctime = 0; + + st->st_dev = 0; + st->st_rdev = 0; + + st->st_ino = 0; + st->st_nlink = 1; + + st->st_uid = 0; + st->st_gid = 0; + + if (node == devfs_root_node->vnode) { + st->st_mode = S_IFDIR | 0755; + } else { + struct dev_entry *ent = node->fs_data; + _assert(ent); + if (ent->dev_class == DEV_CLASS_BLOCK) { + st->st_mode = S_IFBLK | 0600; + } else { + st->st_mode = S_IFCHR | 0600; + } + } + + return 0; +} + +static vnode_t *devfs_create_vnode(fs_t *fs, struct vfs_node *node) { + vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t)); + res->tree_node = node; + res->fs = fs; + res->fs_data = NULL; + res->refcount = 0; + res->op = &_devfs_vnode_op; + res->type = VN_DIR; + return res; +} + +static int devfs_node_mapper(fs_t *devfs, struct vfs_node **root) { + _assert(!devfs_root_node); + struct vfs_node *_root; + struct dev_entry *it; + + // Make a root node + _root = (struct vfs_node *) kmalloc(sizeof(struct vfs_node)); + _root->child = NULL; + _root->cdr = NULL; + _root->ismount = 0; + _root->parent = NULL; + _root->real_vnode = NULL; + _root->vnode = NULL; + + // TODO: directory-categories (like "by-uuid" or something) + for (it = dev_iter(); it; it = it->cdr) { + struct vfs_node *ent_node = kmalloc(sizeof(struct vfs_node)); + ent_node->child = NULL; + ent_node->ismount = 0; + ent_node->real_vnode = NULL; + strcpy(ent_node->name, it->dev_name); + + // Create a vnode for device + vnode_t *ent_vnode = devfs_create_vnode(devfs, ent_node); + if (it->dev_class == DEV_CLASS_BLOCK) { + ent_vnode->type = VN_BLK; + } else if (it->dev_class == DEV_CLASS_CHAR) { + ent_vnode->type = VN_CHR; + } else { + panic("Unsupported device class\n"); + } + ent_vnode->fs_data = it; + ent_vnode->dev = it->dev; + + ent_node->vnode = ent_vnode; + + ent_node->parent = _root; + ent_node->cdr = _root->child; + _root->child = ent_node; + } + + vnode_t *vnode = devfs_create_vnode(devfs, _root); + _root->vnode = vnode; + + *root = _root; + devfs_root_node = _root; + + return 0; +} + +static __init void devfs_init(void) { + fs_class_register(&_devfs); +} diff --git a/sys/vfs/devfs.c b/sys/vfs/devfs.c deleted file mode 100644 index 7b93070..0000000 --- a/sys/vfs/devfs.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "sys/fs/devfs.h" -#include "sys/fs/vfs.h" -#include "sys/string.h" -#include "sys/fs/fs.h" -#include "sys/debug.h" -#include "sys/panic.h" -#include "sys/attr.h" -#include "sys/heap.h" - -static int devfs_node_mapper(fs_t *devfs, struct vfs_node **root); - -static struct fs_class _devfs = { - .name = "devfs", - .opt = FS_NODE_MAPPER, - .mapper = devfs_node_mapper -}; - -static struct vnode_operations _devfs_vnode_op = { -}; - -static vnode_t *devfs_create_vnode(fs_t *fs, struct vfs_node *node) { - vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t)); - res->tree_node = node; - res->fs = fs; - res->fs_data = NULL; - res->refcount = 0; - res->op = &_devfs_vnode_op; - res->type = VN_DIR; - return res; -} - -// TODO: handle devices added post-mapper - -static int devfs_node_mapper(fs_t *devfs, struct vfs_node **root) { - struct vfs_node *_root; - struct dev_entry *it; - - // Make a root node - _root = (struct vfs_node *) kmalloc(sizeof(struct vfs_node)); - _root->child = NULL; - _root->cdr = NULL; - _root->ismount = 0; - _root->parent = NULL; - _root->real_vnode = NULL; - _root->vnode = NULL; - - // TODO: directory-categories (like "by-uuid" or something) - for (it = dev_iter(); it; it = it->cdr) { - struct vfs_node *ent_node = kmalloc(sizeof(struct vfs_node)); - ent_node->child = NULL; - ent_node->ismount = 0; - ent_node->real_vnode = NULL; - strcpy(ent_node->name, it->dev_name); - - // Create a vnode for device - vnode_t *ent_vnode = devfs_create_vnode(devfs, ent_node); - if (it->dev_class == DEV_CLASS_BLOCK) { - ent_vnode->type = VN_BLK; - } else if (it->dev_class == DEV_CLASS_CHAR) { - ent_vnode->type = VN_CHR; - } else { - panic("Unsupported device class\n"); - } - ent_vnode->fs_data = it; - ent_vnode->dev = it->dev; - - ent_node->vnode = ent_vnode; - - ent_node->parent = _root; - ent_node->cdr = _root->child; - _root->child = ent_node; - } - - vnode_t *vnode = devfs_create_vnode(devfs, _root); - _root->vnode = vnode; - - *root = _root; - - return 0; -} - -static __init void devfs_init(void) { - fs_class_register(&_devfs); -} diff --git a/sys/vfs/vfs.c b/sys/vfs/vfs.c index 3a0c483..0cb2f6c 100644 --- a/sys/vfs/vfs.c +++ b/sys/vfs/vfs.c @@ -1076,11 +1076,7 @@ int vfs_truncate(struct vfs_ioctx *ctx, struct ofile *of, size_t length) { return vn->op->truncate(of, length); } -// XXX: Linux seems to differentiate between -// unlink() and rmdir(). I think just -// passing a flag whether sys_rmdir or -// sys_unlink was called. -int vfs_unlink(struct vfs_ioctx *ctx, const char *path) { +int vfs_unlink(struct vfs_ioctx *ctx, const char *path, int is_rmdir) { // XXX: validate this with removing mounted roots _assert(path); // Find the vnode to unlink @@ -1094,6 +1090,13 @@ int vfs_unlink(struct vfs_ioctx *ctx, const char *path) { _assert(vnode && vnode->op); vnode_ref(vnode); + if (vnode->type != VN_DIR && is_rmdir) { + return -ENOTDIR; + } + if (vnode->type == VN_DIR && !is_rmdir) { + return -EISDIR; + } + // Get node parent struct vfs_node *node = vnode->tree_node; _assert(node);