Add mknod() and named pipes

This commit is contained in:
Mark
2020-07-05 17:13:38 +03:00
parent d446846ba6
commit 061d514beb
10 changed files with 153 additions and 1 deletions
+1
View File
@@ -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,
+11
View File
@@ -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;
+55
View File
@@ -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;
+3
View File
@@ -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);
+1
View File
@@ -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);
+2
View File
@@ -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);
+1
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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;
}
+23
View File
@@ -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);