Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 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 */ +}