use color_eyre::{eyre::eyre, Result};
use sn_releases::ReleaseType;
use std::path::PathBuf;
#[cfg(unix)]
pub fn get_daemon_install_path() -> PathBuf {
PathBuf::from("/usr/local/bin/safenodemand")
}
#[cfg(windows)]
pub fn get_daemon_install_path() -> PathBuf {
PathBuf::from("C:\\ProgramData\\safenodemand\\safenodemand.exe")
}
#[cfg(unix)]
pub fn get_node_manager_path() -> Result<PathBuf> {
use std::os::unix::fs::PermissionsExt;
let path = if is_running_as_root() {
let path = PathBuf::from("/var/safenode-manager/");
debug!("Running as root, creating node_manager_path and setting perms if path doesn't exists: {path:?}");
std::fs::create_dir_all(&path)?;
let mut perm = std::fs::metadata(&path)?.permissions();
perm.set_mode(0o755); std::fs::set_permissions(&path, perm)?;
path
} else {
let path = get_user_safenode_data_dir()?;
debug!("Running as non-root, node_manager_path is: {path:?}");
path
};
if is_running_as_root() && !path.exists() {
std::fs::create_dir_all(&path)?;
let mut perm = std::fs::metadata(&path)?.permissions();
perm.set_mode(0o755); std::fs::set_permissions(&path, perm)?;
}
Ok(path)
}
#[cfg(windows)]
pub fn get_node_manager_path() -> Result<PathBuf> {
use std::path::Path;
let path = Path::new("C:\\ProgramData\\safenode-manager");
debug!("Running as root, creating node_manager_path at: {path:?}");
if !path.exists() {
std::fs::create_dir_all(path)?;
}
Ok(path.to_path_buf())
}
#[cfg(unix)]
pub fn get_node_registry_path() -> Result<PathBuf> {
use std::os::unix::fs::PermissionsExt;
let path = get_node_manager_path()?;
let node_registry_path = path.join("node_registry.json");
if is_running_as_root() && !node_registry_path.exists() {
debug!("Running as root and node_registry_path doesn't exist, creating node_registry_path and setting perms at: {node_registry_path:?}");
std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true) .open(node_registry_path.clone())?;
let mut perm = std::fs::metadata(node_registry_path.clone())?.permissions();
perm.set_mode(0o777);
std::fs::set_permissions(node_registry_path.clone(), perm)?;
}
debug!("Node registry path is: {node_registry_path:?}");
Ok(node_registry_path)
}
#[cfg(windows)]
pub fn get_node_registry_path() -> Result<PathBuf> {
use std::path::Path;
let path = Path::new("C:\\ProgramData\\safenode-manager");
if !path.exists() {
std::fs::create_dir_all(path)?;
}
debug!("Node registry path is: {path:?}");
Ok(path.join("node_registry.json"))
}
#[cfg(unix)]
pub fn get_service_data_dir_path(
custom_path: Option<PathBuf>,
owner: Option<String>,
) -> Result<PathBuf> {
let path = match custom_path {
Some(p) => {
debug!("Using custom path for service data dir: {p:?}");
p
}
None => {
if owner.is_some() {
let path = PathBuf::from("/var/safenode-manager/services");
debug!("Using default path for service data dir: {path:?}");
path
} else {
let path = get_user_safenode_data_dir()?;
debug!("Using user mode service data dir: {path:?}");
path
}
}
};
if let Some(owner) = owner {
create_owned_dir(path.clone(), &owner)?;
}
Ok(path)
}
#[cfg(windows)]
pub fn get_service_data_dir_path(
custom_path: Option<PathBuf>,
_owner: Option<String>,
) -> Result<PathBuf> {
let path = match custom_path {
Some(p) => {
debug!("Using custom path for service data dir: {p:?}");
p
}
None => {
let path = PathBuf::from("C:\\ProgramData\\safenode\\data");
debug!("Using default path for service data dir: {path:?}");
path
}
};
std::fs::create_dir_all(&path)?;
Ok(path)
}
#[cfg(unix)]
pub fn get_service_log_dir_path(
bin_type: ReleaseType,
custom_path: Option<PathBuf>,
owner: Option<String>,
) -> Result<PathBuf> {
let path = match custom_path {
Some(p) => {
debug!("Using custom path for service log dir: {p:?}");
p
}
None => {
if owner.is_some() {
let path = PathBuf::from("/var/log").join(bin_type.to_string());
debug!("Using default path for service log dir: {path:?}");
path
} else {
let path = get_user_safenode_data_dir()?;
debug!("Using user mode service log dir: {path:?}");
path
}
}
};
if let Some(owner) = owner {
create_owned_dir(path.clone(), &owner)?;
}
Ok(path)
}
#[cfg(windows)]
pub fn get_service_log_dir_path(
bin_type: ReleaseType,
custom_path: Option<PathBuf>,
_owner: Option<String>,
) -> Result<PathBuf> {
let path = match custom_path {
Some(p) => {
debug!("Using custom path for service log dir: {p:?}");
p
}
None => {
let path = PathBuf::from("C:\\ProgramData")
.join(bin_type.to_string())
.join("logs");
debug!("Using default path for service log dir: {path:?}");
path
}
};
std::fs::create_dir_all(&path)?;
Ok(path)
}
#[cfg(unix)]
pub fn create_owned_dir(path: PathBuf, owner: &str) -> Result<()> {
debug!("Creating owned dir and setting permissions: {path:?} with owner: {owner}");
use nix::unistd::{chown, Gid, Uid};
use std::os::unix::fs::PermissionsExt;
use users::get_user_by_name;
std::fs::create_dir_all(&path)?;
let permissions = std::fs::Permissions::from_mode(0o755);
std::fs::set_permissions(&path, permissions)?;
let user = get_user_by_name(owner).ok_or_else(|| {
error!("User '{owner}' does not exist");
eyre!("User '{owner}' does not exist")
})?;
let uid = Uid::from_raw(user.uid());
let gid = Gid::from_raw(user.primary_group_id());
chown(&path, Some(uid), Some(gid))?;
Ok(())
}
#[cfg(windows)]
pub fn create_owned_dir(path: PathBuf, _owner: &str) -> Result<()> {
debug!("Creating owned dir: {path:?}");
std::fs::create_dir_all(path)?;
Ok(())
}
#[cfg(unix)]
pub fn is_running_as_root() -> bool {
use nix::unistd::geteuid;
geteuid().is_root()
}
#[cfg(windows)]
pub fn is_running_as_root() -> bool {
std::fs::read_dir("C:\\Windows\\System32\\config").is_ok()
}
pub fn get_user_safenode_data_dir() -> Result<PathBuf> {
Ok(dirs_next::data_dir()
.ok_or_else(|| {
error!("Failed to get data_dir");
eyre!("Could not obtain user data directory")
})?
.join("safe")
.join("node"))
}