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;
+}