Compare commits
26 Commits
72b8ebe02c
...
9de4b392a2
Author | SHA1 | Date | |
---|---|---|---|
9de4b392a2 | |||
072b13b023 | |||
ee3319e717 | |||
22b512d7aa | |||
6be0ff8784 | |||
4a1a440f88 | |||
b2665ad8d9 | |||
b2446291d5 | |||
33931a50a0 | |||
cf4184df9b | |||
734e592ac6 | |||
d647462500 | |||
439a635d40 | |||
10e3c83dff | |||
8f21e14889 | |||
6d27aaa8ea | |||
3fef0a852e | |||
303eab4f56 | |||
02b5830e4b | |||
63a62eb820 | |||
faf0a894bd | |||
ed3ddb77e0 | |||
8e272110cd | |||
8f4f451aaa | |||
202623a54e | |||
4ac9dec228 |
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -13,16 +13,5 @@
|
|||||||
"files.trimFinalNewlines": true,
|
"files.trimFinalNewlines": true,
|
||||||
"files.insertFinalNewline": true,
|
"files.insertFinalNewline": true,
|
||||||
"git.inputValidationLength": 72,
|
"git.inputValidationLength": 72,
|
||||||
"git.inputValidationSubjectLength": 72,
|
"git.inputValidationSubjectLength": 72
|
||||||
"doxdocgen.file.fileOrder": [
|
|
||||||
"file",
|
|
||||||
"author",
|
|
||||||
"brief",
|
|
||||||
"empty",
|
|
||||||
"copyright",
|
|
||||||
"empty"
|
|
||||||
],
|
|
||||||
"doxdocgen.file.copyrightTag": [
|
|
||||||
"@copyright Copyright (c) {year}, the Luna authors."
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
FILE* g_init_log;
|
FILE* g_init_log;
|
||||||
@ -96,7 +97,8 @@ static Result<void> try_start_service(Service& service)
|
|||||||
fprintf(g_init_log, "[init] waiting for child process %d to finish\n", pid);
|
fprintf(g_init_log, "[init] waiting for child process %d to finish\n", pid);
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
TRY(os::Process::wait(pid, &status));
|
pid_t id = waitpid(pid, &status, 0);
|
||||||
|
if (id < 0) { return err(errno); }
|
||||||
|
|
||||||
fprintf(g_init_log, "[init] child process %d exited with code %d\n", pid, WEXITSTATUS(status));
|
fprintf(g_init_log, "[init] child process %d exited with code %d\n", pid, WEXITSTATUS(status));
|
||||||
}
|
}
|
||||||
@ -310,10 +312,7 @@ int main()
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
auto rc = os::Process::wait(os::Process::ANY_CHILD, &status);
|
pid_t child = wait(&status);
|
||||||
if (rc.has_error()) continue;
|
|
||||||
|
|
||||||
pid_t child = rc.release_value();
|
|
||||||
|
|
||||||
for (auto& service : g_services)
|
for (auto& service : g_services)
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using os::File;
|
using os::File;
|
||||||
@ -117,7 +118,11 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
if (child == 0) { TRY(execute_command(cmd.view())); }
|
if (child == 0) { TRY(execute_command(cmd.view())); }
|
||||||
|
|
||||||
TRY(os::Process::wait(child, nullptr));
|
if (waitpid(child, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
perror("waitpid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <os/Process.h>
|
#include <os/Process.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
Result<int> luna_main(int argc, char** argv)
|
Result<int> luna_main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@ -22,7 +23,11 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(os::Process::wait(pid, nullptr));
|
if (waitpid(pid, nullptr, 0) < 0)
|
||||||
|
{
|
||||||
|
perror("waitpid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct rusage usage;
|
struct rusage usage;
|
||||||
if (getrusage(RUSAGE_CHILDREN, &usage) < 0)
|
if (getrusage(RUSAGE_CHILDREN, &usage) < 0)
|
||||||
|
@ -25,7 +25,6 @@ set(FREESTANDING_SOURCES
|
|||||||
src/PathParser.cpp
|
src/PathParser.cpp
|
||||||
src/UBSAN.cpp
|
src/UBSAN.cpp
|
||||||
src/Base64.cpp
|
src/Base64.cpp
|
||||||
src/Hash.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <luna/CString.h>
|
|
||||||
#include <luna/Types.h>
|
|
||||||
|
|
||||||
u64 hash_memory(const void* mem, usize size, u64 salt);
|
|
||||||
|
|
||||||
template <typename T> u64 hash(const T& value, u64 salt)
|
|
||||||
{
|
|
||||||
return hash_memory(&value, sizeof(value), salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> u64 hash(const char* const& value, u64 salt);
|
|
||||||
|
|
||||||
template <typename T> static void swap(T* a, T* b)
|
|
||||||
{
|
|
||||||
char* x = (char*)a;
|
|
||||||
char* y = (char*)b;
|
|
||||||
|
|
||||||
usize size = sizeof(T);
|
|
||||||
|
|
||||||
while (size--)
|
|
||||||
{
|
|
||||||
char t = *x;
|
|
||||||
*x = *y;
|
|
||||||
*y = t;
|
|
||||||
x += 1;
|
|
||||||
y += 1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <luna/Hash.h>
|
|
||||||
#include <luna/Heap.h>
|
|
||||||
#include <luna/Option.h>
|
|
||||||
|
|
||||||
template <typename T> class HashTable
|
|
||||||
{
|
|
||||||
static constexpr usize GROW_RATE = 2;
|
|
||||||
static constexpr usize GROW_FACTOR = 16;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Result<bool> try_set(const T& value)
|
|
||||||
{
|
|
||||||
T copy { value };
|
|
||||||
return try_set(move(copy));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<bool> try_set(T&& value)
|
|
||||||
{
|
|
||||||
if (should_grow()) TRY(rehash(m_capacity + GROW_FACTOR));
|
|
||||||
|
|
||||||
u64 index = hash(value, m_salt) % m_capacity;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
auto& bucket = m_buckets[index];
|
|
||||||
if (bucket.has_value())
|
|
||||||
{
|
|
||||||
if (*bucket == value) return false;
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bucket = { move(value) };
|
|
||||||
m_size++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* try_find(const T& value)
|
|
||||||
{
|
|
||||||
if (!m_size) return nullptr;
|
|
||||||
|
|
||||||
check(m_capacity);
|
|
||||||
|
|
||||||
const u64 index = hash(value, m_salt) % m_capacity;
|
|
||||||
usize i = index;
|
|
||||||
|
|
||||||
do {
|
|
||||||
auto& bucket = m_buckets[index];
|
|
||||||
if (bucket.has_value())
|
|
||||||
{
|
|
||||||
if (*bucket == value) return bucket.value_ptr();
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
} while (i != index);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool try_remove(const T& value)
|
|
||||||
{
|
|
||||||
if (!m_size) return false;
|
|
||||||
|
|
||||||
check(m_capacity);
|
|
||||||
|
|
||||||
const u64 index = hash(value, m_salt) % m_capacity;
|
|
||||||
usize i = index;
|
|
||||||
|
|
||||||
do {
|
|
||||||
auto& bucket = m_buckets[index];
|
|
||||||
if (bucket.has_value())
|
|
||||||
{
|
|
||||||
if (*bucket == value)
|
|
||||||
{
|
|
||||||
bucket = {};
|
|
||||||
m_size--;
|
|
||||||
if (i != index) rehash(m_capacity);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} while (i != index);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
for (usize i = 0; i < m_capacity; i++) m_buckets[i].~Option();
|
|
||||||
|
|
||||||
free_impl(m_buckets);
|
|
||||||
m_capacity = m_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HashTable()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool should_grow()
|
|
||||||
{
|
|
||||||
return (m_capacity == 0) || ((m_size * GROW_RATE) >= m_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> rehash(usize new_capacity)
|
|
||||||
{
|
|
||||||
HashTable<T> new_table;
|
|
||||||
TRY(new_table.initialize(new_capacity));
|
|
||||||
|
|
||||||
if (m_capacity != 0)
|
|
||||||
{
|
|
||||||
for (usize i = 0; i < m_capacity; i++)
|
|
||||||
{
|
|
||||||
auto& opt = m_buckets[i];
|
|
||||||
if (opt.has_value())
|
|
||||||
{
|
|
||||||
auto value = opt.release_value();
|
|
||||||
TRY(new_table.try_set(move(value)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
swap(this, &new_table);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> initialize(usize initial_capacity)
|
|
||||||
{
|
|
||||||
check(m_buckets == nullptr);
|
|
||||||
m_capacity = initial_capacity;
|
|
||||||
m_buckets = (Option<T>*)TRY(calloc_impl(initial_capacity, sizeof(Option<T>), false));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Option<T>* m_buckets { nullptr };
|
|
||||||
usize m_capacity { 0 };
|
|
||||||
usize m_size { 0 };
|
|
||||||
// FIXME: Randomize this to protect against hash table attacks.
|
|
||||||
u64 m_salt { 0 };
|
|
||||||
};
|
|
@ -15,7 +15,12 @@ template <typename T> class Vector
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(const Vector<T>& other) = delete;
|
Vector(const Vector<T>& other)
|
||||||
|
{
|
||||||
|
reserve(other.capacity());
|
||||||
|
memcpy(m_data, other.data(), other.size());
|
||||||
|
m_size = other.size();
|
||||||
|
}
|
||||||
|
|
||||||
Vector(Vector<T>&& other)
|
Vector(Vector<T>&& other)
|
||||||
{
|
{
|
||||||
@ -27,7 +32,18 @@ template <typename T> class Vector
|
|||||||
other.m_data = nullptr;
|
other.m_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<T>& operator=(const Vector<T>& other) = delete;
|
Vector<T>& operator=(const Vector<T>& other)
|
||||||
|
{
|
||||||
|
if (&other == this) return *this;
|
||||||
|
|
||||||
|
if (m_data) clear();
|
||||||
|
|
||||||
|
reserve(other.capacity());
|
||||||
|
for (usize i = 0; i < other.size(); i++) { new (&m_data[i]) T(other.m_data[i]); }
|
||||||
|
m_size = other.size();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Vector<T>& operator=(Vector<T>&& other)
|
Vector<T>& operator=(Vector<T>&& other)
|
||||||
{
|
{
|
||||||
@ -201,35 +217,6 @@ template <typename T> class Vector
|
|||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Vector<T>> shallow_copy()
|
|
||||||
{
|
|
||||||
Vector<T> other;
|
|
||||||
TRY(other.try_reserve(m_capacity));
|
|
||||||
memcpy(other.m_data, m_data, m_size);
|
|
||||||
other.m_size = m_size;
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Vector<T>> deep_copy()
|
|
||||||
{
|
|
||||||
Vector<T> other;
|
|
||||||
TRY(other.try_reserve(m_capacity));
|
|
||||||
for (usize i = 0; i < m_size; i++) { TRY(other.try_append(m_data[i])); }
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Vector<T>> deep_copy(Result<T> (*copy_function)(const T&))
|
|
||||||
{
|
|
||||||
Vector<T> other;
|
|
||||||
TRY(other.try_reserve(m_capacity));
|
|
||||||
for (usize i = 0; i < m_size; i++)
|
|
||||||
{
|
|
||||||
auto copy = TRY(copy_function(m_data[i]));
|
|
||||||
TRY(other.try_append(move(copy)));
|
|
||||||
}
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* m_data { nullptr };
|
T* m_data { nullptr };
|
||||||
usize m_capacity { 0 };
|
usize m_capacity { 0 };
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#include <luna/Hash.h>
|
|
||||||
|
|
||||||
u64 hash_memory(const void* mem, usize size, u64 salt)
|
|
||||||
{
|
|
||||||
const char* p = (const char*)mem;
|
|
||||||
u64 h = salt;
|
|
||||||
while (--size) h = h * 101 + (u64)*p++;
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> u64 hash(const char* const& value, u64 salt)
|
|
||||||
{
|
|
||||||
return hash_memory(value, strlen(value), salt);
|
|
||||||
}
|
|
@ -1,173 +1,46 @@
|
|||||||
/**
|
|
||||||
* @file ArgumentParser.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Command-line argument parser.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/StringView.h>
|
#include <luna/StringView.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief A simple command-line argument parser.
|
|
||||||
*/
|
|
||||||
class ArgumentParser
|
class ArgumentParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Construct a new ArgumentParser object.
|
|
||||||
*/
|
|
||||||
ArgumentParser();
|
ArgumentParser();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add a description for this command-line utility (shown in the help text).
|
|
||||||
*
|
|
||||||
* @param description The description to use.
|
|
||||||
*/
|
|
||||||
void add_description(StringView description);
|
void add_description(StringView description);
|
||||||
|
|
||||||
/**
|
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
|
||||||
* @brief Register a new positional argument.
|
|
||||||
*
|
|
||||||
* @param out The variable where the argument's value will be stored.
|
|
||||||
* @param name The positional argument's name.
|
|
||||||
* @param fallback The value to use if the user does not provide one.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
|
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register a new positional argument.
|
|
||||||
*
|
|
||||||
* @param out The variable where the argument's value will be stored.
|
|
||||||
* @param name The positional argument's name.
|
|
||||||
* @param required Whether the user must enter a value for this argument. If this is false and the user does not
|
|
||||||
* enter a value, out will be set to an empty string.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register a new switch argument.
|
|
||||||
*
|
|
||||||
* @param out This variable will be set to true if the user provides the switch argument on the command
|
|
||||||
* line.
|
|
||||||
* @param short_flag The short flag to use for this argument, excluding the '-' prefix: an option '-c' would be
|
|
||||||
* passed as 'c'. Can only be a single ASCII character. If you do not wish this argument to have a short flag,
|
|
||||||
* use the space character: ' '.
|
|
||||||
* @param long_flag The long flag to use for this argument, excluding the '--' prefix: an option '--example'
|
|
||||||
* would be passed as 'example'. Can be a string of any length. If you do not wish this argument to have a long
|
|
||||||
* flag, use an empty string: "".
|
|
||||||
* @param help The help text to show for this argument (optional).
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag, StringView help = {});
|
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag, StringView help = {});
|
||||||
|
|
||||||
/**
|
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required,
|
||||||
* @brief Register a new value argument.
|
StringView help = {});
|
||||||
*
|
|
||||||
* @param out The variable where the argument's value will be stored.
|
|
||||||
* @param short_flag The short flag to use for this argument, excluding the '-' prefix: an option '-c' would be
|
|
||||||
* passed as 'c'. Can only be a single ASCII character. If you do not wish this argument to have a short flag,
|
|
||||||
* use the space character: ' '.
|
|
||||||
* @param long_flag The long flag to use for this argument, excluding the '--' prefix: an option '--example'
|
|
||||||
* would be passed as 'example'. Can be a string of any length. If you do not wish this argument to have a long
|
|
||||||
* flag, use an empty string: "".
|
|
||||||
* @param fallback The value to use if the user uses the argument but does not provide a value. If, however, the
|
|
||||||
* user does not specify this argument at all, out WILL NOT BE MODIFIED!
|
|
||||||
* @param help The help text to show for this argument (optional).
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback,
|
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback,
|
||||||
StringView help = {});
|
StringView help = {});
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register a new value argument.
|
|
||||||
*
|
|
||||||
* @param out The variable where the argument's value will be stored.
|
|
||||||
* @param short_flag The short flag to use for this argument, excluding the '-' prefix: an option '-c' would be
|
|
||||||
* passed as 'c'. Can only be a single ASCII character. If you do not wish this argument to have a short flag,
|
|
||||||
* use the space character: ' '.
|
|
||||||
* @param long_flag The long flag to use for this argument, excluding the '--' prefix: an option '--example'
|
|
||||||
* would be passed as 'example'. Can be a string of any length. If you do not wish this argument to have a long
|
|
||||||
* flag, use an empty string: "".
|
|
||||||
* @param value_required Whether the user is required to pass a value when using this argument. If this is
|
|
||||||
* false and the user does not enter a value along with the argument, out will be set to an empty string. If,
|
|
||||||
* however, the user does not specify this argument at all, out WILL NOT BE MODIFIED!
|
|
||||||
* @param help The help text to show for this argument (optional).
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required,
|
|
||||||
StringView help = {});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the vector to append extra unregistered positional arguments to, after all
|
|
||||||
* registered positional arguments have been parsed. (If no vector is set, these values will instead be
|
|
||||||
* discarded!)
|
|
||||||
*
|
|
||||||
* @param out The vector of StringViews to use.
|
|
||||||
* @param allow_no_more_flags If set, after starting to append values into the vector, no more flags (switch and
|
|
||||||
* value arguments) will be parsed, and will instead be treated as regular positional arguments, as if '--' had
|
|
||||||
* been specified on the command line.
|
|
||||||
*/
|
|
||||||
void set_vector_argument(Vector<StringView>& out, bool allow_no_more_flags = false);
|
void set_vector_argument(Vector<StringView>& out, bool allow_no_more_flags = false);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Parse the given command-line using this ArgumentParser's registered arguments.
|
|
||||||
*
|
|
||||||
* @param argc The argc value passed to main() or luna_main().
|
|
||||||
* @param argv The argv value passed to main() or luna_main().
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> parse(int argc, char* const* argv);
|
Result<void> parse(int argc, char* const* argv);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A program's copyright and version information.
|
|
||||||
*/
|
|
||||||
struct ProgramInfo
|
struct ProgramInfo
|
||||||
{
|
{
|
||||||
StringView name; // The program's name.
|
StringView name;
|
||||||
StringView version; // The program's version/release.
|
StringView version;
|
||||||
StringView copyright; // The program's copyright statement.
|
StringView copyright;
|
||||||
StringView license; // The program's licensing information.
|
StringView license;
|
||||||
StringView authors; // The program's authors (optional).
|
StringView authors;
|
||||||
StringView package; // The package the program is a part of (optional).
|
StringView package;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set this program's copyright and version information (shown in the version text).
|
|
||||||
*
|
|
||||||
* @param info The program information to use.
|
|
||||||
*/
|
|
||||||
void add_program_info(ProgramInfo info);
|
void add_program_info(ProgramInfo info);
|
||||||
|
|
||||||
/**
|
/* Used from programs that are part of the Luna source tree, to add the same version info for all programs.
|
||||||
* @brief For programs that are part of the Luna source tree, set the version information using Luna's own
|
* Should not be used otherwise. */
|
||||||
* version and copyright info and the program name.
|
|
||||||
*
|
|
||||||
* @param name The program name to show in the version information.
|
|
||||||
*/
|
|
||||||
void add_system_program_info(StringView name);
|
void add_system_program_info(StringView name);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Show a short message describing how to find usage information (usually "<program> --help").
|
|
||||||
*
|
|
||||||
* The actual message shown is:
|
|
||||||
* "Try running '<program> --help' for more information." if --help has not been overridden.
|
|
||||||
* "Try running '<program> -h' for more information." if -h has not been overridden.
|
|
||||||
* If both have been overridden, no output is shown.
|
|
||||||
*
|
|
||||||
* Then, the program exits with a non-zero exit code.
|
|
||||||
* This function is designed to be used when the program detects an invalid argument value after parse() has run
|
|
||||||
* successfully.
|
|
||||||
*
|
|
||||||
* @param program_name The program name to show (usually argv[0]).
|
|
||||||
*/
|
|
||||||
void short_usage(StringView program_name);
|
void short_usage(StringView program_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file Directory.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief A C++-friendly API for directory access.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <luna/SharedPtr.h>
|
#include <luna/SharedPtr.h>
|
||||||
@ -16,85 +7,44 @@
|
|||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief An object-oriented directory handle, which is closed when all references to it go out of scope.
|
|
||||||
*/
|
|
||||||
class Directory
|
class Directory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Create a new Directory object from a path, and open the directory.
|
|
||||||
*
|
|
||||||
* @param path The path to open.
|
|
||||||
* @return Result<SharedPtr<Directory>> A new Directory object.
|
|
||||||
*/
|
|
||||||
static Result<SharedPtr<Directory>> open(const Path& path);
|
static Result<SharedPtr<Directory>> open(const Path& path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A filter to skip certain directory entries.
|
|
||||||
*/
|
|
||||||
enum class Filter
|
enum class Filter
|
||||||
{
|
{
|
||||||
None, // Do not skip anything.
|
None,
|
||||||
Hidden, // Skip all hidden files (that start with a '.' character).
|
Hidden,
|
||||||
ParentAndBase // Skip only the '.' and '..' entries.
|
ParentAndBase
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the next entry name from this Directory.
|
|
||||||
*
|
|
||||||
* @param filter The entries to filter out.
|
|
||||||
* @return Result<String> The next entry's name as an owned String object, or an empty string if
|
|
||||||
* there are no more entries.
|
|
||||||
*/
|
|
||||||
Result<String> next(Filter filter);
|
Result<String> next(Filter filter);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the list of entry names from this Directory.
|
|
||||||
*
|
|
||||||
* @param filter The entries to filter out.
|
|
||||||
* @return Result<Vector<String>> The list of entry names.
|
|
||||||
*/
|
|
||||||
Result<Vector<String>> list_names(Filter filter);
|
Result<Vector<String>> list_names(Filter filter);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A directory entry with extra information.
|
|
||||||
*/
|
|
||||||
struct Entry
|
struct Entry
|
||||||
{
|
{
|
||||||
String name; // The entry's name.
|
String name;
|
||||||
mode_t mode; // The entry's file permissions.
|
mode_t mode;
|
||||||
usize size; // The entry's size.
|
usize size;
|
||||||
time_t mtime; // The entry's last modification time.
|
time_t mtime;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the list of entries from this Directory, fetching extra information for each one.
|
|
||||||
*
|
|
||||||
* @param filter The entries to filter out.
|
|
||||||
* @return Result<Vector<Entry>> The list of entries.
|
|
||||||
*/
|
|
||||||
Result<Vector<Entry>> list(Filter filter);
|
Result<Vector<Entry>> list(Filter filter);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Rewinds this Directory back to the beginning of its entry list.
|
|
||||||
*/
|
|
||||||
void rewind();
|
void rewind();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the file descriptor associated with this Directory.
|
|
||||||
*
|
|
||||||
* @return int The file descriptor.
|
|
||||||
*/
|
|
||||||
int fd()
|
int fd()
|
||||||
{
|
{
|
||||||
return dirfd(m_dirp);
|
return dirfd(m_dirp);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Directory();
|
~Directory();
|
||||||
Directory(Badge<Directory>);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Directory(Badge<Directory>);
|
||||||
|
|
||||||
DIR* m_dirp { nullptr };
|
DIR* m_dirp { nullptr };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
/**
|
|
||||||
* @file File.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief A C++-friendly API for file access.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <fcntl.h>
|
#include <bits/open-flags.h>
|
||||||
#include <luna/Buffer.h>
|
#include <luna/Buffer.h>
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
#include <luna/SharedPtr.h>
|
#include <luna/SharedPtr.h>
|
||||||
@ -18,160 +9,52 @@
|
|||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief An object-oriented file handle, which is closed when all references to it go out of scope.
|
|
||||||
*/
|
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief The supported file opening modes.
|
|
||||||
*/
|
|
||||||
enum OpenMode
|
enum OpenMode
|
||||||
{
|
{
|
||||||
ReadOnly = O_RDONLY, // Open the file read-only.
|
ReadOnly = O_RDONLY,
|
||||||
WriteOnly = O_WRONLY | O_TRUNC, // Open the file write-only, truncating it.
|
WriteOnly = O_WRONLY | O_TRUNC,
|
||||||
ReadWrite = O_RDWR | O_TRUNC, // Open the file read-write, truncating it.
|
ReadWrite = O_RDWR | O_TRUNC,
|
||||||
Append = O_WRONLY | O_APPEND, // Open the file write-only, and append to it.
|
Append = O_WRONLY | O_APPEND,
|
||||||
ReadAppend = O_RDWR | O_APPEND, // Open the file read-write, and append to it.
|
ReadAppend = O_RDWR | O_APPEND,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new File object from a file path, opening the file.
|
|
||||||
*
|
|
||||||
* @param path The path to open.
|
|
||||||
* @param flags The opening mode to pass to open(2).
|
|
||||||
* @return Result<SharedPtr<File>> A new File object, or ENOENT if the file did not exist.
|
|
||||||
*/
|
|
||||||
static Result<SharedPtr<File>> open(const Path& path, OpenMode flags);
|
static Result<SharedPtr<File>> open(const Path& path, OpenMode flags);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new File object from a file path, opening the file or creating it if it does not exist.
|
|
||||||
*
|
|
||||||
* @param path The path to open.
|
|
||||||
* @param flags The opening mode to pass to open(2).
|
|
||||||
* @param mode If a new file is created, the file permissions to apply to it. (default: u=rw,g=r,o=r)
|
|
||||||
* @return Result<SharedPtr<File>> A new File object.
|
|
||||||
*/
|
|
||||||
static Result<SharedPtr<File>> open_or_create(const Path& path, OpenMode flags, mode_t mode = 0644);
|
static Result<SharedPtr<File>> open_or_create(const Path& path, OpenMode flags, mode_t mode = 0644);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new File object from a file path, creating the file but erroring out if the file already
|
|
||||||
* exists.
|
|
||||||
*
|
|
||||||
* @param path The path to open.
|
|
||||||
* @param flags The opening mode to pass to open(2).
|
|
||||||
* @param mode The file permissions to apply to the created file. (default: u=rw,g=r,o=r)
|
|
||||||
* @return Result<SharedPtr<File>> A new File object, or EEXIST if the file already existed.
|
|
||||||
*/
|
|
||||||
static Result<SharedPtr<File>> create(const Path& path, OpenMode flags, mode_t mode = 0644);
|
static Result<SharedPtr<File>> create(const Path& path, OpenMode flags, mode_t mode = 0644);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @brief If path is "-", return standard input (as is common for many CLI apps). Otherwise, open path for
|
If path is "-", return standard input (as is common for many CLI apps). Otherwise, open path for reading.
|
||||||
* reading.
|
|
||||||
*
|
This function is a convenience function for CLI apps, so that they don't need to check path and open standard
|
||||||
* @param path The path to open.
|
input if necessary.
|
||||||
* @return Result<SharedPtr<File>> A new File object if path was not "-", or the File
|
|
||||||
* object for standard input if path was "-".
|
|
||||||
*/
|
*/
|
||||||
static Result<SharedPtr<File>> open_input_file(StringView path);
|
static Result<SharedPtr<File>> open_input_file(StringView path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the File corresponding to standard input.
|
|
||||||
*
|
|
||||||
* @return SharedPtr<File> The File object for standard input.
|
|
||||||
*/
|
|
||||||
static SharedPtr<File> standard_input();
|
static SharedPtr<File> standard_input();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the File corresponding to standard output.
|
|
||||||
*
|
|
||||||
* @return SharedPtr<File> The File object for standard output.
|
|
||||||
*/
|
|
||||||
static SharedPtr<File> standard_output();
|
static SharedPtr<File> standard_output();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the File corresponding to standard error.
|
|
||||||
*
|
|
||||||
* @return SharedPtr<File> The File object for standard error.
|
|
||||||
*/
|
|
||||||
static SharedPtr<File> standard_error();
|
static SharedPtr<File> standard_error();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Make this File object automatically close on the next call to execve(2).
|
|
||||||
*/
|
|
||||||
void set_close_on_exec();
|
void set_close_on_exec();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write a string to this File.
|
|
||||||
*
|
|
||||||
* @param str The string to write (can be not null-terminated).
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> write(StringView str);
|
Result<void> write(StringView str);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write a memory buffer to this File.
|
|
||||||
*
|
|
||||||
* @param buf The buffer to write.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> write(const Buffer& buf);
|
Result<void> write(const Buffer& buf);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a line from this File.
|
|
||||||
*
|
|
||||||
* @return Result<String> The line as an owned String object, or an empty string if there is no more
|
|
||||||
* data to read.
|
|
||||||
*/
|
|
||||||
Result<String> read_line();
|
Result<String> read_line();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the entire File's contents as a string.
|
|
||||||
*
|
|
||||||
* @return Result<String> The file's contents as an owned String object.
|
|
||||||
*/
|
|
||||||
Result<String> read_all_as_string();
|
Result<String> read_all_as_string();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read data from this File.
|
|
||||||
*
|
|
||||||
* @param buf The output buffer to store the data in. Will be resized to fit the data.
|
|
||||||
* @param size The maximum number of bytes to read.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> read(Buffer& buf, usize size);
|
Result<void> read(Buffer& buf, usize size);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the entire File's contents.
|
|
||||||
*
|
|
||||||
* @return Result<Buffer> The file's contents as an owned Buffer object.
|
|
||||||
*/
|
|
||||||
Result<Buffer> read_all();
|
Result<Buffer> read_all();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a single character from the File.
|
|
||||||
*
|
|
||||||
* @return Result<int> A character value above 0 (to be cast to an unsigned char), or EOF (typically -1)
|
|
||||||
* if there is no more data to read.
|
|
||||||
*/
|
|
||||||
Result<int> getchar();
|
Result<int> getchar();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the file descriptor associated with this File.
|
|
||||||
*
|
|
||||||
* @return int The file descriptor.
|
|
||||||
*/
|
|
||||||
int fd() const
|
int fd() const
|
||||||
{
|
{
|
||||||
return m_fd;
|
return m_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Move this File's file pointer back to the beginning.
|
|
||||||
*/
|
|
||||||
void rewind();
|
|
||||||
|
|
||||||
File(Badge<File>);
|
File(Badge<File>);
|
||||||
~File();
|
~File();
|
||||||
|
|
||||||
@ -185,39 +68,8 @@ namespace os
|
|||||||
int m_fd { -1 };
|
int m_fd { -1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Print a formatted string to standard output.
|
|
||||||
*
|
|
||||||
* @param fmt The format string (in the same format as printf(3)).
|
|
||||||
* @param ... The format arguments.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> print(StringView fmt, ...);
|
Result<void> print(StringView fmt, ...);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Print a newline-terminated formatted string to standard output.
|
|
||||||
*
|
|
||||||
* @param fmt The format string (in the same format as printf(3)).
|
|
||||||
* @param ... The format arguments.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> println(StringView fmt, ...);
|
Result<void> println(StringView fmt, ...);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Print a formatted string to standard error.
|
|
||||||
*
|
|
||||||
* @param fmt The format string (in the same format as printf(3)).
|
|
||||||
* @param ... The format arguments.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> eprint(StringView fmt, ...);
|
Result<void> eprint(StringView fmt, ...);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Print a newline-terminated formatted string to standard error.
|
|
||||||
*
|
|
||||||
* @param fmt The format string (in the same format as printf(3)).
|
|
||||||
* @param ... The format arguments.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> eprintln(StringView fmt, ...);
|
Result<void> eprintln(StringView fmt, ...);
|
||||||
}
|
}
|
||||||
|
@ -1,111 +1,31 @@
|
|||||||
/**
|
|
||||||
* @file FileSystem.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief APIs to read and modify the general file system.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <bits/struct_stat.h>
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
#include <luna/StringView.h>
|
#include <luna/StringView.h>
|
||||||
#include <os/Path.h>
|
#include <os/Path.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
namespace FileSystem
|
namespace FileSystem
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief Check whether a given path exists.
|
|
||||||
*
|
|
||||||
* @param path The path to check.
|
|
||||||
* @param follow_symlinks If path is a symbolic link, whether to follow it (defaults to true).
|
|
||||||
* @return true The path exists.
|
|
||||||
* @return false The path does not exist, or it was a symbolic link and following it leaded to a nonexistent
|
|
||||||
* path.
|
|
||||||
*/
|
|
||||||
bool exists(const Path& path, bool follow_symlinks = true);
|
bool exists(const Path& path, bool follow_symlinks = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check whether a given path is a directory.
|
|
||||||
*
|
|
||||||
* @param path The path to check.
|
|
||||||
* @param follow_symlinks If path is a symbolic link, whether to follow it (defaults to false).
|
|
||||||
* @return true The path is a directory, or the path was a symbolic link and following it leaded to a directory.
|
|
||||||
* @return false The path does not exist, or it is not a directory.
|
|
||||||
*/
|
|
||||||
bool is_directory(const Path& path, bool follow_symlinks = false);
|
bool is_directory(const Path& path, bool follow_symlinks = false);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieve file status information.
|
|
||||||
*
|
|
||||||
* @param path The path to examine.
|
|
||||||
* @param st The buffer to store file status information in.
|
|
||||||
* @param follow_symlinks If path is a symbolic link, whether to follow it and retrieve its target's status, or
|
|
||||||
* otherwise retrieve the symbolic link's status (defaults to true).
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> stat(const Path& path, struct stat& st, bool follow_symlinks = true);
|
Result<void> stat(const Path& path, struct stat& st, bool follow_symlinks = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new directory in the file system.
|
|
||||||
*
|
|
||||||
* @param path The path for the new directory.
|
|
||||||
* @param mode The file permissions to apply to the new directory.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> create_directory(StringView path, mode_t mode);
|
Result<void> create_directory(StringView path, mode_t mode);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove a file or empty directory from the file system. (The file will continue to exist if there are
|
|
||||||
* other hard links to it or a process still has it open.)
|
|
||||||
*
|
|
||||||
* @param path The path to remove.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> remove(const Path& path);
|
Result<void> remove(const Path& path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove a directory tree from the file system recursively, deleting subfiles and subdirectories as
|
|
||||||
* well.
|
|
||||||
*
|
|
||||||
* @param path The path to remove.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> remove_tree(const Path& path);
|
Result<void> remove_tree(const Path& path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the target of a symbolic link.
|
|
||||||
*
|
|
||||||
* @param path The symbolic link's path.
|
|
||||||
* @return Result<String> If the path was not a symbolic link, an empty string, otherwise the symbolic link's
|
|
||||||
* target.
|
|
||||||
*/
|
|
||||||
Result<String> readlink(const Path& path);
|
Result<String> readlink(const Path& path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read the current process's working directory.
|
|
||||||
*
|
|
||||||
* @return Result<String> The working directory as an owned String object.
|
|
||||||
*/
|
|
||||||
Result<String> working_directory();
|
Result<String> working_directory();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Fetch the current user' home directory.
|
|
||||||
*
|
|
||||||
* @return Result<String> The home directory as an owned String object.
|
|
||||||
*/
|
|
||||||
Result<String> home_directory();
|
Result<String> home_directory();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Change the current process's working directory.
|
|
||||||
*
|
|
||||||
* @param path The new working directory.
|
|
||||||
* @return Result<void> Whether the operation succeeded.
|
|
||||||
*/
|
|
||||||
Result<void> change_directory(StringView path);
|
Result<void> change_directory(StringView path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,4 @@
|
|||||||
/**
|
|
||||||
* @file Main.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Alternative C++ main function.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
|
|
||||||
/**
|
Result<int> luna_main(int argc, char** argv);
|
||||||
* @brief The main() function for Luna C++ apps. This function is extern as it should be implemented by the user if they
|
|
||||||
* do not implement the C main() function.
|
|
||||||
*
|
|
||||||
* @param argc The argc parameter passed to the regular main() function.
|
|
||||||
* @param argv The argv parameter passed to the regular main() function.
|
|
||||||
* @return Result<int> A normal status code, or an errno code, which will be displayed along with an abnormal exit code.
|
|
||||||
*/
|
|
||||||
extern Result<int> luna_main(int argc, char** argv);
|
|
||||||
|
@ -1,30 +1,8 @@
|
|||||||
/**
|
|
||||||
* @file Mode.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Visual file permissions parsing and formatting.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief Create a visual representation of file permissions using the integral representation.
|
|
||||||
*
|
|
||||||
* The output is formatted in the same style as the output of "ls -l".
|
|
||||||
* For example:
|
|
||||||
* An integral mode of S_IFREG | 0644 would result in "-rw-r--r--".
|
|
||||||
* An integral mode of S_IFDIR | 0755 would result in "drwxr-xr-x".
|
|
||||||
* An integral mode of S_IFLNK | 0777 would result in "lrwxrwxrwx".
|
|
||||||
*
|
|
||||||
* @param mode The integral mode.
|
|
||||||
* @param out The buffer to store the formatted file permissions in, as a C-string (minimum 11 bytes, including the
|
|
||||||
* terminating null byte).
|
|
||||||
*/
|
|
||||||
void format_mode(mode_t mode, char out[11]);
|
void format_mode(mode_t mode, char out[11]);
|
||||||
}
|
}
|
||||||
|
@ -1,78 +1,27 @@
|
|||||||
/**
|
|
||||||
* @file Path.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Dirfd-friendly Path class.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <luna/StringView.h>
|
#include <luna/StringView.h>
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief A dirfd-friendly Path class.
|
|
||||||
*/
|
|
||||||
class Path
|
class Path
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Construct a new Path object using a C-string file path.
|
|
||||||
*
|
|
||||||
* @param path The file path to use.
|
|
||||||
*/
|
|
||||||
Path(const char* path);
|
Path(const char* path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Path object using a StringView file path.
|
|
||||||
*
|
|
||||||
* @param path The file path to use.
|
|
||||||
*/
|
|
||||||
Path(StringView path);
|
Path(StringView path);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Path object using a file descriptor.
|
|
||||||
*
|
|
||||||
* @param fd The file descriptor to use.
|
|
||||||
*/
|
|
||||||
Path(int fd);
|
Path(int fd);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Path object using a parent file descriptor and a file path.
|
|
||||||
*
|
|
||||||
* @param dirfd The parent file descriptor to use.
|
|
||||||
* @param name The file path to use.
|
|
||||||
*/
|
|
||||||
Path(int dirfd, StringView name);
|
Path(int dirfd, StringView name);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return the file descriptor associated with this Path.
|
|
||||||
*
|
|
||||||
* @return int The file descriptor, or AT_FDCWD if this Path does not have one.
|
|
||||||
*/
|
|
||||||
int dirfd() const
|
int dirfd() const
|
||||||
{
|
{
|
||||||
return m_dirfd.value_or(AT_FDCWD);
|
return m_dirfd.value_or(AT_FDCWD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return the file path associated with this Path.
|
|
||||||
*
|
|
||||||
* @return StringView The path, or an empty StringView if this Path does not have one.
|
|
||||||
*/
|
|
||||||
StringView name() const
|
StringView name() const
|
||||||
{
|
{
|
||||||
return m_name.value_or(""_sv);
|
return m_name.value_or(""_sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Determine whether this Path consists only of a file descriptor.
|
|
||||||
*
|
|
||||||
* @return int The fstatat()-compatible flag value to use in case this Path consists only of a file descriptor.
|
|
||||||
*/
|
|
||||||
int is_empty_path() const
|
int is_empty_path() const
|
||||||
{
|
{
|
||||||
if (m_dirfd.has_value() && !m_name.has_value()) return AT_EMPTY_PATH;
|
if (m_dirfd.has_value() && !m_name.has_value()) return AT_EMPTY_PATH;
|
||||||
|
@ -1,76 +1,17 @@
|
|||||||
/**
|
|
||||||
* @file Process.h
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Functions to manipulate processes.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief An object representing a process.
|
|
||||||
*/
|
|
||||||
class Process
|
class Process
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Create a new process, which is an identical copy of the current one.
|
|
||||||
*
|
|
||||||
* @return Result<pid_t> The child's process ID in the parent process, and 0 in the child process.
|
|
||||||
*/
|
|
||||||
static Result<pid_t> fork();
|
static Result<pid_t> fork();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Replace the current process's executable with another one.
|
|
||||||
*
|
|
||||||
* @param path The new executable's path.
|
|
||||||
* @param args The argument list to pass to the new executable.
|
|
||||||
* @param search_in_path Determines whether to search in the system binary directories if path is just a name.
|
|
||||||
* @return Result<void> Always an error, as this function does not return on success.
|
|
||||||
*/
|
|
||||||
static Result<void> exec(StringView path, Slice<String> args, bool search_in_path = true);
|
static Result<void> exec(StringView path, Slice<String> args, bool search_in_path = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Replace the current process's executable with another one.
|
|
||||||
*
|
|
||||||
* @param path The new executable's path.
|
|
||||||
* @param args The argument list to pass to the new executable.
|
|
||||||
* @param search_in_path Determines whether to search in the system binary directories if path is just a name.
|
|
||||||
* @return Result<void> Always an error, as this function does not return on success.
|
|
||||||
*/
|
|
||||||
static Result<void> exec(StringView path, Slice<StringView> args, bool search_in_path = true);
|
static Result<void> exec(StringView path, Slice<StringView> args, bool search_in_path = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Replace the current process's executable with another one.
|
|
||||||
*
|
|
||||||
* @param path The new executable's path.
|
|
||||||
* @param args The argument list to pass to the new executable.
|
|
||||||
* @param env The environment to pass to the new executable, instead of the current environment.
|
|
||||||
* @param search_in_path Determines whether to search in the system binary directories if path is just a name.
|
|
||||||
* @return Result<void> Always an error, as this function does not return on success.
|
|
||||||
*/
|
|
||||||
static Result<void> exec(StringView path, Slice<String> args, Slice<String> env, bool search_in_path = true);
|
static Result<void> exec(StringView path, Slice<String> args, Slice<String> env, bool search_in_path = true);
|
||||||
|
|
||||||
// To use as the child argument to wait() to wait for any child.
|
|
||||||
static constexpr pid_t ANY_CHILD = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Wait for a child process to finish running.
|
|
||||||
*
|
|
||||||
* @param child The process ID of the child process, or ANY_CHILD to wait for any child.
|
|
||||||
* @param status The child's exit status will be stored here. If you don't want it, use nullptr.
|
|
||||||
* @param options Options to pass to waitpid(2).
|
|
||||||
* @return Result<pid_t> The process ID of the child process that was waited for (may not be the same as the
|
|
||||||
* child argument if ANY_CHILD was passed).
|
|
||||||
*/
|
|
||||||
static Result<pid_t> wait(pid_t child, int* status, int options = 0);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file ArgumentParser.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Command-line argument parser.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <luna/StringBuilder.h>
|
#include <luna/StringBuilder.h>
|
||||||
#include <os/ArgumentParser.h>
|
#include <os/ArgumentParser.h>
|
||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
@ -84,7 +75,6 @@ namespace os
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change this every year!
|
|
||||||
constexpr auto copyright_text = "Copyright (C) 2023, the Luna authors.";
|
constexpr auto copyright_text = "Copyright (C) 2023, the Luna authors.";
|
||||||
constexpr auto license_text = "Licensed under the BSD-2 license <https://opensource.org/license/bsd-2-clause/>";
|
constexpr auto license_text = "Licensed under the BSD-2 license <https://opensource.org/license/bsd-2-clause/>";
|
||||||
|
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file Directory.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief A C++-friendly API for directory access.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
/**
|
#include <fcntl.h>
|
||||||
* @file File.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief A C++-friendly API for file access.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <luna/StringBuilder.h>
|
#include <luna/StringBuilder.h>
|
||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -202,11 +194,6 @@ namespace os
|
|||||||
fcntl(m_fd, F_SETFD, FD_CLOEXEC);
|
fcntl(m_fd, F_SETFD, FD_CLOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::rewind()
|
|
||||||
{
|
|
||||||
lseek(m_fd, 0, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Do not allocate memory for printing.
|
// FIXME: Do not allocate memory for printing.
|
||||||
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
|
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
/**
|
#include <bits/modes.h>
|
||||||
* @file FileSystem.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief APIs to read and modify the general file system.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -41,8 +33,9 @@ namespace os::FileSystem
|
|||||||
|
|
||||||
Result<void> stat(const Path& path, struct stat& st, bool follow_symlinks)
|
Result<void> stat(const Path& path, struct stat& st, bool follow_symlinks)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_fstatat, path.dirfd(), path.name().chars(), &st,
|
long rc =
|
||||||
(int)(path.is_empty_path() | (follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW)));
|
syscall(SYS_fstatat, path.dirfd(), path.name().chars(), &st,
|
||||||
|
(int)((path.is_empty_path() ? AT_EMPTY_PATH : 0) | (follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
return Result<void>::from_syscall(rc);
|
return Result<void>::from_syscall(rc);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file Main.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Alternative C++ main function.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <os/Main.h>
|
#include <os/Main.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -14,8 +5,6 @@
|
|||||||
int g_argc;
|
int g_argc;
|
||||||
char** g_argv;
|
char** g_argv;
|
||||||
|
|
||||||
// This function will only be linked into the final binary if the user does not already define main(), which implies
|
|
||||||
// that they should have defined luna_main() instead. If not, good for them: linker errors!
|
|
||||||
__attribute__((weak)) int main(int argc, char** argv)
|
__attribute__((weak)) int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
g_argc = argc;
|
g_argc = argc;
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file Mode.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Visual file permissions parsing and formatting.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <os/Mode.h>
|
#include <os/Mode.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file Path.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Dirfd-friendly Path class.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <os/Path.h>
|
#include <os/Path.h>
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file Process.cpp
|
|
||||||
* @author apio (cloudapio.eu)
|
|
||||||
* @brief Functions to manipulate processes.
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023, the Luna authors.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <os/Process.h>
|
#include <os/Process.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -62,10 +53,4 @@ namespace os
|
|||||||
|
|
||||||
return err(errno);
|
return err(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<pid_t> Process::wait(pid_t child, int* status, int options)
|
|
||||||
{
|
|
||||||
long rc = syscall(SYS_waitpid, child, status, options);
|
|
||||||
return Result<pid_t>::from_syscall(rc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ luna_test(libluna/TestVector.cpp TestVector)
|
|||||||
luna_test(libluna/TestBase64.cpp TestBase64)
|
luna_test(libluna/TestBase64.cpp TestBase64)
|
||||||
luna_test(libluna/TestUtf8.cpp TestUtf8)
|
luna_test(libluna/TestUtf8.cpp TestUtf8)
|
||||||
luna_test(libluna/TestFormat.cpp TestFormat)
|
luna_test(libluna/TestFormat.cpp TestFormat)
|
||||||
luna_test(libluna/TestHashTable.cpp TestHashTable)
|
|
||||||
|
|
||||||
luna_app(run-tests.cpp run-tests)
|
luna_app(run-tests.cpp run-tests)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
#include <luna/HashTable.h>
|
|
||||||
#include <os/File.h>
|
|
||||||
#include <test.h>
|
|
||||||
|
|
||||||
struct TwoInts
|
|
||||||
{
|
|
||||||
int a;
|
|
||||||
int b;
|
|
||||||
|
|
||||||
bool operator==(TwoInts other) const
|
|
||||||
{
|
|
||||||
return other.a == a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> u64 hash(const TwoInts& value, u64 salt)
|
|
||||||
{
|
|
||||||
return hash(value.a, salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_empty_hash_table()
|
|
||||||
{
|
|
||||||
HashTable<int> table;
|
|
||||||
|
|
||||||
validate(table.try_find(0) == nullptr);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_hash_table_find()
|
|
||||||
{
|
|
||||||
HashTable<int> table;
|
|
||||||
|
|
||||||
validate(TRY(table.try_set(0)));
|
|
||||||
|
|
||||||
validate(table.try_find(0));
|
|
||||||
validate(table.try_find(1) == nullptr);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_hash_table_remove()
|
|
||||||
{
|
|
||||||
HashTable<int> table;
|
|
||||||
|
|
||||||
validate(TRY(table.try_set(0)));
|
|
||||||
|
|
||||||
validate(table.try_find(0));
|
|
||||||
|
|
||||||
validate(table.try_remove(0));
|
|
||||||
|
|
||||||
validate(table.try_find(0) == nullptr);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult test_hash_table_duplicates()
|
|
||||||
{
|
|
||||||
HashTable<TwoInts> table;
|
|
||||||
|
|
||||||
validate(TRY(table.try_set(TwoInts { 1, 5 })));
|
|
||||||
validate(!TRY(table.try_set(TwoInts { 1, 3 })));
|
|
||||||
|
|
||||||
validate(table.try_find(TwoInts { 1, 0 })->b == 5);
|
|
||||||
|
|
||||||
test_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> test_main()
|
|
||||||
{
|
|
||||||
test_prelude;
|
|
||||||
|
|
||||||
run_test(test_empty_hash_table);
|
|
||||||
run_test(test_hash_table_find);
|
|
||||||
run_test(test_hash_table_remove);
|
|
||||||
run_test(test_hash_table_duplicates);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
@ -17,7 +17,7 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
auto dir = TRY(os::Directory::open(test_dir));
|
auto dir = TRY(os::Directory::open(test_dir));
|
||||||
|
|
||||||
auto files = TRY(dir->list_names(os::Directory::Filter::Hidden));
|
auto files = TRY(dir->list(os::Directory::Filter::Hidden));
|
||||||
|
|
||||||
for (const auto& program : files)
|
for (const auto& program : files)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user