diff --git a/src/kernel/core/fs/bootfs.c b/src/kernel/core/fs/bootfs.c index 23d26a4943..874f3fc24d 100755 --- a/src/kernel/core/fs/bootfs.c +++ b/src/kernel/core/fs/bootfs.c @@ -589,48 +589,34 @@ err: static int -bootfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, stream_type st, int oflags) +bootfs_create(fs_cookie _fs, fs_vnode _dir, file_cookie *_cookie, vnode_id *new_vnid, const char *name, int omode, int perms) +{ + return EROFS; +} + + +static int +bootfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags) { struct bootfs *fs = _fs; - struct bootfs_vnode *v = _v; + struct bootfs_vnode *vnode = _v; struct bootfs_cookie *cookie; - int err = 0; - int start = 0; - TRACE(("bootfs_open: vnode 0x%x, stream_type %d, oflags 0x%x\n", v, st, oflags)); - - if(st != STREAM_TYPE_ANY && st != v->stream.type) { - err = ERR_VFS_WRONG_STREAM_TYPE; - goto err; - } + TRACE(("bootfs_open: vnode 0x%x, oflags 0x%x\n", vnode, oflags)); cookie = kmalloc(sizeof(struct bootfs_cookie)); - if (cookie == NULL) { - err = ENOMEM; - goto err; - } + if (cookie == NULL) + return ENOMEM; mutex_lock(&fs->lock); - cookie->s = &v->stream; - switch(v->stream.type) { - case STREAM_TYPE_DIR: - cookie->u.dir.ptr = v->stream.u.dir.dir_head; - break; - case STREAM_TYPE_FILE: - cookie->u.file.pos = 0; - break; - default: - err = ERR_VFS_WRONG_STREAM_TYPE; - kfree(cookie); - } - + cookie->s = &vnode->stream; + cookie->u.file.pos = 0; *_cookie = cookie; -err1: mutex_unlock(&fs->lock); -err: - return err; + + return B_OK; } @@ -648,7 +634,7 @@ bootfs_close(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) static int -bootfs_freecookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) +bootfs_free_cookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) { struct bootfs *fs = _fs; struct bootfs_vnode *v = _v; @@ -656,7 +642,7 @@ bootfs_freecookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) TRACE(("bootfs_freecookie: entry vnode 0x%x, cookie 0x%x\n", v, cookie)); - if(cookie) + if (cookie) kfree(cookie); return 0; @@ -798,6 +784,42 @@ bootfs_seek(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, off_t pos, int st) } +static int +bootfs_create_dir(fs_cookie _fs, fs_vnode _dir, const char *name, int perms, vnode_id *new_vnid) +{ + return EROFS; +} + + +static int +bootfs_open_dir(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie) +{ + struct bootfs *fs = _fs; + struct bootfs_vnode *vnode = _v; + struct bootfs_cookie *cookie; + int status = 0; + + TRACE(("bootfs_open_dir: vnode 0x%x\n", vnode)); + + if (vnode->stream.type != STREAM_TYPE_DIR) + return EINVAL; + + cookie = kmalloc(sizeof(struct bootfs_cookie)); + if (cookie == NULL) + return ENOMEM; + + mutex_lock(&fs->lock); + + cookie->s = &vnode->stream; + cookie->u.dir.ptr = vnode->stream.u.dir.dir_head; + *_cookie = cookie; + + mutex_unlock(&fs->lock); + + return status; +} + + static int bootfs_read_dir(fs_cookie _fs, fs_vnode _vnode, file_cookie _cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { @@ -917,13 +939,6 @@ bootfs_writepage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos) } -static int -bootfs_create(fs_cookie _fs, fs_vnode _dir, const char *name, stream_type st, void *create_args, vnode_id *new_vnid) -{ - return EROFS; -} - - static int bootfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name) { @@ -939,12 +954,12 @@ bootfs_rename(fs_cookie _fs, fs_vnode _olddir, const char *oldname, fs_vnode _ne static int -bootfs_rstat(fs_cookie _fs, fs_vnode _v, struct stat *stat) +bootfs_read_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat) { struct bootfs *fs = _fs; struct bootfs_vnode *v = _v; int err = 0; -//dprintf("bootfs_rstat:\n"); + TRACE(("bootfs_rstat: vnode 0x%x (0x%x 0x%x), stat 0x%x\n", v, v->id, stat)); mutex_lock(&fs->lock); @@ -978,7 +993,7 @@ err: static int -bootfs_wstat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask) +bootfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask) { struct bootfs *fs = _fs; struct bootfs_vnode *v = _v; @@ -1004,30 +1019,36 @@ static struct fs_calls bootfs_calls = { &bootfs_putvnode, &bootfs_removevnode, - &bootfs_open, - &bootfs_close, - &bootfs_freecookie, - &bootfs_fsync, - - &bootfs_read, - &bootfs_write, - &bootfs_seek, - - &bootfs_read_dir, - &bootfs_rewind_dir, - - &bootfs_ioctl, - &bootfs_canpage, &bootfs_readpage, &bootfs_writepage, - &bootfs_create, + /* common */ + &bootfs_ioctl, + &bootfs_fsync, + &bootfs_unlink, &bootfs_rename, - &bootfs_rstat, - &bootfs_wstat, + &bootfs_read_stat, + &bootfs_write_stat, + + /* file */ + &bootfs_create, + &bootfs_open, + &bootfs_close, + &bootfs_free_cookie, + &bootfs_read, + &bootfs_write, + &bootfs_seek, + + /* dir */ + &bootfs_create_dir, + &bootfs_open_dir, + &bootfs_close, // we are using the same operations for directories + &bootfs_free_cookie, // and files here - that's intended, not by accident + &bootfs_read_dir, + &bootfs_rewind_dir, }; @@ -1041,8 +1062,9 @@ bootstrap_bootfs(void) // find the bootdir and set it up rid = vm_find_region_by_name(vm_get_kernel_aspace_id(), "bootdir"); - if(rid < 0) + if (rid < 0) panic("bootstrap_bootfs: no bootdir area found!\n"); + vm_get_region_info(rid, &rinfo); bootdir = (char *)rinfo.base; bootdir_len = rinfo.size; diff --git a/src/kernel/core/fs/devfs.c b/src/kernel/core/fs/devfs.c index 7461335d9a..15344f1742 100755 --- a/src/kernel/core/fs/devfs.c +++ b/src/kernel/core/fs/devfs.c @@ -399,14 +399,14 @@ devfs_mount(fs_cookie *_fs, fs_id id, const char *devfs, void *args, vnode_id *r TRACE(("devfs_mount: entry\n")); - if(thedevfs) { + if (thedevfs) { dprintf("double mount of devfs attempted\n"); err = ERR_GENERAL; goto err; } fs = kmalloc(sizeof(struct devfs)); - if(fs == NULL) { + if (fs == NULL) { err = ENOMEM; goto err; } @@ -415,20 +415,20 @@ devfs_mount(fs_cookie *_fs, fs_id id, const char *devfs, void *args, vnode_id *r fs->next_vnode_id = 0; err = mutex_init(&fs->lock, "devfs_mutex"); - if(err < 0) { + if (err < 0) { goto err1; } fs->vnode_list_hash = hash_init(BOOTFS_HASH_SIZE, (addr)&v->all_next - (addr)v, &devfs_vnode_compare_func, &devfs_vnode_hash_func); - if(fs->vnode_list_hash == NULL) { + if (fs->vnode_list_hash == NULL) { err = ENOMEM; goto err2; } // create a vnode v = devfs_create_vnode(fs, ""); - if(v == NULL) { + if (v == NULL) { err = ENOMEM; goto err3; } @@ -462,7 +462,9 @@ err: return err; } -static int devfs_unmount(fs_cookie _fs) + +static int +devfs_unmount(fs_cookie _fs) { struct devfs *fs = _fs; struct devfs_vnode *v; @@ -484,14 +486,18 @@ static int devfs_unmount(fs_cookie _fs) return 0; } -static int devfs_sync(fs_cookie fs) + +static int +devfs_sync(fs_cookie fs) { TRACE(("devfs_sync: entry\n")); return 0; } -static int devfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id) + +static int +devfs_lookup(fs_cookie _fs, fs_vnode _dir, const char *name, vnode_id *id) { struct devfs *fs = (struct devfs *)_fs; struct devfs_vnode *dir = (struct devfs_vnode *)_dir; @@ -528,7 +534,9 @@ err: return err; } -static int devfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r) + +static int +devfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r) { struct devfs *fs = (struct devfs *)_fs; @@ -550,7 +558,9 @@ static int devfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r) return ERR_NOT_FOUND; } -static int devfs_putvnode(fs_cookie _fs, fs_vnode _v, bool r) + +static int +devfs_put_vnode(fs_cookie _fs, fs_vnode _v, bool r) { #if DEVFS_TRACE struct devfs_vnode *v = (struct devfs_vnode *)_v; @@ -561,7 +571,9 @@ static int devfs_putvnode(fs_cookie _fs, fs_vnode _v, bool r) return 0; // whatever } -static int devfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r) + +static int +devfs_remove_vnode(fs_cookie _fs, fs_vnode _v, bool r) { struct devfs *fs = (struct devfs *)_fs; struct devfs_vnode *v = (struct devfs_vnode *)_v; @@ -587,82 +599,66 @@ static int devfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r) return err; } -static int devfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, stream_type st, int oflags) + +static int +devfs_create(fs_cookie _fs, fs_vnode _dir, file_cookie *_cookie, vnode_id *new_vnid, const char *name, int omode, int perms) +{ + return EROFS; +} + + +static int +devfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags) { struct devfs *fs = _fs; - struct devfs_vnode *v = _v; + struct devfs_vnode *vnode = _v; struct devfs_cookie *cookie; - int err = 0; + int status = 0; TRACE(("devfs_open: vnode 0x%x, oflags 0x%x\n", v, oflags)); - if (st != STREAM_TYPE_ANY && st != v->stream.type) { - err = ERR_VFS_WRONG_STREAM_TYPE; - goto err; - } - cookie = kmalloc(sizeof(struct devfs_cookie)); - if (cookie == NULL) { - err = ENOMEM; - goto err; - } - - mutex_lock(&fs->lock); - - cookie->s = &v->stream; - switch(v->stream.type) { - case STREAM_TYPE_DIR: - cookie->u.dir.ptr = v->stream.u.dir.dir_head; - break; - case STREAM_TYPE_DEVICE: - // call the device call, but unlock the devfs first - mutex_unlock(&fs->lock); - err = v->stream.u.dev.calls->open(v->name, oflags, &cookie->u.dev.dcookie); - mutex_lock(&fs->lock); - break; - default: - err = ERR_VFS_WRONG_STREAM_TYPE; - kfree(cookie); - } + if (cookie == NULL) + return ENOMEM; + status = vnode->stream.u.dev.calls->open(vnode->name, oflags, &cookie->u.dev.dcookie); *_cookie = cookie; - mutex_unlock(&fs->lock); -err: - return err; + return status; } -static int devfs_close(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) + +static int +devfs_close(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) { - struct devfs_vnode *v = _v; + struct devfs_vnode *vnode = _v; struct devfs_cookie *cookie = _cookie; - int err; TRACE(("devfs_close: entry vnode 0x%x, cookie 0x%x\n", v, cookie)); - if(v->stream.type == STREAM_TYPE_DEVICE) { + if (vnode->stream.type == STREAM_TYPE_DEVICE) { // pass the call through to the underlying device - err = v->stream.u.dev.calls->close(cookie->u.dev.dcookie); - } else { - err = 0; + return vnode->stream.u.dev.calls->close(cookie->u.dev.dcookie); } - return err; + return B_OK; } -static int devfs_freecookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) + +static int +devfs_free_cookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) { - struct devfs_vnode *v = _v; + struct devfs_vnode *vnode = _v; struct devfs_cookie *cookie = _cookie; - TRACE(("devfs_freecookie: entry vnode 0x%x, cookie 0x%x\n", v, cookie)); + TRACE(("devfs_freecookie: entry vnode 0x%x, cookie 0x%x\n", vnode, cookie)); - if(v->stream.type == STREAM_TYPE_DEVICE) { + if (vnode->stream.type == STREAM_TYPE_DEVICE) { // pass the call through to the underlying device - v->stream.u.dev.calls->free(cookie->u.dev.dcookie); + vnode->stream.u.dev.calls->free(cookie->u.dev.dcookie); } - if(cookie) + if (cookie) kfree(cookie); return 0; @@ -677,43 +673,32 @@ devfs_fsync(fs_cookie _fs, fs_vnode _v) static ssize_t -devfs_read(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, void *buf, off_t pos, size_t *len) +devfs_read(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, void *buffer, off_t pos, size_t *length) { struct devfs *fs = _fs; - struct devfs_vnode *v = _v; + struct devfs_vnode *vnode = _v; struct devfs_cookie *cookie = _cookie; - bool is_locked = false; - ssize_t err = 0; - - TRACE(("devfs_read: vnode 0x%x, cookie 0x%x, pos 0x%x 0x%x, len 0x%x\n", v, cookie, pos, len)); + struct devfs_part_map *part_map; - switch (cookie->s->type) { - case STREAM_TYPE_DEVICE: { - struct devfs_part_map *part_map = v->stream.u.dev.part_map; - - if (part_map) { - if( pos < 0 ) - pos = 0; + TRACE(("devfs_read: vnode 0x%x, cookie 0x%x, pos 0x%x 0x%x, len 0x%x\n", vnode, cookie, pos, len)); - if (pos > part_map->size) - return 0; + if (cookie->s->type != STREAM_TYPE_DEVICE) + return EINVAL; - *len = min(*len, part_map->size - pos ); - pos += part_map->offset; - } + part_map = vnode->stream.u.dev.part_map; + if (part_map) { + if( pos < 0 ) + pos = 0; - // pass the call through to the device - err = v->stream.u.dev.calls->read(cookie->u.dev.dcookie, pos, buf, len); - break; - } - default: - err = EINVAL; + if (pos > part_map->size) + return 0; + + *length = min(*length, part_map->size - pos ); + pos += part_map->offset; } -err: - if (is_locked) - mutex_unlock(&fs->lock); - return err; + // pass the call through to the device + return vnode->stream.u.dev.calls->read(cookie->u.dev.dcookie, pos, buffer, length); } @@ -788,6 +773,40 @@ devfs_seek(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, off_t pos, int st) } +static int +devfs_create_dir(fs_cookie _fs, fs_vnode _dir, const char *name, int perms, vnode_id *new_vnid) +{ + return EROFS; +} + + +static int +devfs_open_dir(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie) +{ + struct devfs *fs = _fs; + struct devfs_vnode *vnode = _v; + struct devfs_cookie *cookie; + + TRACE(("devfs_open: vnode 0x%x, oflags 0x%x\n", vnode, oflags)); + + if (vnode->stream.type != STREAM_TYPE_DIR) + return EINVAL; + + cookie = kmalloc(sizeof(struct devfs_cookie)); + if (cookie == NULL) + return ENOMEM; + + mutex_lock(&fs->lock); + + cookie->s = &vnode->stream; + cookie->u.dir.ptr = vnode->stream.u.dir.dir_head; + *_cookie = cookie; + + mutex_unlock(&fs->lock); + return B_OK; +} + + static int devfs_read_dir(fs_cookie _fs, fs_vnode _vnode, file_cookie _cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { @@ -944,13 +963,6 @@ static ssize_t devfs_writepage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t p } */ -static int -devfs_create(fs_cookie _fs, fs_vnode _dir, const char *name, stream_type st, void *create_args, vnode_id *new_vnid) -{ - return EROFS; -} - - static int devfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name) { @@ -994,14 +1006,12 @@ devfs_rename(fs_cookie _fs, fs_vnode _olddir, const char *oldname, fs_vnode _new static int -devfs_rstat(fs_cookie _fs, fs_vnode _v, struct stat *stat) +devfs_read_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat) { struct devfs_vnode *v = _v; TRACE(("devfs_rstat: vnode 0x%x (0x%x 0x%x), stat 0x%x\n", v, v->id, stat)); -//dprintf("devfs_rstat\n"); - stat->st_ino = v->id; stat->st_mode = DEFFILEMODE; stat->st_size = 0; @@ -1016,7 +1026,7 @@ devfs_rstat(fs_cookie _fs, fs_vnode _v, struct stat *stat) static int -devfs_wstat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask) +devfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask) { #if DEVFS_TRACE struct devfs_vnode *v = _v; @@ -1038,34 +1048,40 @@ static struct fs_calls devfs_calls = { &devfs_lookup, - &devfs_getvnode, - &devfs_putvnode, - &devfs_removevnode, + &devfs_get_vnode, + &devfs_put_vnode, + &devfs_remove_vnode, - &devfs_open, - &devfs_close, - &devfs_freecookie, + NULL, // can page (currently commented out for whatever reason...) + NULL, // read page + NULL, // write page + + /* common */ + &devfs_ioctl, &devfs_fsync, - &devfs_read, - &devfs_write, - &devfs_seek, - - &devfs_read_dir, - &devfs_rewind_dir, - - &devfs_ioctl, - - NULL, - NULL, - NULL, - - &devfs_create, &devfs_unlink, &devfs_rename, - &devfs_rstat, - &devfs_wstat, + &devfs_read_stat, + &devfs_write_stat, + + /* file */ + &devfs_create, + &devfs_open, + &devfs_close, + &devfs_free_cookie, + &devfs_read, + &devfs_write, + &devfs_seek, + + /* directory */ + &devfs_create_dir, + &devfs_open_dir, + &devfs_close, // we are using the same operations for directories + &devfs_free_cookie, // and files here - that's intended, not by accident + &devfs_read_dir, + &devfs_rewind_dir, }; diff --git a/src/kernel/core/fs/rootfs.c b/src/kernel/core/fs/rootfs.c index ca6c42f789..1319750cb2 100755 --- a/src/kernel/core/fs/rootfs.c +++ b/src/kernel/core/fs/rootfs.c @@ -351,7 +351,7 @@ err: static int -rootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r) +rootfs_get_vnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r) { struct rootfs *fs = (struct rootfs *)_fs; @@ -375,7 +375,7 @@ rootfs_getvnode(fs_cookie _fs, vnode_id id, fs_vnode *v, bool r) static int -rootfs_putvnode(fs_cookie _fs, fs_vnode _v, bool r) +rootfs_put_vnode(fs_cookie _fs, fs_vnode _v, bool r) { #if ROOTFS_TRACE struct rootfs_vnode *v = (struct rootfs_vnode *)_v; @@ -387,7 +387,7 @@ rootfs_putvnode(fs_cookie _fs, fs_vnode _v, bool r) static int -rootfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r) +rootfs_remove_vnode(fs_cookie _fs, fs_vnode _v, bool r) { struct rootfs *fs = (struct rootfs *)_fs; struct rootfs_vnode *v = (struct rootfs_vnode *)_v; @@ -407,7 +407,7 @@ rootfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r) err = 0; - if(!r) + if (!r) mutex_unlock(&fs->lock); return err; @@ -415,38 +415,17 @@ rootfs_removevnode(fs_cookie _fs, fs_vnode _v, bool r) static int -rootfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, stream_type st, int oflags) +rootfs_create(fs_cookie _fs, fs_vnode _dir, file_cookie *_cookie, vnode_id *new_vnid, const char *name, int omode, int perms) { - struct rootfs *fs = (struct rootfs *)_fs; - struct rootfs_vnode *v = (struct rootfs_vnode *)_v; - struct rootfs_cookie *cookie; - int err = 0; + return EINVAL; +} - TRACE(("rootfs_open: vnode 0x%x, stream_type %d, oflags 0x%x\n", v, st, oflags)); - if (st != STREAM_TYPE_ANY && st != STREAM_TYPE_DIR) { - err = ERR_VFS_WRONG_STREAM_TYPE; - goto err; - } - - cookie = kmalloc(sizeof(struct rootfs_cookie)); - if (cookie == NULL) { - err = ERR_NO_MEMORY; - goto err; - } - - mutex_lock(&fs->lock); - - cookie->ptr = v->stream.dir.dir_head; - cookie->oflags = oflags; - - insert_cookie_in_jar(v, cookie); - - *_cookie = cookie; - - mutex_unlock(&fs->lock); -err: - return err; +static int +rootfs_open(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie, int oflags) +{ + // allow to open the file, but it can't be done anything with it + return B_OK; } @@ -464,7 +443,7 @@ rootfs_close(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) static int -rootfs_freecookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) +rootfs_free_cookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) { struct rootfs_cookie *cookie = _cookie; #if ROOTFS_TRACE @@ -472,7 +451,7 @@ rootfs_freecookie(fs_cookie _fs, fs_vnode _v, file_cookie _cookie) TRACE(("rootfs_freecookie: entry vnode 0x%x, cookie 0x%x\n", v, cookie)); #endif - if(cookie) + if (cookie) kfree(cookie); return 0; @@ -536,6 +515,89 @@ rootfs_seek(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, off_t pos, int st) } +static int +rootfs_create_dir(fs_cookie _fs, fs_vnode _dir, const char *name, int perms, vnode_id *new_vnid) +{ + struct rootfs *fs = _fs; + struct rootfs_vnode *dir = _dir; + struct rootfs_vnode *new_vnode; + struct rootfs_stream *s; + int err = 0; + bool created_vnode = false; + + TRACE(("rootfs_create: dir 0x%x, name = '%s', stream_type = %d\n", dir, name, st)); + + mutex_lock(&fs->lock); + + new_vnode = rootfs_find_in_dir(dir, name); + if (new_vnode == NULL) { + dprintf("rootfs_create: creating new vnode\n"); + new_vnode = rootfs_create_vnode(fs); + if (new_vnode == NULL) { + err = ENOMEM; + goto err; + } + created_vnode = true; + new_vnode->name = kstrdup(name); + if (new_vnode->name == NULL) { + err = ENOMEM; + goto err1; + } + new_vnode->parent = dir; + rootfs_insert_in_dir(dir, new_vnode); + + hash_insert(fs->vnode_list_hash, new_vnode); + + s = &new_vnode->stream; + } else { + // we found the vnode + err = ERR_VFS_ALREADY_EXISTS; + goto err; + } + + new_vnode->stream.dir.dir_head = NULL; + new_vnode->stream.dir.jar_head = NULL; + + mutex_unlock(&fs->lock); + return 0; + +err1: + if (created_vnode) + rootfs_delete_vnode(fs, new_vnode, false); +err: + mutex_unlock(&fs->lock); + + return err; +} + + +static int +rootfs_open_dir(fs_cookie _fs, fs_vnode _v, file_cookie *_cookie) +{ + struct rootfs *fs = (struct rootfs *)_fs; + struct rootfs_vnode *vnode = (struct rootfs_vnode *)_v; + struct rootfs_cookie *cookie; + + TRACE(("rootfs_open: vnode 0x%x\n", vnode)); + + cookie = kmalloc(sizeof(struct rootfs_cookie)); + if (cookie == NULL) + return ENOMEM; + + mutex_lock(&fs->lock); + + cookie->ptr = vnode->stream.dir.dir_head; + //cookie->oflags = oflags; + + insert_cookie_in_jar(vnode, cookie); + *_cookie = cookie; + + mutex_unlock(&fs->lock); + + return B_OK; +} + + static int rootfs_read_dir(fs_cookie _fs, fs_vnode _vnode, file_cookie _cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { @@ -601,88 +663,28 @@ rootfs_ioctl(fs_cookie _fs, fs_vnode _v, file_cookie _cookie, ulong op, void *bu static int -rootfs_canpage(fs_cookie _fs, fs_vnode _v) +rootfs_can_page(fs_cookie _fs, fs_vnode _v) { return -1; } static ssize_t -rootfs_readpage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos) +rootfs_read_page(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos) { return EPERM; } static ssize_t -rootfs_writepage(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos) +rootfs_write_page(fs_cookie _fs, fs_vnode _v, iovecs *vecs, off_t pos) { return EPERM; } static int -rootfs_create(fs_cookie _fs, fs_vnode _dir, const char *name, stream_type st, void *create_args, vnode_id *new_vnid) -{ - struct rootfs *fs = _fs; - struct rootfs_vnode *dir = _dir; - struct rootfs_vnode *new_vnode; - struct rootfs_stream *s; - int err = 0; - bool created_vnode = false; - - TRACE(("rootfs_create: dir 0x%x, name = '%s', stream_type = %d\n", dir, name, st)); - - // we only support stream types of STREAM_TYPE_DIR - if (st != STREAM_TYPE_DIR) { - err = EPERM; - goto err; - } - - mutex_lock(&fs->lock); - - new_vnode = rootfs_find_in_dir(dir, name); - if (new_vnode == NULL) { - dprintf("rootfs_create: creating new vnode\n"); - new_vnode = rootfs_create_vnode(fs); - if(new_vnode == NULL) { - err = ENOMEM; - goto err; - } - created_vnode = true; - new_vnode->name = kstrdup(name); - if(new_vnode->name == NULL) { - err = ENOMEM; - goto err1; - } - new_vnode->parent = dir; - rootfs_insert_in_dir(dir, new_vnode); - - hash_insert(fs->vnode_list_hash, new_vnode); - - s = &new_vnode->stream; - } else { - // we found the vnode - err = ERR_VFS_ALREADY_EXISTS; - goto err; - } - - new_vnode->stream.dir.dir_head = NULL; - new_vnode->stream.dir.jar_head = NULL; - - mutex_unlock(&fs->lock); - return 0; - -err1: - if(created_vnode) - rootfs_delete_vnode(fs, new_vnode, false); -err: - mutex_unlock(&fs->lock); - - return err; -} - -static int rootfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name) +rootfs_unlink(fs_cookie _fs, fs_vnode _dir, const char *name) { struct rootfs *fs = _fs; struct rootfs_vnode *dir = _dir; @@ -788,7 +790,7 @@ err: return err; } -static int rootfs_rstat(fs_cookie _fs, fs_vnode _v, struct stat *stat) +static int rootfs_read_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat) { struct rootfs_vnode *v = _v; @@ -806,7 +808,7 @@ static int rootfs_rstat(fs_cookie _fs, fs_vnode _v, struct stat *stat) static int -rootfs_wstat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask) +rootfs_write_stat(fs_cookie _fs, fs_vnode _v, struct stat *stat, int stat_mask) { #if ROOTFS_TRACE struct rootfs *fs = _fs; @@ -829,34 +831,40 @@ static struct fs_calls rootfs_calls = { &rootfs_lookup, - &rootfs_getvnode, - &rootfs_putvnode, - &rootfs_removevnode, + &rootfs_get_vnode, + &rootfs_put_vnode, + &rootfs_remove_vnode, - &rootfs_open, - &rootfs_close, - &rootfs_freecookie, + &rootfs_can_page, + &rootfs_read_page, + &rootfs_write_page, + + /* common */ + &rootfs_ioctl, &rootfs_fsync, - &rootfs_read, - &rootfs_write, - &rootfs_seek, - - &rootfs_read_dir, - &rootfs_rewind_dir, - - &rootfs_ioctl, - - &rootfs_canpage, - &rootfs_readpage, - &rootfs_writepage, - - &rootfs_create, &rootfs_unlink, &rootfs_rename, - &rootfs_rstat, - &rootfs_wstat, + &rootfs_read_stat, + &rootfs_write_stat, + + /* file */ + &rootfs_create, + &rootfs_open, + &rootfs_close, + &rootfs_free_cookie, + &rootfs_read, + &rootfs_write, + &rootfs_seek, + + /* directory */ + &rootfs_create_dir, + &rootfs_open_dir, + &rootfs_close, // we are using the same operations for directories + &rootfs_free_cookie, // and files here - that's intended, not by accident + &rootfs_read_dir, + &rootfs_rewind_dir, }; diff --git a/src/kernel/core/fs/vfs.c b/src/kernel/core/fs/vfs.c index ff393c9340..e2d3414abc 100755 --- a/src/kernel/core/fs/vfs.c +++ b/src/kernel/core/fs/vfs.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifndef MAKE_NOIZE # define MAKE_NOIZE 0 @@ -96,31 +97,56 @@ static mutex vfs_vnode_mutex; /* function declarations */ static int vfs_mount(char *path, const char *device, const char *fs_name, void *args, bool kernel); static int vfs_unmount(char *path, bool kernel); -static int vfs_open(char *path, stream_type st, int omode, bool kernel); -static int vfs_seek(int fd, off_t pos, int seek_type, bool kernel); static ssize_t vfs_read(struct file_descriptor *, void *, off_t, size_t *); static ssize_t vfs_write(struct file_descriptor *, const void *, off_t, size_t *); static int vfs_ioctl(struct file_descriptor *, ulong, void *buf, size_t len); static status_t vfs_read_dir(struct file_descriptor *,struct dirent *buffer,size_t bufferSize,uint32 *_count); static status_t vfs_rewind_dir(struct file_descriptor *); -static int vfs_rstat(struct file_descriptor *, struct stat *); +static int vfs_read_stat(struct file_descriptor *, struct stat *); static int vfs_close(struct file_descriptor *, int, struct io_context *); -static void vfs_free_fd(struct file_descriptor *); -static int vfs_create(char *path, stream_type stream_type, void *args, bool kernel); +static int common_ioctl(struct file_descriptor *, ulong, void *buf, size_t len); +static int common_read_stat(struct file_descriptor *, struct stat *); +static int common_close(struct file_descriptor *, int, struct io_context *); -/* the vfs fd_ops structure */ -struct fd_ops vfsops = { - "vfs", - vfs_read, - vfs_write, - vfs_ioctl, - vfs_read_dir, - vfs_rewind_dir, - vfs_rstat, - vfs_close, - vfs_free_fd +static ssize_t file_read(struct file_descriptor *, void *, off_t, size_t *); +static ssize_t file_write(struct file_descriptor *, const void *, off_t, size_t *); +static int file_seek(struct file_descriptor *, off_t pos, int seek_type); +static status_t dir_read(struct file_descriptor *,struct dirent *buffer,size_t bufferSize,uint32 *_count); +static status_t dir_rewind(struct file_descriptor *); +static void file_free_fd(struct file_descriptor *); +static void dir_free_fd(struct file_descriptor *); + +static int vfs_open(char *path, int omode, bool kernel); +static int vfs_open_dir(char *path, bool kernel); +static int vfs_create(char *path, int omode, int perms, bool kernel); +static int vfs_create_dir(char *path, int perms, bool kernel); + +struct fd_ops file_ops = { + "file", + file_read, + file_write, + file_seek, + common_ioctl, + NULL, + NULL, + common_read_stat, + common_close, + file_free_fd +}; + +struct fd_ops dir_ops = { + "directory", + NULL, + NULL, + NULL, + common_ioctl, + dir_read, + dir_rewind, + common_read_stat, + common_close, + dir_free_fd }; #define VNODE_HASH_TABLE_SIZE 1024 @@ -299,9 +325,9 @@ dec_vnode_ref_count(struct vnode *v, bool free_mem, bool r) v->cache = NULL; if (v->delete_me) - v->mount->fs->calls->fs_removevnode(v->mount->cookie, v->priv_vnode, r); + FS_CALL(v,fs_remove_vnode)(v->mount->cookie, v->priv_vnode, r); else - v->mount->fs->calls->fs_putvnode(v->mount->cookie, v->priv_vnode, r); + FS_CALL(v,fs_put_vnode)(v->mount->cookie, v->priv_vnode, r); remove_vnode_from_mount_list(v, v->mount); @@ -370,14 +396,14 @@ get_vnode(fs_id fsid, vnode_id vnid, struct vnode **outv, int r) } else { // we need to create a new vnode and read it in v = create_new_vnode(); - if(!v) { + if (!v) { err = ENOMEM; goto err; } v->fsid = fsid; v->vnid = vnid; v->mount = fsid_to_mount(fsid); - if(!v->mount) { + if (!v->mount) { err = ERR_INVALID_HANDLE; goto err; } @@ -387,13 +413,13 @@ get_vnode(fs_id fsid, vnode_id vnid, struct vnode **outv, int r) add_vnode_to_mount_list(v, v->mount); - err = v->mount->fs->calls->fs_getvnode(v->mount->cookie, vnid, &v->priv_vnode, r); + err = FS_CALL(v,fs_get_vnode)(v->mount->cookie, vnid, &v->priv_vnode, r); - if(err < 0) + if (err < 0) remove_vnode_from_mount_list(v, v->mount); mutex_lock(&vfs_vnode_mutex); - if(err < 0) + if (err < 0) goto err1; v->busy = false; @@ -411,7 +437,7 @@ err1: hash_remove(vnode_table, v); err: mutex_unlock(&vfs_vnode_mutex); - if(v) + if (v) kfree(v); return err; @@ -507,12 +533,27 @@ vfs_set_cache_ptr(void *vnode, void *cache) static void -vfs_free_fd(struct file_descriptor *f) +file_free_fd(struct file_descriptor *descriptor) { - if (f->vnode) { - f->vnode->mount->fs->calls->fs_close(f->vnode->mount->cookie, f->vnode->priv_vnode, f->cookie); - f->vnode->mount->fs->calls->fs_freecookie(f->vnode->mount->cookie, f->vnode->priv_vnode, f->cookie); - dec_vnode_ref_count(f->vnode, true, false); + struct vnode *vnode = descriptor->vnode; + + if (vnode != NULL) { + FS_CALL(vnode,fs_close)(vnode->mount->cookie, vnode->priv_vnode, descriptor->cookie); + FS_CALL(vnode,fs_free_cookie)(vnode->mount->cookie, vnode->priv_vnode, descriptor->cookie); + dec_vnode_ref_count(vnode, true, false); + } +} + + +static void +dir_free_fd(struct file_descriptor *descriptor) +{ + struct vnode *vnode = descriptor->vnode; + + if (vnode != NULL) { + FS_CALL(vnode,fs_close_dir)(vnode->mount->cookie, vnode->priv_vnode, descriptor->cookie); + FS_CALL(vnode,fs_free_dir_cookie)(vnode->mount->cookie, vnode->priv_vnode, descriptor->cookie); + dec_vnode_ref_count(vnode, true, false); } } @@ -584,7 +625,7 @@ path_to_vnode(char *path, struct vnode **v, bool kernel) // dprintf("path_to_vnode: top of loop. p 0x%x, *p = %c, p = '%s'\n", p, *p, p); // done? - if(*p == '\0') { + if (*p == '\0') { err = 0; break; } @@ -673,11 +714,10 @@ path_to_dir_vnode(char *path, struct vnode **v, char *filename, bool kernel) // replace the filename portion of the path with a '.' strcpy(filename, p+1); - if(p[1] != '\0'){ + if (p[1] != '\0'){ p[1] = '.'; p[2] = '\0'; } - } return path_to_vnode(path, v, kernel); } @@ -717,7 +757,8 @@ typedef struct generic_vnode { generic_vnode; -int vnode_to_path(struct vnode *v, char *buf, int buflen) +int +vnode_to_path(struct vnode *v, char *buf, int buflen) { int rc; // return code @@ -729,12 +770,9 @@ int vnode_to_path(struct vnode *v, char *buf, int buflen) // its local vnode structure for us (returned in v->priv_vnode). // this fs vnode contains the leaf name and parent link required // - rc = v->mount-> - fs->calls-> - fs_getvnode(v->mount->cookie, v->vnid, &v->priv_vnode, true); + rc = FS_CALL(v,fs_get_vnode)(v->mount->cookie, v->vnid, &v->priv_vnode, true); if (rc < 0) return rc; - else { // // construct the full path, which is: @@ -811,18 +849,18 @@ vfs_new_io_context(void *_parent_ioctx) struct io_context *ioctx; struct io_context *parent_ioctx; - parent_ioctx = (struct io_context *)_parent_ioctx; - if (parent_ioctx) - table_size = parent_ioctx->table_size; - else - table_size = DEFAULT_FD_TABLE_SIZE; - ioctx = kmalloc(sizeof(struct io_context)); if (ioctx == NULL) return NULL; memset(ioctx, 0, sizeof(struct io_context)); + parent_ioctx = (struct io_context *)_parent_ioctx; + if (parent_ioctx) + table_size = parent_ioctx->table_size; + else + table_size = DEFAULT_FD_TABLE_SIZE; + ioctx->fds = kmalloc(sizeof(struct file_descriptor *) * table_size); if (ioctx->fds == NULL) { kfree(ioctx); @@ -845,15 +883,13 @@ vfs_new_io_context(void *_parent_ioctx) mutex_lock(&parent_ioctx->io_mutex); - ioctx->cwd= parent_ioctx->cwd; - if (ioctx->cwd) { + ioctx->cwd = parent_ioctx->cwd; + if (ioctx->cwd) inc_vnode_ref_count(ioctx->cwd); - } - - for (i = 0; i< table_size; i++) { + for (i = 0; i < table_size; i++) { if (parent_ioctx->fds[i]) { - ioctx->fds[i]= parent_ioctx->fds[i]; + ioctx->fds[i] = parent_ioctx->fds[i]; atomic_add(&ioctx->fds[i]->ref_count, 1); } } @@ -862,9 +898,8 @@ vfs_new_io_context(void *_parent_ioctx) } else { ioctx->cwd = root_vnode; - if (ioctx->cwd) { + if (ioctx->cwd) inc_vnode_ref_count(ioctx->cwd); - } } ioctx->table_size = table_size; @@ -1134,61 +1169,111 @@ vfs_sync(void) static int -vfs_open(char *path, stream_type st, int omode, bool kernel) +new_file_fd(struct vnode *vnode,file_cookie cookie, bool kernel) { + struct file_descriptor *descriptor; int fd; - struct vnode *v; - file_cookie cookie; - struct file_descriptor *f; - int err; -//dprintf("vfs_open: %s: omode = %d\n", path, omode); -#if MAKE_NOIZE - dprintf("vfs_open: entry. path = '%s', omode %d, kernel %d\n", path, omode, kernel); -#endif + descriptor = alloc_fd(); + if (!descriptor) + return ENOMEM; - err = path_to_vnode(path, &v, kernel); - if (err < 0) - goto err; + descriptor->vnode = vnode; + descriptor->cookie = cookie; + descriptor->ops = &file_ops; + descriptor->type = FDTYPE_FILE; -//dprintf("calling fs_open, v= %p\n", v); - - err = v->mount->fs->calls->fs_open(v->mount->cookie, v->priv_vnode, &cookie, st, omode); - if (err < 0) - goto err1; - - // file is opened, create a fd - f = alloc_fd(); - if (!f) { - // xxx leaks - err = ENOMEM; - goto err1; - } - f->vnode = v; - f->cookie = cookie; - f->ops = &vfsops; - f->type = FDTYPE_VNODE; - - fd = new_fd(get_current_io_context(kernel), f); - if (fd < 0) { - err = ERR_VFS_FD_TABLE_FULL; - goto err1; - } + fd = new_fd(get_current_io_context(kernel), descriptor); + if (fd < 0) + return ERR_VFS_FD_TABLE_FULL; return fd; - - /* ??? - will this ever be called??? */ - vfs_free_fd(f); -err1: - dec_vnode_ref_count(v, true, false); -err: - return err; } static int -vfs_close(struct file_descriptor *f, int fd, struct io_context *io) +vfs_create(char *path, int omode, int perms, bool kernel) { + char filename[SYS_MAX_NAME_LEN]; + struct vnode *vnode, *newVnode; + file_cookie cookie; + vnode_id newID; + int status; + + FUNCTION(("vfs_create: path '%s', kernel %d\n", path, stream_type, args, kernel)); + + status = path_to_dir_vnode(path, &vnode, filename, kernel); + if (status < 0) + return status; + + if (FS_CALL(vnode,fs_create) == NULL) { + status = EROFS; + goto err; + } + + status = FS_CALL(vnode,fs_create)(vnode->mount->cookie, vnode->priv_vnode, &cookie, &newID, filename, omode, perms); + if (status < 0) + goto err; + + status = get_vnode(vnode->mount->id,newID,&newVnode,false); + if (status < 0) + goto err1; + + status = new_file_fd(newVnode,cookie,kernel); + if (status >= 0) + return status; + +err1: + FS_CALL(vnode,fs_close)(newVnode->mount->cookie, newVnode->priv_vnode, cookie); + FS_CALL(vnode,fs_free_cookie)(newVnode->mount->cookie, newVnode->priv_vnode, cookie); + + FS_CALL(vnode,fs_unlink)(vnode->mount->cookie, vnode->priv_vnode, filename); + dec_vnode_ref_count(newVnode, true, false); + +err: + dec_vnode_ref_count(vnode, true, false); + return status; +} + + +static int +vfs_open(char *path, int omode, bool kernel) +{ + struct file_descriptor *descriptor; + struct vnode *vnode = NULL; + file_cookie cookie; + int status; + int fd; + + FUNCTION(("vfs_open: entry. path = '%s', omode %d, kernel %d\n", path, omode, kernel)); + + status = path_to_vnode(path, &vnode, kernel); + if (status < 0) + return status; + + status = FS_CALL(vnode,fs_open)(vnode->mount->cookie, vnode->priv_vnode, &cookie, omode); + if (status < 0) + goto err; + + status = new_file_fd(vnode,cookie,kernel); + if (status >= 0) + return status; + +err1: + FS_CALL(vnode,fs_close)(vnode->mount->cookie, vnode->priv_vnode, cookie); + FS_CALL(vnode,fs_free_cookie)(vnode->mount->cookie, vnode->priv_vnode, cookie); + +err: + dec_vnode_ref_count(vnode, true, false); + return status; +} + + +static int +common_close(struct file_descriptor *descriptor, int fd, struct io_context *io) +{ + // We don't call fs_close() here, because a forked team might + // have access to the same fd - just remove it from our fd array remove_fd(io, fd); return 0; @@ -1220,7 +1305,7 @@ vfs_fsync(int fd, bool kernel) static ssize_t -vfs_read(struct file_descriptor *f, void *buffer, off_t pos, size_t *length) +file_read(struct file_descriptor *f, void *buffer, off_t pos, size_t *length) { struct vnode *v = f->vnode; @@ -1231,7 +1316,7 @@ vfs_read(struct file_descriptor *f, void *buffer, off_t pos, size_t *length) static ssize_t -vfs_write(struct file_descriptor *f, const void *buffer, off_t pos, size_t *length) +file_write(struct file_descriptor *f, const void *buffer, off_t pos, size_t *length) { struct vnode *v = f->vnode; @@ -1242,34 +1327,90 @@ vfs_write(struct file_descriptor *f, const void *buffer, off_t pos, size_t *leng static int -vfs_seek(int fd, off_t pos, int seek_type, bool kernel) +file_seek(struct file_descriptor *descriptor, off_t pos, int seek_type) { - struct vnode *v; - struct file_descriptor *f; - int err; + struct vnode *vnode = descriptor->vnode; -#if MAKE_NOIZE - dprintf("vfs_seek: fd = %d, pos 0x%x 0x%x, seek_type %d, kernel %d\n", fd, pos, seek_type, kernel); -#endif + FUNCTION(("file_seek: fd = %d, pos 0x%x 0x%x, seek_type %d, kernel %d\n", fd, pos, seek_type, kernel)); - f = get_fd(get_current_io_context(kernel), fd); - if(!f) { - err = EBADF; + return FS_CALL(vnode,fs_seek)(vnode->mount->cookie, vnode->priv_vnode, descriptor->cookie, pos, seek_type); +} + + +static int +vfs_create_dir(char *path, int perms, bool kernel) +{ + char filename[SYS_MAX_NAME_LEN]; + struct vnode *vnode; + vnode_id vnid; + int status; + + FUNCTION(("vfs_create_dir: path '%s', perms %d, kernel %d\n", path, perms, kernel)); + + status = path_to_dir_vnode(path, &vnode, filename, kernel); + if (status < 0) + return status; + + if (FS_CALL(vnode,fs_create_dir)) + status = FS_CALL(vnode,fs_create_dir)(vnode->mount->cookie, vnode->priv_vnode, filename, perms, &vnid); + else + status = EROFS; + + dec_vnode_ref_count(vnode, true, false); + return status; +} + + +static int +vfs_open_dir(char *path, bool kernel) +{ + struct file_descriptor *descriptor; + struct vnode *vnode; + file_cookie cookie; + int status; + int fd; + + FUNCTION(("vfs_open_dir: entry. path = '%s', omode %d, kernel %d\n", path, omode, kernel)); + + status = path_to_vnode(path, &vnode, kernel); + if (status < 0) + return status; + + status = FS_CALL(vnode,fs_open_dir)(vnode->mount->cookie, vnode->priv_vnode, &cookie); + if (status < 0) goto err; + + // file is opened, create a fd + descriptor = alloc_fd(); + if (!descriptor) { + status = ENOMEM; + goto err1; + } + descriptor->vnode = vnode; + descriptor->cookie = cookie; + descriptor->ops = &dir_ops; + descriptor->type = FDTYPE_DIR; + + fd = new_fd(get_current_io_context(kernel), descriptor); + if (fd < 0) { + status = ERR_VFS_FD_TABLE_FULL; + goto err1; } - v = f->vnode; - err = v->mount->fs->calls->fs_seek(v->mount->cookie, v->priv_vnode, f->cookie, pos, seek_type); + return fd; - put_fd(f); +err1: + FS_CALL(vnode,fs_close_dir)(vnode->mount->cookie,vnode->priv_vnode,cookie); + FS_CALL(vnode,fs_free_dir_cookie)(vnode->mount->cookie,vnode->priv_vnode,cookie); err: - return err; + dec_vnode_ref_count(vnode, true, false); + return status; } static status_t -vfs_read_dir(struct file_descriptor *descriptor, struct dirent *buffer, size_t bufferSize, uint32 *_count) +dir_read(struct file_descriptor *descriptor, struct dirent *buffer, size_t bufferSize, uint32 *_count) { struct vnode *vnode = descriptor->vnode; @@ -1281,7 +1422,7 @@ vfs_read_dir(struct file_descriptor *descriptor, struct dirent *buffer, size_t b static status_t -vfs_rewind_dir(struct file_descriptor *descriptor) +dir_rewind(struct file_descriptor *descriptor) { struct vnode *vnode = descriptor->vnode; @@ -1293,35 +1434,14 @@ vfs_rewind_dir(struct file_descriptor *descriptor) static int -vfs_ioctl(struct file_descriptor *f, ulong op, void *buf, size_t len) +common_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer, size_t length) { - struct vnode *v = f->vnode; + struct vnode *vnode = descriptor->vnode; - FUNCTION(("vfs_ioctl: f = %p, op 0x%x, buf 0x%x, len 0x%x\n", f, op, buffer, length)); + if (FS_CALL(vnode,fs_ioctl)) + return FS_CALL(vnode,fs_ioctl)(vnode->mount->cookie,vnode->priv_vnode,descriptor->cookie,op,buffer,length); - return v->mount->fs->calls->fs_ioctl(v->mount->cookie, v->priv_vnode, f->cookie, op, buf, len); -} - - -static int -vfs_create(char *path, stream_type stream_type, void *args, bool kernel) -{ - int err; - struct vnode *v; - char filename[SYS_MAX_NAME_LEN]; - vnode_id vnid; - - FUNCTION(("vfs_create: path '%s', stream_type %d, args 0x%x, kernel %d\n", path, stream_type, args, kernel)); - - err = path_to_dir_vnode(path, &v, filename, kernel); - if(err < 0) - goto err; - - err = v->mount->fs->calls->fs_create(v->mount->cookie, v->priv_vnode, filename, stream_type, args, &vnid); - - dec_vnode_ref_count(v, true, false); -err: - return err; + return EOPNOTSUPP; } @@ -1381,37 +1501,36 @@ err: static int -vfs_rstat(struct file_descriptor *f, struct stat *stat) +common_read_stat(struct file_descriptor *descriptor, struct stat *stat) { - int err; - struct vnode *v = f->vnode; + struct vnode *vnode = descriptor->vnode; FUNCTION(("vfs_rstat: path '%s', stat 0x%x\n", path, stat)); - dprintf("vfs_rstat (%p, %p)\n", f, stat); - err = v->mount->fs->calls->fs_rstat(v->mount->cookie, v->priv_vnode, stat); - dprintf("vfs_rstat: fs_stat gave %d\n", err); - return err; + return FS_CALL(vnode,fs_read_stat)(vnode->mount->cookie, vnode->priv_vnode, stat); } static int -vfs_wstat(char *path, struct stat *stat, int stat_mask, bool kernel) +vfs_write_stat(char *path, struct stat *stat, int stat_mask, bool kernel) { - int err; - struct vnode *v; + struct vnode *vnode; + int status; FUNCTION(("vfs_wstat: path '%s', stat 0x%x, stat_mask %d, kernel %d\n", path, stat, stat_mask, kernel)); - err = path_to_vnode(path, &v, kernel); - if (err < 0) - goto err; + status = path_to_vnode(path, &vnode, kernel); + if (status < 0) + return status; - err = v->mount->fs->calls->fs_wstat(v->mount->cookie, v->priv_vnode, stat, stat_mask); + if (FS_CALL(vnode,fs_write_stat)) + status = FS_CALL(vnode,fs_write_stat)(vnode->mount->cookie, vnode->priv_vnode, stat, stat_mask); + else + status = EROFS; - dec_vnode_ref_count(v, true, false); -err: - return err; + dec_vnode_ref_count(vnode, true, false); + + return status; } @@ -1467,41 +1586,38 @@ vfs_put_vnode_ptr(void *vnode) ssize_t -vfs_canpage(void *_v) +vfs_can_page(void *_v) { - struct vnode *v = _v; + struct vnode *vnode = _v; -#if MAKE_NOIZE - dprintf("vfs_canpage: vnode 0x%x\n", v); -#endif + FUNCTION(("vfs_canpage: vnode 0x%x\n", vnode)); - return v->mount->fs->calls->fs_canpage(v->mount->cookie, v->priv_vnode); + if (FS_CALL(vnode,fs_can_page)) + return FS_CALL(vnode,fs_can_page)(vnode->mount->cookie, vnode->priv_vnode); + + return 0; } ssize_t -vfs_readpage(void *_v, iovecs *vecs, off_t pos) +vfs_read_page(void *_v, iovecs *vecs, off_t pos) { - struct vnode *v = _v; + struct vnode *vnode = _v; -#if MAKE_NOIZE - dprintf("vfs_readpage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", v, vecs, pos); -#endif + FUNCTION(("vfs_readpage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", vnode, vecs, pos)); - return v->mount->fs->calls->fs_readpage(v->mount->cookie, v->priv_vnode, vecs, pos); + return FS_CALL(vnode,fs_read_page)(vnode->mount->cookie, vnode->priv_vnode, vecs, pos); } ssize_t -vfs_writepage(void *_v, iovecs *vecs, off_t pos) +vfs_write_page(void *_v, iovecs *vecs, off_t pos) { - struct vnode *v = _v; + struct vnode *vnode = _v; -#if MAKE_NOIZE - dprintf("vfs_writepage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", v, vecs, pos); -#endif + FUNCTION(("vfs_writepage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", vnode, vecs, pos)); - return v->mount->fs->calls->fs_writepage(v->mount->cookie, v->priv_vnode, vecs, pos); + return FS_CALL(vnode,fs_write_page)(vnode->mount->cookie, vnode->priv_vnode, vecs, pos); } @@ -1510,16 +1626,13 @@ vfs_writepage(void *_v, iovecs *vecs, off_t pos) // static int -vfs_get_cwd(char* buf, size_t size, bool kernel) +vfs_get_cwd(char *buffer, size_t size, bool kernel) { // Get current working directory from io context + struct vnode *cwd = get_current_io_context(kernel)->cwd; -#if MAKE_NOIZE - dprintf("vfs_get_cwd: buf 0x%x, 0x%x\n", buf, size); -#endif + FUNCTION(("vfs_get_cwd: buf 0x%x, 0x%x\n", buffer, size)); - { - struct vnode* cwd = get_current_io_context(kernel)->cwd; if (cwd) // // vnode_to_path() takes the cwd vnode and computes @@ -1530,55 +1643,50 @@ vfs_get_cwd(char* buf, size_t size, bool kernel) // utilizes a gross hack and will be removed and/or // replaced in the future... // - return vnode_to_path(cwd, buf, size); - else - return B_ERROR; - } + return vnode_to_path(cwd, buffer, size); + + return B_ERROR; } static int -vfs_set_cwd(char* path, bool kernel) +vfs_set_cwd(char *path, bool kernel) { - struct io_context* curr_ioctx; - struct vnode* v = NULL; - struct vnode* old_cwd; + struct io_context *io; + struct vnode *vnode = NULL; + struct vnode *old_cwd; struct stat stat; int rc; -#if MAKE_NOIZE - dprintf("vfs_set_cwd: path=\'%s\'\n", path); -#endif + FUNCTION(("vfs_set_cwd: path=\'%s\'\n", path)); // Get vnode for passed path, and bail if it failed - rc = path_to_vnode(path, &v, kernel); - if (rc < 0) { + rc = path_to_vnode(path, &vnode, kernel); + if (rc < 0) + return rc; + + rc = FS_CALL(vnode,fs_read_stat)(vnode->mount->cookie, vnode->priv_vnode, &stat); + if (rc < 0) + goto err; + + if (!S_ISDIR(stat.st_mode)) { + // nope, can't cwd to here + rc = ERR_VFS_WRONG_STREAM_TYPE; goto err; } - rc = v->mount->fs->calls->fs_rstat(v->mount->cookie, v->priv_vnode, &stat); - if(rc < 0) { - goto err1; - } - - if(!S_ISDIR(stat.st_mode)) { - // nope, can't cwd to here - rc = ERR_VFS_WRONG_STREAM_TYPE; - goto err1; - } - // Get current io context and lock - curr_ioctx = get_current_io_context(kernel); - mutex_lock(&curr_ioctx->io_mutex); + io = get_current_io_context(kernel); + mutex_lock(&io->io_mutex); // save the old cwd - old_cwd = curr_ioctx->cwd; + old_cwd = io->cwd; // Set the new vnode - curr_ioctx->cwd = v; + io->cwd = vnode; // Unlock the ioctx - mutex_unlock(&curr_ioctx->io_mutex); + mutex_unlock(&io->io_mutex); // Decrease ref count of previous working dir (as the ref is being replaced) if (old_cwd) @@ -1586,9 +1694,8 @@ vfs_set_cwd(char* path, bool kernel) return B_NO_ERROR; -err1: - dec_vnode_ref_count(v, true, false); err: + dec_vnode_ref_count(vnode, true, false); return rc; } @@ -1720,14 +1827,26 @@ sys_sync(void) int -sys_open(const char *path, stream_type st, int omode) +sys_open(const char *path, int omode) { - char buf[SYS_MAX_PATH_LEN+1]; + char buffer[SYS_MAX_PATH_LEN+1]; - strncpy(buf, path, SYS_MAX_PATH_LEN); - buf[SYS_MAX_PATH_LEN] = 0; + strncpy(buffer, path, SYS_MAX_PATH_LEN); + buffer[SYS_MAX_PATH_LEN] = 0; - return vfs_open(buf, st, omode, true); + return vfs_open(buffer, omode, true); +} + + +int +sys_open_dir(const char *path) +{ + char buffer[SYS_MAX_PATH_LEN+1]; + + strncpy(buffer, path, SYS_MAX_PATH_LEN); + buffer[SYS_MAX_PATH_LEN] = 0; + + return vfs_open_dir(buffer, true); } @@ -1739,21 +1858,26 @@ sys_fsync(int fd) int -sys_seek(int fd, off_t pos, int seek_type) +sys_create(const char *path, int omode, int perms) { - return vfs_seek(fd, pos, seek_type, true); + char buffer[SYS_MAX_PATH_LEN+1]; + + strncpy(buffer, path, SYS_MAX_PATH_LEN); + buffer[SYS_MAX_PATH_LEN] = 0; + + return vfs_create(buffer, omode, perms, true); } int -sys_create(const char *path, stream_type stream_type) +sys_create_dir(const char *path, int perms) { - char buf[SYS_MAX_PATH_LEN+1]; + char buffer[SYS_MAX_PATH_LEN+1]; - strncpy(buf, path, SYS_MAX_PATH_LEN); - buf[SYS_MAX_PATH_LEN] = 0; + strncpy(buffer, path, SYS_MAX_PATH_LEN); + buffer[SYS_MAX_PATH_LEN] = 0; - return vfs_create(buf, stream_type, NULL, true); + return vfs_create_dir(buffer, perms, true); } @@ -1786,39 +1910,37 @@ sys_rename(const char *oldpath, const char *newpath) int -sys_rstat(const char *path, struct stat *stat) +sys_read_stat(const char *path, struct stat *stat) { char buf[SYS_MAX_PATH_LEN+1]; - int err; - struct vnode *v; + struct vnode *vnode; + int status; strncpy(buf, path, SYS_MAX_PATH_LEN); buf[SYS_MAX_PATH_LEN] = 0; -#if MAKE_NOIZE - dprintf("sys_rstat: path '%s', stat 0x%x,\n", path, stat); -#endif - err = path_to_vnode(buf, &v, true); - if(err < 0) - goto err; + FUNCTION(("sys_rstat: path '%s', stat 0x%x,\n", path, stat)); - err = v->mount->fs->calls->fs_rstat(v->mount->cookie, v->priv_vnode, stat); + status = path_to_vnode(buf, &vnode, true); + if (status < 0) + return status; - dec_vnode_ref_count(v, true, false); -err: - return err; + status = FS_CALL(vnode,fs_read_stat)(vnode->mount->cookie, vnode->priv_vnode, stat); + + dec_vnode_ref_count(vnode, true, false); + return status; } int -sys_wstat(const char *path, struct stat *stat, int stat_mask) +sys_write_stat(const char *path, struct stat *stat, int stat_mask) { char buf[SYS_MAX_PATH_LEN+1]; strncpy(buf, path, SYS_MAX_PATH_LEN); buf[SYS_MAX_PATH_LEN] = 0; - return vfs_wstat(buf, stat, stat_mask, true); + return vfs_write_stat(buf, stat, stat_mask, true); } @@ -1945,23 +2067,38 @@ user_sync(void) int -user_open(const char *upath, stream_type st, int omode) +user_open(const char *upath, int omode) { char path[SYS_MAX_PATH_LEN]; int rc; -dprintf("user_open\n"); - if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) return ERR_VM_BAD_USER_MEMORY; rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1); - if(rc < 0) + if (rc < 0) return rc; path[SYS_MAX_PATH_LEN-1] = 0; -dprintf("calling vfs_open(%s)\n", path); - return vfs_open(path, st, omode, false); + return vfs_open(path, omode, false); +} + + +int +user_open_dir(const char *upath) +{ + char path[SYS_MAX_PATH_LEN]; + int rc; + + if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) + return ERR_VM_BAD_USER_MEMORY; + + rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1); + if (rc < 0) + return rc; + path[SYS_MAX_PATH_LEN-1] = 0; + + return vfs_open_dir(path, false); } @@ -1973,27 +2110,38 @@ user_fsync(int fd) int -user_seek(int fd, off_t pos, int seek_type) -{ - return vfs_seek(fd, pos, seek_type, false); -} - - -int -user_create(const char *upath, stream_type stream_type) +user_create(const char *upath, int omode, int perms) { char path[SYS_MAX_PATH_LEN]; int rc; - if((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) + if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) return ERR_VM_BAD_USER_MEMORY; - rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1); - if(rc < 0) + rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN - 1); + if (rc < 0) return rc; - path[SYS_MAX_PATH_LEN-1] = 0; + path[SYS_MAX_PATH_LEN - 1] = 0; - return vfs_create(path, stream_type, NULL, false); + return vfs_create(path, omode, perms, false); +} + + +int +user_create_dir(const char *upath, int perms) +{ + char path[SYS_MAX_PATH_LEN]; + int rc; + + if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) + return ERR_VM_BAD_USER_MEMORY; + + rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN - 1); + if (rc < 0) + return rc; + path[SYS_MAX_PATH_LEN - 1] = 0; + + return vfs_create_dir(path, perms, false); } @@ -2043,63 +2191,65 @@ user_rename(const char *uoldpath, const char *unewpath) int -user_rstat(const char *upath, struct stat *ustat) +user_read_stat(const char *upath, struct stat *ustat) { char path[SYS_MAX_PATH_LEN]; + struct vnode *vnode = NULL; struct stat stat; - int rc, rc2; - struct vnode *v = NULL; + int rc; - if((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) + if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) return ERR_VM_BAD_USER_MEMORY; - if((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP) + if ((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP) return ERR_VM_BAD_USER_MEMORY; rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1); - if(rc < 0) + if (rc < 0) return rc; path[SYS_MAX_PATH_LEN-1] = 0; - rc = path_to_vnode(path, &v, false); + rc = path_to_vnode(path, &vnode, false); if (rc < 0) return rc; - - rc = v->mount->fs->calls->fs_rstat(v->mount->cookie, v->priv_vnode, &stat); - dec_vnode_ref_count(v, true, false); + if (FS_CALL(vnode,fs_read_stat)) + rc = FS_CALL(vnode,fs_read_stat)(vnode->mount->cookie, vnode->priv_vnode, &stat); + + dec_vnode_ref_count(vnode, true, false); + + if (rc < 0) + return rc; + + rc = user_memcpy(ustat, &stat, sizeof(struct stat)); - rc2 = user_memcpy(ustat, &stat, sizeof(struct stat)); - if(rc2 < 0) - return rc2; - return rc; } int -user_wstat(const char *upath, struct stat *ustat, int stat_mask) +user_write_stat(const char *upath, struct stat *ustat, int stat_mask) { char path[SYS_MAX_PATH_LEN+1]; struct stat stat; int rc; - if((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) + if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP) return ERR_VM_BAD_USER_MEMORY; - if((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP) + if ((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP) return ERR_VM_BAD_USER_MEMORY; rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN); - if(rc < 0) + if (rc < 0) return rc; path[SYS_MAX_PATH_LEN] = 0; rc = user_memcpy(&stat, ustat, sizeof(struct stat)); - if(rc < 0) + if (rc < 0) return rc; - return vfs_wstat(path, &stat, stat_mask, false); + return vfs_write_stat(path, &stat, stat_mask, false); } @@ -2284,21 +2434,21 @@ vfs_test(void) dprintf("vfs_test() entry\n"); - fd = sys_open("/", STREAM_TYPE_DIR, 0); + fd = sys_open_dir("/"); dprintf("fd = %d\n", fd); sys_close(fd); - fd = sys_open("/", STREAM_TYPE_DIR, 0); + fd = sys_open_dir("/"); dprintf("fd = %d\n", fd); - sys_create("/foo", STREAM_TYPE_DIR); - sys_create("/foo/bar", STREAM_TYPE_DIR); - sys_create("/foo/bar/gar", STREAM_TYPE_DIR); - sys_create("/foo/bar/tar", STREAM_TYPE_DIR); + sys_create_dir("/foo", 0755); + sys_create_dir("/foo/bar", 0755); + sys_create_dir("/foo/bar/gar", 0755); + sys_create_dir("/foo/bar/tar", 0755); #if 1 - fd = sys_open("/foo/bar", STREAM_TYPE_DIR, 0); - if(fd < 0) + fd = sys_open_dir("/foo/bar"); + if (fd < 0) panic("unable to open /foo/bar\n"); { @@ -2306,7 +2456,7 @@ vfs_test(void) ssize_t len; sys_seek(fd, 0, SEEK_SET); - for(;;) { + for (;;) { len = sys_read(fd, buf, -1, sizeof(buf)); // if(len <= 0) // panic("readdir returned %Ld\n", (long long)len); @@ -2321,18 +2471,18 @@ vfs_test(void) // do some unlink tests err = sys_unlink("/foo/bar"); - if(err == B_NO_ERROR) + if (err == B_NO_ERROR) panic("unlink of full directory should not have passed\n"); sys_unlink("/foo/bar/gar"); sys_unlink("/foo/bar/tar"); err = sys_unlink("/foo/bar"); - if(err != B_NO_ERROR) + if (err != B_NO_ERROR) panic("unlink of empty directory should have worked\n"); - sys_create("/test", STREAM_TYPE_DIR); - sys_create("/test", STREAM_TYPE_DIR); + sys_create_dir("/test", 0755); + sys_create_dir("/test", 0755); err = sys_mount("/test", NULL, "rootfs", NULL); - if(err < 0) + if (err < 0) panic("failed mount test\n"); #endif @@ -2428,7 +2578,7 @@ vfs_bootstrap_all_filesystems(void) bootstrap_rootfs(); err = sys_mount("/", NULL, "rootfs", NULL); - if(err < 0) + if (err < 0) panic("error mounting rootfs!\n"); sys_setcwd("/"); @@ -2436,27 +2586,28 @@ vfs_bootstrap_all_filesystems(void) // bootstrap the bootfs bootstrap_bootfs(); - sys_create("/boot", STREAM_TYPE_DIR); + sys_create_dir("/boot",0755); err = sys_mount("/boot", NULL, "bootfs", NULL); - if(err < 0) + if (err < 0) panic("error mounting bootfs\n"); // bootstrap the devfs bootstrap_devfs(); - sys_create("/dev", STREAM_TYPE_DIR); + sys_create_dir("/dev",0755); err = sys_mount("/dev", NULL, "devfs", NULL); - if(err < 0) + if (err < 0) panic("error mounting devfs\n"); - fd = sys_open("/boot/addons/fs", STREAM_TYPE_DIR, 0); + fd = sys_open_dir("/boot/addons/fs"); if (fd >= 0) { - ssize_t len; - char buf[SYS_MAX_NAME_LEN]; + char buffer[sizeof(struct dirent) + 1 + SYS_MAX_NAME_LEN]; + struct dirent *dirent = (struct dirent *)buffer; + ssize_t length; + + while ((length = sys_read_dir(fd, dirent, sizeof(buffer), 1)) > 0) + vfs_load_fs_module(dirent->d_name); - while ((len = sys_read(fd, buf, 0, sizeof(buf))) > 0) { - vfs_load_fs_module(buf); - } sys_close(fd); }