FlatImage
A configurable Linux containerization system
Loading...
Searching...
No Matches
executor.hpp
Go to the documentation of this file.
1
8
9#pragma once
10
11#include <cstdlib>
12#include <filesystem>
13#include <format>
14#include <iterator>
15#include <set>
16#include <string>
17#include <expected>
18#include <print>
19
22#include "../db/env.hpp"
23#include "../db/remote.hpp"
24#include "../db/boot.hpp"
25#include "../macro.hpp"
29#include "../reserved/boot.hpp"
30#include "../bwrap/bwrap.hpp"
31#include "../config.hpp"
32#include "../lib/subprocess.hpp"
33#include "../portal/portal.hpp"
34#include "interface.hpp"
35#include "parser.hpp"
36#include "cmd/layers.hpp"
37#include "cmd/desktop.hpp"
38#include "cmd/bind.hpp"
39#include "cmd/recipe.hpp"
40#include "cmd/unshare.hpp"
41
42namespace ns_parser
43{
44
45namespace
46{
47
48namespace fs = std::filesystem;
49
50} // namespace
51
54
55using namespace ns_parser::ns_interface;
56
65[[nodiscard]] inline Value<int> execute_command(ns_config::FlatImage& fim, int argc, char** argv)
66{
67 auto& fuse = fim.config.fuse;
68
69 // Parse args
70 CmdType variant_cmd = Pop(ns_parser::parse(argc, argv), "C::Could not parse arguments");
71
72 auto f_bwrap_impl = [&](auto&& program, auto&& args) -> Value<ns_bwrap::bwrap_run_ret_t>
73 {
74 // Check if the data directory is busy
75 Pop(ns_filesystems::ns_utils::wait_busy(fim.path.dir.host_data, std::chrono::seconds(60)));
76 // Mount filesystems
77 [[maybe_unused]] auto filesystem_controller =
79 , fuse
80 );
81 // Execute specified command
82 auto environment = ns_db::ns_env::get(fim.path.bin.self).or_default();
83 // Get path to root directory
84 fs::path path_dir_root = ( fim.flags.is_casefold and fuse.overlay_type != ns_reserved::ns_overlay::OverlayType::BWRAP )?
85 fuse.path_dir_ciopfs
86 : fuse.path_dir_mount;
87 logger("D::Bwrap root: {}", path_dir_root);
88 // Bubblewrap user data
89 ns_bwrap::ns_proxy::User user = Pop(fim.configure_bwrap());
90 logger("D::User: {}", std::string{user.data});
91 // Bwrap wrapper
93 , user
94 , path_dir_root
95 , program
96 , args
97 , environment
98 );
99 // Check for an overlapping data directory
100 // Optionally user bwrap overlays
101 if(fuse.overlay_type == ns_reserved::ns_overlay::OverlayType::BWRAP)
102 {
103 bwrap.set_overlay(ns_bwrap::ns_proxy::Overlay
104 {
105 .vec_path_dir_layer = ns_filesystems::ns_utils::get_mounted_layers(fuse.path_dir_layers)
106 , .path_dir_upper = fuse.path_dir_upper
107 , .path_dir_work = fuse.path_dir_work
108 });
109 }
110 // Include root binding and custom user-defined bindings
111 std::ignore = bwrap
112 .with_bind_ro("/", fim.path.dir.runtime_host)
113 .with_binds(Pop(ns_cmd::ns_bind::db_read(fim.path.bin.self), "E::Failed to configure bindings"));
114 // Retrieve permissions
116 // Retrieve unshare options
118 // Check if should enable GPU
119 if (permissions.contains(ns_reserved::ns_permissions::Permission::GPU))
120 {
121 std::ignore = bwrap.with_bind_gpu(fuse.path_dir_upper, fim.path.dir.runtime_host);
122 }
123 // Build the dispatcher object pointing it to the fifo of the host daemon
124 ns_dispatcher::Dispatcher dispatcher(fim.pid
125 , ns_daemon::Mode::HOST
126 , fim.path.dir.app
127 , fim.logs.dispatcher.path_dir_log
128 );
129 // Start host portal, permissive
130 [[maybe_unused]] auto portal = ns_portal::spawn(fim.config.daemon.host
131 , fim.logs.daemon_host
132 ).forward("E::Could not start portal daemon");
133 // Run the portal program with the guest dispatcher configuration
134 // Run bwrap
135 return bwrap.run(permissions
136 , unshares
137 , fim.path.bin.portal_daemon
138 , dispatcher
139 , fim.config.daemon.guest
140 , fim.logs.daemon_guest
141 );
142 };
143
144
145 auto f_bwrap = [&]<typename T, typename U>(T&& program, U&& args) -> Value<int>
146 {
147 // Setup desktop integration, permissive
148 ns_desktop::integrate(fim).discard("W::Could not perform desktop integration");
149 // Run bwrap
150 ns_bwrap::bwrap_run_ret_t bwrap_run_ret = Pop(f_bwrap_impl(program, args), "E::Failed to execute bwrap");
151 // Log bwrap errors
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);
153 // Retry with fallback if bwrap overlayfs failed
154 if ( fuse.overlay_type == ns_reserved::ns_overlay::OverlayType::BWRAP and bwrap_run_ret.syscall_nr == SYS_mount )
155 {
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");
159 } // if
160 return bwrap_run_ret.code;
161 };
162
163 // Execute a command as a regular user
164 if ( auto cmd = std::get_if<ns_parser::CmdExec>(&variant_cmd) )
165 {
166 return f_bwrap(cmd->program, cmd->args);
167 } // if
168 // Execute a command as root
169 else if ( auto cmd = std::get_if<ns_parser::CmdRoot>(&variant_cmd) )
170 {
171 fim.flags.is_root = true;
172 return f_bwrap(cmd->program, cmd->args);
173 } // if
174 // Configure permissions
175 else if ( auto cmd = std::get_if<ns_parser::CmdPerms>(&variant_cmd) )
176 {
177 // Retrieve permissions
179 // Determine permission operation
180 if(auto cmd_add = std::get_if<CmdPerms::Add>(&(cmd->sub_cmd)))
181 {
182 Pop(permissions.add(cmd_add->permissions), "E::Failed to add permissions");
183 }
184 else if(std::get_if<CmdPerms::Clear>(&(cmd->sub_cmd)))
185 {
186 Pop(permissions.set_all(false), "E::Failed to clear permissions");
187 }
188 else if(auto cmd_del = std::get_if<CmdPerms::Del>(&(cmd->sub_cmd)))
189 {
190 Pop(permissions.del(cmd_del->permissions), "E::Failed to delete permissions");
191 }
192 else if(std::get_if<CmdPerms::List>(&(cmd->sub_cmd)))
193 {
194 std::ranges::copy(Pop(permissions.to_strings(), "E::Failed to stringfy permissions")
195 , std::ostream_iterator<std::string>(std::cout, "\n")
196 );
197 }
198 else if(auto cmd_set = std::get_if<CmdPerms::Set>(&(cmd->sub_cmd)))
199 {
200 Pop(permissions.set(cmd_set->permissions), "E::Failed to set permissions");
201 }
202 else
203 {
204 return Error("C::Invalid permissions sub-command");
205 }
206 }
207 // Configure environment
208 else if ( auto cmd = std::get_if<ns_parser::CmdEnv>(&variant_cmd) )
209 {
210 if(auto cmd_add = std::get_if<CmdEnv::Add>(&(cmd->sub_cmd)))
211 {
212 Pop(ns_db::ns_env::add(fim.path.bin.self, cmd_add->variables), "E::Failed to add variables");
213 }
214 else if(std::get_if<CmdEnv::Clear>(&(cmd->sub_cmd)))
215 {
216 Pop(ns_db::ns_env::set(fim.path.bin.self, std::vector<std::string>()), "E::Failed to clear variables");
217 }
218 else if(auto cmd_del = std::get_if<CmdEnv::Del>(&(cmd->sub_cmd)))
219 {
220 Pop(ns_db::ns_env::del(fim.path.bin.self, cmd_del->variables), "E::Failed to delete variables");
221 }
222 else if(std::get_if<CmdEnv::List>(&(cmd->sub_cmd)))
223 {
224 std::ranges::copy(Pop(ns_db::ns_env::get(fim.path.bin.self), "E::Failed to list variables")
225 , std::ostream_iterator<std::string>(std::cout, "\n")
226 );
227 }
228 else if(auto cmd_set = std::get_if<CmdEnv::Set>(&(cmd->sub_cmd)))
229 {
230 Pop(ns_db::ns_env::set(fim.path.bin.self, cmd_set->variables), "E::Failed to set variables");
231 }
232 else
233 {
234 return Error("C::Invalid environment sub-command");
235 }
236 }
237 // Configure desktop integration
238 else if (auto cmd = std::get_if<CmdDesktop>(&variant_cmd))
239 {
240 if(auto cmd_setup = std::get_if<CmdDesktop::Setup>(&(cmd->sub_cmd)))
241 {
242 Pop(ns_desktop::setup(fim, cmd_setup->path_file_setup), "E::Failed to setup desktop integration");
243 }
244 else if(auto cmd_enable = std::get_if<CmdDesktop::Enable>(&(cmd->sub_cmd)))
245 {
246 Pop(ns_desktop::enable(fim, cmd_enable->set_enable), "E::Failed to enable desktop integration");
247 }
248 else if(std::get_if<CmdDesktop::Clean>(&(cmd->sub_cmd)))
249 {
250 Pop(ns_desktop::clean(fim), "E::Failed to clean desktop integration");
251 }
252 else if(auto cmd_dump = std::get_if<CmdDesktop::Dump>(&(cmd->sub_cmd)))
253 {
254 if(auto cmd_icon = std::get_if<CmdDesktop::Dump::Icon>(&(cmd_dump->sub_cmd)))
255 {
256 Pop(ns_desktop::dump_icon(fim, cmd_icon->path_file_icon), "E::Failed to dump desktop icon");
257 }
258 else if(std::get_if<CmdDesktop::Dump::Entry>(&(cmd_dump->sub_cmd)))
259 {
260 std::println("{}", Pop(ns_desktop::dump_entry(fim), "E::Failed to dump desktop entry"));
261 }
262 else if(std::get_if<CmdDesktop::Dump::MimeType>(&(cmd_dump->sub_cmd)))
263 {
264 std::println("{}", Pop(ns_desktop::dump_mimetype(fim), "E::Failed to dump MIME type"));
265 }
266 else
267 {
268 return Error("C::Invalid dump sub-command");
269 }
270 }
271 else
272 {
273 return Error("C::Invalid desktop sub-command");
274 }
275 }
276 // Manager layers
277 else if ( auto cmd = std::get_if<ns_parser::CmdLayer>(&variant_cmd) )
278 {
279 if(auto cmd_add = std::get_if<CmdLayer::Add>(&(cmd->sub_cmd)))
280 {
281 Pop(ns_layers::add(fim.path.bin.self, cmd_add->path_file_src), "E::Failed to add layer");
282 }
283 else if(auto cmd_commit = std::get_if<CmdLayer::Commit>(&(cmd->sub_cmd)))
284 {
285 // Determine commit mode and optional file path
287 std::optional<fs::path> path_file_dst;
288 if(std::get_if<CmdLayer::Commit::Binary>(&(cmd_commit->sub_cmd)))
289 {
290 mode = ns_layers::CommitMode::BINARY;
291 }
292 else if(std::get_if<CmdLayer::Commit::Layer>(&(cmd_commit->sub_cmd)))
293 {
294 mode = ns_layers::CommitMode::LAYER;
295 path_file_dst = fim.path.dir.host_data_layers;
296 }
297 else if(auto cmd_file = std::get_if<CmdLayer::Commit::File>(&(cmd_commit->sub_cmd)))
298 {
299 mode = ns_layers::CommitMode::FILE;
300 path_file_dst = cmd_file->path_file_dst;
301 }
302 else
303 {
304 return Error("E::Invalid commit sub-command");
305 }
306 // Call commit with the mode
307 Pop(ns_layers::commit(fim.path.bin.self
308 , fuse.path_dir_upper
309 , fim.path.dir.host_data_tmp / "layer.tmp"
310 , fim.path.dir.host_data_tmp / "compression.list"
311 , fuse.compression_level
312 , mode
313 , path_file_dst
314 ), "E::Failed to commit layer");
315 }
316 else if(auto cmd_create = std::get_if<CmdLayer::Create>(&(cmd->sub_cmd)))
317 {
318 Pop(ns_layers::create(cmd_create->path_dir_src
319 , cmd_create->path_file_target
320 , fim.path.dir.host_data_tmp / "compression.list"
321 , fuse.compression_level
322 ), "E::Failed to create layer");
323 logger("I::Filesystem created without errors");
324 }
325 else if(std::get_if<CmdLayer::List>(&(cmd->sub_cmd)))
326 {
327 ns_layers::list(fuse.layers);
328 }
329 else
330 {
331 return Error("C::Invalid layer operation");
332 }
333 }
334 // Bind a device or file to the flatimage
335 else if ( auto cmd = std::get_if<ns_parser::CmdBind>(&variant_cmd) )
336 {
337 if(auto cmd_add = std::get_if<CmdBind::Add>(&(cmd->sub_cmd)))
338 {
339 Pop(ns_cmd::ns_bind::add(fim.path.bin.self
340 , cmd_add->type
341 , cmd_add->path_src
342 , cmd_add->path_dst)
343 , "E::Failed to add binding");
344 }
345 else if(auto cmd_del = std::get_if<CmdBind::Del>(&(cmd->sub_cmd)))
346 {
347 Pop(ns_cmd::ns_bind::del(fim.path.bin.self, cmd_del->index), "E::Failed to delete binding");
348 }
349 else if(std::get_if<CmdBind::List>(&(cmd->sub_cmd)))
350 {
351 Pop(ns_cmd::ns_bind::list(fim.path.bin.self), "E::Failed to list bindings");
352 }
353 else
354 {
355 return Error("C::Invalid bind operation");
356 }
357 }
358 else if ( auto cmd = std::get_if<ns_parser::CmdNotify>(&variant_cmd) )
359 {
360 Pop(ns_reserved::ns_notify::write(fim.path.bin.self, cmd->status == CmdNotifySwitch::ON), "E::Failed to write notify status");
361 } // else if
362 // Enable or disable casefold (useful for wine)
363 else if ( auto cmd = std::get_if<ns_parser::CmdCaseFold>(&variant_cmd) )
364 {
365 Pop(ns_reserved::ns_casefold::write(fim.path.bin.self, cmd->status == CmdCaseFoldSwitch::ON), "E::Failed to write casefold status");
366 } // else if
367 // Update default command on database
368 else if ( auto cmd = std::get_if<ns_parser::CmdBoot>(&variant_cmd) )
369 {
370 if(std::get_if<CmdBoot::Clear>(&(cmd->sub_cmd)))
371 {
372 // Create empty boot configuration
374 // Write empty boot configuration
375 Pop(ns_reserved::ns_boot::write(fim.path.bin.self, Pop(ns_db::ns_boot::serialize(boot), "E::Failed to serialize boot configuration")), "E::Failed to clear boot configuration");
376 }
377 else if(auto cmd_set = std::get_if<CmdBoot::Set>(&(cmd->sub_cmd)))
378 {
379 // Create boot configuration
381 // Set values
382 boot.set_program(cmd_set->program);
383 boot.set_args(cmd_set->args);
384 // Write boot configuration
385 Pop(ns_reserved::ns_boot::write(fim.path.bin.self, Pop(ns_db::ns_boot::serialize(boot), "E::Failed to serialize boot configuration")), "E::Failed to set boot configuration");
386 }
387 else if(std::get_if<CmdBoot::Show>(&(cmd->sub_cmd)))
388 {
389 // Read json data
390 std::string data = Pop(ns_reserved::ns_boot::read(fim.path.bin.self), "E::Failed to read boot configuration");
391 // Deserialize boot configuration
393 // If no program was set, default to bash
394 if (boot.get_program().empty())
395 {
396 boot.set_program("bash");
397 }
398 // Serialize and print
399 std::cout << Pop(ns_db::ns_boot::serialize(boot), "E::Failed to serialize boot configuration") << '\n';
400 }
401 else
402 {
403 return Error("C::Invalid boot sub-command");
404 }
405 }
406 // Configure remote URL
407 else if ( auto cmd = std::get_if<ns_parser::CmdRemote>(&variant_cmd) )
408 {
409 if(std::get_if<CmdRemote::Clear>(&(cmd->sub_cmd)))
410 {
411 Pop(ns_db::ns_remote::clear(fim.path.bin.self), "E::Failed to clear remote URL");
412 }
413 else if(auto cmd_set = std::get_if<CmdRemote::Set>(&(cmd->sub_cmd)))
414 {
415 Pop(ns_db::ns_remote::set(fim.path.bin.self, cmd_set->url), "E::Failed to set remote URL");
416 }
417 else if(std::get_if<CmdRemote::Show>(&(cmd->sub_cmd)))
418 {
419 std::println("{}", Pop(ns_db::ns_remote::get(fim.path.bin.self), "E::Failed to get remote URL"));
420 }
421 else
422 {
423 return Error("C::Invalid remote sub-command");
424 }
425 }
426 // Fetch and install recipes
427 else if ( auto cmd = std::get_if<ns_parser::CmdRecipe>(&variant_cmd) )
428 {
429 auto f_fetch = [&fim](std::string const& recipe, bool use_existing) -> Value<std::vector<std::string>>
430 {
431 return ns_recipe::fetch(
432 fim.distribution
433 , Pop(ns_db::ns_remote::get(fim.path.bin.self), "E::Failed to get remote URL")
434 , fim.path.dir.app_sbin / "wget"
435 , fim.path.dir.host_data
436 , recipe
437 , use_existing
438 );
439 };
440
441 if(auto cmd_fetch = std::get_if<CmdRecipe::Fetch>(&(cmd->sub_cmd)))
442 {
443 // Fetch recipes with dependencies, always download when fetch command is called directly
444 for(auto const& recipe : cmd_fetch->recipes)
445 {
446 Pop(f_fetch(recipe, false), "E::Failed to fetch recipe");
447 }
448 }
449 else if(auto cmd_info = std::get_if<CmdRecipe::Info>(&(cmd->sub_cmd)))
450 {
451 for(auto const& recipe : cmd_info->recipes)
452 {
453 Pop(ns_recipe::info(fim.distribution, fim.path.dir.host_data, recipe), "E::Failed to get recipe info");
454 }
455 }
456 else if(auto cmd_install = std::get_if<CmdRecipe::Install>(&(cmd->sub_cmd)))
457 {
458 std::vector<std::string> all_recipes;
459 // Fetch all recipes and dependencies, overwrite existing
460 for(auto const& recipe : cmd_install->recipes)
461 {
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));
464 }
465 fim.flags.is_root = 1;
466 // Install all packages and dependencies
467 return ns_recipe::install(fim, fim.distribution, fim.path.dir.host_data, all_recipes, f_bwrap);
468 }
469 else
470 {
471 return Error("C::Invalid recipe sub-command");
472 }
473 }
474 else if ( auto cmd = std::get_if<ns_parser::CmdInstance>(&variant_cmd) )
475 {
477 // Get instances
478 auto instances = ns_filesystems::ns_utils::get_instances(fim.path.dir.app / "instance");
479 // Process the exec command
480 if(auto cmd_exec = std::get_if<CmdInstance::Exec>(&(cmd->sub_cmd)))
481 {
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")
485 );
486 // Get instance
487 Instance instance = instances.at(cmd_exec->id);
488 // Build the dispatcher object pointing it to the fifo of the guest daemon
489 ns_dispatcher::Dispatcher dispatcher(instance.pid
490 , ns_daemon::Mode::GUEST
491 , fim.path.dir.app
492 , fim.logs.dispatcher
493 );
494 // Run the portal program with the guest dispatcher configuration
495 return Pop(ns_subprocess::Subprocess(fim.path.dir.app_bin / "fim_portal")
496 .with_var("FIM_DISPATCHER_CFG", Pop(ns_dispatcher::serialize(dispatcher)))
497 .with_args(cmd_exec->args)
498 .spawn()->wait());
499 }
500 else if(std::get_if<CmdInstance::List>(&(cmd->sub_cmd)))
501 {
502 for(uint32_t i = 0; Instance const& instance : instances)
503 {
504 std::println("{}:{}", i++, instance.path.filename().string());
505 }
506 }
507 else
508 {
509 return Error("C::Invalid instance operation");
510 }
511 }
512 else if ( auto cmd = std::get_if<ns_parser::CmdOverlay>(&variant_cmd) )
513 {
514 if(auto cmd_set = std::get_if<CmdOverlay::Set>(&(cmd->sub_cmd)))
515 {
516 Pop(ns_reserved::ns_overlay::write(fim.path.bin.self, cmd_set->overlay), "E::Failed to set overlay type");
517 }
518 else if(std::get_if<CmdOverlay::Show>(&(cmd->sub_cmd)))
519 {
520 std::println("{}", std::string{fuse.overlay_type});
521 }
522 else
523 {
524 return Error("C::Invalid operation for fim-overlay");
525 }
526 }
527 else if ( auto cmd = std::get_if<ns_parser::CmdUnshare>(&variant_cmd) )
528 {
529 if(auto cmd_set = std::get_if<CmdUnshare::Set>(&(cmd->sub_cmd)))
530 {
531 Pop(ns_cmd::ns_unshare::set(fim.path.bin.self, cmd_set->unshares), "E::Failed to set unshare options");
532 }
533 else if(auto cmd_add = std::get_if<CmdUnshare::Add>(&(cmd->sub_cmd)))
534 {
535 Pop(ns_cmd::ns_unshare::add(fim.path.bin.self, cmd_add->unshares), "E::Failed to add unshare options");
536 }
537 else if(auto cmd_del = std::get_if<CmdUnshare::Del>(&(cmd->sub_cmd)))
538 {
539 Pop(ns_cmd::ns_unshare::del(fim.path.bin.self, cmd_del->unshares), "E::Failed to delete unshare options");
540 }
541 else if(std::get_if<CmdUnshare::Clear>(&(cmd->sub_cmd)))
542 {
543 Pop(ns_cmd::ns_unshare::clear(fim.path.bin.self), "E::Failed to clear unshare options");
544 }
545 else if(std::get_if<CmdUnshare::List>(&(cmd->sub_cmd)))
546 {
547 Pop(ns_cmd::ns_unshare::list(fim.path.bin.self), "E::Failed to list unshare options");
548 }
549 else
550 {
551 return Error("C::Invalid operation for fim-unshare");
552 }
553 }
554 else if ( auto cmd = std::get_if<ns_parser::CmdVersion>(&variant_cmd) )
555 {
556 if(auto cmd_short = std::get_if<CmdVersion::Short>(&(cmd->sub_cmd)))
557 {
558 std::println("{}", cmd_short->dump());
559 }
560 else if(auto cmd_full = std::get_if<CmdVersion::Full>(&(cmd->sub_cmd)))
561 {
562 std::println("{}", Pop(cmd_full->dump(), "E::Failed to dump full version info"));
563 }
564 else if(auto cmd_deps = std::get_if<CmdVersion::Deps>(&(cmd->sub_cmd)))
565 {
566 std::println("{}", Pop(cmd_deps->dump(), "E::Failed to dump dependencies info"));
567 }
568 else
569 {
570 return Error("C::Invalid operation for fim-version");
571 }
572 }
573 // Update default command on database
574 else if ( std::get_if<ns_parser::CmdNone>(&variant_cmd) )
575 {
576 std::string data = Pop(ns_reserved::ns_boot::read(fim.path.bin.self), "E::Failed to read boot configuration");
577 // De-serialize boot command
579 // Retrive default program
580 fs::path program = boot.get_program().empty() ?
581 "bash"
582 : ns_env::expand(boot.get_program()).value_or(boot.get_program());
583 // Retrive default arguments
584 std::vector<std::string> args = boot.get_args();
585 // Append arguments from argv
586 std::copy(argv+1, argv+argc, std::back_inserter(args));
587 // Run Bwrap
588 return f_bwrap(program, args);
589 } // else if
590 else if ( std::get_if<ns_parser::CmdExit>(&variant_cmd) )
591 {
592 return EXIT_SUCCESS;
593 }
594 else
595 {
596 return Error("C::Unknown command");
597 }
598
599 return EXIT_SUCCESS;
600}
601
602} // namespace ns_parser
603
604/* vim: set expandtab fdm=marker ts=2 sw=2 tw=100 et :*/
Value< int > boot(int argc, char **argv)
Boots the main flatimage program and the portal process.
Definition boot.cpp:40
Configures and launches bubblewrap
Manages the casefold reserved space.
Manages bubblewrap (bwrap) containerization.
Definition bwrap.hpp:228
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.
Definition unshare.hpp:134
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.
Definition log.hpp:682
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.
Definition bind.hpp:133
Value< void > del(fs::path const &path_file_binary, uint64_t index)
Deletes a binding from the database.
Definition bind.hpp:116
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.
Definition bind.hpp:86
Value< ns_db::ns_bind::Binds > db_read(fs::path const &path_file_binary)
Reads data from the reserved space.
Definition bind.hpp:57
Value< void > list(fs::path const &path_file_binary)
Lists all enabled unshare options.
Definition unshare.hpp:101
Value< void > add(fs::path const &path_file_binary, std::set< ns_reserved::ns_unshare::Unshare > const &unshares)
Adds unshare options to existing configuration.
Definition unshare.hpp:57
Value< void > clear(fs::path const &path_file_binary)
Clears all unshare options.
Definition unshare.hpp:88
Value< void > set(fs::path const &path_file_binary, std::set< ns_reserved::ns_unshare::Unshare > const &unshares)
Sets the unshare options (replaces existing)
Definition unshare.hpp:41
Value< void > del(fs::path const &path_file_binary, std::set< ns_reserved::ns_unshare::Unshare > const &unshares)
Removes unshare options from existing configuration.
Definition unshare.hpp:73
Value< std::string > serialize(Boot const &boot) noexcept
Serializes a Boot class into a json string.
Definition boot.hpp:76
Value< Boot > deserialize(std::string_view str_raw_json) noexcept
Deserializes a json string into a Boot class.
Definition boot.hpp:57
Value< void > del(fs::path const &path_file_binary, std::vector< std::string > const &entries)
Deletes a list of environment variables from the database.
Definition env.hpp:83
Value< std::vector< std::string > > get(fs::path const &path_file_binary)
Get existing variables from the database.
Definition env.hpp:144
Value< void > add(fs::path const &path_file_binary, std::vector< std::string > const &entries)
Adds a new environment variable to the database.
Definition env.hpp:108
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.
Definition env.hpp:131
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.
Definition remote.hpp:62
Value< void > clear(fs::path const &path_file_binary)
Clears the remote URL from the database.
Definition remote.hpp:83
Value< void > set(fs::path const &path_file_binary, std::string const &url)
Sets a remote URL in the database.
Definition remote.hpp:44
Value< void > enable(ns_config::FlatImage const &fim, std::set< IntegrationItem > set_integrations)
Enables desktop integration for FlatImage.
Definition desktop.hpp:620
Value< std::string > dump_entry(ns_config::FlatImage const &fim)
Dumps the desktop entry if integration is configured.
Definition desktop.hpp:743
Value< void > clean(ns_config::FlatImage const &fim)
Cleans desktop integration files.
Definition desktop.hpp:646
Value< void > setup(ns_config::FlatImage const &fim, fs::path const &path_file_json_src)
Setup desktop integration in FlatImage.
Definition desktop.hpp:563
Value< std::string > dump_mimetype(ns_config::FlatImage const &fim)
Dumps the application mime type file if integration is configured.
Definition desktop.hpp:762
Value< void > dump_icon(ns_config::FlatImage const &fim, fs::path path_file_dst)
Dumps the png or svg icon data to a file.
Definition desktop.hpp:708
Value< void > integrate(ns_config::FlatImage const &fim)
Integrates flatimage desktop data in current system.
Definition desktop.hpp:455
Value< std::string > expand(ns_concept::StringRepresentable auto &&var)
Performs variable expansion analogous to a POSIX shell.
Definition env.hpp:96
std::vector< fs::path > get_mounted_layers(fs::path const &path_dir_layers)
Get a path for each layer directory.
Definition utils.hpp:164
Value< void > wait_busy(fs::path const &path_dir, std::chrono::nanoseconds timeout)
Waits for a filesystem path to become available (not busy).
Definition utils.hpp:92
std::vector< Instance > get_instances(fs::path const &path_dir_instances)
Get the running FlatImage instances.
Definition utils.hpp:137
CommitMode
Commit changes into a novel layer (binary/layer/file modes)
Definition layers.hpp:189
Value< void > add(fs::path const &path_file_binary, fs::path const &path_file_layer)
Includes a filesystem in the target FlatImage.
Definition layers.hpp:127
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.
Definition layers.hpp:50
void list(ns_filesystems::ns_layers::Layers const &layers)
Lists all layers in the format index:offset:size:path.
Definition layers.hpp:274
Command interface definitions and argument structures.
FlatImage command parsing and execution engine.
Definition executor.hpp:43
Value< int > execute_command(ns_config::FlatImage &fim, int argc, char **argv)
Executes a parsed FlatImage command.
Definition executor.hpp:65
Value< CmdType > parse(int argc, char **argv)
Parses FlatImage commands.
Definition parser.hpp:185
Value< std::unique_ptr< Portal > > spawn(Daemon const &daemon, Logs const &logs)
Spawns a new portal daemon instance.
Definition portal.hpp:74
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.
Definition recipe.hpp:223
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.
Definition recipe.hpp:275
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.
Definition recipe.hpp:201
Value< void > write(fs::path const &path_file_binary, std::string_view const &json)
Writes the boot json string to the target binary.
Definition boot.hpp:44
Value< std::string > read(fs::path const &path_file_binary)
Reads the json string from the target binary.
Definition boot.hpp:64
Value< void > write(fs::path const &path_file_binary, uint8_t is_casefold)
Writes a notification flag to the flatimage binary.
Definition casefold.hpp:44
Value< void > write(fs::path const &path_file_binary, uint8_t is_notify)
Writes a notification flag to the flatimage binary.
Definition notify.hpp:44
Value< void > write(fs::path const &path_file_binary, OverlayType const &overlay)
Writes a overlay mask to the flatimage binary.
Definition overlay.hpp:48
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.
Definition expected.hpp:44
Bwrap's native overlay related options.
Definition bwrap.hpp:74
The representation of a user in bubblewrap.
Definition bwrap.hpp:96
ns_db::ns_portal::ns_daemon::Daemon const host
Host-side portal daemon.
Definition config.hpp:361
ns_db::ns_portal::ns_daemon::Daemon const guest
Guest-side portal daemon.
Definition config.hpp:362
ns_filesystems::ns_controller::Config fuse
Fuse subsystem configuration.
Definition config.hpp:352
bool is_casefold
Enable case-insensitive filesystem? Via FIM_CASEFOLD or reserved space.
Definition config.hpp:483
bool is_root
Execute as root (UID=0)? Checked via FIM_ROOT env or stored UID.
Definition config.hpp:481
Main FlatImage configuration object.
Definition config.hpp:519
pid_t const pid
Current instance process ID.
Definition config.hpp:521
Path path
Directory, file, and binary paths.
Definition config.hpp:525
Distribution const distribution
Linux distribution (ARCH/ALPINE/BLUEPRINT)
Definition config.hpp:520
Flags flags
Runtime feature flags.
Definition config.hpp:522
Logs logs
Log file paths for all subsystems.
Definition config.hpp:523
Config config
Module configurations (filesystem, daemon)
Definition config.hpp:524
ns_bwrap::ns_proxy::Logs const bwrap
Bubblewrap sandbox log paths.
Definition config.hpp:309
ns_db::ns_portal::ns_daemon::ns_log::Logs const daemon_guest
Guest portal daemon logs.
Definition config.hpp:311
ns_db::ns_portal::ns_dispatcher::Logs const dispatcher
Portal dispatcher logs.
Definition config.hpp:312
ns_db::ns_portal::ns_daemon::ns_log::Logs const daemon_host
Host portal daemon logs.
Definition config.hpp:310
ns_filesystems::ns_controller::Logs const filesystems
Filesystem subsystem logs.
Definition config.hpp:313
fs::path const portal_daemon
Portal daemon for host-container IPC.
Definition config.hpp:231
fs::path const self
Path to the FlatImage binary itself.
Definition config.hpp:228
fs::path const app
Application directory (versioned by commit/timestamp)
Definition config.hpp:152
fs::path const app_bin
Application binaries directory.
Definition config.hpp:153
fs::path const runtime_host
Host-side runtime directory.
Definition config.hpp:158
fs::path const host_data_layers
Layers directory in data directory.
Definition config.hpp:162
fs::path const app_sbin
Application system binaries directory.
Definition config.hpp:154
fs::path const host_data
Data directory next to binary.
Definition config.hpp:160
fs::path const host_data_tmp
Temporary files in data directory.
Definition config.hpp:161
Represents an instance.
Definition utils.hpp:121
A library to spawn sub-processes in linux.
Filesystem utilities for managing instances and layers.