parent
740967756b
commit
837f72f19c
@ -0,0 +1,14 @@
|
|||||||
|
//! Builder pattern for logging options
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use std::{
|
||||||
|
path::{
|
||||||
|
PathBuf,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct LoggingOptions
|
||||||
|
{
|
||||||
|
output_logfile: Some((PathBuf, u32)),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,141 @@
|
|||||||
|
//! Logging hooks for logfile output
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use std::{
|
||||||
|
path::{
|
||||||
|
PathBuf,
|
||||||
|
Path,
|
||||||
|
},
|
||||||
|
sync::Arc,
|
||||||
|
io::{
|
||||||
|
self,
|
||||||
|
ErrorKind,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use tokio::{
|
||||||
|
prelude::*,
|
||||||
|
sync::{
|
||||||
|
mpsc,
|
||||||
|
},
|
||||||
|
task,
|
||||||
|
fs::{OpenOptions,File,},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Internal
|
||||||
|
{
|
||||||
|
stdout: PathBuf,
|
||||||
|
stderr: PathBuf,
|
||||||
|
|
||||||
|
use_local_time: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Command
|
||||||
|
{
|
||||||
|
level: Level,
|
||||||
|
|
||||||
|
trace: Trace,
|
||||||
|
timestamp: Date,
|
||||||
|
message: String,
|
||||||
|
|
||||||
|
is_err: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// Logging hook that appends to logfiles
|
||||||
|
pub struct LogFileHook
|
||||||
|
{
|
||||||
|
mask: Level,
|
||||||
|
|
||||||
|
internal: Arc<Internal>,
|
||||||
|
|
||||||
|
sender: Option<mpsc::Sender<Command>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogFileHook
|
||||||
|
{
|
||||||
|
/// Create a new log file hook
|
||||||
|
pub fn new<L,P,E>(mask: L, path: P, error: E, use_local_time: bool) -> Self
|
||||||
|
where L: Into<Level>,
|
||||||
|
P: AsRef<Path>,
|
||||||
|
E: AsRef<Path>
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
mask: mask.into(),
|
||||||
|
internal: Arc::new(Internal{
|
||||||
|
stderr: error.as_ref().to_owned(),
|
||||||
|
stdout: path.as_ref().to_owned(),
|
||||||
|
use_local_time,
|
||||||
|
}),
|
||||||
|
sender: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_log(file: &mut File, com: Command) -> std::io::Result<()>
|
||||||
|
{
|
||||||
|
let output = format!("{} <{}> [{}]: {}\n", com.timestamp, com.trace, com.level, com.message);
|
||||||
|
file.write(output.as_bytes()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const BACKLOG: usize = 100;
|
||||||
|
|
||||||
|
impl Hook for LogFileHook
|
||||||
|
{
|
||||||
|
fn initialise(&mut self, _: &Index)
|
||||||
|
{
|
||||||
|
let (tx, mut rx) = mpsc::channel(BACKLOG);
|
||||||
|
|
||||||
|
let internal = Arc::clone(&self.internal);
|
||||||
|
|
||||||
|
self.sender = Some(tx);
|
||||||
|
task::spawn(async move {
|
||||||
|
let (stdout, stderr) = (Path::new(&internal.stdout), Path::new(&internal.stderr));
|
||||||
|
|
||||||
|
while let Some(command) = rx.recv().await {
|
||||||
|
let path = if command.is_err {stderr} else {stdout};
|
||||||
|
|
||||||
|
let mut file = match OpenOptions::new()
|
||||||
|
.append(true)
|
||||||
|
.create(true)
|
||||||
|
.open(path).await {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(err) => {
|
||||||
|
crate::warn!("Could not open logfile {:?} for writing: {}", path, err);
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(err) = write_log(&mut file, command).await {
|
||||||
|
crate::warn!("Failed writing to logfile {:?}: {}", path, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalise(&mut self, _: Index)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn println(&mut self, level: &dyn AsLevel, what: &dyn Display, trace: &Trace) -> io::Result<()>
|
||||||
|
{
|
||||||
|
let com = Command {
|
||||||
|
timestamp: if self.internal.use_local_time {Date::now_local()} else {Date::now_utc()},
|
||||||
|
is_err: level.is_err(),
|
||||||
|
trace: trace.clone(),
|
||||||
|
message: what.to_string(),
|
||||||
|
level: level.borrow().clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(sender) = &mut self.sender {
|
||||||
|
if let Err(e) = sender.try_send(com) {
|
||||||
|
return Err(io::Error::new(ErrorKind::BrokenPipe, format!("Failed to pass to worker: {}", e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
//! Permissions shit kms
|
||||||
|
//!
|
||||||
|
//! No I don't care about Microshaft wangblows
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
use bitflags::bitflags;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
enum Class
|
||||||
|
{
|
||||||
|
Owner(Bit),
|
||||||
|
Group(Bit),
|
||||||
|
Other(Bit),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Class
|
||||||
|
{
|
||||||
|
/// Lmfao. Fuck bit masks and unix permissiong, `const fn` so idc
|
||||||
|
const fn mode(&self) -> u32
|
||||||
|
{
|
||||||
|
macro_rules! map {
|
||||||
|
($bit:expr, $bt:path, $constant:ident) => {
|
||||||
|
if $bit.contains($bt) {
|
||||||
|
$constant
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match self {
|
||||||
|
Self::Owner(bit) => {
|
||||||
|
0u32 |
|
||||||
|
map!(bit, Bit::Read, MODE_USER_READ) |
|
||||||
|
map!(bit, Bit::Write, MODE_USER_WRITE) |
|
||||||
|
map!(bit, Bit::Execute, MODE_USER_EXECUTE)
|
||||||
|
},
|
||||||
|
Self::Group(bit) => {
|
||||||
|
0u32 |
|
||||||
|
map!(bit, Bit::Read, MODE_GROUP_READ) |
|
||||||
|
map!(bit, Bit::Write, MODE_GROUP_WRITE) |
|
||||||
|
map!(bit, Bit::Execute, MODE_GROUP_EXECUTE)
|
||||||
|
},
|
||||||
|
Self::Other(bit) => {
|
||||||
|
0u32 |
|
||||||
|
map!(bit, Bit::Read, MODE_OTHER_READ) |
|
||||||
|
map!(bit, Bit::Write, MODE_OTHER_WRITE) |
|
||||||
|
map!(bit, Bit::Execute, MODE_OTHER_EXECUTE)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn mask_mode(&self, bit: u32) -> Bit
|
||||||
|
{
|
||||||
|
macro_rules! map {
|
||||||
|
($bit:expr, $bt:path, $constant:ident) => {
|
||||||
|
if ($bit & $constant) == $constant {$bt.bits()} else {0u32}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit::from_bits_truncate(match self {
|
||||||
|
Self::Owner(_) => {
|
||||||
|
map!(bit, Bit::Read, MODE_USER_READ) |
|
||||||
|
map!(bit, Bit::Write, MODE_USER_WRITE) |
|
||||||
|
map!(bit, Bit::Execute, MODE_USER_EXECUTE)
|
||||||
|
},
|
||||||
|
Self::Group(_) => {
|
||||||
|
map!(bit, Bit::Read, MODE_GROUP_READ) |
|
||||||
|
map!(bit, Bit::Write, MODE_GROUP_WRITE) |
|
||||||
|
map!(bit, Bit::Execute, MODE_GROUP_EXECUTE)
|
||||||
|
},
|
||||||
|
Self::Other(_) => {
|
||||||
|
map!(bit, Bit::Read, MODE_OTHER_READ) |
|
||||||
|
map!(bit, Bit::Write, MODE_OTHER_WRITE) |
|
||||||
|
map!(bit, Bit::Execute, MODE_OTHER_EXECUTE)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MODE_USER: u32 = 0o700;
|
||||||
|
const MODE_USER_READ: u32 = 0o400;
|
||||||
|
const MODE_USER_WRITE: u32 = 0o200;
|
||||||
|
const MODE_USER_EXECUTE: u32 = 0o100;
|
||||||
|
|
||||||
|
const MODE_GROUP: u32 = 0o70;
|
||||||
|
const MODE_GROUP_READ: u32 = 0o40;
|
||||||
|
const MODE_GROUP_WRITE: u32 = 0o20;
|
||||||
|
const MODE_GROUP_EXECUTE: u32 = 0o10;
|
||||||
|
|
||||||
|
const MODE_OTHER: u32 = 0o7;
|
||||||
|
const MODE_OTHER_READ: u32 = 0o4;
|
||||||
|
const MODE_OTHER_WRITE: u32 = 0o2;
|
||||||
|
const MODE_OTHER_EXECUTE: u32 = 0o1;
|
||||||
|
|
||||||
|
const MODE: u32 = 0o777;
|
||||||
|
|
||||||
|
bitflags!{
|
||||||
|
pub struct Bit: u32 {
|
||||||
|
const None = 0;
|
||||||
|
const Read = 1;
|
||||||
|
const Write = 2;
|
||||||
|
const Execute = 4;
|
||||||
|
const Mask = 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags!{
|
||||||
|
struct StickyBit: u32{
|
||||||
|
const None = 0;
|
||||||
|
const Setuid = 0o40000;
|
||||||
|
const Setgid = 0o20000;
|
||||||
|
const SaveSwap = 0o10000;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Permissions struct in readable format
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Ord, PartialOrd)]
|
||||||
|
pub struct Permissions
|
||||||
|
{
|
||||||
|
pub u_owner: Bit,
|
||||||
|
pub u_group: Bit,
|
||||||
|
pub u_other: Bit,
|
||||||
|
|
||||||
|
_u_sticky: StickyBit, //idc about this either
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Permissions
|
||||||
|
{
|
||||||
|
#[inline] fn default() -> Self
|
||||||
|
{
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Permissions
|
||||||
|
{
|
||||||
|
/// Create a new empty `Permissions` struct
|
||||||
|
pub const fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
u_owner: Bit::None,
|
||||||
|
u_group: Bit::None,
|
||||||
|
u_other: Bit::None,
|
||||||
|
_u_sticky: StickyBit::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask impl
|
||||||
|
impl Permissions
|
||||||
|
{
|
||||||
|
#[inline] const fn c_owner(&self) -> Class
|
||||||
|
{
|
||||||
|
Class::Owner(self.u_owner)
|
||||||
|
}
|
||||||
|
#[inline] const fn c_group(&self) -> Class
|
||||||
|
{
|
||||||
|
Class::Group(self.u_group)
|
||||||
|
}
|
||||||
|
#[inline] const fn c_other(&self) -> Class
|
||||||
|
{
|
||||||
|
Class::Other(self.u_other)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert into `mode_t` repr.
|
||||||
|
#[inline] pub const fn mask(&self) -> u32
|
||||||
|
{
|
||||||
|
self.c_owner().mode() |
|
||||||
|
self.c_group().mode() |
|
||||||
|
self.c_other().mode()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert from `mode_t` repr.
|
||||||
|
#[inline] pub const fn from_mask(bit: u32) -> Self
|
||||||
|
{
|
||||||
|
Self{
|
||||||
|
u_owner: Class::Owner(Bit::Mask).mask_mode(bit),
|
||||||
|
u_group: Class::Group(Bit::Mask).mask_mode(bit),
|
||||||
|
u_other: Class::Other(Bit::Mask).mask_mode(bit),
|
||||||
|
|
||||||
|
_u_sticky: StickyBit::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Permissions> for u32
|
||||||
|
{
|
||||||
|
#[inline] fn from(from: Permissions) -> Self
|
||||||
|
{
|
||||||
|
from.mask()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for Permissions
|
||||||
|
{
|
||||||
|
#[inline] fn from(from: u32) -> Self
|
||||||
|
{
|
||||||
|
Self::from_mask(from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue