You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.2 KiB
Rust
84 lines
2.2 KiB
Rust
use anyhow::Context;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::ffi::CString;
|
|
use std::fs;
|
|
use std::fs::Permissions;
|
|
use std::os::unix::fs::MetadataExt;
|
|
use std::os::unix::fs::PermissionsExt;
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct GlobalConfig {
|
|
pub vore: GlobalVoreConfig,
|
|
pub qemu: GlobalQemuConfig,
|
|
pub uefi: HashMap<String, GlobalUefiConfig>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(rename_all(deserialize = "kebab-case"))]
|
|
pub struct GlobalVoreConfig {
|
|
#[serde(default)]
|
|
pub group: Option<String>,
|
|
#[serde(default)]
|
|
pub unix_group_id: Option<libc::gid_t>,
|
|
}
|
|
|
|
impl GlobalVoreConfig {
|
|
pub fn get_gid(&mut self) -> Result<Option<u32>, anyhow::Error> {
|
|
if let Some(id) = self.unix_group_id {
|
|
return Ok(Some(id));
|
|
}
|
|
|
|
let name = self.group.as_ref().cloned();
|
|
|
|
name.map(|group_name| {
|
|
let group_name_c = CString::new(group_name.as_str())?;
|
|
Ok(unsafe {
|
|
let group = libc::getgrnam(group_name_c.as_ptr());
|
|
if group.is_null() {
|
|
anyhow::bail!("No group found with the name '{}'", group_name);
|
|
}
|
|
|
|
let gid = (*group).gr_gid;
|
|
|
|
self.unix_group_id = Some(gid);
|
|
|
|
gid
|
|
})
|
|
})
|
|
.transpose()
|
|
}
|
|
|
|
pub fn chown(&mut self, path: &str) -> Result<(), anyhow::Error> {
|
|
if let Some(gid) = self.get_gid()? {
|
|
let meta = fs::metadata(path)?;
|
|
let path_c = CString::new(path)?;
|
|
unsafe {
|
|
libc::chown(path_c.as_ptr(), meta.uid(), gid);
|
|
}
|
|
|
|
fs::set_permissions(path, Permissions::from_mode(0o774))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct GlobalQemuConfig {
|
|
pub script: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[serde(rename_all(deserialize = "kebab-case"))]
|
|
pub struct GlobalUefiConfig {
|
|
pub template: String,
|
|
pub boot_code: String,
|
|
}
|
|
|
|
impl GlobalConfig {
|
|
pub fn load(toml: &str) -> Result<GlobalConfig, anyhow::Error> {
|
|
toml::from_str(toml).context("Failed to parse toml for global config")
|
|
}
|
|
}
|