2 #include <lunaix/mm/valloc.h>
3 #include <lunaix/process.h>
4 #include <lunaix/spike.h>
6 #include <klibc/string.h>
8 #define VFS_SYMLINK_DEPTH 16
10 extern struct lru_zone *dnode_lru, *inode_lru;
13 __vfs_walk(struct v_dnode* start,
15 struct v_dnode** dentry,
16 struct hstr* component,
24 if (depth >= VFS_SYMLINK_DEPTH) {
28 if (path[0] == VFS_PATH_DELIM || !start) {
29 if ((walk_options & VFS_WALK_FSRELATIVE) && start) {
30 start = start->super_block->root;
33 if (!vfs_sysroot->mnt) {
34 panick("vfs: no root");
38 if (path[0] == VFS_PATH_DELIM) {
45 struct v_dnode* dnode;
46 struct v_dnode* current_level = start;
47 struct v_inode* current_inode = current_level->inode;
49 struct hstr name = HSTR(fname_buffer, 0);
51 char current = path[i++], lookahead;
53 lookahead = path[i++];
54 if (current != VFS_PATH_DELIM) {
55 if (j >= VFS_NAME_MAXLEN - 1) {
58 if (!VFS_VALID_CHAR(current)) {
61 fname_buffer[j++] = current;
67 // handling cases like /^.*(\/+).*$/
68 if (lookahead == VFS_PATH_DELIM) {
74 hstr_rehash(&name, HSTR_FULL_HASH);
76 if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
78 hstrcpy(component, &name);
83 lock_dnode(current_level);
85 dnode = vfs_dcache_lookup(current_level, &name);
88 dnode = vfs_d_alloc(current_level, &name);
95 lock_inode(current_inode);
97 errno = current_inode->ops->dir_lookup(current_inode, dnode);
99 if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) {
100 if (!current_inode->ops->mkdir) {
103 errno = current_inode->ops->mkdir(current_inode, dnode);
107 vfs_dcache_add(current_level, dnode);
108 unlock_inode(current_inode);
111 unlock_dnode(current_level);
116 unlock_dnode(current_level);
119 current_level = dnode;
120 current_inode = current_level->inode;
122 if ((current_inode->itype & F_MSLNK) &&
123 !(walk_options & VFS_WALK_NOFOLLOW)) {
126 if (!current_inode->ops->read_symlink) {
131 lock_inode(current_inode);
133 current_inode->ops->read_symlink(current_inode, &link))) {
134 unlock_inode(current_inode);
137 unlock_inode(current_inode);
139 errno = __vfs_walk(current_level->parent,
145 fname_buffer + name.len + 1);
151 current_level = dnode;
152 current_inode = dnode->inode;
159 *dentry = current_level;
170 vfs_walk(struct v_dnode* start,
172 struct v_dnode** dentry,
173 struct hstr* component,
181 // allocate a file name stack for path walking and recursion to resolve
183 char* name_buffer = valloc(2048);
186 __vfs_walk(start, path, dentry, component, options, 0, name_buffer);
193 vfs_walk_proc(const char* path,
194 struct v_dnode** dentry,
195 struct hstr* component,
198 return vfs_walk(__current->cwd, path, dentry, component, options);