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
9 #define VFS_SYMLINK_MAXLEN 512
11 extern struct lru_zone *dnode_lru, *inode_lru;
14 __vfs_walk(struct v_dnode* start,
16 struct v_dnode** dentry,
17 struct hstr* component,
25 if (depth >= VFS_SYMLINK_DEPTH) {
29 if (path[0] == VFS_PATH_DELIM || !start) {
30 if ((walk_options & VFS_WALK_FSRELATIVE) && start) {
31 start = start->super_block->root;
34 if (!vfs_sysroot->mnt) {
35 panick("vfs: no root");
39 if (path[0] == VFS_PATH_DELIM) {
46 struct v_dnode* dnode;
47 struct v_dnode* current_level = start;
48 struct v_inode* current_inode = current_level->inode;
50 struct hstr name = HSTR(fname_buffer, 0);
52 char current = path[i++], lookahead;
54 lookahead = path[i++];
55 if (current != VFS_PATH_DELIM) {
56 if (j >= VFS_NAME_MAXLEN - 1) {
59 if (!VFS_VALID_CHAR(current)) {
62 fname_buffer[j++] = current;
68 // handling cases like /^.*(\/+).*$/
69 if (lookahead == VFS_PATH_DELIM) {
75 hstr_rehash(&name, HSTR_FULL_HASH);
77 if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
79 hstrcpy(component, &name);
84 lock_dnode(current_level);
86 dnode = vfs_dcache_lookup(current_level, &name);
89 dnode = vfs_d_alloc(current_level, &name);
96 lock_inode(current_inode);
98 errno = current_inode->ops->dir_lookup(current_inode, dnode);
100 if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) {
101 if (!current_inode->ops->mkdir) {
104 errno = current_inode->ops->mkdir(current_inode, dnode);
108 vfs_dcache_add(current_level, dnode);
109 unlock_inode(current_inode);
112 unlock_dnode(current_level);
117 unlock_dnode(current_level);
120 current_level = dnode;
121 current_inode = current_level->inode;
123 assert(current_inode);
125 if (check_symlink_node(current_inode) &&
126 !(walk_options & VFS_WALK_NOFOLLOW)) {
128 struct v_inode_ops* iops;
130 iops = current_inode->ops;
132 if (!iops->read_symlink) {
137 lock_inode(current_inode);
139 errno = iops->read_symlink(current_inode, &link);
141 unlock_inode(current_inode);
145 unlock_inode(current_inode);
147 errno = __vfs_walk(current_level->parent,
153 fname_buffer + name.len + 1);
159 current_level = dnode;
160 current_inode = dnode->inode;
167 *dentry = current_level;
178 vfs_walk(struct v_dnode* start,
180 struct v_dnode** dentry,
181 struct hstr* component,
189 // allocate a file name stack for path walking and recursion to resolve
191 char* name_buffer = valloc(2048);
194 __vfs_walk(start, path, dentry, component, options, 0, name_buffer);
201 vfs_walk_proc(const char* path,
202 struct v_dnode** dentry,
203 struct hstr* component,
206 return vfs_walk(__current->cwd, path, dentry, component, options);