Add mknod() and named pipes
This commit is contained in:
@@ -55,6 +55,7 @@ void *syscall_table[256] = {
|
||||
[SYSCALL_NR_READDIR] = sys_readdir,
|
||||
[SYSCALL_NR_CHMOD] = sys_chmod,
|
||||
[SYSCALL_NR_CHOWN] = sys_chown,
|
||||
[SYSCALL_NR_MKNOD] = sys_mknod,
|
||||
|
||||
// User control
|
||||
[SYSCALL_NR_GETUID] = sys_getuid,
|
||||
|
||||
@@ -66,6 +66,7 @@ static int tarfs_vnode_chmod(struct vnode *node, mode_t mode);
|
||||
static int tarfs_vnode_chown(struct vnode *node, uid_t uid, gid_t gid);
|
||||
//static int tarfs_vnode_mkdir(struct vnode *at, const char *name, uid_t uid, gid_t gid, mode_t mode);
|
||||
//static int tarfs_vnode_creat(struct vnode *at, const char *name, uid_t uid, gid_t gid, mode_t mode);
|
||||
static int tarfs_vnode_mknod(struct vnode *at, struct vnode *nod);
|
||||
static int tarfs_vnode_truncate(struct vnode *node, size_t length);
|
||||
|
||||
static struct vnode_operations _tarfs_vnode_op = {
|
||||
@@ -77,6 +78,7 @@ static struct vnode_operations _tarfs_vnode_op = {
|
||||
.chown = tarfs_vnode_chown,
|
||||
.mkdir = NULL, //tarfs_vnode_mkdir,
|
||||
.creat = NULL, //tarfs_vnode_creat,
|
||||
.mknod = tarfs_vnode_mknod,
|
||||
.write = NULL, //tarfs_vnode_write,
|
||||
.truncate = tarfs_vnode_truncate
|
||||
};
|
||||
@@ -459,6 +461,15 @@ static int tarfs_vnode_stat(struct vnode *vn, struct stat *st) {
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
static int tarfs_vnode_mknod(struct vnode *at, struct vnode *nod) {
|
||||
_assert(at && at->type == VN_DIR && nod);
|
||||
_assert(nod->name[0]);
|
||||
|
||||
vnode_attach(at, nod);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr_t tarfs_block_addr(struct tar *hdr, uint32_t index) {
|
||||
if (index < TAR_DIRECT_BLOCKS) {
|
||||
return hdr->direct_blocks[index] & ~1;
|
||||
|
||||
@@ -358,6 +358,59 @@ int vfs_unlink(struct vfs_ioctx *ctx, const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_mknod(struct vfs_ioctx *ctx, const char *path, mode_t mode, struct vnode **_nod) {
|
||||
char parent_path[PATH_MAX];
|
||||
const char *filename;
|
||||
int res;
|
||||
struct vnode *at;
|
||||
|
||||
_assert(ctx);
|
||||
_assert(path);
|
||||
|
||||
filename = vfs_path_parent(path, parent_path);
|
||||
if (filename[0] == 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// Find parent vnode
|
||||
if ((res = vfs_find(ctx, ctx->cwd_vnode, parent_path, 0, &at)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// Check permission for writing
|
||||
if ((res = vfs_access_node(ctx, at, W_OK)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: check if such file already exists
|
||||
if (!at->op || !at->op->mknod) {
|
||||
// Assume it's a read-only filesystem
|
||||
return -EROFS;
|
||||
}
|
||||
|
||||
enum vnode_type type;
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFIFO:
|
||||
type = VN_FIFO;
|
||||
break;
|
||||
default:
|
||||
panic("mknod: unsupported node type\n");
|
||||
}
|
||||
struct vnode *nod = vnode_create(type, filename);
|
||||
nod->mode = mode & VFS_MODE_MASK;
|
||||
nod->uid = ctx->uid;
|
||||
nod->gid = ctx->gid;
|
||||
|
||||
if ((res = at->op->mknod(at, nod)) != 0) {
|
||||
vnode_destroy(nod);
|
||||
return res;
|
||||
}
|
||||
|
||||
*_nod = nod;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfs_creat(struct vfs_ioctx *ctx, const char *path, mode_t mode) {
|
||||
char parent_path[PATH_MAX];
|
||||
const char *filename;
|
||||
@@ -532,6 +585,7 @@ ssize_t vfs_write(struct vfs_ioctx *ctx, struct ofile *fd, const void *buf, size
|
||||
|
||||
switch (node->type) {
|
||||
case VN_REG:
|
||||
case VN_FIFO:
|
||||
_assert(node->op && node->op->write);
|
||||
b = node->op->write(fd, buf, count);
|
||||
return b;
|
||||
@@ -565,6 +619,7 @@ ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t coun
|
||||
|
||||
switch (node->type) {
|
||||
case VN_REG:
|
||||
case VN_FIFO:
|
||||
_assert(node->op && node->op->read);
|
||||
b = node->op->read(fd, buf, count);
|
||||
return b;
|
||||
|
||||
@@ -31,6 +31,7 @@ enum vnode_type {
|
||||
VN_BLK,
|
||||
VN_CHR,
|
||||
VN_LNK,
|
||||
VN_FIFO,
|
||||
VN_UNK,
|
||||
VN_MNT,
|
||||
};
|
||||
@@ -42,6 +43,8 @@ struct vnode_operations {
|
||||
int (*opendir) (struct ofile *fd);
|
||||
int (*open) (struct ofile *fd, int opt);
|
||||
void (*close) (struct ofile *fd);
|
||||
// TODO: just merge all three?
|
||||
int (*mknod) (struct vnode *at, struct vnode *nod);
|
||||
int (*creat) (struct vnode *at, const char *filename, uid_t uid, gid_t gid, mode_t mode);
|
||||
int (*mkdir) (struct vnode *at, const char *filename, uid_t uid, gid_t gid, mode_t mode);
|
||||
int (*truncate) (struct vnode *at, size_t size);
|
||||
|
||||
@@ -47,6 +47,7 @@ int vfs_readdir(struct vfs_ioctx *ctx, struct ofile *fd, struct dirent *ent);
|
||||
int vfs_unlink(struct vfs_ioctx *ctx, const char *path);
|
||||
int vfs_rmdir(struct vfs_ioctx *ctx, const char *path);
|
||||
int vfs_mkdir(struct vfs_ioctx *ctx, const char *path, mode_t mode);
|
||||
int vfs_mknod(struct vfs_ioctx *ctx, const char *path, mode_t mode, struct vnode **nod);
|
||||
int vfs_chmod(struct vfs_ioctx *ctx, const char *path, mode_t mode);
|
||||
int vfs_chown(struct vfs_ioctx *ctx, const char *path, uid_t uid, gid_t gid);
|
||||
int vfs_ioctl(struct vfs_ioctx *ctx, struct ofile *fd, unsigned int cmd, void *arg);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
struct ofile;
|
||||
struct vnode;
|
||||
|
||||
int pipe_create(struct ofile **read, struct ofile **write);
|
||||
int pipe_fifo_create(struct vnode *res);
|
||||
|
||||
@@ -27,3 +27,4 @@ int sys_dup2(int from, int to);
|
||||
int sys_chmod(const char *path, mode_t mode);
|
||||
int sys_chown(const char *path, uid_t uid, gid_t gid);
|
||||
off_t sys_lseek(int fd, off_t offset, int whence);
|
||||
int sys_mknod(const char *filename, int mode, unsigned int dev);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define SYSCALL_NR_READDIR 89
|
||||
#define SYSCALL_NR_CHMOD 90
|
||||
#define SYSCALL_NR_CHOWN 92
|
||||
#define SYSCALL_NR_MKNOD 133
|
||||
|
||||
#define SYSCALL_NR_NANOSLEEP 35
|
||||
#define SYSCALL_NR_UNAME 63
|
||||
|
||||
+55
-1
@@ -9,14 +9,18 @@
|
||||
|
||||
#define PIPE_RING_SIZE 1024
|
||||
|
||||
static int pipe_vnode_open(struct ofile *of, int opt);
|
||||
static ssize_t pipe_vnode_write(struct ofile *of, const void *buf, size_t count);
|
||||
static ssize_t pipe_vnode_read(struct ofile *of, void *buf, size_t count);
|
||||
static int pipe_vnode_stat(struct vnode *vn, struct stat *st);
|
||||
static void pipe_vnode_close(struct ofile *of);
|
||||
|
||||
static struct vnode_operations pipe_vnode_ops = {
|
||||
.open = pipe_vnode_open,
|
||||
.close = pipe_vnode_close,
|
||||
.write = pipe_vnode_write,
|
||||
.read = pipe_vnode_read
|
||||
.read = pipe_vnode_read,
|
||||
.stat = pipe_vnode_stat
|
||||
};
|
||||
|
||||
int pipe_create(struct ofile **_read, struct ofile **_write) {
|
||||
@@ -51,6 +55,20 @@ int pipe_create(struct ofile **_read, struct ofile **_write) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pipe_fifo_create(struct vnode *nod) {
|
||||
_assert(nod);
|
||||
nod->op = &pipe_vnode_ops;
|
||||
nod->flags |= VN_MEMORY;
|
||||
|
||||
struct ring *pipe_ring = kmalloc(sizeof(struct ring));
|
||||
_assert(pipe_ring);
|
||||
ring_init(pipe_ring, PIPE_RING_SIZE);
|
||||
|
||||
nod->fs_data = pipe_ring;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t pipe_vnode_write(struct ofile *of, const void *buf, size_t count) {
|
||||
struct thread *thr = thread_self;
|
||||
_assert(thr);
|
||||
@@ -98,6 +116,42 @@ static void pipe_vnode_close(struct ofile *of) {
|
||||
if (of->flags & OF_WRITABLE) {
|
||||
ring_signal(of->file.priv_data, RING_SIGNAL_EOF);
|
||||
}
|
||||
// TODO: this
|
||||
//kfree(((struct ring *) of->file.priv_data)->base);
|
||||
//kfree(of->file.priv_data);
|
||||
}
|
||||
|
||||
static int pipe_vnode_open(struct ofile *of, int opt) {
|
||||
_assert(!(of->flags & OF_SOCKET));
|
||||
_assert(of->file.vnode);
|
||||
// TODO: allow only one reader and many writers
|
||||
of->file.pos = 0;
|
||||
of->file.priv_data = of->file.vnode->fs_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pipe_vnode_stat(struct vnode *vn, struct stat *st) {
|
||||
_assert(vn && st);
|
||||
struct ring *pipe_ring = vn->fs_data;
|
||||
_assert(pipe_ring);
|
||||
|
||||
st->st_size = pipe_ring->cap;
|
||||
st->st_blksize = pipe_ring->cap;
|
||||
st->st_blocks = 1;
|
||||
|
||||
st->st_ino = 0;
|
||||
|
||||
st->st_uid = vn->uid;
|
||||
st->st_gid = vn->gid;
|
||||
st->st_mode = vn->mode | S_IFIFO;
|
||||
|
||||
st->st_atime = system_boot_time;
|
||||
st->st_mtime = system_boot_time;
|
||||
st->st_ctime = system_boot_time;
|
||||
|
||||
st->st_nlink = 1;
|
||||
st->st_rdev = 0;
|
||||
st->st_dev = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -387,6 +387,29 @@ ssize_t sys_readdir(int fd, struct dirent *ent) {
|
||||
return vfs_readdir(&thr->ioctx, thr->fds[fd], ent);
|
||||
}
|
||||
|
||||
int sys_mknod(const char *filename, int mode, unsigned int dev) {
|
||||
userptr_check(filename);
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
|
||||
int type = mode & S_IFMT;
|
||||
int res;
|
||||
struct vnode *node;
|
||||
|
||||
if ((res = vfs_mknod(&thr->ioctx, filename, mode, &node)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
_assert(node);
|
||||
|
||||
switch (type) {
|
||||
case S_IFIFO:
|
||||
return pipe_fifo_create(node);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int sys_select_get_ready(struct ofile *fd) {
|
||||
if (fd->flags & OF_SOCKET) {
|
||||
return socket_has_data(&fd->socket);
|
||||
|
||||
Reference in New Issue
Block a user