Skip to content
mod.rs 2.83 KiB
Newer Older
Luker's avatar
Luker committed
/*
 * Copyright (c) 2021, Luca Fulchir <luker@fenrirproject.org>
 *
 * This file is part of dfim.
 *
 * dfim is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * dfim is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with dfim.  If not, see <https://www.gnu.org/licenses/>.
 */

Luker's avatar
Luker committed
pub mod cfg;
pub mod s_trgt;
Luker's avatar
Luker committed
use super::config;
use ::std::io::Read;
use ::std::io::Seek;

/// Check if a device is empty. Meaning: no gpt/mbr, first and last MB all zeros
Luker's avatar
Luker committed
pub fn is_empty(dev: &::udev::Device) -> Result<bool, ::std::io::Error> {
Luker's avatar
Luker committed
    // MBR/GPT have headers in the first/last MB,
    // so checking those will guarantee us that there is no MBR/GPT
    let mut device = ::std::fs::File::open(dev.syspath())?;
    // 1MB buffer
    let mut buffer = Vec::<u8>::with_capacity(1024 * 1024);
    unsafe { buffer.set_len(buffer.capacity()) }

    let bytes = device.read(&mut buffer[..])?;
    if buffer[..bytes].iter().any(|&x| x != 0) {
        return Ok(false);
    }
    // check the end of file
    device.seek(::std::io::SeekFrom::End(0))?;
    let max_size = device.stream_position()?;
    if max_size > 1024 * 1024 {
        // else we have already checked it
Luker's avatar
Luker committed
        let to_end = ::std::cmp::max(max_size - 1024 * 1024, 1024 * 1024);
        device.seek(::std::io::SeekFrom::Start(to_end))?;
        let bytes = device.read(&mut buffer[..])?;
        if buffer[..bytes].iter().any(|&x| x != 0) {
            return Ok(false);
        }
    }
    Ok(true)
}

pub fn get(
    logger: &::slog::Logger,
Luker's avatar
Luker committed
    cfg: &cfg::Cfg,
    cfg_target: &config::trgt::Target,
Luker's avatar
Luker committed
    dev: &::udev::Device,
) -> Result<s_trgt::CheckStatus, ::std::io::Error> {
Luker's avatar
Luker committed
    // analyze a device, get the partition table and filesystem
    // to check if the current state and the destination coincide
Luker's avatar
Luker committed
    //
    // returns the target and its udev syspath for any children to be checked
    use crate::state::s_trgt::TargetApply;
    let mut check_target: s_trgt::Target = cfg_target.into();
Luker's avatar
Luker committed
    let res = check_target.check(logger, cfg, dev);
    // TODO: check recursively
    Ok(s_trgt::CheckStatus::DoNotApply)
Luker's avatar
Luker committed
}

pub fn set(
    logger: &::slog::Logger,
Luker's avatar
Luker committed
    cfg: &cfg::Cfg,
    cfg_dev: &config::device::Device,
    cfg_target: &config::trgt::Target,
    dev: &::udev::Device,
Luker's avatar
Luker committed
) -> Result<(), ::std::io::Error> {
    use crate::state::s_trgt::TargetApply;
    let mut apply_target: s_trgt::Target = cfg_target.into();
Luker's avatar
Luker committed

Luker's avatar
Luker committed
    apply_target.apply(logger, cfg, cfg_dev, dev)?;
Luker's avatar
Luker committed

Luker's avatar
Luker committed
    Ok(())
}