BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / d41a53cbc7d055b1c00cf0a339dbed6925f4f02c / vfs / devfs

// Related

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 */
+}