48namespace fs = std::filesystem;
70 CmdType variant_cmd = Pop(
ns_parser::parse(argc, argv),
"C::Could not parse arguments");
77 [[maybe_unused]]
auto filesystem_controller =
84 fs::path path_dir_root = ( fim.
flags.
is_casefold and fuse.overlay_type != ns_reserved::ns_overlay::OverlayType::BWRAP )?
86 : fuse.path_dir_mount;
87 logger(
"D::Bwrap root: {}", path_dir_root);
90 logger(
"D::User: {}", std::string{user.data});
101 if(fuse.overlay_type == ns_reserved::ns_overlay::OverlayType::BWRAP)
106 , .path_dir_upper = fuse.path_dir_upper
107 , .path_dir_work = fuse.path_dir_work
119 if (permissions.
contains(ns_reserved::ns_permissions::Permission::GPU))
121 std::ignore = bwrap.with_bind_gpu(fuse.path_dir_upper, fim.
path.dir.
runtime_host);
125 , ns_daemon::Mode::HOST
132 ).forward(
"E::Could not start portal daemon");
135 return bwrap.run(permissions
145 auto f_bwrap = [&]<
typename T,
typename U>(T&& program, U&& args) ->
Value<int>
152 log_if(bwrap_run_ret.errno_nr > 0,
"E::Bwrap failed syscall '{}' with errno '{}'", bwrap_run_ret.syscall_nr, bwrap_run_ret.errno_nr);
154 if ( fuse.overlay_type == ns_reserved::ns_overlay::OverlayType::BWRAP and bwrap_run_ret.syscall_nr == SYS_mount )
156 logger(
"E::Bwrap failed SYS_mount, retrying with fuse-unionfs...");
157 fuse.overlay_type = ns_reserved::ns_overlay::OverlayType::UNIONFS;
158 bwrap_run_ret = Pop(f_bwrap_impl(program, args),
"E::Failed to execute bwrap");
160 return bwrap_run_ret.code;
164 if (
auto cmd = std::get_if<ns_parser::CmdExec>(&variant_cmd) )
166 return f_bwrap(cmd->program, cmd->args);
169 else if (
auto cmd = std::get_if<ns_parser::CmdRoot>(&variant_cmd) )
172 return f_bwrap(cmd->program, cmd->args);
175 else if (
auto cmd = std::get_if<ns_parser::CmdPerms>(&variant_cmd) )
180 if(
auto cmd_add = std::get_if<CmdPerms::Add>(&(cmd->sub_cmd)))
182 Pop(permissions.
add(cmd_add->permissions),
"E::Failed to add permissions");
184 else if(std::get_if<CmdPerms::Clear>(&(cmd->sub_cmd)))
186 Pop(permissions.
set_all(
false),
"E::Failed to clear permissions");
188 else if(
auto cmd_del = std::get_if<CmdPerms::Del>(&(cmd->sub_cmd)))
190 Pop(permissions.
del(cmd_del->permissions),
"E::Failed to delete permissions");
192 else if(std::get_if<CmdPerms::List>(&(cmd->sub_cmd)))
194 std::ranges::copy(Pop(permissions.
to_strings(),
"E::Failed to stringfy permissions")
195 , std::ostream_iterator<std::string>(std::cout,
"\n")
198 else if(
auto cmd_set = std::get_if<CmdPerms::Set>(&(cmd->sub_cmd)))
200 Pop(permissions.
set(cmd_set->permissions),
"E::Failed to set permissions");
204 return Error(
"C::Invalid permissions sub-command");
208 else if (
auto cmd = std::get_if<ns_parser::CmdEnv>(&variant_cmd) )
210 if(
auto cmd_add = std::get_if<CmdEnv::Add>(&(cmd->sub_cmd)))
214 else if(std::get_if<CmdEnv::Clear>(&(cmd->sub_cmd)))
218 else if(
auto cmd_del = std::get_if<CmdEnv::Del>(&(cmd->sub_cmd)))
222 else if(std::get_if<CmdEnv::List>(&(cmd->sub_cmd)))
225 , std::ostream_iterator<std::string>(std::cout,
"\n")
228 else if(
auto cmd_set = std::get_if<CmdEnv::Set>(&(cmd->sub_cmd)))
234 return Error(
"C::Invalid environment sub-command");
238 else if (
auto cmd = std::get_if<CmdDesktop>(&variant_cmd))
240 if(
auto cmd_setup = std::get_if<CmdDesktop::Setup>(&(cmd->sub_cmd)))
242 Pop(
ns_desktop::setup(fim, cmd_setup->path_file_setup),
"E::Failed to setup desktop integration");
244 else if(
auto cmd_enable = std::get_if<CmdDesktop::Enable>(&(cmd->sub_cmd)))
246 Pop(
ns_desktop::enable(fim, cmd_enable->set_enable),
"E::Failed to enable desktop integration");
248 else if(std::get_if<CmdDesktop::Clean>(&(cmd->sub_cmd)))
252 else if(
auto cmd_dump = std::get_if<CmdDesktop::Dump>(&(cmd->sub_cmd)))
254 if(
auto cmd_icon = std::get_if<CmdDesktop::Dump::Icon>(&(cmd_dump->sub_cmd)))
258 else if(std::get_if<CmdDesktop::Dump::Entry>(&(cmd_dump->sub_cmd)))
262 else if(std::get_if<CmdDesktop::Dump::MimeType>(&(cmd_dump->sub_cmd)))
268 return Error(
"C::Invalid dump sub-command");
273 return Error(
"C::Invalid desktop sub-command");
277 else if (
auto cmd = std::get_if<ns_parser::CmdLayer>(&variant_cmd) )
279 if(
auto cmd_add = std::get_if<CmdLayer::Add>(&(cmd->sub_cmd)))
283 else if(
auto cmd_commit = std::get_if<CmdLayer::Commit>(&(cmd->sub_cmd)))
287 std::optional<fs::path> path_file_dst;
288 if(std::get_if<CmdLayer::Commit::Binary>(&(cmd_commit->sub_cmd)))
290 mode = ns_layers::CommitMode::BINARY;
292 else if(std::get_if<CmdLayer::Commit::Layer>(&(cmd_commit->sub_cmd)))
294 mode = ns_layers::CommitMode::LAYER;
297 else if(
auto cmd_file = std::get_if<CmdLayer::Commit::File>(&(cmd_commit->sub_cmd)))
299 mode = ns_layers::CommitMode::FILE;
300 path_file_dst = cmd_file->path_file_dst;
304 return Error(
"E::Invalid commit sub-command");
307 Pop(ns_layers::commit(fim.
path.bin.
self
308 , fuse.path_dir_upper
311 , fuse.compression_level
314 ),
"E::Failed to commit layer");
316 else if(
auto cmd_create = std::get_if<CmdLayer::Create>(&(cmd->sub_cmd)))
319 , cmd_create->path_file_target
321 , fuse.compression_level
322 ),
"E::Failed to create layer");
323 logger(
"I::Filesystem created without errors");
325 else if(std::get_if<CmdLayer::List>(&(cmd->sub_cmd)))
331 return Error(
"C::Invalid layer operation");
335 else if (
auto cmd = std::get_if<ns_parser::CmdBind>(&variant_cmd) )
337 if(
auto cmd_add = std::get_if<CmdBind::Add>(&(cmd->sub_cmd)))
343 ,
"E::Failed to add binding");
345 else if(
auto cmd_del = std::get_if<CmdBind::Del>(&(cmd->sub_cmd)))
349 else if(std::get_if<CmdBind::List>(&(cmd->sub_cmd)))
355 return Error(
"C::Invalid bind operation");
358 else if (
auto cmd = std::get_if<ns_parser::CmdNotify>(&variant_cmd) )
363 else if (
auto cmd = std::get_if<ns_parser::CmdCaseFold>(&variant_cmd) )
368 else if (
auto cmd = std::get_if<ns_parser::CmdBoot>(&variant_cmd) )
370 if(std::get_if<CmdBoot::Clear>(&(cmd->sub_cmd)))
377 else if(
auto cmd_set = std::get_if<CmdBoot::Set>(&(cmd->sub_cmd)))
382 boot.set_program(cmd_set->program);
383 boot.set_args(cmd_set->args);
387 else if(std::get_if<CmdBoot::Show>(&(cmd->sub_cmd)))
394 if (
boot.get_program().empty())
396 boot.set_program(
"bash");
403 return Error(
"C::Invalid boot sub-command");
407 else if (
auto cmd = std::get_if<ns_parser::CmdRemote>(&variant_cmd) )
409 if(std::get_if<CmdRemote::Clear>(&(cmd->sub_cmd)))
413 else if(
auto cmd_set = std::get_if<CmdRemote::Set>(&(cmd->sub_cmd)))
417 else if(std::get_if<CmdRemote::Show>(&(cmd->sub_cmd)))
423 return Error(
"C::Invalid remote sub-command");
427 else if (
auto cmd = std::get_if<ns_parser::CmdRecipe>(&variant_cmd) )
429 auto f_fetch = [&fim](std::string
const& recipe,
bool use_existing) ->
Value<std::vector<std::string>>
441 if(
auto cmd_fetch = std::get_if<CmdRecipe::Fetch>(&(cmd->sub_cmd)))
444 for(
auto const& recipe : cmd_fetch->recipes)
446 Pop(f_fetch(recipe,
false),
"E::Failed to fetch recipe");
449 else if(
auto cmd_info = std::get_if<CmdRecipe::Info>(&(cmd->sub_cmd)))
451 for(
auto const& recipe : cmd_info->recipes)
456 else if(
auto cmd_install = std::get_if<CmdRecipe::Install>(&(cmd->sub_cmd)))
458 std::vector<std::string> all_recipes;
460 for(
auto const& recipe : cmd_install->recipes)
462 std::vector<std::string> sub_recipes = Pop(f_fetch(recipe,
true),
"E::Failed to fetch recipe");
463 std::ranges::copy(sub_recipes, std::back_inserter(all_recipes));
471 return Error(
"C::Invalid recipe sub-command");
474 else if (
auto cmd = std::get_if<ns_parser::CmdInstance>(&variant_cmd) )
480 if(
auto cmd_exec = std::get_if<CmdInstance::Exec>(&(cmd->sub_cmd)))
482 return_if(instances.size() == 0, Error(
"C::No instances are running"));
483 return_if(cmd_exec->id < 0 or
static_cast<size_t>(cmd_exec->id) >= instances.size()
484 , Error(
"C::Instance index out of bounds")
487 Instance instance = instances.at(cmd_exec->id);
490 , ns_daemon::Mode::GUEST
497 .with_args(cmd_exec->args)
500 else if(std::get_if<CmdInstance::List>(&(cmd->sub_cmd)))
502 for(uint32_t i = 0; Instance
const& instance : instances)
504 std::println(
"{}:{}", i++, instance.path.filename().string());
509 return Error(
"C::Invalid instance operation");
512 else if (
auto cmd = std::get_if<ns_parser::CmdOverlay>(&variant_cmd) )
514 if(
auto cmd_set = std::get_if<CmdOverlay::Set>(&(cmd->sub_cmd)))
518 else if(std::get_if<CmdOverlay::Show>(&(cmd->sub_cmd)))
520 std::println(
"{}", std::string{fuse.overlay_type});
524 return Error(
"C::Invalid operation for fim-overlay");
527 else if (
auto cmd = std::get_if<ns_parser::CmdUnshare>(&variant_cmd) )
529 if(
auto cmd_set = std::get_if<CmdUnshare::Set>(&(cmd->sub_cmd)))
533 else if(
auto cmd_add = std::get_if<CmdUnshare::Add>(&(cmd->sub_cmd)))
537 else if(
auto cmd_del = std::get_if<CmdUnshare::Del>(&(cmd->sub_cmd)))
541 else if(std::get_if<CmdUnshare::Clear>(&(cmd->sub_cmd)))
545 else if(std::get_if<CmdUnshare::List>(&(cmd->sub_cmd)))
551 return Error(
"C::Invalid operation for fim-unshare");
554 else if (
auto cmd = std::get_if<ns_parser::CmdVersion>(&variant_cmd) )
556 if(
auto cmd_short = std::get_if<CmdVersion::Short>(&(cmd->sub_cmd)))
558 std::println(
"{}", cmd_short->dump());
560 else if(
auto cmd_full = std::get_if<CmdVersion::Full>(&(cmd->sub_cmd)))
562 std::println(
"{}", Pop(cmd_full->dump(),
"E::Failed to dump full version info"));
564 else if(
auto cmd_deps = std::get_if<CmdVersion::Deps>(&(cmd->sub_cmd)))
566 std::println(
"{}", Pop(cmd_deps->dump(),
"E::Failed to dump dependencies info"));
570 return Error(
"C::Invalid operation for fim-version");
574 else if ( std::get_if<ns_parser::CmdNone>(&variant_cmd) )
580 fs::path program =
boot.get_program().empty() ?
584 std::vector<std::string> args =
boot.get_args();
586 std::copy(argv+1, argv+argc, std::back_inserter(args));
588 return f_bwrap(program, args);
590 else if ( std::get_if<ns_parser::CmdExit>(&variant_cmd) )
596 return Error(
"C::Unknown command");
Value< int > boot(int argc, char **argv)
Boots the main flatimage program and the portal process.
Configures and launches bubblewrap
Manages the casefold reserved space.
Manages bubblewrap (bwrap) containerization.
Manages FlatImage permissions stored in reserved space.
Value< std::set< std::string > > to_strings() const noexcept
Converts enabled permissions to string representations.
Value< void > add(std::set< Permission > const &permissions)
Adds permissions to existing configuration.
Value< void > set_all(bool value)
Sets all permissions to the specified value.
Value< void > del(std::set< Permission > const &permissions)
Removes permissions from existing configuration.
bool contains(Permission const &permission) const noexcept
Checks if a specific permission is enabled.
Value< void > set(std::set< Permission > const &permissions)
Sets the specified permissions (replaces existing)
Manages FlatImage unshare options stored in reserved space.
Subprocess & with_var(K &&k, V &&v)
Adds or replaces a single environment variable.
std::unique_ptr< Child > spawn()
Spawns (forks) the child process and begins execution.
FlatImage configuration object.
Manages filesystems used by flatimage.
Defines a class that manages FlatImage's boot configuration.
Manages environment variables in flatimage.
Manages remote URL in flatimage.
Interfaces of FlatImage commands.
#define logger(fmt,...)
Compile-time log level dispatch macro with automatic location capture.
Simplified macros for common control flow patterns with optional logging.
Value< void > list(fs::path const &path_file_binary)
List bindings from the given bindings database.
Value< void > del(fs::path const &path_file_binary, uint64_t index)
Deletes a binding from the database.
Value< void > add(fs::path const &path_file_binary, ns_db::ns_bind::Type bind_type, fs::path const &path_src, fs::path const &path_dst)
Adds a binding instruction to the binding database.
Value< ns_db::ns_bind::Binds > db_read(fs::path const &path_file_binary)
Reads data from the reserved space.
Value< void > list(fs::path const &path_file_binary)
Lists all enabled unshare options.
Value< void > add(fs::path const &path_file_binary, std::set< ns_reserved::ns_unshare::Unshare > const &unshares)
Adds unshare options to existing configuration.
Value< void > clear(fs::path const &path_file_binary)
Clears all unshare options.
Value< void > set(fs::path const &path_file_binary, std::set< ns_reserved::ns_unshare::Unshare > const &unshares)
Sets the unshare options (replaces existing)
Value< void > del(fs::path const &path_file_binary, std::set< ns_reserved::ns_unshare::Unshare > const &unshares)
Removes unshare options from existing configuration.
Value< std::string > serialize(Boot const &boot) noexcept
Serializes a Boot class into a json string.
Value< Boot > deserialize(std::string_view str_raw_json) noexcept
Deserializes a json string into a Boot class.
Value< void > del(fs::path const &path_file_binary, std::vector< std::string > const &entries)
Deletes a list of environment variables from the database.
Value< std::vector< std::string > > get(fs::path const &path_file_binary)
Get existing variables from the database.
Value< void > add(fs::path const &path_file_binary, std::vector< std::string > const &entries)
Adds a new environment variable to the database.
Value< void > set(fs::path const &path_file_binary, std::vector< std::string > const &entries)
Resets all defined environment variables to the ones passed as an argument.
Portal daemon configuration and management.
Portal command dispatcher configuration.
Value< std::string > serialize(Dispatcher const &dispatcher) noexcept
Serializes a Dispatcher class into a json string.
Value< std::string > get(fs::path const &path_file_binary)
Gets the remote URL from the database.
Value< void > clear(fs::path const &path_file_binary)
Clears the remote URL from the database.
Value< void > set(fs::path const &path_file_binary, std::string const &url)
Sets a remote URL in the database.
Value< void > enable(ns_config::FlatImage const &fim, std::set< IntegrationItem > set_integrations)
Enables desktop integration for FlatImage.
Value< std::string > dump_entry(ns_config::FlatImage const &fim)
Dumps the desktop entry if integration is configured.
Value< void > clean(ns_config::FlatImage const &fim)
Cleans desktop integration files.
Value< void > setup(ns_config::FlatImage const &fim, fs::path const &path_file_json_src)
Setup desktop integration in FlatImage.
Value< std::string > dump_mimetype(ns_config::FlatImage const &fim)
Dumps the application mime type file if integration is configured.
Value< void > dump_icon(ns_config::FlatImage const &fim, fs::path path_file_dst)
Dumps the png or svg icon data to a file.
Value< void > integrate(ns_config::FlatImage const &fim)
Integrates flatimage desktop data in current system.
Value< std::string > expand(ns_concept::StringRepresentable auto &&var)
Performs variable expansion analogous to a POSIX shell.
std::vector< fs::path > get_mounted_layers(fs::path const &path_dir_layers)
Get a path for each layer directory.
Value< void > wait_busy(fs::path const &path_dir, std::chrono::nanoseconds timeout)
Waits for a filesystem path to become available (not busy).
std::vector< Instance > get_instances(fs::path const &path_dir_instances)
Get the running FlatImage instances.
CommitMode
Commit changes into a novel layer (binary/layer/file modes)
Value< void > add(fs::path const &path_file_binary, fs::path const &path_file_layer)
Includes a filesystem in the target FlatImage.
Value< void > create(fs::path const &path_dir_src, fs::path const &path_file_dst, fs::path const &path_file_list, uint64_t compression_level)
Creates a layer (filesystem) from a source directory.
void list(ns_filesystems::ns_layers::Layers const &layers)
Lists all layers in the format index:offset:size:path.
Command interface definitions and argument structures.
FlatImage command parsing and execution engine.
Value< int > execute_command(ns_config::FlatImage &fim, int argc, char **argv)
Executes a parsed FlatImage command.
Value< CmdType > parse(int argc, char **argv)
Parses FlatImage commands.
Value< std::unique_ptr< Portal > > spawn(Daemon const &daemon, Logs const &logs)
Spawns a new portal daemon instance.
Value< void > info(ns_config::Distribution const &distribution, fs::path const &path_dir_download, std::string const &recipe)
Displays information about a locally cached recipe.
Value< int > install(ns_config::FlatImage const &fim, ns_config::Distribution const &distribution, fs::path const &path_dir_download, std::vector< std::string > const &recipes, F &&callback)
Installs packages from recipes using the appropriate package manager.
Value< std::vector< std::string > > fetch(ns_config::Distribution const &distribution, std::string url_remote, fs::path const &path_file_downloder, fs::path const &path_dir_download, std::string const &recipe, bool use_existing=false)
Fetches a recipe from the remote repository along with all its dependencies recursively.
Value< void > write(fs::path const &path_file_binary, std::string_view const &json)
Writes the boot json string to the target binary.
Value< std::string > read(fs::path const &path_file_binary)
Reads the json string from the target binary.
Value< void > write(fs::path const &path_file_binary, uint8_t is_casefold)
Writes a notification flag to the flatimage binary.
Value< void > write(fs::path const &path_file_binary, uint8_t is_notify)
Writes a notification flag to the flatimage binary.
Value< void > write(fs::path const &path_file_binary, OverlayType const &overlay)
Writes a overlay mask to the flatimage binary.
Manages the notify reserved space.
Manages the overlay reserved space.
Interface with the bindings database to (de-)serialize objects.
Manages the desktop integration.
Manages filesystem layers in FlatImage.
Manages recipes in FlatImage.
Interface for managing unshare namespace options.
Parses FlatImage commands.
Spawns a portal daemon process.
Manages the boot command reserved space.
Enhanced expected type with integrated logging capabilities.
Bwrap's native overlay related options.
The representation of a user in bubblewrap.
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.
ns_filesystems::ns_controller::Config fuse
Fuse subsystem configuration.
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)
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.
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.
fs::path const portal_daemon
Portal daemon for host-container IPC.
fs::path const self
Path to the FlatImage binary itself.
fs::path const app
Application directory (versioned by commit/timestamp)
fs::path const app_bin
Application binaries directory.
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 host_data
Data directory next to binary.
fs::path const host_data_tmp
Temporary files in data directory.
A library to spawn sub-processes in linux.
Filesystem utilities for managing instances and layers.