BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 88d672affcc1b9e1de646809e06bca1737f94f25

// Related

Nucleus

Barry Device file system 88d672a (3 years, 3 months ago)
diff --git a/include/nucleus/vfs.h b/include/nucleus/vfs.h
index 59162c0..40239c7 100644
--- a/include/nucleus/vfs.h
+++ b/include/nucleus/vfs.h
@@ -107,6 +107,8 @@ Inode *super_find_inode(SuperBlock *sb, ino_t ino);
 int permission(Inode *inode, int mask);
 int inode_create(Inode *inode, DirEntry *entry, mode_t mode);
 DirEntry *inode_lookup(Inode *inode, const char *name);
+int inode_mkdir(Inode *inode, DirEntry *entry, mode_t mode);
+int inode_rmdir(Inode *inode, DirEntry *entry);
 /* Directory Entry functions */
 DirEntry *find_direntry(ObjectList *list, const char *name);
 /* File functions */
diff --git a/vfs/devfs/file.c b/vfs/devfs/file.c
new file mode 100644
index 0000000..a984c1d
--- /dev/null
+++ b/vfs/devfs/file.c
@@ -0,0 +1,75 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <nucleus/memory.h>
+#include <nucleus/vfs.h>
+
+size_t devfs_read(File *file, char *buf, size_t size, off_t offset);
+size_t devfs_write(File *file, char *buf, size_t size, off_t offset);
+int devfs_open(File *file);
+
+FileOps devfsFileOps = {
+	.read = devfs_read,
+	.write = devfs_write,
+	.open = devfs_open,
+};
+
+/* Read a file */
+size_t
+devfs_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;
+
+	Page *page;
+	char *data;
+	size_t count = 0;
+	uint16_t min, indent = offset % PAGE_SIZE;
+	while (size) {
+		min = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+		page = find_page(file->inode->pages, offset);
+		if (!page)
+			break;
+		data = map_page(page);
+		memcpy(buf + count, data + indent, min);
+		size -= min;
+		count += min;
+		indent = 0;
+	}
+	return count;
+}
+
+/* Write a file */
+size_t
+devfs_write(File *file, char *buf, size_t size, off_t offset)
+{
+	if (size + offset > file->inode->size)
+		file->inode->size = size + offset;
+
+	Page *page;
+	char *data;
+	size_t count = 0;
+	uint16_t min, indent = offset % PAGE_SIZE;
+	while (size) {
+		min = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+		page = find_page(file->inode->pages, offset);
+		if (!page)
+			page = create_page(file->inode->pages, alloc_frame(),
+			                   offset);
+		data = map_page(page);
+		memcpy(data + indent, buf + count, min);
+		size -= min;
+		count += min;
+		indent = 0;
+	}
+	return count;
+}
+
+/* Open a file */
+int
+devfs_open(File *file)
+{
+	return 0;
+}
diff --git a/vfs/devfs/inode.c b/vfs/devfs/inode.c
new file mode 100644
index 0000000..3b60e38
--- /dev/null
+++ b/vfs/devfs/inode.c
@@ -0,0 +1,59 @@
+#include <nucleus/vfs.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 directory entry in a directory */
+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..bfab4e9
--- /dev/null
+++ b/vfs/devfs/super.c
@@ -0,0 +1,44 @@
+#include <sys/stat.h>
+#include <nucleus/vfs.h>
+
+extern InodeOps devfsInodeOps;
+extern FileOps devfsFileOps;
+
+Inode *devfs_alloc_inode(SuperBlock *sb);
+
+SuperOps devfsSuperOps = {
+	.alloc_inode = devfs_alloc_inode,
+};
+
+/* Mount a devfs instance */
+Inode *
+devfs_mount(FSType *type, int flags, const char *dev, void *data)
+{
+	static SuperBlock *super = NULL;
+	if (!super) {
+		super = new(&superBlockType);
+		super->type = get(type);
+		super->ops = &devfsSuperOps;
+	}
+
+	static Inode *inode = NULL;
+	if (!inode) {
+		Inode *inode = super_alloc_inode(super);
+		inode->mode = S_IFDIR | 0755;
+		super->root = inode;
+	}
+
+	return inode;
+}
+
+/* Allocate an inode */
+Inode *
+devfs_alloc_inode(SuperBlock *sb)
+{
+	Inode *inode = new(&inodeType);
+	inode->ops = &devfsInodeOps;
+	inode->fileOps = &devfsFileOps;
+	inode->super = get(sb);
+	inode->nlink = 1;
+	return inode;
+}
diff --git a/vfs/inode.c b/vfs/inode.c
index c64542d..3f760e7 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -129,3 +129,36 @@ end:
 	unlock(inode);
 	return entry;
 }
+
+/* Make a directory wrapper */
+int
+inode_mkdir(Inode *inode, DirEntry *entry, mode_t mode)
+{
+	if (!inode->ops || !inode->ops->mkdir)
+		return -EINVAL;
+	lock(inode);
+	int err = inode->ops->mkdir(inode, entry, mode);
+	if (!err) {
+		add(inode->dirEntries, entry);
+		entry->inode = super_alloc_inode(inode->super);
+		entry->inode->mode = mode | S_IFDIR;
+	}
+	unlock(inode);
+	return err;
+}
+
+
+/* Remove a directory wrapper */
+int
+inode_rmdir(Inode *inode, DirEntry *entry)
+{
+	if (!inode->ops || !inode->ops->mkdir)
+		return -EINVAL;
+	lock(inode);
+	int err = inode->ops->rmdir(inode, entry);
+	if (!err)
+		remove(inode->dirEntries, entry);
+	unlock(inode);
+	return err;
+}
+
diff --git a/vfs/open.c b/vfs/open.c
index cf03a24..630b675 100644
--- a/vfs/open.c
+++ b/vfs/open.c
@@ -187,3 +187,41 @@ open(const char *name, int flags, ...)
 	put(inode);
 	return fd;
 }
+
+/* Make a directory */
+int
+mkdir(const char *pathname, mode_t mode)
+{
+	if (!pathname)
+		return -EFAULT;
+	if (!verify_access(pathname, strnlen(pathname, PATH_MAX), PROT_READ))
+		return -EFAULT;
+	int err;
+	ObjectList *custody = create_list(&dirEntryType);
+	Inode *inode = lookup(pathname, custody);
+	if (inode) {
+		err = -EEXIST;
+		goto end;
+	}
+	if (!count(custody)) {
+		err = -ENOENT;
+		goto end;
+	}
+	/* Check write permission */
+	DirEntry *entry = get_nth_item(custody, count(custody) - 2);
+	if (entry)
+		inode = entry->inode;
+	else
+		inode = current->fs->root;
+	if (!permission(inode, PROT_WRITE)) {
+		err = -EACCES;
+		goto end;
+	}
+
+	/* Create directory */
+	err = inode_mkdir(inode, get_nth_item(custody, count(custody) - 1),
+	                  mode);
+end:
+	destroy_list(custody);
+	return err;
+}
diff --git a/vfs/vfs.c b/vfs/vfs.c
index 2f53c99..bbd61db 100644
--- a/vfs/vfs.c
+++ b/vfs/vfs.c
@@ -5,19 +5,21 @@
  * IPC and device management.
  */
 
+#include <sys/stat.h>
 #include <nucleus/object.h>
 #include <nucleus/vfs.h>
 
-#include <nucleus/task.h>
-#include "namespace.h"
-
 Inode *tmpfs_mount(FSType *type, int flags, const char *dev, void *data);
+Inode *devfs_mount(FSType *type, int flags, const char *dev, void *data);
 
 /* Initialise the Virtual File System */
 void
 init_vfs(void)
 {
 	register_fstype("tmpfs", tmpfs_mount);
+	register_fstype("devfs", devfs_mount);
 
 	mount("tmpfs", NULL, "tmpfs", 0, NULL);
+	mkdir("dev", 0);
+	mount("devfs", "/dev", "devfs", 0, NULL);
 }