@@ -4,6 +4,7 @@ use crate::sys::utils::{get_all_utf8_data, to_cpath};
4
4
use crate :: { Disk , DiskKind } ;
5
5
6
6
use libc:: statvfs;
7
+ use std:: collections:: HashMap ;
7
8
use std:: ffi:: { OsStr , OsString } ;
8
9
use std:: fs;
9
10
use std:: mem;
@@ -78,10 +79,7 @@ impl crate::DisksInner {
78
79
}
79
80
80
81
pub ( crate ) fn refresh_list ( & mut self ) {
81
- get_all_list (
82
- & mut self . disks ,
83
- & get_all_utf8_data ( "/proc/mounts" , 16_385 ) . unwrap_or_default ( ) ,
84
- )
82
+ get_all_list ( & mut self . disks )
85
83
}
86
84
87
85
pub ( crate ) fn list ( & self ) -> & [ Disk ] {
@@ -104,17 +102,17 @@ fn new_disk(
104
102
let mut total = 0 ;
105
103
let mut available = 0 ;
106
104
unsafe {
107
- let mut stat: statvfs = mem:: zeroed ( ) ;
108
- if retry_eintr ! ( statvfs( mount_point_cpath. as_ptr( ) as * const _, & mut stat) ) == 0 {
109
- let bsize = cast ! ( stat. f_bsize) ;
110
- let blocks = cast ! ( stat. f_blocks) ;
111
- let bavail = cast ! ( stat. f_bavail) ;
112
- total = bsize. saturating_mul ( blocks) ;
113
- available = bsize. saturating_mul ( bavail) ;
114
- }
115
- if total == 0 {
116
- return None ;
105
+ if !mount_point. as_os_str ( ) . is_empty ( ) {
106
+ let mut stat: statvfs = mem:: zeroed ( ) ;
107
+ if retry_eintr ! ( statvfs( mount_point_cpath. as_ptr( ) as * const _, & mut stat) ) == 0 {
108
+ let bsize = cast ! ( stat. f_bsize) ;
109
+ let blocks = cast ! ( stat. f_blocks) ;
110
+ let bavail = cast ! ( stat. f_bavail) ;
111
+ total = bsize. saturating_mul ( blocks) ;
112
+ available = bsize. saturating_mul ( bavail) ;
113
+ }
117
114
}
115
+
118
116
let mount_point = mount_point. to_owned ( ) ;
119
117
let is_removable = removable_entries
120
118
. iter ( )
@@ -204,8 +202,40 @@ fn find_type_for_device_name(device_name: &OsStr) -> DiskKind {
204
202
}
205
203
}
206
204
207
- fn get_all_list ( container : & mut Vec < Disk > , content : & str ) {
205
+ fn get_all_list ( container : & mut Vec < Disk > ) {
208
206
container. clear ( ) ;
207
+ let partitions = get_all_utf8_data ( "/proc/partitions" , 16_385 ) . unwrap_or_default ( ) ;
208
+ let mut disks: HashMap < String , ( String , String , String ) > = HashMap :: new ( ) ;
209
+
210
+ for line in partitions. lines ( ) . skip ( 2 ) {
211
+ let line = line. trim ( ) ;
212
+ let fields = line. split_whitespace ( ) ;
213
+ let name = format ! ( "/dev/{}" , fields. last( ) . unwrap_or_default( ) ) ;
214
+ disks. insert ( name. clone ( ) , ( name, "" . to_string ( ) , "" . to_string ( ) ) ) ;
215
+ }
216
+
217
+ let mounts = get_all_utf8_data ( "/proc/mounts" , 16_385 ) . unwrap_or_default ( ) ;
218
+
219
+ for line in mounts. lines ( ) {
220
+ let line = line. trim ( ) ;
221
+ let mut fields = line. split_whitespace ( ) ;
222
+ let fs_spec = fields. next ( ) . unwrap_or ( "" ) ;
223
+ let fs_file = fields
224
+ . next ( )
225
+ . unwrap_or ( "" )
226
+ . replace ( "\\ 134" , "\\ " )
227
+ . replace ( "\\ 040" , " " )
228
+ . replace ( "\\ 011" , "\t " )
229
+ . replace ( "\\ 012" , "\n " ) ;
230
+ let fs_vfstype = fields. next ( ) . unwrap_or ( "" ) ;
231
+ if fs_spec. starts_with ( "/dev/" ) {
232
+ if let Some ( disk) = disks. get_mut ( fs_spec) {
233
+ disk. 1 = fs_file. to_string ( ) ;
234
+ disk. 2 = fs_vfstype. to_string ( ) ;
235
+ }
236
+ }
237
+ }
238
+
209
239
// The goal of this array is to list all removable devices (the ones whose name starts with
210
240
// "usb-").
211
241
let removable_entries = match fs:: read_dir ( "/dev/disk/by-id/" ) {
@@ -225,61 +255,15 @@ fn get_all_list(container: &mut Vec<Disk>, content: &str) {
225
255
_ => Vec :: new ( ) ,
226
256
} ;
227
257
228
- for disk in content
229
- . lines ( )
230
- . map ( |line| {
231
- let line = line. trim_start ( ) ;
232
- // mounts format
233
- // http://man7.org/linux/man-pages/man5/fstab.5.html
234
- // fs_spec<tab>fs_file<tab>fs_vfstype<tab>other fields
235
- let mut fields = line. split_whitespace ( ) ;
236
- let fs_spec = fields. next ( ) . unwrap_or ( "" ) ;
237
- let fs_file = fields
238
- . next ( )
239
- . unwrap_or ( "" )
240
- . replace ( "\\ 134" , "\\ " )
241
- . replace ( "\\ 040" , " " )
242
- . replace ( "\\ 011" , "\t " )
243
- . replace ( "\\ 012" , "\n " ) ;
244
- let fs_vfstype = fields. next ( ) . unwrap_or ( "" ) ;
245
- ( fs_spec, fs_file, fs_vfstype)
246
- } )
247
- . filter ( |( fs_spec, fs_file, fs_vfstype) | {
248
- // Check if fs_vfstype is one of our 'ignored' file systems.
249
- let filtered = match * fs_vfstype {
250
- "rootfs" | // https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
251
- "sysfs" | // pseudo file system for kernel objects
252
- "proc" | // another pseudo file system
253
- "devtmpfs" |
254
- "cgroup" |
255
- "cgroup2" |
256
- "pstore" | // https://www.kernel.org/doc/Documentation/ABI/testing/pstore
257
- "squashfs" | // squashfs is a compressed read-only file system (for snaps)
258
- "rpc_pipefs" | // The pipefs pseudo file system service
259
- "iso9660" // optical media
260
- => true ,
261
- "tmpfs" => !cfg ! ( feature = "linux-tmpfs" ) ,
262
- // calling statvfs on a mounted CIFS or NFS may hang, when they are mounted with option: hard
263
- "cifs" | "nfs" | "nfs4" => !cfg ! ( feature = "linux-netdevs" ) ,
264
- _ => false ,
265
- } ;
266
-
267
- !( filtered ||
268
- fs_file. starts_with ( "/sys" ) || // check if fs_file is an 'ignored' mount point
269
- fs_file. starts_with ( "/proc" ) ||
270
- ( fs_file. starts_with ( "/run" ) && !fs_file. starts_with ( "/run/media" ) ) ||
271
- fs_spec. starts_with ( "sunrpc" ) )
272
- } )
273
- . filter_map ( |( fs_spec, fs_file, fs_vfstype) | {
274
- new_disk (
275
- fs_spec. as_ref ( ) ,
276
- Path :: new ( & fs_file) ,
277
- fs_vfstype. as_ref ( ) ,
278
- & removable_entries,
279
- )
280
- } )
281
- {
282
- container. push ( disk) ;
258
+ for ( fs_spec, fs_file, fs_vfstype) in disks. values ( ) {
259
+ if let Some ( disk) = new_disk (
260
+ fs_spec. as_ref ( ) ,
261
+ Path :: new ( & fs_file) ,
262
+ fs_vfstype. as_ref ( ) ,
263
+ & removable_entries,
264
+ ) {
265
+ container. push ( disk) ;
266
+ }
283
267
}
284
268
}
285
269
0 commit comments