51 MOS_ASSERT_X(base_dir && root_dir,
"Invalid VFS lookup parameters");
66 return { parent_ref, std::nullopt };
69 for (
size_t i = 0; i < parts.size(); i++)
71 const bool is_last = i == parts.size() - 1;
72 const auto current_seg = parts[i];
74 dInfo2<dcache> <<
"lookup parent: current segment '" << current_seg <<
"'" << (is_last ?
" (last)" :
"");
79 return { parent_ref, current_seg + (ends_with_slash ?
PATH_DELIM_STR :
"") };
82 if (current_seg ==
"." || current_seg ==
"./")
85 if (current_seg ==
".." || current_seg ==
"../")
88 if (parent_ref != root_dir)
106 if (child_ref->inode ==
NULL)
111 return { -ENOENT, std::nullopt };
114 if (child_ref->is_mountpoint)
124 parent_ref = child_ref.get();
133 if (parent_real_ref.isErr())
134 return { -ENOENT, std::nullopt };
135 parent_ref = parent_real_ref.get();
148 mos_panic(
"inode does not support readlink (symlink) operation, but it's a symlink!");
161 return -ENAMETOOLONG;
170 if (parent_ref.isErr())
174 bool is_symlink =
false;
178 if (child_ref.isErr() || is_symlink)
196 mos_warn(
"RESOLVE_EXPECT_DIR isn't set, but the provided path ends with a slash");
200 if (leaf ==
"." || leaf ==
"./")
202 else if (leaf ==
".." || leaf ==
"../")
214 return parent_parent;
224 child_ref->refcount++;
249 *is_symlink = symlink_target_ref !=
nullptr;
250 return symlink_target_ref;
264 if (child_ref->is_mountpoint)
285 for (std::atomic_size_t i = 0; i < d->
refcount; i++)
378 if (parent_ref.isErr())
380 dInfo2<dcache> <<
"failed to resolve parent of '" << path <<
"', file not found";
387 dInfo2<dcache> <<
"path '" << path <<
"' is a single '/' or is empty";
398 bool symlink =
false;
400 if (child_ref.isErr() || symlink)
#define MOS_ASSERT_X(cond, msg,...)
#define MOS_UNREACHABLE()
#define mos_warn(fmt,...)
#define MOS_PATH_MAX_LENGTH
bool ends_with(CharT c) const
void resize(size_t new_length)
bool ends_with(Char c) const
static PtrResult< dentry_t > dentry_resolve_follow_symlink(dentry_t *dentry, LastSegmentResolveFlags flags)
static PtrResult< dentry_t > dentry_resolve_lastseg(dentry_t *parent, mos::string leaf, const LastSegmentResolveFlags flags, bool *is_symlink)
static void dirter_add(vfs_listdir_state_t *state, u64 ino, mos::string_view name, file_type_t type)
static std::pair< PtrResult< dentry_t >, std::optional< mos::string > > dentry_resolve_to_parent(dentry_t *base_dir, dentry_t *root_dir, mos::string_view path)
Lookup the parent directory of a given path, and return the last segment of the path in last_seg_out.
void dentry_attach(dentry_t *d, inode_t *inode)
Attach an inode to a dentry.
PtrResult< dentry_t > dentry_lookup_child(dentry_t *parent, mos::string_view name)
Get a child dentry from a parent 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.
void dentry_detach(dentry_t *d)
Detach the inode from a dentry.
PtrResult< dentry_t > dentry_resolve(dentry_t *starting_dir, dentry_t *root_dir, mos::string_view path, LastSegmentResolveFlags flags)
Lookup a path in the filesystem.
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.
should_inline bool path_is_absolute(mos::string_view path)
Check if a path is absolute.
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 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)
mos::vector< mos::string > split_string(mos::string_view str, char delim)
dentry_t * dentry_root_get_mountpoint(const 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)
mos::basic_string< char > string
#define mos_panic(fmt,...)
IO * 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
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.