BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / d3f787c50eda2dadb77ae216aef1f0bd0a686ae3 / vfs / namespace.c

// Related

Nucleus

Barry More VFS functions and structure d3f787c (3 years, 2 months ago)
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;
+}