2 #include <lunaix/mm/valloc.h>
3 #include <lunaix/process.h>
4 #include <lunaix/spike.h>
6 #include <usr/lunaix/fcntl_defs.h>
8 #include <klibc/string.h>
10 #define VFS_SYMLINK_DEPTH 16
11 #define VFS_SYMLINK_MAXLEN 512
13 extern struct lru_zone *dnode_lru, *inode_lru;
16 __vfs_walk(struct v_dnode* start,
18 struct v_dnode** dentry,
19 struct hstr* component,
27 if (depth >= VFS_SYMLINK_DEPTH) {
31 if (path[0] == VFS_PATH_DELIM || !start) {
32 if ((walk_options & VFS_WALK_FSRELATIVE) && start) {
33 start = start->super_block->root;
35 else if (unlikely(!__current)) {
39 start = __current->root ?: vfs_sysroot;
42 if (unlikely(!start || !start->mnt)) {
46 if (path[0] == VFS_PATH_DELIM) {
53 struct v_dnode* dnode;
54 struct v_dnode* current_level = start;
55 struct v_inode* current_inode = current_level->inode;
57 struct hstr name = HSTR(fname_buffer, 0);
59 char current = path[i++], lookahead;
62 lookahead = path[i++];
64 if (current != VFS_PATH_DELIM)
66 if (j >= VFS_NAME_MAXLEN - 1) {
69 if (!VFS_VALID_CHAR(current)) {
72 fname_buffer[j++] = current;
78 // handling cases like /^.*(\/+).*$/
79 if (lookahead == VFS_PATH_DELIM) {
85 hstr_rehash(&name, HSTR_FULL_HASH);
87 if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
89 hstrcpy(component, &name);
94 lock_dnode(current_level);
96 if (!check_allow_execute(current_inode)) {
101 dnode = vfs_dcache_lookup(current_level, &name);
105 dnode = vfs_d_alloc(current_level, &name);
112 lock_inode(current_inode);
114 errno = current_inode->ops->dir_lookup(current_inode, dnode);
116 if (errno == ENOENT && (walk_options & VFS_WALK_MKPARENT)) {
117 if (!current_inode->ops->mkdir) {
120 errno = current_inode->ops->mkdir(current_inode, dnode);
124 vfs_dcache_add(current_level, dnode);
125 unlock_inode(current_inode);
128 unlock_dnode(current_level);
133 unlock_dnode(current_level);
136 current_level = dnode;
137 current_inode = current_level->inode;
139 assert(current_inode);
141 if (check_symlink_node(current_inode) &&
142 !(walk_options & VFS_WALK_NOFOLLOW))
145 struct v_inode_ops* iops;
147 iops = current_inode->ops;
149 if (!iops->read_symlink) {
154 lock_inode(current_inode);
156 errno = iops->read_symlink(current_inode, &link);
158 unlock_inode(current_inode);
162 unlock_inode(current_inode);
164 errno = __vfs_walk(current_level->parent,
170 fname_buffer + name.len + 1);
176 current_level = dnode;
177 current_inode = dnode->inode;
184 *dentry = current_level;
196 vfs_walk(struct v_dnode* start,
198 struct v_dnode** dentry,
199 struct hstr* component,
207 // allocate a file name stack for path walking and recursion to resolve
209 char* name_buffer = valloc(2048);
212 __vfs_walk(start, path, dentry, component, options, 0, name_buffer);
219 vfs_walk_proc(const char* path,
220 struct v_dnode** dentry,
221 struct hstr* component,
224 return vfs_walk(__current->cwd, path, dentry, component, options);
228 vfs_walkat(int fd, const char* path, int at_opts, struct v_dnode** dnode_out)
230 int errno, options = 0;
231 struct v_dnode *root_dnode;
234 if ((at_opts & AT_FDCWD)) {
235 root_dnode = __current->cwd;
239 errno = vfs_getfd(fd, &_fd);
244 root_dnode = _fd->file->dnode;
247 if ((at_opts & AT_SYMLINK_NOFOLLOW)) {
248 options |= VFS_WALK_NOFOLLOW;
251 errno = vfs_walk(root_dnode, path, dnode_out, NULL, options);