Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)diff --git a/vfs/devfs/file.c b/vfs/devfs/file.c new file mode 100644 index 0000000..d2da4e4 --- /dev/null +++ b/vfs/devfs/file.c @@ -0,0 +1,84 @@ +/* + * This file controls access to DevFS Files. It contains the functions called + * by the VFS for any operation on a File struct belonging to DevFS. + */ + +#include <stddef.h> +#include <string.h> +#include <errno.h> +#include <dirent.h> +#include "fs.h" +#include "../vfs.h" +#include "../cache.h" +#include "../../mem/paging.h" +#include "../../mem/frame.h" +#include "../../drivers/drivers.h" + +int devfs_open(File *file); +int devfs_readdir(File *file, DirEnt *dent, off_t index); + +FileOps devfsFileOps = { + .open = devfs_open, + .readdir = devfs_readdir, +}; + +/* Open a device node */ +int +devfs_open(File *file) +{ + if (S_ISREG(file->inode->mode) || S_ISDIR(file->inode->mode)) + return 0; + + /* Use major number to find relevant driver */ + Driver *driver; + for (driver = drivers; driver; driver = driver->next) + if (driver->major == MAJOR(file->inode->dev)) + break; + if (!driver) + return -ENXIO; + + file->ops = driver->ops; + if (!file->ops) + return 0; + if (!file->ops->open) + return 0; + return file->ops->open(file); + /* For checking the minor internally */ +} + +/* Read a directory entry */ +int +devfs_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; +} diff --git a/vfs/devfs/fs.h b/vfs/devfs/fs.h new file mode 100644 index 0000000..f972b67 --- /dev/null +++ b/vfs/devfs/fs.h @@ -0,0 +1,13 @@ +#ifndef KERNEL_VFS_DEVFS_H +#define KERNEL_VFS_DEVFS_H + +#include "../vfs.h" + +/* Operations */ +extern SuperOps devfsSuperOps; +extern InodeOps devfsInodeOps; +extern FileOps devfsFileOps; + +extern FileSystemType devfsType; + +#endif diff --git a/vfs/devfs/inode.c b/vfs/devfs/inode.c new file mode 100644 index 0000000..2208263 --- /dev/null +++ b/vfs/devfs/inode.c @@ -0,0 +1,69 @@ +/* + * This file contains the functions dealing with DevFS inodes. The VFS will + * call these when it performs operations on DevFS Inodes, or is dealing with + * the DevFS hierarchy. + */ + +#include <string.h> +#include "fs.h" +#include "../vfs.h" +#include "../../mem/heap.h" + +int devfs_create(Inode *inode, DirEntry *entry, mode_t mode); +Inode *devfs_lookup(Inode *inode, const char *name); +int devfs_mkdir(Inode *inode, DirEntry *entry, mode_t mode); +int devfs_rmdir(Inode *inode, DirEntry *entry); +int devfs_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev); +int devfs_rename(Inode *si, DirEntry *sde, Inode *di, DirEntry *dde); + +InodeOps devfsInodeOps = { + .create = devfs_create, + .lookup = devfs_lookup, + .mkdir = devfs_mkdir, + .rmdir = devfs_rmdir, + .mknod = devfs_mknod, + .rename = devfs_rename, +}; + +/* Create a file */ +int +devfs_create(Inode *inode, DirEntry *entry, mode_t mode) +{ + return 0; +} + + +/* Look up a file */ +Inode * +devfs_lookup(Inode *inode, const char *name) +{ + return NULL; +} + +/* Make a directory */ +int +devfs_mkdir(Inode *inode, DirEntry *entry, mode_t mode) +{ + return 0; +} + +/* Remove a directory */ +int +devfs_rmdir(Inode *inode, DirEntry *entry) +{ + return 0; +} + +/* Make a node */ +int +devfs_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev) +{ + return 0; +} + +/* Rename/mode a directory entry */ +int +devfs_rename(Inode *si, DirEntry *sde, Inode *di, DirEntry *dde) +{ + return 0; +} diff --git a/vfs/devfs/super.c b/vfs/devfs/super.c new file mode 100644 index 0000000..e57d60b --- /dev/null +++ b/vfs/devfs/super.c @@ -0,0 +1,85 @@ +/* + * This file controls the superblock for DevFS. It supports mounting new DevFS + * 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 *devfs_mount(FileSystemType *type, int flags, + const char *dev, void *data); +Inode *devfs_alloc_inode(SuperBlock *sb); + +FileSystemType devfsType = { + .name = "DevFS", + .mount = devfs_mount, +// .kill_sb = devfs_kill_sb, +}; + +SuperOps devfsSuperOps = { + .alloc_inode = devfs_alloc_inode, +// .free_inode = devfs_free_inode, +// .write_inode = devfs_write_inode, +// .delete_inode = devfs_delete_inode, +}; + +Inode devfsRoot = { + .mode = S_IFDIR | 0755, + .ops = &devfsInodeOps, + .fileOps = &devfsFileOps, + .size = 4096, +}; + +/* Mount a DevFS instance */ +Inode * +devfs_mount(FileSystemType *type, int flags, const char *dev, void *data) +{ + if (type != &devfsType) + return NULL; + + SuperBlock *super = kmalloc(sizeof(SuperBlock)); + + super->type = type; + super->ops = &devfsSuperOps; + init_lock(&super->lock); + + /* + * DevFS is special - it has a globally unique root. This means that no + * matter where a DevFS instance is mounted, it will be mounted with + * this inode, meaning the contents are the same. It basically causes + * the mountpoint to act as a hard-link. This means you can mount a new + * DevFS instance in a chroot() environment, and not have to remake all + * the device nodes. + */ + Inode *inode = &devfsRoot; + 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 * +devfs_alloc_inode(SuperBlock *sb) +{ + Inode *inode = kmalloc(sizeof(Inode)); + init_lock(&inode->lock); + inode->ops = &devfsInodeOps; + inode->fileOps = &devfsFileOps; + inode->super = sb; + inode->nlink = 1; + return inode_get(inode); /* This ensures that the inode is never free */ +}