Orion
Barry Importing existing Orion kernel d41a53c (3 years, 3 months ago)
diff --git a/vfs/procfs/file.c b/vfs/procfs/file.c
new file mode 100644
index 0000000..b292cf4
--- /dev/null
+++ b/vfs/procfs/file.c
@@ -0,0 +1,126 @@
+/*
+ * This file controls access to ProcFS Files. It contains the functions called
+ * by the VFS for any operation on a File struct belonging to ProcFS.
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include "fs.h"
+#include "../vfs.h"
+#include "../cache.h"
+#include "../../mem/paging.h"
+#include "../../mem/frame.h"
+
+size_t procfs_read(File *file, char *buf, size_t size, off_t offset);
+size_t procfs_write(File *file, char *buf, size_t size, off_t offset);
+int procfs_readdir(File *file, DirEnt *dent, off_t index);
+int procfs_open(File *file);
+
+FileOps procfsFileOps = {
+ .read = procfs_read,
+ .write = procfs_write,
+ .readdir = procfs_readdir,
+ .open = procfs_open,
+};
+
+/* Read a file */
+size_t
+procfs_read(File *file, char *buf, size_t size, off_t offset)
+{
+ if (offset > file->inode->size)
+ return 0;
+ if (size + offset > file->inode->size)
+ size = file->inode->size - offset;
+
+ uint16_t min;
+ size_t count = 0;
+ Page *page;
+ page_t oldPage;
+ while (size) {
+ min = (size > 0x1000) ? 0x1000 : size;
+ page = page_find(file->inode, offset);
+ if (!page)
+ break;
+ acquire(&quickPageLock);
+ oldPage = quick_page(page->frame);
+ memcpy(buf + count, QUICK_PAGE, min);
+ quick_page(oldPage);
+ release(&quickPageLock);
+ size -= min;
+ count += min;
+ }
+ return count;
+}
+
+/* Write a file */
+size_t
+procfs_write(File *file, char *buf, size_t size, off_t offset)
+{
+ if (size + offset > file->inode->size)
+ file->inode->size = size + offset;
+
+ uint16_t min;
+ size_t count = 0;
+ Page *page;
+ page_t oldPage;
+ while (size) {
+ min = (size > 0x1000) ? 0x1000 : size;
+ page = page_find(file->inode, offset);
+ if (!page)
+ page = page_create(file->inode, alloc_frames(1),
+ offset);
+ acquire(&quickPageLock);
+ oldPage = quick_page(page->frame);
+ memcpy(QUICK_PAGE, buf + count, min);
+ quick_page(oldPage);
+ release(&quickPageLock);
+ size -= min;
+ count += min;
+ }
+ return count;
+}
+
+/* Read a directory entry */
+int
+procfs_readdir(File *file, DirEnt *dent, off_t index)
+{
+ DirEntry *de;
+
+ if (!index--) {
+ dent->ino = file->inode->ino;
+ dent->type = DT_DIR;
+ dent->namelen = 2;
+ strncpy(dent->name, ".", dent->namelen);
+ return 0;
+ }
+
+ for (de = file->inode->dirEntries; de && index; de = de->next, index--);
+ if (!de)
+ return -ENOENT;
+ dent->ino = de->inode->ino;
+ if (S_ISBLK(de->inode->mode))
+ dent->type = DT_BLK;
+ if (S_ISCHR(de->inode->mode))
+ dent->type = DT_CHR;
+ if (S_ISDIR(de->inode->mode))
+ dent->type = DT_DIR;
+ if (S_ISFIFO(de->inode->mode))
+ dent->type = DT_FIFO;
+ if (S_ISLNK(de->inode->mode))
+ dent->type = DT_LNK;
+ if (S_ISREG(de->inode->mode))
+ dent->type = DT_REG;
+ if (S_ISSOCK(de->inode->mode))
+ dent->type = DT_SOCK;
+ dent->namelen = strnlen(de->name, NAME_MAX) + 1;
+ strncpy(dent->name, de->name, NAME_MAX);
+ return 0;
+}
+
+/* Open a file */
+int
+procfs_open(File *file)
+{
+ return 0;
+}
diff --git a/vfs/procfs/fs.h b/vfs/procfs/fs.h
new file mode 100644
index 0000000..346c1b3
--- /dev/null
+++ b/vfs/procfs/fs.h
@@ -0,0 +1,13 @@
+#ifndef KERNEL_VFS_PROCFS_H
+#define KERNEL_VFS_PROCFS_H
+
+#include "../vfs.h"
+
+/* Operations */
+extern SuperOps procfsSuperOps;
+extern InodeOps procfsInodeOps;
+extern FileOps procfsFileOps;
+
+extern FileSystemType procfsType;
+
+#endif
diff --git a/vfs/procfs/inode.c b/vfs/procfs/inode.c
new file mode 100644
index 0000000..a81c3fc
--- /dev/null
+++ b/vfs/procfs/inode.c
@@ -0,0 +1,69 @@
+/*
+ * This file contains the functions dealing with ProcFS inodes. The VFS will
+ * call these when it performs operations on ProcFS Inodes, or is dealing with
+ * the ProcFS hierarchy.
+ */
+
+#include <string.h>
+#include "fs.h"
+#include "../vfs.h"
+#include "../../mem/heap.h"
+
+int procfs_create(Inode *inode, DirEntry *entry, mode_t mode);
+Inode *procfs_lookup(Inode *inode, const char *name);
+int procfs_mkdir(Inode *inode, DirEntry *entry, mode_t mode);
+int procfs_rmdir(Inode *inode, DirEntry *entry);
+int procfs_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev);
+int procfs_rename(Inode *si, DirEntry *sde, Inode *di, DirEntry *dde);
+
+InodeOps procfsInodeOps = {
+ .create = procfs_create,
+ .lookup = procfs_lookup,
+ .mkdir = procfs_mkdir,
+ .rmdir = procfs_rmdir,
+ .mknod = procfs_mknod,
+ .rename = procfs_rename,
+};
+
+/* Create a file */
+int
+procfs_create(Inode *inode, DirEntry *entry, mode_t mode)
+{
+ return 0;
+}
+
+
+/* Look up a file */
+Inode *
+procfs_lookup(Inode *inode, const char *name)
+{
+ return NULL;
+}
+
+/* Make a directory */
+int
+procfs_mkdir(Inode *inode, DirEntry *entry, mode_t mode)
+{
+ return 0;
+}
+
+/* Remove a directory */
+int
+procfs_rmdir(Inode *inode, DirEntry *entry)
+{
+ return 0;
+}
+
+/* Make a node */
+int
+procfs_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev)
+{
+ return 0;
+}
+
+/* Rename/mode a directory entry */
+int
+procfs_rename(Inode *si, DirEntry *sde, Inode *di, DirEntry *dde)
+{
+ return 0;
+}
diff --git a/vfs/procfs/super.c b/vfs/procfs/super.c
new file mode 100644
index 0000000..dcfa871
--- /dev/null
+++ b/vfs/procfs/super.c
@@ -0,0 +1,77 @@
+/*
+ * This file controls the superblock for ProcFS. It supports mounting new ProcFS
+ * filesystems. The VFS will use the calls here when dealing directly with the
+ * filesystem structure.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "fs.h"
+#include "../vfs.h"
+#include "../super.h"
+#include "../inode.h"
+#include "../../mem/heap.h"
+
+Inode *procfs_mount(FileSystemType *type, int flags,
+ const char *dev, void *data);
+Inode *procfs_alloc_inode(SuperBlock *sb);
+
+FileSystemType procfsType = {
+ .name = "ProcFS",
+ .mount = procfs_mount,
+// .kill_sb = procfs_kill_sb,
+};
+
+SuperOps procfsSuperOps = {
+ .alloc_inode = procfs_alloc_inode,
+// .free_inode = procfs_free_inode,
+// .write_inode = procfs_write_inode,
+// .delete_inode = procfs_delete_inode,
+};
+
+Inode procfsRoot = {
+ .mode = S_IFDIR | 0755,
+ .ops = &procfsInodeOps,
+ .fileOps = &procfsFileOps,
+ .size = 4096,
+};
+
+/* Mount a ProcFS instance */
+Inode *
+procfs_mount(FileSystemType *type, int flags, const char *dev, void *data)
+{
+ if (type != &procfsType)
+ return NULL;
+
+ SuperBlock *super = kmalloc(sizeof(SuperBlock));
+
+ super->type = type;
+ super->ops = &procfsSuperOps;
+ init_lock(&super->lock);
+
+ Inode *inode = &procfsRoot;
+ inode->nlink++;
+ inode->super = super;
+ /* FIXME: need an inode per super, or only one super */
+ super->root = inode;
+ /* Never free */
+ if (!inode->usage)
+ inode_get(inode);
+
+ return inode;
+}
+
+/* Allocate an inode */
+Inode *
+procfs_alloc_inode(SuperBlock *sb)
+{
+ Inode *inode = kmalloc(sizeof(Inode));
+ init_lock(&inode->lock);
+ inode->ops = &procfsInodeOps;
+ inode->fileOps = &procfsFileOps;
+ inode->super = sb;
+ inode->nlink = 1;
+ return inode_get(inode); /* This ensures that the inode is never free */
+}