mirror of
https://github.com/drasko/codezero.git
synced 2026-09-18 03:17:07 +02:00
Reorganised sys_open.
vfs_create and mknod now returns the newly created vnode. (which might be used by upper layers).
This commit is contained in:
@@ -53,7 +53,8 @@ struct vnode_ops {
|
|||||||
vnode_op_t link;
|
vnode_op_t link;
|
||||||
vnode_op_t unlink;
|
vnode_op_t unlink;
|
||||||
int (*mkdir)(struct vnode *parent, const char *name);
|
int (*mkdir)(struct vnode *parent, const char *name);
|
||||||
int (*mknod)(struct vnode *parent, const char *name, unsigned int mode);
|
struct vnode *(*mknod)(struct vnode *parent, const char *name,
|
||||||
|
unsigned int mode);
|
||||||
vnode_op_t rmdir;
|
vnode_op_t rmdir;
|
||||||
vnode_op_t rename;
|
vnode_op_t rename;
|
||||||
vnode_op_t getattr;
|
vnode_op_t getattr;
|
||||||
|
|||||||
@@ -208,9 +208,10 @@ int memfs_write_vnode(struct superblock *sb, struct vnode *v)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates ordinary files and directories at the moment. In the future,
|
* Creates ordinary files and directories at the moment. In the future,
|
||||||
* other file types will be added.
|
* other file types will be added. Returns the created node.
|
||||||
*/
|
*/
|
||||||
int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
|
struct vnode *memfs_vnode_mknod(struct vnode *v, const char *dirname,
|
||||||
|
unsigned int mode)
|
||||||
{
|
{
|
||||||
struct dentry *d, *parent = list_entry(v->dentries.next,
|
struct dentry *d, *parent = list_entry(v->dentries.next,
|
||||||
struct dentry, vref);
|
struct dentry, vref);
|
||||||
@@ -230,25 +231,25 @@ int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
|
|||||||
|
|
||||||
/* Populate the children */
|
/* Populate the children */
|
||||||
if ((err = v->ops.readdir(v)) < 0)
|
if ((err = v->ops.readdir(v)) < 0)
|
||||||
return err;
|
return PTR_ERR(err);
|
||||||
|
|
||||||
/* Check there's no existing child with same name */
|
/* Check there's no existing child with same name */
|
||||||
list_for_each_entry(d, &parent->children, child) {
|
list_for_each_entry(d, &parent->children, child) {
|
||||||
/* Does the name exist as a child? */
|
/* Does the name exist as a child? */
|
||||||
if(d->ops.compare(d, dirname))
|
if(d->ops.compare(d, dirname))
|
||||||
return -EEXIST;
|
return PTR_ERR(-EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a new vnode for the new directory */
|
/* Allocate a new vnode for the new directory */
|
||||||
if (IS_ERR(newv = v->sb->ops->alloc_vnode(v->sb)))
|
if (IS_ERR(newv = v->sb->ops->alloc_vnode(v->sb)))
|
||||||
return (int)newv;
|
return newv;
|
||||||
|
|
||||||
/* Initialise the vnode */
|
/* Initialise the vnode */
|
||||||
vfs_set_type(newv, S_IFDIR);
|
vfs_set_type(newv, S_IFDIR);
|
||||||
|
|
||||||
/* Get the next directory entry available on the parent vnode */
|
/* Get the next directory entry available on the parent vnode */
|
||||||
if (v->dirbuf.npages * PAGE_SIZE <= v->size)
|
if (v->dirbuf.npages * PAGE_SIZE <= v->size)
|
||||||
return -ENOSPC;
|
return PTR_ERR(-ENOSPC);
|
||||||
|
|
||||||
/* Fill in the new entry to parent directory entry */
|
/* Fill in the new entry to parent directory entry */
|
||||||
memfsd = (struct memfs_dentry *)&v->dirbuf.buffer[v->size];
|
memfsd = (struct memfs_dentry *)&v->dirbuf.buffer[v->size];
|
||||||
@@ -267,7 +268,7 @@ int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
|
|||||||
|
|
||||||
/* Allocate a new vfs dentry */
|
/* Allocate a new vfs dentry */
|
||||||
if (!(newd = vfs_alloc_dentry()))
|
if (!(newd = vfs_alloc_dentry()))
|
||||||
return -ENOMEM;
|
return PTR_ERR(-ENOMEM);
|
||||||
|
|
||||||
/* Initialise it */
|
/* Initialise it */
|
||||||
newd->ops = generic_dentry_operations;
|
newd->ops = generic_dentry_operations;
|
||||||
@@ -285,7 +286,7 @@ int memfs_vnode_mknod(struct vnode *v, const char *dirname, unsigned int mode)
|
|||||||
list_add(&newd->cache_list, &dentry_cache);
|
list_add(&newd->cache_list, &dentry_cache);
|
||||||
list_add(&newv->cache_list, &vnode_cache);
|
list_add(&newv->cache_list, &vnode_cache);
|
||||||
|
|
||||||
return 0;
|
return newv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+32
-20
@@ -58,35 +58,41 @@ void print_vnode(struct vnode *v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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, struct pathdata *pdata, unsigned int mode)
|
struct vnode *vfs_create(struct tcb *task, struct pathdata *pdata,
|
||||||
|
unsigned int mode)
|
||||||
{
|
{
|
||||||
struct vnode *vparent;
|
struct vnode *vparent, *newnode;
|
||||||
const char *nodename;
|
const char *nodename;
|
||||||
int err;
|
|
||||||
|
|
||||||
/* The last component is to be created */
|
/* The last component is to be created */
|
||||||
nodename = pathdata_last_component(pdata);
|
nodename = pathdata_last_component(pdata);
|
||||||
|
|
||||||
/* Check that the parent directory exists. */
|
/* Check that the parent directory exists. */
|
||||||
if (IS_ERR(vparent = vfs_lookup_bypath(pdata)))
|
if (IS_ERR(vparent = vfs_lookup_bypath(pdata)))
|
||||||
return (int)vparent;
|
return vparent;
|
||||||
|
|
||||||
/* The parent vnode must be a directory. */
|
/* The parent vnode must be a directory. */
|
||||||
if (!vfs_isdir(vparent))
|
if (!vfs_isdir(vparent))
|
||||||
return -ENOENT;
|
return PTR_ERR(-ENOENT);
|
||||||
|
|
||||||
/* Create new directory under the parent */
|
/* Create new directory under the parent */
|
||||||
if ((err = vparent->ops.mknod(vparent, nodename, mode)) < 0)
|
if (IS_ERR(newnode = vparent->ops.mknod(vparent, nodename, mode)))
|
||||||
return err;
|
return newnode;
|
||||||
|
|
||||||
// print_vnode(vparent);
|
// print_vnode(vparent);
|
||||||
return 0;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
* - Check flags and mode.
|
* - Check flags and mode.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* - All return paths should return by destroying pdata.
|
||||||
|
* - Need another pdata for vfs_create since first lookup destroys it.
|
||||||
|
* - Or perhaps we check O_CREAT first, and do lookup once, without the
|
||||||
|
* last path component which is to be created.
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -94,7 +100,7 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
|
|||||||
struct vnode *v;
|
struct vnode *v;
|
||||||
struct tcb *task;
|
struct tcb *task;
|
||||||
int fd;
|
int fd;
|
||||||
int err;
|
int retval;
|
||||||
|
|
||||||
/* Get the task */
|
/* Get the task */
|
||||||
BUG_ON(!(task = find_task(sender)));
|
BUG_ON(!(task = find_task(sender)));
|
||||||
@@ -107,16 +113,17 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the vnode */
|
/* Creating new node, file or directory */
|
||||||
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
|
if (flags & O_CREAT) {
|
||||||
if (!(flags & O_CREAT)) {
|
if (IS_ERR(v = vfs_create(task, pdata, mode))) {
|
||||||
l4_ipc_return((int)v);
|
retval = (int)v;
|
||||||
return 0;
|
goto out;
|
||||||
} else {
|
|
||||||
if ((err = vfs_create(task, pdata, mode)) < 0) {
|
|
||||||
l4_ipc_return(err);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* Not creating, just opening, get the vnode */
|
||||||
|
if (IS_ERR(v = vfs_lookup_bypath(pdata))) {
|
||||||
|
retval = (int)v;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +136,9 @@ int sys_open(l4id_t sender, const char *pathname, int flags, unsigned int mode)
|
|||||||
/* Tell the pager about opened vnode information */
|
/* Tell the pager about opened vnode information */
|
||||||
BUG_ON(pager_sys_open(sender, fd, v->vnum, v->size) < 0);
|
BUG_ON(pager_sys_open(sender, fd, v->vnum, v->size) < 0);
|
||||||
|
|
||||||
|
out:
|
||||||
pathdata_destroy(pdata);
|
pathdata_destroy(pdata);
|
||||||
l4_ipc_return(fd);
|
l4_ipc_return(retval);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,6 +168,7 @@ int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)
|
|||||||
{
|
{
|
||||||
struct tcb *task;
|
struct tcb *task;
|
||||||
struct pathdata *pdata;
|
struct pathdata *pdata;
|
||||||
|
struct vnode *v;
|
||||||
|
|
||||||
/* Get the task */
|
/* Get the task */
|
||||||
BUG_ON(!(task = find_task(sender)));
|
BUG_ON(!(task = find_task(sender)));
|
||||||
@@ -173,7 +182,10 @@ int sys_mkdir(l4id_t sender, const char *pathname, unsigned int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create the directory or fail */
|
/* Create the directory or fail */
|
||||||
l4_ipc_return(vfs_create(task, pdata, mode));
|
if (IS_ERR(v = vfs_create(task, pdata, mode)))
|
||||||
|
l4_ipc_return((int)v);
|
||||||
|
else
|
||||||
|
l4_ipc_return(0);
|
||||||
|
|
||||||
/* Destroy extracted path data */
|
/* Destroy extracted path data */
|
||||||
pathdata_destroy(pdata);
|
pathdata_destroy(pdata);
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ int sys_read(l4id_t sender, int fd, void *buf, int count)
|
|||||||
|
|
||||||
int sys_write(l4id_t sender, int fd, void *buf, int count)
|
int sys_write(l4id_t sender, int fd, void *buf, int count)
|
||||||
{
|
{
|
||||||
|
BUG();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,51 @@ int fileio(void)
|
|||||||
int fd;
|
int fd;
|
||||||
ssize_t cnt;
|
ssize_t cnt;
|
||||||
int err;
|
int err;
|
||||||
|
char buf[128];
|
||||||
|
off_t offset;
|
||||||
|
|
||||||
char *str = "I WROTE TO THIS FILE\n";
|
char *str = "I WROTE TO THIS FILE\n";
|
||||||
|
|
||||||
if ((fd = open("/home/bahadir/newfile.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) {
|
if ((fd = open("/home/bahadir/newfile.txt", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) {
|
||||||
perror("OPEN");
|
perror("OPEN");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int)(cnt = write(fd, str, strlen(str))) < 0) {
|
if ((int)(cnt = write(fd, str, strlen(str))) < 0) {
|
||||||
perror("WRITE");
|
perror("WRITE");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = close(fd)) < 0)
|
if ((int)(offset = lseek(fd, 0, SEEK_SET)) < 0) {
|
||||||
|
perror("LSEEK");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((int)(cnt = read(fd, buf, strlen(str))) < 0) {
|
||||||
|
perror("WRITE");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Read: %d bytes from file.\n", cnt);
|
||||||
|
if (cnt) {
|
||||||
|
printf("Read string: %s\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = close(fd)) < 0) {
|
||||||
perror("CLOSE");
|
perror("CLOSE");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HOST_TESTS)
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("File IO test:\n");
|
||||||
|
if (fileio() == 0)
|
||||||
|
printf("-- PASSED --\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user