mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 20:27:35 +00:00
LibCore: Support using a file descriptor for opening ConfigFile
This patch adds support for opening a ConfigFile using a file descriptor rather than trying to open a the file by name directly. In contrast to the previous implementation, ConfigFile now always keeps a reference to an open File and does not reopen it for writing. This requires providing an additional argument to open functions if a file gets opened based on its name and the user of the api intends to write to the file in the future.
This commit is contained in:
parent
dee3b7b8c9
commit
2ea2d026c2
2 changed files with 50 additions and 31 deletions
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2021, Jakob-Niklas See <git@nwex.de>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -13,35 +14,52 @@
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
NonnullRefPtr<ConfigFile> ConfigFile::get_for_lib(const String& lib_name)
|
NonnullRefPtr<ConfigFile> ConfigFile::get_for_lib(String const& lib_name, AllowWriting allow_altering)
|
||||||
{
|
{
|
||||||
String directory = StandardPaths::config_directory();
|
String directory = StandardPaths::config_directory();
|
||||||
auto path = String::formatted("{}/lib/{}.ini", directory, lib_name);
|
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> ConfigFile::get_for_app(const String& app_name)
|
NonnullRefPtr<ConfigFile> ConfigFile::get_for_app(String const& app_name, AllowWriting allow_altering)
|
||||||
{
|
{
|
||||||
String directory = StandardPaths::config_directory();
|
String directory = StandardPaths::config_directory();
|
||||||
auto path = String::formatted("{}/{}.ini", directory, app_name);
|
auto path = String::formatted("{}/{}.ini", directory, app_name);
|
||||||
return adopt_ref(*new ConfigFile(path));
|
return adopt_ref(*new ConfigFile(path, allow_altering));
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<ConfigFile> ConfigFile::get_for_system(const String& app_name)
|
NonnullRefPtr<ConfigFile> ConfigFile::get_for_system(String const& app_name, AllowWriting allow_altering)
|
||||||
{
|
{
|
||||||
auto path = String::formatted("/etc/{}.ini", app_name);
|
auto path = String::formatted("/etc/{}.ini", app_name);
|
||||||
return adopt_ref(*new ConfigFile(path));
|
return adopt_ref(*new ConfigFile(path, allow_altering));
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<ConfigFile> ConfigFile::open(const String& path)
|
NonnullRefPtr<ConfigFile> 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)
|
NonnullRefPtr<ConfigFile> ConfigFile::open(String const& filename, int fd)
|
||||||
: m_filename(filename)
|
|
||||||
{
|
{
|
||||||
|
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();
|
reparse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +72,10 @@ void ConfigFile::reparse()
|
||||||
{
|
{
|
||||||
m_groups.clear();
|
m_groups.clear();
|
||||||
|
|
||||||
auto file = File::construct(m_filename);
|
|
||||||
if (!file->open(OpenMode::ReadOnly))
|
|
||||||
return;
|
|
||||||
|
|
||||||
HashMap<String, String>* current_group = nullptr;
|
HashMap<String, String>* current_group = nullptr;
|
||||||
|
|
||||||
while (file->can_read_line()) {
|
while (m_file->can_read_line()) {
|
||||||
auto line = file->read_line();
|
auto line = m_file->read_line();
|
||||||
auto* cp = line.characters();
|
auto* cp = line.characters();
|
||||||
|
|
||||||
while (*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n'))
|
while (*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n'))
|
||||||
|
@ -149,19 +163,15 @@ bool ConfigFile::sync()
|
||||||
if (!m_dirty)
|
if (!m_dirty)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
FILE* fp = fopen(m_filename.characters(), "wb");
|
m_file->truncate(0);
|
||||||
if (!fp)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto& it : m_groups) {
|
for (auto& it : m_groups) {
|
||||||
outln(fp, "[{}]", it.key);
|
m_file->write(String::formatted("[{}]\n", it.key));
|
||||||
for (auto& jt : it.value)
|
for (auto& jt : it.value)
|
||||||
outln(fp, "{}={}", jt.key, jt.value);
|
m_file->write(String::formatted("{}={}\n", jt.key, jt.value));
|
||||||
outln(fp);
|
m_file->write("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2021, Jakob-Niklas See <git@nwex.de>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -11,16 +12,23 @@
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibCore/File.h>
|
||||||
#include <LibGfx/Color.h>
|
#include <LibGfx/Color.h>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
class ConfigFile : public RefCounted<ConfigFile> {
|
class ConfigFile : public RefCounted<ConfigFile> {
|
||||||
public:
|
public:
|
||||||
static NonnullRefPtr<ConfigFile> get_for_lib(const String& lib_name);
|
enum class AllowWriting {
|
||||||
static NonnullRefPtr<ConfigFile> get_for_app(const String& app_name);
|
Yes,
|
||||||
static NonnullRefPtr<ConfigFile> get_for_system(const String& app_name);
|
No,
|
||||||
static NonnullRefPtr<ConfigFile> open(const String& path);
|
};
|
||||||
|
|
||||||
|
static NonnullRefPtr<ConfigFile> get_for_lib(String const& lib_name, AllowWriting = AllowWriting::No);
|
||||||
|
static NonnullRefPtr<ConfigFile> get_for_app(String const& app_name, AllowWriting = AllowWriting::No);
|
||||||
|
static NonnullRefPtr<ConfigFile> get_for_system(String const& app_name, AllowWriting = AllowWriting::No);
|
||||||
|
static NonnullRefPtr<ConfigFile> open(String const& filename, AllowWriting = AllowWriting::No);
|
||||||
|
static NonnullRefPtr<ConfigFile> open(String const& filename, int fd);
|
||||||
~ConfigFile();
|
~ConfigFile();
|
||||||
|
|
||||||
bool has_group(const String&) const;
|
bool has_group(const String&) const;
|
||||||
|
@ -49,14 +57,15 @@ public:
|
||||||
void remove_group(const String& group);
|
void remove_group(const String& group);
|
||||||
void remove_entry(const String& group, const String& key);
|
void remove_entry(const String& group, const String& key);
|
||||||
|
|
||||||
String filename() const { return m_filename; }
|
String filename() const { return m_file->filename(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ConfigFile(const String& filename);
|
explicit ConfigFile(String const& filename, AllowWriting);
|
||||||
|
explicit ConfigFile(String const& filename, int fd);
|
||||||
|
|
||||||
void reparse();
|
void reparse();
|
||||||
|
|
||||||
String m_filename;
|
NonnullRefPtr<File> m_file;
|
||||||
HashMap<String, HashMap<String, String>> m_groups;
|
HashMap<String, HashMap<String, String>> m_groups;
|
||||||
bool m_dirty { false };
|
bool m_dirty { false };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue