#pragma once
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <vector>
#include <ranges>
#include <algorithm>
#include "../std/expected.hpp"
#include "../std/filesystem.hpp"
#include "../lib/env.hpp"
#include "../macro.hpp"
namespace ns_filesystems::ns_layers
{
namespace
{
namespace fs = std::filesystem;
}
class Layers
{
private:
struct Layer
{
fs::path const path;
uint64_t offset;
uint64_t size;
};
std::vector<Layer> layers;
[[nodiscard]]
Value<void> append_file(fs::path
const& path)
{
return_if(not
ns_dwarfs::is_dwarfs(path), Error(
"W::Skipping invalid dwarfs filesystem '{}'", path));
layers.push_back({path, 0, std::filesystem::file_size(path)});
return {};
}
[[nodiscard]]
Value<void> append_directory(fs::path
const& path)
{
std::ranges::sort(result);
for(auto&& file : result)
{
append_file(file).discard("W::Failed to append layer from directory");
}
return {};
}
public:
{
if(Try(fs::is_regular_file(path)))
{
append_file(path).discard("W::Failed to append layer from regular file");
}
else if(Try(fs::is_directory(path)))
{
append_directory(path).discard("W::Failed to append layer from directory");
}
return {};
}
{
.transform([](
auto&& e){
return ns_env::expand(e).value_or(std::string{e}); })
.value_or(std::string{})
| std::views::split(':')
| std::views::transform([](auto&& e){ return fs::path(e.begin(), e.end()); })
)
{
}
return {};
}
{
return layers;
}
void push_binary(fs::path
const& path_file_binary, uint64_t offset)
{
std::ifstream file_binary(path_file_binary, std::ios::binary);
file_binary.seekg(offset);
while (true)
{
uint64_t size_fs;
break_if(not file_binary.read(reinterpret_cast<char*>(&size_fs), sizeof(size_fs))
, "D::Stopped reading at offset {}", offset
);
logger(
"D::Filesystem size is '{}'", size_fs);
break_if(size_fs <= 0, "E::Invalid filesystem size '{}' at offset {}", size_fs, offset);
offset += 8;
, "E::Invalid dwarfs filesystem appended on the image"
);
layers.push_back({path_file_binary, offset, size_fs});
offset += size_fs;
file_binary.seekg(offset);
}
file_binary.close();
}
};
}
std::vector< Layer > const & get_layers() const
Retrieves the collected layer file paths with offsets.
Value< void > push_from_var(std::string_view var)
Loads layers from a colon-separated environment variable.
Value< void > push(fs::path const &path)
Adds a layer from a file or directory path.
void push_binary(fs::path const &path_file_binary, uint64_t offset)
Scans a binary file for embedded DwarFS filesystems.
Manage dwarfs filesystems.
#define logger(fmt,...)
Compile-time log level dispatch macro with automatic location capture.
Value< std::string > expand(ns_concept::StringRepresentable auto &&var)
Performs variable expansion analogous to a POSIX shell.
Value< std::string > get_expected(std::string_view name)
Get the value of an environment variable.
bool is_dwarfs(fs::path const &path_file_dwarfs, uint64_t offset=0)
Checks if the filesystem is a Dwarfs filesystem with a given offset.
Value< std::vector< fs::path > > regular_files(fs::path const &path_dir_src)
List the files in a directory.
Enhanced expected type with integrated logging capabilities.