block-devs 0.1.0

Safe portable wrapper for block device opperations
Documentation
use crate::{to_io, BlckExt};
use std::fs::File;
use std::io::Result;
use std::os::unix::fs::FileTypeExt;
use std::os::unix::io::AsRawFd;

impl BlckExt for File {
    fn is_block_device(&self) -> bool {
        match self.metadata() {
            Err(_) => false,
            Ok(meta) => meta.file_type().is_block_device(),
        }
    }

    fn get_block_device_size(&self) -> Result<u64> {
        let fd = self.as_raw_fd();
        let mut blksize = 0;
        unsafe {
            ioctls::blkgetsize64(fd, &mut blksize).map_err(to_io)?;
            Ok(blksize)
        }
    }

    fn get_size_of_block(&self) -> Result<u64> {
        let fd = self.as_raw_fd();
        let mut blksize = 0;
        unsafe {
            ioctls::blksszget(fd, &mut blksize).map_err(to_io)?;
        }
        Ok(blksize as u64)
    }

    fn get_block_count(&self) -> Result<u64> {
        Ok(self.get_block_device_size()? / self.get_size_of_block()?)
    }

    fn block_reread_paritions(&self) -> Result<()> {
        let fd = self.as_raw_fd();
        unsafe {
            ioctls::blkrrpart(fd).map_err(to_io)?;
        }
        Ok(())
    }

    fn block_discard_zeros(&self) -> Result<bool> {
        let fd = self.as_raw_fd();
        let mut discard_zeros = 0;
        unsafe {
            ioctls::blkdiscardzeros(fd, &mut discard_zeros).map_err(to_io)?;
        }
        Ok(discard_zeros != 0)
    }

    fn block_discard(&self, offset: u64, len: u64) -> Result<()> {
        let fd = self.as_raw_fd();
        let range = [offset, len];
        unsafe {
            ioctls::blkdiscard(fd, &range).map_err(to_io)?;
        }
        Ok(())
    }

    fn block_zero_out(&mut self, offset: u64, len: u64) -> Result<()> {
        let fd = self.as_raw_fd();
        let range = [offset, len];
        unsafe {
            ioctls::blkzeroout(fd, &range).map_err(to_io)?;
        }
        Ok(())
    }

    fn sync_data(&self) -> Result<()> {
        File::sync_data(self)
    }
}

mod ioctls {
    use nix::{
        ioctl_none, ioctl_read_bad, ioctl_write_ptr_bad, request_code_none, request_code_read,
    };

    ioctl_none!(blkrrpart, 0x12, 95);
    ioctl_read_bad!(
        blkgetsize64,
        request_code_read!(0x12, 114, ::std::mem::size_of::<usize>()),
        u64
    );
    ioctl_read_bad!(
        blkdiscardzeros,
        request_code_none!(0x12, 124),
        ::std::os::raw::c_uint
    );
    ioctl_write_ptr_bad!(blkdiscard, request_code_none!(0x12, 119), [u64; 2]);
    ioctl_write_ptr_bad!(blkzeroout, request_code_none!(0x12, 127), [u64; 2]);
    ioctl_read_bad!(
        blksszget,
        request_code_none!(0x12, 104),
        ::std::os::raw::c_int
    );
}