Enable -Wexit-time-destructors for all in-tree library targets and update process-lifetime library statics so they no longer register exit-time destructors. Long-lived caches, lookup tables, singleton registries, and generated constants now use NeverDestroyed or leaked references where the data is intended to live until process exit. Update LibWeb, LibLine, and the binding generators so regenerated sources follow the same rule instead of reintroducing destructed statics.
99 lines
3.3 KiB
C++
99 lines
3.3 KiB
C++
/*
|
|
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/NeverDestroyed.h>
|
|
#include <LibCore/DirIterator.h>
|
|
#include <LibCore/ResourceImplementation.h>
|
|
#include <LibCore/ResourceImplementationFile.h>
|
|
#include <LibCore/System.h>
|
|
|
|
namespace Core {
|
|
|
|
static auto& installed_resource_implementation()
|
|
{
|
|
static NeverDestroyed<OwnPtr<ResourceImplementation>> implementation;
|
|
return *implementation;
|
|
}
|
|
|
|
void ResourceImplementation::install(OwnPtr<ResourceImplementation> the)
|
|
{
|
|
installed_resource_implementation() = move(the);
|
|
}
|
|
|
|
ResourceImplementation& ResourceImplementation::the()
|
|
{
|
|
auto& implementation = installed_resource_implementation();
|
|
if (!implementation)
|
|
install(make<ResourceImplementationFile>("/res"_string));
|
|
return *implementation;
|
|
}
|
|
|
|
NonnullRefPtr<Resource> ResourceImplementation::make_resource(String full_path, NonnullOwnPtr<Core::MappedFile> file, time_t modified_time)
|
|
{
|
|
return adopt_ref(*new Resource(move(full_path), Resource::Scheme::Resource, move(file), modified_time));
|
|
}
|
|
|
|
NonnullRefPtr<Resource> ResourceImplementation::make_resource(String full_path, ByteBuffer buffer, time_t modified_time)
|
|
{
|
|
return adopt_ref(*new Resource(move(full_path), Resource::Scheme::Resource, move(buffer), modified_time));
|
|
}
|
|
|
|
NonnullRefPtr<Resource> ResourceImplementation::make_directory_resource(String full_path, time_t modified_time)
|
|
{
|
|
return adopt_ref(*new Resource(move(full_path), Resource::Scheme::Resource, Resource::DirectoryTag {}, modified_time));
|
|
}
|
|
|
|
ErrorOr<NonnullRefPtr<Resource>> ResourceImplementation::load_from_uri(StringView uri)
|
|
{
|
|
StringView const file_scheme = "file://"sv;
|
|
StringView const resource_scheme = "resource://"sv;
|
|
|
|
if (uri.starts_with(resource_scheme))
|
|
return load_from_resource_scheme_uri(uri);
|
|
|
|
if (uri.starts_with(file_scheme)) {
|
|
auto path = uri.substring_view(file_scheme.length());
|
|
auto utf8_path = TRY(String::from_utf8(path));
|
|
auto st = TRY(System::stat(utf8_path));
|
|
if (S_ISDIR(st.st_mode))
|
|
return adopt_ref(*new Resource(utf8_path, Resource::Scheme::File, Resource::DirectoryTag {}, st.st_mtime));
|
|
auto mapped_file = TRY(MappedFile::map(path));
|
|
return adopt_ref(*new Resource(utf8_path, Resource::Scheme::File, move(mapped_file), st.st_mtime));
|
|
}
|
|
|
|
dbgln("ResourceImplementation: Unknown scheme for {}", uri);
|
|
return Error::from_string_literal("Invalid scheme");
|
|
}
|
|
|
|
Vector<String> ResourceImplementation::child_names(Resource const& resource)
|
|
{
|
|
if (!resource.is_directory())
|
|
return {};
|
|
|
|
if (resource.m_scheme == Resource::Scheme::Resource)
|
|
return child_names_for_resource_scheme(resource);
|
|
|
|
VERIFY(resource.m_scheme == Resource::Scheme::File);
|
|
|
|
Vector<String> children;
|
|
Core::DirIterator it(resource.filesystem_path().to_byte_string(), Core::DirIterator::SkipParentAndBaseDir);
|
|
while (it.has_next())
|
|
children.append(MUST(String::from_byte_string(it.next_path())));
|
|
|
|
return children;
|
|
}
|
|
|
|
String ResourceImplementation::filesystem_path(Resource const& resource)
|
|
{
|
|
if (resource.m_scheme == Resource::Scheme::Resource)
|
|
return filesystem_path_for_resource_scheme(resource.m_path);
|
|
|
|
VERIFY(resource.m_scheme == Resource::Scheme::File);
|
|
|
|
return resource.m_path;
|
|
}
|
|
|
|
}
|