2 #include <lunaix/mm/valloc.h>
3 #include <lunaix/spike.h>
5 #include <klibc/string.h>
7 #define VFS_SYMLINK_DEPTH 16
9 extern struct lru_zone *dnode_lru, *inode_lru;
12 __vfs_walk(struct v_dnode* start,
14 struct v_dnode** dentry,
15 struct hstr* component,
23 if (depth >= VFS_SYMLINK_DEPTH) {
27 if (path[0] == VFS_PATH_DELIM || !start) {
28 if ((walk_options & VFS_WALK_FSRELATIVE) && start) {
29 start = start->super_block->root;
32 if (!vfs_sysroot->mnt) {
33 panick("vfs: no root");
37 if (path[0] == VFS_PATH_DELIM) {
44 struct v_dnode* dnode;
45 struct v_inode* current_inode;
46 struct v_dnode* current_level = start;
48 struct hstr name = HSTR(fname_buffer, 0);
50 char current = path[i++], lookahead;
52 lookahead = path[i++];
53 if (current != VFS_PATH_DELIM) {
54 if (j >= VFS_NAME_MAXLEN - 1) {
57 if (!VFS_VALID_CHAR(current)) {
60 fname_buffer[j++] = current;
66 // handling cases like /^.*(\/+).*$/
67 if (lookahead == VFS_PATH_DELIM) {
73 hstr_rehash(&name, HSTR_FULL_HASH);
75 if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
77 component->hash = name.hash;
79 strcpy(component->value, fname_buffer);
84 current_inode = current_level->inode;
86 if ((current_inode->itype & VFS_IFSYMLINK) &&
87 !(walk_options & VFS_WALK_NOFOLLOW)) {
90 lock_inode(current_inode);
92 current_inode->ops->read_symlink(current_inode, &link))) {
93 unlock_inode(current_inode);
96 unlock_inode(current_inode);
98 errno = __vfs_walk(current_level->parent,
104 fname_buffer + name.len + 1);
110 // reposition the resolved subtree pointed by symlink
111 vfs_dcache_rehash(current_level->parent, dnode);
112 current_level = dnode;
113 current_inode = dnode->inode;
116 lock_dnode(current_level);
118 dnode = vfs_dcache_lookup(current_level, &name);
121 dnode = vfs_d_alloc(current_level, &name);
128 lock_inode(current_inode);
130 errno = current_inode->ops->dir_lookup(current_inode, dnode);
132 if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) {
133 if (!current_inode->ops->mkdir) {
136 errno = current_inode->ops->mkdir(current_inode, dnode);
140 vfs_dcache_add(current_level, dnode);
141 unlock_inode(current_inode);
144 unlock_dnode(current_level);
149 unlock_dnode(current_level);
152 current_level = dnode;
157 *dentry = current_level;
168 vfs_walk(struct v_dnode* start,
170 struct v_dnode** dentry,
171 struct hstr* component,
174 // allocate a file name stack for path walking and recursion to resolve
176 char* name_buffer = valloc(2048);
179 __vfs_walk(start, path, dentry, component, options, 0, name_buffer);
186 vfs_walk_proc(const char* path,
187 struct v_dnode** dentry,
188 struct hstr* component,
191 return vfs_walk(__current->cwd, path, dentry, component, options);