1
0
forked from brl/citadel-tools

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