Compare commits

...

4 Commits

Author SHA1 Message Date
51a5727c8d
libluna: Fix a crash in quicksort
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-28 21:51:50 +02:00
069f1c0f97
ls: Sort displayed entries 2023-05-28 21:51:50 +02:00
e864ef2d36
libos: Add a way to also list entry sizes, modes and mtimes 2023-05-28 21:51:50 +02:00
11a4f8cc90
kernel: Wake the parent process when a child exits because of a page fault 2023-05-28 21:50:13 +02:00
7 changed files with 144 additions and 14 deletions

View File

@ -224,7 +224,7 @@ static Result<void> load_services()
{ {
auto dir = TRY(os::Directory::open("/etc/init")); auto dir = TRY(os::Directory::open("/etc/init"));
auto services = TRY(dir->list(os::Directory::Filter::ParentAndBase)); auto services = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
sort(services.begin(), services.end(), String::compare); sort(services.begin(), services.end(), String::compare);
for (const auto& entry : services) TRY(load_service({ dir->fd(), entry.view() })); for (const auto& entry : services) TRY(load_service({ dir->fd(), entry.view() }));

View File

@ -1,4 +1,6 @@
#include <grp.h> #include <grp.h>
#include <luna/Sort.h>
#include <luna/StringBuilder.h>
#include <luna/Units.h> #include <luna/Units.h>
#include <os/ArgumentParser.h> #include <os/ArgumentParser.h>
#include <os/Directory.h> #include <os/Directory.h>
@ -20,6 +22,48 @@ void find_user_and_group(struct stat& st, StringView& owner, StringView& group)
group = grp->gr_name; group = grp->gr_name;
} }
int sort_name(const os::Directory::Entry* a, const os::Directory::Entry* b)
{
return String::compare(&a->name, &b->name);
}
int sort_size(const os::Directory::Entry* a, const os::Directory::Entry* b)
{
return (a->size < b->size) ? -1 : ((a->size == b->size) ? 0 : 1);
}
int sort_time(const os::Directory::Entry* a, const os::Directory::Entry* b)
{
return (a->mtime < b->mtime) ? -1 : ((a->mtime == b->mtime) ? 0 : 1);
}
static int (*sort_function)(const os::Directory::Entry*, const os::Directory::Entry*) = sort_name;
int sort_reverse(const os::Directory::Entry* a, const os::Directory::Entry* b)
{
int rc = sort_function(a, b);
if (rc < 0) return 1;
if (rc > 0) return -1;
return 0;
}
static Result<String> entry_join(const Vector<os::Directory::Entry>& vec, StringView delim)
{
if (vec.size() == 0) return String {};
if (vec.size() == 1) return vec[0].name.clone();
StringBuilder sb;
TRY(sb.add(vec[0].name));
for (usize i = 1; i < vec.size(); i++)
{
TRY(sb.add(delim));
TRY(sb.add(vec[i].name));
}
return sb.string();
}
Result<int> luna_main(int argc, char** argv) Result<int> luna_main(int argc, char** argv)
{ {
StringView pathname; StringView pathname;
@ -32,6 +76,12 @@ Result<int> luna_main(int argc, char** argv)
bool one_per_line { false }; bool one_per_line { false };
bool list_directories { false }; bool list_directories { false };
StringView sort_type { "name" };
bool reverse_sort { false };
bool should_sort { true };
os::ArgumentParser parser; os::ArgumentParser parser;
parser.add_description("List files contained in a directory (defaults to '.', the current directory)"_sv); parser.add_description("List files contained in a directory (defaults to '.', the current directory)"_sv);
parser.add_system_program_info("ls"_sv); parser.add_system_program_info("ls"_sv);
@ -46,14 +96,26 @@ Result<int> luna_main(int argc, char** argv)
"follow symbolic links listed as arguments"_sv); "follow symbolic links listed as arguments"_sv);
parser.add_switch_argument(one_per_line, '1', ""_sv, "list one file per line"_sv); parser.add_switch_argument(one_per_line, '1', ""_sv, "list one file per line"_sv);
parser.add_switch_argument(list_directories, 'd', "directory"_sv, "list directories instead of their contents"_sv); parser.add_switch_argument(list_directories, 'd', "directory"_sv, "list directories instead of their contents"_sv);
parser.add_value_argument(sort_type, ' ', "sort"_sv, true, "sort by name, size or time"_sv);
parser.add_switch_argument(reverse_sort, 'r', "reverse"_sv, "reverse order while sorting"_sv);
parser.parse(argc, argv); parser.parse(argc, argv);
Vector<String> files; Vector<os::Directory::Entry> files;
int dirfd = AT_FDCWD; int dirfd = AT_FDCWD;
SharedPtr<os::Directory> dir; SharedPtr<os::Directory> dir;
if (!long_list) follow_symlink_args = true; if (!long_list) follow_symlink_args = true;
if (sort_type == "none"_sv) { should_sort = false; }
else if (sort_type == "name"_sv) { sort_function = sort_name; }
else if (sort_type == "size"_sv) { sort_function = sort_size; }
else if (sort_type == "time"_sv) { sort_function = sort_time; }
else
{
os::eprintln("%s: unknown sort type: %s", argv[0], sort_type.chars());
return 1;
}
if (os::FileSystem::is_directory(pathname, follow_symlink_args) && !list_directories) if (os::FileSystem::is_directory(pathname, follow_symlink_args) && !list_directories)
{ {
dir = TRY(os::Directory::open(pathname)); dir = TRY(os::Directory::open(pathname));
@ -68,15 +130,31 @@ Result<int> luna_main(int argc, char** argv)
} }
else if (os::FileSystem::exists(pathname, follow_symlink_args)) else if (os::FileSystem::exists(pathname, follow_symlink_args))
{ {
auto str = TRY(String::from_string_view(pathname)); struct stat st;
TRY(files.try_append(move(str))); TRY(os::FileSystem::stat(pathname, st, false));
os::Directory::Entry entry = {
.name = TRY(String::from_string_view(pathname)),
.mode = st.st_mode,
.size = (usize)st.st_size,
.mtime = st.st_mtime,
};
TRY(files.try_append(move(entry)));
} }
else else
return err(ENOENT); return err(ENOENT);
if (should_sort)
{
if (reverse_sort) sort(files.begin(), files.end(), sort_reverse);
else
sort(files.begin(), files.end(), sort_function);
}
if (!long_list) if (!long_list)
{ {
auto list = TRY(String::join(files, one_per_line ? "\n"_sv : " "_sv)); auto list = TRY(entry_join(files, one_per_line ? "\n"_sv : " "_sv));
if (!list.is_empty()) os::println("%s", list.chars()); if (!list.is_empty()) os::println("%s", list.chars());
} }
else else
@ -84,9 +162,9 @@ Result<int> luna_main(int argc, char** argv)
for (const auto& file : files) for (const auto& file : files)
{ {
struct stat st; struct stat st;
TRY(os::FileSystem::stat({ dirfd, file.view() }, st, false)); TRY(os::FileSystem::stat({ dirfd, file.name.view() }, st, false));
auto link = TRY(os::FileSystem::readlink({ dirfd, file.view() })); auto link = TRY(os::FileSystem::readlink({ dirfd, file.name.view() }));
StringView owner; StringView owner;
StringView group; StringView group;
@ -99,13 +177,13 @@ Result<int> luna_main(int argc, char** argv)
if (!human_readable && !si) if (!human_readable && !si)
{ {
os::println("%s %u %4s %4s %10lu %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(), os::println("%s %u %4s %4s %10lu %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(),
st.st_size, file.chars(), link.is_empty() ? "" : " -> ", link.chars()); st.st_size, file.name.chars(), link.is_empty() ? "" : " -> ", link.chars());
} }
else else
{ {
auto size = TRY(to_dynamic_unit(st.st_size, 10, false, si ? Unit::SI : Unit::Binary, false)); auto size = TRY(to_dynamic_unit(st.st_size, 10, false, si ? Unit::SI : Unit::Binary, false));
os::println("%s %u %4s %4s %6s %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(), os::println("%s %u %4s %4s %6s %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(),
size.chars(), file.chars(), link.is_empty() ? "" : " -> ", link.chars()); size.chars(), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars());
} }
} }
} }

View File

@ -73,7 +73,22 @@ void decode_page_fault_error_code(u64 code)
{ {
// FIXME: Kill this process with SIGSEGV once we have signals and all that. // FIXME: Kill this process with SIGSEGV once we have signals and all that.
kerrorln("Current task %zu was terminated because of a page fault", Scheduler::current()->id); kerrorln("Current task %zu was terminated because of a page fault", Scheduler::current()->id);
Scheduler::current()->state = ThreadState::Exited; if (Scheduler::current()->is_kernel) Scheduler::current()->state = ThreadState::Dying;
else
{
auto* current = Scheduler::current();
auto* parent = current->parent;
if (parent && parent->state == ThreadState::Waiting)
{
auto child = *parent->child_being_waited_for;
if (child == -1 || child == (pid_t)current->id)
{
parent->child_being_waited_for = (pid_t)current->id;
parent->wake_up();
}
}
current->state = ThreadState::Exited;
}
Scheduler::current()->status = 127; Scheduler::current()->status = 127;
kernel_yield(); kernel_yield();
unreachable(); unreachable();

View File

@ -1,4 +1,5 @@
#include <luna/Alignment.h> #include <luna/Alignment.h>
#include <luna/DebugLog.h>
#include <luna/Sort.h> #include <luna/Sort.h>
static void swap_sized(void* ptr1, void* ptr2, usize size) static void swap_sized(void* ptr1, void* ptr2, usize size)
@ -42,7 +43,7 @@ static void quicksort_impl(void* base, usize start, usize end, usize size, compa
{ {
usize pivot = partition(base, start, end, size, compar); usize pivot = partition(base, start, end, size, compar);
if ((end - start) < 2) return; if ((end - start) < 2) return;
quicksort_impl(base, start, pivot - 1, size, compar); if (pivot > 0) quicksort_impl(base, start, pivot - 1, size, compar);
quicksort_impl(base, pivot + 1, end, size, compar); quicksort_impl(base, pivot + 1, end, size, compar);
} }
} }

View File

@ -21,7 +21,17 @@ namespace os
Result<String> next(Filter filter); Result<String> next(Filter filter);
Result<Vector<String>> list(Filter filter); Result<Vector<String>> list_names(Filter filter);
struct Entry
{
String name;
mode_t mode;
usize size;
time_t mtime;
};
Result<Vector<Entry>> list(Filter filter);
void rewind(); void rewind();

View File

@ -2,6 +2,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <luna/CString.h> #include <luna/CString.h>
#include <os/Directory.h> #include <os/Directory.h>
#include <os/FileSystem.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
@ -54,7 +55,7 @@ namespace os
return String::from_cstring(ent->d_name); return String::from_cstring(ent->d_name);
} }
Result<Vector<String>> Directory::list(Filter filter) Result<Vector<String>> Directory::list_names(Filter filter)
{ {
Vector<String> result; Vector<String> result;
@ -66,6 +67,31 @@ namespace os
return result; return result;
} }
Result<Vector<Directory::Entry>> Directory::list(Filter filter)
{
Vector<Directory::Entry> result;
rewind();
String name {};
while ((name = TRY(next(filter))), !name.is_empty())
{
struct stat st;
TRY(FileSystem::stat({ dirfd(m_dirp), name.chars() }, st, false));
Directory::Entry entry {
.name = move(name),
.mode = st.st_mode,
.size = (usize)st.st_size,
.mtime = st.st_mtime,
};
TRY(result.try_append(move(entry)));
}
return result;
}
void Directory::rewind() void Directory::rewind()
{ {
rewinddir(m_dirp); rewinddir(m_dirp);

View File

@ -62,7 +62,7 @@ namespace os::FileSystem
auto dir = TRY(os::Directory::open(path)); auto dir = TRY(os::Directory::open(path));
Vector<String> entries = TRY(dir->list(os::Directory::Filter::ParentAndBase)); Vector<String> entries = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
for (const auto& entry : entries) { TRY(remove_tree({ dir->fd(), entry.view() })); } for (const auto& entry : entries) { TRY(remove_tree({ dir->fd(), entry.view() })); }