BarryServer : Git

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

// Related

Nucleus

Barry More VFS functions and structure d3f787c (3 years, 2 months ago)
diff --git a/include/nucleus/vfs.h b/include/nucleus/vfs.h
index 97ebf54..2ab824c 100644
--- a/include/nucleus/vfs.h
+++ b/include/nucleus/vfs.h
@@ -30,6 +30,7 @@ struct SuperBlock {
 	SuperOps *ops;
 	Inode *root;
 	ObjectList *inodes; /* List of cached inodes */
+	File *back;
 	void *data;
 };
 struct SuperOps {
@@ -85,6 +86,7 @@ struct FileOps {
 	size_t (*read)(File *, char *, size_t, off_t);
 	size_t (*write)(File *, char *, size_t, off_t);
 	int (*open)(File *);
+	int (*ioctl)(File *, unsigned long, uintptr_t);
 	void (*mmap)(File *, void *, size_t, off_t);
 };
 
@@ -101,6 +103,7 @@ File *create_anonymous_file(void);
 void register_fstype(const char *name,	mount_callback_t mount);
 int mount(const char *src, const char *target, const char *type,
           unsigned long flags, void *data);
+Inode *lookup(const char *path, ObjectList *newcustody);
 
 /* Super Block functions */
 Inode *super_alloc_inode(SuperBlock *sb);
@@ -118,6 +121,7 @@ DirEntry *find_direntry(ObjectList *list, const char *name);
 int file_open(File *file);
 size_t file_read(File *file, char *buf, size_t count);
 size_t file_write(File *file, char *buf, size_t count);
+int file_ioctl(File *file, unsigned long request, uintptr_t arpg);
 void file_mmap(File *file, void *addr, size_t len, off_t offset);
 /* Files namespace functions */
 File *get_file_by_fd(int fd);
diff --git a/vfs/file.c b/vfs/file.c
index 0d0f31d..bca19dc 100644
--- a/vfs/file.c
+++ b/vfs/file.c
@@ -146,6 +146,17 @@ end:
 	return count;
 }
 
+/* I/O Control */
+int
+file_ioctl(File *file, unsigned long request, uintptr_t argp)
+{
+	if (!file->ops)
+		return -EINVAL;
+	if (!file->ops->ioctl)
+		return -ENOTTY;
+	return file->ops->ioctl(file, request, argp);
+}
+
 /* Map a file into memory */
 void
 file_mmap(File *file, void *addr, size_t len, off_t offset)
diff --git a/vfs/files.c b/vfs/files.c
index fffbc42..b830e40 100644
--- a/vfs/files.c
+++ b/vfs/files.c
@@ -101,6 +101,8 @@ close(int fd)
 int
 read(int fd, void *buf, size_t count)
 {
+	if (!buf)
+		return -EFAULT;
 	if (!verify_access(buf, count, PROT_WRITE))
 		return -EFAULT;
 
@@ -121,6 +123,8 @@ read(int fd, void *buf, size_t count)
 int
 write(int fd, void *buf, size_t count)
 {
+	if (!buf)
+		return -EFAULT;
 	if (!verify_access(buf, count, PROT_READ))
 		return -EFAULT;
 
@@ -163,3 +167,22 @@ lseek(int fd, off_t offset, int whence)
 	unlock(file);
 	return file->pos;
 }
+
+/* Perform I/O control on a file */
+int
+ioctl(int fd, unsigned long request, ...)
+{
+	File *file = get_file_by_fd(fd);
+	if (!file)
+		return -EBADF;
+
+	va_list args;
+	va_start(args, request);
+	uintptr_t argp = va_arg(args, uintptr_t);
+	va_end(args);
+
+	lock(file);
+	int ret = file_ioctl(file, request, argp);
+	unlock(file);
+	return ret;
+}
diff --git a/vfs/mount.c b/vfs/mount.c
index 53bdab2..a321d34 100644
--- a/vfs/mount.c
+++ b/vfs/mount.c
@@ -4,12 +4,14 @@
  */
 
 #include <string.h>
+#include <sys/stat.h>
 #include <errno.h>
 #include <nucleus/memory.h>
 #include <nucleus/task.h>
 #include <nucleus/vfs.h>
 #include "namespace.h"
 
+Inode *lookup(const char *path, ObjectList *newcustody);
 int mount_fstype(const char *name, int flags, const char *src, void *data,
                  Inode **root);
 
@@ -18,6 +20,8 @@ int
 mount(const char *src, const char *target, const char *type,
       unsigned long flags, void *data)
 {
+	if (!src || !type)
+		return -EFAULT;
 	if (!verify_access(src, strnlen(src, PATH_MAX), PROT_READ))
 		return -EFAULT;
 	if (!verify_access(target, strnlen(target, PATH_MAX), PROT_READ))
@@ -39,5 +43,23 @@ mount(const char *src, const char *target, const char *type,
 		return 0;
 	}
 
+	/* Find target's directory entry */
+	ObjectList *custody = create_list(&dirEntryType, LIST_NORMAL);
+	Inode *root = lookup(target, custody);
+	if (!root) {
+		destroy_list(custody);
+		return -ENOENT;
+	}
+	if (!S_ISDIR(root->mode)) {
+		put(root);
+		destroy_list(custody);
+		return -ENOTDIR;
+	}
+	DirEntry *de = get_nth_item(custody, count(custody) - 1);
+	de->mnt = de->inode;
+	de->inode = get(mnt);
+	put(root);
+	destroy_list(custody);
+
 	return 0;
 }
diff --git a/vfs/namespace.c b/vfs/namespace.c
index 1b102af..1d560a9 100644
--- a/vfs/namespace.c
+++ b/vfs/namespace.c
@@ -3,7 +3,12 @@
  * task's file system.  It tracks a task's root and current working directory.
  */
 
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <nucleus/memory.h>
 #include <nucleus/object.h>
+#include <nucleus/task.h>
 #include <nucleus/vfs.h>
 #include "namespace.h"
 
@@ -47,3 +52,94 @@ file_system_copy(Object *a, Object *b)
 	child->cwdPath = copy_list(parent->cwdPath);
 	child->root = get(parent->root);
 }
+
+/* Change the current working directory */
+int
+chdir(const char *path)
+{
+	if (!path)
+		return -EFAULT;
+	if (!verify_access(path, strnlen(path, PATH_MAX), PROT_READ))
+		return -EFAULT;
+	ObjectList *custody = create_list(&dirEntryType, LIST_NORMAL);
+	Inode *inode = lookup(path, custody);
+	if (!inode) {
+		destroy_list(custody);
+		return -ENOENT;
+	}
+	if (!S_ISDIR(inode->mode)) {
+		destroy_list(custody);
+		put(inode);
+		return -ENOTDIR;
+	}
+	if (!permission(inode, PROT_READ)) {
+		destroy_list(custody);
+		put(inode);
+		return -EACCES;
+	}
+	put(current->fs->cwd);
+	current->fs->cwd = inode;
+	destroy_list(current->fs->cwdPath);
+	current->fs->cwdPath = custody;
+	return 0;
+}
+
+/* Change the current root */
+int
+chroot(const char *path)
+{
+	if (!path)
+		return -EFAULT;
+	if (!verify_access(path, strnlen(path, PATH_MAX), PROT_READ))
+		return -EFAULT;
+	Inode *inode = lookup(path, NULL);
+	if (!inode)
+		return -ENOENT;
+	if (!S_ISDIR(inode->mode)) {
+		put(inode);
+		return -ENOTDIR;
+	}
+	if (!permission(inode, PROT_READ)) {
+		put(inode);
+		return -EACCES;
+	}
+	put(current->fs->root);
+	current->fs->root = inode;
+	return 0;
+}
+
+/* Get the current working directory's path */
+char *
+getcwd(char *buf, size_t size)
+{
+	if (!buf || !size)
+		return (char *) -EINVAL;
+	if (!verify_access(buf, size, PROT_WRITE))
+		return (char *) -EFAULT;
+	size_t i = 0, len;
+	char path[PATH_MAX];
+	memset(path, 0, PATH_MAX);
+
+	/* Empty path */
+	if (count(current->fs->cwdPath) == 0) {
+		buf[0] = '/';
+		buf[1] = '\0';
+		return buf;
+	}
+	/* Iterate directory entries */
+	DirEntry *de;
+	foreach (current->fs->cwdPath, de) {
+		len = strlen(de->name);
+		if (i + 1 + len >= PATH_MAX)
+			return (char *) -ENAMETOOLONG;
+		if (i + 1 + len >= size)
+			return (char *) -ERANGE;
+		path[i++] = '/';
+		strcpy(path + i, de->name);
+		i += len;
+	}
+	/* Copy to user buffer */
+	strcpy(buf, path);
+	buf[i] = '\0';
+	return buf;
+}
diff --git a/vfs/open.c b/vfs/open.c
index 9dd8978..cac1512 100644
--- a/vfs/open.c
+++ b/vfs/open.c
@@ -116,6 +116,8 @@ end:
 int
 open(const char *name, int flags, ...)
 {
+	if (!name)
+		return -EFAULT;
 	if (!verify_access(name, strnlen(name, PATH_MAX), PROT_READ))
 		return -EFAULT;