mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-11 13:03:11 +00:00
parent
bfddf08f75
commit
a59f73f7d3
@ -372,9 +372,7 @@ extern "C" int execve(char const *filename,
|
|||||||
|
|
||||||
for (unsigned i = 0; i < MAX_INTERPRETER_NESTING_LEVELS; i++) {
|
for (unsigned i = 0; i < MAX_INTERPRETER_NESTING_LEVELS; i++) {
|
||||||
|
|
||||||
try {
|
if (Libc::resolve_symlinks(path.string(), resolved_path).failed()) {
|
||||||
Libc::resolve_symlinks(path.string(), resolved_path); }
|
|
||||||
catch (Libc::Symlink_resolve_error) {
|
|
||||||
warning("execve: executable binary '", filename, "' does not exist");
|
warning("execve: executable binary '", filename, "' does not exist");
|
||||||
return Libc::Errno(ENOENT);
|
return Libc::Errno(ENOENT);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ extern "C" {
|
|||||||
#include <internal/plugin_registry.h>
|
#include <internal/plugin_registry.h>
|
||||||
#include <internal/plugin.h>
|
#include <internal/plugin.h>
|
||||||
#include <internal/file.h>
|
#include <internal/file.h>
|
||||||
|
#include <internal/file_operations.h>
|
||||||
#include <internal/mem_alloc.h>
|
#include <internal/mem_alloc.h>
|
||||||
#include <internal/mmap_registry.h>
|
#include <internal/mmap_registry.h>
|
||||||
#include <internal/errno.h>
|
#include <internal/errno.h>
|
||||||
@ -104,7 +105,7 @@ typedef Token<Vfs::Scanner_policy_path_element> Path_element_token;
|
|||||||
/**
|
/**
|
||||||
* Resolve symbolic links in a given absolute path
|
* Resolve symbolic links in a given absolute path
|
||||||
*/
|
*/
|
||||||
void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
Symlink_resolve_result Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
||||||
{
|
{
|
||||||
char path_element[PATH_MAX];
|
char path_element[PATH_MAX];
|
||||||
char symlink_target[PATH_MAX];
|
char symlink_target[PATH_MAX];
|
||||||
@ -118,7 +119,7 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
|||||||
do {
|
do {
|
||||||
if (follow_count++ == FOLLOW_LIMIT) {
|
if (follow_count++ == FOLLOW_LIMIT) {
|
||||||
errno = ELOOP;
|
errno = ELOOP;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
current_iteration_working_path = next_iteration_working_path;
|
current_iteration_working_path = next_iteration_working_path;
|
||||||
@ -140,7 +141,7 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
|||||||
next_iteration_working_path.append_element(path_element);
|
next_iteration_working_path.append_element(path_element);
|
||||||
} catch (Path_base::Path_too_long) {
|
} catch (Path_base::Path_too_long) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,14 +153,14 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
|||||||
int res;
|
int res;
|
||||||
FNAME_FUNC_WRAPPER_GENERIC(res = , stat, next_iteration_working_path.base(), &stat_buf);
|
FNAME_FUNC_WRAPPER_GENERIC(res = , stat, next_iteration_working_path.base(), &stat_buf);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
if (S_ISLNK(stat_buf.st_mode)) {
|
if (S_ISLNK(stat_buf.st_mode)) {
|
||||||
FNAME_FUNC_WRAPPER_GENERIC(res = , readlink,
|
FNAME_FUNC_WRAPPER_GENERIC(res = , readlink,
|
||||||
next_iteration_working_path.base(),
|
next_iteration_working_path.base(),
|
||||||
symlink_target, sizeof(symlink_target) - 1);
|
symlink_target, sizeof(symlink_target) - 1);
|
||||||
if (res < 1)
|
if (res < 1)
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
|
|
||||||
/* zero terminate target */
|
/* zero terminate target */
|
||||||
symlink_target[res] = 0;
|
symlink_target[res] = 0;
|
||||||
@ -174,7 +175,7 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
|||||||
next_iteration_working_path.append_element(symlink_target);
|
next_iteration_working_path.append_element(symlink_target);
|
||||||
} catch (Path_base::Path_too_long) {
|
} catch (Path_base::Path_too_long) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
symlink_resolved_in_this_iteration = true;
|
symlink_resolved_in_this_iteration = true;
|
||||||
@ -188,10 +189,12 @@ void Libc::resolve_symlinks(char const *path, Absolute_path &resolved_path)
|
|||||||
|
|
||||||
resolved_path = next_iteration_working_path;
|
resolved_path = next_iteration_working_path;
|
||||||
resolved_path.remove_trailing('/');
|
resolved_path.remove_trailing('/');
|
||||||
|
|
||||||
|
return Symlinks_resolved_ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void resolve_symlinks_except_last_element(char const *path, Absolute_path &resolved_path)
|
static Symlink_resolve_result resolve_symlinks_except_last_element(char const *path, Absolute_path &resolved_path)
|
||||||
{
|
{
|
||||||
Absolute_path absolute_path_without_last_element(path, cwd().base());
|
Absolute_path absolute_path_without_last_element(path, cwd().base());
|
||||||
absolute_path_without_last_element.strip_last_element();
|
absolute_path_without_last_element.strip_last_element();
|
||||||
@ -205,8 +208,10 @@ static void resolve_symlinks_except_last_element(char const *path, Absolute_path
|
|||||||
resolved_path.append_element(absolute_path_last_element.base());
|
resolved_path.append_element(absolute_path_last_element.base());
|
||||||
} catch (Path_base::Path_too_long) {
|
} catch (Path_base::Path_too_long) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Symlinks_resolved_ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -222,14 +227,14 @@ extern "C" int access(const char *path, int amode)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks(path, resolved_path);
|
if (resolve_symlinks(path, resolved_path).failed()) {
|
||||||
FNAME_FUNC_WRAPPER(access, resolved_path.base(), amode);
|
|
||||||
} catch (Symlink_resolve_error) {
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FNAME_FUNC_WRAPPER(access, resolved_path.base(), amode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -408,14 +413,13 @@ extern "C" int lstat(const char *path, struct stat *buf)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks_except_last_element(path, resolved_path);
|
if (resolve_symlinks_except_last_element(path, resolved_path).failed())
|
||||||
resolved_path.remove_trailing('/');
|
|
||||||
FNAME_FUNC_WRAPPER(stat, resolved_path.base(), buf);
|
|
||||||
} catch (Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
resolved_path.remove_trailing('/');
|
||||||
|
FNAME_FUNC_WRAPPER(stat, resolved_path.base(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -427,14 +431,13 @@ extern "C" int mkdir(const char *path, mode_t mode)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks_except_last_element(path, resolved_path);
|
if (resolve_symlinks_except_last_element(path, resolved_path).failed())
|
||||||
resolved_path.remove_trailing('/');
|
|
||||||
FNAME_FUNC_WRAPPER(mkdir, resolved_path.base(), mode);
|
|
||||||
} catch(Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
resolved_path.remove_trailing('/');
|
||||||
|
FNAME_FUNC_WRAPPER(mkdir, resolved_path.base(), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -550,17 +553,12 @@ __SYS_(int, open, (const char *pathname, int flags, ...),
|
|||||||
Plugin *plugin;
|
Plugin *plugin;
|
||||||
File_descriptor *new_fdo;
|
File_descriptor *new_fdo;
|
||||||
|
|
||||||
try {
|
if (resolve_symlinks_except_last_element(pathname, resolved_path).failed())
|
||||||
resolve_symlinks_except_last_element(pathname, resolved_path);
|
|
||||||
} catch (Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & O_NOFOLLOW)) {
|
if (!(flags & O_NOFOLLOW)) {
|
||||||
/* resolve last element */
|
/* resolve last element */
|
||||||
try {
|
if (resolve_symlinks(resolved_path.base(), resolved_path).failed()) {
|
||||||
resolve_symlinks(resolved_path.base(), resolved_path);
|
|
||||||
} catch (Symlink_resolve_error) {
|
|
||||||
if (errno == ENOENT) {
|
if (errno == ENOENT) {
|
||||||
if (!(flags & O_CREAT))
|
if (!(flags & O_CREAT))
|
||||||
return -1;
|
return -1;
|
||||||
@ -671,13 +669,12 @@ extern "C" ssize_t readlink(const char *path, char *buf, ::size_t bufsiz)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks_except_last_element(path, resolved_path);
|
if (resolve_symlinks_except_last_element(path, resolved_path).failed())
|
||||||
FNAME_FUNC_WRAPPER(readlink, resolved_path.base(), buf, bufsiz);
|
|
||||||
} catch(Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
FNAME_FUNC_WRAPPER(readlink, resolved_path.base(), buf, bufsiz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -689,18 +686,18 @@ extern "C" int rename(const char *oldpath, const char *newpath)
|
|||||||
if ((oldpath[0] == '\0') || (newpath[0] == '\0'))
|
if ((oldpath[0] == '\0') || (newpath[0] == '\0'))
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_oldpath, resolved_newpath;
|
||||||
Absolute_path resolved_oldpath, resolved_newpath;
|
|
||||||
resolve_symlinks_except_last_element(oldpath, resolved_oldpath);
|
|
||||||
resolve_symlinks_except_last_element(newpath, resolved_newpath);
|
|
||||||
|
|
||||||
resolved_oldpath.remove_trailing('/');
|
if (resolve_symlinks_except_last_element(oldpath, resolved_oldpath).failed())
|
||||||
resolved_newpath.remove_trailing('/');
|
|
||||||
|
|
||||||
FNAME_FUNC_WRAPPER(rename, resolved_oldpath.base(), resolved_newpath.base());
|
|
||||||
} catch(Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
if (resolve_symlinks_except_last_element(newpath, resolved_newpath).failed())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
resolved_oldpath.remove_trailing('/');
|
||||||
|
resolved_newpath.remove_trailing('/');
|
||||||
|
|
||||||
|
FNAME_FUNC_WRAPPER(rename, resolved_oldpath.base(), resolved_newpath.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -712,25 +709,24 @@ extern "C" int rmdir(const char *path)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks_except_last_element(path, resolved_path);
|
|
||||||
resolved_path.remove_trailing('/');
|
|
||||||
|
|
||||||
struct stat stat_buf { };
|
if (resolve_symlinks_except_last_element(path, resolved_path).failed())
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (stat(resolved_path.base(), &stat_buf) == -1)
|
resolved_path.remove_trailing('/');
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!S_ISDIR(stat_buf.st_mode)) {
|
struct stat stat_buf { };
|
||||||
errno = ENOTDIR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FNAME_FUNC_WRAPPER(rmdir, resolved_path.base());
|
if (stat(resolved_path.base(), &stat_buf) == -1)
|
||||||
} catch(Symlink_resolve_error) {
|
return -1;
|
||||||
|
|
||||||
|
if (!S_ISDIR(stat_buf.st_mode)) {
|
||||||
|
errno = ENOTDIR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FNAME_FUNC_WRAPPER(rmdir, resolved_path.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -742,14 +738,13 @@ extern "C" int stat(const char *path, struct stat *buf)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks(path, resolved_path);
|
if (resolve_symlinks(path, resolved_path).failed())
|
||||||
resolved_path.remove_trailing('/');
|
|
||||||
FNAME_FUNC_WRAPPER(stat, resolved_path.base(), buf);
|
|
||||||
} catch(Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
resolved_path.remove_trailing('/');
|
||||||
|
FNAME_FUNC_WRAPPER(stat, resolved_path.base(), buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -761,13 +756,12 @@ extern "C" int symlink(const char *oldpath, const char *newpath)
|
|||||||
if ((oldpath[0] == '\0') || (newpath[0] == '\0'))
|
if ((oldpath[0] == '\0') || (newpath[0] == '\0'))
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks_except_last_element(newpath, resolved_path);
|
if (resolve_symlinks_except_last_element(newpath, resolved_path).failed())
|
||||||
FNAME_FUNC_WRAPPER(symlink, oldpath, resolved_path.base());
|
|
||||||
} catch(Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
FNAME_FUNC_WRAPPER(symlink, oldpath, resolved_path.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -779,13 +773,12 @@ extern "C" int unlink(const char *path)
|
|||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
|
|
||||||
try {
|
Absolute_path resolved_path;
|
||||||
Absolute_path resolved_path;
|
|
||||||
resolve_symlinks_except_last_element(path, resolved_path);
|
if (resolve_symlinks_except_last_element(path, resolved_path).failed())
|
||||||
FNAME_FUNC_WRAPPER(unlink, resolved_path.base());
|
|
||||||
} catch(Symlink_resolve_error) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
FNAME_FUNC_WRAPPER(unlink, resolved_path.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,12 @@ namespace Libc {
|
|||||||
|
|
||||||
typedef Genode::Path<PATH_MAX> Absolute_path;
|
typedef Genode::Path<PATH_MAX> Absolute_path;
|
||||||
|
|
||||||
void resolve_symlinks(char const *path, Absolute_path &resolved_path);
|
struct Symlinks_resolved_ok { };
|
||||||
|
struct Symlink_resolve_error { };
|
||||||
|
using Symlink_resolve_result = Attempt<Symlinks_resolved_ok, Symlink_resolve_error>;
|
||||||
|
|
||||||
|
Symlink_resolve_result resolve_symlinks(char const *path,
|
||||||
|
Absolute_path &resolved_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _LIBC__INTERNAL__FILE_OPERATIONS_H_ */
|
#endif /* _LIBC__INTERNAL__FILE_OPERATIONS_H_ */
|
||||||
|
@ -35,10 +35,6 @@ namespace Libc {
|
|||||||
|
|
||||||
typedef Genode::Path<PATH_MAX> Absolute_path;
|
typedef Genode::Path<PATH_MAX> Absolute_path;
|
||||||
|
|
||||||
class Symlink_resolve_error : Genode::Exception { };
|
|
||||||
|
|
||||||
void resolve_symlinks(char const *path, Absolute_path &resolved_path);
|
|
||||||
|
|
||||||
class Plugin : public List<Plugin>::Element
|
class Plugin : public List<Plugin>::Element
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
/* libc-internal includes */
|
/* libc-internal includes */
|
||||||
#include <internal/kernel.h>
|
#include <internal/kernel.h>
|
||||||
|
#include <internal/file_operations.h>
|
||||||
|
|
||||||
Libc::Kernel * Libc::Kernel::_kernel_ptr;
|
Libc::Kernel * Libc::Kernel::_kernel_ptr;
|
||||||
|
|
||||||
@ -84,7 +85,8 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
|
|
||||||
} diag_guard { *this };
|
} diag_guard { *this };
|
||||||
|
|
||||||
auto resolve_symlinks = [&] (Absolute_path next_iteration_working_path, Absolute_path &resolved_path)
|
auto resolve_symlinks = [&] (Absolute_path next_iteration_working_path,
|
||||||
|
Absolute_path &resolved_path) -> Symlink_resolve_result
|
||||||
{
|
{
|
||||||
char path_element[PATH_MAX];
|
char path_element[PATH_MAX];
|
||||||
char symlink_target[PATH_MAX];
|
char symlink_target[PATH_MAX];
|
||||||
@ -97,7 +99,7 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
do {
|
do {
|
||||||
if (follow_count++ == FOLLOW_LIMIT) {
|
if (follow_count++ == FOLLOW_LIMIT) {
|
||||||
errno = ELOOP;
|
errno = ELOOP;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
current_iteration_working_path = next_iteration_working_path;
|
current_iteration_working_path = next_iteration_working_path;
|
||||||
@ -119,7 +121,7 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
next_iteration_working_path.append_element(path_element);
|
next_iteration_working_path.append_element(path_element);
|
||||||
} catch (Path_base::Path_too_long) {
|
} catch (Path_base::Path_too_long) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -130,13 +132,13 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
int res = _vfs.stat_from_kernel(next_iteration_working_path.base(), &stat_buf);
|
int res = _vfs.stat_from_kernel(next_iteration_working_path.base(), &stat_buf);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
if (S_ISLNK(stat_buf.st_mode)) {
|
if (S_ISLNK(stat_buf.st_mode)) {
|
||||||
res = readlink(next_iteration_working_path.base(),
|
res = readlink(next_iteration_working_path.base(),
|
||||||
symlink_target, sizeof(symlink_target) - 1);
|
symlink_target, sizeof(symlink_target) - 1);
|
||||||
if (res < 1)
|
if (res < 1)
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
|
|
||||||
/* zero terminate target */
|
/* zero terminate target */
|
||||||
symlink_target[res] = 0;
|
symlink_target[res] = 0;
|
||||||
@ -151,7 +153,7 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
next_iteration_working_path.append_element(symlink_target);
|
next_iteration_working_path.append_element(symlink_target);
|
||||||
} catch (Path_base::Path_too_long) {
|
} catch (Path_base::Path_too_long) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
throw Symlink_resolve_error();
|
return Symlink_resolve_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
symlink_resolved_in_this_iteration = true;
|
symlink_resolved_in_this_iteration = true;
|
||||||
@ -165,21 +167,28 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
|
|
||||||
resolved_path = next_iteration_working_path;
|
resolved_path = next_iteration_working_path;
|
||||||
resolved_path.remove_trailing('/');
|
resolved_path.remove_trailing('/');
|
||||||
|
|
||||||
|
return Symlinks_resolved_ok();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef String<Vfs::MAX_PATH_LEN> Path;
|
typedef String<Vfs::MAX_PATH_LEN> Path;
|
||||||
|
|
||||||
auto resolve_absolute_path = [&] (Path const &path)
|
struct Absolute_path_resolved_ok { };
|
||||||
|
struct Absolute_path_resolve_error { };
|
||||||
|
using Absolute_path_resolve_result = Attempt<Absolute_path_resolved_ok,
|
||||||
|
Absolute_path_resolve_error>;
|
||||||
|
|
||||||
|
auto resolve_absolute_path = [&] (Path const &path, Absolute_path &abs_path) -> Absolute_path_resolve_result
|
||||||
{
|
{
|
||||||
Absolute_path abs_path { };
|
|
||||||
Absolute_path abs_dir(path.string(), _cwd.base()); abs_dir.strip_last_element();
|
Absolute_path abs_dir(path.string(), _cwd.base()); abs_dir.strip_last_element();
|
||||||
Absolute_path dir_entry(path.string(), _cwd.base()); dir_entry.keep_only_last_element();
|
Absolute_path dir_entry(path.string(), _cwd.base()); dir_entry.keep_only_last_element();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
resolve_symlinks(abs_dir, abs_path);
|
if (resolve_symlinks(abs_dir, abs_path).failed())
|
||||||
|
return Absolute_path_resolve_error();
|
||||||
abs_path.append_element(dir_entry.string());
|
abs_path.append_element(dir_entry.string());
|
||||||
return abs_path;
|
return Absolute_path_resolved_ok();
|
||||||
} catch (Path_base::Path_too_long) { return Absolute_path(); }
|
} catch (Path_base::Path_too_long) { return Absolute_path_resolve_error(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
auto init_fd = [&] (Xml_node const &node, char const *attr,
|
auto init_fd = [&] (Xml_node const &node, char const *attr,
|
||||||
@ -189,55 +198,55 @@ void Libc::Kernel::_init_file_descriptors()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Path const attr_value { node.attribute_value(attr, Path()) };
|
Path const attr_value { node.attribute_value(attr, Path()) };
|
||||||
try {
|
|
||||||
Absolute_path const path { resolve_absolute_path(attr_value) };
|
|
||||||
|
|
||||||
struct stat out_stat { };
|
Absolute_path path { };
|
||||||
if (_vfs.stat_from_kernel(path.string(), &out_stat) != 0) {
|
|
||||||
warning("failed to call 'stat' on ", path);
|
|
||||||
diag_guard.show = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File_descriptor *fd =
|
if (resolve_absolute_path(attr_value, path).failed()) {
|
||||||
_vfs.open_from_kernel(path.string(), flags, libc_fd);
|
warning("failed to resolve path for ", path);
|
||||||
|
|
||||||
if (!fd)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fd->libc_fd != libc_fd) {
|
|
||||||
error("could not allocate fd ",libc_fd," for ",path,", "
|
|
||||||
"got fd ",fd->libc_fd);
|
|
||||||
_vfs.close_from_kernel(fd);
|
|
||||||
diag_guard.show = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd->cloexec = node.attribute_value("cloexec", false);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to manually register the path. Normally this is done
|
|
||||||
* by '_open'. But we call the local 'open' function directly
|
|
||||||
* because we want to explicitly specify the libc fd ID.
|
|
||||||
*/
|
|
||||||
if (fd->fd_path)
|
|
||||||
warning("may leak former FD path memory");
|
|
||||||
|
|
||||||
{
|
|
||||||
char *dst = (char *)_heap.alloc(path.max_len());
|
|
||||||
copy_cstring(dst, path.string(), path.max_len());
|
|
||||||
fd->fd_path = dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
::off_t const seek = node.attribute_value("seek", 0ULL);
|
|
||||||
if (seek)
|
|
||||||
_vfs.lseek_from_kernel(fd, seek);
|
|
||||||
|
|
||||||
} catch (Symlink_resolve_error) {
|
|
||||||
warning("failed to resolve path for ", attr_value);
|
|
||||||
diag_guard.show = true;
|
diag_guard.show = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct stat out_stat { };
|
||||||
|
if (_vfs.stat_from_kernel(path.string(), &out_stat) != 0) {
|
||||||
|
warning("failed to call 'stat' on ", path);
|
||||||
|
diag_guard.show = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File_descriptor *fd =
|
||||||
|
_vfs.open_from_kernel(path.string(), flags, libc_fd);
|
||||||
|
|
||||||
|
if (!fd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fd->libc_fd != libc_fd) {
|
||||||
|
error("could not allocate fd ",libc_fd," for ",path,", "
|
||||||
|
"got fd ",fd->libc_fd);
|
||||||
|
_vfs.close_from_kernel(fd);
|
||||||
|
diag_guard.show = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd->cloexec = node.attribute_value("cloexec", false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to manually register the path. Normally this is done
|
||||||
|
* by '_open'. But we call the local 'open' function directly
|
||||||
|
* because we want to explicitly specify the libc fd ID.
|
||||||
|
*/
|
||||||
|
if (fd->fd_path)
|
||||||
|
warning("may leak former FD path memory");
|
||||||
|
|
||||||
|
{
|
||||||
|
char *dst = (char *)_heap.alloc(path.max_len());
|
||||||
|
copy_cstring(dst, path.string(), path.max_len());
|
||||||
|
fd->fd_path = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
::off_t const seek = node.attribute_value("seek", 0ULL);
|
||||||
|
if (seek)
|
||||||
|
_vfs.lseek_from_kernel(fd, seek);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_vfs.root_dir_has_dirents()) {
|
if (_vfs.root_dir_has_dirents()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user