21#include <unordered_map>
41#error "FIM_VERSION is undefined"
46#error "FIM_COMMIT is undefined"
51#error "FIM_DIST is undefined"
56#error "FIM_TIMESTAMP is undefined"
61#error "FIM_FILE_TOOLS is undefined"
66#error "FIM_FILE_META is undefined"
70#ifndef FIM_RESERVED_SIZE
71 #error "FIM_RESERVED_SIZE is undefined"
74extern "C" uint32_t FIM_RESERVED_OFFSET;
76using DaemonMode = ns_db::ns_portal::ns_daemon::Mode;
91ENUM(Distribution, ARCH, ALPINE, BLUEPRINT)
96namespace fs = std::filesystem;
169 fs::path
self = path_bin_self.parent_path();
170 fs::path
global = fs::path(
"/tmp/fim");
171 fs::path
app =
global /
"app" / std::format(
"{}_{}", FIM_COMMIT, FIM_TIMESTAMP);
174 fs::path
instance = std::format(
"{}/{}/{}",
app.string(),
"instance", std::to_string(getpid()));
176 fs::path
runtime = fs::path(
"/tmp/fim/run");
179 fs::path
host_data = getenv(
"FIM_DIR_DATA")?:
180 self / std::format(
".{}.data", path_bin_self.filename().string());
189 .self = std::move(
self),
190 .global = std::move(
global),
191 .app = std::move(
app),
195 .portal = std::move(
portal),
214 static File create(fs::path
const& path_dir_instance)
217 .bashrc = path_dir_instance /
"bashrc",
218 .passwd = path_dir_instance /
"passwd"
239 .bash = path_dir_app_bin /
"bash",
240 .janitor = path_dir_app_bin /
"fim_janitor",
241 .portal_daemon = path_dir_app_bin /
"fim_portal_daemon",
242 .portal_dispatcher = path_dir_app_bin /
"fim_portal"
259 auto dir = Pop(Dir::create());
260 auto file = File::create(dir.instance);
261 auto bin = Pop(Bin::create(dir.app_bin));
262 return Path(dir, file, bin);
266 Path(Dir
const& dir, File
const& file, Bin
const& bin)
317 Logs(fs::path
const& path_dir_log)
318 :
bwrap(path_dir_log /
"bwrap")
324 .path_file_dwarfs = path_dir_log /
"fuse" /
"dwarfs.log",
325 .path_file_ciopfs = path_dir_log /
"fuse" /
"ciopfs.log",
326 .path_file_overlayfs = path_dir_log /
"fuse" /
"overlayfs.log",
327 .path_file_unionfs = path_dir_log /
"fuse" /
"unionfs.log",
328 .path_file_janitor = path_dir_log /
"fuse" /
"janitor.log",
332 fs::create_directories(path_dir_log);
333 fs::create_directories(path_dir_log /
"bwrap");
334 fs::create_directories(path_dir_log /
"daemon" /
"host");
335 fs::create_directories(path_dir_log /
"fuse" /
"guest");
336 fs::create_directories(path_dir_log /
"dispatcher");
383 bool const is_casefold,
384 fs::path
const& path_dir_instance,
385 fs::path
const& path_dir_host_data,
386 fs::path
const& path_bin_janitor,
387 fs::path
const& path_bin_self,
388 fs::path
const& path_bin_portal_daemon,
389 fs::path
const& path_dir_portal
393 auto path_dir_mount = path_dir_instance /
"mount";
394 auto path_dir_work = path_dir_host_data /
"work" / std::to_string(getpid());
395 auto path_dir_upper = path_dir_host_data /
"root";
396 auto path_dir_layers = path_dir_instance /
"layers";
397 auto path_dir_ciopfs = path_dir_host_data /
"casefold";
400 fs::create_directories(path_dir_mount);
401 fs::create_directories(path_dir_work);
402 fs::create_directories(path_dir_upper);
403 fs::create_directories(path_dir_layers);
404 fs::create_directories(path_dir_ciopfs);
407 using ns_reserved::ns_overlay::OverlayType;
408 OverlayType overlay_type =
409 ns_env::exists(
"FIM_OVERLAY",
"unionfs")? ns_reserved::ns_overlay::OverlayType::UNIONFS
410 :
ns_env::exists(
"FIM_OVERLAY",
"overlayfs")? ns_reserved::ns_overlay::OverlayType::OVERLAYFS
411 :
ns_env::exists(
"FIM_OVERLAY",
"bwrap")? ns_reserved::ns_overlay::OverlayType::BWRAP
413 .value_or(OverlayType::BWRAP).get();
414 if(is_casefold and overlay_type == ns_reserved::ns_overlay::OverlayType::BWRAP)
416 logger(
"W::casefold cannot be used with bwrap overlayfs, falling back to unionfs");
417 overlay_type = ns_reserved::ns_overlay::OverlayType::UNIONFS;
421 uint32_t
const compression_level = ({
422 std::string str_compression_level =
ns_env::get_expected<
"D">(
"FIM_COMPRESSION_LEVEL").value_or(
"7");
423 uint64_t level = Catch(std::stoull(str_compression_level)).value_or(7);
424 std::clamp(level, uint64_t{0}, uint64_t{9});
430 .is_casefold = is_casefold,
431 .compression_level = compression_level,
432 .overlay_type = overlay_type,
433 .path_dir_mount = std::move(path_dir_mount),
434 .path_dir_work = std::move(path_dir_work),
435 .path_dir_upper = std::move(path_dir_upper),
436 .path_dir_layers = std::move(path_dir_layers),
437 .path_dir_ciopfs = std::move(path_dir_ciopfs),
438 .path_bin_janitor = path_bin_janitor,
439 .path_bin_self = path_bin_self,
446 , path_bin_portal_daemon
450 , path_bin_portal_daemon
457 .fuse = std::move(
fuse),
458 .daemon = std::move(daemon)
503 or (environment.contains(
"UID") and environment.at(
"UID") ==
"0");
533 struct passwd *pw = getpwuid(getuid());
534 return_if(not pw, Error(
"E::Failed to get current user info"));
541 .uid =
static_cast<mode_t
>(Catch(std::stoul(Catch(variables.at(
"UID")).or_default())).value_or(pw->pw_uid)),
542 .gid =
static_cast<mode_t
>(Catch(std::stoul(Catch(variables.at(
"GID")).or_default())).value_or(pw->pw_gid)),
548 .name = (
id.uid == 0)?
"root"
549 : variables.contains(
"USER")? variables.at(
"USER")
551 .path_dir_home = (
id.uid == 0)?
"/root"
552 : variables.contains(
"HOME")? variables.at(
"HOME")
554 .path_file_shell = variables.contains(
"SHELL")? fs::path{variables.at(
"SHELL")}
556 .path_file_bashrc =
path.file.bashrc,
557 .path_file_passwd =
path.file.passwd,
560 Pop(user.write_bashrc(
path.file.bashrc, variables.contains(
"PS1")? variables.at(
"PS1") :
""));
561 Pop(user.write_passwd(
path.file.passwd));
565 ns_reserved::ns_overlay::OverlayType overlay_type()
568 using ns_reserved::ns_overlay::OverlayType;
569 OverlayType overlay_type =
ns_env::exists(
"FIM_OVERLAY",
"unionfs")? ns_reserved::ns_overlay::OverlayType::UNIONFS
570 :
ns_env::exists(
"FIM_OVERLAY",
"overlayfs")? ns_reserved::ns_overlay::OverlayType::OVERLAYFS
571 :
ns_env::exists(
"FIM_OVERLAY",
"bwrap")? ns_reserved::ns_overlay::OverlayType::BWRAP
575 if(
flags.
is_casefold and overlay_type == ns_reserved::ns_overlay::OverlayType::BWRAP)
577 logger(
"W::casefold cannot be used with bwrap overlayfs, falling back to unionfs");
578 overlay_type = ns_reserved::ns_overlay::OverlayType::UNIONFS;
592 Distribution
const distribution = Pop(Distribution::from_string(FIM_DIST));
601 Logs logs = Try(
Logs(path.dir.instance /
"logs"));
605 layers.
push_binary(path.bin.self, FIM_RESERVED_OFFSET + FIM_RESERVED_SIZE);
606 layers.
push_from_var(
"FIM_LAYERS").discard(
"W::Failed to setup FIM_LAYERS");
607 layers.
push(path.dir.host_data_layers).discard(
"W::Failed to setup host_data_layers");
617 path.bin.portal_daemon,
625 , std::format(
"/usr/lib/x86_64-linux-gnu:/usr/lib/i386-linux-gnu:{}", ret.value())
632 ,
"/usr/lib/x86_64-linux-gnu:/usr/lib/i386-linux-gnu"
638 std::string env_path = path.dir.app_bin.string()
642 +
"/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin"
644 + path.dir.app_sbin.string();
648 pid_t pid = getpid();
652 ns_env::set(
"FIM_DIR_SELF", path.dir.self, ns_env::Replace::Y);
653 ns_env::set(
"FIM_DIR_GLOBAL", path.dir.global, ns_env::Replace::Y);
654 ns_env::set(
"FIM_DIR_APP", path.dir.app, ns_env::Replace::Y);
655 ns_env::set(
"FIM_DIR_APP_BIN", path.dir.app_bin, ns_env::Replace::Y);
656 ns_env::set(
"FIM_DIR_APP_SBIN", path.dir.app_sbin, ns_env::Replace::Y);
657 ns_env::set(
"FIM_DIR_INSTANCE", path.dir.instance, ns_env::Replace::Y);
658 ns_env::set(
"FIM_DIR_LAYERS", path.dir.host_data_layers, ns_env::Replace::Y);
660 ns_env::set(
"FIM_DIST", FIM_DIST, ns_env::Replace::Y);
661 ns_env::set(
"FIM_DIR_RUNTIME", path.dir.runtime, ns_env::Replace::Y);
662 ns_env::set(
"FIM_DIR_RUNTIME_HOST", path.dir.runtime_host, ns_env::Replace::Y);
663 ns_env::set(
"FIM_DIR_DATA", path.dir.host_data, ns_env::Replace::Y);
666 return std::shared_ptr<FlatImage>(
new FlatImage{
667 .distribution = distribution,
Configures and launches bubblewrap
Manages the casefold reserved space.
Defines all fundamental FlatImage paths.
static Value< Path > create()
Factory method to create Path configuration.
Manages external DwarFS layer files and directories for the filesystem controller.
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.
Manages filesystems used by flatimage.
Defines a class that manages FlatImage's portal configuration.
Manages environment variables in flatimage.
Defines a class that manages FlatImage's portal dispatcher configuration.
Custom enumeration class.
Enhanced error handling framework built on std::expected.
Layer management for DwarFS filesystems.
A library for manipulating environment variables.
A library for file logging.
#define logger(fmt,...)
Compile-time log level dispatch macro with automatic location capture.
Simplified macros for common control flow patterns with optional logging.
Bubblewrap proxy types and user configuration.
Central FlatImage configuration system.
Value< std::shared_ptr< FlatImage > > config()
Factory method that makes a FlatImage configuration object.
Value< std::vector< std::string > > get(fs::path const &path_file_binary)
Get existing variables from the database.
Value< std::string > get_expected(std::string_view name)
Get the value of an environment variable.
bool exists(std::string_view name, std::string_view value)
Checks if variable exists and equals value.
void set(T &&name, U &&value, Replace replace)
Sets an environment variable.
FlatImage filesystem layer implementations.
Value< fs::path > create_directories(fs::path const &p)
Creates directories recursively.
Value< uint8_t > read(fs::path const &path_file_binary)
Read a notification flag from the flatimage binary.
Value< uint8_t > read(fs::path const &path_file_binary)
Read a notification flag from the flatimage binary.
Value< OverlayType > read(fs::path const &path_file_binary)
Read the overlay mask from the flatimage binary.
Manages the notify reserved space.
Manages the overlay reserved space.
Enhanced expected type with integrated logging capabilities.
A pair of uid and gid mode_t values.
The representation of a user in bubblewrap.
Portal daemon configuration.
ns_db::ns_portal::ns_daemon::Daemon const host
Host-side portal daemon.
ns_db::ns_portal::ns_daemon::Daemon const guest
Guest-side portal daemon.
Module configurations linked with FlatImage paths.
ns_filesystems::ns_controller::Config fuse
Fuse subsystem configuration.
static Value< Config > create(ns_filesystems::ns_layers::Layers const &layers, bool const is_casefold, fs::path const &path_dir_instance, fs::path const &path_dir_host_data, fs::path const &path_bin_janitor, fs::path const &path_bin_self, fs::path const &path_bin_portal_daemon, fs::path const &path_dir_portal)
Factory method to create Config.
static Value< Flags > create(fs::path const &path_bin_self)
Factory method to create Flags.
bool is_debug
Enable debug logging? Set via FIM_DEBUG=1.
bool is_notify
Show desktop notifications? Stored in reserved space.
bool is_casefold
Enable case-insensitive filesystem? Via FIM_CASEFOLD or reserved space.
bool is_root
Execute as root (UID=0)? Checked via FIM_ROOT env or stored UID.
Main FlatImage configuration object.
pid_t const pid
Current instance process ID.
Path path
Directory, file, and binary paths.
Distribution const distribution
Linux distribution (ARCH/ALPINE/BLUEPRINT)
Flags flags
Runtime feature flags.
Logs logs
Log file paths for all subsystems.
Config config
Module configurations (filesystem, daemon)
Log file paths for all FlatImage subsystems.
ns_bwrap::ns_proxy::Logs const bwrap
Bubblewrap sandbox log paths.
ns_db::ns_portal::ns_daemon::ns_log::Logs const daemon_guest
Guest portal daemon logs.
fs::path const path_file_boot
Boot initialization log file.
ns_db::ns_portal::ns_dispatcher::Logs const dispatcher
Portal dispatcher logs.
ns_db::ns_portal::ns_daemon::ns_log::Logs const daemon_host
Host portal daemon logs.
ns_filesystems::ns_controller::Logs const filesystems
Filesystem subsystem logs.
Paths to embedded and extracted binaries.
fs::path const portal_daemon
Portal daemon for host-container IPC.
fs::path const self
Path to the FlatImage binary itself.
fs::path const portal_dispatcher
Portal dispatcher for command routing.
fs::path const janitor
Janitor cleanup process.
fs::path const bash
Embedded bash shell.
Directory paths used throughout FlatImage.
fs::path const app
Application directory (versioned by commit/timestamp)
fs::path const app_bin
Application binaries directory.
fs::path const runtime
Runtime directory (/tmp/fim/run)
fs::path const runtime_host
Host-side runtime directory.
fs::path const host_data_layers
Layers directory in data directory.
fs::path const app_sbin
Application system binaries directory.
fs::path const self
Parent directory of the FlatImage binary.
fs::path const global
Global temporary directory (/tmp/fim)
fs::path const host_data
Data directory next to binary.
fs::path const instance
Instance-specific directory (per-PID)
fs::path const host_data_tmp
Temporary files in data directory.
fs::path const portal
Portal directory for IPC.
fs::path const host_home
Relative path to user's home directory.
Instance-specific configuration files.
fs::path const bashrc
Path to instance-specific bashrc file.
fs::path const passwd
Path to instance-specific passwd file.