Avril 4 years ago
parent 740967756b
commit 837f72f19c
Signed by: flanchan
GPG Key ID: 284488987C31F630

1
Cargo.lock generated

@ -388,6 +388,7 @@ dependencies = [
name = "lolicron"
version = "0.1.0"
dependencies = [
"bitflags",
"cfg-if",
"chrono",
"config_struct",

@ -41,6 +41,7 @@ libc = "0.2"
cfg-if = "0.1"
generational-arena = "0.2"
mopa = "0.2"
readable-perms = "0.1"
[build-dependencies]
rustc_version = "0.2"

@ -0,0 +1,14 @@
//! Builder pattern for logging options
use super::*;
use std::{
path::{
PathBuf,
},
};
pub struct LoggingOptions
{
output_logfile: Some((PathBuf, u32)),
}

@ -26,3 +26,9 @@ impl std::fmt::Debug for dyn Hook
write!(f, "<opaque type>")
}
}
// Customs
mod global_logfile;
pub use global_logfile::*;

@ -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(())
}
}

@ -19,10 +19,17 @@ pub trait AsLevel: fmt::Display + Borrow<Level>{
{
write!(f, "{}/", Borrow::<Level>::borrow(self))
}
#[inline] fn is_err(&self) -> bool {self.borrow().is_err()}
}
impl AsLevel for Level{
#[inline] fn prefix(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result{Ok(())}
#[inline] fn is_err(&self) -> bool {
match self {
Self::Error | Self::Warn | Self::Silent => true,
_ => false,
}
}
}
impl AsLevel for &Level{
#[inline] fn prefix(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result{Ok(())}

@ -41,6 +41,58 @@ pub struct Logger
static INSTANCE: OnceCell<Logger> = OnceCell::new();
#[derive(Debug)]
/// Dynamic date wrapper
enum Date {
/// Local time
Local(chrono::DateTime<chrono::offset::Local>),
/// Utc time
Utc(chrono::DateTime<chrono::offset::Utc>),
}
impl Date
{
/// Timestamp for now (local time)
pub fn now_local() -> Self
{
chrono::offset::Local::now().into()
}
/// Timestamp for now (UTC time)
pub fn now_utc() -> Self
{
chrono::offset::Utc::now().into()
}
}
impl std::fmt::Display for Date
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Local(l) => write!(f, "{}", l.format(DATE_FORMAT.as_ref())),
Self::Utc(l) => write!(f, "{}", l.format(DATE_FORMAT.as_ref())),
}
}
}
impl From<chrono::DateTime<chrono::offset::Local>> for Date
{
#[inline]
fn from(from: chrono::DateTime<chrono::offset::Local>) -> Self
{
Self::Local(from)
}
}
impl From<chrono::DateTime<chrono::offset::Utc>> for Date
{
#[inline]
fn from(from: chrono::DateTime<chrono::offset::Utc>) -> Self
{
Self::Utc(from)
}
}
impl Logger
{
/// Create a new logger
@ -171,39 +223,7 @@ impl Logger
{
self.dispatch(&level, &what, &trace);
//lol
enum Date {
Local(chrono::DateTime<chrono::offset::Local>),
Utc(chrono::DateTime<chrono::offset::Utc>),
}
impl std::fmt::Display for Date
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Local(l) => write!(f, "{}", l.format(DATE_FORMAT.as_ref())),
Self::Utc(l) => write!(f, "{}", l.format(DATE_FORMAT.as_ref())),
}
}
}
impl From<chrono::DateTime<chrono::offset::Local>> for Date
{
#[inline]
fn from(from: chrono::DateTime<chrono::offset::Local>) -> Self
{
Self::Local(from)
}
}
impl From<chrono::DateTime<chrono::offset::Utc>> for Date
{
#[inline]
fn from(from: chrono::DateTime<chrono::offset::Utc>) -> Self
{
Self::Utc(from)
}
}
if &self.level >= level.borrow() {
let now: Date = if self.use_local_time {
@ -365,7 +385,6 @@ impl Logger
};
}
#[macro_export] macro_rules! dangerous {
($obj:expr) => {
{

@ -32,6 +32,8 @@ mod hot;
mod context;
mod job;
mod perms;
//This is a test function, when we have a real job server, remove it.
async fn do_thing_every() -> Result<(mpsc::Sender<()>, task::JoinHandle<()>), Box<dyn std::error::Error>>
{
@ -123,6 +125,7 @@ fn print_stats()
async fn main() -> Result<(), Box<dyn std::error::Error>> {
log::init(log::Level::Debug);
//log::Logger::global().add_hook(log::custom::LogFileHook::new(log::Level::Debug, "test.log", "test.err.log", false));
debug!("Logger initialised"); //TODO: Parse config first
print_stats();

@ -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)
}
}

@ -0,0 +1,21 @@
2020-08-05 01:04:28 UTC <src/main.rs:128:5> [Debug]: Logger initialised2020-08-05 01:04:28 UTC <src/main.rs:88:5> [Debug]: This is the lolicron daemon version 0.1.0 by Avril <flanchan@cumallover.me>, Mx. Package Install <boku@plum.moe> (debug build)2020-08-05 01:04:28 UTC <src/main.rs:89:5> [Debug]: ---2020-08-05 01:04:28 UTC <src/main.rs:90:5> [Debug]: Compiled with (on (default), off (default)):2020-08-05 01:04:28 UTC <src/main.rs:92:21> [Debug]:  +nightly2020-08-05 01:04:28 UTC <src/main.rs:93:30> [Debug]:  +debug_assertions2020-08-05 01:04:28 UTC <src/main.rs:95:5> [Debug]: features:2020-08-05 01:04:28 UTC <src/main.rs:97:32> [Debug]:  +threaded2020-08-05 01:04:28 UTC <src/main.rs:100:31> [Debug]:  +watcher2020-08-05 01:04:28 UTC <src/main.rs:103:36> [Debug]:  +debug_logger2020-08-05 01:04:28 UTC <src/main.rs:107:46> [Debug]:  -watcher_unlimited2020-08-05 01:04:28 UTC <src/main.rs:109:39> [Debug]:  +watcher_timeout2020-08-05 01:04:28 UTC <src/main.rs:112:5> [Debug]: 2020-08-05 01:04:28 UTC <src/config/mod.rs:71:2> [Debug]: Static options:2020-08-05 01:04:28 UTC <src/config/mod.rs:72:2> [Debug]: hot::BACKLOG = 1002020-08-05 01:04:28 UTC <src/config/mod.rs:73:2> [Debug]: hot::TIMEOUT = 52020-08-05 01:04:28 UTC <src/main.rs:116:5> [Debug]: GPl'd with <32020-08-05 01:04:28 UTC <src/main.rs:117:5> [Debug]: Please enjoy2020-08-05 01:04:28 UTC <src/main.rs:119:5> [Debug]: ---2020-08-05 01:04:28 UTC <src/hot.rs:276:6> [Debug]: Watcher initialised, starting for path "/home/avril/work/lolicron"2020-08-05 01:04:28 UTC <src/hot.rs:305:6> [Info]: Watcher up2020-08-05 01:05:39 UTC <src/main.rs:128:5> [Debug]: Logger initialised
2020-08-05 01:05:39 UTC <src/main.rs:88:5> [Debug]: This is the lolicron daemon version 0.1.0 by Avril <flanchan@cumallover.me>, Mx. Package Install <boku@plum.moe> (debug build)
2020-08-05 01:05:39 UTC <src/main.rs:89:5> [Debug]: ---
2020-08-05 01:05:39 UTC <src/main.rs:90:5> [Debug]: Compiled with (on (default), off (default)):
2020-08-05 01:05:39 UTC <src/main.rs:92:21> [Debug]:  +nightly
2020-08-05 01:05:39 UTC <src/main.rs:93:30> [Debug]:  +debug_assertions
2020-08-05 01:05:39 UTC <src/main.rs:95:5> [Debug]: features:
2020-08-05 01:05:39 UTC <src/main.rs:97:32> [Debug]:  +threaded
2020-08-05 01:05:39 UTC <src/main.rs:100:31> [Debug]:  +watcher
2020-08-05 01:05:39 UTC <src/main.rs:103:36> [Debug]:  +debug_logger
2020-08-05 01:05:39 UTC <src/main.rs:107:46> [Debug]:  -watcher_unlimited
2020-08-05 01:05:39 UTC <src/main.rs:109:39> [Debug]:  +watcher_timeout
2020-08-05 01:05:39 UTC <src/main.rs:112:5> [Debug]:
2020-08-05 01:05:39 UTC <src/config/mod.rs:71:2> [Debug]: Static options:
2020-08-05 01:05:39 UTC <src/config/mod.rs:72:2> [Debug]: hot::BACKLOG = 100
2020-08-05 01:05:39 UTC <src/config/mod.rs:73:2> [Debug]: hot::TIMEOUT = 5
2020-08-05 01:05:39 UTC <src/main.rs:116:5> [Debug]: GPl'd with <3
2020-08-05 01:05:39 UTC <src/main.rs:117:5> [Debug]: Please enjoy
2020-08-05 01:05:39 UTC <src/main.rs:119:5> [Debug]: ---
2020-08-05 01:05:39 UTC <src/hot.rs:276:6> [Debug]: Watcher initialised, starting for path "/home/avril/work/lolicron"
2020-08-05 01:05:39 UTC <src/hot.rs:305:6> [Info]: Watcher up
Loading…
Cancel
Save