Repository: cholcombe973/block-utils (language: rust)

Issue:
`get_block_dev_properties` doesn't work
I've found one another bug in [my last PR.](https://github.com/cholcombe973/block-utils/pull/19)

```rust
pub fn get_block_dev_properties(
    device_path: impl AsRef<Path>,
) -> BlockResult<HashMap<String, String>> {
    let syspath = device_path
        .as_ref()
        .file_name()
        .map(PathBuf::from)
        .ok_or_else(|| {
            BlockUtilsError::new(format!(
                "Unable to get file_name on device {:?}",
                device_path.as_ref()
            ))
        })?;

    let udev_device = udev::Device::from_syspath(&syspath)?; //HERE
    Ok(udev_device
        .clone()
        .properties()
        .map(|property| {
            let key = property.name().to_string_lossy().to_string();
            let value = property.value().to_string_lossy().to_string();
            (key, value)
        })
        .collect()) // We can't return iterator because `udev_device` doesn't live long enough
}
```

`udev::Device::from_syspath` expects full syspath like `/sys/block/loop0` instead of just a sysname `loop0` like in `udevadm` CLI.
`udevadm` CLI expects sysname and found exact syspath automatically. 
So, these functions `get_block_dev_properties` and `get_block_dev_property` doesn't work properly.

And I'm not sure how to fix it right now. As far as I understand, this path can lay not only in `/sys/block/$dev` but also in other `/sys/` subdirectories.

Unfortunately I don't have enough time right now so I'm going to investigate it over the next few weeks.


Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index a02c921..1651498 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1212,22 +1212,38 @@ pub fn is_block_device(device_path: impl AsRef<Path>) -> BlockResult<bool> {
     )))
 }
 
-/// Get property value by key `tag` for device with devpath `device_path` (like "/dev/sda") if present
-#[cfg(target_os = "linux")]
-pub fn get_block_dev_property(
-    device_path: impl AsRef<Path>,
-    tag: &str,
-) -> BlockResult<Option<String>> {
-    let syspath = device_path
+/// Get sys path (like `/sys/class/block/loop0`) by dev path (like `/dev/loop0`).
+/// Dev path should refer to block device.
+/// Returns error if sys path doesn't exist.
+fn dev_path_to_sys_path(dev_path: impl AsRef<Path>) -> BlockResult<PathBuf> {
+    let sys_path = dev_path
         .as_ref()
         .file_name()
-        .map(PathBuf::from)
+        .map(|name| PathBuf::from("/sys/class/block").join(name))
         .ok_or_else(|| {
             BlockUtilsError::new(format!(
                 "Unable to get file_name on device {:?}",
-                device_path.as_ref()
+                dev_path.as_ref()
             ))
         })?;
+    if sys_path.exists() {
+        Ok(sys_path)
+    } else {
+        Err(BlockUtilsError::new(format!(
+            "Sys path {} doesn't exist. Maybe {} is not a block device",
+            sys_path.display(),
+            dev_path.as_ref().display()
+        )))
+    }
+}
+
+/// Get property value by key `tag` for device with devpath `device_path` (like "/dev/sda") if present
+#[cfg(target_os = "linux")]
+pub fn get_block_dev_property(
+    device_path: impl AsRef<Path>,
+    tag: &str,
+) -> BlockResult<Option<String>> {
+    let syspath = dev_path_to_sys_path(device_path)?;
 
     Ok(udev::Device::from_syspath(&syspath)?
         .property_value(tag)
@@ -1239,16 +1255,7 @@ pub fn get_block_dev_property(
 pub fn get_block_dev_properties(
     device_path: impl AsRef<Path>,
 ) -> BlockResult<HashMap<String, String>> {
-    let syspath = device_path
-        .as_ref()
-        .file_name()
-        .map(PathBuf::from)
-        .ok_or_else(|| {
-            BlockUtilsError::new(format!(
-                "Unable to get file_name on device {:?}",
-                device_path.as_ref()
-            ))
-        })?;
+    let syspath = dev_path_to_sys_path(device_path)?;
 
     let udev_device = udev::Device::from_syspath(&syspath)?;
     Ok(udev_device


Test patch: