192 lines
5.3 KiB
Rust
192 lines
5.3 KiB
Rust
|
use crate::config::WorldConfig;
|
||
|
use crate::region::Region;
|
||
|
use flate2::write::GzEncoder;
|
||
|
use flate2::Compression;
|
||
|
use std::convert::TryFrom;
|
||
|
use std::fs::{copy, create_dir, File};
|
||
|
use std::path::PathBuf;
|
||
|
|
||
|
/// Backup a file
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `file_name` - file name
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
pub fn backup_file(
|
||
|
file_name: &str,
|
||
|
mut world_path: PathBuf,
|
||
|
mut backup_path: PathBuf,
|
||
|
) -> Result<u64, std::io::Error> {
|
||
|
world_path.push(file_name);
|
||
|
backup_path.push(file_name);
|
||
|
|
||
|
copy(world_path, backup_path)
|
||
|
}
|
||
|
|
||
|
/// Backup a directory
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `dir_name` - directory name
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
pub fn backup_dir(
|
||
|
dir_name: &str,
|
||
|
world_path: &PathBuf,
|
||
|
backup_path: &PathBuf,
|
||
|
) -> Result<u64, std::io::Error> {
|
||
|
let mut src_dir = world_path.clone();
|
||
|
src_dir.push(dir_name);
|
||
|
let mut backup_dir = backup_path.clone();
|
||
|
backup_dir.push(dir_name);
|
||
|
create_dir(&backup_dir)?;
|
||
|
|
||
|
let mut file_count = 0;
|
||
|
for entry in src_dir.read_dir()? {
|
||
|
let entry = entry?;
|
||
|
let mut target = backup_dir.clone();
|
||
|
target.push(entry.file_name());
|
||
|
|
||
|
copy(entry.path(), target)?;
|
||
|
file_count += 1;
|
||
|
}
|
||
|
|
||
|
Ok(file_count)
|
||
|
}
|
||
|
|
||
|
/// Backup the regions
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `dir_name` - name of the backup folder
|
||
|
/// * `save_radius` - block radius to save
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
pub fn backup_region(
|
||
|
dir_name: &str,
|
||
|
save_radius: u64,
|
||
|
world_path: &PathBuf,
|
||
|
backup_path: &PathBuf,
|
||
|
) -> Result<u64, std::io::Error> {
|
||
|
let mut count: u64 = 0;
|
||
|
let mut src_dir = world_path.clone();
|
||
|
src_dir.push(dir_name);
|
||
|
let mut backup_dir = backup_path.clone();
|
||
|
backup_dir.push(dir_name);
|
||
|
create_dir(&backup_dir)?;
|
||
|
|
||
|
let save_radius = (save_radius as f64 / 512.0).ceil() as i64;
|
||
|
|
||
|
for entry in src_dir.read_dir()? {
|
||
|
let entry = entry?;
|
||
|
let file_name = entry.file_name().to_str().unwrap().to_string();
|
||
|
|
||
|
if let Ok(region) = Region::try_from(file_name) {
|
||
|
if region.x.abs() <= save_radius && region.y.abs() <= save_radius {
|
||
|
let mut target = backup_dir.clone();
|
||
|
target.push(entry.file_name());
|
||
|
|
||
|
copy(entry.path(), target)?;
|
||
|
count += 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Ok(count)
|
||
|
}
|
||
|
|
||
|
/// Backup a world
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
/// * `world_config` - world config options
|
||
|
pub fn backup_world(
|
||
|
world_path: PathBuf,
|
||
|
mut backup_path: PathBuf,
|
||
|
world_config: &WorldConfig,
|
||
|
) -> Result<u64, std::io::Error> {
|
||
|
let region_count;
|
||
|
backup_path.push(&world_config.world_name);
|
||
|
create_dir(backup_path.as_path())?;
|
||
|
|
||
|
backup_region("poi", world_config.save_radius, &world_path, &backup_path)?;
|
||
|
region_count = backup_region(
|
||
|
"region",
|
||
|
world_config.save_radius,
|
||
|
&world_path,
|
||
|
&backup_path,
|
||
|
)?;
|
||
|
Ok(region_count)
|
||
|
}
|
||
|
|
||
|
/// Backup the overworld
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
/// * `world_config` - world config options
|
||
|
pub fn backup_overworld(
|
||
|
world_path: PathBuf,
|
||
|
backup_path: PathBuf,
|
||
|
world_config: &WorldConfig,
|
||
|
) -> Result<(u64, u64), std::io::Error> {
|
||
|
backup_dir("data", &world_path, &backup_path)?;
|
||
|
backup_dir("stats", &world_path, &backup_path)?;
|
||
|
|
||
|
backup_file("level.dat", world_path.clone(), backup_path.clone())?;
|
||
|
backup_file("level.dat_old", world_path.clone(), backup_path.clone())?;
|
||
|
backup_file("session.lock", world_path.clone(), backup_path.clone())?;
|
||
|
backup_file("uid.dat", world_path.clone(), backup_path.clone())?;
|
||
|
|
||
|
let player_count = backup_dir("playerdata", &world_path, &backup_path)?;
|
||
|
let region_count = backup_world(world_path, backup_path, world_config)?;
|
||
|
|
||
|
Ok((region_count, player_count))
|
||
|
}
|
||
|
|
||
|
/// Backup the nether
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
/// * `world_config` - world config options
|
||
|
pub fn backup_nether(
|
||
|
world_path: PathBuf,
|
||
|
backup_path: PathBuf,
|
||
|
world_config: &WorldConfig,
|
||
|
) -> Result<u64, std::io::Error> {
|
||
|
let mut nether_path = world_path;
|
||
|
nether_path.push("DIM-1");
|
||
|
|
||
|
backup_world(nether_path, backup_path, world_config)
|
||
|
}
|
||
|
|
||
|
/// Backup the end
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `world_path` - path to the world folder
|
||
|
/// * `backup_path` - path to the backup folder
|
||
|
/// * `world_config` - world config options
|
||
|
pub fn backup_end(
|
||
|
world_path: PathBuf,
|
||
|
backup_path: PathBuf,
|
||
|
world_config: &WorldConfig,
|
||
|
) -> Result<u64, std::io::Error> {
|
||
|
let mut end_path = world_path;
|
||
|
end_path.push("DIM1");
|
||
|
|
||
|
backup_world(end_path, backup_path, world_config)
|
||
|
}
|
||
|
|
||
|
/// Compress the backup after the files have been copied
|
||
|
///
|
||
|
/// # Param
|
||
|
/// * `tmp_dir`: tmp directory with the backed up files
|
||
|
/// * `output_file`: output archive
|
||
|
pub fn compress_backup(tmp_dir: &PathBuf, output_file: &PathBuf) -> Result<(), std::io::Error> {
|
||
|
let archive = File::create(output_file)?;
|
||
|
let enc = GzEncoder::new(archive, Compression::default());
|
||
|
let mut tar_builder = tar::Builder::new(enc);
|
||
|
tar_builder.append_dir_all(".", tmp_dir)?;
|
||
|
Ok(())
|
||
|
}
|