Structural simplification, rustfmt configuration applied, and snake_case

for declared modules within tag vars

- For the sake of coherency, there are now four types of containers:
  Symbolic, Base, Slice, and Aggregate. These names better reflect the
  associated container types.
- Global configuration template is now written to disk prior to
  instantiation
- Inclusion of .rustfmt.toml with formatting applied to source files
- Breaking format change: SCREAMING_CASE has been replaced with
  snake_case for tag variables
- Simplified data structure in cache module
- InstanceCache type within the cache module replaces 'registered_base',
  'registered_dep', and 'registered_root', with 'filter'.
- Cleaned up argument parsing match statements in the front-end modules.
- Specifying dependencies with a comma deliniation is now supported
- Manual updated to reflect argument changes.
- query module updated to utilise internal APIs
- Some minor improvements to error handling.
- Removed redundant calls to --clear-env with bubblewrap.
- Scripting no longer outputs ANSI charcodes to unsupported terminals
This commit is contained in:
Xavier Moffett 2024-01-14 20:45:59 -05:00
parent 3b5951cea6
commit 9b495390d2
71 changed files with 2781 additions and 2398 deletions

16
.rustfmt.toml Normal file
View File

@ -0,0 +1,16 @@
unstable_features = true
indent_style = "Block"
imports_indent = "Block"
imports_layout = "HorizontalVertical"
imports_granularity = "Crate"
brace_style = "PreferSameLine"
match_arm_leading_pipes = "Never"
match_arm_blocks = false
condense_wildcard_suffixes = true
overflow_delimited_expr = false
spaces_around_ranges = true
reorder_imports = true
hard_tabs = false
max_width = 130
fn_call_width = 120
chain_width = 90

View File

@ -355,7 +355,7 @@ replicate_instance() {
[[ $type != BASE ]] && depend=$(return_dependency)
case $type in
ROOT) params+="r";;
ROOT) params+="a";;
BASE) params+="b";;
DEP) params+="s";;
LINK) ln -s "$INSTANCE_ROOT_DIR/$depend" "$INSTANCE_ROOT_DIR/$instance"

11
dist/tools/clean.sh vendored
View File

@ -18,10 +18,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
BOLD=$(tput bold)
GREEN=$(tput setaf 2)
RED=$(tput setaf 1)
RESET=$(tput sgr0)
if ! [[ -z $COLORTERM ]] || [[ $TERM == "dummy" ]]; then
BOLD=$(tput bold)
GREEN=$(tput setaf 2)
RED=$(tput setaf 1)
RESET=$(tput sgr0)
fi
DIST_RUNTIME="./dist/runtime"
DIST_BASE="./dist/pacwrap-base-dist"
DIST_REPO="./dist/repo"

11
dist/tools/runtime.sh vendored
View File

@ -21,10 +21,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
BOLD=$(tput bold)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
RESET=$(tput sgr0)
if ! [[ -z $COLORTERM ]] || [[ $TERM == "dummy" ]]; then
BOLD=$(tput bold)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
RESET=$(tput sgr0)
fi
LIB_DIR="/lib"
BIN_DIR="/bin"
DEST_DIR="./dist/runtime"

View File

@ -1,6 +1,6 @@
/*
* pacwrap-agent
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -18,7 +18,7 @@
*/
fn main() {
if ! cfg!(target_os="linux") || ! cfg!(target_family="unix") {
if !cfg!(target_os = "linux") || !cfg!(target_family = "unix") {
panic!("Unsupported build target. Please refer to the documentation for further information.")
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-agent
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -16,57 +16,64 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{fs::{self, File}, io::ErrorKind::NotFound, os::unix::prelude::FileExt, env};
use std::{
env,
fs::{self, File},
io::ErrorKind::NotFound,
os::unix::prelude::FileExt,
};
use serde::Deserialize;
use pacwrap_core::{err,
use pacwrap_core::{
config::Global,
err,
sync::{
self,
event::{
download::{self, DownloadEvent},
progress::{self, ProgressEvent},
query,
},
transaction::{TransactionHandle, TransactionMetadata, TransactionParameters, TransactionType, MAGIC_NUMBER},
utils::{erroneous_preparation, erroneous_transaction},
AlpmConfigData,
SyncError,
},
utils::{print_warning, read_le_32},
Error,
Result,
sync::{self,
SyncError,
AlpmConfigData,
utils::{erroneous_transaction,
erroneous_preparation},
transaction::{TransactionHandle,
TransactionType,
TransactionMetadata,
TransactionParameters,
MAGIC_NUMBER},
event::{download::{self, DownloadEvent},
progress::{self, ProgressEvent},
query}},
utils::{print_warning, read_le_32}, config::Global};
};
use crate::error::AgentError;
static AGENT_PARAMS: &'static str = "/mnt/agent_params";
pub fn transact() -> Result<()> {
let mut header_buffer = vec![0; 7];
let mut header_buffer = vec![0; 7];
let mut file = match File::open(AGENT_PARAMS) {
Ok(file) => file,
Err(error) => {
if let Ok(var) = env::var("SHELL") {
if ! var.is_empty() {
if !var.is_empty() {
err!(AgentError::DirectExecution)?
}
}
err!(AgentError::IOError(AGENT_PARAMS, error.kind()))?
},
};
}
};
if let Err(error) = file.read_exact_at(&mut header_buffer, 0) {
err!(AgentError::IOError(AGENT_PARAMS, error.kind()))?
}
decode_header(&header_buffer)?;
let params: TransactionParameters = deserialize(&mut file)?;
let config: Global = deserialize(&mut file)?;
let alpm_remotes: AlpmConfigData = deserialize(&mut file)?;
let mut metadata: TransactionMetadata = deserialize(&mut file)?;
let mut metadata: TransactionMetadata = deserialize(&mut file)?;
let alpm = sync::instantiate_alpm_agent(&config, &alpm_remotes);
let mut handle = TransactionHandle::new(&config, alpm, &mut metadata);
@ -74,11 +81,11 @@ pub fn transact() -> Result<()> {
}
fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: TransactionParameters) -> Result<()> {
let flags = handle.retrieve_flags();
let flags = handle.retrieve_flags();
let mode = agent.mode();
let action = agent.action();
let config = config.config();
let progress = config.progress();
let pkind = config.progress();
let bytes = agent.bytes();
let files = agent.files();
@ -86,12 +93,12 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
err!(SyncError::InitializationFailure(error.to_string().into()))?
}
handle.ignore(true);
handle.ignore(true);
if let TransactionType::Upgrade(upgrade, downgrade, _) = action {
if let TransactionType::Upgrade(upgrade, downgrade, _) = action {
if upgrade {
handle.alpm().sync_sysupgrade(downgrade).unwrap();
}
}
}
handle.prepare(&action, &flags.0.unwrap())?;
@ -100,17 +107,12 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
erroneous_preparation(error)?
}
let progress_cb = ProgressEvent::new()
.style(progress.0)
.configure(&action);
let download_cb = DownloadEvent::new()
.style(progress.0)
.total(bytes, files)
.configure(&mode, progress.1);
let progress_cb = ProgressEvent::new().style(pkind.0).configure(&action);
let download_cb = DownloadEvent::new().style(pkind.0).total(bytes, files).configure(&mode, pkind.1);
handle.alpm().set_question_cb((), query::callback);
handle.alpm().set_progress_cb(progress_cb, progress::callback(&mode, progress.0));
handle.alpm().set_dl_cb(download_cb, download::callback(progress.1));
handle.alpm().set_progress_cb(progress_cb, progress::callback(&mode, pkind.0));
handle.alpm().set_dl_cb(download_cb, download::callback(pkind.1));
if let Err(error) = handle.alpm_mut().trans_commit() {
erroneous_transaction(error)?
@ -121,7 +123,8 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
if let Err(error) = fs::copy("/etc/ld.so.cache", "/mnt/fs/etc/ld.so.cache") {
match error.kind() {
NotFound => (), _ => print_warning(format!("Failed to propagate ld.so.cache: {}", error)),
NotFound => (),
_ => print_warning(format!("Failed to propagate ld.so.cache: {}", error)),
}
}
@ -139,7 +142,7 @@ fn decode_header(buffer: &Vec<u8>) -> Result<()> {
}
if major.0 != major.1 || minor.0 != minor.1 || patch.0 != patch.1 {
err!(AgentError::InvalidVersion(major.0,minor.0,patch.0,major.1,minor.1,patch.1))?;
err!(AgentError::InvalidVersion(major.0, minor.0, patch.0, major.1, minor.1, patch.1))?;
}
Ok(())
@ -148,6 +151,6 @@ fn decode_header(buffer: &Vec<u8>) -> Result<()> {
fn deserialize<T: for<'de> Deserialize<'de>>(stdin: &mut File) -> Result<T> {
match bincode::deserialize_from::<&mut File, T>(stdin) {
Ok(meta) => Ok(meta),
Err(error) => err!(AgentError::DeserializationError(error.as_ref().to_string()))
Err(error) => err!(AgentError::DeserializationError(error.as_ref().to_string())),
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-agent
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -19,25 +19,30 @@
use std::fmt::{Display, Formatter};
use pacwrap_core::{ErrorTrait, constants::{RESET, BOLD}};
use pacwrap_core::{
constants::{BOLD, RESET},
ErrorTrait,
};
#[derive(Debug)]
pub enum AgentError {
DeserializationError(String),
InvalidVersion(u8,u8,u8,u8,u8,u8),
InvalidVersion(u8, u8, u8, u8, u8, u8),
InvalidMagic(u32, u32),
IOError(&'static str, std::io::ErrorKind),
DirectExecution,
}
impl Display for AgentError {
fn fmt(&self, fmter: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
fn fmt(&self, fmter: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self {
Self::DirectExecution => write!(fmter, "Direct execution of this binary is unsupported."),
Self::InvalidMagic(magic, comparator) => write!(fmter, "Magic mismatch {} != {}", magic, comparator),
Self::InvalidVersion(a, b, c, d, e, f) => write!(fmter, "Version mismatch {}.{}.{} != {}.{}.{}", a, b, c, d, e, f),
Self::InvalidVersion(a, b, c, d, e, f) => {
write!(fmter, "Version mismatch {}.{}.{} != {}.{}.{}", a, b, c, d, e, f)
}
Self::DeserializationError(error) => write!(fmter, "Deserilization error: {}", error),
Self::IOError(file, error) => write!(fmter, "'{}{}{}' {}", *BOLD, file, *RESET, error)
Self::IOError(file, error) => write!(fmter, "'{}{}{}' {}", *BOLD, file, *RESET, error),
}
}
}
@ -49,7 +54,7 @@ impl ErrorTrait for AgentError {
Self::InvalidVersion(..) => 4,
Self::DeserializationError(..) => 3,
Self::IOError(..) => 2,
_ => 1
_ => 1,
}
}
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-agent
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -17,20 +17,25 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use pacwrap_core::{err, Error, utils::{Arguments, arguments::Operand}};
use pacwrap_core::{
err,
utils::{arguments::Operand, Arguments},
Error,
};
use crate::error::AgentError;
mod error;
mod agent;
mod error;
fn main() {
let arguments = &mut Arguments::new().populate();
let param = arguments.next().unwrap_or_default();
let result = match param {
Operand::Value("transact") => agent::transact(), _ => err!(AgentError::DirectExecution)
Operand::Value("transact") => agent::transact(),
_ => err!(AgentError::DirectExecution),
};
if let Err(error) = result {
error.handle();
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -27,7 +27,7 @@ fn dist_repo() -> String {
}
fn main() {
if ! cfg!(target_os="linux") || ! cfg!(target_family="unix") {
if !cfg!(target_os = "linux") || !cfg!(target_family = "unix") {
panic!("Unsupported build target. Please refer to the documentation for further information.")
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -17,35 +17,42 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{fmt::Display,
io::{Write, ErrorKind::NotFound},
fmt::Formatter,
path::Path,
fs::File};
use std::{
fmt::{Display, Formatter},
fs::File,
io::{ErrorKind::NotFound, Write},
path::Path,
};
use serde::Serialize;
use crate::{err, impl_error, ErrorKind, error::*, constants::{BOLD, RESET, CONFIG_FILE}};
use crate::{
constants::{BOLD, CONFIG_FILE, RESET},
err,
error::*,
impl_error,
ErrorKind,
};
pub use self::{cache::InstanceCache,
instance::{Instance,
InstanceHandle,
InstanceType},
vars::InsVars,
filesystem::{Filesystem, BindError},
permission::{Permission, PermError},
pub use self::{
cache::InstanceCache,
dbus::Dbus,
global::{Global, CONFIG}};
filesystem::{BindError, Filesystem},
global::{Global, CONFIG},
instance::{Instance, InstanceHandle, InstanceType},
permission::{PermError, Permission},
vars::InsVars,
};
pub mod vars;
pub mod filesystem;
pub mod permission;
pub mod dbus;
pub mod cache;
pub mod instance;
pub mod init;
pub mod register;
pub mod dbus;
pub mod filesystem;
pub mod global;
pub mod init;
pub mod instance;
pub mod permission;
pub mod register;
pub mod vars;
#[derive(Debug, Clone)]
pub enum ConfigError {
@ -61,13 +68,13 @@ impl_error!(ConfigError);
impl Display for ConfigError {
fn fmt(&self, fmter: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self {
Self::Filesystem(module, err) => write!(fmter, "Failed to register filesystem {}: {} ", module, err),
Self::Permission(module, err) => write!(fmter, "Failed to register permission {}: {} ", module, err),
match self {
Self::Filesystem(module, err) => write!(fmter, "Failed to register filesystem '{}': {} ", module, err),
Self::Permission(module, err) => write!(fmter, "Failed to register permission '{}': {} ", module, err),
Self::Load(ins, error) => write!(fmter, "Failed to load '{ins}': {error}"),
Self::Save(ins, error) => write!(fmter, "Failed to save '{ins}': {error}"),
Self::AlreadyExists(ins) => write!(fmter, "Container {}{ins}{} already exists.", *BOLD, *RESET),
Self::ConfigNotFound(ins) => write!(fmter, "Configuration '{}{ins}{}.yml' not found.", *BOLD, *RESET)
Self::ConfigNotFound(ins) => write!(fmter, "Configuration '{}{ins}{}' not found.", *BOLD, *RESET),
}
}
}
@ -79,10 +86,10 @@ impl From<ConfigError> for String {
}
#[inline]
pub fn provide_handle(instance: &str) -> Result<InstanceHandle> {
pub fn provide_handle(instance: &str) -> Result<InstanceHandle> {
let vars = InsVars::new(instance);
if ! Path::new(vars.root()).exists() {
if !Path::new(vars.root()).exists() {
err!(ErrorKind::InstanceNotFound(instance.into()))?
}
@ -94,19 +101,19 @@ pub fn provide_new_handle(instance: &str) -> Result<InstanceHandle> {
handle(instance, InsVars::new(instance))
}
fn save<T: Serialize>(obj: &T, path: &str) -> Result<()> {
fn save<T: Serialize>(obj: &T, path: &str) -> Result<()> {
let mut f = match File::create(Path::new(path)) {
Ok(f) => f,
Err(error) => err!(ErrorKind::IOError(path.into(), error.kind()))?
Err(error) => err!(ErrorKind::IOError(path.into(), error.kind()))?,
};
let config = match serde_yaml::to_string(&obj) {
Ok(file) => file,
Err(error) => err!(ConfigError::Save(path.into(), error.to_string()))?
Err(error) => err!(ConfigError::Save(path.into(), error.to_string()))?,
};
match write!(f, "{}", config) {
Ok(_) => Ok(()),
Err(error) => err!(ErrorKind::IOError(path.into(), error.kind()))
Err(error) => err!(ErrorKind::IOError(path.into(), error.kind())),
}
}
@ -115,15 +122,15 @@ fn handle<'a>(instance: &str, vars: InsVars<'a>) -> Result<InstanceHandle<'a>> {
Ok(file) => {
let config = match serde_yaml::from_reader(&file) {
Ok(file) => file,
Err(error) => err!(ConfigError::Load(vars.instance().into(), error.to_string()))?
Err(error) => err!(ConfigError::Load(vars.instance().into(), error.to_string()))?,
};
Ok(InstanceHandle::new(config, vars))
},
}
Err(error) => match error.kind() {
NotFound => err!(ConfigError::ConfigNotFound(instance.into()))?,
_ => err!(ErrorKind::IOError(vars.config_path().into(), error.kind()))?,
}
},
}
}
@ -133,11 +140,11 @@ fn config() -> Result<Global> {
match File::open(*CONFIG_FILE) {
Ok(file) => match serde_yaml::from_reader(&file) {
Ok(file) => Ok(file),
Err(error) => err!(ConfigError::Load(CONFIG_FILE.to_string(), error.to_string()))?
Err(error) => err!(ConfigError::Load(CONFIG_FILE.to_string(), error.to_string()))?,
},
Err(error) => match error.kind() {
NotFound => err!(ConfigError::ConfigNotFound(CONFIG_FILE.to_string()))?,
_ => err!(ErrorKind::IOError(CONFIG_FILE.to_string(), error.kind()))?,
}
},
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -19,33 +19,24 @@
use std::{collections::HashMap, fs::read_dir};
use crate::{err,
ErrorKind,
use crate::{
config::{self, InstanceHandle},
constants::DATA_DIR,
err,
error::*,
constants::DATA_DIR,
config::{self, InstanceHandle}};
ErrorKind,
};
use super::{InsVars,
ConfigError,
Instance,
instance::InstanceType};
use super::{instance::InstanceType, ConfigError, InsVars, Instance};
pub struct InstanceCache<'a> {
instances: HashMap<&'a str, InstanceHandle<'a>>,
registered: Vec<&'a str>,
registered_base: Vec<&'a str>,
registered_dep: Vec<&'a str>,
registered_root: Vec<&'a str>
}
impl <'a>InstanceCache<'a> {
impl<'a> InstanceCache<'a> {
pub fn new() -> Self {
Self {
instances: HashMap::new(),
registered: Vec::new(),
registered_base: Vec::new(),
registered_dep: Vec::new(),
registered_root: Vec::new(),
}
}
@ -57,87 +48,84 @@ impl <'a>InstanceCache<'a> {
for dep in deps.iter() {
if let None = self.instances.get(dep) {
err!(ErrorKind::DependencyNotFound((*dep).into(), ins.into()))?
}
}
}
let deps = deps.iter().map(|a| (*a).into()).collect();
let handle = match config::provide_new_handle(ins) {
Ok(mut handle) => {
handle.metadata_mut().set(deps, vec!());
handle
},
Ok(mut handle) => {
handle.metadata_mut().set(deps, vec![]);
handle
}
Err(err) => match err.downcast::<ConfigError>() {
Ok(error) => match error {
ConfigError::ConfigNotFound(_) => {
let vars = InsVars::new(ins);
let cfg = Instance::new(instype, deps, vec!());
InstanceHandle::new(cfg, vars)
},
let vars = InsVars::new(ins);
let cfg = Instance::new(instype, deps, vec![]);
InstanceHandle::new(cfg, vars)
}
_ => Err(err)?,
}
},
_ => Err(err)?,
},
};
Ok(self.register(ins, handle))
Ok(self.register(ins, handle))
}
fn map(&mut self, ins: &'a str) -> Result<()> {
fn map(&mut self, ins: &'a str) -> Result<()> {
if let Some(_) = self.instances.get(ins) {
err!(ConfigError::AlreadyExists(ins.to_owned()))?
}
Ok(self.register(ins, match config::provide_handle(ins) {
Ok(ins) => ins,
Err(error) => {
error.warn();
return Ok(())
}
}))
Ok(self.register(
ins,
match config::provide_handle(ins) {
Ok(ins) => ins,
Err(error) => {
error.warn();
return Ok(());
}
},
))
}
fn register(&mut self, ins: &'a str, handle: InstanceHandle<'a>) {
match handle.metadata().container_type() {
InstanceType::BASE => self.registered_base.push(ins),
InstanceType::DEP => self.registered_dep.push(ins),
InstanceType::ROOT => self.registered_root.push(ins),
InstanceType::LINK => return,
}
if let InstanceType::Symbolic = handle.metadata().container_type() {
return;
}
self.instances.insert(ins, handle);
self.registered.push(ins);
}
pub fn registered(&self) -> &Vec<&'a str> {
&self.registered
}
pub fn registered_base(&self) -> &Vec<&'a str> {
&self.registered_base
}
pub fn registered_dep(&self) -> &Vec<&'a str> {
&self.registered_dep
pub fn registered(&self) -> Vec<&'a str> {
self.instances.iter().map(|a| *a.0).collect()
}
pub fn registered_root(&self) -> &Vec<&'a str> {
&self.registered_root
pub fn filter(&self, filter: Vec<InstanceType>) -> Vec<&'a str> {
self.instances
.iter()
.filter(|a| filter.contains(a.1.metadata().container_type()))
.map(|a| *a.0)
.collect()
}
pub fn obtain_base_handle(&self) -> Option<&InstanceHandle> {
match self.registered_base.get(0) {
Some(instance) => self.instances.get(instance), None => None,
match self.filter(vec![InstanceType::Base]).get(0) {
Some(instance) => self.instances.get(instance),
None => None,
}
}
pub fn get_instance(&self, ins: &str) -> Result<&InstanceHandle> {
pub fn get_instance(&self, ins: &str) -> Result<&InstanceHandle> {
match self.instances.get(ins) {
Some(ins) => Ok(ins), None => err!(ErrorKind::InstanceNotFound(ins.into())),
Some(ins) => Ok(ins),
None => err!(ErrorKind::InstanceNotFound(ins.into())),
}
}
pub fn get_instance_option(&self, ins: &str) -> Option<&InstanceHandle> {
pub fn get_instance_option(&self, ins: &str) -> Option<&InstanceHandle> {
self.instances.get(ins)
}
}
@ -156,22 +144,25 @@ pub fn populate<'a>() -> Result<InstanceCache<'a>> {
populate_from(&roots()?)
}
fn roots<'a>() -> Result<Vec<&'a str>> {
fn roots<'a>() -> Result<Vec<&'a str>> {
match read_dir(format!("{}/root", *DATA_DIR)) {
Ok(dir) => Ok(dir.filter(|f| match f {
Ok(f) => match f.metadata() {
Ok(meta) => meta.is_dir() | meta.is_symlink(), Err(_) => false
},
Err(_) => false
})
.map(|s| match s {
Ok(dir) => Ok(dir
.filter(|f| match f {
Ok(f) => match f.metadata() {
Ok(meta) => meta.is_dir() | meta.is_symlink(),
Err(_) => false,
},
Err(_) => false,
})
.map(|s| match s {
Ok(f) => match f.file_name().to_str() {
Some(f) => f.to_owned().leak(), None => "",
Some(f) => f.to_owned().leak(),
None => "",
},
Err(_) => "",
})
.filter(|e| ! e.is_empty())
.collect()),
.filter(|e| !e.is_empty())
.collect()),
Err(error) => err!(ErrorKind::IOError(format!("{}/root", *DATA_DIR), error.kind())),
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -19,13 +19,13 @@
use crate::exec::args::ExecutionArgs;
use dyn_clone::{DynClone, clone_trait_object};
use dyn_clone::{clone_trait_object, DynClone};
mod socket;
mod appindicator;
mod socket;
mod xdg_portal;
#[typetag::serde(tag = "permission")]
#[typetag::serde(tag = "module")]
pub trait Dbus: DynClone {
fn register(&self, args: &mut ExecutionArgs);
}

View File

@ -3,10 +3,10 @@ use serde::{Deserialize, Serialize};
use crate::{config::Dbus, exec::args::ExecutionArgs};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct APPINDICATOR;
struct AppIndicator;
#[typetag::serde]
impl Dbus for APPINDICATOR {
#[typetag::serde(name = "appindicator")]
impl Dbus for AppIndicator {
fn register(&self, args: &mut ExecutionArgs) {
args.dbus("broadcast", "org.kde.StatusNotifierWatcher=@/StatusNotifierWatcher");
}

View File

@ -3,22 +3,20 @@ use serde::{Deserialize, Serialize};
use crate::{config::Dbus, exec::args::ExecutionArgs};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SOCKET {
struct Socket {
socket: String,
address: Vec<String>
address: Vec<String>,
}
#[typetag::serde]
impl Dbus for SOCKET {
#[typetag::serde(name = "socket")]
impl Dbus for Socket {
fn register(&self, args: &mut ExecutionArgs) {
match self.socket.to_lowercase().as_str() {
p if p == "call" || p == "talk" || p == "see" || p == "own" || p == "broadcast" => {
p if p == "call" || p == "talk" || p == "see" || p == "own" || p == "broadcast" =>
for sock in self.address.iter() {
args.dbus(p, sock);
}
},
},
&_ => {}
}
}
}

View File

@ -5,11 +5,11 @@ use serde::{Deserialize, Serialize};
use crate::{config::Dbus, exec::args::ExecutionArgs};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct XDG_PORTAL;
struct XdgPortal;
#[typetag::serde]
impl Dbus for XDG_PORTAL {
fn register(&self, args: &mut ExecutionArgs) {
#[typetag::serde(name = "xdg_portal")]
impl Dbus for XdgPortal {
fn register(&self, args: &mut ExecutionArgs) {
args.dbus("call", "org.freedesktop.portal.*=*");
args.dbus("broadcast", "org.freedesktop.portal.*=@/org/freedesktop/portal/*");
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -19,22 +19,21 @@
use std::fmt::{Display, Formatter};
use crate::exec::args::ExecutionArgs;
use crate::config::InsVars;
use crate::{config::InsVars, exec::args::ExecutionArgs};
use dyn_clone::{DynClone, clone_trait_object};
use dyn_clone::{clone_trait_object, DynClone};
mod dir;
pub mod home;
pub mod root;
mod sys;
mod to_home;
mod to_root;
mod dir;
mod sys;
pub enum Condition {
Success,
SuccessWarn(String),
Nothing
Nothing,
}
#[derive(Debug, Clone)]
@ -48,7 +47,6 @@ impl Display for BindError {
match self {
Self::Fail(error) => write!(fmter, "{}", error),
Self::Warn(error) => write!(fmter, "{}", error),
}
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -19,23 +19,27 @@
use serde::{Deserialize, Serialize};
use crate::{exec::args::ExecutionArgs,
config::InsVars,
config::filesystem::{Filesystem, BindError}};
use crate::{
config::{
filesystem::{BindError, Filesystem},
InsVars,
},
exec::args::ExecutionArgs,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DIR {
pub struct Dir {
#[serde(default)]
path: Vec<String>
path: Vec<String>,
}
#[typetag::serde]
impl Filesystem for DIR {
#[typetag::serde(name = "dir")]
impl Filesystem for Dir {
fn check(&self, _vars: &InsVars) -> Result<(), BindError> {
if self.path.len() == 0 {
Err(BindError::Fail(format!("Path not specified.")))?
}
Ok(())
}
@ -46,6 +50,6 @@ impl Filesystem for DIR {
}
fn module(&self) -> &'static str {
"DIR"
"dir"
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -21,18 +21,22 @@ use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::{exec::args::ExecutionArgs,
config::InsVars,
config::filesystem::{Filesystem, BindError}};
use crate::{
config::{
filesystem::{BindError, Filesystem},
InsVars,
},
exec::args::ExecutionArgs,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HOME;
pub struct Home;
#[typetag::serde]
impl Filesystem for HOME {
#[typetag::serde(name = "home")]
impl Filesystem for Home {
fn check(&self, vars: &InsVars) -> Result<(), BindError> {
if ! Path::new(vars.home()).exists() {
Err(BindError::Fail(format!("INSTANCE_HOME not found.")))?
if !Path::new(vars.home()).exists() {
Err(BindError::Fail(format!("Specified home directory not found.")))?
}
Ok(())
}
@ -40,10 +44,10 @@ impl Filesystem for HOME {
fn register(&self, args: &mut ExecutionArgs, vars: &InsVars) {
args.bind(vars.home(), vars.home_mount());
args.env("HOME", vars.home_mount());
args.env("USER", vars.user());
args.env("USER", vars.user());
}
fn module(&self) -> &'static str {
"HOME"
"home"
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -21,23 +21,27 @@ use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::{exec::args::ExecutionArgs,
config::InsVars,
config::filesystem::{Filesystem, BindError}};
use crate::{
config::{
filesystem::{BindError, Filesystem},
InsVars,
},
exec::args::ExecutionArgs,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ROOT;
pub struct Root;
#[typetag::serde]
impl Filesystem for ROOT {
#[typetag::serde(name = "root")]
impl Filesystem for Root {
fn check(&self, vars: &InsVars) -> Result<(), BindError> {
if ! Path::new(vars.root()).exists() {
if !Path::new(vars.root()).exists() {
Err(BindError::Fail(format!("Container {} not found. ", vars.instance())))?
}
Ok(())
}
fn register(&self, args: &mut ExecutionArgs, vars: &InsVars) {
fn register(&self, args: &mut ExecutionArgs, vars: &InsVars) {
args.robind(format!("{}/usr", vars.root()), "/usr");
args.robind(format!("{}/etc", vars.root()), "/etc");
args.symlink("/usr/lib", "/lib");
@ -47,6 +51,6 @@ impl Filesystem for ROOT {
}
fn module(&self) -> &'static str {
"ROOT"
"root"
}
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -16,41 +16,44 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::{exec::args::ExecutionArgs,
config::InsVars,
config::filesystem::{Filesystem, BindError}};
use crate::{
config::{
filesystem::{BindError, Filesystem},
InsVars,
},
exec::args::ExecutionArgs,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SYSFS {
#[serde(skip_serializing_if = "is_default_path", default = "default_path")]
path: Vec<String>
struct System {
#[serde(skip_serializing_if = "is_default_path", default = "default_path")]
path: Vec<String>,
}
#[typetag::serde]
impl Filesystem for SYSFS {
fn check(&self, _vars: &InsVars) -> Result<(), BindError> {
#[typetag::serde(name = "sysfs")]
impl Filesystem for System {
fn check(&self, _vars: &InsVars) -> Result<(), BindError> {
for dir in self.path.iter() {
if ! Path::new(&format!("/sys/{}",dir)).exists() {
if !Path::new(&format!("/sys/{}", dir)).exists() {
Err(BindError::Fail(format!("/sys/{} is inaccessible.", dir)))?
}
}
Ok(())
}
fn register(&self, args: &mut ExecutionArgs, _: &InsVars) {
for dir in self.path.iter() {
fn register(&self, args: &mut ExecutionArgs, _: &InsVars) {
for dir in self.path.iter() {
args.robind(format!("/sys/{}", dir), format!("/sys/{}", dir));
}
}
fn module(&self) -> &'static str {
"SUSFS"
"sysfs"
}
}
@ -59,9 +62,5 @@ fn is_default_path(path: &Vec<String>) -> bool {
}
fn default_path() -> Vec<String> {
vec!("block".into(),
"bus".into(),
"class".into(),
"dev".into(),
"devices".into())
vec!["block".into(), "bus".into(), "class".into(), "dev".into(), "devices".into()]
}

View File

@ -1,6 +1,6 @@
/*
* pacwrap-core
*
*
* Copyright (C) 2023-2024 Xavier R.M. <sapphirus@azorium.net>
* SPDX-License-Identifier: GPL-3.0-only
*
@ -16,57 +16,48 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#![allow(non_camel_case_types)]
use std::path::Path;
use serde::{Deserialize, Serialize};
use crate::{exec::args::ExecutionArgs,
config::InsVars,
config::filesystem::{Filesystem,
BindError,
default_permission,
is_default_permission},
constants::HOME};
use crate::{
config::{
filesystem::{default_permission, is_default_permission, BindError, Filesystem},
InsVars,
},
constants::HOME,
exec::args::ExecutionArgs,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TO_HOME {
#[serde(skip_serializing_if = "is_default_permission", default = "default_permission")]
permission: String,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
path: Vec<String>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
filesystem: Vec<Mount>
pub struct ToHome {
#[serde(skip_serializing_if = "Vec::is_empty", default, rename = "volumes")]
mounts: Vec<Mount>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Mount {
#[serde(skip_serializing_if = "is_default_permission", default = "default_permission")]
#[serde(skip_serializing_if = "is_default_permission", default = "default_permission")]
permission: String,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
path: Vec<String>
#[serde(skip_serializing_if = "String::is_empty", default)]
path: String,
#[serde(skip_serializing_if = "String::is_empty", default)]
dest: String,
}
#[typetag::serde]
impl Filesystem for TO_HOME {
#[typetag::serde(name = "to_home")]
impl Filesystem for ToHome {
fn check(&self, _vars: &InsVars) -> Result<(), BindError> {
if self.path.len() > 0 {
if let Err(e) = check_mount(&self.permission, &self.path[0]) {
return Err(e);
}
} else {
if self.filesystem.len() == 0 {
Err(BindError::Warn(format!(