Increased log coverage and refactored error module

- Error logging is now present in pacwrap-agent
- Agent error code handling now correctly traps runtime panics.
- impl of DisplayTrait for TransactionError no longer handles the
  display of transaction failure messages.
- Error handling for TransactionAggregation is split into three
  categories: Fatal, Error, and Non-Fatal Error. While two former are
  immediately trapped and the program is terminated, the latter can
  safely terminate the program without consequence.
This commit is contained in:
Xavier Moffett 2024-09-23 18:06:02 -04:00
parent 2f45f12b3e
commit 8191764098
Signed by: Sapphirus
GPG key ID: A6C061B2CEA1A7AC
12 changed files with 169 additions and 120 deletions

View file

@ -29,6 +29,7 @@ use pacwrap_core::{
config::Global,
constants::{VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH},
err,
log::{Level, Logger},
sync::{
self,
event::{
@ -77,16 +78,23 @@ pub fn transact() -> Result<()> {
let (transflags, ..) = handle.metadata().retrieve_flags();
let alpm = sync::instantiate_alpm_agent(&config, &alpm_remotes, &transflags.expect("TransactionFlags"));
let mut handle = handle.alpm_handle(alpm).config(&config).agent();
let mut logger = Logger::new("pacwrap-agent").location("/mnt/share/pacwrap.log")?;
if let Err(err) = conduct_transaction(&config, &mut handle, params) {
if let Err(err) = conduct_transaction(&config, &mut logger, &mut handle, params) {
handle.release();
logger.log(Level::Error, &format!("Transaction Error: {}", err))?;
return Err(err);
}
Ok(())
}
fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: TransactionParameters) -> Result<()> {
fn conduct_transaction(
config: &Global,
logger: &mut Logger,
handle: &mut TransactionHandle,
agent: TransactionParameters,
) -> Result<()> {
let flags = handle.metadata().retrieve_flags();
let mode = agent.mode();
let action = agent.action();
@ -95,7 +103,7 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
let bytes = agent.bytes();
let files = agent.files();
if let Err(error) = handle.alpm_mut().trans_init(flags.1.unwrap()) {
if let Err(error) = handle.alpm_mut().trans_init(flags.1.expect("ALPM TransFlag")) {
err!(SyncError::InitializationFailure(error.to_string()))?
}
@ -103,11 +111,11 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
if let TransactionType::Upgrade(upgrade, downgrade, _) = action {
if upgrade {
handle.alpm().sync_sysupgrade(downgrade).unwrap();
handle.alpm().sync_sysupgrade(downgrade).expect("ALPM sync_sysupgrade")
}
}
handle.prepare(&action, &flags.0.unwrap())?;
handle.prepare(&action, &flags.0.expect("TransactionFlags"))?;
if let Err(error) = handle.alpm_mut().trans_prepare() {
erroneous_preparation(error)?
@ -124,12 +132,15 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
erroneous_transaction(error)?
}
handle.alpm_mut().trans_release().unwrap();
handle.alpm_mut().trans_release().expect("ALPM trans_release");
handle.mark_depends();
if let Err(error) = fs::copy("/etc/ld.so.cache", "/mnt/fs/etc/ld.so.cache") {
if error.kind() != NotFound {
print_warning(&format!("Failed to propagate ld.so.cache: {}", error));
let message = &format!("Failed to propagate ld.so.cache: {}", error);
print_warning(message);
logger.log(Level::Warn, message)?;
}
}

View file

@ -25,7 +25,7 @@ use signal_hook::consts::*;
use crate::{
error,
utils::{ansi::*, unix_time_as_seconds},
utils::{ansi::*, unix_epoch_time},
Error,
ErrorKind,
};
@ -83,7 +83,7 @@ lazy_static! {
pub static ref DBUS_SOCKET: String = format!("/run/user/{}/pacwrap_dbus_{}", *UID, &id());
pub static ref WAYLAND_SOCKET: String = format!("{}{}", *XDG_RUNTIME_DIR, *WAYLAND_DISPLAY);
pub static ref LOG_LOCATION: &'static str = format_str!("{}/pacwrap.log", *DATA_DIR);
pub static ref UNIX_TIMESTAMP: u64 = unix_time_as_seconds();
pub static ref UNIX_TIMESTAMP: u64 = unix_epoch_time().as_secs();
pub static ref IS_COLOR_TERMINAL: bool = is_color_terminal();
pub static ref IS_TRUECOLOR_TERMINLAL: bool = is_truecolor_terminal();
pub static ref BOLD: &'static str = bold();

View file

@ -121,6 +121,12 @@ impl Error {
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", self.kind)
}
}
impl Display for ErrorType<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {

View file

@ -49,7 +49,7 @@ use crate::{
seccomp::{provide_bpf_program, FilterType::*},
utils::{agent_params, decode_info_json, wait_on_fakeroot, wait_on_process},
},
sync::transaction::{TransactionMetadata, TransactionParameters},
sync::transaction::{TransactionFlags, TransactionMetadata, TransactionParameters},
to_static_str,
utils::TermControl,
Error,
@ -162,34 +162,34 @@ pub fn fakeroot_container(exec_type: ExecutionType, trap: Option<fn(i32)>, ins:
.arg("--info-fd")
.arg(info_fd.to_string());
if let ContainerType::Slice = ins.metadata().container_type() {
process.arg("--dir").arg("/root")
.arg("--ro-bind").arg(format!("{}/bin", *DIST_IMG)).arg("/mnt/fs/bin")
.arg("--ro-bind").arg(format!("{}/lib", *DIST_IMG)).arg("/mnt/fs/lib64")
.arg("--dir").arg("/mnt/fs/root") ;
if let ContainerType::Slice = ins.metadata().container_type() {
process.arg("--dir").arg("/root")
.arg("--ro-bind").arg(format!("{}/bin", *DIST_IMG)).arg("/mnt/fs/bin")
.arg("--ro-bind").arg(format!("{}/lib", *DIST_IMG)).arg("/mnt/fs/lib64")
.arg("--dir").arg("/mnt/fs/root") ;
if arguments[0] == "ash" {
process.arg("--hostname").arg("BusyBox")
.arg("--setenv").arg("ENV").arg("/etc/profile")
} else {
process.arg("--hostname").arg("FakeChroot")
.arg("fakeroot").arg("chroot").arg("/mnt/fs")
}
if arguments[0] == "ash" {
process.arg("--hostname").arg("BusyBox")
.arg("--setenv").arg("ENV").arg("/etc/profile")
} else {
process.arg("--hostname").arg("FakeChroot")
.arg("--ro-bind").arg("/etc/resolv.conf").arg("/etc/resolv.conf")
.arg("--bind").arg(ins.vars().pacman_gnupg()).arg("/mnt/fs/etc/pacman.d/gnupg")
.arg("--bind").arg(ins.vars().pacman_cache()).arg("/mnt/fs/var/cache/pacman/pkg")
.arg("--bind").arg(ins.vars().home()).arg("/mnt/fs/root")
.arg("--setenv").arg("EUID").arg("0")
.arg("--setenv").arg("PATH").arg(DEFAULT_PATH)
.arg("fakeroot").arg("chroot").arg("/mnt/fs")
};
}
} else {
process.arg("--hostname").arg("FakeChroot")
.arg("--ro-bind").arg("/etc/resolv.conf").arg("/etc/resolv.conf")
.arg("--bind").arg(ins.vars().pacman_gnupg()).arg("/mnt/fs/etc/pacman.d/gnupg")
.arg("--bind").arg(ins.vars().pacman_cache()).arg("/mnt/fs/var/cache/pacman/pkg")
.arg("--bind").arg(ins.vars().home()).arg("/mnt/fs/root")
.arg("--setenv").arg("EUID").arg("0")
.arg("--setenv").arg("PATH").arg(DEFAULT_PATH)
.arg("fakeroot").arg("chroot").arg("/mnt/fs")
};
match process.args(arguments)
.fd_mappings(fd_mappings)
.unwrap()
.spawn()
match process.args(arguments)
.fd_mappings(fd_mappings)
.expect("FD Mappings")
.spawn()
{
Ok(child) => wait_on_fakeroot(exec_type, child, term_control, decode_info_json(info_pipe)?, trap),
Err(err) => err!(ErrorKind::ProcessInitFailure(BWRAP_EXECUTABLE, err.kind())),
@ -197,30 +197,35 @@ pub fn fakeroot_container(exec_type: ExecutionType, trap: Option<fn(i32)>, ins:
}
#[rustfmt::skip]
pub fn transaction_agent(ins: &ContainerHandle, params: TransactionParameters, metadata: &TransactionMetadata) -> Result<Child> {
let params_pipe = os_pipe::pipe().expect("params pipe");
pub fn transaction_agent(
ins: &ContainerHandle,
flags: &TransactionFlags,
params: TransactionParameters,
metadata: &TransactionMetadata,
) -> Result<Child> {
let params_pipe = os_pipe::pipe().expect("params pipe");
let params_fd = agent_params(&params_pipe.0, &params_pipe.1, &params, metadata)?;
let sec_pipe = os_pipe::pipe().expect("eBPF pipe");
let sec_fd = provide_bpf_program(vec![Standard, Namespaces], &sec_pipe.0, sec_pipe.1).expect("eBPF program");
let fd_mappings = vec![
FdMapping {
parent_fd: sec_fd,
child_fd: sec_fd
},
FdMapping {
parent_fd: params_fd,
child_fd: params_fd
},
];
match Command::new(BWRAP_EXECUTABLE).env_clear()
.arg("--bind").arg(ins.vars().root()).arg("/mnt/fs")
let fd_mappings = vec![
FdMapping {
parent_fd: sec_fd,
child_fd: sec_fd
},
FdMapping {
parent_fd: params_fd,
child_fd: params_fd
},
];
let mut process = Command::new(BWRAP_EXECUTABLE);
process.arg("--bind").arg(ins.vars().root()).arg("/mnt/fs")
.arg("--symlink").arg("/mnt/fs/usr").arg("/usr")
.arg("--ro-bind").arg(format!("{}/bin", *DIST_IMG)).arg("/bin")
.arg("--ro-bind").arg(format!("{}/lib", *DIST_IMG)).arg("/lib64")
.arg("--symlink").arg("lib").arg("/lib")
.arg("--ro-bind").arg("/etc/resolv.conf").arg("/etc/resolv.conf")
.arg("--ro-bind").arg("/etc/localtime").arg("/etc/localtime")
.arg("--ro-bind").arg("/etc/localtime").arg("/etc/localtime")
.arg("--ro-bind").arg(*DIST_TLS).arg("/etc/ssl/certs/ca-certificates.crt")
.arg("--bind").arg(*LOG_LOCATION).arg("/mnt/share/pacwrap.log")
.arg("--bind").arg(ins.vars().pacman_gnupg()).arg("/mnt/share/gnupg")
@ -228,6 +233,7 @@ pub fn transaction_agent(ins: &ContainerHandle, params: TransactionParameters, m
.arg("--dev").arg("/dev")
.arg("--dev").arg("/mnt/fs/dev")
.arg("--proc").arg("/mnt/fs/proc")
.arg("--proc").arg("/proc")
.arg("--unshare-all")
.arg("--share-net")
.arg("--hostname").arg("pacwrap-agent")
@ -241,7 +247,6 @@ pub fn transaction_agent(ins: &ContainerHandle, params: TransactionParameters, m
.arg("--setenv").arg("LD_PRELOAD").arg("/lib64/libfakechroot.so")
.arg("--setenv").arg("PACWRAP_REAL_UID").arg(ID.0)
.arg("--setenv").arg("PACWRAP_REAL_GID").arg(ID.1)
.arg("--setenv").arg("RUST_BACKTRACE").arg("1")
.arg("--die-with-parent")
.arg("--unshare-user")
.arg("--disable-userns")
@ -249,15 +254,20 @@ pub fn transaction_agent(ins: &ContainerHandle, params: TransactionParameters, m
.arg(sec_fd.to_string())
.arg("--ro-bind-data")
.arg(params_fd.to_string())
.arg("/mnt/agent_params")
.arg("agent")
.arg("/mnt/agent_params");
if flags.contains(TransactionFlags::DEBUG) {
process.arg("--setenv").arg("RUST_BACKTRACE").arg("full");
}
match process.arg("agent")
.arg("transact")
.fd_mappings(fd_mappings)
.unwrap()
.expect("FD Mappings")
.spawn()
{
Ok(child) => Ok(child),
Err(err) => err!(ErrorKind::ProcessInitFailure(BWRAP_EXECUTABLE, err.kind())),
Ok(child) => Ok(child),
Err(err) => err!(ErrorKind::ProcessInitFailure(BWRAP_EXECUTABLE, err.kind())),
}
}

View file

@ -22,7 +22,6 @@ use std::{
fs::{File, OpenOptions},
io::Write,
path::Path,
time::{SystemTime, UNIX_EPOCH},
};
use time::{format_description::FormatItem, macros::format_description, OffsetDateTime, UtcOffset};
@ -31,8 +30,9 @@ use crate::{
constants::{LOG_LOCATION, UNIX_TIMESTAMP},
err,
impl_error,
utils::unix_epoch_time,
Error,
ErrorKind,
ErrorGeneric,
ErrorTrait,
Result,
};
@ -107,7 +107,7 @@ impl From<i8> for Level {
}
impl Display for Level {
fn fmt(&self, fmter: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
fn fmt(&self, fmter: &mut Formatter<'_>) -> FmtResult {
write!(fmter, "{}", self.to_str())
}
}
@ -126,11 +126,15 @@ impl Logger {
* between libalpm and the time crate, cache the offset during the
* initalisation of this struct.
*/
let ofs = OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.format(UTC_OFFSET)
.unwrap();
let ofs = UtcOffset::parse(ofs.as_str(), UTC_OFFSET).unwrap();
let ofs = UtcOffset::parse(
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.format(UTC_OFFSET)
.expect("Format UTC offset")
.as_str(),
UTC_OFFSET,
)
.expect("Parse UTC offset");
Self {
verbosity: 3,
@ -140,14 +144,16 @@ impl Logger {
}
}
pub fn init(mut self) -> Result<Self> {
let path = Path::new(*LOG_LOCATION);
pub fn location(mut self, location: &str) -> Result<Self> {
let path = Path::new(location);
let file = OpenOptions::new().create(true).append(true).truncate(false).open(path);
self.file = Some(match file {
Ok(file) => file,
Err(error) => err!(ErrorKind::IOError(LOG_LOCATION.to_string(), error.kind()))?,
});
self.file = Some(file.prepend_io(|| location.into())?);
Ok(self)
}
pub fn init(mut self) -> Result<Self> {
self = self.location(*LOG_LOCATION)?;
Ok(self)
}
@ -155,9 +161,10 @@ impl Logger {
self.verbosity = verbosity
}
pub fn log(&mut self, level: Level, msg: &str) -> Result<()> {
pub fn log(&mut self, level: Level, msg: &str) -> Result<usize> {
// Check message verbosity against logger verbosity
if level.verbosity() > self.verbosity {
return Ok(());
return Ok(0);
}
/*
@ -168,27 +175,27 @@ impl Logger {
* time offset if a change were to occur whilst this application is running.
*/
if let Ok(local) = OffsetDateTime::now_local() {
self.offset = UtcOffset::parse(local.format(UTC_OFFSET).unwrap().as_str(), UTC_OFFSET).unwrap();
}
let local_time = local.format(UTC_OFFSET).expect("Format localtime");
let time: OffsetDateTime = OffsetDateTime::now_utc().to_offset(self.offset);
let write = if let Some(file) = self.file.as_mut() {
file.write(format!("[{}] [{}] [{}] {}\n", time.format(DATE_FORMAT).unwrap(), self.module, level, msg).as_bytes())
} else {
err!(LoggerError::Uninitialized)?
};
self.offset = UtcOffset::parse(&local_time, UTC_OFFSET).expect("Offset localtime");
}
if let Level::Debug = level {
let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("SystemTime now");
let now = unix_epoch_time();
let nano = format!("{:.6}", now.subsec_nanos().to_string());
let time = now.as_secs() as usize - *UNIX_TIMESTAMP as usize;
let nano = now.subsec_nanos().to_string();
eprintln!("[{}.{:.6}] [{}] {}", time, nano, self.module, msg);
eprintln!("[{}.{}] [{}] {}", time, nano, self.module, msg);
}
match write {
Ok(_) => Ok(()),
Err(error) => err!(ErrorKind::IOError(LOG_LOCATION.to_string(), error.kind())),
match self.file.as_mut() {
Some(file) => {
let time = OffsetDateTime::now_utc().to_offset(self.offset).format(DATE_FORMAT).expect("Format time");
let log = format!("[{}] [{}] [{}] {}\n", time, self.module, level, msg);
file.write(log.as_bytes()).generic()
}
None => err!(LoggerError::Uninitialized)?,
}
}
}

View file

@ -22,7 +22,6 @@ use std::{
os::unix::fs::symlink,
path::Path,
sync::OnceLock,
time::{SystemTime, UNIX_EPOCH},
};
use alpm::{Alpm, LogLevel, SigLevel, Usage};
@ -30,16 +29,22 @@ use pacmanconf::{self, Config, Repository};
use serde::{Deserialize, Serialize};
use crate::{
config::{global, global::ProgressKind, ContainerHandle, ContainerType::*, ContainerVariables, Global},
config::{
global::{global, ProgressKind},
ContainerHandle,
ContainerType::*,
ContainerVariables,
Global,
},
constants::{ARROW_RED, BAR_GREEN, BOLD, CACHE_DIR, CONFIG_DIR, DATA_DIR, RESET, UNIX_TIMESTAMP, VERBOSE},
err,
exec::pacwrap_key,
impl_error,
sync::{
event::download::{self, DownloadEvent},
filesystem::{create_blank_state, create_hard_link},
transaction::{TransactionAggregator, TransactionFlags},
},
utils::unix_epoch_time,
Error,
ErrorGeneric,
ErrorTrait,
@ -91,6 +96,8 @@ impl Display for SyncError {
write!(fmter, "Target package {}{pkg}{}: Not available in sync databases.", *BOLD, *RESET),
Self::TargetUpstream(pkg) =>
write!(fmter, "Target package {}{pkg}{}: Installed in upstream container.", *BOLD, *RESET),
Self::TransactionAgentError | Self::TransactionAgentFailure =>
write!(fmter, "Agent process terminated due to upstream error."),
Self::RecursionDepthExceeded(u) => write!(fmter, "Recursion depth exceeded maximum of {}{u}{}.", *BOLD, *RESET),
Self::NoCompatibleRemotes => write!(fmter, "No compatible containers available to synchronize remote database."),
Self::InvalidMagicNumber => write!(fmter, "Deserialization of input parameters failed: Invalid magic number."),
@ -104,23 +111,23 @@ impl Display for SyncError {
Self::InternalError(msg) => write!(fmter, "Internal failure: {msg}"),
Self::SignalInterrupt => write!(fmter, "Signal interrupt was triggered."),
Self::UnableToLocateKeyrings => write!(fmter, "Unable to locate pacman keyrings."),
Self::TransactionAgentError => write!(fmter, "Agent process terminated due to upstream error."),
Self::RepoConfError(path, err) => write!(fmter, "'{}': {}", path, err),
Self::NothingToDo => write!(fmter, "Nothing to do."),
_ => Ok(()),
}?;
if let Self::TransactionFailure(_) = self {
Ok(())
} else if let Self::SignalInterrupt = self {
write!(fmter, "\n{} Transaction aborted.", *ARROW_RED)
} else {
write!(fmter, "\n{} Transaction failed.", *ARROW_RED)
}
}
}
impl_error!(SyncError);
impl ErrorTrait for SyncError {
fn code(&self) -> i32 {
match self {
Self::TransactionFailure(_) => (),
Self::SignalInterrupt => eprintln!("{} Transaction aborted.", *ARROW_RED),
_ => eprintln!("{} Transaction failed.", *ARROW_RED),
}
1
}
}
impl From<&Error> for SyncError {
fn from(error: &Error) -> SyncError {
@ -255,7 +262,7 @@ fn alpm_handle(
}
fn alpm_log_callback(level: LogLevel, msg: &str, counter: &mut usize) {
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let now = unix_epoch_time();
let time = now.as_secs() as usize - *counter;
let nano = now.subsec_nanos().to_string();
let log_level = level.bits() / 4;

View file

@ -287,12 +287,18 @@ impl<'a> TransactionAggregator<'a> {
handle.release();
return match err.downcast::<SyncError>().map_err(|err| error!(SyncError::from(err)))? {
SyncError::TransactionAgentFailure => {
self.logger().log(Level::Fatal, &format!("Transaction error: {:?}", err))?;
SyncError::TransactionAgentFailure
| SyncError::ParameterAcquisitionFailure
| SyncError::DeserializationFailure => {
self.logger().log(Level::Fatal, &format!("Transaction error: {}", err))?;
err.fatal()
}
SyncError::AgentVersionMismatch | SyncError::InvalidMagicNumber => {
self.logger().log(Level::Error, &format!("Transaction error: {}", err))?;
err.error()
}
_ => {
self.logger().log(Level::Error, &format!("Transaction error: {:?}", err))?;
self.logger().log(Level::Error, &format!("Transaction error: {}", err))?;
Err(err)
}
};

View file

@ -87,19 +87,15 @@ impl Transaction for Commit {
erroneous_preparation(error)?
}
let result = confirm(&self.state, ag, handle, global()?);
let result = match result {
Err(result) => return result,
Ok(result) => result,
let trans_state = match confirm(&self.state, ag, handle, global()?) {
Err(error) => return error,
Ok(state) => state,
};
let params = TransactionParameters::new(*ag.action(), *handle.get_mode(), trans_state);
handle.set_alpm(None);
ag.lock()?.assert()?;
wait_on_agent(transaction_agent(
inshandle,
TransactionParameters::new(*ag.action(), *handle.get_mode(), result),
handle.meta,
)?)?;
wait_on_agent(transaction_agent(inshandle, ag.flags(), params, handle.meta)?)?;
if self.keyring {
ag.keyring_update(inshandle)?;
@ -203,7 +199,7 @@ fn wait_on_agent(mut agent: Child) -> Result<()> {
Ok(status) => match status.code().unwrap_or(-1) {
0 => Ok(()),
1 => err!(SyncError::TransactionAgentError),
2 => err!(SyncError::TransactionAgentFailure),
2 | 101 => err!(SyncError::TransactionAgentFailure),
3 => err!(SyncError::ParameterAcquisitionFailure),
4 => err!(SyncError::DeserializationFailure),
5 => err!(SyncError::InvalidMagicNumber),

View file

@ -20,7 +20,14 @@
use std::thread::Builder;
use alpm::{
Alpm, CommitData, CommitError, Error::{ConflictingDeps, FileConflicts, PkgInvalid, PkgInvalidArch, PkgInvalidChecksum, PkgInvalidSig, UnsatisfiedDeps}, FileConflictType, Package, PrepareData, PrepareError
Alpm,
CommitData,
CommitError,
Error::{ConflictingDeps, FileConflicts, PkgInvalid, PkgInvalidArch, PkgInvalidChecksum, PkgInvalidSig, UnsatisfiedDeps},
FileConflictType,
Package,
PrepareData,
PrepareError,
};
use signal_hook::iterator::Signals;
@ -109,7 +116,6 @@ pub fn erroneous_transaction(error: CommitError) -> Result<()> {
}
}
}
}
err!(SyncError::TransactionFailure("Conflict within container filesystem".into()))?

View file

@ -21,7 +21,7 @@ use std::{
env::var,
os::unix::net::UnixStream,
path::Path,
time::{SystemTime, UNIX_EPOCH},
time::{Duration, SystemTime, UNIX_EPOCH},
};
use crate::{
@ -55,8 +55,8 @@ pub fn check_socket(socket: &String) -> bool {
UnixStream::connect(Path::new(socket)).is_ok()
}
pub fn unix_time_as_seconds() -> u64 {
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()
pub fn unix_epoch_time() -> Duration {
SystemTime::now().duration_since(UNIX_EPOCH).expect("SystemTime")
}
pub fn whitespace(amt: usize) -> String {

View file

@ -43,7 +43,7 @@ pub fn remove(args: &mut Arguments) -> Result<()> {
return remove_containers(args);
}
let mut logger = Logger::new("pacwrap-sync").init().unwrap();
let mut logger = Logger::new("pacwrap-sync").init()?;
let action = action(args);
let lock = Lock::new().lock()?;
let result = engage_aggregator(action, args, &mut logger, &lock);

View file

@ -44,7 +44,7 @@ pub fn synchronize(args: &mut Arguments) -> Result<()> {
check_root()?;
init()?;
let mut logger = Logger::new("pacwrap-sync").init().unwrap();
let mut logger = Logger::new("pacwrap-sync").init()?;
let mut cache = cache::populate()?;
let (action, create) = action(args);
let lock = Lock::new().lock()?;