diff --git a/drivers/char/null.c b/drivers/char/null.c index f24fc593..c1fc9e69 100644 --- a/drivers/char/null.c +++ b/drivers/char/null.c @@ -39,7 +39,7 @@ static ssize_t null_write(fildes_t* file, uint8_t* buffer, size_t size) return size; } -static int null_open(vfs_node_t* node) +static int null_open(fildes_t* file, const char* name) { return 0; } diff --git a/drivers/stderr/stderr.c b/drivers/stderr/stderr.c index 32a926e8..5ee63ec7 100644 --- a/drivers/stderr/stderr.c +++ b/drivers/stderr/stderr.c @@ -43,7 +43,7 @@ static ssize_t stderr_write(fildes_t* file, uint8_t* buffer, size_t size) return size; } -static int stderr_open(vfs_node_t* node) +static int stderr_open(fildes_t* file, const char* name) { return 0; } diff --git a/drivers/stdin/stdin.c b/drivers/stdin/stdin.c index 9baecb3a..ab4d0c36 100644 --- a/drivers/stdin/stdin.c +++ b/drivers/stdin/stdin.c @@ -54,7 +54,7 @@ static ssize_t stdin_write(fildes_t* file, uint8_t* buffer, size_t size) return size; } -static int stdin_open(vfs_node_t* node) +static int stdin_open(fildes_t* file, const char* name) { return 0; } diff --git a/drivers/stdout/stdout.c b/drivers/stdout/stdout.c index c68eb588..e0082934 100644 --- a/drivers/stdout/stdout.c +++ b/drivers/stdout/stdout.c @@ -42,7 +42,7 @@ static ssize_t stdout_write(fildes_t* file, uint8_t* buffer, size_t size) return size; } -static int stdout_open(vfs_node_t* node) +static int stdout_open(fildes_t* file, const char* name) { return 0; } diff --git a/fs/fs.c b/fs/fs.c index 53488e97..9944f9a1 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -59,45 +59,48 @@ ssize_t write_fs(fildes_t* file, uint8_t* buffer, size_t size) return ret; } -vfs_node_t* open_fs(const char* name, int flags) +int open_fs(fildes_t* file, const char* name) { - uint32_t i, j = 1; - vfs_node_t* ret = NULL; - vfs_node_t* fnode = NULL; /* file node */ - vfs_node_t* node = NULL; + uint32_t ret = 0, i, j = 1; + vfs_node_t* file_node = NULL; /* file node */ + vfs_node_t* dir_node = NULL; char fname[MAX_FNAME]; if (BUILTIN_EXPECT(!name, 0)) return ret; if (name[0] == '/') - ret = fs_root; + file_node = fs_root; - while((name[j] != '\0') && ret) { + while((name[j] != '\0') && file_node) { i = 0; while((name[j] != '/') && (name[j] != '\0')) { fname[i] = name[j]; i++; j++; } fname[i] = '\0'; - node = fnode; - fnode = finddir_fs(fnode, fname); + dir_node = file_node; /* file must be a dictionary */ + file_node = finddir_fs(dir_node, fname); if (name[j] == '/') j++; } - if(fnode) { - node = fnode; - name = NULL; - if(!(flags & O_TRUNC)) - return fnode; + /* file exists */ + if(file_node) { + spinlock_lock(&file_node->lock); + file->node = file_node; + // Has the file_node got an open callback? + if (file_node->open != 0) + ret = file->node->open(file, NULL); + spinlock_unlock(&file_node->lock); + } else { /* file doesn't exist */ + spinlock_lock(&dir_node->lock); + file->node = dir_node; + // Has the dir_node got an open callback? + if (file_node->open != 0) + ret = file->node->open(file, fname); + spinlock_unlock(&file_node->lock); } - - spinlock_lock(&node->lock); - // Has the node got an open callback? - if (node->open != 0) - ret = node->open(node); - spinlock_unlock(&node->lock); return ret; } diff --git a/fs/initrd.c b/fs/initrd.c index 0c49cac8..22915cb8 100644 --- a/fs/initrd.c +++ b/fs/initrd.c @@ -165,20 +165,46 @@ static ssize_t initrd_write(fildes_t* file, uint8_t* buffer, size_t size) return size; } -static int initrd_open(vfs_node_t* node) +static int initrd_open(fildes_t* file, const char* name) { + if (file->node->type == FS_FILE) { + if ((file->flags & O_CREAT) && (file->flags & O_EXCL)) + return -EINVAL; + + /* in the case of O_TRUNC kfree all the nodes */ + if (file->flags & O_TRUNC) { + uint32_t i; + char* data = NULL; + block_list_t* blist = &file->node->block_list; + block_list_t* preblist = NULL; + do { + for(i=0; idata[i]) { + kfree(blist->data[i], + sizeof(data_block_t)); + } + } + preblist = blist; + blist = blist->next; + kfree(preblist, sizeof(block_list_t)); + } while(blist); + /* reset the block_size */ + file->node->block_size = 0; + } + } + if (file->node->type == FS_DIRECTORY) { + if (!(file->flags & O_CREAT)) + return -EINVAL; - uint32_t i, j; - char* data = NULL; - block_list_t* blist = NULL; + uint32_t i, j; - if (BUILTIN_EXPECT(node->type != FS_DIRECTORY, 0)) { + block_list_t* blist = NULL; /* CREATE FILE */ vfs_node_t* new_node = kmalloc(sizeof(vfs_node_t)); if (BUILTIN_EXPECT(!new_node, 0)) - return 0; + return -EINVAL; - blist = &node->block_list; + blist = &file->node->block_list; dir_block_t* dir_block; dirent_t* dirent; @@ -198,8 +224,8 @@ static int initrd_open(vfs_node_t* node) dirent = &dir_block->entries[j]; if (!dirent->vfs_node) { dirent->vfs_node = new_node; - //strncpy(dirent->name, (char*) name, MAX_FNAME); - goto exit_for; /* there might be a better Solution *********************************/ + strncpy(dirent->name, (char*) name, MAX_FNAME); + goto exit_create_file; /* there might be a better Solution *********************************/ } } } @@ -213,30 +239,11 @@ static int initrd_open(vfs_node_t* node) blist = blist->next; } while(blist); -exit_for: - node = new_node; - } - if (BUILTIN_EXPECT(node->type != FS_FILE, 0)) { - /* in the case of O_TRUNC */ - block_list_t* blist = &node->block_list; - block_list_t* preblist = NULL; - do { - for(i=0; idata[i]) { - kfree(blist->data[i], sizeof(data_block_t)); - } - } - preblist = blist; - blist = blist->next; - kfree(preblist, sizeof(block_list_t)); - } while(blist); - } - /* init new file */ - node->block_size = 0; - //&node->block_list = NULL; - - //return node; +exit_create_file: + file->node = new_node; + file->node->block_size = 0; + } return 0; } diff --git a/include/metalsvm/fs.h b/include/metalsvm/fs.h index 1584477f..03495bda 100644 --- a/include/metalsvm/fs.h +++ b/include/metalsvm/fs.h @@ -83,7 +83,7 @@ typedef ssize_t (*read_type_t) (struct fildes *, uint8_t*, size_t); /** @brief Write function pointer */ typedef ssize_t (*write_type_t) (struct fildes *, uint8_t*, size_t); /** @brief Open function pointer */ -typedef int (*open_type_t) (struct vfs_node *); +typedef int (*open_type_t) (struct fildes *, const char *name); /** @brief Close function pointer */ typedef int (*close_type_t) (struct vfs_node *); /** @brief Read directory function pointer */ @@ -200,7 +200,7 @@ ssize_t read_fs(fildes_t* file, uint8_t* buffer, size_t size); ssize_t write_fs(fildes_t* file, uint8_t* buffer, size_t size); /** @brief Yet to be documented */ -vfs_node_t* open_fs(const char* name, int flags); +int open_fs(fildes_t* file, const char* fname); /** @brief Yet to be documented */ int close_fs(vfs_node_t * node); diff --git a/kernel/syscall.c b/kernel/syscall.c index 7c0ce5b5..ff2ff601 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -33,26 +33,25 @@ static int sys_write(int fd, const char *buf, size_t len) (uint8_t*)buf, len); } -static int sys_open(const char* fname, int flags, int mode) +static int sys_open(const char* name, int flags, int mode) { - int fd; + int fd, check; fildes_t* file = NULL; - if (!findnode_fs((char*) fname)) { - if (flags & O_CREAT) { - //create file, not implemented yet - } - return -EINVAL; - } else { - if ((flags & O_CREAT) && (flags & O_EXCL)); - return -EINVAL; - } for (fd = 3; fd < NR_OPEN; fd++) { if (per_core(current_task)->fildes_table[fd].node == NULL) { file = &(per_core(current_task)->fildes_table[fd]); - file->node = findnode_fs((char*) fname); file->mode = mode; file->flags = flags; + check = open_fs(file, (char*) name); + if (BUILTIN_EXPECT(check != -EINVAL, 0)) { + /* file doesn't exist! */ + file->node = NULL; + file->offset = 0; + file->mode = 0; + file->flags = 0; + return -EINVAL; + } } } if (fd >= NR_OPEN) { @@ -61,7 +60,6 @@ static int sys_open(const char* fname, int flags, int mode) } return fd; - } static int sys_close(int fd) @@ -163,10 +161,10 @@ int syscall_handler(uint32_t sys_nr, ...) break; } case __NR_open: { - const char* fname = va_arg(vl, const char*); + const char* name = va_arg(vl, const char*); int flags = va_arg(vl, int); int mode = va_arg(vl, int); - ret = sys_open(fname, flags, mode); + ret = sys_open(name, flags, mode); break; } case __NR_close: {