SHA256
Saving more work.
This commit is contained in:
Generated
+144
@@ -61,12 +61,27 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-polyfill"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.13.1"
|
version = "2.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -119,12 +134,39 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cobs"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "critical-section"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embedded-io"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embedded-io"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -141,12 +183,35 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.7.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-polyfill",
|
||||||
|
"hash32",
|
||||||
|
"rustc_version",
|
||||||
|
"serde",
|
||||||
|
"spin",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -159,6 +224,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"nix",
|
"nix",
|
||||||
|
"postcard",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -195,6 +261,15 @@ version = "0.2.189"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.3"
|
version = "2.8.3"
|
||||||
@@ -219,6 +294,19 @@ version = "1.70.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "postcard"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
|
||||||
|
dependencies = [
|
||||||
|
"cobs",
|
||||||
|
"embedded-io 0.4.0",
|
||||||
|
"embedded-io 0.6.1",
|
||||||
|
"heapless",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.107"
|
version = "1.0.107"
|
||||||
@@ -266,6 +354,27 @@ version = "0.8.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.229"
|
version = "1.0.229"
|
||||||
@@ -338,6 +447,21 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@@ -355,6 +479,26 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-format"
|
name = "time-format"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
|
|||||||
+3
-2
@@ -6,9 +6,10 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.6", features = ["derive"] }
|
clap = { version = "4.6", features = ["derive"] }
|
||||||
nix = { version = "0", features = ["user"] }
|
nix = { version = "0", features = ["user"] }
|
||||||
|
postcard = { version = "1.1", features = ["use-std"] }
|
||||||
regex = "1"
|
regex = "1"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1.0.151"
|
serde_json = "1.0"
|
||||||
signal-hook = "0.4"
|
signal-hook = "0.4"
|
||||||
time-format = "1.2"
|
time-format = "1.2"
|
||||||
toml = "1.1.4"
|
toml = "1.1"
|
||||||
|
|||||||
+131
-34
@@ -18,22 +18,23 @@
|
|||||||
hive-up daemon logic
|
hive-up daemon logic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::fs;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
use time_format;
|
use std::os::unix::net::UnixDatagram;
|
||||||
|
|
||||||
use crate::hive_config::HiveConfig;
|
use crate::hive_config::HiveConfig;
|
||||||
use crate::hive_db;
|
use crate::hive_db::{self, HiveDb};
|
||||||
|
use crate::hive_config;
|
||||||
use crate::hive_system;
|
use crate::hive_system;
|
||||||
|
use crate::hive_intercom::{self, IntercomError, BzzReq, BzzResp};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DaemonError {
|
pub enum DaemonError {
|
||||||
IoError(std::io::Error),
|
IoError(std::io::Error),
|
||||||
DBError(hive_db::DBError),
|
DBError(hive_db::DBError),
|
||||||
|
ConfigError(hive_config::ConfigError),
|
||||||
ExecCommandError(hive_system::ExecCommandError),
|
ExecCommandError(hive_system::ExecCommandError),
|
||||||
TimestampError,
|
TimestampError,
|
||||||
}
|
}
|
||||||
@@ -51,6 +52,13 @@ impl From<hive_db::DBError> for DaemonError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<hive_config::ConfigError> for DaemonError {
|
||||||
|
fn from(err: hive_config::ConfigError) -> Self {
|
||||||
|
DaemonError::ConfigError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl From<hive_system::ExecCommandError> for DaemonError {
|
impl From<hive_system::ExecCommandError> for DaemonError {
|
||||||
fn from(err: hive_system::ExecCommandError) -> Self {
|
fn from(err: hive_system::ExecCommandError) -> Self {
|
||||||
DaemonError::ExecCommandError(err)
|
DaemonError::ExecCommandError(err)
|
||||||
@@ -61,12 +69,9 @@ impl std::fmt::Display for DaemonError {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
DaemonError::IoError(e) => write!(f, "IO Error: {}", e),
|
DaemonError::IoError(e) => write!(f, "IO Error: {}", e),
|
||||||
DaemonError::DBError(e) => {
|
DaemonError::DBError(e) => write!(f, "Database error: {}", e),
|
||||||
write!(f, "Database error: {}", e)
|
DaemonError::ConfigError(e) => write!(f, "Config Error: {}", e),
|
||||||
},
|
DaemonError::ExecCommandError(e) => write!(f, "Exec Command Error: {}", e),
|
||||||
DaemonError::ExecCommandError(e) => {
|
|
||||||
write!(f, "Exec Command Error: {}", e)
|
|
||||||
},
|
|
||||||
DaemonError::TimestampError => write!(f, "Timestamp Error"),
|
DaemonError::TimestampError => write!(f, "Timestamp Error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,41 +87,133 @@ fn get_timestamp_sec() -> u64 {
|
|||||||
.as_secs()
|
.as_secs()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// bloking function. Bloaks for configured socker recv timeout
|
||||||
|
fn process_remoute(bzz_db: &mut HiveDb, listening_socket: &UnixDatagram, recv_buf: &mut [u8]) -> Result<(), DaemonError> {
|
||||||
|
// waiting on socket recv_from untill timeout (also using this as a timer)
|
||||||
|
match hive_intercom::socket_recv(&listening_socket, recv_buf) {
|
||||||
|
// we get some request to process
|
||||||
|
Ok((bzz_req, client_addr)) => {
|
||||||
|
match bzz_req {
|
||||||
|
// return awailable updates number
|
||||||
|
BzzReq::UpdatesAvailable => {
|
||||||
|
let resp = BzzResp::UpdatesAvailable(bzz_db.updates_available);
|
||||||
|
if let Err(ex) = hive_intercom::socket_send(&listening_socket,&client_addr, resp) {
|
||||||
|
println!("Error while ansvering cli request: {}", ex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// we should apply updates if any on reboot
|
||||||
|
BzzReq::ScheduleUpdate => {
|
||||||
|
// but only if we have actually any updates
|
||||||
|
if bzz_db.updates_available > 0 {
|
||||||
|
bzz_db.update_on_reboot = true;
|
||||||
|
// keep it simple Kira
|
||||||
|
// lets just return err from the loop if something wrong with db
|
||||||
|
hive_db::write_db(&bzz_db)?;
|
||||||
|
// signal remoute that evertyhing go OK
|
||||||
|
if let Err(ex) = hive_intercom::socket_send(&listening_socket,&client_addr, BzzResp::Finish) {
|
||||||
|
println!("Error while ansvering cli request: {}", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
// if time out - do nothing
|
||||||
|
Err(IntercomError::Timeout) => {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
// if some actual IO error then return it
|
||||||
|
Err(IntercomError::IoError(ex)) => Err(ex.into()),
|
||||||
|
// if other kinds of errors - log and continue
|
||||||
|
Err(ex) => {
|
||||||
|
println!("Got error while listenin to unix socket: {}", ex);
|
||||||
|
print!("Sleeping for 1 secong and continue...");
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// doing what daemons usually beezz
|
||||||
|
fn do_local_work(config: &HiveConfig, bzz_db: &mut HiveDb)-> Result<(), DaemonError> {
|
||||||
|
// if updates check is turned on
|
||||||
|
if config.update.updates_check_interval != 0 {
|
||||||
|
let timestamp = get_timestamp_sec();
|
||||||
|
|
||||||
|
// calculate how many hours passed sinse last update
|
||||||
|
let hours_since_update_check = timestamp
|
||||||
|
.checked_sub(bzz_db.update_check_timestamp)
|
||||||
|
.ok_or(DaemonError::TimestampError)?
|
||||||
|
/ 3600;
|
||||||
|
|
||||||
|
// if more than updates_check_interval specifiyed in config - check for updates
|
||||||
|
if hours_since_update_check > config.update.updates_check_interval {
|
||||||
|
// perform update check
|
||||||
|
println!("Cheking for updates...");
|
||||||
|
// now that may fail because of bad internet and idealy we
|
||||||
|
// want to just log error and retry in other time
|
||||||
|
bzz_db.updates_available = match hive_system::check_updates() {
|
||||||
|
Ok(updates_num) => updates_num,
|
||||||
|
Err(ex) => {
|
||||||
|
println!("Error while shecking for updates: {}", ex);
|
||||||
|
0u32
|
||||||
|
}
|
||||||
|
};
|
||||||
|
hive_db::write_db(&bzz_db)?;
|
||||||
|
println!("Found {} packages that needs to be updated.", bzz_db.updates_available);
|
||||||
|
|
||||||
|
// if auto download for updates is enabled and there is some updates - download them
|
||||||
|
if config.update.download_updates && bzz_db.updates_available != 0 {
|
||||||
|
println!("Downloadin updates...");
|
||||||
|
match hive_system::download_updates() {
|
||||||
|
Ok(()) => {println!("Updates downloaded...");},
|
||||||
|
Err(ex) => {println!("Error downloading updates: {}", ex);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// updating las tcheck for updates timestamp in db
|
||||||
|
bzz_db.update_check_timestamp = get_timestamp_sec();
|
||||||
|
hive_db::write_db(&bzz_db)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(
|
||||||
config: HiveConfig,
|
mut bzz_config: HiveConfig,
|
||||||
term_flag: Arc<AtomicBool>,
|
term_flag: Arc<AtomicBool>,
|
||||||
reload_flag: Arc<AtomicBool>,
|
reload_flag: Arc<AtomicBool>,
|
||||||
) -> Result<(), DaemonError> {
|
) -> Result<(), DaemonError> {
|
||||||
let duration = SystemTime::now()
|
|
||||||
.duration_since(UNIX_EPOCH)
|
|
||||||
.expect("Time went backwards");
|
|
||||||
|
|
||||||
|
// reading db from disk
|
||||||
let mut bzz_db = hive_db::read_db()?;
|
let mut bzz_db = hive_db::read_db()?;
|
||||||
|
|
||||||
//duration.as_secs()
|
// stop flag
|
||||||
let keep_going = true;
|
let mut keep_going = true;
|
||||||
|
|
||||||
//last_check.
|
// init udp unix socket for communication with cli and such
|
||||||
|
let listening_socket = hive_intercom::socket_bind(1)?;
|
||||||
|
let mut recv_buf: Vec<u8> = Vec::with_capacity(1024);
|
||||||
|
|
||||||
|
// main loop (I love loops) (No please just do recursion properly)
|
||||||
while keep_going {
|
while keep_going {
|
||||||
thread::sleep(Duration::from_secs(1));
|
process_remoute(&mut bzz_db, &listening_socket, recv_buf.as_mut_slice())?;
|
||||||
|
do_local_work(&bzz_config, &mut bzz_db)?;
|
||||||
|
// check termination flags
|
||||||
|
if term_flag.load(Ordering::Relaxed) {
|
||||||
|
println!("SIGTERM recieved - wrapping things up.");
|
||||||
|
keep_going = false;
|
||||||
|
}
|
||||||
|
|
||||||
// if updates check is turned on
|
// checking reload signal flag
|
||||||
if config.update.updates_check_interval != 0 {
|
if reload_flag.load(Ordering::Relaxed) {
|
||||||
let timestamp = get_timestamp_sec();
|
println!("SIGHUP recieved - reloading config and DB.");
|
||||||
let hours_since_update_check = timestamp
|
bzz_config = hive_config::read_config()?;
|
||||||
.checked_sub(bzz_db.last_update_check)
|
bzz_db = hive_db::read_db()?;
|
||||||
.ok_or(DaemonError::TimestampError)?
|
println!("Reloaded!");
|
||||||
/ 3600;
|
|
||||||
|
|
||||||
if hours_since_update_check > config.update.updates_check_interval {
|
|
||||||
// perform update check
|
|
||||||
let packages_num = hive_system::check_updates()?;
|
|
||||||
// updating las tupdate timestamp in db
|
|
||||||
bzz_db.last_update_check = get_timestamp_sec();
|
|
||||||
hive_db::write_db(&bzz_db)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("Exiting...");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -23,6 +23,8 @@ use serde::{Serialize, Deserialize};
|
|||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
use toml;
|
use toml;
|
||||||
|
|
||||||
|
const CONFIG_PATH: &str = "/etc/hive_up.toml";
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct HiveConfig {
|
pub struct HiveConfig {
|
||||||
// Matches [kernel] in TOML
|
// Matches [kernel] in TOML
|
||||||
@@ -91,18 +93,18 @@ impl std::fmt::Display for ConfigError {
|
|||||||
// Implement std::error::Error
|
// Implement std::error::Error
|
||||||
impl std::error::Error for ConfigError {}
|
impl std::error::Error for ConfigError {}
|
||||||
|
|
||||||
pub fn read_config(conf_file: &str) -> Result<HiveConfig, ConfigError> {
|
pub fn read_config() -> Result<HiveConfig, ConfigError> {
|
||||||
let file_content = fs::read_to_string(conf_file)?;
|
let file_content = fs::read_to_string(CONFIG_PATH)?;
|
||||||
let config:HiveConfig = toml::from_str(&file_content)?;
|
let config:HiveConfig = toml::from_str(&file_content)?;
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn change_updates_check_interval(conf_file: &str, new_interval: u64) -> Result<HiveConfig, ConfigError> {
|
pub fn change_updates_check_interval(new_interval: u64) -> Result<HiveConfig, ConfigError> {
|
||||||
let mut config: HiveConfig = read_config(conf_file)?;
|
let mut config: HiveConfig = read_config()?;
|
||||||
config.update.updates_check_interval = new_interval;
|
config.update.updates_check_interval = new_interval;
|
||||||
let conf_str = toml::to_string_pretty(&config)?;
|
let conf_str = toml::to_string_pretty(&config)?;
|
||||||
fs::write(conf_file, conf_str)?;
|
fs::write(CONFIG_PATH, conf_str)?;
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
|
|
||||||
|
|||||||
+16
-9
@@ -58,9 +58,16 @@ impl std::error::Error for DBError {}
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct HiveDb {
|
pub struct HiveDb {
|
||||||
pub last_update_check: u64,
|
/// Timestamp of last check for updates in seconds from UNIX_EPOCH
|
||||||
pub update_sucess_status: bool,
|
pub update_check_timestamp: u64,
|
||||||
pub last_update_timestamp: String,
|
/// non zero if there is updates that can bee applied, showing numbers of packages that can be updated
|
||||||
|
pub updates_available: u32,
|
||||||
|
/// true if last update fas successful
|
||||||
|
pub update_status: bool,
|
||||||
|
/// datetime of last snapshot in format "%Y-%m-%dT%H:%M:%S"
|
||||||
|
pub last_snapshot_time: String,
|
||||||
|
/// set to true if we want to apply available updates on reboot
|
||||||
|
pub update_on_reboot: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_db() -> Result<HiveDb, DBError> {
|
pub fn read_db() -> Result<HiveDb, DBError> {
|
||||||
@@ -81,8 +88,8 @@ pub fn write_db(db: &HiveDb) -> Result<(), DBError> {
|
|||||||
///
|
///
|
||||||
pub fn update_last_check_update_time(new_timestamp: u64) -> Result<u64, DBError> {
|
pub fn update_last_check_update_time(new_timestamp: u64) -> Result<u64, DBError> {
|
||||||
let mut db = read_db()?;
|
let mut db = read_db()?;
|
||||||
let old_value = db.last_update_check;
|
let old_value = db.update_check_timestamp;
|
||||||
db.last_update_check = new_timestamp;
|
db.update_check_timestamp = new_timestamp;
|
||||||
write_db(&db)?;
|
write_db(&db)?;
|
||||||
Ok(old_value)
|
Ok(old_value)
|
||||||
}
|
}
|
||||||
@@ -93,8 +100,8 @@ pub fn update_last_check_update_time(new_timestamp: u64) -> Result<u64, DBError>
|
|||||||
///
|
///
|
||||||
pub fn update_update_status(sucess_status: bool) -> Result<bool, DBError> {
|
pub fn update_update_status(sucess_status: bool) -> Result<bool, DBError> {
|
||||||
let mut db = read_db()?;
|
let mut db = read_db()?;
|
||||||
let old_value = db.update_sucess_status;
|
let old_value = db.update_status;
|
||||||
db.update_sucess_status = sucess_status;
|
db.update_status = sucess_status;
|
||||||
write_db(&db)?;
|
write_db(&db)?;
|
||||||
Ok(old_value)
|
Ok(old_value)
|
||||||
}
|
}
|
||||||
@@ -105,8 +112,8 @@ pub fn update_update_status(sucess_status: bool) -> Result<bool, DBError> {
|
|||||||
///
|
///
|
||||||
pub fn update_last_update_timestamp(new_timestamp: String) -> Result<String, DBError> {
|
pub fn update_last_update_timestamp(new_timestamp: String) -> Result<String, DBError> {
|
||||||
let mut db = read_db()?;
|
let mut db = read_db()?;
|
||||||
let old_value = db.last_update_timestamp;
|
let old_value = db.last_snapshot_time;
|
||||||
db.last_update_timestamp = new_timestamp;
|
db.last_snapshot_time = new_timestamp;
|
||||||
write_db(&db)?;
|
write_db(&db)?;
|
||||||
Ok(old_value)
|
Ok(old_value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
// <hive-up - update program fot Kira Linux.>
|
||||||
|
// Copyright (C) <2026> <Kira Foundation>
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/*
|
||||||
|
hive-up unix socket communication
|
||||||
|
*/
|
||||||
|
|
||||||
|
use postcard;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fs;
|
||||||
|
use std::os::unix::net::{SocketAddr, UnixDatagram};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub const SOCKET_DIR: &str = "/run/hive-up";
|
||||||
|
pub const SOCKET_PATH: &str = "/run/hive-up/hive-intercom.soc";
|
||||||
|
pub const CLINET_READ_TIMEOUT: u64 = 5;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum IntercomError {
|
||||||
|
IoError(std::io::Error),
|
||||||
|
PostcardError(postcard::Error),
|
||||||
|
ConnectionClosed,
|
||||||
|
Timeout,
|
||||||
|
UnexpectedResponse,
|
||||||
|
ServerError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapping IO errors but separating time out error
|
||||||
|
impl From<std::io::Error> for IntercomError {
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
if err.kind() == std::io::ErrorKind::TimedOut
|
||||||
|
|| err.kind() == std::io::ErrorKind::WouldBlock
|
||||||
|
{
|
||||||
|
IntercomError::Timeout
|
||||||
|
} else {
|
||||||
|
IntercomError::IoError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<postcard::Error> for IntercomError {
|
||||||
|
fn from(err: postcard::Error) -> Self {
|
||||||
|
IntercomError::PostcardError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for IntercomError {
|
||||||
|
fn from(err: String) -> Self {
|
||||||
|
IntercomError::ServerError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for IntercomError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
IntercomError::IoError(e) => write!(f, "IO Error: {}", e),
|
||||||
|
IntercomError::PostcardError(e) => {
|
||||||
|
write!(f, "Data parsing (postcard) error: {}", e)
|
||||||
|
}
|
||||||
|
IntercomError::Timeout => write!(f, "Operation Timeout"),
|
||||||
|
IntercomError::ConnectionClosed => write!(f, "Connection closed"),
|
||||||
|
IntercomError::UnexpectedResponse => write!(f, "Unexpected response"),
|
||||||
|
IntercomError::ServerError(err) => write!(f, "Server side error: {}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement std::error::Error
|
||||||
|
impl std::error::Error for IntercomError {}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum BzzResp {
|
||||||
|
Working,
|
||||||
|
Finish,
|
||||||
|
UpdatesAvailable(u32),
|
||||||
|
Error(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum BzzReq {
|
||||||
|
UpdatesAvailable,
|
||||||
|
ScheduleUpdate,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn socket_bind(read_timeout_sec: u64) -> Result<UnixDatagram, std::io::Error> {
|
||||||
|
// create socket directory if it is does not exist
|
||||||
|
if let Ok(path_exist) = fs::exists(SOCKET_DIR)
|
||||||
|
&& path_exist == false
|
||||||
|
{
|
||||||
|
fs::create_dir(SOCKET_DIR)?;
|
||||||
|
}
|
||||||
|
// remove socket file if any present
|
||||||
|
let _ = fs::remove_file(SOCKET_PATH);
|
||||||
|
|
||||||
|
// bind datagram unix socket
|
||||||
|
let socket = UnixDatagram::bind(SOCKET_PATH)?;
|
||||||
|
socket.set_read_timeout(Some(Duration::from_secs(read_timeout_sec)))?;
|
||||||
|
Ok(socket)
|
||||||
|
}
|
||||||
|
|
||||||
|
// for daemon side
|
||||||
|
pub fn socket_send(socket: &UnixDatagram, client_addr: &SocketAddr, resp: BzzResp) -> Result<(), IntercomError> {
|
||||||
|
let resp_buff = postcard::to_stdvec(&resp)?;
|
||||||
|
socket.send_to_addr(resp_buff.as_slice(), client_addr)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// for daemon side
|
||||||
|
pub fn socket_recv(
|
||||||
|
socket: &UnixDatagram,
|
||||||
|
recv_buf: &mut [u8],
|
||||||
|
) -> Result<(BzzReq, SocketAddr), IntercomError> {
|
||||||
|
match socket.recv_from(recv_buf) {
|
||||||
|
Ok((rec_count, client_addr)) => {
|
||||||
|
if rec_count != 0 {
|
||||||
|
println!("DEBUG: Total bytes recieved {}", rec_count);
|
||||||
|
let decoded_req: BzzReq = postcard::from_bytes(&recv_buf)?;
|
||||||
|
Ok((decoded_req, client_addr))
|
||||||
|
} else {
|
||||||
|
Err(IntercomError::ConnectionClosed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ex) => Err(ex.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_and_recv(request: BzzReq) -> Result<BzzResp, IntercomError> {
|
||||||
|
let socket = UnixDatagram::unbound()?;
|
||||||
|
socket.connect(SOCKET_PATH)?;
|
||||||
|
socket.set_read_timeout(Some(Duration::from_secs(CLINET_READ_TIMEOUT)))?;
|
||||||
|
|
||||||
|
let encoded_buf = postcard::to_stdvec(&request)?;
|
||||||
|
|
||||||
|
socket.send(encoded_buf.as_slice())?;
|
||||||
|
|
||||||
|
let mut recv_buf: Vec<u8> = Vec::with_capacity(1024);
|
||||||
|
match socket.recv(recv_buf.as_mut_slice()) {
|
||||||
|
Ok(rec_count) => {
|
||||||
|
if rec_count != 0 {
|
||||||
|
println!("DEBUG: Total bytes recieved {}", rec_count);
|
||||||
|
let decoded_resp: BzzResp = postcard::from_bytes(&recv_buf)?;
|
||||||
|
Ok(decoded_resp)
|
||||||
|
} else {
|
||||||
|
Err(IntercomError::ConnectionClosed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn updates_available() -> Result<u32, IntercomError> {
|
||||||
|
let resp = send_and_recv(BzzReq::UpdatesAvailable)?;
|
||||||
|
match resp {
|
||||||
|
BzzResp::UpdatesAvailable(updates_count) => Ok(updates_count),
|
||||||
|
BzzResp::Error(ex) => Err(IntercomError::ServerError(ex)),
|
||||||
|
_ => Err(IntercomError::UnexpectedResponse),
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-3
@@ -134,11 +134,13 @@ pub fn exec_command_out(cmd: &str, args: &Vec<&str>) -> Result<String, ExecComma
|
|||||||
/// pacman -Sy
|
/// pacman -Sy
|
||||||
/// pacman -Qu
|
/// pacman -Qu
|
||||||
/// returns number of updatable packages, returns 0 if there is no updates awailable
|
/// returns number of updatable packages, returns 0 if there is no updates awailable
|
||||||
pub fn check_updates() -> Result<usize, ExecCommandError> {
|
pub fn check_updates() -> Result<u32, ExecCommandError> {
|
||||||
|
// Synchronize pacman DB
|
||||||
exec_command("pacman", &vec!["-Sy"])?;
|
exec_command("pacman", &vec!["-Sy"])?;
|
||||||
|
// Check for updates
|
||||||
let out = Command::new("pacman").arg("-Qu").output()?;
|
let out = Command::new("pacman").arg("-Qu").output()?;
|
||||||
if out.status.success() {
|
if out.status.success() {
|
||||||
Ok(String::from_utf8(out.stdout)?.lines().count())
|
Ok(String::from_utf8(out.stdout)?.lines().count().try_into().unwrap())
|
||||||
} else {
|
} else {
|
||||||
if let Some(code) = out.status.code() && code == 1 { Ok(0) }
|
if let Some(code) = out.status.code() && code == 1 { Ok(0) }
|
||||||
else {
|
else {
|
||||||
@@ -149,7 +151,7 @@ pub fn check_updates() -> Result<usize, ExecCommandError> {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// sudo pacman -Suw --noconfirm --noprogressbar
|
/// sudo pacman -Suw --noconfirm --noprogressbar
|
||||||
/// Dopwnload updates (need to check for updates first)
|
/// Download updates (need to check for updates first)
|
||||||
///
|
///
|
||||||
pub fn download_updates() -> Result<(), ExecCommandError> {
|
pub fn download_updates() -> Result<(), ExecCommandError> {
|
||||||
exec_command("pacman", &vec!["-Suw", "--noconfirm", "--noprogressbar"])
|
exec_command("pacman", &vec!["-Suw", "--noconfirm", "--noprogressbar"])
|
||||||
|
|||||||
+16
-22
@@ -16,9 +16,9 @@
|
|||||||
|
|
||||||
use clap::{Args, Parser};
|
use clap::{Args, Parser};
|
||||||
use signal_hook::{consts::SIGINT, iterator::Signals};
|
use signal_hook::{consts::SIGINT, iterator::Signals};
|
||||||
use std::{error::Error, thread, time::Duration};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::{error::Error, thread, time::Duration};
|
||||||
|
|
||||||
mod hive_system;
|
mod hive_system;
|
||||||
use hive_system::ExecCommandError;
|
use hive_system::ExecCommandError;
|
||||||
@@ -26,11 +26,9 @@ use hive_system::ExecCommandError;
|
|||||||
mod hive_config;
|
mod hive_config;
|
||||||
use hive_config::{HiveConfig, KernelConfig};
|
use hive_config::{HiveConfig, KernelConfig};
|
||||||
|
|
||||||
mod hive_db;
|
|
||||||
|
|
||||||
mod daemon;
|
mod daemon;
|
||||||
|
mod hive_db;
|
||||||
const CONFIG_PATH_STR: &str = "/etc/hive_up.toml";
|
mod hive_intercom;
|
||||||
|
|
||||||
// Define the mutually exclusive group
|
// Define the mutually exclusive group
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
@@ -62,7 +60,7 @@ struct Cli {
|
|||||||
mode: HiveUpMode,
|
mode: HiveUpMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), String> {
|
||||||
// registering signals handling
|
// registering signals handling
|
||||||
let term_flag: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
let term_flag: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
||||||
let reload_flag = Arc::new(AtomicBool::new(false));
|
let reload_flag = Arc::new(AtomicBool::new(false));
|
||||||
@@ -73,18 +71,15 @@ fn main() {
|
|||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
|
|
||||||
if !hive_system::check_if_run_as_root() {
|
if !hive_system::check_if_run_as_root() {
|
||||||
eprintln!("Error: This program requires root privileges.");
|
return Err("Error: This program requires root privileges.".to_string());
|
||||||
std::process::exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read config
|
// read config
|
||||||
let hive_config = match hive_config::read_config(CONFIG_PATH_STR) {
|
let bzz_config = match hive_config::read_config() {
|
||||||
Ok(conf) => conf,
|
Ok(conf) => conf,
|
||||||
Err(ex) => {
|
Err(ex) => {
|
||||||
println!("Error reading \"{}\" hive-up config file: {}", CONFIG_PATH_STR, ex);
|
return Err(format!("Error reading hive-up config file: {}", ex));
|
||||||
std::process::exit(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Logic to check which one was set
|
// Logic to check which one was set
|
||||||
@@ -99,17 +94,16 @@ fn main() {
|
|||||||
} else if args.mode.update {
|
} else if args.mode.update {
|
||||||
println!("update mode");
|
println!("update mode");
|
||||||
} else if args.mode.daemon {
|
} else if args.mode.daemon {
|
||||||
let snaps = hive_system::list_bzzpss_snaps().unwrap();
|
if let Err(ex) = daemon::run(bzz_config, term_flag.clone(), reload_flag.clone()) {
|
||||||
println!("Snaps num: {}", snaps.len());
|
return Err(format!("Hive-Up daemon error: {}", ex));
|
||||||
for sn in snaps {
|
|
||||||
println!("Snap: {}", sn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let snaps = hive_system::list_bzzpss_snaps().unwrap();
|
||||||
|
// println!("Snaps num: {}", snaps.len());
|
||||||
|
// for sn in snaps {
|
||||||
|
// println!("Snap: {}", sn);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
while !term_flag.load(Ordering::Relaxed) {
|
Ok(())
|
||||||
// Do some time-limited stuff here
|
|
||||||
// (if this could block forever, then there's no guarantee the signal will have any
|
|
||||||
// effect).
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user