Repository: GuillaumeGomez/sysinfo (language: rust)

Issue:
Filesystem with the same mountpoint but different device is not added anymore to Disks
**Describe the bug**
Platform: Linux

This bug was introduced in 0.33 (more precisely in 08e3d13 in src/unix/linux/disk.rs on line 406-414)

Now if a disk entry with the same mountpoint already exists, it is refreshed instead of added, even if it has a different backing device.

This, however, is not always correct and/or desired. I use automounts (autofs) to mount my ESP (this is what systemd does by default) and want to check the underlying filesystem of this mount. This is not possible anymore as sysinfo will only ever display the autofs entry even if the mount is activated.

When the mount is not "activated", you have one entry in /proc/mounts. When activated, you get a second entry.

Before activating automount:
```
systemd-1 /efi autofs rw,relatime,fd=181,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=8311 0 0
``` 

After activating automount:
```
systemd-1 /efi autofs rw,relatime,fd=181,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=8311 0 0
/dev/nvme0n1p1 /efi vfat rw,nosuid,nodev,noexec,relatime,nosymfollow,fmask=0077,dmask=0077 0 0
``` 
Even after activating the automount, sysinfo will only show `/efi` as `autofs`.

This used to work in 0.32

**To Reproduce**
Please provide the code showing the bug so it can be reproduced.



Discussion / hints:
Thanks for the bug report! I'll take a look in the next few weeks but don't hesitate to give it a try before then.

Fix patch:
diff --git a/src/unix/apple/disk.rs b/src/unix/apple/disk.rs
index c5b24b4f0..d598eb062 100644
--- a/src/unix/apple/disk.rs
+++ b/src/unix/apple/disk.rs
@@ -322,6 +322,8 @@ unsafe fn get_list(container: &mut Vec<Disk>, refresh_kind: DiskRefreshKind) {
 
         let disk = container
             .iter_mut()
+            // FIXME: Using the mount point might not be enough to ensure this disk is the one
+            // we're looking for.
             .find(|d| d.inner.mount_point == mount_point);
         if let Some(disk) = new_disk(
             disk,
diff --git a/src/unix/freebsd/disk.rs b/src/unix/freebsd/disk.rs
index 4aff58ee2..1100dcaa8 100644
--- a/src/unix/freebsd/disk.rs
+++ b/src/unix/freebsd/disk.rs
@@ -375,7 +375,15 @@ pub unsafe fn get_all_list(
             OsString::from(mount_point)
         };
 
-        if let Some(disk) = container.iter_mut().find(|d| d.inner.name == name) {
+        if let Some(disk) = container.iter_mut().find(|d| {
+            d.inner.name == name
+                && d.inner
+                    .file_system
+                    .as_encoded_bytes()
+                    .iter()
+                    .zip(fs_type.iter())
+                    .all(|(a, b)| a == b)
+        }) {
             // I/O usage is updated for all disks at once at the end.
             refresh_disk(&mut disk.inner, refresh_kind.without_io_usage());
             disk.inner.updated = true;
diff --git a/src/unix/linux/disk.rs b/src/unix/linux/disk.rs
index babbd0839..f7379ef30 100644
--- a/src/unix/linux/disk.rs
+++ b/src/unix/linux/disk.rs
@@ -406,10 +406,11 @@ fn get_all_list(container: &mut Vec<Disk>, content: &str, refresh_kind: DiskRefr
         })
     {
         let mount_point = Path::new(&fs_file);
-        if let Some(disk) = container
-            .iter_mut()
-            .find(|d| d.inner.mount_point == mount_point)
-        {
+        if let Some(disk) = container.iter_mut().find(|d| {
+            d.inner.mount_point == mount_point
+                && d.inner.device_name == fs_spec
+                && d.inner.file_system == fs_vfstype
+        }) {
             disk.inner
                 .efficient_refresh(refresh_kind, &procfs_disk_stats, false);
             disk.inner.updated = true;
@@ -465,9 +466,9 @@ impl DiskStat {
         // 3rd field
         let name = iter.nth(2).map(ToString::to_string)?;
         // 6th field
-        let sectors_read = iter.nth(2).and_then(|v| u64::from_str(v).ok())?;
+        let sectors_read = iter.nth(2).and_then(|v| u64::from_str(v).ok()).unwrap_or(0);
         // 10th field
-        let sectors_written = iter.nth(3).and_then(|v| u64::from_str(v).ok())?;
+        let sectors_written = iter.nth(3).and_then(|v| u64::from_str(v).ok()).unwrap_or(0);
         Some((
             name,
             Self {
@@ -583,4 +584,32 @@ mod test {
 
         assert_eq!(data, expected_data);
     }
+
+    #[test]
+    fn disk_entry_with_less_information() {
+        let file_content = "\
+ systemd-1      /efi autofs rw,relatime,fd=181,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=8311 0 0
+ /dev/nvme0n1p1 /efi vfat   rw,nosuid,nodev,noexec,relatime,nosymfollow,fmask=0077,dmask=0077                0 0
+";
+
+        let data = disk_stats_inner(file_content);
+        let expected_data: HashMap<String, DiskStat> = HashMap::from([
+            (
+                "autofs".to_string(),
+                DiskStat {
+                    sectors_read: 0,
+                    sectors_written: 0,
+                },
+            ),
+            (
+                "vfat".to_string(),
+                DiskStat {
+                    sectors_read: 0,
+                    sectors_written: 0,
+                },
+            ),
+        ]);
+
+        assert_eq!(data, expected_data);
+    }
 }
diff --git a/src/windows/disk.rs b/src/windows/disk.rs
index 7fe11ef49..1a443e6a4 100644
--- a/src/windows/disk.rs
+++ b/src/windows/disk.rs
@@ -320,7 +320,10 @@ pub(crate) unsafe fn get_list(
         let name = os_string_from_zero_terminated(&name);
         let file_system = os_string_from_zero_terminated(&file_system);
         for mount_path in mount_paths {
-            if let Some(disk) = disks.iter_mut().find(|d| d.inner.mount_point == mount_path) {
+            if let Some(disk) = disks
+                .iter_mut()
+                .find(|d| d.inner.mount_point == mount_path && d.inner.file_system == file_system)
+            {
                 disk.refresh_specifics(refreshes);
                 disk.inner.updated = true;
                 continue;


Test patch: