50 pr_dinfo2(dcache,
"lookup parent of '%s'", original_path);
51 MOS_ASSERT_X(base_dir && root_dir && original_path,
"Invalid VFS lookup parameters");
52 if (last_seg_out !=
NULL)
64 char *path =
strdup(original_path);
71 if (last_seg_out !=
NULL)
78 pr_dinfo2(dcache,
"lookup parent: current segment '%s'", current_seg);
85 if (parent_real_ref.isErr())
87 parent_ref = parent_real_ref.get();
93 if (last_seg_out !=
NULL)
95 const bool ends_with_slash = original_path[
strlen(original_path) - 1] ==
PATH_DELIM;
96 char *tmp = kcalloc<char>(
strlen(current_seg) + 2);
107 if (
strncmp(current_seg,
".", 2) == 0 ||
strcmp(current_seg,
"./") == 0)
113 if (
strncmp(current_seg,
"..", 3) == 0 ||
strcmp(current_seg,
"../") == 0)
115 if (parent_ref == root_dir)
139 if (child_ref->inode ==
NULL)
141 *last_seg_out =
NULL;
148 if (child_ref->is_mountpoint)
150 pr_dinfo2(dcache,
"jumping to mountpoint %s", child_ref->name.c_str());
158 parent_ref = child_ref.get();
173 mos_panic(
"inode does not support readlink (symlink) operation, but it's a symlink!");
186 return -ENAMETOOLONG;
191 pr_dinfo2(dcache,
"symlink target: %s", target);
193 char *last_segment =
NULL;
196 if (parent_ref.isErr())
200 bool is_symlink =
false;
205 if (child_ref.isErr() || is_symlink)
216 pr_dinfo2(dcache,
"resolving last segment: '%s'", leaf);
219 leaf[
strlen(leaf) - 1] =
'\0';
223 mos_warn(
"RESOLVE_EXPECT_DIR isn't set, but the provided path ends with a slash");
229 else if (
strncmp(leaf,
"..", 3) == 0 ||
strcmp(leaf,
"../") == 0)
241 return parent_parent;
251 child_ref->refcount++;
255 pr_dinfo2(dcache,
"file does not exist");
272 pr_dinfo2(dcache,
"resolving symlink for '%s'", leaf);
276 *is_symlink = symlink_target_ref !=
nullptr;
277 return symlink_target_ref;
280 pr_dinfo2(dcache,
"not following symlink");
291 if (child_ref->is_mountpoint)
312 for (std::atomic_size_t i = 0; i < d->
refcount; i++)
378 pr_dinfo2(dcache,
"filesystem doesn't support lookup");
388 pr_dinfo2(dcache,
"dentry '%s' found in the filesystem",
name);
393 pr_dinfo2(dcache,
"dentry '%s' not found in the filesystem",
name);
404 pr_dinfo2(dcache,
"resolving path '%s'", path);
406 if (parent_ref.isErr())
408 pr_dinfo2(dcache,
"failed to resolve parent of '%s', file not found", path);
412 if (last_segment ==
NULL)
415 pr_dinfo2(dcache,
"path '%s' is a single '/' or is empty", path);
426 bool symlink =
false;
429 if (child_ref.isErr() || symlink)
#define MOS_ASSERT_X(cond, msg,...)
#define MOS_UNREACHABLE()
#define mos_warn(fmt,...)
#define MOS_PATH_MAX_LENGTH
static PtrResult< dentry_t > dentry_resolve_to_parent(dentry_t *base_dir, dentry_t *root_dir, const char *original_path, char **last_seg_out)
Lookup the parent directory of a given path, and return the last segment of the path in last_seg_out.
static PtrResult< dentry_t > dentry_resolve_follow_symlink(dentry_t *dentry, lastseg_resolve_flags_t flags)
static PtrResult< dentry_t > dentry_resolve_lastseg(dentry_t *parent, char *leaf, lastseg_resolve_flags_t flags, bool *symlink_resolved)
static void dirter_add(vfs_listdir_state_t *state, u64 ino, mos::string_view name, file_type_t type)
void dentry_attach(dentry_t *d, inode_t *inode)
Attach an inode to a dentry.
dentry_t * dentry_ref_up_to(dentry_t *dentry, dentry_t *root)
Increment the reference count of a dentry up to a given dentry.
PtrResult< dentry_t > dentry_from_fd(fd_t fd)
Get the dentry from a file descriptor.
should_inline bool path_is_absolute(const char *path)
Check if a path is absolute.
PtrResult< dentry_t > dentry_lookup_child(dentry_t *parent, const char *name)
Get a child dentry from a parent dentry.
void dentry_detach(dentry_t *d)
Detach the inode from a dentry.
void dentry_try_release(dentry_t *dentry)
should_inline dentry_t * dentry_parent(const dentry_t &dentry)
void vfs_populate_listdir_buf(dentry_t *dir, vfs_listdir_state_t *state)
List the contents of a directory.
dentry_t * dentry_ref(dentry_t *dentry)
Increment the reference count of a dentry.
PtrResult< dentry_t > dentry_resolve(dentry_t *starting_dir, dentry_t *root_dir, const char *path, lastseg_resolve_flags_t flags)
Lookup a path in the filesystem.
void dentry_unref(dentry_t *dentry)
Decrement the reference count of a dentry.
__nodiscard bool dentry_unref_one_norelease(dentry_t *dentry)
Decrease the refcount of ONE SINGLE dentry, including (if it's a mountpoint) the mountpoint dentry.
@ RESOLVE_SYMLINK_NOFOLLOW
@ RESOLVE_EXPECT_NONEXIST
MOSAPI char * strcat(char *__restrict dest, const char *__restrict src)
MOSAPI char * strcpy(char *__restrict dest, const char *__restrict src)
MOSAPI char * strdup(const char *src)
MOSAPI s32 strncmp(const char *str1, const char *str2, size_t n)
MOSAPI char * strtok_r(char *str, const char *delim, char **saveptr)
MOSAPI s32 strcmp(const char *str1, const char *str2)
MOSAPI void(1, 2) fatal_abort(const char *fmt
MOSAPI void linked_list_init(list_node_t *head_node)
Initialise a circular double linked list.
MOSAPI void list_node_append(list_node_t *head, list_node_t *item)
#define list_node(element)
Get the ‘list_node’ of a list element. This is exactly the reverse of ‘list_entry’ above.
void inode_ref(inode_t *inode)
bool inode_unref(inode_t *inode)
dentry_t * dentry_root_get_mountpoint(dentry_t *dentry)
Given a mounted root dentry, return the mountpoint dentry that points to it.
ptr< mount_t > dentry_get_mount(const dentry_t *dentry)
basic_string_view< char > string_view
T * create(Args &&...args)
#define mos_panic(fmt,...)
static size_t strlen(const char *s)
#define pr_dinfo2(feat, fmt,...)
io_t * process_get_fd(Process *process, fd_t fd)
#define spinlock_acquire(lock)
#define spinlock_release(lock)
superblock_t * superblock
size_t(* readlink)(dentry_t *dentry, char *buffer, size_t buflen)
read the contents of a symbolic link
bool(* lookup)(inode_t *dir, dentry_t *dentry)
lookup a file in a directory, if it's unset for a directory, the VFS will use the default lookup
void(* iterate_dir)(dentry_t *dentry, vfs_listdir_state_t *iterator_state, dentry_iterator_op op)
iterate over the contents of a directory
size_t n_count
number of entries in the list
#define container_of(ptr, type, member)
mos::string dentry_name(const dentry_t *dentry)
void vfs_generic_iterate_dir(const dentry_t *dir, vfs_listdir_state_t *state, dentry_iterator_op add_record)
dentry_t * dentry_get_from_parent(superblock_t *sb, dentry_t *parent, mos::string_view name)
Create a new dentry with the given name and parent.