2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
5 #include <kernel/kernel.h>
6 #include <boot/stage2.h>
7 #include <kernel/vfs.h>
9 #include <kernel/vm_cache.h>
10 #include <kernel/debug.h>
11 #include <kernel/khash.h>
12 #include <kernel/lock.h>
13 #include <kernel/thread.h>
14 #include <kernel/heap.h>
15 #include <kernel/arch/cpu.h>
16 #include <kernel/elf.h>
17 #include <kernel/fs/rootfs.h>
18 #include <kernel/fs/bootfs.h>
19 #include <kernel/fs/devfs.h>
20 #include <sys/errors.h>
22 #include <kernel/fs/rootfs.h>
24 #include <libc/string.h>
25 #include <libc/printf.h>
26 #include <libc/ctype.h>
32 struct vnode
*mount_prev
;
33 struct vnode
*mount_next
;
34 struct vm_cache
*cache
;
38 struct fs_mount
*mount
;
39 struct vnode
*covered_by
;
44 struct vnode_hash_key
{
49 struct file_descriptor
{
60 struct file_descriptor
*fds
[0];
64 struct fs_container
*next
;
65 struct fs_calls
*calls
;
68 static struct fs_container
*fs_list
;
71 struct fs_mount
*next
;
72 struct fs_container
*fs
;
77 struct vnode
*root_vnode
;
78 struct vnode
*covers_vnode
;
79 struct vnode
*vnodes_head
;
80 struct vnode
*vnodes_tail
;
84 static mutex vfs_mutex
;
85 static mutex vfs_mount_mutex
;
86 static mutex vfs_mount_op_mutex
;
87 static mutex vfs_vnode_mutex
;
89 /* function declarations */
90 static int vfs_mount(char *path
, const char *fs_name
, bool kernel
);
91 static int vfs_unmount(char *path
, bool kernel
);
92 static int vfs_open(char *path
, stream_type st
, int omode
, bool kernel
);
93 static int vfs_seek(int fd
, off_t pos
, seek_type seek_type
, bool kernel
);
94 static ssize_t
vfs_read(int fd
, void *buf
, off_t pos
, ssize_t len
, bool kernel
);
95 static ssize_t
vfs_write(int fd
, const void *buf
, off_t pos
, ssize_t len
, bool kernel
);
96 static int vfs_ioctl(int fd
, int op
, void *buf
, size_t len
, bool kernel
);
97 static int vfs_close(int fd
, bool kernel
);
98 static int vfs_create(char *path
, stream_type stream_type
, void *args
, bool kernel
);
99 static int vfs_rstat(char *path
, struct file_stat
*stat
, bool kernel
);
101 #define VNODE_HASH_TABLE_SIZE 1024
102 static void *vnode_table
;
103 static struct vnode
*root_vnode
;
104 static vnode_id next_vnode_id
= 0;
106 #define MOUNTS_HASH_TABLE_SIZE 16
107 static void *mounts_table
;
108 static fs_id next_fsid
= 0;
110 static int mount_compare(void *_m
, void *_key
)
112 struct fs_mount
*mount
= _m
;
121 static unsigned int mount_hash(void *_m
, void *_key
, int range
)
123 struct fs_mount
*mount
= _m
;
127 return mount
->id
% range
;
132 static struct fs_mount
*fsid_to_mount(fs_id id
)
134 struct fs_mount
*mount
;
136 mutex_lock(&vfs_mount_mutex
);
138 mount
= hash_lookup(mounts_table
, &id
);
140 mutex_unlock(&vfs_mount_mutex
);
145 static int vnode_compare(void *_v
, void *_key
)
147 struct vnode
*v
= _v
;
148 struct vnode_hash_key
*key
= _key
;
150 if(v
->fsid
== key
->fsid
&& v
->vnid
== key
->vnid
)
156 static unsigned int vnode_hash(void *_v
, void *_key
, int range
)
158 struct vnode
*v
= _v
;
159 struct vnode_hash_key
*key
= _key
;
161 #define VHASH(fsid, vnid) (((uint32)((vnid)>>32) + (uint32)(vnid)) ^ (uint32)(fsid))
164 return (VHASH(v
->fsid
, v
->vnid
) % range
);
166 return (VHASH(key
->fsid
, key
->vnid
) % range
);
171 static int init_vnode(struct vnode
*v
)
174 v
->mount_prev
= NULL
;
175 v
->mount_next
= NULL
;
176 v
->priv_vnode
= NULL
;
181 v
->delete_me
= false;
183 v
->covered_by
= NULL
;
189 static void add_vnode_to_mount_list(struct vnode
*v
, struct fs_mount
*mount
)
191 recursive_lock_lock(&mount
->rlock
);
193 v
->mount_next
= mount
->vnodes_head
;
194 v
->mount_prev
= NULL
;
195 mount
->vnodes_head
= v
;
196 if(!mount
->vnodes_tail
)
197 mount
->vnodes_tail
= v
;
199 recursive_lock_unlock(&mount
->rlock
);
202 static void remove_vnode_from_mount_list(struct vnode
*v
, struct fs_mount
*mount
)
204 recursive_lock_lock(&mount
->rlock
);
207 v
->mount_next
->mount_prev
= v
->mount_prev
;
209 mount
->vnodes_tail
= v
->mount_prev
;
211 v
->mount_prev
->mount_next
= v
->mount_next
;
213 mount
->vnodes_head
= v
->mount_next
;
215 v
->mount_prev
= v
->mount_next
= NULL
;
217 recursive_lock_unlock(&mount
->rlock
);
220 static struct vnode
*create_new_vnode()
224 v
= (struct vnode
*)kmalloc(sizeof(struct vnode
));
232 static int dec_vnode_ref_count(struct vnode
*v
, bool free_mem
, bool r
)
236 mutex_lock(&vfs_vnode_mutex
);
239 panic("dec_vnode_ref_count called on vnode that was busy! vnode 0x%x\n", v
);
244 dprintf("dec_vnode_ref_count: vnode 0x%x, ref now %d\n", v
, v
->ref_count
);
247 if(v
->ref_count
<= 0) {
250 mutex_unlock(&vfs_vnode_mutex
);
252 /* if we have a vm_cache attached, remove it */
254 vm_cache_release_ref((vm_cache_ref
*)v
->cache
);
258 v
->mount
->fs
->calls
->fs_removevnode(v
->mount
->fscookie
, v
->priv_vnode
, r
);
260 v
->mount
->fs
->calls
->fs_putvnode(v
->mount
->fscookie
, v
->priv_vnode
, r
);
262 remove_vnode_from_mount_list(v
, v
->mount
);
264 mutex_lock(&vfs_vnode_mutex
);
265 hash_remove(vnode_table
, v
);
266 mutex_unlock(&vfs_vnode_mutex
);
272 mutex_unlock(&vfs_vnode_mutex
);
278 static int inc_vnode_ref_count(struct vnode
*v
, bool locked
)
281 mutex_lock(&vfs_vnode_mutex
);
286 dprintf("inc_vnode_ref_count: vnode 0x%x, ref now %d\n", v
, v
->ref_count
);
290 mutex_unlock(&vfs_vnode_mutex
);
294 static struct vnode
*lookup_vnode(fs_id fsid
, vnode_id vnid
)
296 struct vnode_hash_key key
;
301 return hash_lookup(vnode_table
, &key
);
304 static int get_vnode(fs_id fsid
, vnode_id vnid
, struct vnode
**outv
, int r
)
310 dprintf("get_vnode: fsid %d vnid 0x%x 0x%x\n", fsid
, vnid
);
313 mutex_lock(&vfs_vnode_mutex
);
316 v
= lookup_vnode(fsid
, vnid
);
319 mutex_unlock(&vfs_vnode_mutex
);
320 thread_snooze(10000); // 10 ms
321 mutex_lock(&vfs_vnode_mutex
);
328 dprintf("get_vnode: tried to lookup vnode, got 0x%x\n", v
);
331 inc_vnode_ref_count(v
, true);
333 // we need to create a new vnode and read it in
334 v
= create_new_vnode();
341 v
->mount
= fsid_to_mount(fsid
);
343 err
= ERR_INVALID_HANDLE
;
347 hash_insert(vnode_table
, v
);
348 mutex_unlock(&vfs_vnode_mutex
);
350 add_vnode_to_mount_list(v
, v
->mount
);
352 err
= v
->mount
->fs
->calls
->fs_getvnode(v
->mount
->fscookie
, vnid
, &v
->priv_vnode
, r
);
355 remove_vnode_from_mount_list(v
, v
->mount
);
357 mutex_lock(&vfs_vnode_mutex
);
365 mutex_unlock(&vfs_vnode_mutex
);
367 dprintf("get_vnode: returning 0x%x\n", v
);
373 hash_remove(vnode_table
, v
);
375 mutex_unlock(&vfs_vnode_mutex
);
382 static void put_vnode(struct vnode
*v
)
384 dec_vnode_ref_count(v
, true, false);
387 int vfs_get_vnode(fs_id fsid
, vnode_id vnid
, fs_vnode
*fsv
)
392 err
= get_vnode(fsid
, vnid
, &v
, true);
396 *fsv
= v
->priv_vnode
;
400 int vfs_put_vnode(fs_id fsid
, vnode_id vnid
)
404 mutex_lock(&vfs_vnode_mutex
);
406 v
= lookup_vnode(fsid
, vnid
);
408 mutex_unlock(&vfs_vnode_mutex
);
410 dec_vnode_ref_count(v
, true, true);
415 void vfs_vnode_acquire_ref(void *v
)
418 dprintf("vfs_vnode_acquire_ref: vnode 0x%x\n", v
);
420 inc_vnode_ref_count((struct vnode
*)v
, false);
423 void vfs_vnode_release_ref(void *v
)
426 dprintf("vfs_vnode_release_ref: vnode 0x%x\n", v
);
428 dec_vnode_ref_count((struct vnode
*)v
, true, false);
431 int vfs_remove_vnode(fs_id fsid
, vnode_id vnid
)
435 mutex_lock(&vfs_vnode_mutex
);
437 v
= lookup_vnode(fsid
, vnid
);
441 mutex_unlock(&vfs_vnode_mutex
);
445 void *vfs_get_cache_ptr(void *vnode
)
447 return ((struct vnode
*)vnode
)->cache
;
450 int vfs_set_cache_ptr(void *vnode
, void *cache
)
452 if(test_and_set((int *)&(((struct vnode
*)vnode
)->cache
), (int)cache
, 0) == 0)
458 static struct file_descriptor
*alloc_fd()
460 struct file_descriptor
*f
;
462 f
= kmalloc(sizeof(struct file_descriptor
));
471 static struct file_descriptor
*get_fd(struct ioctx
*ioctx
, int fd
)
473 struct file_descriptor
*f
;
475 mutex_lock(&ioctx
->io_mutex
);
477 if(fd
>= 0 && fd
< ioctx
->table_size
&& ioctx
->fds
[fd
]) {
480 atomic_add(&f
->ref_count
, 1);
485 mutex_unlock(&ioctx
->io_mutex
);
489 static void free_fd(struct file_descriptor
*f
)
491 f
->vnode
->mount
->fs
->calls
->fs_close(f
->vnode
->mount
->fscookie
, f
->vnode
->priv_vnode
, f
->cookie
);
492 f
->vnode
->mount
->fs
->calls
->fs_freecookie(f
->vnode
->mount
->fscookie
, f
->vnode
->priv_vnode
, f
->cookie
);
493 dec_vnode_ref_count(f
->vnode
, true, false);
497 static void put_fd(struct file_descriptor
*f
)
499 if(atomic_add(&f
->ref_count
, -1) == 1) {
504 static void remove_fd(struct ioctx
*ioctx
, int fd
)
506 struct file_descriptor
*f
;
508 mutex_lock(&ioctx
->io_mutex
);
510 if(fd
>= 0 && fd
< ioctx
->table_size
&& ioctx
->fds
[fd
]) {
513 ioctx
->fds
[fd
] = NULL
;
514 ioctx
->num_used_fds
--;
519 mutex_unlock(&ioctx
->io_mutex
);
525 static int new_fd(struct ioctx
*ioctx
, struct file_descriptor
*f
)
530 mutex_lock(&ioctx
->io_mutex
);
533 for(i
=0; i
<ioctx
->table_size
; i
++) {
543 ioctx
->num_used_fds
++;
546 mutex_unlock(&ioctx
->io_mutex
);
551 static struct vnode
*get_vnode_from_fd(struct ioctx
*ioctx
, int fd
)
553 struct file_descriptor
*f
;
556 f
= get_fd(ioctx
, fd
);
564 inc_vnode_ref_count(v
, false);
572 static struct fs_container
*find_fs(const char *fs_name
)
574 struct fs_container
*fs
= fs_list
;
576 if(strcmp(fs_name
, fs
->name
) == 0) {
584 static struct ioctx
*get_current_ioctx(bool kernel
)
589 ioctx
= proc_get_kernel_proc()->ioctx
;
591 ioctx
= thread_get_current_thread()->proc
->ioctx
;
596 static int path_to_vnode(char *path
, struct vnode
**v
, bool kernel
)
600 struct vnode
*curr_v
;
601 struct vnode
*next_v
;
606 return ERR_INVALID_ARGS
;
608 // figure out if we need to start at root or at cwd
613 inc_vnode_ref_count(curr_v
, false);
615 struct ioctx
*ioctx
= get_current_ioctx(kernel
);
617 mutex_lock(&ioctx
->io_mutex
);
619 inc_vnode_ref_count(curr_v
, false);
620 mutex_unlock(&ioctx
->io_mutex
);
624 // dprintf("path_to_vnode: top of loop. p 0x%x, *p = %c, p = '%s'\n", p, *p, p);
632 // walk to find the next component
633 for(next_p
= p
+1; *next_p
!= '\0' && *next_p
!= '/'; next_p
++);
639 while(*next_p
== '/');
642 // see if the .. is at the root of a mount
643 if(strcmp("..", p
) == 0 && curr_v
->mount
->root_vnode
== curr_v
) {
644 // move to the covered vnode so we pass the '..' parse to the underlying filesystem
645 if(curr_v
->mount
->covers_vnode
) {
646 next_v
= curr_v
->mount
->covers_vnode
;
647 inc_vnode_ref_count(next_v
, false);
648 dec_vnode_ref_count(curr_v
, false, false);
653 // tell the filesystem to parse this path
654 err
= curr_v
->mount
->fs
->calls
->fs_lookup(curr_v
->mount
->fscookie
, curr_v
->priv_vnode
, p
, &vnid
);
656 dec_vnode_ref_count(curr_v
, false, false);
660 // lookup the vnode, the call to fs_lookup should have caused a get_vnode to be called
661 // from inside the filesystem, thus the vnode would have to be in the list and it's
662 // ref count incremented at this point
663 mutex_lock(&vfs_vnode_mutex
);
664 next_v
= lookup_vnode(curr_v
->fsid
, vnid
);
665 mutex_unlock(&vfs_vnode_mutex
);
668 // pretty screwed up here
669 panic("path_to_vnode: could not lookup vnode (fsid 0x%x vnid 0x%x 0x%x)\n", curr_v
->fsid
, vnid
);
670 err
= ERR_VFS_PATH_NOT_FOUND
;
671 dec_vnode_ref_count(curr_v
, false, false);
675 // decrease the ref count on the old dir we just looked up into
676 dec_vnode_ref_count(curr_v
, false, false);
681 // see if we hit a mount point
682 if(curr_v
->covered_by
) {
683 next_v
= curr_v
->covered_by
;
684 inc_vnode_ref_count(next_v
, false);
685 dec_vnode_ref_count(curr_v
, false, false);
696 // returns the vnode in the next to last segment of the path, returns the last
697 // portion in filename
698 static int path_to_dir_vnode(char *path
, struct vnode
**v
, char *filename
, bool kernel
)
702 p
= strrchr(path
, '/');
704 // this path is single segment with no '/' in it
706 strcpy(filename
, path
);
709 // replace the filename portion of the path with a '.'
710 strcpy(filename
, p
+1);
714 return path_to_vnode(path
, v
, kernel
);
717 #define NEW_FD_TABLE_SIZE 32
718 void *vfs_new_ioctx()
723 ioctx
= kmalloc(sizeof(struct ioctx
) + sizeof(struct file_descriptor
) * NEW_FD_TABLE_SIZE
);
728 memset(ioctx
, 0, sizeof(struct ioctx
) + sizeof(struct file_descriptor
) * NEW_FD_TABLE_SIZE
);
730 if(mutex_init(&ioctx
->io_mutex
, "ioctx_mutex") < 0) {
735 ioctx
->cwd
= root_vnode
;
736 ioctx
->table_size
= NEW_FD_TABLE_SIZE
;
739 inc_vnode_ref_count(ioctx
->cwd
, false);
744 int vfs_free_ioctx(void *_ioctx
)
746 struct ioctx
*ioctx
= (struct ioctx
*)_ioctx
;
750 dec_vnode_ref_count(ioctx
->cwd
, true, false);
752 mutex_lock(&ioctx
->io_mutex
);
754 for(i
=0; i
<ioctx
->table_size
; i
++) {
756 put_fd(ioctx
->fds
[i
]);
760 mutex_unlock(&ioctx
->io_mutex
);
762 mutex_destroy(&ioctx
->io_mutex
);
768 int vfs_init(kernel_args
*ka
)
772 dprintf("vfs_init: entry\n");
776 vnode_table
= hash_init(VNODE_HASH_TABLE_SIZE
, (addr
)&v
->next
- (addr
)v
,
777 &vnode_compare
, &vnode_hash
);
778 if(vnode_table
== NULL
)
779 panic("vfs_init: error creating vnode hash table\n");
782 struct fs_mount
*mount
;
783 mounts_table
= hash_init(MOUNTS_HASH_TABLE_SIZE
, (addr
)&mount
->next
- (addr
)mount
,
784 &mount_compare
, &mount_hash
);
785 if(mounts_table
== NULL
)
786 panic("vfs_init: error creating mounts hash table\n");
791 if(mutex_init(&vfs_mutex
, "vfs_lock") < 0)
792 panic("vfs_init: error allocating vfs lock\n");
794 if(mutex_init(&vfs_mount_op_mutex
, "vfs_mount_op_lock") < 0)
795 panic("vfs_init: error allocating vfs_mount_op lock\n");
797 if(mutex_init(&vfs_mount_mutex
, "vfs_mount_lock") < 0)
798 panic("vfs_init: error allocating vfs_mount lock\n");
800 if(mutex_init(&vfs_vnode_mutex
, "vfs_vnode_lock") < 0)
801 panic("vfs_init: error allocating vfs_vnode lock\n");
811 dprintf("vfs_test() entry\n");
813 fd
= sys_open("/", STREAM_TYPE_DIR
, 0);
814 dprintf("fd = %d\n", fd
);
817 fd
= sys_open("/", STREAM_TYPE_DIR
, 0);
818 dprintf("fd = %d\n", fd
);
820 sys_create("/foo", STREAM_TYPE_DIR
);
821 sys_create("/foo/bar", STREAM_TYPE_DIR
);
822 sys_create("/foo/bar/gar", STREAM_TYPE_DIR
);
823 sys_create("/foo/bar/tar", STREAM_TYPE_DIR
);
826 fd
= sys_open("/foo/bar", STREAM_TYPE_DIR
, 0);
828 panic("unable to open /foo/bar\n");
834 sys_seek(fd
, 0, SEEK_SET
);
836 len
= sys_read(fd
, buf
, -1, sizeof(buf
));
838 panic("readdir returned %d\n", len
);
840 dprintf("readdir returned name = '%s'\n", buf
);
846 // do some unlink tests
847 err
= sys_unlink("/foo/bar");
849 panic("unlink of full directory should not have passed\n");
850 sys_unlink("/foo/bar/gar");
851 sys_unlink("/foo/bar/tar");
852 err
= sys_unlink("/foo/bar");
854 panic("unlink of empty directory should have worked\n");
856 sys_create("/test", STREAM_TYPE_DIR
);
857 sys_create("/test", STREAM_TYPE_DIR
);
858 err
= sys_mount("/test", "rootfs");
860 panic("failed mount test\n");
865 fd
= sys_open("/boot", STREAM_TYPE_DIR
, 0);
866 dprintf("fd = %d\n", fd
);
869 fd
= sys_open("/boot", STREAM_TYPE_DIR
, 0);
871 panic("unable to open dir /boot\n");
876 sys_seek(fd
, 0, SEEK_SET
);
878 len
= sys_read(fd
, buf
, -1, sizeof(buf
));
880 panic("readdir returned %d\n", len
);
882 dprintf("readdir returned name = '%s'\n", buf
);
889 fd
= sys_open("/boot/kernel", STREAM_TYPE_FILE
, 0);
891 panic("unable to open kernel file '/boot/kernel'\n");
896 len
= sys_read(fd
, buf
, 0, sizeof(buf
));
898 panic("failed on read\n");
899 dprintf("read returned %d\n", len
);
903 struct file_stat stat
;
905 err
= sys_rstat("/boot/kernel", &stat
);
907 panic("err stating '/boot/kernel'\n");
908 dprintf("stat results:\n");
909 dprintf("\tvnid 0x%x 0x%x\n\ttype %d\n\tsize 0x%x 0x%x\n", stat
.vnid
, stat
.type
, stat
.size
);
913 dprintf("vfs_test() done\n");
919 int vfs_register_filesystem(const char *name
, struct fs_calls
*calls
)
921 struct fs_container
*container
;
923 container
= (struct fs_container
*)kmalloc(sizeof(struct fs_container
));
924 if(container
== NULL
)
925 return ERR_NO_MEMORY
;
927 container
->name
= name
;
928 container
->calls
= calls
;
930 mutex_lock(&vfs_mutex
);
932 container
->next
= fs_list
;
935 mutex_unlock(&vfs_mutex
);
939 static int vfs_mount(char *path
, const char *fs_name
, bool kernel
)
941 struct fs_mount
*mount
;
943 struct vnode
*covered_vnode
= NULL
;
947 dprintf("vfs_mount: entry. path = '%s', fs_name = '%s'\n", path
, fs_name
);
950 mutex_lock(&vfs_mount_op_mutex
);
952 mount
= (struct fs_mount
*)kmalloc(sizeof(struct fs_mount
));
958 mount
->mount_point
= (char *)kmalloc(strlen(path
)+1);
959 if(mount
->mount_point
== NULL
) {
963 strcpy(mount
->mount_point
, path
);
965 mount
->fs
= find_fs(fs_name
);
966 if(mount
->fs
== NULL
) {
967 err
= ERR_VFS_INVALID_FS
;
971 recursive_lock_create(&mount
->rlock
);
972 mount
->id
= next_fsid
++;
973 mount
->unmounting
= false;
976 // we haven't mounted anything yet
977 if(strcmp(path
, "/") != 0) {
978 err
= ERR_VFS_GENERAL
;
982 err
= mount
->fs
->calls
->fs_mount(&mount
->fscookie
, mount
->id
, NULL
, &root_id
);
984 err
= ERR_VFS_GENERAL
;
988 mount
->covers_vnode
= NULL
; // this is the root mount
994 err
= path_to_vnode(path
,&covered_vnode
,kernel
);
1000 err
= ERR_VFS_GENERAL
;
1004 // XXX insert check to make sure covered_vnode is a DIR, or maybe it's okay for it not to be
1006 if((covered_vnode
!= root_vnode
) && (covered_vnode
->mount
->root_vnode
== covered_vnode
)){
1007 err
= ERR_VFS_ALREADY_MOUNTPOINT
;
1011 mount
->covers_vnode
= covered_vnode
;
1014 err
= mount
->fs
->calls
->fs_mount(&mount
->fscookie
, mount
->id
, NULL
, &root_id
);
1019 mutex_lock(&vfs_mount_mutex
);
1021 // insert mount struct into list
1022 hash_insert(mounts_table
, mount
);
1024 mutex_unlock(&vfs_mount_mutex
);
1026 err
= get_vnode(mount
->id
, root_id
, &mount
->root_vnode
, 0);
1030 // XXX may be a race here
1031 if(mount
->covers_vnode
)
1032 mount
->covers_vnode
->covered_by
= mount
->root_vnode
;
1035 root_vnode
= mount
->root_vnode
;
1037 mutex_unlock(&vfs_mount_op_mutex
);
1042 mount
->fs
->calls
->fs_unmount(mount
->fscookie
);
1044 if(mount
->covers_vnode
)
1045 dec_vnode_ref_count(mount
->covers_vnode
, true, false);
1047 recursive_lock_destroy(&mount
->rlock
);
1049 kfree(mount
->mount_point
);
1053 mutex_unlock(&vfs_mount_op_mutex
);
1058 static int vfs_unmount(char *path
, bool kernel
)
1061 struct fs_mount
*mount
;
1065 dprintf("vfs_unmount: entry. path = '%s', kernel %d\n", path
, kernel
);
1068 err
= path_to_vnode(path
, &v
, kernel
);
1070 err
= ERR_VFS_PATH_NOT_FOUND
;
1074 mutex_lock(&vfs_mount_op_mutex
);
1076 mount
= fsid_to_mount(v
->fsid
);
1078 panic("vfs_unmount: fsid_to_mount failed on root vnode @0x%x of mount\n", v
);
1081 if(mount
->root_vnode
!= v
) {
1083 dec_vnode_ref_count(v
, true, false);
1084 err
= ERR_VFS_NOT_MOUNTPOINT
;
1088 /* grab the vnode master mutex to keep someone from creating a vnode
1089 while we're figuring out if we can continue */
1090 mutex_lock(&vfs_vnode_mutex
);
1092 /* simulate the root vnode having it's refcount decremented */
1093 mount
->root_vnode
->ref_count
-= 2;
1095 /* cycle through the list of vnodes associated with this mount and
1096 make sure all of them are not busy or have refs on them */
1098 for(v
= mount
->vnodes_head
; v
; v
= v
->mount_next
) {
1099 if(v
->busy
|| v
->ref_count
!= 0) {
1100 mount
->root_vnode
->ref_count
+= 2;
1101 mutex_unlock(&vfs_vnode_mutex
);
1102 dec_vnode_ref_count(mount
->root_vnode
, true, false);
1103 err
= ERR_VFS_FS_BUSY
;
1108 /* we can safely continue, mark all of the vnodes busy and this mount
1109 structure in unmounting state */
1110 for(v
= mount
->vnodes_head
; v
; v
= v
->mount_next
)
1111 if(v
!= mount
->root_vnode
)
1113 mount
->unmounting
= true;
1115 mutex_unlock(&vfs_vnode_mutex
);
1117 mount
->covers_vnode
->covered_by
= NULL
;
1118 dec_vnode_ref_count(mount
->covers_vnode
, true, false);
1120 /* release the ref on the root vnode twice */
1121 dec_vnode_ref_count(mount
->root_vnode
, true, false);
1122 dec_vnode_ref_count(mount
->root_vnode
, true, false);
1124 // XXX when full vnode cache in place, will need to force
1125 // a putvnode/removevnode here
1127 /* remove the mount structure from the hash table */
1128 mutex_lock(&vfs_mount_mutex
);
1129 hash_remove(mounts_table
, mount
);
1130 mutex_unlock(&vfs_mount_mutex
);
1132 mutex_unlock(&vfs_mount_op_mutex
);
1134 mount
->fs
->calls
->fs_unmount(mount
->fscookie
);
1136 kfree(mount
->mount_point
);
1142 mutex_unlock(&vfs_mount_op_mutex
);
1147 static int vfs_sync()
1149 struct hash_iterator iter
;
1150 struct fs_mount
*mount
;
1153 dprintf("vfs_sync: entry.\n");
1156 /* cycle through and call sync on each mounted fs */
1157 mutex_lock(&vfs_mount_op_mutex
);
1158 mutex_lock(&vfs_mount_mutex
);
1160 hash_open(mounts_table
, &iter
);
1161 while((mount
= hash_next(mounts_table
, &iter
))) {
1162 mount
->fs
->calls
->fs_sync(mount
->fscookie
);
1164 hash_close(mounts_table
, &iter
, false);
1166 mutex_unlock(&vfs_mount_mutex
);
1167 mutex_unlock(&vfs_mount_op_mutex
);
1172 static int vfs_open(char *path
, stream_type st
, int omode
, bool kernel
)
1177 struct file_descriptor
*f
;
1181 dprintf("vfs_open: entry. path = '%s', omode %d, kernel %d\n", path
, omode
, kernel
);
1184 err
= path_to_vnode(path
, &v
, kernel
);
1188 err
= v
->mount
->fs
->calls
->fs_open(v
->mount
->fscookie
, v
->priv_vnode
, &cookie
, st
, omode
);
1192 // file is opened, create a fd
1196 err
= ERR_NO_MEMORY
;
1202 fd
= new_fd(get_current_ioctx(kernel
), f
);
1204 err
= ERR_VFS_FD_TABLE_FULL
;
1213 dec_vnode_ref_count(v
, true, false);
1218 static int vfs_close(int fd
, bool kernel
)
1220 struct file_descriptor
*f
;
1221 struct ioctx
*ioctx
;
1224 dprintf("vfs_close: entry. fd %d, kernel %d\n", fd
, kernel
);
1227 ioctx
= get_current_ioctx(kernel
);
1229 f
= get_fd(ioctx
, fd
);
1231 return ERR_INVALID_HANDLE
;
1233 remove_fd(ioctx
, fd
);
1239 static int vfs_fsync(int fd
, bool kernel
)
1241 struct file_descriptor
*f
;
1246 dprintf("vfs_fsync: entry. fd %d kernel %d\n", fd
, kernel
);
1249 f
= get_fd(get_current_ioctx(kernel
), fd
);
1251 return ERR_INVALID_HANDLE
;
1254 err
= v
->mount
->fs
->calls
->fs_fsync(v
->mount
->fscookie
, v
->priv_vnode
);
1261 static ssize_t
vfs_read(int fd
, void *buf
, off_t pos
, ssize_t len
, bool kernel
)
1264 struct file_descriptor
*f
;
1268 dprintf("vfs_read: fd = %d, buf 0x%x, pos 0x%x 0x%x, len 0x%x, kernel %d\n", fd
, buf
, pos
, len
, kernel
);
1271 f
= get_fd(get_current_ioctx(kernel
), fd
);
1273 err
= ERR_INVALID_HANDLE
;
1278 err
= v
->mount
->fs
->calls
->fs_read(v
->mount
->fscookie
, v
->priv_vnode
, f
->cookie
, buf
, pos
, len
);
1286 static ssize_t
vfs_write(int fd
, const void *buf
, off_t pos
, ssize_t len
, bool kernel
)
1289 struct file_descriptor
*f
;
1293 dprintf("vfs_write: fd = %d, buf 0x%x, pos 0x%x 0x%x, len 0x%x, kernel %d\n", fd
, buf
, pos
, len
, kernel
);
1296 f
= get_fd(get_current_ioctx(kernel
), fd
);
1298 err
= ERR_INVALID_HANDLE
;
1303 err
= v
->mount
->fs
->calls
->fs_write(v
->mount
->fscookie
, v
->priv_vnode
, f
->cookie
, buf
, pos
, len
);
1311 static int vfs_seek(int fd
, off_t pos
, seek_type seek_type
, bool kernel
)
1314 struct file_descriptor
*f
;
1318 dprintf("vfs_seek: fd = %d, pos 0x%x 0x%x, seek_type %d, kernel %d\n", fd
, pos
, seek_type
, kernel
);
1321 f
= get_fd(get_current_ioctx(kernel
), fd
);
1323 err
= ERR_INVALID_HANDLE
;
1328 err
= v
->mount
->fs
->calls
->fs_seek(v
->mount
->fscookie
, v
->priv_vnode
, f
->cookie
, pos
, seek_type
);
1337 static int vfs_ioctl(int fd
, int op
, void *buf
, size_t len
, bool kernel
)
1340 struct file_descriptor
*f
;
1344 dprintf("vfs_ioctl: fd = %d, op 0x%x, buf 0x%x, len 0x%x, kernel %d\n", fd
, op
, buf
, len
, kernel
);
1347 f
= get_fd(get_current_ioctx(kernel
), fd
);
1349 err
= ERR_INVALID_HANDLE
;
1354 err
= v
->mount
->fs
->calls
->fs_ioctl(v
->mount
->fscookie
, v
->priv_vnode
, f
->cookie
, op
, buf
, len
);
1362 static int vfs_create(char *path
, stream_type stream_type
, void *args
, bool kernel
)
1366 char filename
[SYS_MAX_NAME_LEN
];
1370 dprintf("vfs_create: path '%s', stream_type %d, args 0x%x, kernel %d\n", path
, stream_type
, args
, kernel
);
1373 err
= path_to_dir_vnode(path
, &v
, filename
, kernel
);
1377 err
= v
->mount
->fs
->calls
->fs_create(v
->mount
->fscookie
, v
->priv_vnode
, filename
, stream_type
, args
, &vnid
);
1380 dec_vnode_ref_count(v
, true, false);
1385 static int vfs_unlink(char *path
, bool kernel
)
1389 char filename
[SYS_MAX_NAME_LEN
];
1392 dprintf("vfs_unlink: path '%s', kernel %d\n", path
, kernel
);
1395 err
= path_to_dir_vnode(path
, &v
, filename
, kernel
);
1399 err
= v
->mount
->fs
->calls
->fs_unlink(v
->mount
->fscookie
, v
->priv_vnode
, filename
);
1402 dec_vnode_ref_count(v
, true, false);
1407 static int vfs_rename(char *path
, char *newpath
, bool kernel
)
1409 struct vnode
*v1
, *v2
;
1410 char filename1
[SYS_MAX_NAME_LEN
];
1411 char filename2
[SYS_MAX_NAME_LEN
];
1414 err
= path_to_dir_vnode(path
, &v1
, filename1
, kernel
);
1418 err
= path_to_dir_vnode(path
, &v2
, filename2
, kernel
);
1422 if(v1
->fsid
!= v2
->fsid
) {
1423 err
= ERR_VFS_CROSS_FS_RENAME
;
1427 err
= v1
->mount
->fs
->calls
->fs_rename(v1
->mount
->fscookie
, v1
->priv_vnode
, filename1
, v2
->priv_vnode
, filename2
);
1430 dec_vnode_ref_count(v2
, true, false);
1432 dec_vnode_ref_count(v1
, true, false);
1437 static int vfs_rstat(char *path
, struct file_stat
*stat
, bool kernel
)
1443 dprintf("vfs_rstat: path '%s', stat 0x%x, kernel %d\n", path
, stat
, kernel
);
1446 err
= path_to_vnode(path
, &v
, kernel
);
1450 err
= v
->mount
->fs
->calls
->fs_rstat(v
->mount
->fscookie
, v
->priv_vnode
, stat
);
1453 dec_vnode_ref_count(v
, true, false);
1458 static int vfs_wstat(char *path
, struct file_stat
*stat
, int stat_mask
, bool kernel
)
1464 dprintf("vfs_wstat: path '%s', stat 0x%x, stat_mask %d, kernel %d\n", path
, stat
, stat_mask
, kernel
);
1467 err
= path_to_vnode(path
, &v
, kernel
);
1471 err
= v
->mount
->fs
->calls
->fs_wstat(v
->mount
->fscookie
, v
->priv_vnode
, stat
, stat_mask
);
1474 dec_vnode_ref_count(v
, true, false);
1479 int vfs_get_vnode_from_fd(int fd
, bool kernel
, void **vnode
)
1481 struct ioctx
*ioctx
;
1484 ioctx
= get_current_ioctx(kernel
);
1485 *vnode
= get_vnode_from_fd(ioctx
, fd
);
1488 return ERR_INVALID_HANDLE
;
1493 int vfs_get_vnode_from_path(const char *path
, bool kernel
, void **vnode
)
1497 char buf
[SYS_MAX_PATH_LEN
+1];
1500 dprintf("vfs_get_vnode_from_path: entry. path = '%s', kernel %d\n", path
, kernel
);
1503 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1504 buf
[SYS_MAX_PATH_LEN
] = 0;
1506 err
= path_to_vnode(buf
, &v
, kernel
);
1516 int vfs_put_vnode_ptr(void *vnode
)
1518 struct vnode
*v
= vnode
;
1525 ssize_t
vfs_canpage(void *_v
)
1527 struct vnode
*v
= _v
;
1530 dprintf("vfs_canpage: vnode 0x%x\n", v
);
1533 return v
->mount
->fs
->calls
->fs_canpage(v
->mount
->fscookie
, v
->priv_vnode
);
1536 ssize_t
vfs_readpage(void *_v
, iovecs
*vecs
, off_t pos
)
1538 struct vnode
*v
= _v
;
1541 dprintf("vfs_readpage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", v
, vecs
, pos
);
1544 return v
->mount
->fs
->calls
->fs_readpage(v
->mount
->fscookie
, v
->priv_vnode
, vecs
, pos
);
1547 ssize_t
vfs_writepage(void *_v
, iovecs
*vecs
, off_t pos
)
1549 struct vnode
*v
= _v
;
1552 dprintf("vfs_writepage: vnode 0x%x, vecs 0x%x, pos 0x%x 0x%x\n", v
, vecs
, pos
);
1555 return v
->mount
->fs
->calls
->fs_writepage(v
->mount
->fscookie
, v
->priv_vnode
, vecs
, pos
);
1558 int vfs_get_cwd(char* buf
, size_t size
, bool kernel
)
1560 // Get current working directory from io context
1561 struct vnode
* v
= get_current_ioctx(kernel
)->cwd
;
1565 dprintf("vfs_get_cwd: buf 0x%x, 0x%x\n", buf
, size
);
1567 //TODO: parse cwd back into a full path
1574 rc
= ERR_VFS_INSUFFICIENT_BUF
;
1577 // Tell caller all is ok
1581 int vfs_set_cwd(char* path
, bool kernel
)
1583 struct ioctx
* curr_ioctx
;
1584 struct vnode
* v
= NULL
;
1585 struct vnode
* old_cwd
;
1586 struct file_stat stat
;
1590 dprintf("vfs_set_cwd: path=\'%s\'\n", path
);
1593 // Get vnode for passed path, and bail if it failed
1594 rc
= path_to_vnode(path
, &v
, kernel
);
1599 rc
= v
->mount
->fs
->calls
->fs_rstat(v
->mount
->fscookie
, v
->priv_vnode
, &stat
);
1604 if(stat
.type
!= STREAM_TYPE_DIR
) {
1605 // nope, can't cwd to here
1606 rc
= ERR_VFS_WRONG_STREAM_TYPE
;
1610 // Get current io context and lock
1611 curr_ioctx
= get_current_ioctx(kernel
);
1612 mutex_lock(&curr_ioctx
->io_mutex
);
1615 old_cwd
= curr_ioctx
->cwd
;
1617 // Set the new vnode
1618 curr_ioctx
->cwd
= v
;
1621 mutex_unlock(&curr_ioctx
->io_mutex
);
1623 // Decrease ref count of previous working dir (as the ref is being replaced)
1625 dec_vnode_ref_count(old_cwd
, true, false);
1630 dec_vnode_ref_count(v
, true, false);
1635 int sys_mount(const char *path
, const char *fs_name
)
1637 char buf
[SYS_MAX_PATH_LEN
+1];
1639 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1640 buf
[SYS_MAX_PATH_LEN
] = 0;
1642 return vfs_mount(buf
, fs_name
, true);
1645 int sys_unmount(const char *path
)
1647 char buf
[SYS_MAX_PATH_LEN
+1];
1649 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1650 buf
[SYS_MAX_PATH_LEN
] = 0;
1652 return vfs_unmount(buf
, true);
1660 int sys_open(const char *path
, stream_type st
, int omode
)
1662 char buf
[SYS_MAX_PATH_LEN
+1];
1664 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1665 buf
[SYS_MAX_PATH_LEN
] = 0;
1667 return vfs_open(buf
, st
, omode
, true);
1670 int sys_close(int fd
)
1672 return vfs_close(fd
, true);
1675 int sys_fsync(int fd
)
1677 return vfs_fsync(fd
, true);
1680 ssize_t
sys_read(int fd
, void *buf
, off_t pos
, ssize_t len
)
1682 return vfs_read(fd
, buf
, pos
, len
, true);
1685 ssize_t
sys_write(int fd
, const void *buf
, off_t pos
, ssize_t len
)
1687 return vfs_write(fd
, buf
, pos
, len
, true);
1690 int sys_seek(int fd
, off_t pos
, seek_type seek_type
)
1692 return vfs_seek(fd
, pos
, seek_type
, true);
1695 int sys_ioctl(int fd
, int op
, void *buf
, size_t len
)
1697 return vfs_ioctl(fd
, op
, buf
, len
, true);
1700 int sys_create(const char *path
, stream_type stream_type
)
1702 char buf
[SYS_MAX_PATH_LEN
+1];
1704 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1705 buf
[SYS_MAX_PATH_LEN
] = 0;
1707 return vfs_create(buf
, stream_type
, NULL
, true);
1710 int sys_unlink(const char *path
)
1712 char buf
[SYS_MAX_PATH_LEN
+1];
1714 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1715 buf
[SYS_MAX_PATH_LEN
] = 0;
1717 return vfs_unlink(buf
, true);
1720 int sys_rename(const char *oldpath
, const char *newpath
)
1722 char buf1
[SYS_MAX_PATH_LEN
+1];
1723 char buf2
[SYS_MAX_PATH_LEN
+1];
1725 strncpy(buf1
, oldpath
, SYS_MAX_PATH_LEN
);
1726 buf1
[SYS_MAX_PATH_LEN
] = 0;
1728 strncpy(buf2
, newpath
, SYS_MAX_PATH_LEN
);
1729 buf2
[SYS_MAX_PATH_LEN
] = 0;
1731 return vfs_rename(buf1
, buf2
, true);
1734 int sys_rstat(const char *path
, struct file_stat
*stat
)
1736 char buf
[SYS_MAX_PATH_LEN
+1];
1738 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1739 buf
[SYS_MAX_PATH_LEN
] = 0;
1741 return vfs_rstat(buf
, stat
, true);
1744 int sys_wstat(const char *path
, struct file_stat
*stat
, int stat_mask
)
1746 char buf
[SYS_MAX_PATH_LEN
+1];
1748 strncpy(buf
, path
, SYS_MAX_PATH_LEN
);
1749 buf
[SYS_MAX_PATH_LEN
] = 0;
1751 return vfs_wstat(buf
, stat
, stat_mask
, true);
1754 char* sys_getcwd(char *buf
, size_t size
)
1756 char path
[SYS_MAX_PATH_LEN
];
1760 dprintf("sys_getcwd: buf 0x%x, 0x%x\n", buf
, size
);
1763 // Call vfs to get current working directory
1764 rc
= vfs_get_cwd(path
,SYS_MAX_PATH_LEN
-1,true);
1765 path
[SYS_MAX_PATH_LEN
-1] = 0;
1767 // Copy back the result
1768 strncpy(buf
,path
,size
);
1770 // Return either NULL or the buffer address to indicate failure or success
1771 return (rc
< 0) ? NULL
: buf
;
1774 int sys_setcwd(const char* _path
)
1776 char path
[SYS_MAX_PATH_LEN
];
1779 dprintf("sys_setcwd: path=0x%x\n", _path
);
1782 // Copy new path to kernel space
1783 strncpy(path
, _path
, SYS_MAX_PATH_LEN
-1);
1784 path
[SYS_MAX_PATH_LEN
-1] = 0;
1786 // Call vfs to set new working directory
1787 return vfs_set_cwd(path
,true);
1790 int user_mount(const char *upath
, const char *ufs_name
)
1792 char path
[SYS_MAX_PATH_LEN
+1];
1793 char fs_name
[SYS_MAX_OS_NAME_LEN
+1];
1796 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
1797 return ERR_VM_BAD_USER_MEMORY
;
1799 if((addr
)ufs_name
>= KERNEL_BASE
&& (addr
)ufs_name
<= KERNEL_TOP
)
1800 return ERR_VM_BAD_USER_MEMORY
;
1802 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
);
1805 path
[SYS_MAX_PATH_LEN
] = 0;
1807 rc
= user_strncpy(fs_name
, ufs_name
, SYS_MAX_PATH_LEN
);
1810 fs_name
[SYS_MAX_PATH_LEN
] = 0;
1812 return vfs_mount(path
, fs_name
, false);
1815 int user_unmount(const char *upath
)
1817 char path
[SYS_MAX_PATH_LEN
+1];
1820 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
);
1823 path
[SYS_MAX_PATH_LEN
] = 0;
1825 return vfs_unmount(path
, false);
1833 int user_open(const char *upath
, stream_type st
, int omode
)
1835 char path
[SYS_MAX_PATH_LEN
];
1838 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
1839 return ERR_VM_BAD_USER_MEMORY
;
1841 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
-1);
1844 path
[SYS_MAX_PATH_LEN
-1] = 0;
1846 return vfs_open(path
, st
, omode
, false);
1849 int user_close(int fd
)
1851 return vfs_close(fd
, false);
1854 int user_fsync(int fd
)
1856 return vfs_fsync(fd
, false);
1859 ssize_t
user_read(int fd
, void *buf
, off_t pos
, ssize_t len
)
1861 if((addr
)buf
>= KERNEL_BASE
&& (addr
)buf
<= KERNEL_TOP
)
1862 return ERR_VM_BAD_USER_MEMORY
;
1864 return vfs_read(fd
, buf
, pos
, len
, false);
1867 ssize_t
user_write(int fd
, const void *buf
, off_t pos
, ssize_t len
)
1869 if((addr
)buf
>= KERNEL_BASE
&& (addr
)buf
<= KERNEL_TOP
)
1870 return ERR_VM_BAD_USER_MEMORY
;
1872 return vfs_write(fd
, buf
, pos
, len
, false);
1875 int user_seek(int fd
, off_t pos
, seek_type seek_type
)
1877 return vfs_seek(fd
, pos
, seek_type
, false);
1880 int user_ioctl(int fd
, int op
, void *buf
, size_t len
)
1882 if((addr
)buf
>= KERNEL_BASE
&& (addr
)buf
<= KERNEL_TOP
)
1883 return ERR_VM_BAD_USER_MEMORY
;
1884 return vfs_ioctl(fd
, op
, buf
, len
, false);
1887 int user_create(const char *upath
, stream_type stream_type
)
1889 char path
[SYS_MAX_PATH_LEN
];
1892 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
1893 return ERR_VM_BAD_USER_MEMORY
;
1895 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
-1);
1898 path
[SYS_MAX_PATH_LEN
-1] = 0;
1900 return vfs_create(path
, stream_type
, NULL
, false);
1903 int user_unlink(const char *upath
)
1905 char path
[SYS_MAX_PATH_LEN
+1];
1908 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
1909 return ERR_VM_BAD_USER_MEMORY
;
1911 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
);
1914 path
[SYS_MAX_PATH_LEN
] = 0;
1916 return vfs_unlink(path
, false);
1919 int user_rename(const char *uoldpath
, const char *unewpath
)
1921 char oldpath
[SYS_MAX_PATH_LEN
+1];
1922 char newpath
[SYS_MAX_PATH_LEN
+1];
1925 if((addr
)uoldpath
>= KERNEL_BASE
&& (addr
)uoldpath
<= KERNEL_TOP
)
1926 return ERR_VM_BAD_USER_MEMORY
;
1928 if((addr
)unewpath
>= KERNEL_BASE
&& (addr
)unewpath
<= KERNEL_TOP
)
1929 return ERR_VM_BAD_USER_MEMORY
;
1931 rc
= user_strncpy(oldpath
, uoldpath
, SYS_MAX_PATH_LEN
);
1934 oldpath
[SYS_MAX_PATH_LEN
] = 0;
1936 rc
= user_strncpy(newpath
, unewpath
, SYS_MAX_PATH_LEN
);
1939 newpath
[SYS_MAX_PATH_LEN
] = 0;
1941 return vfs_rename(oldpath
, newpath
, false);
1944 int user_rstat(const char *upath
, struct file_stat
*ustat
)
1946 char path
[SYS_MAX_PATH_LEN
];
1947 struct file_stat stat
;
1950 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
1951 return ERR_VM_BAD_USER_MEMORY
;
1953 if((addr
)ustat
>= KERNEL_BASE
&& (addr
)ustat
<= KERNEL_TOP
)
1954 return ERR_VM_BAD_USER_MEMORY
;
1956 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
-1);
1959 path
[SYS_MAX_PATH_LEN
-1] = 0;
1961 rc
= vfs_rstat(path
, &stat
, false);
1965 rc2
= user_memcpy(ustat
, &stat
, sizeof(struct file_stat
));
1972 int user_wstat(const char *upath
, struct file_stat
*ustat
, int stat_mask
)
1974 char path
[SYS_MAX_PATH_LEN
+1];
1975 struct file_stat stat
;
1978 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
1979 return ERR_VM_BAD_USER_MEMORY
;
1981 if((addr
)ustat
>= KERNEL_BASE
&& (addr
)ustat
<= KERNEL_TOP
)
1982 return ERR_VM_BAD_USER_MEMORY
;
1984 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
);
1987 path
[SYS_MAX_PATH_LEN
] = 0;
1989 rc
= user_memcpy(&stat
, ustat
, sizeof(struct file_stat
));
1993 return vfs_wstat(path
, &stat
, stat_mask
, false);
1996 int user_getcwd(char *buf
, size_t size
)
1998 char path
[SYS_MAX_PATH_LEN
];
2002 dprintf("user_getcwd: buf 0x%x, 0x%x\n", buf
, size
);
2005 // Check if userspace address is inside "shared" kernel space
2006 if((addr
)buf
>= KERNEL_BASE
&& (addr
)buf
<= KERNEL_TOP
)
2007 return NULL
; //ERR_VM_BAD_USER_MEMORY;
2009 // Call vfs to get current working directory
2010 rc
= vfs_get_cwd(path
, SYS_MAX_PATH_LEN
-1, false);
2014 // Copy back the result
2015 rc2
= user_strncpy(buf
, path
, size
);
2022 int user_setcwd(const char* upath
)
2024 char path
[SYS_MAX_PATH_LEN
];
2028 dprintf("user_setcwd: path=0x%x\n", upath
);
2031 // Check if userspace address is inside "shared" kernel space
2032 if((addr
)upath
>= KERNEL_BASE
&& (addr
)upath
<= KERNEL_TOP
)
2033 return ERR_VM_BAD_USER_MEMORY
;
2035 // Copy new path to kernel space
2036 rc
= user_strncpy(path
, upath
, SYS_MAX_PATH_LEN
-1);
2040 path
[SYS_MAX_PATH_LEN
-1] = 0;
2042 // Call vfs to set new working directory
2043 return vfs_set_cwd(path
,false);
2046 image_id
vfs_load_fs_module(const char *name
)
2049 void (*bootstrap
)();
2050 char path
[SYS_MAX_PATH_LEN
];
2052 sprintf(path
, "/boot/addons/fs/%s", name
);
2054 id
= elf_load_kspace(path
, "");
2058 bootstrap
= (void *)elf_lookup_symbol(id
, "fs_bootstrap");
2060 return ERR_VFS_INVALID_FS
;
2067 int vfs_bootstrap_all_filesystems()
2072 // bootstrap the root filesystem
2075 err
= sys_mount("/", "rootfs");
2077 panic("error mounting rootfs!\n");
2081 // bootstrap the bootfs
2084 sys_create("/boot", STREAM_TYPE_DIR
);
2085 err
= sys_mount("/boot", "bootfs");
2087 panic("error mounting bootfs\n");
2089 // bootstrap the devfs
2092 sys_create("/dev", STREAM_TYPE_DIR
);
2093 err
= sys_mount("/dev", "devfs");
2095 panic("error mounting devfs\n");
2098 fd
= sys_open("/boot/addons/fs", STREAM_TYPE_DIR
, 0);
2101 char buf
[SYS_MAX_NAME_LEN
];
2103 while((len
= sys_read(fd
, buf
, 0, sizeof(buf
))) > 0) {
2104 dprintf("loading '%s' fs module\n", buf
);
2105 vfs_load_fs_module(buf
);