forked from brl/citadel-tools
126 lines
3.5 KiB
Rust
126 lines
3.5 KiB
Rust
use std::path::{PathBuf, Path};
|
|
use crate::{Realms, Result, util};
|
|
use std::fs;
|
|
|
|
/// Creation and removal of a Realm
|
|
pub struct RealmCreateDestroy {
|
|
name: String,
|
|
}
|
|
|
|
impl RealmCreateDestroy {
|
|
|
|
pub fn new(name: &str) -> Self {
|
|
let name = name.to_string();
|
|
RealmCreateDestroy { name }
|
|
}
|
|
|
|
fn tmpdir() -> PathBuf {
|
|
Path::new(Realms::BASE_PATH).join(".tmp")
|
|
}
|
|
|
|
pub fn temp_basepath(&self) -> PathBuf {
|
|
Self::tmpdir().join(self.dirname())
|
|
}
|
|
|
|
pub fn basepath(&self) -> PathBuf {
|
|
Path::new(Realms::BASE_PATH)
|
|
.join(self.dirname())
|
|
}
|
|
|
|
fn dirname(&self) -> String {
|
|
format!("realm-{}", self.name)
|
|
}
|
|
|
|
/// Create a new realm with the name `self.name`
|
|
pub fn create(&self) -> Result<()> {
|
|
if self.basepath().exists() {
|
|
bail!("realm directory {} already exists", self.basepath().display());
|
|
}
|
|
|
|
if let Err(e) = self.create_realm_directory() {
|
|
let tmpdir = self.temp_basepath();
|
|
if tmpdir.exists() {
|
|
let _ = fs::remove_dir_all(tmpdir);
|
|
}
|
|
return Err(e);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn create_realm_directory(&self) -> Result<()> {
|
|
self.create_home()?;
|
|
self.move_from_temp()
|
|
}
|
|
|
|
fn create_home(&self) -> Result<()> {
|
|
let home = self.temp_basepath().join("home");
|
|
|
|
util::create_dir(&home)?;
|
|
util::chown(&home, 1000, 1000)?;
|
|
|
|
let skel = Path::new(Realms::BASE_PATH).join("skel");
|
|
|
|
if skel.exists() {
|
|
info!("Populating realm home directory with files from {}", skel.display());
|
|
util::copy_tree(&skel, &home)
|
|
.map_err(context!("failed to copy tree of files from {:?} to {:?}", skel, home))?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn move_from_temp(&self) -> Result<()> {
|
|
let from = self.temp_basepath();
|
|
let to = self.basepath();
|
|
if to.exists() {
|
|
bail!("Cannot move temporary directory {} to {} because the target already exists", from.display(), to.display());
|
|
}
|
|
util::rename(&from, &to)
|
|
}
|
|
|
|
fn move_to_temp(&self) -> Result<()> {
|
|
let from = self.basepath();
|
|
let to = self.temp_basepath();
|
|
if to.exists() {
|
|
bail!("Cannot move realm directory {} to {} because the target already exists", from.display(), to.display());
|
|
}
|
|
|
|
let tmpdir = Self::tmpdir();
|
|
util::create_dir(&tmpdir)?;
|
|
util::rename(&from, &to)
|
|
}
|
|
|
|
pub fn delete_realm(&self, save_home: bool) -> Result<()> {
|
|
|
|
self.move_to_temp()?;
|
|
if save_home {
|
|
self.save_home_for_delete()?;
|
|
}
|
|
|
|
let realmdir = self.temp_basepath();
|
|
info!("removing realm directory {:?}", realmdir);
|
|
fs::remove_dir_all(&realmdir)
|
|
.map_err(context!("error removing realm directory {:?}", realmdir))
|
|
}
|
|
|
|
fn save_home_for_delete(&self) -> Result<()> {
|
|
util::create_dir("/realms/removed")?;
|
|
|
|
let target = self.home_save_directory();
|
|
let home = self.temp_basepath().join("home");
|
|
|
|
util::rename(&home, &target)?;
|
|
info!("home directory been moved to {}, delete it at your leisure", target.display());
|
|
Ok(())
|
|
}
|
|
|
|
fn home_save_directory(&self) -> PathBuf {
|
|
let mut n = 1;
|
|
let mut save_dir= PathBuf::from(&format!("/realms/removed/home-{}", self.name));
|
|
while save_dir.exists() {
|
|
save_dir.set_extension(n.to_string());
|
|
n += 1;
|
|
}
|
|
save_dir
|
|
}
|
|
|
|
} |