Merge devfs into dev.c, add stat()
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+8
-5
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user