mirror of
https://github.com/drasko/codezero.git
synced 2026-08-28 17:20:06 +02:00
mkdir almost working.
Added changes to pathname lookup code so that the root directory special case is handled properly.
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
#include <l4/macros.h>
|
#include <l4/macros.h>
|
||||||
#include <l4lib/types.h>
|
#include <l4lib/types.h>
|
||||||
#include <stat.h>
|
#include <stat.h>
|
||||||
|
#include <path.h>
|
||||||
|
|
||||||
typedef void (*vnode_op_t)(void);
|
typedef void (*vnode_op_t)(void);
|
||||||
typedef void (*file_op_t)(void);
|
typedef void (*file_op_t)(void);
|
||||||
@@ -46,7 +46,7 @@ struct file_ops {
|
|||||||
/* Operations that work on vnode fields and associations between vnodes */
|
/* Operations that work on vnode fields and associations between vnodes */
|
||||||
struct vnode_ops {
|
struct vnode_ops {
|
||||||
vnode_op_t create;
|
vnode_op_t create;
|
||||||
struct vnode *(*lookup)(struct vnode *root, char *path);
|
struct vnode *(*lookup)(struct vnode *root, struct pathdata *pdata);
|
||||||
int (*readdir)(struct vnode *v);
|
int (*readdir)(struct vnode *v);
|
||||||
int (*filldir)(void *buf, struct vnode *v, int count);
|
int (*filldir)(void *buf, struct vnode *v, int count);
|
||||||
vnode_op_t link;
|
vnode_op_t link;
|
||||||
|
|||||||
26
tasks/fs0/include/path.h
Normal file
26
tasks/fs0/include/path.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Bahadir Balban
|
||||||
|
*
|
||||||
|
* Path lookup related information
|
||||||
|
*/
|
||||||
|
#ifndef __PATH_H__
|
||||||
|
#define __PATH_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME:
|
||||||
|
* These ought to be strings and split/comparison functions should
|
||||||
|
* always use strings because formats like UTF-8 wouldn't work.
|
||||||
|
*/
|
||||||
|
#define VFS_CHAR_SEP '/'
|
||||||
|
#define VFS_STR_ROOTDIR "/"
|
||||||
|
#define VFS_STR_PARDIR ".."
|
||||||
|
#define VFS_STR_CURDIR "."
|
||||||
|
#define VFS_STR_XATDIR "...."
|
||||||
|
|
||||||
|
struct pathdata {
|
||||||
|
struct tcb *task;
|
||||||
|
int root;
|
||||||
|
char *path;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __PATH_H__ */
|
||||||
@@ -8,20 +8,11 @@
|
|||||||
#include <l4/macros.h>
|
#include <l4/macros.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
#include <path.h>
|
||||||
|
|
||||||
extern struct list_head vnode_cache;
|
extern struct list_head vnode_cache;
|
||||||
extern struct list_head dentry_cache;
|
extern struct list_head dentry_cache;
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME:
|
|
||||||
* These ought to be strings and split/comparison functions should
|
|
||||||
* always use strings because formats like UTF-8 wouldn't work.
|
|
||||||
*/
|
|
||||||
#define VFS_STR_SEP '/'
|
|
||||||
#define VFS_STR_PARDIR ".."
|
|
||||||
#define VFS_STR_CURDIR "."
|
|
||||||
#define VFS_STR_XATDIR "...."
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a temporary replacement for page cache support provided by mm0.
|
* This is a temporary replacement for page cache support provided by mm0.
|
||||||
* Normally mm0 tracks all vnode pages, but this is used to track pages in
|
* Normally mm0 tracks all vnode pages, but this is used to track pages in
|
||||||
@@ -91,8 +82,8 @@ struct vfs_mountpoint {
|
|||||||
extern struct vfs_mountpoint vfs_root;
|
extern struct vfs_mountpoint vfs_root;
|
||||||
|
|
||||||
int vfs_mount_root(struct superblock *sb);
|
int vfs_mount_root(struct superblock *sb);
|
||||||
struct vnode *generic_vnode_lookup(struct vnode *thisnode, char *path);
|
struct vnode *generic_vnode_lookup(struct vnode *thisnode, struct pathdata *p);
|
||||||
struct vnode *vfs_lookup_bypath(struct tcb *task, char *path);
|
struct vnode *vfs_lookup_bypath(struct tcb *task, struct pathdata *p);
|
||||||
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum);
|
struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum);
|
||||||
|
|
||||||
#endif /* __VFS_H__ */
|
#endif /* __VFS_H__ */
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ char *splitpath(char **str, char sep)
|
|||||||
char *cursor = *str;
|
char *cursor = *str;
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
/* Root is the special case, return it as is. */
|
|
||||||
if (strcmp(*str, "/"))
|
|
||||||
return *str;
|
|
||||||
|
|
||||||
/* Move forward until no seperator */
|
/* Move forward until no seperator */
|
||||||
while (*cursor == sep) {
|
while (*cursor == sep) {
|
||||||
*cursor = '\0';
|
*cursor = '\0';
|
||||||
|
|||||||
@@ -14,47 +14,99 @@
|
|||||||
* and their vnodes, this itself checks all those children on that level for
|
* and their vnodes, this itself checks all those children on that level for
|
||||||
* a match, but it also calls lookup, which recursively checks lower levels.
|
* a match, but it also calls lookup, which recursively checks lower levels.
|
||||||
*/
|
*/
|
||||||
struct vnode *lookup_dentry_children(struct dentry *parentdir, char *path)
|
struct vnode *lookup_dentry_children(struct dentry *parentdir,
|
||||||
|
struct pathdata *pdata)
|
||||||
{
|
{
|
||||||
struct dentry *childdir;
|
struct dentry *childdir;
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
|
|
||||||
list_for_each_entry(childdir, &parentdir->children, child)
|
list_for_each_entry(childdir, &parentdir->children, child)
|
||||||
/* Non-zero result means either found it or error occured */
|
/* Non-zero result means either found it or error occured */
|
||||||
if ((v = childdir->vnode->ops.lookup(childdir->vnode, path)))
|
if ((v = childdir->vnode->ops.lookup(childdir->vnode, pdata)))
|
||||||
return v;
|
return v;
|
||||||
|
|
||||||
/* Out of all children dentries, neither was a match, so we return 0 */
|
/* Out of all children dentries, neither was a match, so we return 0 */
|
||||||
return PTR_ERR(-ENOENT);
|
return PTR_ERR(-ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup, recursive, assuming single-mountpoint */
|
/*
|
||||||
struct vnode *generic_vnode_lookup(struct vnode *thisnode, char *path)
|
* Check if we're really at root, return root string if so, and
|
||||||
|
* move the pdata string cursor to next component or the end of string.
|
||||||
|
*/
|
||||||
|
char *pathdata_handle_root(struct pathdata *pdata)
|
||||||
{
|
{
|
||||||
char *component = splitpath(&path, VFS_STR_SEP);
|
char *cursor = pdata->path;
|
||||||
|
|
||||||
|
/* Only handle if root */
|
||||||
|
if (!pdata->root)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Move forward until no seperator */
|
||||||
|
while (*cursor == VFS_CHAR_SEP) {
|
||||||
|
*cursor = '\0'; /* Zero out separators */
|
||||||
|
cursor++; /* Move to next */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Moved the cursor either to first char of
|
||||||
|
* next component, or the end of string
|
||||||
|
* (in which case cursor = '\0')
|
||||||
|
*/
|
||||||
|
pdata->path = cursor;
|
||||||
|
|
||||||
|
/* We have handled the root case, now turn it off */
|
||||||
|
pdata->root = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified pdata appropriately, return the root
|
||||||
|
* component. It's the root representer string, e.g. "/"
|
||||||
|
*/
|
||||||
|
return VFS_STR_ROOTDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lookup, recursive, assuming single-mountpoint */
|
||||||
|
struct vnode *generic_vnode_lookup(struct vnode *thisnode,
|
||||||
|
struct pathdata *pdata)
|
||||||
|
{
|
||||||
|
char *component;
|
||||||
struct dentry *d;
|
struct dentry *d;
|
||||||
struct vnode *found;
|
struct vnode *found;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine first component, taking root as special case.
|
||||||
|
*
|
||||||
|
* path (root = 0) -> first path component
|
||||||
|
* path (root = 1) -> VFS_STR_ROOTDIR
|
||||||
|
* where path = { "//comp1/comp2", "/", "/comp1/comp2", "comp1/comp2" }
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Handle the special root case */
|
||||||
|
if (pdata->root)
|
||||||
|
component = pathdata_handle_root(pdata);
|
||||||
|
/* Handle paths normally */
|
||||||
|
else
|
||||||
|
component = splitpath(&pdata->path, VFS_CHAR_SEP);
|
||||||
|
|
||||||
/* Does this path component match with any of this vnode's dentries? */
|
/* Does this path component match with any of this vnode's dentries? */
|
||||||
list_for_each_entry(d, &thisnode->dentries, vref) {
|
list_for_each_entry(d, &thisnode->dentries, vref) {
|
||||||
if (d->ops.compare(d, component)) {
|
if (d->ops.compare(d, component)) {
|
||||||
/* Is this a directory? */
|
/* Is this a directory? */
|
||||||
if (vfs_isdir(thisnode)) {
|
if (vfs_isdir(thisnode)) {
|
||||||
/* Are there any more path components? */
|
/* Are there any more path components? */
|
||||||
if (path) {
|
if (*pdata->path) {
|
||||||
/* Read directory contents */
|
/* Read directory contents */
|
||||||
if ((err = d->vnode->ops.readdir(d->vnode)) < 0)
|
if ((err = d->vnode->ops.readdir(d->vnode)) < 0)
|
||||||
return PTR_ERR(err);
|
return PTR_ERR(err);
|
||||||
|
|
||||||
/* Search all children one level below. */
|
/* Search all children one level below. */
|
||||||
if ((found = lookup_dentry_children(d, path)))
|
if ((found = lookup_dentry_children(d, pdata)))
|
||||||
/* Either found, or non-zero error */
|
/* Either found, or non-zero error */
|
||||||
return found;
|
return found;
|
||||||
} else
|
} else
|
||||||
return thisnode;
|
return thisnode;
|
||||||
} else { /* Its a file */
|
} else { /* Its a file */
|
||||||
if (path) /* There's still path, but not directory */
|
if (*pdata->path) /* There's still path, but not directory */
|
||||||
return PTR_ERR(-ENOTDIR);
|
return PTR_ERR(-ENOTDIR);
|
||||||
else /* No path left, found it, so return file */
|
else /* No path left, found it, so return file */
|
||||||
return thisnode;
|
return thisnode;
|
||||||
@@ -68,7 +120,7 @@ struct vnode *generic_vnode_lookup(struct vnode *thisnode, char *path)
|
|||||||
|
|
||||||
int generic_dentry_compare(struct dentry *d, char *name)
|
int generic_dentry_compare(struct dentry *d, char *name)
|
||||||
{
|
{
|
||||||
if (!strcmp(d->name, name))
|
if (!strcmp(d->name, name) || !strcmp(name, VFS_STR_CURDIR))
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ int memfs_file_read_write(struct vnode *v, unsigned int pfn,
|
|||||||
} else { /* Write-specific operations */
|
} else { /* Write-specific operations */
|
||||||
/* Is the write beyond current file size? */
|
/* Is the write beyond current file size? */
|
||||||
if (v->size < ((pfn + npages) * (blocksize))) {
|
if (v->size < ((pfn + npages) * (blocksize))) {
|
||||||
unsigned long diff = pfn + npages - __pfn(v->size);
|
unsigned long pagediff = pfn + npages - __pfn(v->size);
|
||||||
unsigned long holes;
|
unsigned long holes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -102,19 +102,18 @@ int memfs_file_read_write(struct vnode *v, unsigned int pfn,
|
|||||||
*/
|
*/
|
||||||
if (pfn > __pfn(v->size))
|
if (pfn > __pfn(v->size))
|
||||||
holes = pfn - __pfn(v->size);
|
holes = pfn - __pfn(v->size);
|
||||||
|
else
|
||||||
|
holes = 0;
|
||||||
|
|
||||||
/* Allocate new blocks */
|
/* Allocate new blocks */
|
||||||
for (int x = 0; x < diff; x++)
|
for (int x = 0; x < pagediff; x++)
|
||||||
if (!(i->block[__pfn(v->size) + x] = memfs_alloc_block(memfs_sb)))
|
if (!(i->block[__pfn(v->size) + x] =
|
||||||
|
memfs_alloc_block(v->sb->fs_super)))
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
/* Zero out the holes. FIXME: How do we zero out non-page-aligned bytes?` */
|
/* Zero out the holes. FIXME: How do we zero out non-page-aligned bytes?` */
|
||||||
for (int x = 0; x < holes; x++)
|
for (int x = 0; x < holes; x++)
|
||||||
memset(i->block[__pfn(v->size) + x], 0, blocksize);
|
memset(i->block[__pfn(v->size) + x], 0, blocksize);
|
||||||
|
|
||||||
/* Update size and the inode. FIXME: How do we handle non page-aligned size */
|
|
||||||
v->size = (pfn + npages) * blocksize;
|
|
||||||
v->sb->ops->write_vnode(v->sb, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the data from page buffer into inode blocks */
|
/* Copy the data from page buffer into inode blocks */
|
||||||
|
|||||||
@@ -135,8 +135,13 @@ int memfs_init_rootdir(struct superblock *sb)
|
|||||||
if (!(d = vfs_alloc_dentry()))
|
if (!(d = vfs_alloc_dentry()))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Initialise it. NOTE: On root, parent is itself */
|
/*
|
||||||
strncpy(d->name, "/", VFS_DNAME_MAX);
|
* Initialise it.
|
||||||
|
* NOTE: On root, parent is itself.
|
||||||
|
* NOTE: Root has no name. This helps since splitpath
|
||||||
|
* cuts out the '/' and "" is left for root name search.
|
||||||
|
*/
|
||||||
|
strncpy(d->name, VFS_STR_ROOTDIR, VFS_DNAME_MAX);
|
||||||
d->ops = generic_dentry_operations;
|
d->ops = generic_dentry_operations;
|
||||||
d->parent = d;
|
d->parent = d;
|
||||||
d->vnode = v;
|
d->vnode = v;
|
||||||
|
|||||||
@@ -228,8 +228,6 @@ int memfs_vnode_mknod(struct vnode *v, char *dirname, unsigned int mode)
|
|||||||
BUG_ON(parent->vref.next != &v->dentries);
|
BUG_ON(parent->vref.next != &v->dentries);
|
||||||
BUG_ON(!vfs_isdir(v));
|
BUG_ON(!vfs_isdir(v));
|
||||||
|
|
||||||
printf("Parent name: %s\n", parent->name);
|
|
||||||
|
|
||||||
/* Populate the children */
|
/* Populate the children */
|
||||||
if ((err = v->ops.readdir(v)) < 0)
|
if ((err = v->ops.readdir(v)) < 0)
|
||||||
return err;
|
return err;
|
||||||
@@ -263,8 +261,9 @@ int memfs_vnode_mknod(struct vnode *v, char *dirname, unsigned int mode)
|
|||||||
/* Write the updated directory buffer back to disk block */
|
/* Write the updated directory buffer back to disk block */
|
||||||
v->fops.write(v, 0, 1, v->dirbuf.buffer);
|
v->fops.write(v, 0, 1, v->dirbuf.buffer);
|
||||||
|
|
||||||
/* Update parent vnode */
|
/* Update parent vnode size */
|
||||||
v->size += sizeof(*memfsd);
|
v->size += sizeof(*memfsd);
|
||||||
|
v->sb->ops->write_vnode(v->sb, v);
|
||||||
|
|
||||||
/* Allocate a new vfs dentry */
|
/* Allocate a new vfs dentry */
|
||||||
if (!(newd = vfs_alloc_dentry()))
|
if (!(newd = vfs_alloc_dentry()))
|
||||||
@@ -382,7 +381,10 @@ int memfs_vnode_readdir(struct vnode *v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copies fs-specific dirent data into user buffer in
|
||||||
|
* generic struct dirent format.
|
||||||
|
*/
|
||||||
int memfs_vnode_filldir(void *userbuf, struct vnode *v, int count)
|
int memfs_vnode_filldir(void *userbuf, struct vnode *v, int count)
|
||||||
{
|
{
|
||||||
int nbytes;
|
int nbytes;
|
||||||
@@ -412,6 +414,7 @@ struct vnode_ops memfs_vnode_operations = {
|
|||||||
.readdir = memfs_vnode_readdir,
|
.readdir = memfs_vnode_readdir,
|
||||||
.filldir = memfs_vnode_filldir,
|
.filldir = memfs_vnode_filldir,
|
||||||
.mknod = memfs_vnode_mknod,
|
.mknod = memfs_vnode_mknod,
|
||||||
|
.lookup = generic_vnode_lookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct superblock_ops memfs_superblock_operations = {
|
struct superblock_ops memfs_superblock_operations = {
|
||||||
|
|||||||
@@ -43,21 +43,17 @@ int pager_sys_open(l4id_t sender, int fd, unsigned long vnum, unsigned long size
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Creates a node under a directory, e.g. a file, directory. */
|
/* Creates a node under a directory, e.g. a file, directory. */
|
||||||
int vfs_create(struct tcb *task, const char *pathname, unsigned int mode)
|
int vfs_create(struct tcb *task, struct pathdata *pdata, unsigned int mode)
|
||||||
{
|
{
|
||||||
char *pathbuf = alloca(strlen(pathname) + 1);
|
|
||||||
char *parentpath = pathbuf;
|
|
||||||
struct vnode *vparent;
|
struct vnode *vparent;
|
||||||
char *nodename;
|
char *nodename;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
strcpy(pathbuf, pathname);
|
|
||||||
|
|
||||||
/* The last component is to be created */
|
/* The last component is to be created */
|
||||||
nodename = splitpath_end(&parentpath, '/');
|
nodename = splitpath_end(&pdata->path, '/');
|
||||||
|
|
||||||
/* Check that the parent directory exists. */
|
/* Check that the parent directory exists. */
|
||||||
if (IS_ERR(vparent = vfs_lookup_bypath(task, parentpath)))
|
if (IS_ERR(vparent = vfs_lookup_bypath(task, pdata)))
|
||||||
return (int)vparent;
|
return (int)vparent;
|
||||||
|
|
||||||
/* The parent vnode must be a directory. */
|
/* The parent vnode must be a directory. */
|
||||||
@@ -71,6 +67,17 @@ int vfs_create(struct tcb *task, const char *pathname, unsigned int mode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init_path_data(struct pathdata *pdata, const char *pathname,
|
||||||
|
void *pathbuf, struct tcb *task)
|
||||||
|
{
|
||||||
|
pdata->path = pathbuf;
|
||||||
|
strcpy(pdata->path, pathname);
|
||||||
|
pdata->task = task;
|
||||||
|
|
||||||
|
if (pdata->path[0] == '/')
|
||||||
|
pdata->root = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME:
|
/* FIXME:
|
||||||
* - Is it already open?
|
* - Is it already open?
|
||||||
* - Allocate a copy of path string since lookup destroys it
|
* - Allocate a copy of path string since lookup destroys it
|
||||||
@@ -78,24 +85,25 @@ int vfs_create(struct tcb *task, const char *pathname, unsigned int mode)
|
|||||||
*/
|
*/
|
||||||
int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
|
int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
|
||||||
{
|
{
|
||||||
char *pathbuf = alloca(strlen(pathname) + 1);
|
struct pathdata pdata;
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
struct tcb *task;
|
struct tcb *task;
|
||||||
int fd;
|
int fd;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
strcpy(pathbuf, pathname);
|
|
||||||
|
|
||||||
/* Get the task */
|
/* Get the task */
|
||||||
BUG_ON(!(task = find_task(sender)));
|
BUG_ON(!(task = find_task(sender)));
|
||||||
|
|
||||||
|
/* Initialise pdata */
|
||||||
|
init_path_data(&pdata, pathname, alloca(strlen(pathname) + 1), task);
|
||||||
|
|
||||||
/* Get the vnode */
|
/* Get the vnode */
|
||||||
if (IS_ERR(v = vfs_lookup_bypath(task, pathbuf))) {
|
if (IS_ERR(v = vfs_lookup_bypath(task, &pdata))) {
|
||||||
if (!(flags & O_CREAT)) {
|
if (!(flags & O_CREAT)) {
|
||||||
l4_ipc_return((int)v);
|
l4_ipc_return((int)v);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if ((err = vfs_create(task, pathname, mode)) < 0) {
|
if ((err = vfs_create(task, &pdata, mode)) < 0) {
|
||||||
l4_ipc_return(err);
|
l4_ipc_return(err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -123,27 +131,32 @@ int sys_close(l4id_t sender, int fd)
|
|||||||
int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)
|
int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)
|
||||||
{
|
{
|
||||||
struct tcb *task;
|
struct tcb *task;
|
||||||
|
struct pathdata pdata;
|
||||||
|
|
||||||
/* Get the task */
|
/* Get the task */
|
||||||
BUG_ON(!(task = find_task(sender)));
|
BUG_ON(!(task = find_task(sender)));
|
||||||
|
|
||||||
l4_ipc_return(vfs_create(task, pathname, mode));
|
/* Init path data */
|
||||||
|
init_path_data(&pdata, pathname, alloca(strlen(pathname) + 1), task);
|
||||||
|
|
||||||
|
l4_ipc_return(vfs_create(task, &pdata, mode));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_chdir(l4id_t sender, const char *pathname)
|
int sys_chdir(l4id_t sender, const char *pathname)
|
||||||
{
|
{
|
||||||
char *pathbuf = alloca(strlen(pathname) + 1);
|
|
||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
struct tcb *task;
|
struct tcb *task;
|
||||||
|
struct pathdata pdata;
|
||||||
strcpy(pathbuf, pathname);
|
|
||||||
|
|
||||||
/* Get the task */
|
/* Get the task */
|
||||||
BUG_ON(!(task = find_task(sender)));
|
BUG_ON(!(task = find_task(sender)));
|
||||||
|
|
||||||
|
/* Init path data */
|
||||||
|
init_path_data(&pdata, pathname, alloca(strlen(pathname) + 1), task);
|
||||||
|
|
||||||
/* Get the vnode */
|
/* Get the vnode */
|
||||||
if (IS_ERR(v = vfs_lookup_bypath(task, pathbuf)))
|
if (IS_ERR(v = vfs_lookup_bypath(task, &pdata)))
|
||||||
return (int)v;
|
return (int)v;
|
||||||
|
|
||||||
/* Ensure it's a directory */
|
/* Ensure it's a directory */
|
||||||
|
|||||||
@@ -57,18 +57,12 @@ struct vnode *vfs_lookup_byvnum(struct superblock *sb, unsigned long vnum)
|
|||||||
* have, the other is their vnum. This one checks the vnode cache by the path
|
* have, the other is their vnum. This one checks the vnode cache by the path
|
||||||
* first. If nothing is found, it reads the vnode from disk into the cache.
|
* first. If nothing is found, it reads the vnode from disk into the cache.
|
||||||
*/
|
*/
|
||||||
struct vnode *vfs_lookup_bypath(struct tcb *task, char *path)
|
struct vnode *vfs_lookup_bypath(struct tcb *task, struct pathdata *pdata)
|
||||||
{
|
{
|
||||||
struct vnode *vstart;
|
struct vnode *vstart;
|
||||||
|
|
||||||
/* Is it the root or current directory? If so, we already got it. */
|
|
||||||
if (!strcmp(path, "/"))
|
|
||||||
return task->rootdir;
|
|
||||||
if (!strcmp(path, "."))
|
|
||||||
return task->curdir;
|
|
||||||
|
|
||||||
/* Do we start from root or curdir? */
|
/* Do we start from root or curdir? */
|
||||||
if (path[0] == '/')
|
if (pdata->root)
|
||||||
vstart = task->rootdir;
|
vstart = task->rootdir;
|
||||||
else
|
else
|
||||||
vstart = task->curdir;
|
vstart = task->curdir;
|
||||||
@@ -76,7 +70,7 @@ struct vnode *vfs_lookup_bypath(struct tcb *task, char *path)
|
|||||||
/*
|
/*
|
||||||
* This does vfs cache + fs lookup.
|
* This does vfs cache + fs lookup.
|
||||||
*/
|
*/
|
||||||
return generic_vnode_lookup(vstart, path);
|
return vstart->ops.lookup(vstart, pdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
int vfs_mount_root(struct superblock *sb)
|
int vfs_mount_root(struct superblock *sb)
|
||||||
|
|||||||
@@ -136,6 +136,20 @@ int dirtest(void)
|
|||||||
printf("\nCreating directories: usr, etc, tmp, var, home, opt, bin, boot, lib, dev\n");
|
printf("\nCreating directories: usr, etc, tmp, var, home, opt, bin, boot, lib, dev\n");
|
||||||
if (mkdir("/usr", 0) < 0)
|
if (mkdir("/usr", 0) < 0)
|
||||||
perror("MKDIR");
|
perror("MKDIR");
|
||||||
|
if (mkdir("/etc", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
if (mkdir("/tmp", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
if (mkdir("/var", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
if (mkdir("/bin", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
if (mkdir("/boot", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
if (mkdir("/lib", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
if (mkdir("/dev", 0) < 0)
|
||||||
|
perror("MKDIR");
|
||||||
|
|
||||||
printf("\nlsdir root directory:\n");
|
printf("\nlsdir root directory:\n");
|
||||||
lsdir("/");
|
lsdir("/");
|
||||||
|
|||||||
Reference in New Issue
Block a user