@@ -9,6 +9,7 @@ use std::{
99} ;
1010
1111pub use disk:: * ;
12+ use partition:: Partition ;
1213pub mod loopback;
1314pub mod mmc;
1415pub mod mock;
@@ -18,8 +19,8 @@ pub mod scsi;
1819mod sysfs;
1920pub mod virt;
2021
21- const SYSFS_DIR : & str = "/ sys/class/block" ;
22- const DEVFS_DIR : & str = "/ dev" ;
22+ const SYSFS_DIR : & str = "sys/class/block" ;
23+ const DEVFS_DIR : & str = "dev" ;
2324
2425/// A block device on the system which can be either a physical disk or a partition.
2526#[ derive( Debug ) ]
@@ -39,6 +40,65 @@ impl BlockDevice {
3940 Self :: discover_in_sysroot ( "/" )
4041 }
4142
43+ /// Returns the total number of sectors on the block device.
44+ pub fn sectors ( & self ) -> u64 {
45+ match self {
46+ BlockDevice :: Disk ( disk) => disk. sectors ( ) ,
47+ BlockDevice :: Loopback ( device) => device. disk ( ) . map_or ( 0 , |d| d. sectors ( ) ) ,
48+ }
49+ }
50+
51+ /// Returns the total size of the block device in bytes.
52+ pub fn size ( & self ) -> u64 {
53+ self . sectors ( ) * 512
54+ }
55+
56+ /// Returns the partitions on the block device.
57+ pub fn partitions ( & self ) -> & [ Partition ] {
58+ match self {
59+ BlockDevice :: Disk ( disk) => disk. partitions ( ) ,
60+ BlockDevice :: Loopback ( device) => device. disk ( ) . map_or ( & [ ] , |d| d. partitions ( ) ) ,
61+ }
62+ }
63+
64+ /// Creates a mock block device with a specified number of sectors.
65+ pub fn mock_device ( disk : mock:: MockDisk ) -> Self {
66+ BlockDevice :: Disk ( Box :: new ( Disk :: Mock ( disk) ) )
67+ }
68+
69+ /// Creates a loopback block device from a file path.
70+ pub fn loopback_device ( device : loopback:: Device ) -> Self {
71+ BlockDevice :: Loopback ( Box :: new ( device) )
72+ }
73+
74+ /// Creates a BlockDevice from a specific device path
75+ ///
76+ /// # Arguments
77+ ///
78+ /// * `device_path` - Path to the block device (e.g. "/dev/sda")
79+ ///
80+ /// # Returns
81+ ///
82+ /// The block device or an IO error if creation fails.
83+ pub fn from_sysfs_path ( sysfs_root : impl AsRef < Path > , name : impl AsRef < str > ) -> io:: Result < BlockDevice > {
84+ let name = name. as_ref ( ) ;
85+ let sysfs_dir = sysfs_root. as_ref ( ) ;
86+
87+ if let Some ( disk) = scsi:: Disk :: from_sysfs_path ( sysfs_dir, name) {
88+ return Ok ( BlockDevice :: Disk ( Box :: new ( Disk :: Scsi ( disk) ) ) ) ;
89+ } else if let Some ( disk) = nvme:: Disk :: from_sysfs_path ( sysfs_dir, name) {
90+ return Ok ( BlockDevice :: Disk ( Box :: new ( Disk :: Nvme ( disk) ) ) ) ;
91+ } else if let Some ( disk) = mmc:: Disk :: from_sysfs_path ( sysfs_dir, name) {
92+ return Ok ( BlockDevice :: Disk ( Box :: new ( Disk :: Mmc ( disk) ) ) ) ;
93+ } else if let Some ( device) = virt:: Disk :: from_sysfs_path ( sysfs_dir, name) {
94+ return Ok ( BlockDevice :: Disk ( Box :: new ( Disk :: Virtual ( device) ) ) ) ;
95+ } else if let Some ( device) = loopback:: Device :: from_sysfs_path ( sysfs_dir, name) {
96+ return Ok ( BlockDevice :: Loopback ( Box :: new ( device) ) ) ;
97+ }
98+
99+ Err ( io:: Error :: new ( io:: ErrorKind :: NotFound , "Device not found" ) )
100+ }
101+
42102 /// Returns the name of the block device.
43103 pub fn name ( & self ) -> & str {
44104 match self {
@@ -79,21 +139,9 @@ impl BlockDevice {
79139 // For all the discovered block devices, try to create a Disk instance
80140 // At this point we completely ignore partitions. They come later.
81141 for entry in entries {
82- let device = if let Some ( disk) = scsi:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
83- BlockDevice :: Disk ( Box :: new ( Disk :: Scsi ( disk) ) )
84- } else if let Some ( disk) = nvme:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
85- BlockDevice :: Disk ( Box :: new ( Disk :: Nvme ( disk) ) )
86- } else if let Some ( disk) = mmc:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
87- BlockDevice :: Disk ( Box :: new ( Disk :: Mmc ( disk) ) )
88- } else if let Some ( device) = virt:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
89- BlockDevice :: Disk ( Box :: new ( Disk :: Virtual ( device) ) )
90- } else if let Some ( device) = loopback:: Device :: from_sysfs_path ( & sysfs_dir, & entry) {
91- BlockDevice :: Loopback ( Box :: new ( device) )
92- } else {
93- continue ;
94- } ;
95-
96- devices. push ( device) ;
142+ if let Ok ( device) = BlockDevice :: from_sysfs_path ( & sysfs_dir, & entry) {
143+ devices. push ( device) ;
144+ }
97145 }
98146
99147 Ok ( devices)
0 commit comments