block_devs/
linux.rs

1use crate::{to_io, BlckExt};
2use std::fs::File;
3use std::io::Result;
4use std::os::unix::fs::FileTypeExt;
5use std::os::unix::io::AsRawFd;
6
7impl BlckExt for File {
8    fn is_block_device(&self) -> bool {
9        match self.metadata() {
10            Err(_) => false,
11            Ok(meta) => meta.file_type().is_block_device(),
12        }
13    }
14
15    fn get_block_device_size(&self) -> Result<u64> {
16        let fd = self.as_raw_fd();
17        let mut blksize = 0;
18        unsafe {
19            ioctls::blkgetsize64(fd, &mut blksize).map_err(to_io)?;
20            Ok(blksize)
21        }
22    }
23
24    fn get_size_of_block(&self) -> Result<u64> {
25        let fd = self.as_raw_fd();
26        let mut blksize = 0;
27        unsafe {
28            ioctls::blksszget(fd, &mut blksize).map_err(to_io)?;
29        }
30        Ok(blksize as u64)
31    }
32
33    fn get_block_count(&self) -> Result<u64> {
34        Ok(self.get_block_device_size()? / self.get_size_of_block()?)
35    }
36
37    fn block_reread_paritions(&self) -> Result<()> {
38        let fd = self.as_raw_fd();
39        unsafe {
40            ioctls::blkrrpart(fd).map_err(to_io)?;
41        }
42        Ok(())
43    }
44
45    fn block_discard_zeros(&self) -> Result<bool> {
46        let fd = self.as_raw_fd();
47        let mut discard_zeros = 0;
48        unsafe {
49            ioctls::blkdiscardzeros(fd, &mut discard_zeros).map_err(to_io)?;
50        }
51        Ok(discard_zeros != 0)
52    }
53
54    fn block_discard(&self, offset: u64, len: u64) -> Result<()> {
55        let fd = self.as_raw_fd();
56        let range = [offset, len];
57        unsafe {
58            ioctls::blkdiscard(fd, &range).map_err(to_io)?;
59        }
60        Ok(())
61    }
62
63    fn block_zero_out(&mut self, offset: u64, len: u64) -> Result<()> {
64        let fd = self.as_raw_fd();
65        let range = [offset, len];
66        unsafe {
67            ioctls::blkzeroout(fd, &range).map_err(to_io)?;
68        }
69        Ok(())
70    }
71
72    fn sync_data(&self) -> Result<()> {
73        File::sync_data(self)
74    }
75}
76
77mod ioctls {
78    use nix::{
79        ioctl_none, ioctl_read_bad, ioctl_write_ptr_bad, request_code_none, request_code_read,
80    };
81
82    ioctl_none!(blkrrpart, 0x12, 95);
83    ioctl_read_bad!(
84        blkgetsize64,
85        request_code_read!(0x12, 114, ::std::mem::size_of::<usize>()),
86        u64
87    );
88    ioctl_read_bad!(
89        blkdiscardzeros,
90        request_code_none!(0x12, 124),
91        ::std::os::raw::c_uint
92    );
93    ioctl_write_ptr_bad!(blkdiscard, request_code_none!(0x12, 119), [u64; 2]);
94    ioctl_write_ptr_bad!(blkzeroout, request_code_none!(0x12, 127), [u64; 2]);
95    ioctl_read_bad!(
96        blksszget,
97        request_code_none!(0x12, 104),
98        ::std::os::raw::c_int
99    );
100}