i2pd-launch 0.3.0-beta.2

Launches i2pd with clean state
use std::fs::OpenOptions;
use std::io::{self, Write, BufWriter};
use std::path::Path;

/** 2MB souborový buffer používaný pro zápis */
const BUFFER_SIZE: usize = 2 * 1024 * 1024;

/** 32KB velikost dávky používaná pro zápis do bufferu */
const BATCH_SIZE: usize = 32 * 1024;
const BATCH_SIZE_U64: u64 = BATCH_SIZE as u64; // Pro výpočty s u64

/// Přepíše obsah souboru nulami.
///
/// Tato funkce otevře soubor, zjistí jeho velikost a poté jej přepíše
/// nulovými bajty s využitím `BufWriteru` pro zvýšení výkonu.
/// Tato funkce je nyní zaměřena pouze na bezpečné přepsání dat.
///
/// Funkce je generická přes `P` a přijímá jakýkoli typ, který implementuje `AsRef<Path>`.
///
/// # Typové parametry
/// * `P`: Typ cesty k souboru, který musí implementovat `AsRef<Path>`.
///
/// # Argumenty
/// * `path`: Cesta k souboru, který má být přepsán nulami.
///
/// # Návratová hodnota
/// Vrací `Result<(), io::Error>`, kde `Ok(())` značí úspěch,
/// a `Err(io::Error)` značí chybu.
pub fn wipe_with_zeros<P: AsRef<Path>>(path: P) -> io::Result<()> {
    let file_path = path.as_ref();

    // Krok 1: Otevření souboru pro čtení a zápis.
    let file = OpenOptions::new()
        .read(true)
        .write(true)
        .truncate(false)     // Důležité: soubor nebude zkrácen na nulu při otevření
        .create_new(false)    // Soubor už musí existovat
        .open(file_path)?;

    // Krok 2: Zjištění velikosti souboru.
    let file_size = file.metadata()?.len();

    // Krok 3: Inicializace BufWriteru a nulového bloku.
    let mut writer = BufWriter::with_capacity(BUFFER_SIZE, file);
    let zero_batch = vec![0u8; BATCH_SIZE];

    // Krok 4: Přepsání souboru nulami.
    let num_batches = (file_size + BATCH_SIZE_U64 - 1) / BATCH_SIZE_U64;
    for _ in 0..num_batches {
        writer.write_all(&zero_batch)?;
    }

    // Krok 5: Vyprázdnění bufferu BufWriteru.
    // Zajistí, že data z bufferu jdou do OS.
    writer.flush()?;

    // Krok 6: Získání zpět vnitřního souboru a zajištění zápisu na fyzický disk.
    // let mut inner_file = writer.into_inner()?;
    // inner_file.sync_data()?;

    Ok(())
}

// --- Makro `wipe_and_delete!` ---
/// Makro pro bezpečné přepsání souboru nulami a jeho následné smazání.
///
/// Toto makro volá funkci `wipe_with_zeros` pro přepsání dat
/// a následně `std::fs::remove_file` pro smazání souboru.
/// Vrací `Result<(), io::Error>`.
///
/// # Příklady
/// ```
/// # use std::fs;
/// # use std::io;
/// # use std::path::Path;
/// # // Pro účely příkladu definujeme dummy funkci
/// # pub fn wipe_with_zeros<P: AsRef<Path>>(_path: P) -> io::Result<()> { Ok(()) }
/// # #[macro_export]
/// # macro_rules! wipe_and_delete {
/// #     ($path:expr) => {{
/// #         let path_ref = ($path).as_ref();
/// #         $crate::wipe_with_zeros(path_ref)
/// #             .and_then(|_| std::fs::remove_file(path_ref))
/// #     }};
/// # }
/// # // Pro kompilaci příkladu s makrem potřebujeme dummy crate name
/// # #[allow(unused_imports)]
/// # use wipe_and_delete;
/// # #[macro_use]
/// # extern crate your_crate_name;
/// // Vytvoříme testovací soubor
/// let test_file = "my_secret_doc.txt";
/// fs::File::create(test_file).unwrap();
///
/// // Použijeme makro pro přepsání a smazání
/// match wipe_and_delete!(test_file) {
///     Ok(_) => println!("Soubor byl bezpečně přepsán a smazán."),
///     Err(e) => eprintln!("Chyba při mazání souboru: {}", e),
/// }
/// assert!(!Path::new(test_file).exists());
/// ```
#[macro_export]
macro_rules! wipe_and_delete {
    ($path:expr) => {{
        let path_ref : &Path = ($path).as_ref();
        $crate::wipe::wipe_with_zeros(path_ref)
            .and_then(|_| std::fs::remove_file(path_ref))
    }};
}

#[cfg(test)]
#[path = "wipe_tests.rs"]
mod wipe_tests;