diff --git a/Userland/Libraries/LibCore/ConfigFile.cpp b/Userland/Libraries/LibCore/ConfigFile.cpp index 4e7ad28665..412aa393e1 100644 --- a/Userland/Libraries/LibCore/ConfigFile.cpp +++ b/Userland/Libraries/LibCore/ConfigFile.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Jakob-Niklas See * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,35 +14,52 @@ namespace Core { -NonnullRefPtr ConfigFile::get_for_lib(const String& lib_name) +NonnullRefPtr ConfigFile::get_for_lib(String const& lib_name, AllowWriting allow_altering) { String directory = StandardPaths::config_directory(); auto path = String::formatted("{}/lib/{}.ini", directory, lib_name); - return adopt_ref(*new ConfigFile(path)); + return adopt_ref(*new ConfigFile(path, allow_altering)); } -NonnullRefPtr ConfigFile::get_for_app(const String& app_name) +NonnullRefPtr ConfigFile::get_for_app(String const& app_name, AllowWriting allow_altering) { String directory = StandardPaths::config_directory(); auto path = String::formatted("{}/{}.ini", directory, app_name); - return adopt_ref(*new ConfigFile(path)); + return adopt_ref(*new ConfigFile(path, allow_altering)); } -NonnullRefPtr ConfigFile::get_for_system(const String& app_name) +NonnullRefPtr ConfigFile::get_for_system(String const& app_name, AllowWriting allow_altering) { auto path = String::formatted("/etc/{}.ini", app_name); - return adopt_ref(*new ConfigFile(path)); + return adopt_ref(*new ConfigFile(path, allow_altering)); } -NonnullRefPtr ConfigFile::open(const String& path) +NonnullRefPtr ConfigFile::open(String const& filename, AllowWriting allow_altering) { - return adopt_ref(*new ConfigFile(path)); + return adopt_ref(*new ConfigFile(filename, allow_altering)); } -ConfigFile::ConfigFile(const String& filename) - : m_filename(filename) +NonnullRefPtr ConfigFile::open(String const& filename, int fd) { + return adopt_ref(*new ConfigFile(filename, fd)); +} + +ConfigFile::ConfigFile(const String& filename, AllowWriting allow_altering) + : m_file(File::construct(filename)) +{ + if (!m_file->open(allow_altering == AllowWriting::Yes ? OpenMode::ReadWrite : OpenMode::ReadOnly)) + return; + + reparse(); +} + +ConfigFile::ConfigFile(String const& filename, int fd) + : m_file(File::construct(filename)) +{ + if (!m_file->open(fd, OpenMode::ReadWrite, File::ShouldCloseFileDescriptor::Yes)) + return; + reparse(); } @@ -54,14 +72,10 @@ void ConfigFile::reparse() { m_groups.clear(); - auto file = File::construct(m_filename); - if (!file->open(OpenMode::ReadOnly)) - return; - HashMap* current_group = nullptr; - while (file->can_read_line()) { - auto line = file->read_line(); + while (m_file->can_read_line()) { + auto line = m_file->read_line(); auto* cp = line.characters(); while (*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n')) @@ -149,19 +163,15 @@ bool ConfigFile::sync() if (!m_dirty) return true; - FILE* fp = fopen(m_filename.characters(), "wb"); - if (!fp) - return false; + m_file->truncate(0); for (auto& it : m_groups) { - outln(fp, "[{}]", it.key); + m_file->write(String::formatted("[{}]\n", it.key)); for (auto& jt : it.value) - outln(fp, "{}={}", jt.key, jt.value); - outln(fp); + m_file->write(String::formatted("{}={}\n", jt.key, jt.value)); + m_file->write("\n"); } - fclose(fp); - m_dirty = false; return true; } diff --git a/Userland/Libraries/LibCore/ConfigFile.h b/Userland/Libraries/LibCore/ConfigFile.h index 7c90087ad5..bfce1c95ad 100644 --- a/Userland/Libraries/LibCore/ConfigFile.h +++ b/Userland/Libraries/LibCore/ConfigFile.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Jakob-Niklas See * * SPDX-License-Identifier: BSD-2-Clause */ @@ -11,16 +12,23 @@ #include #include #include +#include #include namespace Core { class ConfigFile : public RefCounted { public: - static NonnullRefPtr get_for_lib(const String& lib_name); - static NonnullRefPtr get_for_app(const String& app_name); - static NonnullRefPtr get_for_system(const String& app_name); - static NonnullRefPtr open(const String& path); + enum class AllowWriting { + Yes, + No, + }; + + static NonnullRefPtr get_for_lib(String const& lib_name, AllowWriting = AllowWriting::No); + static NonnullRefPtr get_for_app(String const& app_name, AllowWriting = AllowWriting::No); + static NonnullRefPtr get_for_system(String const& app_name, AllowWriting = AllowWriting::No); + static NonnullRefPtr open(String const& filename, AllowWriting = AllowWriting::No); + static NonnullRefPtr open(String const& filename, int fd); ~ConfigFile(); bool has_group(const String&) const; @@ -49,14 +57,15 @@ public: void remove_group(const String& group); void remove_entry(const String& group, const String& key); - String filename() const { return m_filename; } + String filename() const { return m_file->filename(); } private: - explicit ConfigFile(const String& filename); + explicit ConfigFile(String const& filename, AllowWriting); + explicit ConfigFile(String const& filename, int fd); void reparse(); - String m_filename; + NonnullRefPtr m_file; HashMap> m_groups; bool m_dirty { false }; };