#include <lunaix/fs.h>
#include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
#include <lunaix/spike.h>
#include <klibc/string.h>
#define VFS_SYMLINK_DEPTH 16
+#define VFS_SYMLINK_MAXLEN 512
extern struct lru_zone *dnode_lru, *inode_lru;
int i = 0, j = 0;
if (depth >= VFS_SYMLINK_DEPTH) {
- return ENAMETOOLONG;
+ return ELOOP;
}
if (path[0] == VFS_PATH_DELIM || !start) {
panick("vfs: no root");
}
}
- i++;
+
+ if (path[0] == VFS_PATH_DELIM) {
+ i++;
+ }
}
+ assert(start);
+
struct v_dnode* dnode;
- struct v_inode* current_inode;
struct v_dnode* current_level = start;
+ struct v_inode* current_inode = current_level->inode;
struct hstr name = HSTR(fname_buffer, 0);
char current = path[i++], lookahead;
- while (current && current_level) {
+ while (current) {
lookahead = path[i++];
if (current != VFS_PATH_DELIM) {
if (j >= VFS_NAME_MAXLEN - 1) {
if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
if (component) {
- component->hash = name.hash;
- component->len = j;
- strcpy(component->value, fname_buffer);
+ hstrcpy(component, &name);
}
break;
}
- current_inode = current_level->inode;
-
- if ((current_inode->itype & VFS_IFSYMLINK) &&
- !(walk_options & VFS_WALK_NOFOLLOW)) {
- const char* link;
-
- lock_inode(current_inode);
- if ((errno =
- current_inode->ops->read_symlink(current_inode, &link))) {
- unlock_inode(current_inode);
- goto error;
- }
- unlock_inode(current_inode);
-
- errno = __vfs_walk(current_level->parent,
- link,
- &dnode,
- NULL,
- 0,
- depth + 1,
- fname_buffer + name.len + 1);
-
- if (errno) {
- goto error;
- }
-
- // reposition the resolved subtree pointed by symlink
- vfs_dcache_rehash(current_level->parent, dnode);
- current_level = dnode;
- current_inode = dnode->inode;
- }
-
lock_dnode(current_level);
dnode = vfs_dcache_lookup(current_level, &name);
j = 0;
current_level = dnode;
+ current_inode = current_level->inode;
+
+ assert(current_inode);
+
+ if (check_symlink_node(current_inode) &&
+ !(walk_options & VFS_WALK_NOFOLLOW)) {
+ const char* link;
+ struct v_inode_ops* iops;
+
+ iops = current_inode->ops;
+
+ if (!iops->read_symlink) {
+ errno = ENOTSUP;
+ goto error;
+ }
+
+ lock_inode(current_inode);
+
+ errno = iops->read_symlink(current_inode, &link);
+ if ((errno < 0)) {
+ unlock_inode(current_inode);
+ goto error;
+ }
+
+ unlock_inode(current_inode);
+
+ errno = __vfs_walk(current_level->parent,
+ link,
+ &dnode,
+ NULL,
+ 0,
+ depth + 1,
+ fname_buffer + name.len + 1);
+
+ if (errno) {
+ goto error;
+ }
+
+ current_level = dnode;
+ current_inode = dnode->inode;
+ }
+
cont:
current = lookahead;
};
struct hstr* component,
int options)
{
+ if (!path) {
+ *dentry = NULL;
+ return 0;
+ }
+
// allocate a file name stack for path walking and recursion to resolve
// symlink
char* name_buffer = valloc(2048);