33// SPDX-License-Identifier: MPL-2.0
44
55mod disk;
6- use std:: { fs, io, path:: PathBuf } ;
6+ use std:: {
7+ fs, io,
8+ path:: { Path , PathBuf } ,
9+ } ;
710
811pub use disk:: * ;
12+ pub mod loopback;
913pub mod mmc;
1014pub mod nvme;
1115pub mod partition;
@@ -20,7 +24,7 @@ const DEVFS_DIR: &str = "/dev";
2024pub enum BlockDevice {
2125 /// A physical disk device
2226 Disk ( Box < Disk > ) ,
23- Unknown ,
27+ Loopback ( Box < loopback :: Device > ) ,
2428}
2529
2630impl BlockDevice {
@@ -33,6 +37,22 @@ impl BlockDevice {
3337 Self :: discover_in_sysroot ( "/" )
3438 }
3539
40+ /// Returns the name of the block device.
41+ pub fn name ( & self ) -> & str {
42+ match self {
43+ BlockDevice :: Disk ( disk) => disk. name ( ) ,
44+ BlockDevice :: Loopback ( device) => device. name ( ) ,
45+ }
46+ }
47+
48+ /// Returns the path to the block device in /dev.
49+ pub fn device ( & self ) -> & Path {
50+ match self {
51+ BlockDevice :: Disk ( disk) => disk. device_path ( ) ,
52+ BlockDevice :: Loopback ( device) => device. device_path ( ) ,
53+ }
54+ }
55+
3656 /// Discovers block devices in a specified sysroot directory.
3757 ///
3858 /// # Arguments
@@ -48,24 +68,28 @@ impl BlockDevice {
4868 let mut devices = Vec :: new ( ) ;
4969
5070 // Iterate over all block devices in sysfs and collect their filenames
51- let entries = fs:: read_dir ( & sysfs_dir) ?
71+ let mut entries = fs:: read_dir ( & sysfs_dir) ?
5272 . filter_map ( Result :: ok)
53- . filter_map ( |e| Some ( e. file_name ( ) . to_str ( ) ?. to_owned ( ) ) ) ;
73+ . filter_map ( |e| Some ( e. file_name ( ) . to_str ( ) ?. to_owned ( ) ) )
74+ . collect :: < Vec < _ > > ( ) ;
75+ entries. sort ( ) ;
5476
5577 // For all the discovered block devices, try to create a Disk instance
5678 // At this point we completely ignore partitions. They come later.
5779 for entry in entries {
58- let disk = if let Some ( disk) = scsi:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
59- Disk :: Scsi ( disk)
80+ let device = if let Some ( disk) = scsi:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
81+ BlockDevice :: Disk ( Box :: new ( Disk :: Scsi ( disk) ) )
6082 } else if let Some ( disk) = nvme:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
61- Disk :: Nvme ( disk)
83+ BlockDevice :: Disk ( Box :: new ( Disk :: Nvme ( disk) ) )
6284 } else if let Some ( disk) = mmc:: Disk :: from_sysfs_path ( & sysfs_dir, & entry) {
63- Disk :: Mmc ( disk)
85+ BlockDevice :: Disk ( Box :: new ( Disk :: Mmc ( disk) ) )
86+ } else if let Some ( device) = loopback:: Device :: from_sysfs_path ( & sysfs_dir, & entry) {
87+ BlockDevice :: Loopback ( Box :: new ( device) )
6488 } else {
6589 continue ;
6690 } ;
6791
68- devices. push ( BlockDevice :: Disk ( Box :: new ( disk ) ) ) ;
92+ devices. push ( device ) ;
6993 }
7094
7195 Ok ( devices)
@@ -80,10 +104,27 @@ mod tests {
80104 fn test_discover ( ) {
81105 let devices = BlockDevice :: discover ( ) . unwrap ( ) ;
82106 for device in & devices {
83- if let BlockDevice :: Disk ( disk) = device {
84- println ! ( "{}: {disk}" , disk. name( ) ) ;
85- for partition in disk. partitions ( ) {
86- println ! ( "├─{} {partition}" , partition. name) ;
107+ match device {
108+ BlockDevice :: Disk ( disk) => {
109+ println ! ( "{}: {disk}" , disk. name( ) ) ;
110+ for partition in disk. partitions ( ) {
111+ println ! ( "├─{} {partition}" , partition. name) ;
112+ }
113+ }
114+ BlockDevice :: Loopback ( device) => {
115+ if let Some ( file) = device. file_path ( ) {
116+ if let Some ( disk) = device. disk ( ) {
117+ println ! ( "Loopback device: {} (backing file: {})" , device. name( ) , file. display( ) ) ;
118+ println ! ( "└─Disk: {} ({})" , disk. name( ) , disk. model( ) . unwrap_or( "Unknown" ) ) ;
119+ for partition in disk. partitions ( ) {
120+ println ! ( " ├─{} {partition}" , partition. name) ;
121+ }
122+ } else {
123+ println ! ( "Loopback device: {} (backing file: {})" , device. name( ) , file. display( ) ) ;
124+ }
125+ } else {
126+ println ! ( "Loopback device: {}" , device. name( ) ) ;
127+ }
87128 }
88129 }
89130 }
0 commit comments