Compare commits
12 Commits
57e76a65a4
...
d68ad893f0
Author | SHA1 | Date |
---|---|---|
Bananymous | d68ad893f0 | |
Bananymous | 4ca147699d | |
Bananymous | abed41b8fa | |
Bananymous | 2604a55f80 | |
Bananymous | 39667de662 | |
Bananymous | 8956835d95 | |
Bananymous | ea4ec2eafc | |
Bananymous | 3a352078de | |
Bananymous | 6060b39548 | |
Bananymous | dce2436b2c | |
Bananymous | 2b52ea4c6f | |
Bananymous | b41738b47b |
|
@ -7,6 +7,7 @@
|
||||||
#include <BAN/New.h>
|
#include <BAN/New.h>
|
||||||
#include <BAN/PlacementNew.h>
|
#include <BAN/PlacementNew.h>
|
||||||
#include <BAN/Span.h>
|
#include <BAN/Span.h>
|
||||||
|
#include <BAN/Swap.h>
|
||||||
|
|
||||||
namespace BAN
|
namespace BAN
|
||||||
{
|
{
|
||||||
|
@ -65,6 +66,8 @@ namespace BAN
|
||||||
const T& front() const;
|
const T& front() const;
|
||||||
T& front();
|
T& front();
|
||||||
|
|
||||||
|
void reverse();
|
||||||
|
|
||||||
ErrorOr<void> resize(size_type) requires is_default_constructible_v<T>;
|
ErrorOr<void> resize(size_type) requires is_default_constructible_v<T>;
|
||||||
ErrorOr<void> resize(size_type, const T&) requires is_copy_constructible_v<T>;
|
ErrorOr<void> resize(size_type, const T&) requires is_copy_constructible_v<T>;
|
||||||
ErrorOr<void> reserve(size_type);
|
ErrorOr<void> reserve(size_type);
|
||||||
|
@ -301,6 +304,13 @@ namespace BAN
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Vector<T>::reverse()
|
||||||
|
{
|
||||||
|
for (size_type i = 0; i < m_size / 2; i++)
|
||||||
|
BAN::swap(m_data[i], m_data[m_size - i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::resize(size_type size) requires is_default_constructible_v<T>
|
ErrorOr<void> Vector<T>::resize(size_type size) requires is_default_constructible_v<T>
|
||||||
{
|
{
|
||||||
|
|
|
@ -215,8 +215,10 @@ namespace BAN
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Formatter
|
||||||
|
{
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Formatter::print_argument(F putc, const Kernel::ACPI::AML::NameSeg& name_seg, const ValueFormat&)
|
void print_argument(F putc, const Kernel::ACPI::AML::NameSeg& name_seg, const ValueFormat&)
|
||||||
{
|
{
|
||||||
size_t len = 4;
|
size_t len = 4;
|
||||||
while (len > 0 && name_seg.chars[len - 1] == '_')
|
while (len > 0 && name_seg.chars[len - 1] == '_')
|
||||||
|
@ -226,7 +228,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Formatter::print_argument(F putc, const Kernel::ACPI::AML::NameString& name_string, const ValueFormat&)
|
void print_argument(F putc, const Kernel::ACPI::AML::NameString& name_string, const ValueFormat&)
|
||||||
{
|
{
|
||||||
print_argument(putc, name_string.prefix, {});
|
print_argument(putc, name_string.prefix, {});
|
||||||
if (!name_string.path.empty())
|
if (!name_string.path.empty())
|
||||||
|
@ -237,5 +239,6 @@ namespace BAN
|
||||||
print_argument(putc, name_string.path[i], {});
|
print_argument(putc, name_string.path[i], {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
virtual ~Inode() {}
|
virtual ~Inode() {}
|
||||||
|
|
||||||
bool can_access(const Credentials&, int);
|
bool can_access(const Credentials&, int) const;
|
||||||
|
|
||||||
bool operator==(const Inode& other) const { return dev() == other.dev() && ino() == other.ino(); }
|
bool operator==(const Inode& other) const { return dev() == other.dev() && ino() == other.ino(); }
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,51 @@ namespace Kernel
|
||||||
|
|
||||||
struct File
|
struct File
|
||||||
{
|
{
|
||||||
|
File() = default;
|
||||||
|
explicit File(BAN::RefPtr<Inode> inode)
|
||||||
|
: inode(BAN::move(inode))
|
||||||
|
{ }
|
||||||
|
explicit File(BAN::RefPtr<Inode> inode, BAN::String&& canonical_path)
|
||||||
|
: inode(BAN::move(inode))
|
||||||
|
, canonical_path(BAN::move(canonical_path))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
File(const File&) = delete;
|
||||||
|
File(File&& other)
|
||||||
|
: inode(BAN::move(other.inode))
|
||||||
|
, canonical_path(BAN::move(other.canonical_path))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
File& operator=(const File&) = delete;
|
||||||
|
File& operator=(File&& other)
|
||||||
|
{
|
||||||
|
inode = BAN::move(other.inode);
|
||||||
|
canonical_path = BAN::move(other.canonical_path);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<File> clone() const
|
||||||
|
{
|
||||||
|
File result;
|
||||||
|
result.inode = inode;
|
||||||
|
TRY(result.canonical_path.append(canonical_path));
|
||||||
|
return BAN::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
BAN::RefPtr<Inode> inode;
|
BAN::RefPtr<Inode> inode;
|
||||||
BAN::String canonical_path;
|
BAN::String canonical_path;
|
||||||
};
|
};
|
||||||
BAN::ErrorOr<File> file_from_absolute_path(const Credentials&, BAN::StringView, int);
|
|
||||||
|
File root_file()
|
||||||
|
{
|
||||||
|
return File(root_inode(), "/"_sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<File> file_from_relative_path(const File& parent, const Credentials&, BAN::StringView, int);
|
||||||
|
BAN::ErrorOr<File> file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags)
|
||||||
|
{
|
||||||
|
return file_from_relative_path(File(root_inode()), credentials, path, flags);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VirtualFileSystem() = default;
|
VirtualFileSystem() = default;
|
||||||
|
|
|
@ -39,10 +39,6 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> truncate(int fd, off_t length);
|
BAN::ErrorOr<void> truncate(int fd, off_t length);
|
||||||
|
|
||||||
BAN::ErrorOr<void> fstat(int fd, struct stat*) const;
|
|
||||||
BAN::ErrorOr<void> fstatat(int fd, BAN::StringView path, struct stat* buf, int flag);
|
|
||||||
BAN::ErrorOr<void> stat(BAN::StringView absolute_path, struct stat* buf, int flag);
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> close(int);
|
BAN::ErrorOr<void> close(int);
|
||||||
void close_all();
|
void close_all();
|
||||||
void close_cloexec();
|
void close_cloexec();
|
||||||
|
@ -52,6 +48,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> read_dir_entries(int fd, struct dirent* list, size_t list_len);
|
BAN::ErrorOr<size_t> read_dir_entries(int fd, struct dirent* list, size_t list_len);
|
||||||
|
|
||||||
|
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
|
||||||
BAN::ErrorOr<BAN::StringView> path_of(int) const;
|
BAN::ErrorOr<BAN::StringView> path_of(int) const;
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
|
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);
|
||||||
BAN::ErrorOr<int> flags_of(int) const;
|
BAN::ErrorOr<int> flags_of(int) const;
|
||||||
|
@ -59,15 +56,16 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
struct OpenFileDescription : public BAN::RefCounted<OpenFileDescription>
|
struct OpenFileDescription : public BAN::RefCounted<OpenFileDescription>
|
||||||
{
|
{
|
||||||
OpenFileDescription(BAN::RefPtr<Inode> inode, BAN::String path, off_t offset, int flags)
|
OpenFileDescription(VirtualFileSystem::File file, off_t offset, int flags)
|
||||||
: inode(inode)
|
: file(BAN::move(file))
|
||||||
, path(BAN::move(path))
|
|
||||||
, offset(offset)
|
, offset(offset)
|
||||||
, flags(flags)
|
, flags(flags)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
BAN::RefPtr<Inode> inode;
|
BAN::RefPtr<Inode> inode() const { return file.inode; }
|
||||||
BAN::String path;
|
BAN::StringView path() const { return file.canonical_path.sv(); }
|
||||||
|
|
||||||
|
VirtualFileSystem::File file;
|
||||||
off_t offset { 0 };
|
off_t offset { 0 };
|
||||||
int flags { 0 };
|
int flags { 0 };
|
||||||
|
|
||||||
|
|
|
@ -101,10 +101,10 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
|
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
|
||||||
|
|
||||||
BAN::ErrorOr<long> open_inode(BAN::RefPtr<Inode>, int flags);
|
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags);
|
||||||
|
|
||||||
BAN::ErrorOr<void> create_file_or_dir(BAN::StringView name, mode_t mode);
|
BAN::ErrorOr<void> create_file_or_dir(const VirtualFileSystem::File& parent, BAN::StringView path, mode_t mode) const;
|
||||||
BAN::ErrorOr<long> open_file(BAN::StringView path, int oflag, mode_t = 0);
|
BAN::ErrorOr<long> open_file_impl(const VirtualFileSystem::File& parent, BAN::StringView path, int oflag, mode_t = 0);
|
||||||
BAN::ErrorOr<long> sys_open(const char* path, int, mode_t);
|
BAN::ErrorOr<long> sys_open(const char* path, int, mode_t);
|
||||||
BAN::ErrorOr<long> sys_openat(int, const char* path, int, mode_t);
|
BAN::ErrorOr<long> sys_openat(int, const char* path, int, mode_t);
|
||||||
BAN::ErrorOr<long> sys_close(int fd);
|
BAN::ErrorOr<long> sys_close(int fd);
|
||||||
|
@ -114,7 +114,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> sys_create(const char*, mode_t);
|
BAN::ErrorOr<long> sys_create(const char*, mode_t);
|
||||||
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
||||||
BAN::ErrorOr<long> sys_unlink(const char*);
|
BAN::ErrorOr<long> sys_unlink(const char*);
|
||||||
BAN::ErrorOr<long> readlink_impl(BAN::StringView absolute_path, char* buffer, size_t bufsize);
|
BAN::ErrorOr<long> readlink_impl(BAN::RefPtr<Inode>, char* buffer, size_t bufsize);
|
||||||
BAN::ErrorOr<long> sys_readlink(const char* path, char* buffer, size_t bufsize);
|
BAN::ErrorOr<long> sys_readlink(const char* path, char* buffer, size_t bufsize);
|
||||||
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
||||||
|
|
||||||
|
@ -217,13 +217,12 @@ namespace Kernel
|
||||||
// ONLY CALLED BY TIMER INTERRUPT
|
// ONLY CALLED BY TIMER INTERRUPT
|
||||||
static void update_alarm_queue();
|
static void update_alarm_queue();
|
||||||
|
|
||||||
|
const VirtualFileSystem::File& working_directory() const { return m_working_directory; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
Process(const Credentials&, pid_t pid, pid_t parent, pid_t sid, pid_t pgrp);
|
||||||
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
|
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
|
||||||
|
|
||||||
// Load elf from a file
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<LibELF::LoadableELF>> load_elf_for_exec(const Credentials&, BAN::StringView file_path, const BAN::String& cwd, Kernel::PageTable&);
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> validate_string_access(const char*);
|
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||||
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write);
|
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write);
|
||||||
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t, bool needs_write);
|
BAN::ErrorOr<void> validate_pointer_access(const void*, size_t, bool needs_write);
|
||||||
|
@ -280,7 +279,8 @@ namespace Kernel
|
||||||
|
|
||||||
mutable Mutex m_process_lock;
|
mutable Mutex m_process_lock;
|
||||||
|
|
||||||
BAN::String m_working_directory;
|
VirtualFileSystem::File m_working_directory;
|
||||||
|
|
||||||
BAN::Vector<Thread*> m_threads;
|
BAN::Vector<Thread*> m_threads;
|
||||||
|
|
||||||
uint64_t m_alarm_interval_ns { 0 };
|
uint64_t m_alarm_interval_ns { 0 };
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
bool Inode::can_access(const Credentials& credentials, int flags)
|
bool Inode::can_access(const Credentials& credentials, int flags) const
|
||||||
{
|
{
|
||||||
if (credentials.is_superuser())
|
if (credentials.is_superuser())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
|
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
TRY(m_mount_points.push_back({ file_system, file }));
|
TRY(m_mount_points.emplace_back(file_system, BAN::move(file)));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,43 +127,59 @@ namespace Kernel
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_absolute_path(const Credentials& credentials, BAN::StringView path, int flags)
|
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
|
||||||
{
|
{
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
ASSERT(path.front() == '/');
|
auto inode = parent.inode;
|
||||||
|
|
||||||
auto inode = root_inode();
|
|
||||||
ASSERT(inode);
|
ASSERT(inode);
|
||||||
|
|
||||||
BAN::String canonical_path;
|
BAN::String canonical_path;
|
||||||
|
TRY(canonical_path.append(parent.canonical_path));
|
||||||
|
if (!canonical_path.empty() && canonical_path.back() == '/')
|
||||||
|
canonical_path.pop_back();
|
||||||
|
ASSERT(canonical_path.empty() || canonical_path.back() != '/');
|
||||||
|
|
||||||
BAN::Vector<BAN::String> path_parts;
|
BAN::Vector<BAN::String> path_parts;
|
||||||
|
|
||||||
|
const auto append_string_view_in_reverse =
|
||||||
|
[&path_parts](BAN::StringView path) -> BAN::ErrorOr<void>
|
||||||
{
|
{
|
||||||
auto temp = TRY(path.split('/'));
|
auto split_path = TRY(path.split('/'));
|
||||||
for (size_t i = 0; i < temp.size(); i++)
|
split_path.reverse();
|
||||||
TRY(path_parts.emplace_back(temp[temp.size() - i - 1]));
|
for (auto part : split_path)
|
||||||
|
{
|
||||||
|
TRY(path_parts.emplace_back());
|
||||||
|
TRY(path_parts.back().append(part));
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
TRY(append_string_view_in_reverse(path));
|
||||||
|
|
||||||
size_t link_depth = 0;
|
size_t link_depth = 0;
|
||||||
|
|
||||||
while (!path_parts.empty())
|
while (!path_parts.empty())
|
||||||
{
|
{
|
||||||
const auto& path_part = path_parts.back();
|
BAN::String path_part = BAN::move(path_parts.back());
|
||||||
auto orig = inode;
|
path_parts.pop_back();
|
||||||
|
|
||||||
if (path_part.empty() || path_part == "."_sv)
|
if (path_part.empty() || path_part == "."_sv)
|
||||||
{
|
continue;
|
||||||
|
|
||||||
}
|
auto orig = inode;
|
||||||
else if (path_part == ".."_sv)
|
|
||||||
|
// resolve file name
|
||||||
{
|
{
|
||||||
|
auto parent_inode = inode;
|
||||||
|
if (path_part == ".."_sv)
|
||||||
if (auto* mount_point = mount_from_root_inode(inode))
|
if (auto* mount_point = mount_from_root_inode(inode))
|
||||||
inode = TRY(mount_point->host.inode->find_inode(".."_sv));
|
parent_inode = mount_point->host.inode;
|
||||||
else
|
if (!parent_inode->can_access(credentials, O_SEARCH))
|
||||||
inode = TRY(inode->find_inode(".."_sv));
|
return BAN::Error::from_errno(EACCES);
|
||||||
|
inode = TRY(parent_inode->find_inode(path_part));
|
||||||
|
|
||||||
|
if (path_part == ".."_sv)
|
||||||
|
{
|
||||||
if (!canonical_path.empty())
|
if (!canonical_path.empty())
|
||||||
{
|
{
|
||||||
ASSERT(canonical_path.front() == '/');
|
ASSERT(canonical_path.front() == '/');
|
||||||
|
@ -174,34 +190,28 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!inode->can_access(credentials, O_SEARCH))
|
|
||||||
return BAN::Error::from_errno(EACCES);
|
|
||||||
|
|
||||||
inode = TRY(inode->find_inode(path_part));
|
|
||||||
|
|
||||||
if (auto* mount_point = mount_from_host_inode(inode))
|
if (auto* mount_point = mount_from_host_inode(inode))
|
||||||
inode = mount_point->target->root_inode();
|
inode = mount_point->target->root_inode();
|
||||||
|
|
||||||
TRY(canonical_path.push_back('/'));
|
TRY(canonical_path.push_back('/'));
|
||||||
TRY(canonical_path.append(path_part));
|
TRY(canonical_path.append(path_part));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path_parts.pop_back();
|
if (!inode->mode().iflnk())
|
||||||
|
continue;
|
||||||
|
if ((flags & O_NOFOLLOW) && path_parts.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (inode->mode().iflnk() && (!(flags & O_NOFOLLOW) || !path_parts.empty()))
|
// resolve symbolic links
|
||||||
{
|
{
|
||||||
auto target = TRY(inode->link_target());
|
auto link_target = TRY(inode->link_target());
|
||||||
if (target.empty())
|
if (link_target.empty())
|
||||||
return BAN::Error::from_errno(ENOENT);
|
return BAN::Error::from_errno(ENOENT);
|
||||||
|
|
||||||
if (target.front() == '/')
|
if (link_target.front() == '/')
|
||||||
{
|
{
|
||||||
inode = root_inode();
|
inode = root_inode();
|
||||||
canonical_path.clear();
|
canonical_path.clear();
|
||||||
|
|
||||||
auto temp = TRY(target.sv().split('/'));
|
|
||||||
for (size_t i = 0; i < temp.size(); i++)
|
|
||||||
TRY(path_parts.emplace_back(temp[temp.size() - i - 1]));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -210,12 +220,10 @@ namespace Kernel
|
||||||
while (canonical_path.back() != '/')
|
while (canonical_path.back() != '/')
|
||||||
canonical_path.pop_back();
|
canonical_path.pop_back();
|
||||||
canonical_path.pop_back();
|
canonical_path.pop_back();
|
||||||
|
|
||||||
auto new_parts = TRY(target.sv().split('/'));
|
|
||||||
for (size_t i = 0; i < new_parts.size(); i++)
|
|
||||||
TRY(path_parts.emplace_back(new_parts[new_parts.size() - i - 1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRY(append_string_view_in_reverse(link_target.sv()));
|
||||||
|
|
||||||
link_depth++;
|
link_depth++;
|
||||||
if (link_depth > 100)
|
if (link_depth > 100)
|
||||||
return BAN::Error::from_errno(ELOOP);
|
return BAN::Error::from_errno(ELOOP);
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace Kernel
|
||||||
memcpy(address, &connection.target.address, *address_len);
|
memcpy(address, &connection.target.address, *address_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRY(Process::current().open_inode(return_inode, O_RDWR | flags));
|
return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<tcp socket>"_sv), O_RDWR | flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> TCPSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> TCPSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace Kernel
|
||||||
strncpy(sockaddr_un.sun_path, pending->m_bound_path.data(), copy_len);
|
strncpy(sockaddr_un.sun_path, pending->m_bound_path.data(), copy_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRY(Process::current().open_inode(return_inode, O_RDWR | flags));
|
return TRY(Process::current().open_inode(VirtualFileSystem::File(return_inode, "<unix socket>"_sv), O_RDWR | flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> UnixDomainSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
BAN::ErrorOr<void> UnixDomainSocket::connect_impl(const sockaddr* address, socklen_t address_len)
|
||||||
|
@ -200,16 +200,24 @@ namespace Kernel
|
||||||
if (sockaddr_un.sun_family != AF_UNIX)
|
if (sockaddr_un.sun_family != AF_UNIX)
|
||||||
return BAN::Error::from_errno(EAFNOSUPPORT);
|
return BAN::Error::from_errno(EAFNOSUPPORT);
|
||||||
|
|
||||||
auto absolute_path = TRY(Process::current().absolute_path_of(sockaddr_un.sun_path));
|
auto bind_path = BAN::StringView(sockaddr_un.sun_path);
|
||||||
if (auto ret = Process::current().create_file_or_dir(absolute_path, 0755 | S_IFSOCK); ret.is_error())
|
if (bind_path.empty())
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
// FIXME: This feels sketchy
|
||||||
|
auto parent_file = bind_path.front() == '/'
|
||||||
|
? VirtualFileSystem::get().root_file()
|
||||||
|
: TRY(Process::current().working_directory().clone());
|
||||||
|
if (auto ret = Process::current().create_file_or_dir(parent_file, bind_path, 0755 | S_IFSOCK); ret.is_error())
|
||||||
{
|
{
|
||||||
if (ret.error().get_error_code() == EEXIST)
|
if (ret.error().get_error_code() == EEXIST)
|
||||||
return BAN::Error::from_errno(EADDRINUSE);
|
return BAN::Error::from_errno(EADDRINUSE);
|
||||||
return ret.release_error();
|
return ret.release_error();
|
||||||
}
|
}
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(
|
auto file = TRY(VirtualFileSystem::get().file_from_relative_path(
|
||||||
|
parent_file,
|
||||||
Process::current().credentials(),
|
Process::current().credentials(),
|
||||||
absolute_path,
|
bind_path,
|
||||||
O_RDWR
|
O_RDWR
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,11 @@ namespace Kernel
|
||||||
|
|
||||||
auto& open_file = other.m_open_files[fd];
|
auto& open_file = other.m_open_files[fd];
|
||||||
|
|
||||||
auto result = BAN::RefPtr<OpenFileDescription>::create(open_file->inode, open_file->path, open_file->offset, open_file->flags);
|
VirtualFileSystem::File temp_file;
|
||||||
|
temp_file.inode = open_file->inode();
|
||||||
|
TRY(temp_file.canonical_path.append(open_file->path()));
|
||||||
|
|
||||||
|
auto result = BAN::RefPtr<OpenFileDescription>::create(BAN::move(temp_file), open_file->offset, open_file->flags);
|
||||||
|
|
||||||
if (result.is_error())
|
if (result.is_error())
|
||||||
{
|
{
|
||||||
|
@ -48,10 +52,10 @@ namespace Kernel
|
||||||
|
|
||||||
m_open_files[fd] = result.release_value();
|
m_open_files[fd] = result.release_value();
|
||||||
|
|
||||||
if (m_open_files[fd]->path == "<pipe wr>"_sv)
|
if (m_open_files[fd]->path() == "<pipe wr>"_sv)
|
||||||
{
|
{
|
||||||
ASSERT(m_open_files[fd]->inode->is_pipe());
|
ASSERT(m_open_files[fd]->inode()->is_pipe());
|
||||||
static_cast<Pipe*>(m_open_files[fd]->inode.ptr())->clone_writing();
|
static_cast<Pipe*>(m_open_files[fd]->inode().ptr())->clone_writing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +79,7 @@ namespace Kernel
|
||||||
TRY(file.inode->truncate(0));
|
TRY(file.inode->truncate(0));
|
||||||
|
|
||||||
int fd = TRY(get_free_fd());
|
int fd = TRY(get_free_fd());
|
||||||
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(file.inode, BAN::move(file.canonical_path), 0, flags));
|
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(BAN::move(file), 0, flags));
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +144,7 @@ namespace Kernel
|
||||||
auto socket = TRY(NetworkManager::get().create_socket(sock_domain, sock_type, 0777, m_credentials.euid(), m_credentials.egid()));
|
auto socket = TRY(NetworkManager::get().create_socket(sock_domain, sock_type, 0777, m_credentials.euid(), m_credentials.egid()));
|
||||||
|
|
||||||
int fd = TRY(get_free_fd());
|
int fd = TRY(get_free_fd());
|
||||||
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(socket, "<socket>"_sv, 0, O_RDWR | extra_flags));
|
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(socket, "<socket>"_sv), 0, O_RDWR | extra_flags));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,8 +153,8 @@ namespace Kernel
|
||||||
TRY(get_free_fd_pair(fds));
|
TRY(get_free_fd_pair(fds));
|
||||||
|
|
||||||
auto pipe = TRY(Pipe::create(m_credentials));
|
auto pipe = TRY(Pipe::create(m_credentials));
|
||||||
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, "<pipe rd>"_sv, 0, O_RDONLY));
|
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(pipe, "<pipe rd>"_sv), 0, O_RDONLY));
|
||||||
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, "<pipe wr>"_sv, 0, O_WRONLY));
|
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(VirtualFileSystem::File(pipe, "<pipe wr>"_sv), 0, O_WRONLY));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -162,10 +166,10 @@ namespace Kernel
|
||||||
int result = TRY(get_free_fd());
|
int result = TRY(get_free_fd());
|
||||||
m_open_files[result] = m_open_files[fildes];
|
m_open_files[result] = m_open_files[fildes];
|
||||||
|
|
||||||
if (m_open_files[result]->path == "<pipe wr>"_sv)
|
if (m_open_files[result]->path() == "<pipe wr>"_sv)
|
||||||
{
|
{
|
||||||
ASSERT(m_open_files[result]->inode->is_pipe());
|
ASSERT(m_open_files[result]->inode()->is_pipe());
|
||||||
static_cast<Pipe*>(m_open_files[result]->inode.ptr())->clone_writing();
|
static_cast<Pipe*>(m_open_files[result]->inode().ptr())->clone_writing();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -185,10 +189,10 @@ namespace Kernel
|
||||||
m_open_files[fildes2] = m_open_files[fildes];
|
m_open_files[fildes2] = m_open_files[fildes];
|
||||||
m_open_files[fildes2]->flags &= ~O_CLOEXEC;
|
m_open_files[fildes2]->flags &= ~O_CLOEXEC;
|
||||||
|
|
||||||
if (m_open_files[fildes2]->path == "<pipe wr>"_sv)
|
if (m_open_files[fildes2]->path() == "<pipe wr>"_sv)
|
||||||
{
|
{
|
||||||
ASSERT(m_open_files[fildes2]->inode->is_pipe());
|
ASSERT(m_open_files[fildes2]->inode()->is_pipe());
|
||||||
static_cast<Pipe*>(m_open_files[fildes2]->inode.ptr())->clone_writing();
|
static_cast<Pipe*>(m_open_files[fildes2]->inode().ptr())->clone_writing();
|
||||||
}
|
}
|
||||||
|
|
||||||
return fildes;
|
return fildes;
|
||||||
|
@ -234,7 +238,7 @@ namespace Kernel
|
||||||
base_offset = m_open_files[fd]->offset;
|
base_offset = m_open_files[fd]->offset;
|
||||||
break;
|
break;
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
base_offset = m_open_files[fd]->inode->size();
|
base_offset = m_open_files[fd]->inode()->size();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
@ -258,71 +262,17 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> OpenFileDescriptorSet::truncate(int fd, off_t length)
|
BAN::ErrorOr<void> OpenFileDescriptorSet::truncate(int fd, off_t length)
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
return m_open_files[fd]->inode->truncate(length);
|
return m_open_files[fd]->inode()->truncate(length);
|
||||||
}
|
|
||||||
|
|
||||||
static void read_stat_from_inode(BAN::RefPtr<Inode> inode, struct stat* out)
|
|
||||||
{
|
|
||||||
out->st_dev = inode->dev();
|
|
||||||
out->st_ino = inode->ino();
|
|
||||||
out->st_mode = inode->mode().mode;
|
|
||||||
out->st_nlink = inode->nlink();
|
|
||||||
out->st_uid = inode->uid();
|
|
||||||
out->st_gid = inode->gid();
|
|
||||||
out->st_rdev = inode->rdev();
|
|
||||||
out->st_size = inode->size();
|
|
||||||
out->st_atim = inode->atime();
|
|
||||||
out->st_mtim = inode->mtime();
|
|
||||||
out->st_ctim = inode->ctime();
|
|
||||||
out->st_blksize = inode->blksize();
|
|
||||||
out->st_blocks = inode->blocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> OpenFileDescriptorSet::fstat(int fd, struct stat* out) const
|
|
||||||
{
|
|
||||||
TRY(validate_fd(fd));
|
|
||||||
read_stat_from_inode(m_open_files[fd]->inode, out);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> OpenFileDescriptorSet::fstatat(int fd, BAN::StringView path, struct stat* out, int flag)
|
|
||||||
{
|
|
||||||
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
if (flag == AT_SYMLINK_NOFOLLOW)
|
|
||||||
flag = O_NOFOLLOW;
|
|
||||||
|
|
||||||
BAN::String absolute_path;
|
|
||||||
TRY(absolute_path.append(TRY(path_of(fd))));
|
|
||||||
TRY(absolute_path.push_back('/'));
|
|
||||||
TRY(absolute_path.append(path));
|
|
||||||
|
|
||||||
// FIXME: handle O_SEARCH in fd
|
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flag));
|
|
||||||
read_stat_from_inode(file.inode, out);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> OpenFileDescriptorSet::stat(BAN::StringView absolute_path, struct stat* out, int flag)
|
|
||||||
{
|
|
||||||
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
if (flag == AT_SYMLINK_NOFOLLOW)
|
|
||||||
flag = O_NOFOLLOW;
|
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flag));
|
|
||||||
read_stat_from_inode(file.inode, out);
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> OpenFileDescriptorSet::close(int fd)
|
BAN::ErrorOr<void> OpenFileDescriptorSet::close(int fd)
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
if (m_open_files[fd]->path == "<pipe wr>"_sv)
|
if (m_open_files[fd]->path() == "<pipe wr>"_sv)
|
||||||
{
|
{
|
||||||
ASSERT(m_open_files[fd]->inode->is_pipe());
|
ASSERT(m_open_files[fd]->inode()->is_pipe());
|
||||||
static_cast<Pipe*>(m_open_files[fd]->inode.ptr())->close_writing();
|
static_cast<Pipe*>(m_open_files[fd]->inode().ptr())->close_writing();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_open_files[fd].clear();
|
m_open_files[fd].clear();
|
||||||
|
@ -351,9 +301,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->can_read())
|
if ((open_file->flags & O_NONBLOCK) && !open_file->inode()->can_read())
|
||||||
return 0;
|
return 0;
|
||||||
size_t nread = TRY(open_file->inode->read(open_file->offset, buffer));
|
size_t nread = TRY(open_file->inode()->read(open_file->offset, buffer));
|
||||||
open_file->offset += nread;
|
open_file->offset += nread;
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
@ -362,11 +312,11 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
if ((open_file->flags & O_NONBLOCK) && !open_file->inode->can_write())
|
if ((open_file->flags & O_NONBLOCK) && !open_file->inode()->can_write())
|
||||||
return 0;
|
return 0;
|
||||||
if (open_file->flags & O_APPEND)
|
if (open_file->flags & O_APPEND)
|
||||||
open_file->offset = open_file->inode->size();
|
open_file->offset = open_file->inode()->size();
|
||||||
size_t nwrite = TRY(open_file->inode->write(open_file->offset, buffer));
|
size_t nwrite = TRY(open_file->inode()->write(open_file->offset, buffer));
|
||||||
open_file->offset += nwrite;
|
open_file->offset += nwrite;
|
||||||
return nwrite;
|
return nwrite;
|
||||||
}
|
}
|
||||||
|
@ -377,19 +327,25 @@ namespace Kernel
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
if (!(open_file->flags & O_RDONLY))
|
if (!(open_file->flags & O_RDONLY))
|
||||||
return BAN::Error::from_errno(EACCES);
|
return BAN::Error::from_errno(EACCES);
|
||||||
return TRY(open_file->inode->list_next_inodes(open_file->offset++, list, list_len));
|
return TRY(open_file->inode()->list_next_inodes(open_file->offset++, list, list_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
return TRY(m_open_files[fd]->file.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::StringView> OpenFileDescriptorSet::path_of(int fd) const
|
BAN::ErrorOr<BAN::StringView> OpenFileDescriptorSet::path_of(int fd) const
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
return m_open_files[fd]->path.sv();
|
return m_open_files[fd]->path();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> OpenFileDescriptorSet::inode_of(int fd)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> OpenFileDescriptorSet::inode_of(int fd)
|
||||||
{
|
{
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
return m_open_files[fd]->inode;
|
return m_open_files[fd]->inode();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<int> OpenFileDescriptorSet::flags_of(int fd) const
|
BAN::ErrorOr<int> OpenFileDescriptorSet::flags_of(int fd) const
|
||||||
|
|
|
@ -96,14 +96,12 @@ namespace Kernel
|
||||||
Process* Process::create_kernel()
|
Process* Process::create_kernel()
|
||||||
{
|
{
|
||||||
auto* process = create_process({ 0, 0, 0, 0 }, 0);
|
auto* process = create_process({ 0, 0, 0, 0 }, 0);
|
||||||
MUST(process->m_working_directory.push_back('/'));
|
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* Process::create_kernel(entry_t entry, void* data)
|
Process* Process::create_kernel(entry_t entry, void* data)
|
||||||
{
|
{
|
||||||
auto* process = create_process({ 0, 0, 0, 0 }, 0);
|
auto* process = create_process({ 0, 0, 0, 0 }, 0);
|
||||||
MUST(process->m_working_directory.push_back('/'));
|
|
||||||
auto* thread = MUST(Thread::create_kernel(entry, data, process));
|
auto* thread = MUST(Thread::create_kernel(entry, data, process));
|
||||||
process->add_thread(thread);
|
process->add_thread(thread);
|
||||||
process->register_to_scheduler();
|
process->register_to_scheduler();
|
||||||
|
@ -115,13 +113,15 @@ namespace Kernel
|
||||||
auto* process = create_process(credentials, 0);
|
auto* process = create_process(credentials, 0);
|
||||||
TRY(process->m_credentials.initialize_supplementary_groups());
|
TRY(process->m_credentials.initialize_supplementary_groups());
|
||||||
|
|
||||||
MUST(process->m_working_directory.push_back('/'));
|
process->m_working_directory = VirtualFileSystem::get().root_file();
|
||||||
process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace()));
|
process->m_page_table = BAN::UniqPtr<PageTable>::adopt(MUST(PageTable::create_userspace()));
|
||||||
|
|
||||||
TRY(process->m_cmdline.push_back({}));
|
TRY(process->m_cmdline.push_back({}));
|
||||||
TRY(process->m_cmdline.back().append(path));
|
TRY(process->m_cmdline.back().append(path));
|
||||||
|
|
||||||
process->m_loadable_elf = TRY(load_elf_for_exec(credentials, path, "/"_sv, process->page_table()));
|
auto absolute_path = TRY(process->absolute_path_of(path));
|
||||||
|
auto executable_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(process->m_credentials, absolute_path, O_EXEC)).inode;
|
||||||
|
process->m_loadable_elf = TRY(LibELF::LoadableELF::load_from_inode(process->page_table(), process->m_credentials, executable_inode));
|
||||||
if (!process->m_loadable_elf->is_address_space_free())
|
if (!process->m_loadable_elf->is_address_space_free())
|
||||||
{
|
{
|
||||||
dprintln("Could not load ELF address space");
|
dprintln("Could not load ELF address space");
|
||||||
|
@ -362,7 +362,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
TRY(validate_pointer_access(termios, sizeof(termios), true));
|
TRY(validate_pointer_access(termios, sizeof(struct termios), true));
|
||||||
|
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||||
if (!inode->is_tty())
|
if (!inode->is_tty())
|
||||||
|
@ -381,7 +381,7 @@ namespace Kernel
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
TRY(validate_pointer_access(termios, sizeof(termios), false));
|
TRY(validate_pointer_access(termios, sizeof(struct termios), false));
|
||||||
|
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||||
if (!inode->is_tty())
|
if (!inode->is_tty())
|
||||||
|
@ -394,26 +394,6 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<LibELF::LoadableELF>> Process::load_elf_for_exec(const Credentials& credentials, BAN::StringView file_path, const BAN::String& cwd, PageTable& page_table)
|
|
||||||
{
|
|
||||||
if (file_path.empty())
|
|
||||||
return BAN::Error::from_errno(ENOENT);
|
|
||||||
|
|
||||||
BAN::String absolute_path;
|
|
||||||
|
|
||||||
if (file_path.front() == '/')
|
|
||||||
TRY(absolute_path.append(file_path));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRY(absolute_path.append(cwd));
|
|
||||||
TRY(absolute_path.push_back('/'));
|
|
||||||
TRY(absolute_path.append(file_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(credentials, absolute_path, O_EXEC));
|
|
||||||
return TRY(LibELF::LoadableELF::load_from_inode(page_table, credentials, file.inode));
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_fork(uintptr_t sp, uintptr_t ip)
|
BAN::ErrorOr<long> Process::sys_fork(uintptr_t sp, uintptr_t ip)
|
||||||
{
|
{
|
||||||
auto page_table = BAN::UniqPtr<PageTable>::adopt(TRY(PageTable::create_userspace()));
|
auto page_table = BAN::UniqPtr<PageTable>::adopt(TRY(PageTable::create_userspace()));
|
||||||
|
@ -434,8 +414,7 @@ namespace Kernel
|
||||||
child_exit_status = &m_child_exit_statuses.back();
|
child_exit_status = &m_child_exit_statuses.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::String working_directory;
|
auto working_directory = TRY(m_working_directory.clone());
|
||||||
TRY(working_directory.append(m_working_directory));
|
|
||||||
|
|
||||||
OpenFileDescriptorSet open_file_descriptors(m_credentials);
|
OpenFileDescriptorSet open_file_descriptors(m_credentials);
|
||||||
TRY(open_file_descriptors.clone_from(m_open_file_descriptors));
|
TRY(open_file_descriptors.clone_from(m_open_file_descriptors));
|
||||||
|
@ -479,7 +458,10 @@ namespace Kernel
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
auto loadable_elf = TRY(load_elf_for_exec(m_credentials, path, m_working_directory, page_table()));
|
|
||||||
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
|
auto executable_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_EXEC)).inode;
|
||||||
|
auto loadable_elf = TRY(LibELF::LoadableELF::load_from_inode(page_table(), m_credentials, executable_inode));
|
||||||
|
|
||||||
BAN::Vector<BAN::String> str_argv;
|
BAN::Vector<BAN::String> str_argv;
|
||||||
for (int i = 0; argv && argv[i]; i++)
|
for (int i = 0; argv && argv[i]; i++)
|
||||||
|
@ -809,7 +791,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::create_file_or_dir(BAN::StringView path, mode_t mode)
|
BAN::ErrorOr<void> Process::create_file_or_dir(const VirtualFileSystem::File& parent, BAN::StringView path, mode_t mode) const
|
||||||
{
|
{
|
||||||
switch (mode & Inode::Mode::TYPE_MASK)
|
switch (mode & Inode::Mode::TYPE_MASK)
|
||||||
{
|
{
|
||||||
|
@ -821,22 +803,19 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
BAN::RefPtr<Inode> parent_inode;
|
||||||
|
BAN::StringView file_name;
|
||||||
|
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
if (auto index = path.rfind('/'); index.has_value())
|
||||||
|
{
|
||||||
size_t index;
|
parent_inode = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path.substring(0, index.value()), O_EXEC | O_WRONLY)).inode;
|
||||||
for (index = absolute_path.size(); index > 0; index--)
|
file_name = path.substring(index.value() + 1);
|
||||||
if (absolute_path[index - 1] == '/')
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
auto directory = absolute_path.sv().substring(0, index);
|
parent_inode = parent.inode;
|
||||||
auto file_name = absolute_path.sv().substring(index);
|
file_name = path;
|
||||||
|
}
|
||||||
auto parent_inode = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, directory, O_EXEC | O_WRONLY)).inode;
|
|
||||||
|
|
||||||
if (auto ret = parent_inode->find_inode(file_name); !ret.is_error())
|
|
||||||
return BAN::Error::from_errno(EEXIST);
|
|
||||||
|
|
||||||
if (Inode::Mode(mode).ifdir())
|
if (Inode::Mode(mode).ifdir())
|
||||||
TRY(parent_inode->create_directory(file_name, mode, m_credentials.euid(), parent_inode->gid()));
|
TRY(parent_inode->create_directory(file_name, mode, m_credentials.euid(), parent_inode->gid()));
|
||||||
|
@ -875,23 +854,21 @@ namespace Kernel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::open_inode(BAN::RefPtr<Inode> inode, int flags)
|
BAN::ErrorOr<long> Process::open_inode(VirtualFileSystem::File&& file, int flags)
|
||||||
{
|
{
|
||||||
ASSERT(inode);
|
ASSERT(file.inode);
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
return TRY(m_open_file_descriptors.open(VirtualFileSystem::File { .inode = inode, .canonical_path = {} }, flags));
|
return TRY(m_open_file_descriptors.open(BAN::move(file), flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::open_file(BAN::StringView path, int flags, mode_t mode)
|
BAN::ErrorOr<long> Process::open_file_impl(const VirtualFileSystem::File& parent, BAN::StringView path, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
if ((flags & (O_DIRECTORY | O_CREAT)) == (O_DIRECTORY | O_CREAT))
|
if ((flags & (O_DIRECTORY | O_CREAT)) == (O_DIRECTORY | O_CREAT))
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
BAN::String absolute_path = TRY(absolute_path_of(path));
|
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path, flags | O_NOFOLLOW);
|
||||||
|
|
||||||
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags | O_NOFOLLOW);
|
|
||||||
|
|
||||||
VirtualFileSystem::File file;
|
VirtualFileSystem::File file;
|
||||||
if (file_or_error.is_error())
|
if (file_or_error.is_error())
|
||||||
|
@ -899,9 +876,9 @@ namespace Kernel
|
||||||
if (!(flags & O_CREAT) || file_or_error.error().get_error_code() != ENOENT)
|
if (!(flags & O_CREAT) || file_or_error.error().get_error_code() != ENOENT)
|
||||||
return file_or_error.release_error();
|
return file_or_error.release_error();
|
||||||
|
|
||||||
// FIXME: There is a race condition between these lines
|
// FIXME: There is a race condition between next two lines
|
||||||
TRY(create_file_or_dir(absolute_path, (mode & 0777) | Inode::Mode::IFREG));
|
TRY(create_file_or_dir(parent, path, (mode & 0777) | Inode::Mode::IFREG));
|
||||||
file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags));
|
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path, flags));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -914,7 +891,7 @@ namespace Kernel
|
||||||
if (!file.inode->mode().ifdir() && (flags & O_DIRECTORY))
|
if (!file.inode->mode().ifdir() && (flags & O_DIRECTORY))
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (file.inode->mode().iflnk() && !(flags & O_NOFOLLOW))
|
if (file.inode->mode().iflnk() && !(flags & O_NOFOLLOW))
|
||||||
file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags));
|
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto inode = file.inode;
|
auto inode = file.inode;
|
||||||
|
@ -933,7 +910,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
return open_file(path, flags, mode);
|
if (path[0] == '/')
|
||||||
|
return open_file_impl(VirtualFileSystem::get().root_file(), path, flags, mode);
|
||||||
|
return open_file_impl(m_working_directory, path, flags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_openat(int fd, const char* path, int flags, mode_t mode)
|
BAN::ErrorOr<long> Process::sys_openat(int fd, const char* path, int flags, mode_t mode)
|
||||||
|
@ -942,10 +921,9 @@ namespace Kernel
|
||||||
|
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
|
|
||||||
BAN::String absolute_path;
|
VirtualFileSystem::File parent_file;
|
||||||
|
|
||||||
if (fd == AT_FDCWD)
|
if (fd == AT_FDCWD)
|
||||||
TRY(absolute_path.append(m_working_directory));
|
parent_file = TRY(m_working_directory.clone());
|
||||||
else if (path[0] != '/')
|
else if (path[0] != '/')
|
||||||
{
|
{
|
||||||
int flags = TRY(m_open_file_descriptors.flags_of(fd));
|
int flags = TRY(m_open_file_descriptors.flags_of(fd));
|
||||||
|
@ -953,12 +931,10 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(EBADF);
|
return BAN::Error::from_errno(EBADF);
|
||||||
if (!TRY(m_open_file_descriptors.inode_of(fd))->mode().ifdir())
|
if (!TRY(m_open_file_descriptors.inode_of(fd))->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd))));
|
parent_file = TRY(m_open_file_descriptors.file_of(fd));
|
||||||
}
|
}
|
||||||
TRY(absolute_path.push_back('/'));
|
|
||||||
TRY(absolute_path.append(path));
|
|
||||||
|
|
||||||
return open_file(absolute_path, flags, mode);
|
return open_file_impl(parent_file, path, flags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_close(int fd)
|
BAN::ErrorOr<long> Process::sys_close(int fd)
|
||||||
|
@ -1012,7 +988,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
TRY(create_file_or_dir(path, mode));
|
TRY(create_file_or_dir(VirtualFileSystem::get().root_file(), path, mode));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,7 +999,7 @@ namespace Kernel
|
||||||
BAN::StringView path_sv(path);
|
BAN::StringView path_sv(path);
|
||||||
if (!path_sv.empty() && path_sv.back() == '/')
|
if (!path_sv.empty() && path_sv.back() == '/')
|
||||||
path_sv = path_sv.substring(0, path_sv.size() - 1);
|
path_sv = path_sv.substring(0, path_sv.size() - 1);
|
||||||
TRY(create_file_or_dir(path_sv, Inode::Mode::IFDIR | mode));
|
TRY(create_file_or_dir(VirtualFileSystem::get().root_file(), path_sv, Inode::Mode::IFDIR | mode));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,10 +1023,8 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::readlink_impl(BAN::StringView absolute_path, char* buffer, size_t bufsize)
|
BAN::ErrorOr<long> Process::readlink_impl(BAN::RefPtr<Inode> inode, char* buffer, size_t bufsize)
|
||||||
{
|
{
|
||||||
auto inode = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_NOFOLLOW | O_RDONLY)).inode;
|
|
||||||
|
|
||||||
// FIXME: no allocation needed
|
// FIXME: no allocation needed
|
||||||
auto link_target = TRY(inode->link_target());
|
auto link_target = TRY(inode->link_target());
|
||||||
|
|
||||||
|
@ -1067,8 +1041,8 @@ namespace Kernel
|
||||||
TRY(validate_pointer_access(buffer, bufsize, true));
|
TRY(validate_pointer_access(buffer, bufsize, true));
|
||||||
|
|
||||||
auto absolute_path = TRY(absolute_path_of(path));
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
|
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_NOFOLLOW | O_RDONLY));
|
||||||
return readlink_impl(absolute_path.sv(), buffer, bufsize);
|
return readlink_impl(file.inode, buffer, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
|
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
|
||||||
|
@ -1077,15 +1051,9 @@ namespace Kernel
|
||||||
TRY(validate_string_access(path));
|
TRY(validate_string_access(path));
|
||||||
TRY(validate_pointer_access(buffer, bufsize, true));
|
TRY(validate_pointer_access(buffer, bufsize, true));
|
||||||
|
|
||||||
// FIXME: handle O_SEARCH in fd
|
auto parent_file = TRY(m_open_file_descriptors.file_of(fd));
|
||||||
auto parent_path = TRY(m_open_file_descriptors.path_of(fd));
|
auto file = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, O_NOFOLLOW | O_RDONLY));
|
||||||
|
return readlink_impl(file.inode, buffer, bufsize);
|
||||||
BAN::String absolute_path;
|
|
||||||
TRY(absolute_path.append(parent_path));
|
|
||||||
TRY(absolute_path.push_back('/'));
|
|
||||||
TRY(absolute_path.append(path));
|
|
||||||
|
|
||||||
return readlink_impl(absolute_path.sv(), buffer, bufsize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
||||||
|
@ -1461,27 +1429,62 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void read_stat_from_inode(BAN::RefPtr<Inode> inode, struct stat* out)
|
||||||
|
{
|
||||||
|
out->st_dev = inode->dev();
|
||||||
|
out->st_ino = inode->ino();
|
||||||
|
out->st_mode = inode->mode().mode;
|
||||||
|
out->st_nlink = inode->nlink();
|
||||||
|
out->st_uid = inode->uid();
|
||||||
|
out->st_gid = inode->gid();
|
||||||
|
out->st_rdev = inode->rdev();
|
||||||
|
out->st_size = inode->size();
|
||||||
|
out->st_atim = inode->atime();
|
||||||
|
out->st_mtim = inode->mtime();
|
||||||
|
out->st_ctim = inode->ctime();
|
||||||
|
out->st_blksize = inode->blksize();
|
||||||
|
out->st_blocks = inode->blocks();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* buf)
|
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* buf)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
||||||
TRY(m_open_file_descriptors.fstat(fd, buf));
|
|
||||||
|
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||||
|
read_stat_from_inode(inode, buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_fstatat(int fd, const char* path, struct stat* buf, int flag)
|
BAN::ErrorOr<long> Process::sys_fstatat(int fd, const char* path, struct stat* buf, int flags)
|
||||||
{
|
{
|
||||||
|
if (flags & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if (flags == AT_SYMLINK_NOFOLLOW)
|
||||||
|
flags = O_NOFOLLOW;
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
||||||
TRY(m_open_file_descriptors.fstatat(fd, path, buf, flag));
|
|
||||||
|
auto parent_file = TRY(m_open_file_descriptors.file_of(fd));
|
||||||
|
auto inode = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags)).inode;
|
||||||
|
read_stat_from_inode(inode, buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_stat(const char* path, struct stat* buf, int flag)
|
BAN::ErrorOr<long> Process::sys_stat(const char* path, struct stat* buf, int flags)
|
||||||
{
|
{
|
||||||
|
if (flags & ~AT_SYMLINK_NOFOLLOW)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
if (flags == AT_SYMLINK_NOFOLLOW)
|
||||||
|
flags = O_NOFOLLOW;
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
TRY(validate_pointer_access(buf, sizeof(struct stat), true));
|
||||||
TRY(m_open_file_descriptors.stat(TRY(absolute_path_of(path)), buf, flag));
|
|
||||||
|
auto absolute_path = TRY(absolute_path_of(path));
|
||||||
|
auto inode = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags)).inode;
|
||||||
|
read_stat_from_inode(inode, buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1561,7 +1564,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
m_working_directory = BAN::move(file.canonical_path);
|
m_working_directory = BAN::move(file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1572,11 +1575,11 @@ namespace Kernel
|
||||||
|
|
||||||
TRY(validate_pointer_access(buffer, size, true));
|
TRY(validate_pointer_access(buffer, size, true));
|
||||||
|
|
||||||
if (size < m_working_directory.size() + 1)
|
if (size < m_working_directory.canonical_path.size() + 1)
|
||||||
return BAN::Error::from_errno(ERANGE);
|
return BAN::Error::from_errno(ERANGE);
|
||||||
|
|
||||||
memcpy(buffer, m_working_directory.data(), m_working_directory.size());
|
memcpy(buffer, m_working_directory.canonical_path.data(), m_working_directory.canonical_path.size());
|
||||||
buffer[m_working_directory.size()] = '\0';
|
buffer[m_working_directory.canonical_path.size()] = '\0';
|
||||||
|
|
||||||
return (long)buffer;
|
return (long)buffer;
|
||||||
}
|
}
|
||||||
|
@ -2332,11 +2335,11 @@ namespace Kernel
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
if (path.empty() || path == "."_sv)
|
if (path.empty() || path == "."_sv)
|
||||||
return m_working_directory;
|
return m_working_directory.canonical_path;
|
||||||
|
|
||||||
BAN::String absolute_path;
|
BAN::String absolute_path;
|
||||||
if (path.front() != '/')
|
if (path.front() != '/')
|
||||||
TRY(absolute_path.append(m_working_directory));
|
TRY(absolute_path.append(m_working_directory.canonical_path));
|
||||||
|
|
||||||
if (!absolute_path.empty() && absolute_path.back() != '/')
|
if (!absolute_path.empty() && absolute_path.back() != '/')
|
||||||
TRY(absolute_path.push_back('/'));
|
TRY(absolute_path.push_back('/'));
|
||||||
|
|
|
@ -222,6 +222,9 @@ namespace Kernel
|
||||||
case LibInput::Key::Escape:
|
case LibInput::Key::Escape:
|
||||||
ansi_c_str = "\e";
|
ansi_c_str = "\e";
|
||||||
break;
|
break;
|
||||||
|
case LibInput::Key::Delete:
|
||||||
|
ansi_c_str = "\x7F";
|
||||||
|
break;
|
||||||
case LibInput::Key::ArrowUp:
|
case LibInput::Key::ArrowUp:
|
||||||
ansi_c_str = "\e[A";
|
ansi_c_str = "\e[A";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -24,10 +22,10 @@ static int last_return = 0;
|
||||||
|
|
||||||
static BAN::String hostname;
|
static BAN::String hostname;
|
||||||
|
|
||||||
static void clean_exit()
|
static void clean_exit(int exit_code)
|
||||||
{
|
{
|
||||||
tcsetattr(0, TCSANOW, &old_termios);
|
tcsetattr(0, TCSANOW, &old_termios);
|
||||||
exit(0);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::Vector<BAN::Vector<BAN::String>> parse_command(BAN::StringView);
|
BAN::Vector<BAN::Vector<BAN::String>> parse_command(BAN::StringView);
|
||||||
|
@ -308,7 +306,7 @@ BAN::Optional<int> execute_builtin(BAN::Vector<BAN::String>& args, int fd_in, in
|
||||||
}
|
}
|
||||||
else if (args.front() == "exit"_sv)
|
else if (args.front() == "exit"_sv)
|
||||||
{
|
{
|
||||||
clean_exit();
|
clean_exit(0);
|
||||||
}
|
}
|
||||||
else if (args.front() == "export"_sv)
|
else if (args.front() == "export"_sv)
|
||||||
{
|
{
|
||||||
|
@ -353,187 +351,6 @@ BAN::Optional<int> execute_builtin(BAN::Vector<BAN::String>& args, int fd_in, in
|
||||||
execl("/bin/Terminal", "Terminal", NULL);
|
execl("/bin/Terminal", "Terminal", NULL);
|
||||||
waitpid(pid, nullptr, 0);
|
waitpid(pid, nullptr, 0);
|
||||||
}
|
}
|
||||||
else if (args.front() == "page-fault-test"_sv)
|
|
||||||
{
|
|
||||||
volatile int* ptr = nullptr;
|
|
||||||
*ptr = 0;
|
|
||||||
}
|
|
||||||
else if (args.front() == "kill-test"_sv)
|
|
||||||
{
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0)
|
|
||||||
{
|
|
||||||
fprintf(fout, "child\n");
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
if (pid == -1)
|
|
||||||
{
|
|
||||||
perror("fork");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
if (kill(pid, SIGSEGV) == -1)
|
|
||||||
{
|
|
||||||
perror("kill");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args.front() == "signal-test"_sv)
|
|
||||||
{
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0)
|
|
||||||
{
|
|
||||||
dup2(fileno(fout), STDOUT_FILENO);
|
|
||||||
if (signal(SIGSEGV, [](int) { printf("SIGSEGV\n"); }) == SIG_ERR)
|
|
||||||
{
|
|
||||||
perror("signal");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
printf("child\n");
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
if (pid == -1)
|
|
||||||
{
|
|
||||||
perror("fork");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
if (kill(pid, SIGSEGV) == -1)
|
|
||||||
{
|
|
||||||
perror("kill");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
if (kill(pid, SIGTERM) == -1)
|
|
||||||
{
|
|
||||||
perror("kill");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (args.front() == "printf-test"_sv)
|
|
||||||
{
|
|
||||||
fprintf(fout, " 0.0: %f\n", 0.0f);
|
|
||||||
fprintf(fout, " 123.0: %f\n", 123.0f);
|
|
||||||
fprintf(fout, " 0.123: %f\n", 0.123f);
|
|
||||||
fprintf(fout, " NAN: %f\n", NAN);
|
|
||||||
fprintf(fout, "+INF: %f\n", INFINITY);
|
|
||||||
fprintf(fout, "-INF: %f\n", -INFINITY);
|
|
||||||
}
|
|
||||||
else if (args.front() == "cd"_sv)
|
|
||||||
{
|
|
||||||
if (args.size() > 2)
|
|
||||||
{
|
|
||||||
fprintf(fout, "cd: too many arguments\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::StringView path;
|
|
||||||
|
|
||||||
if (args.size() == 1)
|
|
||||||
{
|
|
||||||
if (const char* path_env = getenv("HOME"))
|
|
||||||
path = path_env;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
path = args[1];
|
|
||||||
|
|
||||||
if (chdir(path.data()) == -1)
|
|
||||||
ERROR_RETURN("chdir", 1);
|
|
||||||
}
|
|
||||||
else if (args.front() == "time"_sv)
|
|
||||||
{
|
|
||||||
args.remove(0);
|
|
||||||
|
|
||||||
timespec start, end;
|
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
|
|
||||||
ERROR_RETURN("clock_gettime", 1);
|
|
||||||
|
|
||||||
int ret = execute_command(args, fd_in, fd_out);
|
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &end) == -1)
|
|
||||||
ERROR_RETURN("clock_gettime", 1);
|
|
||||||
|
|
||||||
uint64_t total_ns = 0;
|
|
||||||
total_ns += (end.tv_sec - start.tv_sec) * 1'000'000'000;
|
|
||||||
total_ns += end.tv_nsec - start.tv_nsec;
|
|
||||||
|
|
||||||
int secs = total_ns / 1'000'000'000;
|
|
||||||
int msecs = (total_ns % 1'000'000'000) / 1'000'000;
|
|
||||||
|
|
||||||
fprintf(fout, "took %d.%03d s\n", secs, msecs);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else if (args.front() == "test-strtox")
|
|
||||||
{
|
|
||||||
#define TEST(num, base) do { errno = 0; printf("strtol(\"" num "\", nullptr, " #base ") = %ld ", strtol(num, nullptr, base)); puts(errno ? strerrorname_np(errno) : ""); } while (false)
|
|
||||||
TEST("0", 10);
|
|
||||||
TEST("", 10);
|
|
||||||
TEST("+", 10);
|
|
||||||
TEST("123", 10);
|
|
||||||
TEST("-123", 10);
|
|
||||||
TEST("7fffffffffffffff", 10);
|
|
||||||
TEST("7fffffffffffffff", 16);
|
|
||||||
TEST("8000000000000000", 16);
|
|
||||||
TEST("-8000000000000000", 16);
|
|
||||||
TEST("-8000000000000001", 16);
|
|
||||||
TEST("123", 0);
|
|
||||||
TEST("0123", 0);
|
|
||||||
TEST("0x123", 0);
|
|
||||||
TEST("123", 1);
|
|
||||||
TEST("hello", 10);
|
|
||||||
TEST("hello", 36);
|
|
||||||
#undef TEST
|
|
||||||
#define TEST(num, base) do { errno = 0; printf("strtoul(\"" num "\", nullptr, " #base ") = %lu ", strtoul(num, nullptr, base)); puts(errno ? strerrorname_np(errno) : ""); } while (false)
|
|
||||||
TEST("0", 10);
|
|
||||||
TEST("123", 10);
|
|
||||||
TEST("-123", 10);
|
|
||||||
TEST("-1", 10);
|
|
||||||
TEST("fffffffffffffff", 16);
|
|
||||||
TEST("ffffffffffffffff", 16);
|
|
||||||
TEST("10000000000000000", 16);
|
|
||||||
#undef TEST
|
|
||||||
#if __enable_sse
|
|
||||||
#define TEST(num) do { errno = 0; printf("strtod(\"" num "\", nullptr) = %e ", strtod(num, nullptr)); puts(errno ? strerrorname_np(errno) : ""); } while (false)
|
|
||||||
TEST("0");
|
|
||||||
TEST(".1");
|
|
||||||
TEST("1.");
|
|
||||||
TEST("0x.1");
|
|
||||||
TEST("0x1.");
|
|
||||||
TEST("123");
|
|
||||||
TEST("-123");
|
|
||||||
TEST("0x123");
|
|
||||||
TEST("123.456");
|
|
||||||
TEST("-123.456");
|
|
||||||
TEST("1.2e5");
|
|
||||||
TEST("1.e5");
|
|
||||||
TEST(".2e5");
|
|
||||||
TEST("0x1.2p5");
|
|
||||||
TEST("0x1.p5");
|
|
||||||
TEST("0x.2p5");
|
|
||||||
TEST("1e999");
|
|
||||||
TEST("-1e999");
|
|
||||||
TEST("1e308");
|
|
||||||
TEST("1e-307");
|
|
||||||
TEST("1e309");
|
|
||||||
TEST("1e-308");
|
|
||||||
TEST("0.00000000001e312");
|
|
||||||
TEST("1000000000000e-312");
|
|
||||||
TEST("0e999");
|
|
||||||
TEST("0e-999");
|
|
||||||
TEST("1237754.446f");
|
|
||||||
TEST("inf");
|
|
||||||
TEST("-inf");
|
|
||||||
TEST("nan");
|
|
||||||
#undef TEST
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
|
@ -916,7 +733,7 @@ int prompt_length()
|
||||||
void print_prompt()
|
void print_prompt()
|
||||||
{
|
{
|
||||||
auto prompt = get_prompt();
|
auto prompt = get_prompt();
|
||||||
fprintf(stdout, "%.*s", (int)prompt.size(), prompt.data());
|
printf("%.*s", (int)prompt.size(), prompt.data());
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,13 +795,19 @@ int main(int argc, char** argv)
|
||||||
int chi = getchar();
|
int chi = getchar();
|
||||||
if (chi == EOF)
|
if (chi == EOF)
|
||||||
{
|
{
|
||||||
if (errno == EINTR)
|
if (errno != EINTR)
|
||||||
{
|
{
|
||||||
clearerr(stdin);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
perror("getchar");
|
perror("getchar");
|
||||||
return 1;
|
clean_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearerr(stdin);
|
||||||
|
buffers = history;
|
||||||
|
MUST(buffers.emplace_back(""_sv));
|
||||||
|
col = 0;
|
||||||
|
putchar('\n');
|
||||||
|
print_prompt();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ch = chi;
|
uint8_t ch = chi;
|
||||||
|
@ -995,11 +818,11 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
ASSERT((ch & 0xC0) == 0x80);
|
ASSERT((ch & 0xC0) == 0x80);
|
||||||
|
|
||||||
fputc(ch, stdout);
|
putchar(ch);
|
||||||
MUST(buffers[index].insert(ch, col++));
|
MUST(buffers[index].insert(ch, col++));
|
||||||
if (waiting_utf8 == 0)
|
if (waiting_utf8 == 0)
|
||||||
{
|
{
|
||||||
fprintf(stdout, "\e[s%s\e[u", buffers[index].data() + col);
|
printf("\e[s%s\e[u", buffers[index].data() + col);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -1015,7 +838,7 @@ int main(int argc, char** argv)
|
||||||
else
|
else
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
fputc(ch, stdout);
|
putchar(ch);
|
||||||
MUST(buffers[index].insert(ch, col++));
|
MUST(buffers[index].insert(ch, col++));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1029,18 +852,18 @@ int main(int argc, char** argv)
|
||||||
ch = getchar();
|
ch = getchar();
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case 'A': if (index > 0) { index--; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length() + 1, buffers[index].data()); fflush(stdout); } break;
|
case 'A': if (index > 0) { index--; col = buffers[index].size(); printf("\e[%dG%s\e[K", prompt_length() + 1, buffers[index].data()); fflush(stdout); } break;
|
||||||
case 'B': if (index < buffers.size() - 1) { index++; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length() + 1, buffers[index].data()); fflush(stdout); } break;
|
case 'B': if (index < buffers.size() - 1) { index++; col = buffers[index].size(); printf("\e[%dG%s\e[K", prompt_length() + 1, buffers[index].data()); fflush(stdout); } break;
|
||||||
case 'C': if (col < buffers[index].size()) { col++; while ((buffers[index][col - 1] & 0xC0) == 0x80) col++; fprintf(stdout, "\e[C"); fflush(stdout); } break;
|
case 'C': if (col < buffers[index].size()) { col++; while ((buffers[index][col - 1] & 0xC0) == 0x80) col++; printf("\e[C"); fflush(stdout); } break;
|
||||||
case 'D': if (col > 0) { while ((buffers[index][col - 1] & 0xC0) == 0x80) col--; col--; fprintf(stdout, "\e[D"); fflush(stdout); } break;
|
case 'D': if (col > 0) { while ((buffers[index][col - 1] & 0xC0) == 0x80) col--; col--; printf("\e[D"); fflush(stdout); } break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\x0C': // ^L
|
case '\x0C': // ^L
|
||||||
{
|
{
|
||||||
int x = prompt_length() + character_length(buffers[index].sv().substring(col)) + 1;
|
int x = prompt_length() + character_length(buffers[index].sv().substring(col)) + 1;
|
||||||
fprintf(stdout, "\e[H\e[J");
|
printf("\e[H\e[J");
|
||||||
print_prompt();
|
print_prompt();
|
||||||
fprintf(stdout, "%s\e[u\e[1;%dH", buffers[index].data(), x);
|
printf("%s\e[u\e[1;%dH", buffers[index].data(), x);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1050,27 +873,37 @@ int main(int argc, char** argv)
|
||||||
while ((buffers[index][col - 1] & 0xC0) == 0x80)
|
while ((buffers[index][col - 1] & 0xC0) == 0x80)
|
||||||
buffers[index].remove(--col);
|
buffers[index].remove(--col);
|
||||||
buffers[index].remove(--col);
|
buffers[index].remove(--col);
|
||||||
fprintf(stdout, "\b\e[s%s \e[u", buffers[index].data() + col);
|
printf("\b\e[s%s \e[u", buffers[index].data() + col);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\x01': // ^A
|
case '\x01': // ^A
|
||||||
col = 0;
|
col = 0;
|
||||||
fprintf(stdout, "\e[%dG", prompt_length() + 1);
|
printf("\e[%dG", prompt_length() + 1);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
break;
|
break;
|
||||||
case '\x03': // ^C
|
case '\x03': // ^C
|
||||||
fputc('\n', stdout);
|
putchar('\n');
|
||||||
print_prompt();
|
print_prompt();
|
||||||
buffers[index].clear();
|
buffers[index].clear();
|
||||||
col = 0;
|
col = 0;
|
||||||
break;
|
break;
|
||||||
case '\x04': // ^D
|
case '\x04': // ^D
|
||||||
fprintf(stdout, "\n");
|
putchar('\n');
|
||||||
clean_exit();
|
clean_exit(0);
|
||||||
|
break;
|
||||||
|
case '\x7F': // delete
|
||||||
|
if (col < buffers[index].size())
|
||||||
|
{
|
||||||
|
buffers[index].remove(col);
|
||||||
|
while (col < buffers[index].size() && (buffers[index][col] & 0xC0) == 0x80)
|
||||||
|
buffers[index].remove(col);
|
||||||
|
printf("\e[s%s \e[u", buffers[index].data() + col);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
fputc('\n', stdout);
|
putchar('\n');
|
||||||
if (!buffers[index].empty())
|
if (!buffers[index].empty())
|
||||||
{
|
{
|
||||||
last_return = parse_and_execute_command(buffers[index]);
|
last_return = parse_and_execute_command(buffers[index]);
|
||||||
|
@ -1088,13 +921,13 @@ int main(int argc, char** argv)
|
||||||
default:
|
default:
|
||||||
MUST(buffers[index].insert(ch, col++));
|
MUST(buffers[index].insert(ch, col++));
|
||||||
if (col == buffers[index].size())
|
if (col == buffers[index].size())
|
||||||
fputc(ch, stdout);
|
putchar(ch);
|
||||||
else
|
else
|
||||||
fprintf(stdout, "%c\e[s%s\e[u", ch, buffers[index].data() + col);
|
printf("%c\e[s%s\e[u", ch, buffers[index].data() + col);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clean_exit();
|
clean_exit(0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue