From a71d702d98d090eb0bc68fa7950a590967de8716 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 23 Nov 2023 14:23:46 +0800
Subject: [PATCH 082/103] fix(device): avoid panic on shallow clone when
 subsystem is not available

Some special sysfs device, such as /sys/devices/platform, may not contain
available subsystem. This leads to panic in shallow cloning such device
object when getting its subsystem.
---
 libs/device/src/device.rs | 51 ++++++++++++++++++++++++---------------
 1 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index e8e2dcc5..a9cb196c 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -2396,14 +2396,15 @@ impl Device {
 
         device.set_syspath(&syspath, false)?;
 
-        let subsystem = self.get_subsystem()?;
+        /* Some devices, such as /sys/devices/platform, do not have subsystem. */
+        if let Ok(subsystem) = self.get_subsystem() {
+            device.set_subsystem(&subsystem);
 
-        device.set_subsystem(&subsystem);
-
-        if subsystem == "drivers" {
-            device
-                .driver_subsystem
-                .replace(self.driver_subsystem.borrow().clone());
+            if subsystem == "drivers" {
+                device
+                    .driver_subsystem
+                    .replace(self.driver_subsystem.borrow().clone());
+            }
         }
 
         if let Ok(ifindex) = self.get_property_value("IFINDEX") {
@@ -3506,19 +3507,31 @@ mod tests {
 
     #[test]
     fn test_shallow_clone() {
-        #[inline]
-        fn inner_test(dev: &mut Device) -> Result<(), Error> {
-            let s1 = dev.get_syspath().unwrap();
-
-            let dev_clone = dev.shallow_clone().unwrap();
-
-            assert_eq!(s1, dev_clone.get_syspath().unwrap());
-
-            Ok(())
-        }
+        /* Enumerator merely collect devices with valid subsystems,
+         * while get_parent method may not, e.g., /sys/devices/platform.
+         */
+        let mut e = DeviceEnumerator::new();
+        e.set_enumerator_type(DeviceEnumerationType::All);
+
+        for mut dev in e.iter() {
+            let dev_clone = dev.borrow().shallow_clone().unwrap();
+            dev_clone.get_syspath().unwrap();
+            dev_clone.get_subsystem().unwrap();
+
+            loop {
+                let ret = dev.borrow().get_parent();
+
+                if let Ok(parent) = ret {
+                    parent.borrow().get_syspath().unwrap();
+                    if let Err(e) = parent.borrow().get_subsystem() {
+                        assert_eq!(e.get_errno(), Errno::ENOENT);
+                    }
+                    dev = parent;
+                    continue;
+                }
 
-        if let Err(e) = LoopDev::inner_process("/tmp/test_shallow_clone", 1024 * 10, inner_test) {
-            assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
+                break;
+            }
         }
     }
 
2.33.0

