Nucleus
Barry System headers (remove libc dependency) 18495cf (3 years, 2 months ago)
/*
* This file handles mounting various file systems into the VFS. This is the
* mount system call.
*/
#include <sys/errno.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <nucleus/lib.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);
/* Mount a file system */
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))
return -EFAULT;
if (!verify_access(type, strnlen(type, 16), PROT_READ))
return -EFAULT;
Inode *mnt = NULL;
int res = mount_fstype(type, flags, src, data, &mnt);
if (res < 0)
return res;
if (!mnt)
return -ENODEV;
/* Mount as VFS root */
if (!target && !current->fs->root) {
current->fs->root = get(mnt);
current->fs->cwd = get(mnt);
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;
}