Libraries: Remove some Serenity-only interface implementations

This commit is contained in:
Timothy Flynn 2024-06-03 20:10:39 -04:00 committed by Andreas Kling
parent 126cbce632
commit edb527e04d
Notes: sideshowbarker 2024-07-17 07:20:57 +09:00
5 changed files with 11 additions and 527 deletions

View file

@ -16,13 +16,6 @@ set(SOURCES
serenity_lib(LibCoreMinimal coreminimal)
if (SERENITYOS)
add_library(DynamicLoader_LibCoreArgsParser
ArgsParser.cpp
Version.cpp)
target_link_libraries(DynamicLoader_LibCoreArgsParser PUBLIC DynamicLoader_CompileOptions)
endif()
set(SOURCES
AnonymousBuffer.cpp
Command.cpp
@ -65,12 +58,7 @@ if (NOT WIN32 AND NOT EMSCRIPTEN)
endif()
# FIXME: Implement Core::FileWatcher for *BSD and Windows.
if (SERENITYOS)
list(APPEND SOURCES
FileWatcherSerenity.cpp
Platform/ProcessStatisticsSerenity.cpp
)
elseif (LINUX AND NOT EMSCRIPTEN)
if (LINUX AND NOT EMSCRIPTEN)
list(APPEND SOURCES
FileWatcherLinux.cpp
Platform/ProcessStatisticsLinux.cpp

View file

@ -1,222 +0,0 @@
/*
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
* Copyright (c) 2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "FileWatcher.h"
#include <AK/ByteString.h>
#include <AK/Debug.h>
#include <AK/LexicalPath.h>
#include <AK/NonnullRefPtr.h>
#include <Kernel/API/InodeWatcherEvent.h>
#include <Kernel/API/InodeWatcherFlags.h>
#include <LibCore/Notifier.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#if !defined(AK_OS_SERENITY)
static_assert(false, "This file must only be used for SerenityOS");
#endif
namespace Core {
static constexpr unsigned file_watcher_flags_to_inode_watcher_flags(FileWatcherFlags flags)
{
auto result = InodeWatcherFlags::None;
if (has_flag(flags, FileWatcherFlags::Nonblock))
result |= InodeWatcherFlags::Nonblock;
if (has_flag(flags, FileWatcherFlags::CloseOnExec))
result |= InodeWatcherFlags::CloseOnExec;
return static_cast<unsigned>(result);
}
static Optional<FileWatcherEvent> get_event_from_fd(int fd, HashMap<unsigned, ByteString> const& wd_to_path)
{
u8 buffer[MAXIMUM_EVENT_SIZE];
int rc = read(fd, &buffer, MAXIMUM_EVENT_SIZE);
if (rc == 0) {
return {};
} else if (rc < 0) {
dbgln_if(FILE_WATCHER_DEBUG, "get_event_from_fd: Reading from wd {} failed: {}", fd, strerror(errno));
return {};
}
InodeWatcherEvent* event = reinterpret_cast<InodeWatcherEvent*>(buffer);
FileWatcherEvent result;
auto it = wd_to_path.find(event->watch_descriptor);
if (it == wd_to_path.end()) {
dbgln_if(FILE_WATCHER_DEBUG, "get_event_from_fd: Got an event for a non-existent wd {}?!", event->watch_descriptor);
return {};
}
ByteString const& path = it->value;
switch (event->type) {
case InodeWatcherEvent::Type::ChildCreated:
result.type = FileWatcherEvent::Type::ChildCreated;
break;
case InodeWatcherEvent::Type::ChildDeleted:
result.type = FileWatcherEvent::Type::ChildDeleted;
break;
case InodeWatcherEvent::Type::Deleted:
result.type = FileWatcherEvent::Type::Deleted;
break;
case InodeWatcherEvent::Type::ContentModified:
result.type = FileWatcherEvent::Type::ContentModified;
break;
case InodeWatcherEvent::Type::MetadataModified:
result.type = FileWatcherEvent::Type::MetadataModified;
break;
default:
warnln("Unknown event type {} returned by the watch_file descriptor for {}", static_cast<unsigned>(event->type), path);
return {};
}
// We trust that the kernel only sends the name when appropriate.
if (event->name_length > 0) {
ByteString child_name { event->name, event->name_length - 1 };
result.event_path = LexicalPath::join(path, child_name).string();
} else {
result.event_path = path;
}
dbgln_if(FILE_WATCHER_DEBUG, "get_event_from_fd: got event from wd {} on '{}' type {}", fd, result.event_path, result.type);
return result;
}
static ByteString canonicalize_path(ByteString path)
{
if (!path.is_empty() && path[0] == '/')
return LexicalPath::canonicalized_path(move(path));
char* cwd = getcwd(nullptr, 0);
VERIFY(cwd);
return LexicalPath::join({ cwd, strlen(cwd) }, move(path)).string();
}
ErrorOr<bool> FileWatcherBase::add_watch(ByteString path, FileWatcherEvent::Type event_mask)
{
ByteString canonical_path = canonicalize_path(move(path));
if (m_path_to_wd.find(canonical_path) != m_path_to_wd.end()) {
dbgln_if(FILE_WATCHER_DEBUG, "add_watch: path '{}' is already being watched", canonical_path);
return false;
}
auto kernel_mask = InodeWatcherEvent::Type::Invalid;
if (has_flag(event_mask, FileWatcherEvent::Type::ChildCreated))
kernel_mask |= InodeWatcherEvent::Type::ChildCreated;
if (has_flag(event_mask, FileWatcherEvent::Type::ChildDeleted))
kernel_mask |= InodeWatcherEvent::Type::ChildDeleted;
if (has_flag(event_mask, FileWatcherEvent::Type::Deleted))
kernel_mask |= InodeWatcherEvent::Type::Deleted;
if (has_flag(event_mask, FileWatcherEvent::Type::ContentModified))
kernel_mask |= InodeWatcherEvent::Type::ContentModified;
if (has_flag(event_mask, FileWatcherEvent::Type::MetadataModified))
kernel_mask |= InodeWatcherEvent::Type::MetadataModified;
int wd = inode_watcher_add_watch(m_watcher_fd, canonical_path.characters(), canonical_path.length(), static_cast<unsigned>(kernel_mask));
if (wd < 0)
return Error::from_errno(errno);
m_path_to_wd.set(canonical_path, wd);
m_wd_to_path.set(wd, canonical_path);
dbgln_if(FILE_WATCHER_DEBUG, "add_watch: watching path '{}' on InodeWatcher {} wd {}", canonical_path, m_watcher_fd, wd);
return true;
}
ErrorOr<bool> FileWatcherBase::remove_watch(ByteString path)
{
ByteString canonical_path = canonicalize_path(move(path));
auto it = m_path_to_wd.find(canonical_path);
if (it == m_path_to_wd.end()) {
dbgln_if(FILE_WATCHER_DEBUG, "remove_watch: path '{}' is not being watched", canonical_path);
return false;
}
if (inode_watcher_remove_watch(m_watcher_fd, it->value) < 0)
return Error::from_errno(errno);
m_path_to_wd.remove(it);
m_wd_to_path.remove(it->value);
dbgln_if(FILE_WATCHER_DEBUG, "remove_watch: stopped watching path '{}' on InodeWatcher {}", canonical_path, m_watcher_fd);
return true;
}
BlockingFileWatcher::BlockingFileWatcher(FileWatcherFlags flags)
: FileWatcherBase(create_inode_watcher(file_watcher_flags_to_inode_watcher_flags(flags)))
{
VERIFY(m_watcher_fd != -1);
dbgln_if(FILE_WATCHER_DEBUG, "BlockingFileWatcher created with InodeWatcher {}", m_watcher_fd);
}
BlockingFileWatcher::~BlockingFileWatcher()
{
close(m_watcher_fd);
}
Optional<FileWatcherEvent> BlockingFileWatcher::wait_for_event()
{
dbgln_if(FILE_WATCHER_DEBUG, "BlockingFileWatcher::wait_for_event()");
auto maybe_event = get_event_from_fd(m_watcher_fd, m_wd_to_path);
if (!maybe_event.has_value())
return maybe_event;
auto event = maybe_event.release_value();
if (event.type == FileWatcherEvent::Type::Deleted) {
auto result = remove_watch(event.event_path);
if (result.is_error()) {
dbgln_if(FILE_WATCHER_DEBUG, "wait_for_event: {}", result.error());
}
}
return event;
}
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(FileWatcherFlags flags)
{
auto watcher_fd = create_inode_watcher(file_watcher_flags_to_inode_watcher_flags(flags | FileWatcherFlags::CloseOnExec));
if (watcher_fd < 0)
return Error::from_errno(errno);
auto notifier = Notifier::construct(watcher_fd, Notifier::Type::Read);
return adopt_ref(*new FileWatcher(watcher_fd, move(notifier)));
}
FileWatcher::FileWatcher(int watcher_fd, NonnullRefPtr<Notifier> notifier)
: FileWatcherBase(watcher_fd)
, m_notifier(move(notifier))
{
m_notifier->on_activation = [this] {
auto maybe_event = get_event_from_fd(m_notifier->fd(), m_wd_to_path);
if (maybe_event.has_value()) {
auto event = maybe_event.value();
on_change(event);
if (event.type == FileWatcherEvent::Type::Deleted) {
auto result = remove_watch(event.event_path);
if (result.is_error()) {
dbgln_if(FILE_WATCHER_DEBUG, "on_ready_to_read: {}", result.error());
}
}
}
};
}
FileWatcher::~FileWatcher()
{
m_notifier->on_activation = nullptr;
close(m_notifier->fd());
dbgln_if(FILE_WATCHER_DEBUG, "Stopped watcher at fd {}", m_notifier->fd());
}
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Platform.h>
#if !defined(AK_OS_SERENITY)
# error "This file is for Serenity OS only"
#endif
#include <LibCore/File.h>
#include <LibCore/Platform/ProcessStatistics.h>
#include <LibCore/ProcessStatisticsReader.h>
namespace Core::Platform {
ErrorOr<void> update_process_statistics(ProcessStatistics& statistics)
{
static auto proc_all_file = TRY(Core::File::open("/sys/kernel/processes"sv, Core::File::OpenMode::Read));
auto const all_processes = TRY(Core::ProcessStatisticsReader::get_all(*proc_all_file, false));
auto const total_time_scheduled = all_processes.total_time_scheduled;
auto const total_time_scheduled_diff = total_time_scheduled - statistics.total_time_scheduled;
statistics.total_time_scheduled = total_time_scheduled;
for (auto& process : statistics.processes) {
auto it = all_processes.processes.find_if([&](auto& entry) { return entry.pid == process->pid; });
if (!it.is_end()) {
process->memory_usage_bytes = it->amount_resident;
u64 time_process = 0;
for (auto& thread : it->threads) {
time_process += thread.time_user + thread.time_kernel;
}
u64 time_scheduled_diff = time_process - process->time_spent_in_process;
process->time_spent_in_process = time_process;
process->cpu_percent = 0.0;
if (total_time_scheduled_diff > 0) {
process->cpu_percent = static_cast<float>((time_scheduled_diff * 1000) / total_time_scheduled_diff) / 10.0f;
}
} else {
process->memory_usage_bytes = 0;
process->cpu_percent = 0.0;
process->time_spent_in_process = 0;
}
}
return {};
}
}

View file

@ -1,221 +0,0 @@
/*
* Copyright (c) 2020, Emanuel Sprung <emanuel.sprung@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteString.h>
#include <AK/StringBuilder.h>
#include <AK/Variant.h>
#include <LibRegex/Regex.h>
#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
#ifndef AK_OS_SERENITY
# error "This file is intended for use on Serenity only to implement POSIX regex.h"
#endif
struct internal_regex_t {
u8 cflags;
u8 eflags;
Optional<Variant<NonnullOwnPtr<Regex<PosixExtended>>, NonnullOwnPtr<Regex<PosixBasic>>>> re;
size_t re_pat_errpos;
ReError re_pat_err;
ByteString re_pat;
};
static internal_regex_t* impl_from(regex_t* re)
{
if (!re)
return nullptr;
return reinterpret_cast<internal_regex_t*>(re->__data);
}
static internal_regex_t const* impl_from(regex_t const* re)
{
return impl_from(const_cast<regex_t*>(re));
}
extern "C" {
int regcomp(regex_t* reg, char const* pattern, int cflags)
{
if (!reg)
return REG_ESPACE;
// Note that subsequent uses of regcomp() without regfree() _will_ leak memory
// This could've been prevented if libc provided a reginit() or similar, but it does not.
reg->__data = new internal_regex_t { 0, 0, {}, 0, ReError::REG_NOERR, {} };
auto* preg = impl_from(reg);
bool is_extended = cflags & REG_EXTENDED;
preg->cflags = cflags;
ByteString pattern_str(pattern);
if (is_extended)
preg->re = make<Regex<PosixExtended>>(pattern_str, PosixOptions {} | (PosixFlags)cflags | PosixFlags::SkipTrimEmptyMatches);
else
preg->re = make<Regex<PosixBasic>>(pattern_str, PosixOptions {} | (PosixFlags)cflags | PosixFlags::SkipTrimEmptyMatches);
auto parser_result = preg->re->visit([](auto& re) { return re->parser_result; });
if (parser_result.error != regex::Error::NoError) {
preg->re_pat_errpos = parser_result.error_token.position();
preg->re_pat_err = (ReError)parser_result.error;
preg->re_pat = pattern;
dbgln("Have Error: {}", (int)parser_result.error);
return (ReError)parser_result.error;
}
reg->re_nsub = parser_result.capture_groups_count;
return REG_NOERR;
}
int regexec(regex_t const* reg, char const* string, size_t nmatch, regmatch_t pmatch[], int eflags)
{
auto const* preg = impl_from(reg);
if (!preg->re.has_value() || preg->re_pat_err) {
if (preg->re_pat_err)
return preg->re_pat_err;
return REG_BADPAT;
}
RegexResult result;
StringView string_view { string, strlen(string) };
if (eflags & REG_SEARCH)
result = preg->re->visit([&](auto& re) { return re->search(string_view, PosixOptions {} | (PosixFlags)eflags); });
else
result = preg->re->visit([&](auto& re) { return re->match(string_view, PosixOptions {} | (PosixFlags)eflags); });
if (result.success) {
auto capture_groups_count = preg->re->visit([](auto& re) { return re->parser_result.capture_groups_count; });
auto size = result.matches.size();
if (size && nmatch && pmatch) {
pmatch[0].rm_cnt = size;
size_t match_index { 0 };
for (size_t i = 0; i < size; ++i) {
pmatch[match_index].rm_so = result.matches.at(i).global_offset;
pmatch[match_index].rm_eo = pmatch[match_index].rm_so + result.matches.at(i).view.length();
if (match_index > 0)
pmatch[match_index].rm_cnt = result.capture_group_matches.size();
++match_index;
if (match_index >= nmatch)
return REG_NOERR;
if (i < result.capture_group_matches.size()) {
auto capture_groups_size = result.capture_group_matches.at(i).size();
for (size_t j = 0; j < capture_groups_count; ++j) {
if (j >= capture_groups_size || !result.capture_group_matches.at(i).at(j).view.length()) {
pmatch[match_index].rm_so = -1;
pmatch[match_index].rm_eo = -1;
pmatch[match_index].rm_cnt = 0;
} else {
pmatch[match_index].rm_so = result.capture_group_matches.at(i).at(j).global_offset;
pmatch[match_index].rm_eo = pmatch[match_index].rm_so + result.capture_group_matches.at(i).at(j).view.length();
pmatch[match_index].rm_cnt = 1;
}
++match_index;
if (match_index >= nmatch)
return REG_NOERR;
}
}
}
if (match_index < nmatch) {
for (size_t i = match_index; i < nmatch; ++i) {
pmatch[i].rm_so = -1;
pmatch[i].rm_eo = -1;
pmatch[i].rm_cnt = 0;
}
}
}
return REG_NOERR;
}
if (nmatch && pmatch) {
pmatch[0].rm_so = -1;
pmatch[0].rm_eo = -1;
pmatch[0].rm_cnt = 0;
}
return REG_NOMATCH;
}
static StringView get_error(ReError errcode)
{
switch (errcode) {
case REG_NOERR:
return "No error"sv;
case REG_NOMATCH:
return "regexec() failed to match."sv;
case REG_BADPAT:
return "Invalid regular expression."sv;
case REG_ECOLLATE:
return "Invalid collating element referenced."sv;
case REG_ECTYPE:
return "Invalid character class type referenced."sv;
case REG_EESCAPE:
return "Trailing \\ in pattern."sv;
case REG_ESUBREG:
return "Number in \\digit invalid or in error."sv;
case REG_EBRACK:
return "[ ] imbalance."sv;
case REG_EPAREN:
return "\\( \\) or ( ) imbalance."sv;
case REG_EBRACE:
return "\\{ \\} imbalance."sv;
case REG_BADBR:
return "Content of \\{ \\} invalid: not a number, number too large, more than two numbers, first larger than second."sv;
case REG_ERANGE:
return "Invalid endpoint in range expression."sv;
case REG_ESPACE:
return "Out of memory."sv;
case REG_BADRPT:
return "?, * or + not preceded by valid regular expression."sv;
case REG_ENOSYS:
return "The implementation does not support the function."sv;
case REG_EMPTY_EXPR:
return "Empty expression provided"sv;
}
return {};
}
size_t regerror(int errcode, regex_t const* reg, char* errbuf, size_t errbuf_size)
{
ByteString error;
auto const* preg = impl_from(reg);
if (!preg)
error = get_error((ReError)errcode);
else
error = preg->re->visit([&](auto& re) { return re->error_string(get_error(preg->re_pat_err)); });
if (!errbuf_size)
return error.length();
if (!error.copy_characters_to_buffer(errbuf, errbuf_size))
return 0;
return error.length();
}
void regfree(regex_t* reg)
{
auto* preg = impl_from(reg);
if (preg) {
delete preg;
reg->__data = nullptr;
}
}
}

View file

@ -21,10 +21,6 @@ set(SOURCES
set(GENERATED_SOURCES ${CURRENT_LIB_GENERATED})
if (SERENITYOS)
list(APPEND SOURCES OutOfProcessWebView.cpp)
endif()
embed_as_string_view(
"NativeStyleSheetSource.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Native.css"
@ -53,18 +49,16 @@ serenity_lib(LibWebView webview)
target_link_libraries(LibWebView PRIVATE LibCore LibFileSystem LibGfx LibIPC LibProtocol LibJS LibWeb LibSQL LibUnicode LibURL)
target_compile_definitions(LibWebView PRIVATE ENABLE_PUBLIC_SUFFIX=$<BOOL:${ENABLE_PUBLIC_SUFFIX_DOWNLOAD}>)
if (NOT SERENITYOS)
foreach(header ${GENERATED_SOURCES})
get_filename_component(extension ${header} EXT)
if (NOT "${extension}" STREQUAL ".h")
continue()
endif()
foreach(header ${GENERATED_SOURCES})
get_filename_component(extension ${header} EXT)
if (NOT "${extension}" STREQUAL ".h")
continue()
endif()
get_filename_component(subdirectory ${header} DIRECTORY)
string(REGEX REPLACE "^\\.\\./\\.\\./" "" subdirectory "${subdirectory}")
get_filename_component(subdirectory ${header} DIRECTORY)
string(REGEX REPLACE "^\\.\\./\\.\\./" "" subdirectory "${subdirectory}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${header}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${subdirectory}")
endforeach()
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${header}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${subdirectory}")
endforeach()
install(FILES "${SERENITY_PROJECT_ROOT}/Userland/Services/RequestServer/ConnectionCache.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/RequestServer")
endif()
install(FILES "${SERENITY_PROJECT_ROOT}/Userland/Services/RequestServer/ConnectionCache.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/RequestServer")