From 524f1b554566b2086c755ce62b042adb31da3cac Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 1 Dec 2023 16:20:40 +0800 Subject: [PATCH 01/48] feature(libudev): add our own SDK compatible with libudev Support udev_device_new_* and udev_device_ref, udev_device_unref functions, and give some C examples on how to use the SDK in place of libudev. --- Cargo.lock | 33 ++- Cargo.toml | 1 + exts/libudev/Cargo.toml | 13 + exts/libudev/src/lib.rs | 19 ++ exts/libudev/src/libudev.rs | 37 +++ exts/libudev/src/libudev_device.rs | 273 ++++++++++++++++++ exts/libudev/tests/Makefile | 28 ++ exts/libudev/tests/README | 25 ++ exts/libudev/tests/test_libudev_device_leak.c | 24 ++ .../tests/test_libudev_device_thread.c | 57 ++++ exts/libudev_macro/Cargo.toml | 14 + exts/libudev_macro/src/lib.rs | 67 +++++ 12 files changed, 583 insertions(+), 8 deletions(-) create mode 100644 exts/libudev/Cargo.toml create mode 100644 exts/libudev/src/lib.rs create mode 100644 exts/libudev/src/libudev.rs create mode 100644 exts/libudev/src/libudev_device.rs create mode 100644 exts/libudev/tests/Makefile create mode 100644 exts/libudev/tests/README create mode 100644 exts/libudev/tests/test_libudev_device_leak.c create mode 100644 exts/libudev/tests/test_libudev_device_thread.c create mode 100644 exts/libudev_macro/Cargo.toml create mode 100644 exts/libudev_macro/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 73ea1a30..ed4d84a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,7 +630,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] @@ -1007,6 +1007,23 @@ dependencies = [ name = "libtests" version = "0.5.1" +[[package]] +name = "libudev" +version = "0.5.1" +dependencies = [ + "device", + "libudev_macro", +] + +[[package]] +name = "libudev_macro" +version = "0.5.1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1072,7 +1089,7 @@ version = "0.5.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] @@ -1445,9 +1462,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -1684,7 +1701,7 @@ checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] @@ -1817,9 +1834,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1961,7 +1978,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.39", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7137f026..791ab795 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -126,6 +126,7 @@ members = [ "exts/hostname_setup", "exts/hwdb", "exts/machine-id-setup", + "exts/libudev", #internal libraries crates "libs/cmdproto", #external libraries crates diff --git a/exts/libudev/Cargo.toml b/exts/libudev/Cargo.toml new file mode 100644 index 00000000..678aa39d --- /dev/null +++ b/exts/libudev/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "libudev" +version = "0.5.1" +edition = "2021" + +[lib] +name = "udev" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[dependencies] +device = { path = "../../libs/device", default-features = false } +libudev_macro = { path = "../libudev_macro" } diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs new file mode 100644 index 00000000..d15e2771 --- /dev/null +++ b/exts/libudev/src/lib.rs @@ -0,0 +1,19 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +//! This crate provides C ABI compatible with libudev. + +/// libudev +pub mod libudev; + +/// libudev_device +pub mod libudev_device; diff --git a/exts/libudev/src/libudev.rs b/exts/libudev/src/libudev.rs new file mode 100644 index 00000000..082b7dc7 --- /dev/null +++ b/exts/libudev/src/libudev.rs @@ -0,0 +1,37 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use libudev_macro::RefUnref; +use std::rc::Rc; + +#[repr(C)] +#[derive(Debug, Clone, RefUnref)] +/// udev +pub struct udev { + _unused: [u8; 0], +} + +#[no_mangle] +/// udev_new +pub extern "C" fn udev_new() -> *mut udev { + std::ptr::null_mut() +} + +impl Drop for udev { + fn drop(&mut self) {} +} diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs new file mode 100644 index 00000000..e7f14b3a --- /dev/null +++ b/exts/libudev/src/libudev_device.rs @@ -0,0 +1,273 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use device::Device; +use std::ffi::{CStr, CString}; +use std::mem; +use std::os::linux::raw::dev_t; +use std::rc::Rc; + +use crate::libudev::*; +use libudev_macro::RefUnref; + +#[repr(C)] +#[derive(Debug, Clone, RefUnref)] +/// udev_device +pub struct udev_device { + pub(crate) udev: *mut udev, + pub(crate) device: Rc, + pub(crate) syspath: CString, +} + +impl Drop for udev_device { + fn drop(&mut self) { + if !self.udev.is_null() { + let _ = unsafe { Rc::from_raw(self.udev) }; + } + } +} + +impl udev_device { + fn new(udev: *mut udev, device: Device) -> Self { + Self { + udev, + device: Rc::new(device), + syspath: CString::new("").unwrap(), + } + } +} + +#[no_mangle] +/// udev_device_new_from_device_id +pub extern "C" fn udev_device_new_from_device_id( + udev: *mut udev, + id: *const ::std::os::raw::c_char, +) -> *mut udev_device { + let id = unsafe { CStr::from_ptr(id as *const i8) }; + + let s = match id.to_str() { + Ok(s) => s, + Err(_) => return std::ptr::null_mut(), + }; + + let device = match Device::from_device_id(s) { + Ok(d) => d, + Err(_) => return std::ptr::null_mut(), + }; + + Rc::into_raw(Rc::new(udev_device::new(udev, device))) as *mut udev_device +} + +#[no_mangle] +/// udev_device_new_from_devnum +pub extern "C" fn udev_device_new_from_devnum( + udev: *mut udev, + type_: ::std::os::raw::c_char, + devnum: dev_t, +) -> *mut udev_device { + let device = match Device::from_devnum(type_ as u8 as char, devnum) { + Ok(d) => d, + Err(_) => return std::ptr::null_mut(), + }; + + Rc::into_raw(Rc::new(udev_device::new(udev, device))) as *mut udev_device +} + +#[no_mangle] +/// udev_device_new_from_subsystem_sysname +pub extern "C" fn udev_device_new_from_subsystem_sysname( + udev: *mut udev, + subsystem: *const ::std::os::raw::c_char, + sysname: *const ::std::os::raw::c_char, +) -> *mut udev_device { + let subsystem = unsafe { CStr::from_ptr(subsystem as *const i8) } + .to_str() + .unwrap(); + let sysname = unsafe { CStr::from_ptr(sysname as *const i8) } + .to_str() + .unwrap(); + let device = match Device::from_subsystem_sysname(subsystem, sysname) { + Ok(d) => d, + Err(_) => { + return std::ptr::null_mut(); + } + }; + + Rc::into_raw(Rc::new(udev_device::new(udev, device))) as *mut udev_device +} + +#[no_mangle] +/// udev_device_new_from_syspath +pub extern "C" fn udev_device_new_from_syspath( + udev: *mut udev, + syspath: *const ::std::os::raw::c_char, +) -> *mut udev_device { + let syspath = unsafe { CStr::from_ptr(syspath as *const i8) } + .to_str() + .unwrap(); + let device = match Device::from_syspath(syspath, true) { + Ok(d) => d, + Err(_) => { + return std::ptr::null_mut(); + } + }; + + Rc::into_raw(Rc::new(udev_device::new(udev, device))) as *mut udev_device +} + +#[no_mangle] +/// udev_device_get_syspath +pub extern "C" fn udev_device_get_syspath( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .syspath + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.syspath.as_ptr(); + } + + let device_rc = udev_device_mut.device.clone(); + + let syspath = match device_rc.get_syspath() { + Ok(s) => s, + Err(_) => return std::ptr::null_mut(), + }; + + let cstr = match CString::new(syspath) { + Ok(s) => s, + Err(_) => return std::ptr::null_mut(), + }; + + udev_device_mut.syspath = cstr; + + udev_device_mut.syspath.as_ptr() +} + +#[cfg(test)] +mod test { + use std::cell::RefCell; + + use super::*; + use device::device_enumerator::*; + + type RCDevice = Rc>; + pub type Result = std::result::Result<(), device::error::Error>; + + fn test_udev_device_new_from_devnum(device: RCDevice) -> Result { + let devnum = device.borrow().get_devnum()?; + + let t = if &device.borrow().get_subsystem().unwrap() == "block" { + 'b' + } else { + 'c' + }; + + let raw_udev_device = + udev_device_new_from_devnum(std::ptr::null_mut(), t as ::std::os::raw::c_char, devnum); + + let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(raw_udev_device)) }; + + assert_eq!( + syspath.to_str().unwrap(), + &device.borrow().get_syspath().unwrap() + ); + + udev_device_unref(raw_udev_device); + + Ok(()) + } + + fn test_udev_device_new_from_subsystem_sysname(device: RCDevice) -> Result { + let subsystem = device.borrow().get_subsystem().unwrap(); + let sysname = device.borrow().get_sysname().unwrap(); + + /* If subsystem is 'drivers', sysname should use ':'. */ + let name = if subsystem == "drivers" { + format!("{}:{}", device.borrow().driver_subsystem.borrow(), sysname) + } else { + sysname + }; + + let c_subsystem = CString::new(subsystem).unwrap(); + let c_name = CString::new(name).unwrap(); + let raw_udev_device = udev_device_new_from_subsystem_sysname( + std::ptr::null_mut(), + c_subsystem.as_ptr(), + c_name.as_ptr(), + ); + + let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(raw_udev_device)) }; + + assert_eq!( + syspath.to_str().unwrap(), + &device.borrow().get_syspath().unwrap() + ); + + udev_device_unref(raw_udev_device); + + Ok(()) + } + + fn test_udev_device_new_from_device_id(device: RCDevice) -> Result { + let id = device.borrow().get_device_id().unwrap(); + let c_id = CString::new(id).unwrap(); + let udev_device = udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()); + let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(udev_device)) }; + + assert_eq!( + device.borrow().get_syspath().unwrap(), + syspath.to_str().unwrap().to_string() + ); + + udev_device_unref(udev_device); + + Ok(()) + } + + fn test_udev_device_new_from_syspath(device: RCDevice) -> Result { + let syspath = device.borrow().get_syspath().unwrap(); + let c_syspath = CString::new(syspath).unwrap(); + let udev_device = udev_device_new_from_syspath(std::ptr::null_mut(), c_syspath.as_ptr()); + let ret_syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(udev_device)) }; + + assert_eq!(c_syspath.to_str().unwrap(), ret_syspath.to_str().unwrap()); + + udev_device_unref(udev_device); + + Ok(()) + } + + #[test] + fn test_udev_device_new() { + let mut e = DeviceEnumerator::new(); + e.set_enumerator_type(DeviceEnumerationType::All); + + for dev in e.iter() { + let _ = test_udev_device_new_from_device_id(dev.clone()); + let _ = test_udev_device_new_from_devnum(dev.clone()); + let _ = test_udev_device_new_from_subsystem_sysname(dev.clone()); + let _ = test_udev_device_new_from_syspath(dev.clone()); + } + } +} diff --git a/exts/libudev/tests/Makefile b/exts/libudev/tests/Makefile new file mode 100644 index 00000000..0c0cf1a3 --- /dev/null +++ b/exts/libudev/tests/Makefile @@ -0,0 +1,28 @@ +SRCS = $(wildcard *.c) +PROGS = $(patsubst %.c,%,$(SRCS)) +PROGS_LN_RUST = $(patsubst %.c,%_rust,$(SRCS)) + +RELEASE_DIR = $(patsubst %/exts/libudev/tests,%/target/release/,$(CURDIR)) + +CFLAGS=-lpthread -L/lib64 -ludev + +CFLGAS_LN_RUST=-lpthread -L $(RELEASE_DIR) -ludev + +all: c rust + +c: $(PROGS) + +%: %.c + $(CC) $(CFLAGS) -o $@ $< + +rust: build_release $(PROGS_LN_RUST) + +build_release: + cargo build -p libudev --release + +%_rust: %.c + $(CC) $(CFLGAS_LN_RUST) -o $@ $< + +clean: + rm -f $(PROGS) + rm -f $(PROGS_LN_RUST) diff --git a/exts/libudev/tests/README b/exts/libudev/tests/README new file mode 100644 index 00000000..9ec7510c --- /dev/null +++ b/exts/libudev/tests/README @@ -0,0 +1,25 @@ +# README + +## Build + +```shell +$ make all +cc -lpthread -L/lib64 -ludev -o ... +... +$ ./test_libudev_* +... +``` + +## Clean up + +```shell +$ make clean +rm -f ... +``` + +## Pre-load libudev + +```shell +$ LD_PRELOAD= ./test_libudev_* +... +``` diff --git a/exts/libudev/tests/test_libudev_device_leak.c b/exts/libudev/tests/test_libudev_device_leak.c new file mode 100644 index 00000000..f5e981fd --- /dev/null +++ b/exts/libudev/tests/test_libudev_device_leak.c @@ -0,0 +1,24 @@ +#include +#include +#include + +#include + +void dump(struct udev_device *d) +{ + const char *s = udev_device_get_syspath(d); + + printf("%s\n", s); + + udev_device_unref(d); +} + +void main() +{ + while (1) + { + struct udev_device *lo = udev_device_new_from_device_id(NULL, "n1"); + dump(udev_device_ref(lo)); + lo = udev_device_unref(lo); + } +} diff --git a/exts/libudev/tests/test_libudev_device_thread.c b/exts/libudev/tests/test_libudev_device_thread.c new file mode 100644 index 00000000..044e6eb4 --- /dev/null +++ b/exts/libudev/tests/test_libudev_device_thread.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include +#include + +#include + +#define handle_error_errno(error, msg) \ + ({ \ + errno = abs(error); \ + perror(msg); \ + EXIT_FAILURE; \ + }) + +static void *thread(void *p) +{ + struct udev_device **d = p; + + *d = udev_device_unref(*d); + + return NULL; +} + +int main(int argc, char *argv[]) +{ + struct udev_device *loopback; + // struct udev_list_entry *entry, *e; + pthread_t t; + int r; + + // loopback = udev_device_new_from_syspath(NULL, "/sys/class/net/lo"); + loopback = udev_device_new_from_device_id(NULL, "n1"); + if (!loopback) + return handle_error_errno(errno, "Failed to create loopback device object"); + + // entry = udev_device_get_properties_list_entry(loopback); + // udev_list_entry_foreach(e, entry) + // printf("%s=%s\n", udev_list_entry_get_name(e), udev_list_entry_get_value(e)); + + const char *syspath = udev_device_get_syspath(loopback); + printf("SYSPATH=%s\n", syspath); + + r = pthread_create(&t, NULL, thread, &loopback); + if (r != 0) + return handle_error_errno(r, "Failed to create thread"); + + r = pthread_join(t, NULL); + if (r != 0) + return handle_error_errno(r, "Failed to wait thread finished"); + + if (loopback) + return handle_error_errno(r, "loopback device is not unref()ed"); + + return 0; +} diff --git a/exts/libudev_macro/Cargo.toml b/exts/libudev_macro/Cargo.toml new file mode 100644 index 00000000..284be8f4 --- /dev/null +++ b/exts/libudev_macro/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "libudev_macro" +version = "0.5.1" +edition = "2021" + +[lib] +name = "libudev_macro" +path = "src/lib.rs" +proc-macro = true + +[dependencies] +syn = { version = "2.0.39", features = ["full", "fold"] } +quote = "1.0" +proc-macro2 = "1.0" diff --git a/exts/libudev_macro/src/lib.rs b/exts/libudev_macro/src/lib.rs new file mode 100644 index 00000000..b129403b --- /dev/null +++ b/exts/libudev_macro/src/lib.rs @@ -0,0 +1,67 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +//! This crate provides a procedual macro RefUnref to derive ref and unref methods +//! for a Rc wrapped raw pointer. + +use quote::quote; +use syn::spanned::Spanned; +use syn::{parse_macro_input, DeriveInput}; + +#[proc_macro_derive(RefUnref)] +/// Gerenrate ref and unref methods. +/// +/// The input parameter is a raw pointer. +/// It will be recovered into Rust Rc and do Rc clone or drop. +pub fn derive_ref_unref(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + /* Generate an AST */ + let input = parse_macro_input!(input as DeriveInput); + + // Used in the quasi-quotation below as `#name`. + let name = &input.ident; + + let fn_ref = syn::Ident::new(&format!("{}_ref", quote!(#name)), input.span()); + let fn_unref = syn::Ident::new(&format!("{}_unref", quote!(#name)), input.span()); + + let expanded = quote! { + #[no_mangle] + /// Recover Rc from the raw pointer and do Rc clone. + /// + /// Return the raw pointer of the cloned Rc. + pub extern "C" fn #fn_ref(#name: *mut #name) -> *mut #name { + if #name.is_null() { + return std::ptr::null_mut(); + } + + let recover = unsafe { Rc::from_raw(#name) }; + let ret = recover.clone(); + let _ = Rc::into_raw(recover); + Rc::into_raw(ret) as *mut #name + } + + #[no_mangle] + /// Recover Rc from the raw pointer and do Rc drop. + /// + /// Return a null pointer. + pub extern "C" fn #fn_unref(#name: *mut #name) -> *mut #name { + if #name.is_null() { + return std::ptr::null_mut(); + } + + let _ = unsafe { Rc::from_raw(#name) }; + std::ptr::null_mut() + } + }; + + // Hand the output tokens back to the compiler. + proc_macro::TokenStream::from(expanded) +} -- Gitee From e7300d8c45af0cb5014abfd63426acf9e4f5a5fc Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sun, 3 Dec 2023 05:27:23 +0800 Subject: [PATCH 02/48] refactor(device): use C representation of DeviceAction enum Use C representation of DeviceAction enum to change it to integer. --- libs/device/src/device_action.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/device/src/device_action.rs b/libs/device/src/device_action.rs index 2438512d..d547c0fa 100644 --- a/libs/device/src/device_action.rs +++ b/libs/device/src/device_action.rs @@ -19,6 +19,7 @@ use nix::errno::Errno; /// device action based on kobject from kernel #[allow(missing_docs)] +#[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DeviceAction { Add, -- Gitee From 6ba3ba98d004746d1c6c453df895d3b9bb5471bf Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sun, 3 Dec 2023 05:30:59 +0800 Subject: [PATCH 03/48] feature(libudev): support some new ABIs Involved ABIs are as following: udev_device_has_tag udev_device_has_current_tag udev_device_get_action udev_device_get_devnode udev_device_get_devnum udev_device_get_devpath udev_device_get_devtype udev_device_get_driver --- Cargo.lock | 78 +++++- exts/libudev/Cargo.toml | 3 + exts/libudev/src/libudev_device.rs | 371 ++++++++++++++++++++++++++++- 3 files changed, 439 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed4d84a5..ffb523d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,13 +469,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1012,7 +1011,10 @@ name = "libudev" version = "0.5.1" dependencies = [ "device", + "errno 0.3.8", + "libc", "libudev_macro", + "nix 0.24.3", ] [[package]] @@ -1638,7 +1640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags", - "errno 0.3.2", + "errno 0.3.8", "io-lifetimes", "libc", "linux-raw-sys", @@ -2265,6 +2267,15 @@ dependencies = [ "windows-targets 0.48.1", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -2295,6 +2306,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -2307,6 +2333,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -2319,6 +2351,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -2331,6 +2369,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -2343,6 +2387,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -2355,6 +2405,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -2367,6 +2423,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -2379,6 +2441,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "xattr" version = "0.2.3" diff --git a/exts/libudev/Cargo.toml b/exts/libudev/Cargo.toml index 678aa39d..bbb11fc8 100644 --- a/exts/libudev/Cargo.toml +++ b/exts/libudev/Cargo.toml @@ -11,3 +11,6 @@ crate-type = ["cdylib"] [dependencies] device = { path = "../../libs/device", default-features = false } libudev_macro = { path = "../libudev_macro" } +libc = { default-features = false, version = "0.2.140" } +nix = { default-features = false, version = "0.24" } +errno = { version = "0.3.8", default-features = false } diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index e7f14b3a..e2291a40 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -25,13 +25,32 @@ use std::rc::Rc; use crate::libudev::*; use libudev_macro::RefUnref; +const ACTION_CNT: usize = 8; + +static ACTION_STRING_TABLE: [&str; ACTION_CNT] = [ + "add\0", + "remove\0", + "change\0", + "move\0", + "online\0", + "offline\0", + "bind\0", + "unbind\0", +]; + #[repr(C)] #[derive(Debug, Clone, RefUnref)] /// udev_device pub struct udev_device { pub(crate) udev: *mut udev, pub(crate) device: Rc, + + /* Cache CString in udev_device memory. */ pub(crate) syspath: CString, + pub(crate) devnode: CString, + pub(crate) devpath: CString, + pub(crate) devtype: CString, + pub(crate) driver: CString, } impl Drop for udev_device { @@ -47,7 +66,11 @@ impl udev_device { Self { udev, device: Rc::new(device), - syspath: CString::new("").unwrap(), + syspath: CString::default(), + devnode: CString::default(), + devpath: CString::default(), + devtype: CString::default(), + driver: CString::default(), } } } @@ -164,17 +187,196 @@ pub extern "C" fn udev_device_get_syspath( udev_device_mut.syspath.as_ptr() } +#[no_mangle] +/// udev_device_has_tag +pub extern "C" fn udev_device_has_tag( + udev_device: *mut udev_device, + tag: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap(); + + match udev_device_mut.device.has_tag(tag) { + Ok(true) => 1, + _ => 0, + } +} + +#[no_mangle] +/// udev_device_has_current_tag +pub extern "C" fn udev_device_has_current_tag( + udev_device: *mut udev_device, + tag: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap(); + + match udev_device_mut.device.has_current_tag(tag) { + Ok(true) => 1, + _ => 0, + } +} + +#[no_mangle] +/// udev_device_get_action +pub extern "C" fn udev_device_get_action( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if let Ok(action) = udev_device_mut.device.get_action() { + let ret = ACTION_STRING_TABLE[action as usize]; + return ret.as_ptr() as *const ::std::os::raw::c_char; + } + + std::ptr::null() +} + +#[no_mangle] +/// udev_device_get_devnode +pub extern "C" fn udev_device_get_devnode( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .devnode + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.devnode.as_ptr(); + } + + if let Ok(devnode) = udev_device_mut.device.get_devname() { + udev_device_mut.devnode = CString::new(devnode).unwrap(); + return udev_device_mut.devnode.as_ptr(); + } + + std::ptr::null() +} + +#[no_mangle] +/// udev_device_get_devnum +pub extern "C" fn udev_device_get_devnum(udev_device: *mut udev_device) -> dev_t { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + match udev_device_mut.device.get_devnum() { + Ok(n) => n, + Err(e) => { + if !e.is_errno(nix::Error::ENOENT) { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + } + + 0 + } + } +} + +#[no_mangle] +/// udev_device_get_devpath +pub extern "C" fn udev_device_get_devpath( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .devpath + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.devpath.as_ptr(); + } + + match udev_device_mut.device.get_devpath() { + Ok(devpath) => { + udev_device_mut.devpath = CString::new(devpath).unwrap(); + udev_device_mut.devpath.as_ptr() + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null() + } + } +} + +#[no_mangle] +/// udev_device_get_devtype +pub extern "C" fn udev_device_get_devtype( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .devtype + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.devtype.as_ptr(); + } + + match udev_device_mut.device.get_devtype() { + Ok(devtype) => { + udev_device_mut.devtype = CString::new(devtype).unwrap(); + udev_device_mut.devtype.as_ptr() + } + Err(e) => { + if !e.is_errno(nix::Error::ENOENT) { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + } + + std::ptr::null() + } + } +} + +#[no_mangle] +/// udev_device_get_driver +pub extern "C" fn udev_device_get_driver( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .driver + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.driver.as_ptr(); + } + + match udev_device_mut.device.get_driver() { + Ok(driver) => { + udev_device_mut.driver = CString::new(driver).unwrap(); + udev_device_mut.driver.as_ptr() + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null() + } + } +} + #[cfg(test)] mod test { - use std::cell::RefCell; + use std::{cell::RefCell, intrinsics::transmute}; use super::*; use device::device_enumerator::*; - type RCDevice = Rc>; + type RD = Rc>; pub type Result = std::result::Result<(), device::error::Error>; - fn test_udev_device_new_from_devnum(device: RCDevice) -> Result { + fn test_udev_device_new_from_devnum(device: RD) -> Result { let devnum = device.borrow().get_devnum()?; let t = if &device.borrow().get_subsystem().unwrap() == "block" { @@ -198,7 +400,7 @@ mod test { Ok(()) } - fn test_udev_device_new_from_subsystem_sysname(device: RCDevice) -> Result { + fn test_udev_device_new_from_subsystem_sysname(device: RD) -> Result { let subsystem = device.borrow().get_subsystem().unwrap(); let sysname = device.borrow().get_sysname().unwrap(); @@ -229,7 +431,7 @@ mod test { Ok(()) } - fn test_udev_device_new_from_device_id(device: RCDevice) -> Result { + fn test_udev_device_new_from_device_id(device: RD) -> Result { let id = device.borrow().get_device_id().unwrap(); let c_id = CString::new(id).unwrap(); let udev_device = udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()); @@ -245,7 +447,7 @@ mod test { Ok(()) } - fn test_udev_device_new_from_syspath(device: RCDevice) -> Result { + fn test_udev_device_new_from_syspath(device: RD) -> Result { let syspath = device.borrow().get_syspath().unwrap(); let c_syspath = CString::new(syspath).unwrap(); let udev_device = udev_device_new_from_syspath(std::ptr::null_mut(), c_syspath.as_ptr()); @@ -258,8 +460,140 @@ mod test { Ok(()) } + fn from_rd(device: RD) -> *mut udev_device { + let id = device.borrow().get_device_id().unwrap(); + let c_id = CString::new(id).unwrap(); + udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()) + } + + fn test_udev_device_has_tag(device: RD) -> Result { + let _ = device.borrow_mut().read_db_internal(true); + device + .borrow_mut() + .add_tag("test_udev_device_has_tag", true); + device.borrow_mut().update_db()?; + + let udev_device = from_rd(device.clone()); + + assert!( + udev_device_has_tag( + udev_device, + "test_udev_device_has_tag\0".as_ptr() as *const i8 + ) > 0 + ); + + assert!( + udev_device_has_current_tag( + udev_device, + "test_udev_device_has_tag\0".as_ptr() as *const i8 + ) > 0 + ); + + udev_device_unref(udev_device); + + device + .borrow_mut() + .all_tags + .borrow_mut() + .remove("test_udev_device_has_tag"); + device.borrow_mut().remove_tag("test_udev_device_has_tag"); + device.borrow_mut().update_db()?; + + Ok(()) + } + + fn test_udev_device_get_action(dev: RD) -> Result { + let udev_device = from_rd(dev); + + let udev_device_mut: &mut udev_device = unsafe { transmute(&mut *udev_device) }; + + udev_device_mut + .device + .set_action_from_string("change") + .unwrap(); + + let ptr = udev_device_get_action(udev_device); + + let action = unsafe { CStr::from_ptr(ptr) }; + + assert_eq!(action.to_str().unwrap(), "change"); + + udev_device_unref(udev_device); + + Ok(()) + } + + fn test_udev_device_get_devnode(dev: RD) -> Result { + let udev_device = from_rd(dev.clone()); + + let devnode = dev.borrow().get_devname()?; + + let ptr = udev_device_get_devnode(udev_device); + + assert_eq!(unsafe { CStr::from_ptr(ptr) }.to_str().unwrap(), &devnode); + + udev_device_unref(udev_device); + + Ok(()) + } + + fn test_udev_device_get_devnum(dev: RD) -> Result { + let udev_device = from_rd(dev.clone()); + + let devnum = dev.borrow().get_devnum()?; + + assert_eq!(udev_device_get_devnum(udev_device), devnum); + + Ok(()) + } + + fn test_udev_device_get_devpath(dev: RD) -> Result { + let udev_device = from_rd(dev.clone()); + + let devpath = dev.borrow().get_devpath()?; + + assert_eq!( + unsafe { CStr::from_ptr(udev_device_get_devpath(udev_device)) } + .to_str() + .unwrap(), + &devpath + ); + + Ok(()) + } + + fn test_udev_device_get_devtype(dev: RD) -> Result { + let ud = from_rd(dev.clone()); + + let devtype = dev.borrow().get_devtype()?; + + assert_eq!( + unsafe { CStr::from_ptr(udev_device_get_devtype(ud)) } + .to_str() + .unwrap(), + &devtype + ); + + Ok(()) + } + + fn test_udev_device_get_driver(dev: RD) -> Result { + let ud = from_rd(dev.clone()); + + let driver = dev.borrow().get_driver()?; + + assert_eq!( + unsafe { CStr::from_ptr(udev_device_get_driver(ud)) } + .to_str() + .unwrap(), + &driver + ); + + Ok(()) + } + #[test] - fn test_udev_device_new() { + fn test_udev_device_ut() { let mut e = DeviceEnumerator::new(); e.set_enumerator_type(DeviceEnumerationType::All); @@ -268,6 +602,27 @@ mod test { let _ = test_udev_device_new_from_devnum(dev.clone()); let _ = test_udev_device_new_from_subsystem_sysname(dev.clone()); let _ = test_udev_device_new_from_syspath(dev.clone()); + let _ = test_udev_device_get_devnode(dev.clone()); + let _ = test_udev_device_get_devnum(dev.clone()); + let _ = test_udev_device_get_devpath(dev.clone()); + let _ = test_udev_device_get_devtype(dev.clone()); + let _ = test_udev_device_get_driver(dev.clone()); } } + + #[test] + fn test_udev_device_has_tag_ut() { + let dev = Rc::new(RefCell::new( + Device::from_subsystem_sysname("net", "lo").unwrap(), + )); + let _ = test_udev_device_has_tag(dev); + } + + #[test] + fn test_udev_device_get_action_ut() { + let dev = Rc::new(RefCell::new( + Device::from_subsystem_sysname("net", "lo").unwrap(), + )); + let _ = test_udev_device_get_action(dev); + } } -- Gitee From a024db85c1a568eac4c9a3a0fc43d6c68b73d57a Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Wed, 6 Dec 2023 17:28:02 +0800 Subject: [PATCH 04/48] feature(libudev): support several ABIs Include: udev_device_get_sysname udev_device_get_subsystem udev_device_get_seqnum udev_device_get_property_value --- exts/libudev/src/libudev_device.rs | 181 ++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 2 deletions(-) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index e2291a40..9a17e90f 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -17,6 +17,7 @@ #![allow(clippy::not_unsafe_ptr_arg_deref)] use device::Device; +use std::collections::HashMap; use std::ffi::{CStr, CString}; use std::mem; use std::os::linux::raw::dev_t; @@ -51,6 +52,10 @@ pub struct udev_device { pub(crate) devpath: CString, pub(crate) devtype: CString, pub(crate) driver: CString, + pub(crate) sysname: CString, + pub(crate) subsystem: CString, + + pub(crate) properties: HashMap, } impl Drop for udev_device { @@ -71,6 +76,9 @@ impl udev_device { devpath: CString::default(), devtype: CString::default(), driver: CString::default(), + sysname: CString::default(), + subsystem: CString::default(), + properties: HashMap::default(), } } } @@ -366,6 +374,108 @@ pub extern "C" fn udev_device_get_driver( } } +#[no_mangle] +/// udev_device_get_sysname +pub extern "C" fn udev_device_get_sysname( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .sysname + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.sysname.as_ptr(); + } + + match udev_device_mut.device.get_sysname() { + Ok(sysname) => { + udev_device_mut.sysname = CString::new(sysname).unwrap(); + udev_device_mut.sysname.as_ptr() + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null() + } + } +} + +#[no_mangle] +/// udev_device_get_subsystem +pub extern "C" fn udev_device_get_subsystem( + udev_device: *mut udev_device, +) -> *const ::std::os::raw::c_char { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !udev_device_mut + .subsystem + .as_c_str() + .to_str() + .unwrap_or_default() + .is_empty() + { + return udev_device_mut.subsystem.as_ptr(); + } + + match udev_device_mut.device.get_subsystem() { + Ok(subsystem) => { + udev_device_mut.subsystem = CString::new(subsystem).unwrap(); + udev_device_mut.subsystem.as_ptr() + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null() + } + } +} + +#[no_mangle] +/// udev_device_get_seqnum +pub extern "C" fn udev_device_get_seqnum( + udev_device: *mut udev_device, +) -> ::std::os::raw::c_ulonglong { + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + udev_device_mut.device.get_seqnum().unwrap_or_default() as ::std::os::raw::c_ulonglong +} + +#[no_mangle] +/// udev_device_get_property_value +pub extern "C" fn udev_device_get_property_value( + udev_device: *mut udev_device, + key: *const ::std::os::raw::c_char, +) -> *const ::std::os::raw::c_char { + let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap_or_default(); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if udev_device_mut + .properties + .contains_key(&CString::new(key).unwrap()) + { + return udev_device_mut + .properties + .get(&CString::new(key).unwrap()) + .unwrap() + .as_ptr(); + } + + match udev_device_mut.device.get_property_value(key) { + Ok(v) => { + let key_c = CString::new(key).unwrap(); + let value_c = CString::new(v).unwrap(); + udev_device_mut.properties.insert(key_c.clone(), value_c); + udev_device_mut.properties.get(&key_c).unwrap().as_ptr() + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null() + } + } +} + #[cfg(test)] mod test { use std::{cell::RefCell, intrinsics::transmute}; @@ -592,6 +702,69 @@ mod test { Ok(()) } + fn test_udev_device_get_sysname(dev: RD) -> Result { + let ud = from_rd(dev.clone()); + + let sysname = dev.borrow().get_sysname()?; + + assert_eq!( + unsafe { CStr::from_ptr(udev_device_get_sysname(ud)) } + .to_str() + .unwrap(), + &sysname + ); + + Ok(()) + } + + fn test_udev_device_get_subsystem(dev: RD) -> Result { + let ud = from_rd(dev.clone()); + + let subsystem = dev.borrow().get_subsystem()?; + + assert_eq!( + unsafe { CStr::from_ptr(udev_device_get_subsystem(ud)) } + .to_str() + .unwrap(), + &subsystem + ); + + Ok(()) + } + + fn test_udev_device_get_seqnum(dev: RD) -> Result { + let ud = from_rd(dev); + + let ud_mut: &mut udev_device = unsafe { transmute(&mut *ud) }; + + ud_mut.device.set_seqnum(10000); + + assert_eq!(udev_device_get_seqnum(ud), 10000); + + Ok(()) + } + + fn test_udev_device_get_property_value(dev: RD) -> Result { + let ud = from_rd(dev); + let ud_mut: &mut udev_device = unsafe { transmute(&mut *ud) }; + ud_mut.device.sealed.replace(true); + ud_mut.device.add_property("hello", "world").unwrap(); + + assert_eq!( + unsafe { + CStr::from_ptr(udev_device_get_property_value( + ud, + "hello\0".as_ptr() as *const i8, + )) + } + .to_str() + .unwrap(), + "world" + ); + + Ok(()) + } + #[test] fn test_udev_device_ut() { let mut e = DeviceEnumerator::new(); @@ -607,6 +780,8 @@ mod test { let _ = test_udev_device_get_devpath(dev.clone()); let _ = test_udev_device_get_devtype(dev.clone()); let _ = test_udev_device_get_driver(dev.clone()); + let _ = test_udev_device_get_sysname(dev.clone()); + let _ = test_udev_device_get_subsystem(dev.clone()); } } @@ -619,10 +794,12 @@ mod test { } #[test] - fn test_udev_device_get_action_ut() { + fn test_udev_device_fake_from_monitor_ut() { let dev = Rc::new(RefCell::new( Device::from_subsystem_sysname("net", "lo").unwrap(), )); - let _ = test_udev_device_get_action(dev); + let _ = test_udev_device_get_action(dev.clone()); + let _ = test_udev_device_get_seqnum(dev.clone()); + let _ = test_udev_device_get_property_value(dev); } } -- Gitee From 018b74be955437f71738846a901c1933322ac6f9 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Thu, 7 Dec 2023 03:33:40 +0800 Subject: [PATCH 05/48] refactor: use Rc to contain Device object instead of Rc RefCell Device struct has used RefCell to encapsulate inner fields, thus it is unnecessary to wrapper the Device object with RefCell again. In addition, previous get_parent method of Device will return Rc>, which has conflict with the implementation of libudev as it requires the raw pointer inside Rc. To deal with these two problems, we decide to use Rc across the project uniformly. --- exts/devmaster/src/bin/devctl/subcmds/info.rs | 6 +- .../src/bin/devctl/subcmds/test_builtin.rs | 11 +- .../src/bin/devctl/subcmds/trigger.rs | 5 +- exts/devmaster/src/lib/builtin/blkid.rs | 9 +- exts/devmaster/src/lib/builtin/example.rs | 7 +- exts/devmaster/src/lib/builtin/hwdb.rs | 16 +- exts/devmaster/src/lib/builtin/input_id.rs | 67 ++-- exts/devmaster/src/lib/builtin/keyboard.rs | 20 +- exts/devmaster/src/lib/builtin/kmod.rs | 1 - exts/devmaster/src/lib/builtin/mod.rs | 4 +- exts/devmaster/src/lib/builtin/net_id.rs | 319 ++++++++---------- .../src/lib/builtin/net_setup_link.rs | 51 ++- exts/devmaster/src/lib/builtin/path_id.rs | 208 ++++-------- exts/devmaster/src/lib/builtin/usb_id.rs | 58 ++-- exts/devmaster/src/lib/config/netif_conf.rs | 14 +- exts/devmaster/src/lib/error.rs | 20 +- .../src/lib/framework/worker_manager.rs | 4 +- exts/devmaster/src/lib/rules/exec_mgr.rs | 306 +++++++---------- exts/devmaster/src/lib/rules/exec_unit.rs | 174 +++++----- exts/devmaster/src/lib/rules/node.rs | 114 +++---- exts/devmaster/src/lib/utils/commons.rs | 30 +- exts/devmaster/src/lib/utils/macros.rs | 2 +- exts/devmaster/src/lib/utils/spawn.rs | 5 +- exts/libudev/src/libudev_device.rs | 67 ++-- libs/device/examples/enumerator.rs | 4 +- libs/device/src/device.rs | 40 +-- libs/device/src/device_enumerator.rs | 94 +++--- 27 files changed, 677 insertions(+), 979 deletions(-) diff --git a/exts/devmaster/src/bin/devctl/subcmds/info.rs b/exts/devmaster/src/bin/devctl/subcmds/info.rs index 0457dc08..1129fc6a 100644 --- a/exts/devmaster/src/bin/devctl/subcmds/info.rs +++ b/exts/devmaster/src/bin/devctl/subcmds/info.rs @@ -284,9 +284,9 @@ fn print_device_chain(device: Device) -> Result<()> { let mut child = device; while let Ok(parent) = child.get_parent() { - print_all_attributes(&parent.borrow(), true)?; + print_all_attributes(&parent, true)?; - child = parent.borrow().shallow_clone().unwrap(); + child = parent.shallow_clone().unwrap(); } Ok(()) @@ -489,7 +489,7 @@ fn export_devices() -> Result<()> { } for device in e.iter() { - print_record(device.borrow().shallow_clone().unwrap(), ""); + print_record(device.shallow_clone().unwrap(), ""); } Ok(()) diff --git a/exts/devmaster/src/bin/devctl/subcmds/test_builtin.rs b/exts/devmaster/src/bin/devctl/subcmds/test_builtin.rs index 8a6f09bf..b1456e9e 100644 --- a/exts/devmaster/src/bin/devctl/subcmds/test_builtin.rs +++ b/exts/devmaster/src/bin/devctl/subcmds/test_builtin.rs @@ -18,8 +18,8 @@ use libdevmaster::builtin::{BuiltinCommand, BuiltinManager}; use libdevmaster::config::devmaster_conf::{DevmasterConfig, DEFAULT_CONFIG}; use libdevmaster::framework::devmaster::Cache; use libdevmaster::rules::exec_unit::ExecuteUnit; +use std::rc::Rc; use std::sync::{Arc, RwLock}; -use std::{cell::RefCell, rc::Rc}; /// test builtin command on processing a device /// Commands: @@ -52,15 +52,12 @@ pub fn subcommand_test_builtin(action: Option, builtin_cmd: String, devi let mgr = BuiltinManager::new(cache); mgr.init(); - let d = Rc::new(RefCell::new(match Device::from_path(&device) { + let d = Rc::new(match Device::from_path(&device) { Ok(ret) => ret, Err(_) => Device::from_path(&format!("/sys{}", device)).expect("invalid device path."), - })); + }); - if let Err(e) = d - .borrow() - .add_property("ACTION", &action.unwrap_or_else(|| "change".to_string())) - { + if let Err(e) = d.add_property("ACTION", &action.unwrap_or_else(|| "change".to_string())) { eprintln!("{:?}", e); } diff --git a/exts/devmaster/src/bin/devctl/subcmds/trigger.rs b/exts/devmaster/src/bin/devctl/subcmds/trigger.rs index 74a9e77e..82a31c68 100644 --- a/exts/devmaster/src/bin/devctl/subcmds/trigger.rs +++ b/exts/devmaster/src/bin/devctl/subcmds/trigger.rs @@ -263,7 +263,7 @@ impl TriggerArgs { let mut uuids = HashSet::new(); let mut ret = Ok(HashSet::::new()); for device in enumerator.iter() { - let syspath = match device.borrow().get_syspath() { + let syspath = match device.get_syspath() { Ok(syspath) => syspath, Err(_) => continue, }; @@ -275,7 +275,6 @@ impl TriggerArgs { } let id = match device - .borrow() .trigger_with_uuid(action, (self.uuid || self.settle) && uuid_supported != 0) { Ok(id) => id, @@ -288,7 +287,7 @@ impl TriggerArgs { /* If we specified a UUID because of the settling logic, and we got EINVAL this might * be caused by an old kernel which doesn't know the UUID logic (pre-4.13). Let's try * if it works without the UUID logic then. */ - if let Err(e) = device.borrow().trigger(action) { + if let Err(e) = device.trigger(action) { if e.get_errno() != nix::Error::EINVAL { /* dropping the uuid stuff changed the return code, * hence don't bother next time */ diff --git a/exts/devmaster/src/lib/builtin/blkid.rs b/exts/devmaster/src/lib/builtin/blkid.rs index 6787f429..d782cab8 100644 --- a/exts/devmaster/src/lib/builtin/blkid.rs +++ b/exts/devmaster/src/lib/builtin/blkid.rs @@ -31,7 +31,6 @@ use blkid_rs::BlkidUsageFlags; use clap::Parser; use device::Device; use nix::fcntl::OFlag; -use std::cell::RefCell; use std::fs::File; use std::io::Read; use std::os::unix::prelude::AsRawFd; @@ -92,7 +91,7 @@ macro_rules! op_command_err { impl Blkid { fn print_property( &self, - device: Rc>, + device: Rc, name: &str, value: &str, test: bool, @@ -379,13 +378,11 @@ impl Builtin for Blkid { ) -> Result { let device = exec_unit.get_device(); let subsystem = device - .borrow() .get_subsystem() .map_err(op_command_err!("device get_subsystem error"))?; if subsystem != *"block" { let syspath = device - .borrow() .get_syspath() .map_err(op_command_err!("device get_syspath error"))?; log::warn!("blkid can only probe block devices, ignoring {}", syspath); @@ -426,7 +423,6 @@ impl Builtin for Blkid { } let file = device - .borrow() .open(OFlag::O_CLOEXEC | OFlag::O_RDONLY | OFlag::O_NONBLOCK) .map_err(op_command_err!("device open error"))?; @@ -436,7 +432,6 @@ impl Builtin for Blkid { self.probe_superblocks(&mut probe)?; let root_partition = device - .borrow() .get_property_value("ID_PART_GPT_AUTO_ROOT_UUID") .map_or(String::new(), |e| e); @@ -523,7 +518,7 @@ mod test { let file_name = String::from(entry.file_name().to_str().unwrap()); let dev_path = format!("/dev/{}", file_name); log::info!("{} device probe:", dev_path); - let device = Rc::new(RefCell::new(Device::from_devname(&dev_path).unwrap())); + let device = Rc::new(Device::from_devname(&dev_path).unwrap()); let exec_unit = ExecuteUnit::new(device); builtin diff --git a/exts/devmaster/src/lib/builtin/example.rs b/exts/devmaster/src/lib/builtin/example.rs index 51ca7c7d..5ac56b6c 100644 --- a/exts/devmaster/src/lib/builtin/example.rs +++ b/exts/devmaster/src/lib/builtin/example.rs @@ -32,7 +32,7 @@ impl Builtin for Example { ) -> Result { let device = exec_unit.get_device(); - let syspath = device.borrow().get_syspath().context(DeviceSnafu)?; + let syspath = device.get_syspath().context(DeviceSnafu)?; self.add_property(device, test, "ID_EXAMPLE_SYSPATH", &syspath) .map_err(|_| Error::BuiltinCommandError { @@ -81,10 +81,7 @@ mod tests { let builtin = Example {}; builtin.cmd(&exec_unit, 0, vec![], true).unwrap(); - device - .borrow() - .get_property_value("ID_EXAMPLE_SYSPATH") - .unwrap(); + device.get_property_value("ID_EXAMPLE_SYSPATH").unwrap(); } } } diff --git a/exts/devmaster/src/lib/builtin/hwdb.rs b/exts/devmaster/src/lib/builtin/hwdb.rs index 0b797874..5ba996b2 100644 --- a/exts/devmaster/src/lib/builtin/hwdb.rs +++ b/exts/devmaster/src/lib/builtin/hwdb.rs @@ -63,7 +63,7 @@ impl Hwdb { fn lookup( &self, - dev: Rc>, + dev: Rc, prefix: &Option, modalias: String, filter: &Option, @@ -97,7 +97,7 @@ impl Hwdb { } } - if let Err(e) = dev.borrow_mut().add_property(key, value) { + if let Err(e) = dev.add_property(key, value) { return Err(e.get_errno()); } @@ -112,7 +112,7 @@ impl Hwdb { fn search( &self, - dev: Rc>, + dev: Rc, srcdev: Option, subsystem: &Option, prefix: Option, @@ -123,7 +123,7 @@ impl Hwdb { let mut last = false; let mut src_dev = match srcdev { Some(d) => d, - None => dev.borrow_mut().shallow_clone().unwrap(), + None => dev.shallow_clone().unwrap(), }; loop { @@ -131,7 +131,7 @@ impl Hwdb { Ok(str_subsystem) => str_subsystem, Err(_) => { src_dev = match src_dev.get_parent() { - Ok(d) => d.borrow_mut().shallow_clone().unwrap(), + Ok(d) => d.shallow_clone().unwrap(), Err(_) => break, }; continue; @@ -142,7 +142,7 @@ impl Hwdb { if let Some(str_subsystem) = subsystem { if &dsubsys != str_subsystem { src_dev = match src_dev.get_parent() { - Ok(d) => d.borrow_mut().shallow_clone().unwrap(), + Ok(d) => d.shallow_clone().unwrap(), Err(_) => break, }; continue; @@ -170,7 +170,7 @@ impl Hwdb { if modalias.is_empty() { src_dev = match src_dev.get_parent() { - Ok(d) => d.borrow_mut().shallow_clone().unwrap(), + Ok(d) => d.shallow_clone().unwrap(), Err(_) => break, }; continue; @@ -189,7 +189,7 @@ impl Hwdb { } src_dev = match src_dev.get_parent() { - Ok(d) => d.borrow_mut().shallow_clone().unwrap(), + Ok(d) => d.shallow_clone().unwrap(), Err(_) => break, }; } diff --git a/exts/devmaster/src/lib/builtin/input_id.rs b/exts/devmaster/src/lib/builtin/input_id.rs index 77313f43..90d096d7 100644 --- a/exts/devmaster/src/lib/builtin/input_id.rs +++ b/exts/devmaster/src/lib/builtin/input_id.rs @@ -23,7 +23,6 @@ use input_event_codes; use ioctls::{eviocgabs, input_absinfo}; use libc::input_id; use nix::fcntl::OFlag; -use std::cell::RefCell; use std::os::unix::prelude::AsRawFd; use std::rc::Rc; @@ -118,7 +117,6 @@ impl Builtin for InputId { if pdev .as_ref() .unwrap() - .borrow() .get_sysattr_value("capabilities/ev") .is_ok() { @@ -127,7 +125,6 @@ impl Builtin for InputId { let tmp_dev = match pdev .unwrap() - .borrow() .get_parent_with_subsystem_devtype("input", None) { Ok(dev) => Option::Some(dev), @@ -201,7 +198,7 @@ impl Builtin for InputId { } } - let sysname = device.borrow().get_sysname().unwrap_or_default(); + let sysname = device.get_sysname().unwrap_or_default(); if sysname.starts_with("event") { self.extract_info(device, test); @@ -233,16 +230,16 @@ impl Builtin for InputId { fn add_property( &self, - device: Rc>, + device: Rc, test: bool, key: &str, value: &str, ) -> Result<(), crate::error::Error> { - device.borrow().add_property(key, value).map_err(|e| { - crate::error::Error::BuiltinCommandError { + device + .add_property(key, value) + .map_err(|e| crate::error::Error::BuiltinCommandError { msg: format!("Failed to add property '{}'='{}': ({})", key, value, e), - } - })?; + })?; if test { println!("{}={}", key, value); @@ -253,7 +250,7 @@ impl Builtin for InputId { } impl InputId { - fn get_input_id(&self, dev: Rc>) -> input_id { + fn get_input_id(&self, dev: Rc) -> input_id { let mut id = input_id { bustype: u16::default(), vendor: u16::default(), @@ -261,19 +258,19 @@ impl InputId { version: u16::default(), }; - if let Ok(v) = dev.borrow().get_sysattr_value("id/bustype") { + if let Ok(v) = dev.get_sysattr_value("id/bustype") { id.bustype = u16::from_str_radix(&v, 16).unwrap(); } - if let Ok(v) = dev.borrow().get_sysattr_value("id/vendor") { + if let Ok(v) = dev.get_sysattr_value("id/vendor") { id.vendor = u16::from_str_radix(&v, 16).unwrap(); } - if let Ok(v) = dev.borrow().get_sysattr_value("id/product") { + if let Ok(v) = dev.get_sysattr_value("id/product") { id.product = u16::from_str_radix(&v, 16).unwrap(); } - if let Ok(v) = dev.borrow().get_sysattr_value("id/version") { + if let Ok(v) = dev.get_sysattr_value("id/version") { id.version = u16::from_str_radix(&v, 16).unwrap(); } @@ -282,17 +279,17 @@ impl InputId { fn get_cap_mask( &self, - dev: Rc>, + dev: Rc, attr: &str, bitmask_size: usize, bitmask: &mut [u64], test: bool, ) { - let text = dev.borrow().get_sysattr_value(attr).unwrap_or_default(); + let text = dev.get_sysattr_value(attr).unwrap_or_default(); log_dev!( debug, - dev.borrow(), + dev, format!("{} raw kernel attribute: {}", attr, text) ); @@ -301,7 +298,7 @@ impl InputId { Err(_) => { log_dev!( debug, - dev.borrow(), + dev, format!("Ignoring {} block which failed to parse", attr) ); continue; @@ -314,7 +311,7 @@ impl InputId { } else { log_dev!( debug, - dev.borrow(), + dev, format!( "Ignoring {} block {:X} which is larger than maximum size", attr, val @@ -324,7 +321,7 @@ impl InputId { } if test { - log_dev!(debug, dev.borrow(), format!("{} decoded bit map:", attr)); + log_dev!(debug, dev, format!("{} decoded bit map:", attr)); let mut val = bitmask_size / std::mem::size_of::(); while val > 0 && bitmask[val - 1] == 0 { @@ -341,13 +338,13 @@ impl InputId { if std::mem::size_of::() == 4 { log_dev!( debug, - dev.borrow(), + dev, format!(" bit {:4}: {:08X}", j * bits_per_long!(), bit) ); } else { log_dev!( debug, - dev.borrow(), + dev, format!(" bit {:4}: {:016X}", j * bits_per_long!(), bit) ); } @@ -358,7 +355,7 @@ impl InputId { #[allow(clippy::too_many_arguments)] fn test_pointer( &self, - dev: Rc>, + dev: Rc, id: &input_id, bitmasks: &mut Bitmasks, test: bool, @@ -545,7 +542,7 @@ impl InputId { } if num_well_known_keys >= 4 || num_joystick_buttons + num_joystick_axes < 2 { - log_dev!(debug, dev.borrow(), + log_dev!(debug, dev, format!("Input device has {} joystick buttons and {} axes but also {} keyboard key sets, \ assuming this is a keyboard, not a joystick.", num_joystick_buttons, num_joystick_axes, num_well_known_keys)); @@ -555,7 +552,7 @@ impl InputId { if has_wheel && has_pad_buttons { log_dev!( debug, - dev.borrow(), + dev, format!( "Input device has {} joystick buttons as well as tablet pad buttons, \ assuming this is a tablet pad, not a joystick.", @@ -611,13 +608,9 @@ impl InputId { || is_pointing_stick } - fn test_key(&self, dev: Rc>, bitmasks: &mut Bitmasks, test: bool) -> bool { + fn test_key(&self, dev: Rc, bitmasks: &mut Bitmasks, test: bool) -> bool { if test_bit!(input_event_codes::EV_KEY!(), bitmasks.bitmask_ev, false) { - log_dev!( - debug, - dev.borrow(), - "test_key: no EV_KEY capability".to_string() - ); + log_dev!(debug, dev, "test_key: no EV_KEY capability".to_string()); return false; } @@ -629,7 +622,7 @@ impl InputId { } log_dev!( debug, - dev.borrow(), + dev, format!( "test_key: checking bit block {} for any keys; found={}", i * bits_per_long!(), @@ -660,7 +653,7 @@ impl InputId { if test_bit!(i, bitmasks.bitmask_key) && !found { log_dev!( debug, - dev.borrow(), + dev, format!("test_key: Found key {} in high block", i) ); found = true; @@ -688,7 +681,7 @@ impl InputId { (absinfo.maximum - absinfo.minimum) / absinfo.resolution } - fn extract_info(&self, dev: Rc>, test: bool) { + fn extract_info(&self, dev: Rc, test: bool) { let mut xabsinfo = input_absinfo { ..Default::default() }; @@ -697,7 +690,6 @@ impl InputId { }; let fd = match dev - .borrow() .open(OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_NONBLOCK | OFlag::O_NOCTTY) { Ok(fd) => fd, @@ -748,10 +740,7 @@ mod tests { let mut enumerator = DeviceEnumerator::new(); - for device in enumerator - .iter() - .filter(|d| d.borrow().get_devpath().is_ok()) - { + for device in enumerator.iter().filter(|d| d.get_devpath().is_ok()) { let exec_unit = ExecuteUnit::new(device); let builtin = InputId {}; let _ = builtin.cmd(&exec_unit, 0, vec![], true); diff --git a/exts/devmaster/src/lib/builtin/keyboard.rs b/exts/devmaster/src/lib/builtin/keyboard.rs index 67e7c722..ffc19dc5 100644 --- a/exts/devmaster/src/lib/builtin/keyboard.rs +++ b/exts/devmaster/src/lib/builtin/keyboard.rs @@ -21,7 +21,6 @@ use input_event_codes_rs::{get_input_event_key, input_event_codes}; use ioctls::{eviocgabs, eviocgbit, eviocskeycode, input_absinfo}; use nix::fcntl::OFlag; use snafu::ResultExt; -use std::cell::RefCell; use std::mem; use std::os::unix::prelude::AsRawFd; use std::rc::Rc; @@ -63,12 +62,11 @@ impl Keyboard { }; } - fn force_release(device: Rc>, release: [u32; 1024], release_count: usize) { + fn force_release(device: Rc, release: [u32; 1024], release_count: usize) { let atkbd = device - .borrow() .get_parent_with_subsystem_devtype("serio", None) .unwrap(); - let current = atkbd.borrow().get_sysattr_value("force_release").unwrap(); + let current = atkbd.get_sysattr_value("force_release").unwrap(); let mut codes = current; for i in release.iter().take(release_count) { if !codes.is_empty() { @@ -76,9 +74,7 @@ impl Keyboard { } codes += &release[*i as usize].to_string(); } - let _ = atkbd - .borrow() - .set_sysattr_value("force_release", Some(&codes)); + let _ = atkbd.set_sysattr_value("force_release", Some(&codes)); } unsafe fn eviocsabs( @@ -124,15 +120,14 @@ impl Keyboard { } } - fn set_trackpoint_sensitivity(device: Rc>, value: &str) { + fn set_trackpoint_sensitivity(device: Rc, value: &str) { let pdev = device - .borrow() .get_parent_with_subsystem_devtype("serio", None) .unwrap(); if value.parse::().unwrap() < 0 || value.parse::().unwrap() > 255 { return; } - let _ = pdev.borrow().set_sysattr_value("sensitivity", Some(value)); + let _ = pdev.set_sysattr_value("sensitivity", Some(value)); } } @@ -151,12 +146,11 @@ impl Builtin for Keyboard { let mut has_abs = -1; let device = exec_unit.get_device(); let devname = device - .borrow() .get_devname() .context(DeviceSnafu) - .log_dev_error(&device.borrow(), "Failed to get devname!")?; + .log_dev_error(&device, "Failed to get devname!")?; - for (key, value) in &device.borrow().property_iter() { + for (key, value) in &device.property_iter() { // KEYBOARD_KEY_= if value.starts_with("KEYBOARD_KEY_") { let mut keycode: String = value.to_string(); diff --git a/exts/devmaster/src/lib/builtin/kmod.rs b/exts/devmaster/src/lib/builtin/kmod.rs index cf718d41..fab38f44 100644 --- a/exts/devmaster/src/lib/builtin/kmod.rs +++ b/exts/devmaster/src/lib/builtin/kmod.rs @@ -66,7 +66,6 @@ impl Builtin for Kmod { if argc == 2 { let modalias = device - .borrow() .get_property_value("MODALIAS") .map_or(String::new(), |e| e); diff --git a/exts/devmaster/src/lib/builtin/mod.rs b/exts/devmaster/src/lib/builtin/mod.rs index ea632479..259ebd13 100644 --- a/exts/devmaster/src/lib/builtin/mod.rs +++ b/exts/devmaster/src/lib/builtin/mod.rs @@ -20,7 +20,6 @@ use crate::{ }; use device::Device; use std::{ - cell::RefCell, collections::HashMap, fmt::{self, Display}, rc::Rc, @@ -75,13 +74,12 @@ pub trait Builtin { /// add property into device fn add_property( &self, - device: Rc>, + device: Rc, test: bool, key: &str, value: &str, ) -> Result<(), Error> { device - .borrow() .add_property(key, value) .map_err(|e| Error::BuiltinCommandError { msg: format!("Failed to add property '{}'='{}': ({})", key, value, e), diff --git a/exts/devmaster/src/lib/builtin/net_id.rs b/exts/devmaster/src/lib/builtin/net_id.rs index 091d6ccd..87e093a8 100644 --- a/exts/devmaster/src/lib/builtin/net_id.rs +++ b/exts/devmaster/src/lib/builtin/net_id.rs @@ -23,7 +23,6 @@ use device::Device; use libc::{c_char, faccessat, ARPHRD_INFINIBAND, F_OK}; use nix::errno::errno; use snafu::ResultExt; -use std::cell::RefCell; use std::ffi::CString; use std::os::unix::prelude::{AsRawFd, RawFd}; use std::rc::Rc; @@ -49,7 +48,7 @@ enum HwAddrAssignType { struct NetNames { r#type: NetNameType, - pcidev: Rc>, + pcidev: Rc, pci_slot: String, pci_path: String, pci_onboard: String, @@ -66,7 +65,7 @@ struct NetNames { } impl NetNames { - fn new(dev: Rc>) -> Self { + fn new(dev: Rc) -> Self { NetNames { r#type: NetNameType::default(), @@ -122,7 +121,7 @@ struct LinkInfo { } /// Skip intermediate virtio device -fn skip_virtio(dev: Rc>) -> Option>> { +fn skip_virtio(dev: Rc) -> Option> { let mut dev = dev; /* @@ -132,7 +131,7 @@ fn skip_virtio(dev: Rc>) -> Option>> { */ #[allow(clippy::while_let_loop)] loop { - let subsystem = match dev.borrow().get_subsystem() { + let subsystem = match dev.get_subsystem() { Ok(s) => s, Err(_) => break, }; @@ -141,7 +140,7 @@ fn skip_virtio(dev: Rc>) -> Option>> { break; } - let parent = match dev.borrow().get_parent() { + let parent = match dev.get_parent() { Ok(p) => p, Err(_) => return None, }; @@ -152,15 +151,15 @@ fn skip_virtio(dev: Rc>) -> Option>> { Some(dev) } -fn get_virtfn_info(pcidev: Rc>) -> Result<(Rc>, String)> { - let syspath = pcidev.borrow().get_syspath().context(DeviceSnafu)?; +fn get_virtfn_info(pcidev: Rc) -> Result<(Rc, String)> { + let syspath = pcidev.get_syspath().context(DeviceSnafu)?; /* Get physical function's pci device. */ - let physfn_pcidev = pcidev.borrow().get_child("physfn").context(DeviceSnafu)?; + let physfn_pcidev = pcidev.get_child("physfn").context(DeviceSnafu)?; let mut suffix = ""; /* Find the virtual function number by finding the right virtfn link. */ - for (subdir, child) in &physfn_pcidev.borrow().child_iter() { + for (subdir, child) in &physfn_pcidev.child_iter() { /* Only accepts e.g. virtfn0, virtfn1, and so on. */ if subdir.starts_with("virtfn") { suffix = subdir.trim_start_matches("virtfn"); @@ -169,7 +168,7 @@ fn get_virtfn_info(pcidev: Rc>) -> Result<(Rc>, } } - let child_syspath = match child.borrow().get_syspath() { + let child_syspath = match child.get_syspath() { Ok(s) => s, Err(_) => continue, }; @@ -201,34 +200,33 @@ fn is_valid_onboard_index(idx: u32) -> bool { } /// Retrieve on-board index number and label from firmware -fn dev_pci_onboard(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> Result<()> { +fn dev_pci_onboard(dev: Rc, info: &LinkInfo, names: &mut NetNames) -> Result<()> { let mut dev_port: u32 = 0; - let attr = match names.pcidev.borrow().get_sysattr_value("acpi_index") { + let attr = match names.pcidev.get_sysattr_value("acpi_index") { Ok(v) => { - log_dev!(debug, names.pcidev.borrow(), format!("acpi_index={}", v)); + log_dev!(debug, names.pcidev, format!("acpi_index={}", v)); v } Err(_) => { let v = names .pcidev - .borrow() .get_sysattr_value("index") .context(DeviceSnafu)?; - log_dev!(debug, names.pcidev.borrow(), format!("index={}", v)); + log_dev!(debug, names.pcidev, format!("index={}", v)); v } }; - let idx = attr.parse::().context(ParseIntSnafu).log_dev_debug( - &names.pcidev.borrow(), - &format!("Failed to parse '{}'", attr), - )?; + let idx = attr + .parse::() + .context(ParseIntSnafu) + .log_dev_debug(&names.pcidev, &format!("Failed to parse '{}'", attr))?; if idx == 0 && !naming_scheme_has(NamingSchemeFlags::ZERO_ACPI_INDEX) { log_dev!( debug, - names.pcidev.borrow(), + names.pcidev, "Naming scheme does not allow onboard index==0" ); return Err(Error::Nix { @@ -239,7 +237,7 @@ fn dev_pci_onboard(dev: Rc>, info: &LinkInfo, names: &mut NetNam if !is_valid_onboard_index(idx) { log_dev!( debug, - names.pcidev.borrow(), + names.pcidev, format!("Not a valid onboard index: {}", idx) ); return Err(Error::Nix { @@ -247,15 +245,15 @@ fn dev_pci_onboard(dev: Rc>, info: &LinkInfo, names: &mut NetNam }); } - if let Ok(v) = dev.borrow().get_sysattr_value("dev_port") { + if let Ok(v) = dev.get_sysattr_value("dev_port") { if let Ok(n) = v .parse::() .context(ParseIntSnafu) - .log_dev_debug(&dev.borrow(), "Failed to parse dev_port, ignoring") + .log_dev_debug(&dev, "Failed to parse dev_port, ignoring") { dev_port = n; } - log_dev!(debug, dev.borrow(), format!("dev_port={}", dev_port)); + log_dev!(debug, dev, format!("dev_port={}", dev_port)); } names.pci_onboard.push_str(&format!("o{}", idx)); @@ -269,18 +267,18 @@ fn dev_pci_onboard(dev: Rc>, info: &LinkInfo, names: &mut NetNam log_dev!( debug, - dev.borrow(), + dev, format!( "Onboard index identifier: index={} phys_port={} dev_port={} >>> {}", idx, info.physical_port_name, dev_port, names.pci_onboard ) ); - if let Ok(v) = names.pcidev.borrow().get_sysattr_value("label") { + if let Ok(v) = names.pcidev.get_sysattr_value("label") { names.pci_onboard_label = v; log_dev!( debug, - dev.borrow(), + dev, format!("Onboard label from PCI device: {}", names.pci_onboard_label) ); } else { @@ -291,8 +289,8 @@ fn dev_pci_onboard(dev: Rc>, info: &LinkInfo, names: &mut NetNam } /// Read the 256 bytes PCI configuration space to check the multi-function bit -fn is_pci_multifunction(dev: Rc>) -> Result { - let syspath = dev.borrow().get_syspath().context(DeviceSnafu)?; +fn is_pci_multifunction(dev: Rc) -> Result { + let syspath = dev.get_syspath().context(DeviceSnafu)?; let filename = format!("{}/config", syspath); let config = std::fs::read(&filename).context(IoSnafu { filename })?; @@ -302,8 +300,8 @@ fn is_pci_multifunction(dev: Rc>) -> Result { Ok(config[PCI_HEADER_TYPE as usize] & PCI_HEADER_TYPE_MULTIFUNC != 0) } -fn is_pci_ari_enabled(dev: Rc>) -> bool { - let attr = match dev.borrow().get_sysattr_value("ari_enabled") { +fn is_pci_ari_enabled(dev: Rc) -> bool { + let attr = match dev.get_sysattr_value("ari_enabled") { Ok(v) => v, Err(_) => return false, }; @@ -311,8 +309,8 @@ fn is_pci_ari_enabled(dev: Rc>) -> bool { &attr == "1" } -fn is_pci_bridge(dev: Rc>) -> bool { - let modalias = match dev.borrow().get_sysattr_value("modalias") { +fn is_pci_bridge(dev: Rc) -> bool { + let modalias = match dev.get_sysattr_value("modalias") { Ok(v) => v, Err(_) => return false, }; @@ -344,17 +342,14 @@ fn is_pci_bridge(dev: Rc>) -> bool { }; if pci_subclass == "04" { - log_dev!(debug, dev.borrow(), "Device is a PCI bridge"); + log_dev!(debug, dev, "Device is a PCI bridge"); return true; } false } -fn parse_hotplug_slot_from_function_id( - dev: Rc>, - slots_dirfd: RawFd, -) -> Result> { +fn parse_hotplug_slot_from_function_id(dev: Rc, slots_dirfd: RawFd) -> Result> { if !naming_scheme_has(NamingSchemeFlags::SLOT_FUNCTION_ID) { return Ok(None); } @@ -368,20 +363,20 @@ fn parse_hotplug_slot_from_function_id( * the domain part doesn't belong to the slot name here because there's a 1-to-1 relationship * between PCI function and its hotplug slot. */ - let attr = match dev.borrow().get_sysattr_value("function_id") { + let attr = match dev.get_sysattr_value("function_id") { Ok(v) => v, Err(_) => return Ok(None), }; let function_id = attr.parse::().context(ParseIntSnafu).log_dev_debug( - &dev.borrow(), + &dev, &format!("Failed to parse function_id, ignoring '{}'", attr), )?; if function_id > u32::MAX.into() { log_dev!( debug, - dev.borrow(), + dev, format!("Invalid function id '{}', ignoring", function_id) ); @@ -393,7 +388,7 @@ fn parse_hotplug_slot_from_function_id( if function_id.to_string().len() > 8 { log_dev!( warn, - dev.borrow(), + dev, format!("function_id '{}' is too long, ignoring", function_id) ); return Err(Error::Nix { @@ -406,7 +401,7 @@ fn parse_hotplug_slot_from_function_id( if unsafe { faccessat(slots_dirfd, filename.as_ptr() as *const c_char, F_OK, 0) } < 0 { log_dev!( debug, - dev.borrow(), + dev, format!( "Cannot access '{}' under pci slots, ignoring: {}", filename, @@ -421,15 +416,14 @@ fn parse_hotplug_slot_from_function_id( Ok(Some(function_id as u32)) } -fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> Result<()> { +fn dev_pci_slot(dev: Rc, info: &LinkInfo, names: &mut NetNames) -> Result<()> { let mut hotplug_slot: u32 = 0; let mut dev_port: u32 = 0; let sysname = names .pcidev - .borrow() .get_sysname() .context(DeviceSnafu) - .log_dev_error(&dev.borrow(), "Failed to get sysname")?; + .log_dev_error(&dev, "Failed to get sysname")?; let mut domain: u32 = 0; let mut bus: u32 = 0; @@ -451,7 +445,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) if ret != 4 { log_dev!( debug, - dev.borrow(), + dev, "Failed to parse slot information from PCI device sysname" ); @@ -462,7 +456,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) log_dev!( debug, - dev.borrow(), + dev, format!( "Parsing slot information from PCI device sysname '{}'", sysname @@ -478,11 +472,11 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) func += slot * 8; } /* kernel provided port index for multiple ports on a single PCI function */ - if let Ok(attr) = dev.borrow().get_sysattr_value("dev_port") { - log_dev!(debug, dev.borrow(), format!("dev_port={}", attr)); + if let Ok(attr) = dev.get_sysattr_value("dev_port") { + log_dev!(debug, dev, format!("dev_port={}", attr)); dev_port = attr.parse::().context(ParseIntSnafu).log_dev_debug( - &dev.borrow(), + &dev, &format!("Failed to parse attribute dev_port '{}', ignoring", attr), )?; @@ -492,11 +486,11 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) * which thus stays initialized as 0. */ if dev_port == 0 && info.iftype == ARPHRD_INFINIBAND { - if let Ok(attr) = dev.borrow().get_sysattr_value("dev_id") { - log_dev!(debug, dev.borrow(), format!("dev_id={}", attr)); + if let Ok(attr) = dev.get_sysattr_value("dev_id") { + log_dev!(debug, dev, format!("dev_id={}", attr)); dev_port = attr.parse::().context(ParseIntSnafu).log_dev_debug( - &dev.borrow(), + &dev, &format!("Failed to parse attribute dev_id '{}', ignoring", attr), )?; } @@ -524,7 +518,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) log_dev!( debug, - dev.borrow(), + dev, format!( "PCI path identifier: domain={} bus={} slot={} func={} phys_port={} dev_port={} >>> {}", domain, bus, slot, func, info.physical_port_name, dev_port, names.pci_path @@ -556,10 +550,9 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) } let sysname = hotplug_slot_dev - .borrow() .get_sysname() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "Failed to get sysname")?; + .log_dev_debug(&dev, "Failed to get sysname")?; let read_dir = pci .read_dir("slots") @@ -614,7 +607,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) { log_dev!( debug, - dev.borrow(), + dev, "Not using slot information because the PCI device associated with the hotplug slot is a bridge and the PCI device has a single function." ); return Ok(()); @@ -623,7 +616,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) if !naming_scheme_has(NamingSchemeFlags::BRIDGE_MULTIFUNCTION_SLOT) { log_dev!( debug, - dev.borrow(), + dev, "Not using slot information because the PCI device is a bridge." ); return Ok(()); @@ -636,10 +629,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) break; } - let parent = match hotplug_slot_dev - .borrow() - .get_parent_with_subsystem_devtype("pci", None) - { + let parent = match hotplug_slot_dev.get_parent_with_subsystem_devtype("pci", None) { Ok(d) => d, Err(_) => break, }; @@ -666,7 +656,7 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) log_dev!( debug, - dev.borrow(), + dev, format!( "Slot identifier: domain={} slot={} func={} phys_port={} dev_port={} >>> {}", domain, hotplug_slot, func, info.physical_port_name, dev_port, names.pci_slot @@ -677,18 +667,16 @@ fn dev_pci_slot(dev: Rc>, info: &LinkInfo, names: &mut NetNames) Ok(()) } -fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { +fn names_vio(dev: Rc, names: &mut NetNames) -> Result<()> { /* Check if our direct parent is a VIO device with no other bus in-between */ - dev.borrow() - .get_parent() + dev.get_parent() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "failed to get parent")?; + .log_dev_debug(&dev, "failed to get parent")?; let subsystem = dev - .borrow() .get_subsystem() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "failed to get subsystem")?; + .log_dev_debug(&dev, "failed to get subsystem")?; if "vio" != &subsystem { return Err(Error::Nix { @@ -696,7 +684,7 @@ fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { }); } - log_dev!(debug, dev.borrow(), "Parent device is in the vio subsystem"); + log_dev!(debug, dev, "Parent device is in the vio subsystem"); /* * The devices' $DEVPATH number is tied to (virtual) hardware (slot id @@ -705,19 +693,14 @@ fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { * there should only ever be one bus, and then remove leading zeros. */ let syspath = dev - .borrow() .get_syspath() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "failed to get syspath")?; + .log_dev_debug(&dev, "failed to get syspath")?; let s = match get_first_path_component(&syspath, "/sys/devices/vio/") { Some(s) => s, None => { - log_dev!( - debug, - dev.borrow(), - "Syspath does not begin with /sys/devices/vio/" - ); + log_dev!(debug, dev, "Syspath does not begin with /sys/devices/vio/"); return Err(Error::Nix { source: nix::Error::EINVAL, }); @@ -727,7 +710,7 @@ fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { if s.len() != 8 || !str_satisfy(s, |c| c.is_ascii_hexdigit()) { log_dev!( debug, - dev.borrow(), + dev, "VIO bus ID and slot ID contain non ascii digits." ); return Err(Error::Nix { @@ -739,7 +722,7 @@ fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { log_dev!( debug, - dev.borrow(), + dev, format!("Parsing vio slot information from syspath '{}'", syspath) ); @@ -747,7 +730,7 @@ fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { names.r#type = NetNameType::Vio; log_dev!( debug, - dev.borrow(), + dev, format!( "Vio slot identifier: slotid={} >>> {}", slotid, names.vio_slot @@ -759,19 +742,17 @@ fn names_vio(dev: Rc>, names: &mut NetNames) -> Result<()> { const PLATFORM_TEST: &str = "/sys/devices/platform/aaaaBBBB"; -fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) -> Result<()> { +fn names_platform(dev: Rc, names: &mut NetNames, _test: bool) -> Result<()> { /* Check if our direct parent is a platform device with no other bus in-between */ let parent = dev - .borrow() .get_parent() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "failed to get parent")?; + .log_dev_debug(&dev, "failed to get parent")?; let subsystem = parent - .borrow() .get_subsystem() .context(DeviceSnafu) - .log_dev_debug(&parent.borrow(), "failed to get subsystem")?; + .log_dev_debug(&parent, "failed to get subsystem")?; if &subsystem != "platform" { return Err(Error::Nix { @@ -779,22 +760,17 @@ fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) - }); } - log_dev!( - debug, - dev.borrow(), - "Parent device is in the platform subsystem" - ); + log_dev!(debug, dev, "Parent device is in the platform subsystem"); let syspath = dev - .borrow() .get_syspath() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "failed to get syspath")?; + .log_dev_debug(&dev, "failed to get syspath")?; if syspath.len() < PLATFORM_TEST.len() + 1 { log_dev!( debug, - dev.borrow(), + dev, format!( "The syspath '{}' is too short for a valid ACPI instance", syspath @@ -815,7 +791,7 @@ fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) - let s = match get_first_path_component(&syspath, "/sys/devices/platform/") { Some(s) => s, None => { - log_dev!(debug, dev.borrow(), "Failed to get platform ID".to_string()); + log_dev!(debug, dev, "Failed to get platform ID".to_string()); return Err(Error::Nix { source: nix::Error::EINVAL, }); @@ -840,7 +816,7 @@ fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) - if !str_satisfy(vendor, |c| validchars.contains(c)) { log_dev!( debug, - &dev.borrow(), + &dev, format!("Platform vendor contains invalid characters: {}", vendor) ); return Err(Error::Nix { @@ -852,10 +828,10 @@ fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) - vendor.to_ascii_lowercase(), u32::from_str_radix(model, 16) .context(ParseIntSnafu) - .log_dev_debug(&dev.borrow(), &format!("invalid model '{}'", model))?, + .log_dev_debug(&dev, &format!("invalid model '{}'", model))?, u32::from_str_radix(instance, 16) .context(ParseIntSnafu) - .log_dev_debug(&dev.borrow(), &format!("invalid instance '{}'", instance))?, + .log_dev_debug(&dev, &format!("invalid instance '{}'", instance))?, ); names.platform_path = format!("a{}{:x}i{}", vendor, model, instance); @@ -863,7 +839,7 @@ fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) - log_dev!( debug, - dev.borrow(), + dev, format!( "Platform identifier: vendor={} model={} instance={} >>> {}", vendor, model, instance, names.platform_path @@ -873,15 +849,15 @@ fn names_platform(dev: Rc>, names: &mut NetNames, _test: bool) - Ok(()) } -fn dev_devicetree_onboard(dev: Rc>, names: &mut NetNames) -> Result<()> { +fn dev_devicetree_onboard(dev: Rc, names: &mut NetNames) -> Result<()> { if !naming_scheme_has(NamingSchemeFlags::DEVICETREE_ALIASES) { return Ok(()); } /* Check if our direct parent has an of_node */ - let parent = dev.borrow().get_parent().context(DeviceSnafu)?; - let ofnode_dev = parent.borrow().get_child("of_node").context(DeviceSnafu)?; - let ofnode_syspath = ofnode_dev.borrow().get_syspath().context(DeviceSnafu)?; + let parent = dev.get_parent().context(DeviceSnafu)?; + let ofnode_dev = parent.get_child("of_node").context(DeviceSnafu)?; + let ofnode_syspath = ofnode_dev.get_syspath().context(DeviceSnafu)?; /* /proc/device-tree should be a symlink to /sys/firmware/devicetree/base. */ let devicetree_dev = Device::from_path("/proc/device-tree").context(DeviceSnafu)?; @@ -906,13 +882,13 @@ fn dev_devicetree_onboard(dev: Rc>, names: &mut NetNames) -> Res let aliases_dev = devicetree_dev.get_child("aliases").context(DeviceSnafu)?; - for alias in &aliases_dev.borrow().sysattr_iter() { + for alias in &aliases_dev.sysattr_iter() { let alias_index = match alias.strip_prefix("ethernet") { Some(suffix) => suffix, None => continue, }; - let alias_path = match aliases_dev.borrow().get_sysattr_value(alias) { + let alias_path = match aliases_dev.get_sysattr_value(alias) { Ok(v) => v, Err(_) => continue, }; @@ -928,18 +904,15 @@ fn dev_devicetree_onboard(dev: Rc>, names: &mut NetNames) -> Res let i = alias_index .parse::() .context(ParseIntSnafu) - .log_dev_debug( - &dev.borrow(), - &format!("Could not get index of alias '{}'", alias), - )?; + .log_dev_debug(&dev, &format!("Could not get index of alias '{}'", alias))?; (i, "ethernet") }; /* ...but make sure we don't have an alias conflict */ - if i == 0 && aliases_dev.borrow().get_sysattr_value(conflict).is_ok() { + if i == 0 && aliases_dev.get_sysattr_value(conflict).is_ok() { log_dev!( debug, - dev.borrow(), + dev, "Ethernet alias conflict: ethernet and ethernet0 both exist" ); return Err(Error::Nix { @@ -958,8 +931,8 @@ fn dev_devicetree_onboard(dev: Rc>, names: &mut NetNames) -> Res } #[allow(clippy::unnecessary_unwrap)] -fn names_pci(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> Result<()> { - let parent = dev.borrow().get_parent().context(DeviceSnafu)?; +fn names_pci(dev: Rc, info: &LinkInfo, names: &mut NetNames) -> Result<()> { + let parent = dev.get_parent().context(DeviceSnafu)?; /* Skip virtio subsystem if present */ let parent = skip_virtio(parent); @@ -973,7 +946,7 @@ fn names_pci(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> let parent = parent.unwrap(); /* Check if our direct parent is a PCI device with no other bus in-between */ - match parent.borrow().get_subsystem() { + match parent.get_subsystem() { Ok(s) => { if &s == "pci" { names.r#type = NetNameType::Pci; @@ -982,7 +955,6 @@ fn names_pci(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> } Err(_) => { names.pcidev = dev - .borrow() .get_parent_with_subsystem_devtype("pci", None) .context(DeviceSnafu)?; } @@ -1020,28 +992,26 @@ fn names_pci(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> Ok(()) } -fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { +fn names_usb(dev: Rc, names: &mut NetNames) -> Result<()> { let usbdev = dev - .borrow() .get_parent_with_subsystem_devtype("usb", Some("usb_interface")) .context(DeviceSnafu) .log_dev_debug( - &dev.borrow(), + &dev, "Failed to get parent with subsystem 'usb' and devtype 'usb_interface'", )?; let sysname = usbdev - .borrow() .get_sysname() .context(DeviceSnafu) - .log_dev_debug(&usbdev.borrow(), "Failed to get parent sysname")?; + .log_dev_debug(&usbdev, "Failed to get parent sysname")?; /* Get USB port number chain, configuration, interface */ let name = sysname.clone(); let idx_1 = name.find('-').ok_or_else(|| { log_dev!( debug, - usbdev.borrow(), + usbdev, format!("sysname '{}' does not have '-' as expected", sysname) ); Error::Nix { @@ -1052,7 +1022,7 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { let ports = name.get(idx_1 + 1..).ok_or_else(|| { log_dev!( debug, - usbdev.borrow(), + usbdev, format!("sysname '{}' does not contain ports", sysname) ); Error::Nix { @@ -1063,7 +1033,7 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { let idx_2 = ports.find(':').ok_or_else(|| { log_dev!( debug, - usbdev.borrow(), + usbdev, format!("sysname '{}' does not have ':' as expected", sysname) ); Error::Nix { @@ -1076,7 +1046,7 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { let config = name.get(idx_2 + 1..).ok_or_else(|| { log_dev!( debug, - usbdev.borrow(), + usbdev, format!("sysname '{}' does not contain config", sysname) ); Error::Nix { @@ -1087,7 +1057,7 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { let idx_3 = config.find('.').ok_or_else(|| { log_dev!( debug, - usbdev.borrow(), + usbdev, format!("sysname '{}' does not have '.' as expected", sysname) ); Error::Nix { @@ -1101,7 +1071,7 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { .ok_or_else(|| { log_dev!( debug, - usbdev.borrow(), + usbdev, format!("sysname '{}' does not contain interface", sysname) ); Error::Nix { @@ -1125,7 +1095,7 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { log_dev!( debug, - dev.borrow(), + dev, format!( "USB name identifier: ports={} config={} interface={} >>> {}", ports, config, interf, names.usb_ports @@ -1137,32 +1107,27 @@ fn names_usb(dev: Rc>, names: &mut NetNames) -> Result<()> { Ok(()) } -fn names_bcma(dev: Rc>, names: &mut NetNames) -> Result<()> { +fn names_bcma(dev: Rc, names: &mut NetNames) -> Result<()> { let bcmadev = dev - .borrow() .get_parent_with_subsystem_devtype("bcma", None) .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "Failed to get parent with subsystem 'bcma'")?; + .log_dev_debug(&dev, "Failed to get parent with subsystem 'bcma'")?; let sysname = bcmadev - .borrow() .get_sysname() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "Failed to get bcma device sysname")?; + .log_dev_debug(&dev, "Failed to get bcma device sysname")?; /* Bus num:core num */ let core = match sysname.find(':') { Some(idx) => sysname[idx + 1..] .parse::() .context(ParseIntSnafu) - .log_dev_debug( - &dev.borrow(), - &format!("core string is not a number: {}", sysname), - )?, + .log_dev_debug(&dev, &format!("core string is not a number: {}", sysname))?, None => { log_dev!( debug, - &dev.borrow(), + &dev, format!("Failed to get core number: {}", sysname) ); return Err(Error::Nix { @@ -1173,7 +1138,7 @@ fn names_bcma(dev: Rc>, names: &mut NetNames) -> Result<()> { log_dev!( debug, - dev.borrow(), + dev, format!("Parsing bcma device information from sysname '{}'", sysname) ); @@ -1186,7 +1151,7 @@ fn names_bcma(dev: Rc>, names: &mut NetNames) -> Result<()> { log_dev!( debug, - dev.borrow(), + dev, format!( "BCMA core identifier: core={} >>> {}", core, names.bcma_core @@ -1196,13 +1161,12 @@ fn names_bcma(dev: Rc>, names: &mut NetNames) -> Result<()> { Ok(()) } -fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { +fn names_ccw(dev: Rc, names: &mut NetNames) -> Result<()> { /* Retrieve the associated CCW device */ let _ = dev - .borrow() .get_parent() .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "Failed to get parent")?; + .log_dev_debug(&dev, "Failed to get parent")?; /* Skip virtio subsystem if present */ let cdev = match skip_virtio(dev.clone()) { @@ -1215,10 +1179,9 @@ fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { }; let subsys = cdev - .borrow() .get_subsystem() .context(DeviceSnafu) - .log_dev_debug(&cdev.borrow(), "Failed to get subsystem")?; + .log_dev_debug(&cdev, "Failed to get subsystem")?; /* Network devices are either single or grouped CCW devices */ if !["ccwgroup", "ccw"].contains(&subsys.as_str()) { @@ -1227,7 +1190,7 @@ fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { }); } - log_dev!(debug, dev.borrow(), "Device is CCW"); + log_dev!(debug, dev, "Device is CCW"); /* * Retrieve bus-ID of the CCW device. The bus-ID uniquely @@ -1235,10 +1198,9 @@ fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { * subsystem. Note that the bus-ID contains lowercase characters. */ let bus_id = cdev - .borrow() .get_sysname() .context(DeviceSnafu) - .log_dev_debug(&cdev.borrow(), "Failed to get sysname")?; + .log_dev_debug(&cdev, "Failed to get sysname")?; /* * Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID; @@ -1246,7 +1208,7 @@ fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { */ let bus_id_len = bus_id.len(); if ![8, 9].contains(&bus_id_len) { - log_dev!(debug, cdev.borrow(), format!("Invalid bus_id '{}'", bus_id)); + log_dev!(debug, cdev, format!("Invalid bus_id '{}'", bus_id)); return Err(Error::Nix { source: nix::Error::EINVAL, }); @@ -1270,7 +1232,7 @@ fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { log_dev!( debug, - dev.borrow(), + dev, format!( "CCW identifier: ccw_busid={} >>> {}", bus_id, names.ccw_busid @@ -1280,7 +1242,7 @@ fn names_ccw(dev: Rc>, names: &mut NetNames) -> Result<()> { Ok(()) } -fn names_mac(dev: Rc>, info: &LinkInfo) -> Result<()> { +fn names_mac(dev: Rc, info: &LinkInfo) -> Result<()> { /* * The persistent part of a hardware address of an InfiniBand NIC is 8 bytes long. We cannot * fit this much in an iface name. @@ -1288,11 +1250,7 @@ fn names_mac(dev: Rc>, info: &LinkInfo) -> Result<()> { */ if info.iftype == ARPHRD_INFINIBAND { - log_dev!( - debug, - dev.borrow(), - "Not generating MAC name for infiniband device" - ); + log_dev!(debug, dev, "Not generating MAC name for infiniband device"); return Err(Error::Nix { source: nix::Error::EOPNOTSUPP, }); @@ -1301,7 +1259,7 @@ fn names_mac(dev: Rc>, info: &LinkInfo) -> Result<()> { if info.hw_addr.length as u8 != 6 { log_dev!( debug, - dev.borrow(), + dev, format!( "Not generating MAC name for device with MAC address of length {}", info.hw_addr.length as u8 @@ -1314,20 +1272,19 @@ fn names_mac(dev: Rc>, info: &LinkInfo) -> Result<()> { /* Check for NET_ADDR_PERM, skip random MAC addresses */ let s = dev - .borrow() .get_sysattr_value("addr_assign_type") .context(DeviceSnafu) - .log_dev_debug(&dev.borrow(), "Failed to read addr_assign_type")?; + .log_dev_debug(&dev, "Failed to read addr_assign_type")?; let i = s .parse::() .context(ParseIntSnafu) - .log_dev_debug(&dev.borrow(), "Failed to parse addr_assign_type number")?; + .log_dev_debug(&dev, "Failed to parse addr_assign_type number")?; if i != HwAddrAssignType::Permanent as u32 { log_dev!( debug, - dev.borrow(), + dev, format!("addr_assign_type={}, MAC address is not permant", i) ); return Err(Error::Nix { @@ -1338,7 +1295,7 @@ fn names_mac(dev: Rc>, info: &LinkInfo) -> Result<()> { Ok(()) } -fn names_netdevsim(dev: Rc>, info: &LinkInfo, names: &mut NetNames) -> Result<()> { +fn names_netdevsim(dev: Rc, info: &LinkInfo, names: &mut NetNames) -> Result<()> { if !naming_scheme_has(NamingSchemeFlags::NETDEVSIM) { return Ok(()); } @@ -1350,21 +1307,20 @@ fn names_netdevsim(dev: Rc>, info: &LinkInfo, names: &mut NetNam } let netdevsimdev = dev - .borrow() .get_parent_with_subsystem_devtype("netdevsim", None) .context(DeviceSnafu)?; - let sysname = netdevsimdev.borrow().get_sysname().context(DeviceSnafu)?; + let sysname = netdevsimdev.get_sysname().context(DeviceSnafu)?; let addr = match sysname.strip_prefix("netdevsim") { Some(suffix) => suffix.parse::().context(ParseIntSnafu).log_dev_debug( - &dev.borrow(), + &dev, &format!("Failed to parse netdevsim address '{}'", sysname), )?, None => { log_dev!( debug, - &dev.borrow(), + &dev, format!("Netdevsim does not contain address '{}'", sysname) ); return Err(Error::Nix { @@ -1379,20 +1335,20 @@ fn names_netdevsim(dev: Rc>, info: &LinkInfo, names: &mut NetNam Ok(()) } -fn names_xen(dev: Rc>, names: &mut NetNames) -> Result<()> { +fn names_xen(dev: Rc, names: &mut NetNames) -> Result<()> { if !naming_scheme_has(NamingSchemeFlags::XEN_VIF) { return Ok(()); } /* Check if our direct parent is a Xen VIF device with no other bus in-between */ - let parent = dev.borrow().get_parent().context(DeviceSnafu)?; + let parent = dev.get_parent().context(DeviceSnafu)?; /* * Do an exact-match on subsystem "xen". This will miss on "xen-backend" on * purpose as the VIFs on the backend (dom0) have their own naming scheme * which we don't want to affect */ - let subsystem = parent.borrow().get_subsystem().context(DeviceSnafu)?; + let subsystem = parent.get_subsystem().context(DeviceSnafu)?; if "xen" != &subsystem { return Err(Error::Nix { @@ -1401,7 +1357,7 @@ fn names_xen(dev: Rc>, names: &mut NetNames) -> Result<()> { } /* Use the vif-n name to extract "n" */ - let syspath = dev.borrow().get_syspath().context(DeviceSnafu)?; + let syspath = dev.get_syspath().context(DeviceSnafu)?; let p = match syspath.strip_prefix("/sys/devices/") { Some(p) => p, @@ -1446,7 +1402,7 @@ fn names_xen(dev: Rc>, names: &mut NetNames) -> Result<()> { } /// IEEE Organizationally Unique Identifier vendor string -fn ieee_oui(_dev: Rc>, info: &LinkInfo, _test: bool) -> Result<()> { +fn ieee_oui(_dev: Rc, info: &LinkInfo, _test: bool) -> Result<()> { if info.hw_addr.length as u8 != 0 { return Err(Error::Nix { source: nix::Error::EOPNOTSUPP, @@ -1476,24 +1432,22 @@ fn ieee_oui(_dev: Rc>, info: &LinkInfo, _test: bool) -> Result<( todo!("hwdb lookup s") } -fn get_link_info(dev: Rc>) -> Result { - let ifindex = dev.borrow().get_ifindex().context(DeviceSnafu)?; +fn get_link_info(dev: Rc) -> Result { + let ifindex = dev.get_ifindex().context(DeviceSnafu)?; let iflink = dev - .borrow() .get_sysattr_value("iflink") .context(DeviceSnafu)? .parse::() .context(ParseIntSnafu)?; let iftype = dev - .borrow() .get_sysattr_value("type") .context(DeviceSnafu)? .parse::() .context(ParseIntSnafu)?; - let devtype = match dev.borrow().get_devtype() { + let devtype = match dev.get_devtype() { Ok(t) => t, Err(e) => { if !e.is_errno(nix::Error::ENOENT) { @@ -1504,15 +1458,12 @@ fn get_link_info(dev: Rc>) -> Result { } }; - let physical_port_name = dev - .borrow() - .get_sysattr_value("phys_port_name") - .unwrap_or_default(); + let physical_port_name = dev.get_sysattr_value("phys_port_name").unwrap_or_default(); - let hw_addr = match dev.borrow().get_sysattr_value("address") { + let hw_addr = match dev.get_sysattr_value("address") { Ok(s) => parse_hw_addr_full(&s, 0) .context(BasicSnafu) - .log_dev_debug(&dev.borrow(), "Failed to parse 'address' sysattr, ignoring")?, + .log_dev_debug(&dev, "Failed to parse 'address' sysattr, ignoring")?, Err(e) => { if !e.is_errno(nix::Error::ENOENT) { return Err(Error::Device { source: e }); @@ -1544,7 +1495,7 @@ impl Builtin for NetId { test: bool, ) -> Result { let dev = exec_unit.get_device(); - let mut names = NetNames::new(Rc::new(RefCell::new(Device::default()))); + let mut names = NetNames::new(Rc::new(Device::default())); let link_info = get_link_info(dev.clone())?; /* Skip stacked devices, like VLANs, ... */ @@ -1587,7 +1538,7 @@ impl Builtin for NetId { let _ = self.add_property(dev.clone(), test, "ID_NET_NAME_MAC", &s); log_dev!( debug, - dev.borrow(), + dev, format!( "MAC address identifier: hw_addr={} >>> {}", link_info.hw_addr, diff --git a/exts/devmaster/src/lib/builtin/net_setup_link.rs b/exts/devmaster/src/lib/builtin/net_setup_link.rs index 34297813..5848920f 100644 --- a/exts/devmaster/src/lib/builtin/net_setup_link.rs +++ b/exts/devmaster/src/lib/builtin/net_setup_link.rs @@ -14,7 +14,6 @@ //! use std::{ - cell::RefCell, rc::Rc, sync::{Arc, RwLock}, }; @@ -34,12 +33,12 @@ pub struct NetSetupLink { struct NetifLink<'a> { netif_cfg: &'a NetifConfig, - netif: Rc>, + netif: Rc, new_name: String, } impl<'a> NetifLink<'a> { - fn new(netif_cfg: &'a NetifConfig, netif: Rc>) -> NetifLink<'a> { + fn new(netif_cfg: &'a NetifConfig, netif: Rc) -> NetifLink<'a> { NetifLink { netif_cfg, netif, @@ -48,16 +47,16 @@ impl<'a> NetifLink<'a> { } fn apply_cfg(&mut self) -> Result<()> { - let action = self.netif.borrow().get_action().context(DeviceSnafu)?; + let action = self.netif.get_action().context(DeviceSnafu)?; if ![DeviceAction::Add, DeviceAction::Bind, DeviceAction::Move].contains(&action) { log_dev!( debug, - &self.netif.borrow(), + &self.netif, format!("Skipping to apply .link on '{}' uevent", action) ); - self.new_name = self.netif.borrow().get_sysname().context(DeviceSnafu)?; + self.new_name = self.netif.get_sysname().context(DeviceSnafu)?; return Ok(()); } @@ -87,24 +86,18 @@ impl<'a> NetifLink<'a> { // todo continue; } - "database" => match self - .netif - .borrow() - .get_property_value("ID_NET_NAME_FROM_DATABASE") - { - Ok(v) => { - new_name = v; - } - Err(_) => { - continue; + "database" => { + match self.netif.get_property_value("ID_NET_NAME_FROM_DATABASE") { + Ok(v) => { + new_name = v; + } + Err(_) => { + continue; + } } - }, + } - "onboard" => match self - .netif - .borrow() - .get_property_value("ID_NET_NAME_ONBOARD") - { + "onboard" => match self.netif.get_property_value("ID_NET_NAME_ONBOARD") { Ok(v) => { new_name = v; } @@ -113,7 +106,7 @@ impl<'a> NetifLink<'a> { } }, - "slot" => match self.netif.borrow().get_property_value("ID_NET_NAME_SLOT") { + "slot" => match self.netif.get_property_value("ID_NET_NAME_SLOT") { Ok(v) => { new_name = v; } @@ -121,7 +114,7 @@ impl<'a> NetifLink<'a> { continue; } }, - "path" => match self.netif.borrow().get_property_value("ID_NET_NAME_PATH") { + "path" => match self.netif.get_property_value("ID_NET_NAME_PATH") { Ok(v) => { new_name = v; } @@ -129,7 +122,7 @@ impl<'a> NetifLink<'a> { continue; } }, - "mac" => match self.netif.borrow().get_property_value("ID_NET_NAME_MAC") { + "mac" => match self.netif.get_property_value("ID_NET_NAME_MAC") { Ok(v) => { new_name = v; } @@ -175,15 +168,11 @@ impl Builtin for NetSetupLink { if e.get_errno() == nix::Error::ENODEV { log_dev!( debug, - device.borrow(), + device, "Link vanished while applying network configuration" ); } else { - log_dev!( - warn, - device.borrow(), - "Could not apply network configuration" - ) + log_dev!(warn, device, "Could not apply network configuration") } } diff --git a/exts/devmaster/src/lib/builtin/path_id.rs b/exts/devmaster/src/lib/builtin/path_id.rs index 303b7528..2727d5ba 100644 --- a/exts/devmaster/src/lib/builtin/path_id.rs +++ b/exts/devmaster/src/lib/builtin/path_id.rs @@ -17,7 +17,6 @@ use crate::builtin::Builtin; use crate::error::{Error, Result}; use crate::rules::exec_unit::ExecuteUnit; use device::Device; -use std::cell::RefCell; use std::ffi::CString; use std::fs::read_dir; use std::rc::Rc; @@ -71,7 +70,7 @@ impl Builtin for PathId { * devices do not expose their buses and do not provide a unique * and predictable name that way. */ - if let Ok(subsystem) = device.borrow().get_subsystem() { + if let Ok(subsystem) = device.get_subsystem() { if subsystem == "block" && !supported_transport { return Err(Error::BuiltinCommandError { msg: "block error".to_string(), @@ -150,7 +149,7 @@ impl PathId { #[allow(clippy::ptr_arg)] fn compose_path( &self, - dev: Rc>, + dev: Rc, path: &mut String, compat_path: &mut String, supported_transport: &mut bool, @@ -158,18 +157,8 @@ impl PathId { ) -> Result { let mut parent = Option::Some(dev.clone()); loop { - let subsys = parent - .as_ref() - .unwrap() - .borrow() - .get_subsystem() - .unwrap_or_default(); - let mut sysname = parent - .as_ref() - .unwrap() - .borrow() - .get_sysname() - .unwrap_or_default(); + let subsys = parent.as_ref().unwrap().get_subsystem().unwrap_or_default(); + let mut sysname = parent.as_ref().unwrap().get_sysname().unwrap_or_default(); if !subsys.is_empty() && !sysname.is_empty() { if subsys == "scsi_tape" { self.handle_scsi_tape(parent.as_ref().unwrap().clone(), path); @@ -250,7 +239,7 @@ impl PathId { break; } - let temp = match parent.as_ref().unwrap().borrow().get_parent() { + let temp = match parent.as_ref().unwrap().get_parent() { Ok(res) => Some(res), Err(_) => { break; @@ -263,8 +252,8 @@ impl PathId { Ok(true) } - fn handle_scsi_tape(&self, dev: Rc>, path: &mut String) { - let name = match dev.borrow().get_sysname() { + fn handle_scsi_tape(&self, dev: Rc, path: &mut String) { + let name = match dev.get_sysname() { Ok(name) => name, Err(_) => return, }; @@ -280,12 +269,12 @@ impl PathId { fn handle_scsi( &self, - parent: Rc>, + parent: Rc, path: &mut String, compat_path: &mut str, supported_parent: &mut bool, - ) -> Option>> { - let devtype = match parent.borrow().get_devtype() { + ) -> Option> { + let devtype = match parent.get_devtype() { Ok(devtype) => devtype, Err(_) => return Some(parent.clone()), }; @@ -294,14 +283,14 @@ impl PathId { return Some(parent); } - let id = parent.borrow().get_sysattr_value("ieee1394_id"); + let id = parent.get_sysattr_value("ieee1394_id"); if id.is_ok() { self.path_prepend(path, format!("ieee1394-0x{}", id.unwrap())); *supported_parent = true; return self.skip_subsystem(parent, "scsi"); } - let name = match parent.borrow().get_syspath() { + let name = match parent.get_syspath() { Ok(name) => name, Err(_) => return None, }; @@ -335,17 +324,15 @@ impl PathId { fn handle_scsi_fibre_channel( &self, - parent: Rc>, + parent: Rc, path: &mut String, - ) -> Option>> { - let targetdev = match parent - .borrow() - .get_parent_with_subsystem_devtype("scsi", Some("scsi_target")) + ) -> Option> { + let targetdev = match parent.get_parent_with_subsystem_devtype("scsi", Some("scsi_target")) { Ok(dev) => dev, Err(_) => return None, }; - let sysname = match targetdev.borrow().get_sysname() { + let sysname = match targetdev.get_sysname() { Ok(sysname) => sysname, Err(_) => return None, }; @@ -365,23 +352,17 @@ impl PathId { Some(parent) } - fn handle_scsi_sas( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let targetdev = match parent - .borrow() - .get_parent_with_subsystem_devtype("scsi", Some("scsi_target")) + fn handle_scsi_sas(&self, parent: Rc, path: &mut String) -> Option> { + let targetdev = match parent.get_parent_with_subsystem_devtype("scsi", Some("scsi_target")) { Ok(dev) => dev, Err(_) => return None, }; - let target_parent = match targetdev.borrow().get_parent() { + let target_parent = match targetdev.get_parent() { Ok(dev) => dev, Err(_) => return None, }; - let sysname = match target_parent.borrow().get_sysname() { + let sysname = match target_parent.get_sysname() { Ok(sysname) => sysname, Err(_) => return None, }; @@ -402,20 +383,16 @@ impl PathId { Some(parent) } - fn handle_scsi_iscsi( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { + fn handle_scsi_iscsi(&self, parent: Rc, path: &mut String) -> Option> { let transportdev = parent.clone(); let mut sysname; /* find iscsi session */ loop { - let transportdev = match transportdev.borrow().get_parent() { + let transportdev = match transportdev.get_parent() { Ok(dev) => dev, Err(_) => return None, }; - sysname = match transportdev.borrow().get_sysname() { + sysname = match transportdev.get_sysname() { Ok(name) => name, Err(_) => return None, }; @@ -435,7 +412,7 @@ impl PathId { Err(_) => return None, }; - let sysnum = match transportdev.borrow().get_sysnum() { + let sysnum = match transportdev.get_sysnum() { Ok(num) => num, Err(_) => return None, }; @@ -465,11 +442,11 @@ impl PathId { fn handle_scsi_ata( &self, - parent: Rc>, + parent: Rc, path: &mut String, compat_path: &mut str, - ) -> Option>> { - let sysname = match parent.borrow().get_sysname() { + ) -> Option> { + let sysname = match parent.get_sysname() { Ok(name) => name, Err(_) => return None, }; @@ -493,20 +470,17 @@ impl PathId { return None; } - let targetdev = match parent - .borrow() - .get_parent_with_subsystem_devtype("scsi", Some("scsi_host")) - { + let targetdev = match parent.get_parent_with_subsystem_devtype("scsi", Some("scsi_host")) { Ok(dev) => dev, Err(_) => return None, }; - let target_parent = match targetdev.borrow().get_parent() { + let target_parent = match targetdev.get_parent() { Ok(dev) => dev, Err(_e) => return None, }; - let sysname = match target_parent.borrow().get_sysname() { + let sysname = match target_parent.get_sysname() { Ok(name) => name, Err(_) => return None, }; @@ -539,24 +513,21 @@ impl PathId { fn handle_scsi_hyperv( &self, - parent: Rc>, + parent: Rc, path: &mut String, giud_str_len: usize, - ) -> Option>> { - let hostdev = match parent - .borrow() - .get_parent_with_subsystem_devtype("scsi", Some("scsi_host")) - { + ) -> Option> { + let hostdev = match parent.get_parent_with_subsystem_devtype("scsi", Some("scsi_host")) { Ok(dev) => dev, Err(_) => return None, }; - let vmbusdev = match hostdev.borrow().get_parent() { + let vmbusdev = match hostdev.get_parent() { Ok(dev) => dev, Err(_e) => return None, }; - let guid_str = match vmbusdev.borrow().get_sysattr_value("device_id") { + let guid_str = match vmbusdev.get_sysattr_value("device_id") { Ok(str) => str, Err(_e) => return None, }; @@ -578,20 +549,13 @@ impl PathId { Some(parent) } - fn handle_scsi_default( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { + fn handle_scsi_default(&self, parent: Rc, path: &mut String) -> Option> { let mut basenum = -1; - let hostdev = match parent - .borrow() - .get_parent_with_subsystem_devtype("scsi", Some("scsi_host")) - { + let hostdev = match parent.get_parent_with_subsystem_devtype("scsi", Some("scsi_host")) { Ok(dev) => dev, Err(_) => return None, }; - let name = match parent.borrow().get_sysname() { + let name = match parent.get_sysname() { Ok(name) => name, Err(_) => return None, }; @@ -633,7 +597,7 @@ impl PathId { * this. Manual driver unbind/bind, parallel hotplug/unplug will * get into the way of this "I hope it works" logic. */ - let base = match hostdev.borrow().get_syspath() { + let base = match hostdev.get_syspath() { Ok(base) => base, Err(_) => return None, }; @@ -695,8 +659,8 @@ impl PathId { Some(hostdev) } - fn format_lun_number(&self, dev: Rc>) -> String { - let sysnum = match dev.borrow().get_sysnum() { + fn format_lun_number(&self, dev: Rc) -> String { + let sysnum = match dev.get_sysnum() { Ok(sysnum) => sysnum, Err(_) => return String::new(), }; @@ -721,12 +685,8 @@ impl PathId { path } - fn handle_cciss( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let name = match parent.borrow().get_sysname() { + fn handle_cciss(&self, parent: Rc, path: &mut String) -> Option> { + let name = match parent.get_sysname() { Ok(s) => s, Err(_) => return None, }; @@ -750,12 +710,8 @@ impl PathId { self.skip_subsystem(parent, &name) } - fn handle_usb( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let devtype = match parent.borrow().get_devtype() { + fn handle_usb(&self, parent: Rc, path: &mut String) -> Option> { + let devtype = match parent.get_devtype() { Ok(devtype) => devtype, Err(_) => return Some(parent.clone()), }; @@ -764,7 +720,7 @@ impl PathId { return Some(parent); } - let sysname = match parent.borrow().get_sysname() { + let sysname = match parent.get_sysname() { Ok(sysname) => sysname, Err(_) => return Some(parent.clone()), }; @@ -779,12 +735,8 @@ impl PathId { self.skip_subsystem(parent, "usb") } - fn handle_bcma( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let sysname = match parent.borrow().get_sysname() { + fn handle_bcma(&self, parent: Rc, path: &mut String) -> Option> { + let sysname = match parent.get_sysname() { Ok(sysname) => sysname, Err(_) => return None, }; @@ -802,12 +754,8 @@ impl PathId { Some(parent) } - fn handle_serio( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let sysnum = match parent.borrow().get_sysnum() { + fn handle_serio(&self, parent: Rc, path: &mut String) -> Option> { + let sysnum = match parent.get_sysnum() { Ok(sysnum) => sysnum, Err(_) => return Some(parent.clone()), }; @@ -822,12 +770,12 @@ impl PathId { fn handle_subsys( &self, - parent: Rc>, + parent: Rc, subsys: String, path: &mut String, sysname: &mut String, compat_path: &mut String, - ) -> Option>> { + ) -> Option> { self.path_prepend(path, format!("{}-{}", subsys, sysname)); if !compat_path.is_empty() { self.path_prepend(compat_path, format!("{}-{}", subsys, sysname)); @@ -835,16 +783,12 @@ impl PathId { self.skip_subsystem(parent, &subsys) } - fn handle_ap( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let systype = parent.borrow().get_sysattr_value("type"); - let func = parent.borrow().get_sysattr_value("ap_functions"); + fn handle_ap(&self, parent: Rc, path: &mut String) -> Option> { + let systype = parent.get_sysattr_value("type"); + let func = parent.get_sysattr_value("ap_functions"); if systype.is_ok() && func.is_ok() { self.path_prepend(path, format!("ap-{}-{}", systype.unwrap(), func.unwrap())); - } else if let Ok(sysname) = parent.borrow().get_sysname() { + } else if let Ok(sysname) = parent.get_sysname() { self.path_prepend(path, format!("ap-{}", sysname)); } @@ -853,14 +797,14 @@ impl PathId { fn handle_nvme( &self, - dev: Rc>, - parent: Rc>, + dev: Rc, + parent: Rc, path: &mut String, compat_path: &mut String, supported_parent: &mut bool, supported_transport: &mut bool, - ) -> Option>> { - if let Ok(nsid) = dev.borrow().get_sysattr_value("nsid") { + ) -> Option> { + if let Ok(nsid) = dev.get_sysattr_value("nsid") { self.path_prepend(path, format!("nvme-{}", nsid)); if !compat_path.is_empty() { self.path_prepend(compat_path, format!("nvme-{}", nsid)); @@ -875,14 +819,14 @@ impl PathId { fn handle_nvme_subsystem( &self, - dev: Rc>, - parent: Rc>, + dev: Rc, + parent: Rc, path: &mut String, compat_path: &mut String, supported_parent: &mut bool, supported_transport: &mut bool, - ) -> Result>>> { - if let Ok(nsid) = dev.borrow().get_sysattr_value("nsid") { + ) -> Result>> { + if let Ok(nsid) = dev.get_sysattr_value("nsid") { self.path_prepend(path, format!("nvme-{}", nsid)); if !compat_path.is_empty() { self.path_prepend(compat_path, format!("nvme-{}", nsid)); @@ -898,12 +842,8 @@ impl PathId { Ok(Some(parent)) } - fn handle_nvme_spi( - &self, - parent: Rc>, - path: &mut String, - ) -> Option>> { - let sysnum = match parent.borrow().get_sysnum() { + fn handle_nvme_spi(&self, parent: Rc, path: &mut String) -> Option> { + let sysnum = match parent.get_sysnum() { Ok(sysnum) => sysnum, Err(_) => return Some(parent.clone()), }; @@ -914,7 +854,7 @@ impl PathId { Some(parent) } - fn find_real_nvme_parent(&self, dev: Rc>) -> Result>> { + fn find_real_nvme_parent(&self, dev: Rc) -> Result> { /* If the device belongs to "nvme-subsystem" (not to be confused with "nvme"), which happens when * NVMe multipathing is enabled in the kernel (/sys/module/nvme_core/parameters/multipath is Y), * then the syspath is something like the following: @@ -922,7 +862,7 @@ impl PathId { * Hence, we need to find the 'real parent' in "nvme" subsystem, e.g, * /sys/devices/pci0000:00/0000:00:1c.4/0000:3c:00.0/nvme/nvme0 */ - let sysname = match dev.borrow().get_sysname() { + let sysname = match dev.get_sysname() { Ok(name) => name, Err(_) => { return Err(Error::BuiltinCommandError { @@ -947,7 +887,7 @@ impl PathId { let sysname = &sysname[..sysname.len() - end.len()]; match Device::from_subsystem_sysname("nvme", sysname) { - Ok(dev) => Ok(Rc::new(RefCell::new(dev))), + Ok(dev) => Ok(Rc::new(dev)), Err(e) => Err(Error::BuiltinCommandError { msg: format!("Failed to get_sysname :{:?}", e), }), @@ -962,16 +902,12 @@ impl PathId { } } - fn skip_subsystem( - &self, - device: Rc>, - subsys: &str, - ) -> Option>> { + fn skip_subsystem(&self, device: Rc, subsys: &str) -> Option> { let mut dev = device.clone(); let mut parent = device; #[allow(clippy::while_let_loop)] loop { - let subsystem = match parent.borrow().get_subsystem() { + let subsystem = match parent.get_subsystem() { Ok(str) => str, Err(_e) => break, }; @@ -982,7 +918,7 @@ impl PathId { dev = parent.clone(); - let temp = match parent.borrow().get_parent() { + let temp = match parent.get_parent() { Ok(res) => res, Err(_e) => break, }; diff --git a/exts/devmaster/src/lib/builtin/usb_id.rs b/exts/devmaster/src/lib/builtin/usb_id.rs index 7bc52234..28f33440 100644 --- a/exts/devmaster/src/lib/builtin/usb_id.rs +++ b/exts/devmaster/src/lib/builtin/usb_id.rs @@ -19,7 +19,6 @@ use crate::utils::commons::*; use crate::{error::*, log_dev}; use device::Device; use snafu::ResultExt; -use std::cell::RefCell; use std::ffi::CString; use std::fs::File; use std::io::Read; @@ -179,30 +178,24 @@ impl UsbId { .get_parent_with_subsystem_devtype("usb", Some("usb_interface")) .context(DeviceSnafu)?; - let _interface_syspath = dev_interface.borrow().get_syspath().context(DeviceSnafu)?; + let _interface_syspath = dev_interface.get_syspath().context(DeviceSnafu)?; info.ifnum = dev_interface - .borrow() .get_sysattr_value("bInterfacceNumber") .unwrap_or_default(); info.driver = dev_interface - .borrow() .get_sysattr_value("driver") .unwrap_or_default(); info.if_class = dev_interface - .borrow() .get_sysattr_value("bInterfaceClass") .context(DeviceSnafu)?; info.type_str = match info.if_class.parse::().context(ParseIntSnafu)? { 8 => { let mut type_str = String::new(); - if let Ok(if_subclass) = dev_interface - .borrow() - .get_sysattr_value("bInterfaceSubClass") - { + if let Ok(if_subclass) = dev_interface.get_sysattr_value("bInterfaceSubClass") { type_str = UsbId::usb_mass_storage_ifsubtype(&if_subclass, &mut info.protocol) .unwrap() .to_string(); @@ -220,7 +213,7 @@ impl UsbId { .get_parent_with_subsystem_devtype("scsi", Some("scsi_device")) .context(DeviceSnafu)?; - let scsi_sysname = dev_scsi.borrow().get_sysname().context(DeviceSnafu)?; + let scsi_sysname = dev_scsi.get_sysname().context(DeviceSnafu)?; let mut _host: u32 = 0; let mut _bus: u32 = 0; @@ -241,7 +234,7 @@ impl UsbId { if ret != 4 { log_dev!( debug, - &dev_scsi.borrow(), + &dev_scsi, format!("Failed to parse target number '{}'", scsi_sysname) ); return Err(Error::Nix { @@ -249,38 +242,26 @@ impl UsbId { }); } - let scsi_vendor: String = dev_scsi - .borrow() - .get_sysattr_value("vendor") - .context(DeviceSnafu)?; + let scsi_vendor: String = dev_scsi.get_sysattr_value("vendor").context(DeviceSnafu)?; // scsi_vendor to vendor encode_devnode_name(&scsi_vendor, &mut info.vendor_enc); info.vendor = replace_whitespace(&scsi_vendor); info.vendor = replace_chars(&info.vendor, ""); - let scsi_model = dev_scsi - .borrow() - .get_sysattr_value("model") - .context(DeviceSnafu)?; + let scsi_model = dev_scsi.get_sysattr_value("model").context(DeviceSnafu)?; // scsi_model to model encode_devnode_name(&scsi_model, &mut info.model_enc); info.model = replace_whitespace(&scsi_model); info.model = replace_chars(&info.model, ""); - let scsi_type_str = dev_scsi - .borrow() - .get_sysattr_value("type") - .context(DeviceSnafu)?; + let scsi_type_str = dev_scsi.get_sysattr_value("type").context(DeviceSnafu)?; // scsi_type_str to type_str if let Some(s) = UsbId::scsi_type(&scsi_type_str) { info.type_str = s.to_string(); }; - let scsi_revision = dev_scsi - .borrow() - .get_sysattr_value("rev") - .context(DeviceSnafu)?; + let scsi_revision = dev_scsi.get_sysattr_value("rev").context(DeviceSnafu)?; // scsi_revision to revision, unimplemented!() info.revision = replace_whitespace(&scsi_revision); @@ -365,21 +346,21 @@ impl Builtin for UsbId { let device = exec_unit.get_device(); let mut info = UsbInfo::default(); - let mut usb_device = Rc::new(RefCell::new(Device::default())); + let mut usb_device = Rc::new(Device::default()); - let _syspath = device.borrow().get_syspath().context(DeviceSnafu)?; - let _sysname = device.borrow().get_sysname().context(DeviceSnafu)?; - let devtype = device.borrow().get_devtype().context(DeviceSnafu)?; + let _syspath = device.get_syspath().context(DeviceSnafu)?; + let _sysname = device.get_sysname().context(DeviceSnafu)?; + let devtype = device.get_devtype().context(DeviceSnafu)?; #[allow(clippy::never_loop)] loop { if devtype == "usb_device" { - let _ = Self::dev_if_packed_info(&device.borrow(), &mut info); + let _ = Self::dev_if_packed_info(&device, &mut info); usb_device = device.clone(); break; } - match self.interface_directory(&device.borrow(), &mut info) { + match self.interface_directory(&device, &mut info) { Ok(true) => (), Ok(false) => break, Err(e) => return Err(e), @@ -388,13 +369,12 @@ impl Builtin for UsbId { log::debug!("if_class:{} protocol:{}", info.if_class, info.protocol); let dev_usb = device - .borrow() .get_parent_with_subsystem_devtype("usb", Some("usb_interface")) .context(DeviceSnafu)?; - let _ = Self::dev_if_packed_info(&dev_usb.borrow(), &mut info); + let _ = Self::dev_if_packed_info(&dev_usb, &mut info); - match self.mass_storage(&device.borrow(), &mut info) { + match self.mass_storage(&device, &mut info) { Ok(_) => (), Err(e) => { log::error!("{:?}", e); @@ -405,10 +385,10 @@ impl Builtin for UsbId { break; } - self.set_sysattr(&usb_device.borrow(), &mut info)?; + self.set_sysattr(&usb_device, &mut info)?; // Set up a temporary variable id_bus here to prevent deadlock. - let id_bus = device.borrow().get_property_value("ID_BUS"); + let id_bus = device.get_property_value("ID_BUS"); match id_bus { Ok(_) => log::debug!("ID_BUS property is already set, setting only properties prefixed with \"ID_USB_\"."), Err(_) => { @@ -555,7 +535,7 @@ mod test { for device in enumerator.iter() { let builtin = UsbId {}; - if let Ok(str) = device.borrow().get_devpath() { + if let Ok(str) = device.get_devpath() { if !str.contains("usb") { continue; } diff --git a/exts/devmaster/src/lib/config/netif_conf.rs b/exts/devmaster/src/lib/config/netif_conf.rs index 3e47cf26..9c593902 100644 --- a/exts/devmaster/src/lib/config/netif_conf.rs +++ b/exts/devmaster/src/lib/config/netif_conf.rs @@ -17,7 +17,7 @@ use device::Device; use fnmatch_sys::fnmatch; use lazy_static::lazy_static; use serde::Deserialize; -use std::{cell::RefCell, os::raw::c_char, path::Path, rc::Rc}; +use std::{os::raw::c_char, path::Path, rc::Rc}; use crate::log_dev; @@ -59,11 +59,11 @@ pub(crate) struct Link { } impl NetifConfigData { - pub(crate) fn match_netif(&self, netif: Rc>) -> bool { + pub(crate) fn match_netif(&self, netif: Rc) -> bool { if let Some(original_name) = &self.Match.OriginalName { let pattern = format!("{}\0", original_name); - match netif.borrow().get_sysname() { + match netif.get_sysname() { Ok(sysname) => { let source = format!("{}\0", sysname); @@ -79,11 +79,7 @@ impl NetifConfigData { } } Err(e) => { - log_dev!( - error, - netif.borrow(), - format!("Failed to get sysname: {}", e) - ); + log_dev!(error, netif, format!("Failed to get sysname: {}", e)); return false; } } @@ -159,7 +155,7 @@ impl NetifConfigCtx { } } - pub(crate) fn get_config(&self, netif: Rc>) -> Option<&NetifConfig> { + pub(crate) fn get_config(&self, netif: Rc) -> Option<&NetifConfig> { self.configs .iter() .find(|&config| config.inner.match_netif(netif.clone())) diff --git a/exts/devmaster/src/lib/error.rs b/exts/devmaster/src/lib/error.rs index b2a0bbe2..5f1480ae 100644 --- a/exts/devmaster/src/lib/error.rs +++ b/exts/devmaster/src/lib/error.rs @@ -15,7 +15,7 @@ use crate::log_dev; use device::Device; use snafu::prelude::*; -use std::{cell::RefCell, ffi::OsString, rc::Rc, str::Utf8Error}; +use std::{ffi::OsString, rc::Rc, str::Utf8Error}; pub(crate) type Result = std::result::Result; @@ -133,9 +133,9 @@ pub(crate) trait Log { fn log_dev_error(self, dev: &Device, msg: &str) -> Self; fn log_dev_debug(self, dev: &Device, msg: &str) -> Self; fn log_dev_info(self, dev: &Device, msg: &str) -> Self; - fn log_dev_error_option(self, dev: Option>>, msg: &str) -> Self; - fn log_dev_debug_option(self, dev: Option>>, msg: &str) -> Self; - fn log_dev_info_option(self, dev: Option>>, msg: &str) -> Self; + fn log_dev_error_option(self, dev: Option>, msg: &str) -> Self; + fn log_dev_debug_option(self, dev: Option>, msg: &str) -> Self; + fn log_dev_info_option(self, dev: Option>, msg: &str) -> Self; } impl Log for std::result::Result { @@ -175,28 +175,28 @@ impl Log for std::result::Result { e }) } - fn log_dev_error_option(self, dev: Option>>, msg: &str) -> Self { + fn log_dev_error_option(self, dev: Option>, msg: &str) -> Self { self.map_err(|e| { match dev { - Some(d) => log_dev!(error, d.borrow(), format!("{}: {}", msg, e)), + Some(d) => log_dev!(error, d, format!("{}: {}", msg, e)), None => log::error!("{}: {}", msg, e), } e }) } - fn log_dev_debug_option(self, dev: Option>>, msg: &str) -> Self { + fn log_dev_debug_option(self, dev: Option>, msg: &str) -> Self { self.map_err(|e| { match dev { - Some(d) => log_dev!(debug, d.borrow(), format!("{}: {}", msg, e)), + Some(d) => log_dev!(debug, d, format!("{}: {}", msg, e)), None => log::error!("{}: {}", msg, e), } e }) } - fn log_dev_info_option(self, dev: Option>>, msg: &str) -> Self { + fn log_dev_info_option(self, dev: Option>, msg: &str) -> Self { self.map_err(|e| { match dev { - Some(d) => log_dev!(info, d.borrow(), format!("{}: {}", msg, e)), + Some(d) => log_dev!(info, d, format!("{}: {}", msg, e)), None => log::error!("{}: {}", msg, e), } e diff --git a/exts/devmaster/src/lib/framework/worker_manager.rs b/exts/devmaster/src/lib/framework/worker_manager.rs index bddc9deb..0c2b87f1 100644 --- a/exts/devmaster/src/lib/framework/worker_manager.rs +++ b/exts/devmaster/src/lib/framework/worker_manager.rs @@ -144,12 +144,12 @@ impl Worker { .unwrap_or_default() ); - let device = Rc::new(RefCell::new(device)); + let device = Rc::new(device); let _ = execute_mgr.process_device(device.clone()); log::info!("Worker {}: finished job", id); - broadcaster.send_device(&device.borrow(), None).unwrap(); + broadcaster.send_device(&device, None).unwrap(); let mut tcp_stream = UnixStream::connect(listen_addr.as_str()) .unwrap_or_else(|error| { diff --git a/exts/devmaster/src/lib/rules/exec_mgr.rs b/exts/devmaster/src/lib/rules/exec_mgr.rs index 03da901d..3f6cd143 100644 --- a/exts/devmaster/src/lib/rules/exec_mgr.rs +++ b/exts/devmaster/src/lib/rules/exec_mgr.rs @@ -86,11 +86,8 @@ impl ExecuteManager { } /// process a device object - pub(crate) fn process_device(&self, device: Rc>) -> Result<()> { - log::debug!( - "{}", - device_trace!("Start processing device", device.borrow()) - ); + pub(crate) fn process_device(&self, device: Rc) -> Result<()> { + log::debug!("{}", device_trace!("Start processing device", device)); *self.current_unit.borrow_mut() = Some(ExecuteUnit::new(device.clone())); // lock whole disk: todo @@ -105,10 +102,7 @@ impl ExecuteManager { // begin inotify watch: todo - log::debug!( - "{}", - device_trace!("Finish processing device", device.borrow()) - ); + log::debug!("{}", device_trace!("Finish processing device", device)); *self.current_unit.borrow_mut() = None; @@ -122,10 +116,9 @@ impl ExecuteManager { let device = self.current_unit.borrow().as_ref().unwrap().get_device(); let action = device - .borrow() .get_action() .context(DeviceSnafu) - .log_dev_error(&device.borrow(), "not from uevent")?; + .log_dev_error(&device, "not from uevent")?; if action == DeviceAction::Remove { return self.execute_rules_on_remove(); @@ -140,7 +133,7 @@ impl ExecuteManager { .as_ref() .unwrap() .clone_device_db() - .log_dev_debug(&device.borrow(), "failed to clone with db"); + .log_dev_debug(&device, "failed to clone with db"); let device_db_clone = self .current_unit .borrow() @@ -149,13 +142,12 @@ impl ExecuteManager { .get_device_db_clone(); // copy all tags to cloned device - for tag in &device.borrow().tag_iter() { - device_db_clone.borrow().add_tag(tag, false); + for tag in &device.tag_iter() { + device_db_clone.add_tag(tag, false); } // add property to cloned device device_db_clone - .borrow() .add_property("ID_RENAMING", "") .map_err(|e| Error::RulesExecuteError { msg: format!("failed to add tag ({})", e), @@ -171,7 +163,7 @@ impl ExecuteManager { .as_ref() .unwrap() .rename_netif() - .log_dev_error(&device.borrow(), "rename ifname failed")?; + .log_dev_error(&device, "rename ifname failed")?; } // update devnode @@ -183,18 +175,17 @@ impl ExecuteManager { // preserve old, or get new initialization timestamp initialize_device_usec(device.clone(), device_db_clone.clone()) - .log_dev_error(&device.borrow(), "failed to initialize device timestamp")?; + .log_dev_error(&device, "failed to initialize device timestamp")?; // update tags and database let _ = device_update_tag(device.clone(), Some(device_db_clone), true); device - .borrow() .update_db() .context(DeviceSnafu) .log_error("failed to update db")?; - device.borrow().set_is_initialized(); + device.set_is_initialized(); Ok(()) } @@ -206,7 +197,6 @@ impl ExecuteManager { let device = self.current_unit.borrow().as_ref().unwrap().get_device(); device - .borrow() .read_db_internal(true) .context(DeviceSnafu) .log_error("remove event failed")?; @@ -219,7 +209,7 @@ impl ExecuteManager { let ret = self.apply_rules(); - if device.borrow().get_devnum().is_err() { + if device.get_devnum().is_err() { return ret; } @@ -296,15 +286,15 @@ impl ExecuteManager { let current_unit = self.current_unit.borrow(); let device = current_unit.as_ref().unwrap().get_device(); - let action = device.borrow().get_action().context(DeviceSnafu)?; + let action = device.get_action().context(DeviceSnafu)?; let current_line = self.current_rule_line.borrow().clone(); if action != DeviceAction::Remove { - if device.borrow().get_devnum().is_ok() { + if device.get_devnum().is_ok() { mask |= RuleLineType::HAS_DEVLINK; } - if device.borrow().get_ifindex().is_ok() { + if device.get_ifindex().is_ok() { mask |= RuleLineType::HAS_NAME; } } @@ -384,7 +374,7 @@ impl ExecuteManager { } /// apply rule token on device - pub(crate) fn apply_rule_token(&self, device: Rc>) -> Result { + pub(crate) fn apply_rule_token(&self, device: Rc) -> Result { debug_assert!(self.current_unit.borrow().is_some()); debug_assert!(self.current_rule_token.borrow().read().unwrap().is_some()); let token = self.current_rule_token.borrow().clone(); @@ -408,10 +398,8 @@ impl ExecuteManager { let token_type = token.read().unwrap().as_ref().unwrap().r#type; match token_type { MatchAction => { - let action = execute_err!( - token.read().unwrap().as_ref().unwrap(), - device.borrow().get_action() - )?; + let action = + execute_err!(token.read().unwrap().as_ref().unwrap(), device.get_action())?; Ok(token .read() @@ -423,7 +411,7 @@ impl ExecuteManager { MatchDevpath => { let devpath = execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_devpath() + device.get_devpath() )?; Ok(token @@ -436,7 +424,7 @@ impl ExecuteManager { MatchKernel | MatchParentsKernel => { let sysname = execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_sysname() + device.get_sysname() )?; Ok(token @@ -447,7 +435,7 @@ impl ExecuteManager { .pattern_match(&sysname)) } MatchDevlink => { - for devlink in &device.borrow().devlink_iter() { + for devlink in &device.devlink_iter() { if token .read() .unwrap() @@ -471,10 +459,7 @@ impl ExecuteManager { .unwrap() .pattern_match(¤t_unit.as_ref().unwrap().get_name())), MatchEnv => { - let value = match device - .borrow() - .get_property_value(token_attribute.as_ref().unwrap()) - { + let value = match device.get_property_value(token_attribute.as_ref().unwrap()) { Ok(v) => v, Err(e) => { if e.get_errno() != Errno::ENOENT { @@ -503,7 +488,7 @@ impl ExecuteManager { todo!() } MatchTag | MatchParentsTag => { - for tag in &device.borrow().current_tag_iter() { + for tag in &device.current_tag_iter() { if token.read().unwrap().as_ref().unwrap().pattern_match(tag) ^ (token.read().unwrap().as_ref().unwrap().op == OperatorType::Nomatch) { @@ -518,7 +503,7 @@ impl ExecuteManager { MatchSubsystem | MatchParentsSubsystem => { let subsystem = execute_err_ignore_ENOENT!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_subsystem() + device.get_subsystem() )?; Ok(token @@ -531,7 +516,7 @@ impl ExecuteManager { MatchDriver | MatchParentsDriver => { let driver = execute_err_ignore_ENOENT!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_driver() + device.get_driver() )?; Ok(token @@ -574,7 +559,7 @@ impl ExecuteManager { // only throw out error when getting the syspath of device let syspath = execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_syspath() + device.get_syspath() ) .map_err(|e| { log_rule_token!( @@ -696,7 +681,7 @@ impl ExecuteManager { Ok((key, value)) => { execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().add_property(&key, &value) + device.add_property(&key, &value) )?; } Err(e) => { @@ -765,7 +750,7 @@ impl ExecuteManager { Ok((key, value)) => { execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().add_property(&key, &value) + device.add_property(&key, &value) )?; log_rule_token!( @@ -881,7 +866,7 @@ impl ExecuteManager { MatchImportDb => { let dev_db_clone = current_unit.as_ref().unwrap().get_device_db_clone(); - let val = match dev_db_clone.borrow().get_property_value(&token_value) { + let val = match dev_db_clone.get_property_value(&token_value) { Ok(v) => v, Err(e) => { if e.get_errno() == Errno::ENOENT { @@ -914,7 +899,7 @@ impl ExecuteManager { execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().add_property(&token_value, &val) + device.add_property(&token_value, &val) )?; Ok(token.read().unwrap().as_ref().unwrap().op == OperatorType::Match) @@ -943,9 +928,7 @@ impl ExecuteManager { execute_err!( token.read().unwrap().as_ref().unwrap(), - device - .borrow() - .add_property(&token_value, if value.is_empty() { "1" } else { value }) + device.add_property(&token_value, if value.is_empty() { "1" } else { value }) )?; Ok(token.read().unwrap().as_ref().unwrap().op == OperatorType::Match) @@ -971,7 +954,7 @@ impl ExecuteManager { glob_patterns.push(pat); } - let parent = match device.borrow().get_parent() { + let parent = match device.get_parent() { Ok(p) => p, Err(e) => { // do not match if the device has no parent @@ -994,7 +977,7 @@ impl ExecuteManager { } }; - for (k, v) in &parent.borrow().property_iter() { + for (k, v) in &parent.property_iter() { let source = format!("{}\0", k); // check whether the key of property matches the @@ -1026,7 +1009,7 @@ impl ExecuteManager { execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().add_property(k, v) + device.add_property(k, v) )?; } @@ -1115,7 +1098,7 @@ impl ExecuteManager { Ok(true) } AssignOptionsDbPersist => { - device.borrow().set_db_persist(); + device.set_db_persist(); log_rule_token!( debug, token.read().unwrap().as_ref().unwrap(), @@ -1123,7 +1106,7 @@ impl ExecuteManager { "set db '{}' to persistence", execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_device_id() + device.get_device_id() )? ) ); @@ -1165,7 +1148,7 @@ impl ExecuteManager { token.read().unwrap().as_ref().unwrap(), token_value.parse::().context(ParseIntSnafu) )?; - device.borrow().set_devlink_priority(r); + device.set_devlink_priority(r); log_rule_token!( debug, token.read().unwrap().as_ref().unwrap(), @@ -1455,9 +1438,7 @@ impl ExecuteManager { */ execute_err!( token.read().unwrap().as_ref().unwrap(), - device - .borrow() - .add_property(&token_attribute.unwrap(), &token_value) + device.add_property(&token_attribute.unwrap(), &token_value) )?; return Ok(true); } @@ -1465,9 +1446,8 @@ impl ExecuteManager { let mut value: String = String::new(); if token.read().unwrap().as_ref().unwrap().op == OperatorType::Add { - if let Ok(old_value) = device - .borrow() - .get_property_value(token_attribute.as_ref().unwrap()) + if let Ok(old_value) = + device.get_property_value(token_attribute.as_ref().unwrap()) { value.push_str(&old_value); value.push(' '); @@ -1490,9 +1470,7 @@ impl ExecuteManager { execute_err!( token.read().unwrap().as_ref().unwrap(), - device - .borrow() - .add_property(token_attribute.as_ref().unwrap(), &v) + device.add_property(token_attribute.as_ref().unwrap(), &v) )?; Ok(true) @@ -1515,7 +1493,7 @@ impl ExecuteManager { }; if token.read().unwrap().as_ref().unwrap().op == OperatorType::Assign { - device.borrow().cleanup_tags(); + device.cleanup_tags(); } if value @@ -1531,9 +1509,9 @@ impl ExecuteManager { } if token.read().unwrap().as_ref().unwrap().op == OperatorType::Remove { - device.borrow().remove_tag(&value); + device.remove_tag(&value); } else { - device.borrow().add_tag(&value, true); + device.add_tag(&value, true); } Ok(true) @@ -1547,7 +1525,7 @@ impl ExecuteManager { current_unit.as_ref().unwrap().set_name_final(true); } - if device.borrow().get_ifindex().is_err() { + if device.get_ifindex().is_err() { log_rule_token!( error, token.read().unwrap().as_ref().unwrap(), @@ -1600,7 +1578,7 @@ impl ExecuteManager { return Ok(true); } - if device.borrow().get_devnum().is_err() { + if device.get_devnum().is_err() { return Ok(true); } @@ -1611,7 +1589,7 @@ impl ExecuteManager { if [OperatorType::Assign, OperatorType::AssignFinal] .contains(&token.read().unwrap().as_ref().unwrap().op) { - device.borrow().cleanup_devlinks(); + device.cleanup_devlinks(); } let value = match current_unit.as_ref().unwrap().apply_format( @@ -1655,7 +1633,7 @@ impl ExecuteManager { execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().add_devlink(&devlink) + device.add_devlink(&devlink) )?; } } @@ -1670,7 +1648,7 @@ impl ExecuteManager { } else { let syspath = execute_err!( token.read().unwrap().as_ref().unwrap(), - device.borrow().get_syspath() + device.get_syspath() )?; format!("{}/{}", syspath, token_attribute.as_ref().unwrap()) }; @@ -1824,7 +1802,7 @@ impl ExecuteManager { } let tmp = current_unit.as_ref().unwrap().get_parent().unwrap(); - match tmp.borrow().get_parent() { + match tmp.get_parent() { Ok(d) => { current_unit.as_ref().unwrap().set_parent(Some(d)); } @@ -1864,7 +1842,7 @@ impl ExecuteManager { Err(e) => { log_dev!( debug, - device.borrow(), + device, format!("Failed to run builtin command '{}': {}", builtin_str, e) ); continue; @@ -1873,7 +1851,7 @@ impl ExecuteManager { log_dev!( debug, - device.borrow(), + device, format!("Running builtin command '{}'", builtin_str) ); @@ -1886,7 +1864,7 @@ impl ExecuteManager { ) { log_dev!( debug, - &device.borrow(), + &device, format!("Failed to run builtin command '{}': '{}'", builtin_str, e) ); } @@ -1902,11 +1880,7 @@ impl ExecuteManager { * todo: redundant string vector clone */ for cmd_str in ¤t_unit.as_ref().unwrap().program_run_list_iter() { - log_dev!( - debug, - device.borrow(), - format!("Running program '{}'", cmd_str) - ); + log_dev!(debug, device, format!("Running program '{}'", cmd_str)); if let Err(e) = spawn( cmd_str, @@ -1915,7 +1889,7 @@ impl ExecuteManager { ) { log_dev!( debug, - device.borrow(), + device, format!("Failed to run program '{}': '{}'", cmd_str, e) ); } @@ -1967,56 +1941,59 @@ impl RuleToken { (self.op == OperatorType::Nomatch) ^ value_match } - fn attr_match(&self, device: Rc>, unit: &ExecuteUnit) -> Result { + fn attr_match(&self, device: Rc, unit: &ExecuteUnit) -> Result { debug_assert!(self.attr.is_some()); let attr = self.get_token_attribute().unwrap(); - let val = - match self.attr_subst_type { - SubstituteType::Plain => { - if let Ok(v) = device.borrow().get_sysattr_value(&attr).map_err(|e| { - Error::RulesExecuteError { + let val = match self.attr_subst_type { + SubstituteType::Plain => { + if let Ok(v) = + device + .get_sysattr_value(&attr) + .map_err(|e| Error::RulesExecuteError { msg: format!("failed to match sysattr: ({})", e), errno: e.get_errno(), - } - }) { - v - } else { - return Ok(false); - } + }) + { + v + } else { + return Ok(false); } - SubstituteType::Format => { - let attr_name = - unit.apply_format(&attr, false) - .map_err(|e| Error::RulesExecuteError { - msg: format!("failed to match sysattr: ({})", e), - errno: e.get_errno(), - })?; - if let Ok(v) = device.borrow().get_sysattr_value(&attr_name).map_err(|e| { - Error::RulesExecuteError { + } + SubstituteType::Format => { + let attr_name = + unit.apply_format(&attr, false) + .map_err(|e| Error::RulesExecuteError { msg: format!("failed to match sysattr: ({})", e), errno: e.get_errno(), - } - }) { - v - } else { - return Ok(false); - } - } - SubstituteType::Subsys => { - resolve_subsystem_kernel(&attr, true).map_err(|e| Error::RulesExecuteError { - msg: format!("failed to match sysattr: ({})", e), - errno: e.get_errno(), - })? - } - _ => { - return Err(Error::RulesExecuteError { - msg: "invalid substitute type.".to_string(), - errno: Errno::EINVAL, - }) + })?; + if let Ok(v) = + device + .get_sysattr_value(&attr_name) + .map_err(|e| Error::RulesExecuteError { + msg: format!("failed to match sysattr: ({})", e), + errno: e.get_errno(), + }) + { + v + } else { + return Ok(false); } - }; + } + SubstituteType::Subsys => { + resolve_subsystem_kernel(&attr, true).map_err(|e| Error::RulesExecuteError { + msg: format!("failed to match sysattr: ({})", e), + errno: e.get_errno(), + })? + } + _ => { + return Err(Error::RulesExecuteError { + msg: "invalid substitute type.".to_string(), + errno: Errno::EINVAL, + }) + } + }; Ok(self.pattern_match(&val)) } @@ -2151,7 +2128,7 @@ mod tests { #[test] #[ignore] fn test_subst_format() { - let device = Rc::new(RefCell::new(Device::from_path("/dev/sda1").unwrap())); + let device = Rc::new(Device::from_path("/dev/sda1").unwrap()); let unit = ExecuteUnit::new(device); println!( "{:?}", @@ -2167,9 +2144,7 @@ mod tests { .unwrap() ); - let device = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); + let device = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); let unit = ExecuteUnit::new(device); println!( "{:?}", @@ -2180,9 +2155,7 @@ mod tests { #[test] fn test_apply_format() { - let device = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); + let device = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); let unit = ExecuteUnit::new(device); // test long substitution formatter // $kernel @@ -2287,9 +2260,7 @@ mod tests { #[test] #[ignore] fn test_apply_format_2() { - let device = Rc::new(RefCell::new( - Device::from_subsystem_sysname("block", "sda1").unwrap(), - )); + let device = Rc::new(Device::from_subsystem_sysname("block", "sda1").unwrap()); let unit = ExecuteUnit::new(device); assert_eq!(unit.apply_format("$number", false).unwrap(), "1"); assert_eq!(unit.apply_format("$major", false).unwrap(), "8"); @@ -2310,7 +2281,7 @@ mod tests { value: &str, rules: Arc>, rule_line: Arc>>, - device: Rc>, + device: Rc, ) -> Result { let token = RuleToken::parse_token( key.to_string(), @@ -2342,10 +2313,8 @@ mod tests { false, ); - let device = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); - device.borrow().set_base_path("/tmp/devmaster"); + let device = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); + device.set_base_path("/tmp/devmaster"); let rules = Arc::new(RwLock::new(Rules::new(vec![], ResolveNameTime::Early))); let rule_file = Arc::new(RwLock::new(Some(RuleFile::new("".to_string())))); let rule_line = Arc::new(RwLock::new(Some(RuleLine::new( @@ -2357,7 +2326,7 @@ mod tests { let mgr = ExecuteManager::new(Arc::new(RwLock::new(Cache::new(vec![], vec![])))); *mgr.current_unit.borrow_mut() = Some(unit); - device.borrow().set_action_from_string("change").unwrap(); + device.set_action_from_string("change").unwrap(); assert!(mgr .test_apply_one_rule_token( "ACTION", @@ -2405,7 +2374,7 @@ mod tests { ) .unwrap()); - device.borrow().add_tag("xxx", true); + device.add_tag("xxx", true); assert!(mgr .test_apply_one_rule_token( "TAG", @@ -2510,12 +2479,9 @@ GOOD=LUCK", ) .unwrap()); - assert_eq!( - &device.borrow().get_property_value("HELLO").unwrap(), - "WORLD" - ); + assert_eq!(&device.get_property_value("HELLO").unwrap(), "WORLD"); - assert_eq!(&device.borrow().get_property_value("GOOD").unwrap(), "LUCK"); + assert_eq!(&device.get_property_value("GOOD").unwrap(), "LUCK"); remove_file("/tmp/property").unwrap(); @@ -2530,14 +2496,11 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert_eq!( - &device.borrow().get_property_value("WATER").unwrap(), - "FLOW" - ); + assert_eq!(&device.get_property_value("WATER").unwrap(), "FLOW"); create_tmp_file( "/tmp/devmaster/data", - &device.borrow().get_device_id().unwrap(), + &device.get_device_id().unwrap(), "E:BLACK=PINK", true, ); @@ -2558,13 +2521,10 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert_eq!( - &device.borrow().get_property_value("BLACK").unwrap(), - "PINK" - ); + assert_eq!(&device.get_property_value("BLACK").unwrap(), "PINK"); remove_file(&format!( "/tmp/devmaster/data/{}", - device.borrow().get_device_id().unwrap() + device.get_device_id().unwrap() )) .unwrap(); @@ -2579,11 +2539,7 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert!(!device - .borrow() - .get_property_value("root") - .unwrap() - .is_empty()); + assert!(!device.get_property_value("root").unwrap().is_empty()); assert!(mgr .test_apply_one_rule_token( @@ -2885,10 +2841,7 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert_eq!( - &device.borrow().get_property_value("BLACK").unwrap(), - "YELLOW" - ); + assert_eq!(&device.get_property_value("BLACK").unwrap(), "YELLOW"); assert!(mgr .test_apply_one_rule_token( @@ -2901,8 +2854,8 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert!(device.borrow().has_tag("aaa").unwrap()); - assert!(device.borrow().has_current_tag("aaa").unwrap()); + assert!(device.has_tag("aaa").unwrap()); + assert!(device.has_current_tag("aaa").unwrap()); assert!(mgr .test_apply_one_rule_token( @@ -2915,8 +2868,8 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert!(device.borrow().has_tag("aaa").unwrap()); - assert!(!device.borrow().has_current_tag("aaa").unwrap()); + assert!(device.has_tag("aaa").unwrap()); + assert!(!device.has_current_tag("aaa").unwrap()); assert!(mgr .test_apply_one_rule_token( @@ -2929,10 +2882,10 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert!(!device.borrow().has_tag("aaa").unwrap()); - assert!(!device.borrow().has_current_tag("aaa").unwrap()); - assert!(device.borrow().has_tag("bbb").unwrap()); - assert!(device.borrow().has_current_tag("bbb").unwrap()); + assert!(!device.has_tag("aaa").unwrap()); + assert!(!device.has_current_tag("aaa").unwrap()); + assert!(device.has_tag("bbb").unwrap()); + assert!(device.has_current_tag("bbb").unwrap()); assert!(mgr .test_apply_one_rule_token( @@ -3052,10 +3005,7 @@ GOOD=LUCK", device.clone(), ) .unwrap()); - assert_eq!( - &device.borrow().get_property_value("PAPER").unwrap(), - "BOOK" - ); + assert_eq!(&device.get_property_value("PAPER").unwrap(), "BOOK"); assert!(!mgr .test_apply_one_rule_token( @@ -3137,12 +3087,10 @@ GOOD=LUCK", match LoopDev::new("/tmp/test_apply_rules", 1024 * 1024 * 10) { Ok(lo) => { let devpath = lo.get_device_path().unwrap(); - let dev = Rc::new(RefCell::new( - Device::from_path(devpath.to_str().unwrap()).unwrap(), - )); - dev.borrow().set_base_path("/tmp/devmaster"); + let dev = Rc::new(Device::from_path(devpath.to_str().unwrap()).unwrap()); + dev.set_base_path("/tmp/devmaster"); - dev.borrow().add_devlink("/dev/test").unwrap(); + dev.add_devlink("/dev/test").unwrap(); assert!(mgr .test_apply_one_rule_token( "SYMLINK", @@ -3176,7 +3124,7 @@ GOOD=LUCK", dev.clone(), ) .unwrap()); - assert!(dev.borrow().has_devlink("/dev/xxx")); + assert!(dev.has_devlink("/dev/xxx")); assert!(mgr .test_apply_one_rule_token( diff --git a/exts/devmaster/src/lib/rules/exec_unit.rs b/exts/devmaster/src/lib/rules/exec_unit.rs index 93684659..e17ca515 100644 --- a/exts/devmaster/src/lib/rules/exec_unit.rs +++ b/exts/devmaster/src/lib/rules/exec_unit.rs @@ -47,9 +47,9 @@ pub struct ExecuteUnit { } struct ExecuteUnitData { - device: Rc>, - parent: Option>>, - device_db_clone: Option>>, + device: Rc, + parent: Option>, + device_db_clone: Option>, name: String, program_result: String, mode: Option, @@ -73,7 +73,7 @@ struct ExecuteUnitData { } impl ExecuteUnitData { - fn new(device: Rc>) -> Self { + fn new(device: Rc) -> Self { ExecuteUnitData { device, parent: None, @@ -100,11 +100,11 @@ impl ExecuteUnitData { } } - fn get_device(&self) -> Rc> { + fn get_device(&self) -> Rc { self.device.clone() } - fn get_device_db_clone(&self) -> Rc> { + fn get_device_db_clone(&self) -> Rc { debug_assert!(self.device_db_clone.is_some()); self.device_db_clone.clone().unwrap() @@ -168,28 +168,27 @@ impl ExecuteUnitData { } fn clone_device_db(&mut self) -> Result<()> { - self.device_db_clone = Some(Rc::new(RefCell::new( + self.device_db_clone = Some(Rc::new( self.device - .borrow() .clone_with_db() .context(DeviceSnafu) - .log_dev_error(&self.device.borrow(), "failed to clone db")?, - ))); + .log_dev_error(&self.device, "failed to clone db")?, + )); Ok(()) } fn update_devnode(&mut self, seclabel_list: &HashMap) -> Result<()> { - if let Err(e) = self.device.borrow().get_devnum() { + if let Err(e) = self.device.get_devnum() { if e.is_errno(Errno::ENOENT) { return Ok(()); } - log_dev!(error, self.device.borrow(), e); + log_dev!(error, self.device, e); return Err(Error::Device { source: e }); } if self.uid.is_none() { - match self.device.borrow().get_devnode_uid() { + match self.device.get_devnode_uid() { Ok(uid) => self.uid = Some(uid), Err(e) => { if !e.is_errno(Errno::ENOENT) { @@ -200,7 +199,7 @@ impl ExecuteUnitData { } if self.gid.is_none() { - match self.device.borrow().get_devnode_gid() { + match self.device.get_devnode_gid() { Ok(gid) => self.gid = Some(gid), Err(e) => { if !e.is_errno(Errno::ENOENT) { @@ -211,7 +210,7 @@ impl ExecuteUnitData { } if self.mode.is_none() { - match self.device.borrow().get_devnode_mode() { + match self.device.get_devnode_mode() { Ok(mode) => self.mode = Some(mode), Err(e) => { if !e.is_errno(Errno::ENOENT) { @@ -223,7 +222,6 @@ impl ExecuteUnitData { let apply_mac = self .device - .borrow() .get_action() .map(|action| action == DeviceAction::Add) .unwrap_or(false); @@ -241,7 +239,7 @@ impl ExecuteUnitData { } fn rename_netif(&self) -> Result { - let ifindex = match self.device.borrow().get_ifindex().context(DeviceSnafu) { + let ifindex = match self.device.get_ifindex().context(DeviceSnafu) { Ok(ifindex) => ifindex, Err(e) => { if e.get_errno() == nix::Error::ENOENT { @@ -265,10 +263,10 @@ impl ExecuteUnitData { if e.get_errno() == nix::Error::EBUSY { log_dev!( info, - &self.device.borrow(), + &self.device, format!( "Network interface '{}' is busy, cannot rename to '{}'", - self.device.borrow().get_sysname().context(DeviceSnafu)?, + self.device.get_sysname().context(DeviceSnafu)?, self.name.clone(), ) ); @@ -280,11 +278,11 @@ impl ExecuteUnitData { log_dev!( info, - &self.device.borrow(), + &self.device, format!( "Network interface '{}' is renamed from '{}' to '{}'", - self.device.borrow().get_ifindex().context(DeviceSnafu)?, - self.device.borrow().get_sysname().context(DeviceSnafu)?, + self.device.get_ifindex().context(DeviceSnafu)?, + self.device.get_sysname().context(DeviceSnafu)?, self.name.clone(), ) ); @@ -326,7 +324,7 @@ impl ExecuteUnitData { ) -> Result { match subst_type { FormatSubstitutionType::Devnode => subst_format_map_err_ignore!( - self.device.borrow().get_devname(), + self.device.get_devname(), "devnode", Errno::ENOENT, String::default() @@ -343,19 +341,13 @@ impl ExecuteUnitData { // try to read attribute value form path '[/[SYSNAME]]' let value = if let Ok(v) = resolve_subsystem_kernel(&attr, true) { v - } else if let Ok(v) = self.device.borrow().get_sysattr_value(&attr) { + } else if let Ok(v) = self.device.get_sysattr_value(&attr) { v } else if self.parent.is_some() { // try to get sysattr upwards // we did not check whether self.parent is equal to self.device // this perhaps will result in problems - if let Ok(v) = self - .parent - .clone() - .unwrap() - .borrow() - .get_sysattr_value(&attr) - { + if let Ok(v) = self.parent.clone().unwrap().get_sysattr_value(&attr) { v } else { return Ok(String::default()); @@ -377,20 +369,18 @@ impl ExecuteUnitData { } subst_format_map_err_ignore!( - self.device.borrow().get_property_value(&attribute.unwrap()), + self.device.get_property_value(&attribute.unwrap()), "env", Errno::ENOENT, String::default() ) } - FormatSubstitutionType::Kernel => { - Ok(self.device.borrow().get_sysname().unwrap_or_else(|_| { - log::debug!("formatter 'kernel' got empty value."); - "".to_string() - })) - } + FormatSubstitutionType::Kernel => Ok(self.device.get_sysname().unwrap_or_else(|_| { + log::debug!("formatter 'kernel' got empty value."); + "".to_string() + })), FormatSubstitutionType::KernelNumber => subst_format_map_err_ignore!( - self.device.borrow().get_sysnum(), + self.device.get_sysnum(), "number", Errno::ENOENT, String::default() @@ -401,18 +391,16 @@ impl ExecuteUnitData { } subst_format_map_err_ignore!( - self.parent.as_ref().unwrap().borrow().get_driver(), + self.parent.as_ref().unwrap().get_driver(), "driver", Errno::ENOENT, String::default() ) } - FormatSubstitutionType::Devpath => { - Ok(self.device.borrow().get_devpath().unwrap_or_else(|_| { - log::debug!("formatter 'devpath' got empty value."); - "".to_string() - })) - } + FormatSubstitutionType::Devpath => Ok(self.device.get_devpath().unwrap_or_else(|_| { + log::debug!("formatter 'devpath' got empty value."); + "".to_string() + })), FormatSubstitutionType::Id => { if self.parent.is_none() { return Ok(String::default()); @@ -422,7 +410,6 @@ impl ExecuteUnitData { .parent .as_ref() .unwrap() - .borrow() .get_sysname() .unwrap_or_else(|_| { log::debug!("formatter 'id' got empty value."); @@ -431,7 +418,7 @@ impl ExecuteUnitData { } FormatSubstitutionType::Major | FormatSubstitutionType::Minor => { subst_format_map_err_ignore!( - self.device.borrow().get_devnum().map(|n| { + self.device.get_devnum().map(|n| { match subst_type { FormatSubstitutionType::Major => nix::sys::stat::major(n).to_string(), _ => nix::sys::stat::minor(n).to_string(), @@ -495,7 +482,7 @@ impl ExecuteUnitData { Ok(ret) } FormatSubstitutionType::Parent => { - let parent = match self.device.borrow().get_parent() { + let parent = match self.device.get_parent() { Ok(p) => p, Err(e) => { if e.get_errno() == Errno::ENOENT { @@ -508,17 +495,17 @@ impl ExecuteUnitData { }); } }; - let devname = parent.borrow().get_devname(); + let devname = parent.get_devname(); subst_format_map_err_ignore!(devname, "parent", Errno::ENOENT, String::default()) .map(|v| v.trim_start_matches("/dev/").to_string()) } FormatSubstitutionType::Name => { if !self.name.is_empty() { Ok(self.name.clone()) - } else if let Ok(devname) = self.device.borrow().get_devname() { + } else if let Ok(devname) = self.device.get_devname() { Ok(devname.trim_start_matches("/dev/").to_string()) } else { - Ok(self.device.borrow().get_sysname().unwrap_or_else(|_| { + Ok(self.device.get_sysname().unwrap_or_else(|_| { log::debug!("formatter 'name' got empty value."); "".to_string() })) @@ -526,7 +513,7 @@ impl ExecuteUnitData { } FormatSubstitutionType::Links => { let mut ret = String::new(); - for link in &self.device.borrow().devlink_iter() { + for link in &self.device.devlink_iter() { ret += link.trim_start_matches("/dev/"); ret += " "; } @@ -613,18 +600,18 @@ impl ExecuteUnitData { self.mode = mode; } - fn set_parent(&mut self, parent: Option>>) { + fn set_parent(&mut self, parent: Option>) { self.parent = parent; } - fn get_parent(&self) -> Option>> { + fn get_parent(&self) -> Option> { self.parent.clone() } } impl ExecuteUnit { /// create a execute unit based on device object - pub fn new(device: Rc>) -> Self { + pub fn new(device: Rc) -> Self { ExecuteUnit { seclabel_list: RefCell::new(HashMap::new()), builtin_run_list: RefCell::new(vec![]), @@ -653,11 +640,11 @@ impl ExecuteUnit { .update_devnode(&self.seclabel_list.borrow()) } - pub(crate) fn get_device(&self) -> Rc> { + pub(crate) fn get_device(&self) -> Rc { self.inner.borrow().get_device() } - pub(crate) fn get_device_db_clone(&self) -> Rc> { + pub(crate) fn get_device_db_clone(&self) -> Rc { self.inner.borrow().get_device_db_clone() } @@ -826,11 +813,11 @@ impl ExecuteUnit { self.seclabel_list.borrow_mut().clear() } - pub(crate) fn set_parent(&self, parent: Option>>) { + pub(crate) fn set_parent(&self, parent: Option>) { self.inner.borrow_mut().set_parent(parent) } - pub(crate) fn get_parent(&self) -> Option>> { + pub(crate) fn get_parent(&self) -> Option> { self.inner.borrow().get_parent() } } @@ -994,7 +981,6 @@ mod test { use crate::rules::rules_load::tests::create_tmp_file; use device::utils::*; use nix::sys::stat::{major, minor}; - use std::cell::RefCell; use std::fs::remove_dir_all; use std::path::Path; use std::rc::Rc; @@ -1005,26 +991,26 @@ mod test { "/tmp/test_update_devnode_tmpfile", 1024 * 1024 * 10, |dev| { - let dev = Rc::new(RefCell::new(dev.shallow_clone().unwrap())); - let id = dev.borrow().get_device_id().unwrap(); - let devnum = dev.borrow().get_devnum().unwrap(); + let dev = Rc::new(dev.shallow_clone().unwrap()); + let id = dev.get_device_id().unwrap(); + let devnum = dev.get_devnum().unwrap(); let major_minor = format!("{}:{}", major(devnum), minor(devnum)); create_tmp_file("/tmp/test_update_devnode/data", &id, "", true); - dev.borrow().sealed.replace(true); - dev.borrow().set_base_path("/tmp/test_update_devnode"); - dev.borrow().set_devgid("1").unwrap(); - dev.borrow().set_devuid("1").unwrap(); - dev.borrow().set_devmode("666").unwrap(); - dev.borrow().add_devlink("test_update_devnode/bbb").unwrap(); + dev.sealed.replace(true); + dev.set_base_path("/tmp/test_update_devnode"); + dev.set_devgid("1").unwrap(); + dev.set_devuid("1").unwrap(); + dev.set_devmode("666").unwrap(); + dev.add_devlink("test_update_devnode/bbb").unwrap(); let mut unit = ExecuteUnitData::new(dev.clone()); unit.clone_device_db().unwrap(); unit.update_devnode(&HashMap::new()).unwrap(); /* Record the devlink in db */ - dev.borrow().update_db().unwrap(); + dev.update_db().unwrap(); let p = Path::new("/dev/test_update_devnode/bbb"); let p_block_s = format!("/dev/block/{}", major_minor); @@ -1035,15 +1021,15 @@ mod test { assert!(p .canonicalize() .unwrap() - .ends_with(&dev.borrow().get_sysname().unwrap())); + .ends_with(&dev.get_sysname().unwrap())); let _ = prior_p.symlink_metadata().unwrap(); // Test symlink exists. - let new_dev = Rc::new(RefCell::new(Device::from_device_id(&id).unwrap())); - new_dev.borrow().sealed.replace(true); - new_dev.borrow().set_base_path("/tmp/test_update_devnode"); - new_dev.borrow().set_devgid("0").unwrap(); - new_dev.borrow().set_devuid("0").unwrap(); - new_dev.borrow().set_devmode("600").unwrap(); + let new_dev = Rc::new(Device::from_device_id(&id).unwrap()); + new_dev.sealed.replace(true); + new_dev.set_base_path("/tmp/test_update_devnode"); + new_dev.set_devgid("0").unwrap(); + new_dev.set_devuid("0").unwrap(); + new_dev.set_devmode("600").unwrap(); let mut unit = ExecuteUnitData::new(new_dev); /* See the devlink in db, but it is absent in the current device object. @@ -1060,17 +1046,15 @@ mod test { remove_dir_all("/tmp/test_update_devnode").unwrap(); /* Non-block devices do not have device nodes, thus update_devnode method will do nothing. */ - let lo = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); + let lo = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); let mut unit = ExecuteUnitData::new(lo); unit.update_devnode(&HashMap::new()).unwrap(); /* Cover error paths when uid, gid or mode is not set. */ - let dev = Rc::new(RefCell::new(Device::from_device_id(&id).unwrap())); - dev.borrow().sealed.replace(true); - dev.borrow().add_devlink("test_update_devnode/xxx").unwrap(); + let dev = Rc::new(Device::from_device_id(&id).unwrap()); + dev.sealed.replace(true); + dev.add_devlink("test_update_devnode/xxx").unwrap(); let mut unit = ExecuteUnitData::new(dev.clone()); unit.clone_device_db().unwrap(); @@ -1083,7 +1067,7 @@ mod test { assert!(p .canonicalize() .unwrap() - .ends_with(&dev.borrow().get_sysname().unwrap())); + .ends_with(&dev.get_sysname().unwrap())); let _ = Path::new(&prior_p_s).symlink_metadata().unwrap(); // Test symlink exists. cleanup_node(dev).unwrap(); @@ -1103,11 +1087,11 @@ mod test { fn test_subst_format() { if let Err(e) = LoopDev::inner_process("/tmp/test_subst_format_tmpfile", 1024 * 1024 * 10, |dev| { - let dev = Rc::new(RefCell::new(dev.shallow_clone().unwrap())); + let dev = Rc::new(dev.shallow_clone().unwrap()); let mut unit = ExecuteUnitData::new(dev.clone()); - let devnum = dev.borrow().get_devnum().unwrap(); + let devnum = dev.get_devnum().unwrap(); let major_minor = format!("{}:{}", major(devnum), minor(devnum)); - let sysname = dev.borrow().get_sysname().unwrap(); + let sysname = dev.get_sysname().unwrap(); assert_eq!( unit.subst_format(FormatSubstitutionType::Attr, Some("dev".to_string())) @@ -1124,9 +1108,9 @@ mod test { major_minor ); - unit.set_parent(Some(Rc::new(RefCell::new( + unit.set_parent(Some(Rc::new( Device::from_subsystem_sysname("net", "lo").unwrap(), - )))); + ))); /* Get the sysattr of parent device set in unit. */ assert_eq!( @@ -1144,7 +1128,7 @@ mod test { .unwrap() .is_empty()); - dev.borrow().add_property("hello", "world").unwrap(); + dev.add_property("hello", "world").unwrap(); assert_eq!( unit.subst_format(FormatSubstitutionType::Env, Some("hello".to_string())) @@ -1214,8 +1198,8 @@ mod test { "test".to_string(), ); - dev.borrow().add_devlink("test").unwrap(); - dev.borrow().sealed.replace(true); + dev.add_devlink("test").unwrap(); + dev.sealed.replace(true); assert_eq!( unit.subst_format(FormatSubstitutionType::Links, None) .unwrap(), @@ -1231,9 +1215,7 @@ mod test { assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY)); } - let dev = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); + let dev = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); let unit = ExecuteUnitData::new(dev); assert_eq!( unit.subst_format(FormatSubstitutionType::Name, None) diff --git a/exts/devmaster/src/lib/rules/node.rs b/exts/devmaster/src/lib/rules/node.rs index 50276787..830801ad 100644 --- a/exts/devmaster/src/lib/rules/node.rs +++ b/exts/devmaster/src/lib/rules/node.rs @@ -45,7 +45,6 @@ use nix::sys::stat::{self, fstat, lstat, major, minor, Mode}; use nix::unistd::unlink; use nix::unistd::{symlinkat, unlinkat, Gid, Uid, UnlinkatFlags}; use snafu::ResultExt; -use std::cell::RefCell; use std::collections::HashMap; use std::fs::{create_dir_all, read_dir, remove_dir, File}; use std::io::ErrorKind; @@ -54,7 +53,7 @@ use std::path::Path; use std::rc::Rc; pub(crate) fn node_apply_permissions( - dev: Rc>, + dev: Rc, apply_mac: bool, mode: Option, uid: Option, @@ -62,12 +61,11 @@ pub(crate) fn node_apply_permissions( seclabel_list: &HashMap, ) -> Result<()> { let devnode = dev - .borrow() .get_devname() .context(DeviceSnafu) .log_error("failed to apply node permissions")?; - let file = match dev.borrow().open(OFlag::O_PATH | OFlag::O_CLOEXEC) { + let file = match dev.open(OFlag::O_PATH | OFlag::O_CLOEXEC) { Ok(r) => r, Err(e) => { if e.is_absent() { @@ -136,7 +134,7 @@ pub(crate) fn static_node_apply_permissions( #[allow(clippy::too_many_arguments)] pub(crate) fn apply_permission_impl( - dev: Option>>, + dev: Option>, file: File, devnode: &str, apply_mac: bool, @@ -197,72 +195,69 @@ pub(crate) fn apply_permission_impl( Ok(()) } -pub(crate) fn update_node( - dev_new: Rc>, - dev_old: Rc>, -) -> Result<()> { - for devlink in &dev_old.borrow().devlink_iter() { - if dev_new.borrow().has_devlink(devlink) { +pub(crate) fn update_node(dev_new: Rc, dev_old: Rc) -> Result<()> { + for devlink in &dev_old.devlink_iter() { + if dev_new.has_devlink(devlink) { continue; } log_dev!( debug, - dev_new.borrow(), + dev_new, format!("removing old devlink '{}'", devlink) ); let _ = update_symlink(dev_new.clone(), devlink, false).log_dev_error( - &dev_new.borrow(), + &dev_new, &format!("failed to remove old symlink '{}'", devlink), ); } - for devlink in &dev_new.borrow().devlink_iter() { + for devlink in &dev_new.devlink_iter() { log_dev!( debug, - dev_new.borrow(), + dev_new, format!("updating new devlink '{}'", devlink) ); let _ = update_symlink(dev_new.clone(), devlink, true).log_dev_error( - &dev_new.borrow(), + &dev_new, &format!("failed to add new symlink '{}'", devlink), ); } /* create '/dev/{block, char}/$major:$minor' symlink */ let target = device_get_symlink_by_devnum(dev_new.clone()) - .log_dev_error(&dev_new.borrow(), "failed to get devnum symlink")?; + .log_dev_error(&dev_new, "failed to get devnum symlink")?; if let Err(e) = node_symlink(dev_new.clone(), "", &target) { - log_dev!(debug, dev_new.borrow(), e); + log_dev!(debug, dev_new, e); } Ok(()) } -pub(crate) fn cleanup_node(dev: Rc>) -> Result<()> { - for link in &dev.borrow().devlink_iter() { +pub(crate) fn cleanup_node(dev: Rc) -> Result<()> { + for link in &dev.devlink_iter() { if let Err(e) = update_symlink(dev.clone(), link.as_str(), false) { log_dev!( error, - dev.borrow(), + dev, format!("failed to remove symlink '{}': {}", link, e) ); } } let filename = device_get_symlink_by_devnum(dev.clone()) - .log_dev_error(&dev.borrow(), "failed to get devnum symlink")?; + .log_dev_error(&dev, "failed to get devnum symlink")?; match unlink(filename.as_str()) { - Ok(_) => log_dev!(debug, dev.borrow(), format!("unlinked '{}'", filename)), + Ok(_) => log_dev!(debug, dev, format!("unlinked '{}'", filename)), Err(e) => { if e != nix::Error::ENOENT { log_dev!( error, - dev.borrow(), + dev, format!("failed to unlink '{}' when cleanup node: {}", filename, e) ); } @@ -274,7 +269,7 @@ pub(crate) fn cleanup_node(dev: Rc>) -> Result<()> { /// if 'add' is true, add or update the target device symlink under '/run/devmaster/links/', /// otherwise delete the old symlink. -pub(crate) fn update_symlink(dev: Rc>, symlink: &str, add: bool) -> Result<()> { +pub(crate) fn update_symlink(dev: Rc, symlink: &str, add: bool) -> Result<()> { /* * Create link priority directory if it does not exist. * The directory is locked until finishing updating device symlink. @@ -284,7 +279,7 @@ pub(crate) fn update_symlink(dev: Rc>, symlink: &str, add: bool) if let Err(e) = ExclusiveFlock::wait_lock(&lock_file) { log_dev!( error, - dev.borrow(), + dev, format!("failed to lock priority directory for '{}': {}", symlink, e) ); } else { @@ -310,23 +305,15 @@ pub(crate) fn update_symlink(dev: Rc>, symlink: &str, add: bool) }; } - log_dev!( - debug, - dev.borrow(), - format!("removing symlink '{}'", symlink) - ); + log_dev!(debug, dev, format!("removing symlink '{}'", symlink)); match unlink(symlink).context(NixSnafu) { - Ok(_) => log_dev!( - debug, - dev.borrow(), - format!("unlinked symlink '{}'", symlink) - ), + Ok(_) => log_dev!(debug, dev, format!("unlinked symlink '{}'", symlink)), Err(e) => { if e.get_errno() != nix::Error::ENOENT { log_dev!( error, - dev.borrow(), + dev, format!( "failed to unlink '{}' when updating symlink: {}", symlink, e @@ -422,21 +409,18 @@ pub(crate) fn escape_prior_dir(symlink: &str) -> String { } /// return true if the link priority directory is updated -pub(crate) fn update_prior_dir(dev: Rc>, dirfd: RawFd, add: bool) -> Result { +pub(crate) fn update_prior_dir(dev: Rc, dirfd: RawFd, add: bool) -> Result { let id = dev - .borrow() .get_device_id() .context(DeviceSnafu) .log_error("failed to get device id")?; if add { let devname = dev - .borrow() .get_devname() .context(DeviceSnafu) .log_error("failed to get devname")?; let priority = dev - .borrow() .get_devlink_priority() .context(DeviceSnafu) .log_error("failed to get devlink priority")?; @@ -448,12 +432,12 @@ pub(crate) fn update_prior_dir(dev: Rc>, dirfd: RawFd, add: bool } } match unlinkat(Some(dirfd), id.as_str(), UnlinkatFlags::NoRemoveDir) { - Ok(_) => log_dev!(debug, dev.borrow(), format!("unlinked '{}'", id)), + Ok(_) => log_dev!(debug, dev, format!("unlinked '{}'", id)), Err(e) => { if e != nix::Error::ENOENT { log_dev!( error, - dev.borrow(), + dev, format!("failed to unlink '{}' when updating prior dir: {}", id, e) ); } @@ -464,7 +448,7 @@ pub(crate) fn update_prior_dir(dev: Rc>, dirfd: RawFd, add: bool .log_error("symlinkat failed")?; } else { match unlinkat(Some(dirfd), id.as_str(), UnlinkatFlags::NoRemoveDir).context(NixSnafu) { - Ok(_) => log_dev!(debug, dev.borrow(), format!("unlinked '{}'", id)), + Ok(_) => log_dev!(debug, dev, format!("unlinked '{}'", id)), Err(e) => { if e.get_errno() == nix::Error::ENOENT { /* unchange */ @@ -472,7 +456,7 @@ pub(crate) fn update_prior_dir(dev: Rc>, dirfd: RawFd, add: bool } log_dev!( error, - dev.borrow(), + dev, format!("failed to unlink '{}' when cleanup prior dir: {}", id, e) ); return Err(e); @@ -515,10 +499,10 @@ fn prior_dir_read_one(dirfd: RawFd, name: &str) -> Result<(i32, String)> { Ok((priority, tokens[1].to_string())) } -pub(crate) fn device_get_symlink_by_devnum(dev: Rc>) -> Result { - let subsystem = dev.borrow().get_subsystem().context(DeviceSnafu)?; +pub(crate) fn device_get_symlink_by_devnum(dev: Rc) -> Result { + let subsystem = dev.get_subsystem().context(DeviceSnafu)?; - let devnum = dev.borrow().get_devnum().context(DeviceSnafu)?; + let devnum = dev.get_devnum().context(DeviceSnafu)?; Ok(match subsystem.as_str() { "block" => { @@ -530,10 +514,9 @@ pub(crate) fn device_get_symlink_by_devnum(dev: Rc>) -> Result>, devnode: &str, target: &str) -> Result<()> { +pub(crate) fn node_symlink(dev: Rc, devnode: &str, target: &str) -> Result<()> { let devnode = if devnode.is_empty() { - dev.borrow() - .get_devname() + dev.get_devname() .context(DeviceSnafu) .log_error("failed to get devname")? } else { @@ -545,7 +528,7 @@ pub(crate) fn node_symlink(dev: Rc>, devnode: &str, target: &str if stat.st_mode & S_IFMT != S_IFLNK { log_dev!( error, - dev.borrow(), + dev, format!( "conflicting inode '{}' found, symlink to '{}' will not be created", target, devnode @@ -559,7 +542,7 @@ pub(crate) fn node_symlink(dev: Rc>, devnode: &str, target: &str } Err(e) => { if e != nix::Error::ENOENT { - log_dev!(error, dev.borrow(), format!("failed to lstat '{}'", target)); + log_dev!(error, dev, format!("failed to lstat '{}'", target)); return Err(Error::Nix { source: e }); } } @@ -570,28 +553,25 @@ pub(crate) fn node_symlink(dev: Rc>, devnode: &str, target: &str .context(IoSnafu { filename: target.to_string(), }) - .log_dev_error(&dev.borrow(), "failed to create directory all")?; + .log_dev_error(&dev, "failed to create directory all")?; } symlink(&devnode, target, true) .context(BasicSnafu) .log_dev_error( - &dev.borrow(), + &dev, &format!("failed to create symlink '{}'->'{}'", devnode, target), )?; log_dev!( debug, - dev.borrow(), + dev, format!("successfully created symlink '{}' to '{}'", target, devnode) ); Ok(()) } -pub(crate) fn find_prioritized_devnode( - dev: Rc>, - dirfd: i32, -) -> Result> { +pub(crate) fn find_prioritized_devnode(dev: Rc, dirfd: i32) -> Result> { let mut dir = xopendirat(dirfd, ".", OFlag::O_NOFOLLOW) .context(BasicSnafu) .log_error(&format!("failed to opendirat '{}'", dirfd))?; @@ -615,11 +595,7 @@ pub(crate) fn find_prioritized_devnode( } Err(e) => { if e.get_errno() != nix::Error::ENODEV { - log_dev!( - error, - dev.borrow(), - format!("prior_dir_read_one failed: {}", e) - ); + log_dev!(error, dev, format!("prior_dir_read_one failed: {}", e)); } } } @@ -734,8 +710,8 @@ mod test { unlink(link_path).unwrap(); } - let dev_new_arc = Rc::new(RefCell::new(dev_new)); - let dev_old_arc = Rc::new(RefCell::new(dev_old)); + let dev_new_arc = Rc::new(dev_new); + let dev_old_arc = Rc::new(dev_old); update_node(dev_new_arc.clone(), dev_old_arc.clone()).unwrap(); @@ -788,7 +764,7 @@ mod test { Device::from_path(lodev.get_device_path().unwrap().to_str().unwrap()).unwrap(); dev.add_devlink("test/update_prior_dir").unwrap(); - let dev_rc = Rc::new(RefCell::new(dev)); + let dev_rc = Rc::new(dev); { match open_prior_dir("/dev/test/update_prior_dir") { @@ -885,7 +861,7 @@ mod test { #[test] fn test_node_symlink() { if let Err(e) = LoopDev::inner_process("/tmp/test_node_symlink", 1024 * 1024 * 10, |dev| { - let dev = Rc::new(RefCell::new(dev.shallow_clone().unwrap())); + let dev = Rc::new(dev.shallow_clone().unwrap()); touch_file( "/tmp/test_node_symlink_link", diff --git a/exts/devmaster/src/lib/utils/commons.rs b/exts/devmaster/src/lib/utils/commons.rs index 1162a9ef..700caf2d 100644 --- a/exts/devmaster/src/lib/utils/commons.rs +++ b/exts/devmaster/src/lib/utils/commons.rs @@ -13,7 +13,6 @@ //! common utilities use std::{ - cell::RefCell, rc::Rc, sync::{Arc, RwLock}, }; @@ -531,44 +530,39 @@ pub(crate) fn get_property_from_string(s: &str) -> Result<(String, String)> { } /// inherit initial timestamp from old device object -pub(crate) fn initialize_device_usec( - dev_new: Rc>, - dev_old: Rc>, -) -> Result<()> { - let timestamp = dev_old.borrow().get_usec_initialized().unwrap_or_else(|_| { +pub(crate) fn initialize_device_usec(dev_new: Rc, dev_old: Rc) -> Result<()> { + let timestamp = dev_old.get_usec_initialized().unwrap_or_else(|_| { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map_or(0, |v| v.as_secs()) }); - dev_new.borrow().set_usec_initialized(timestamp); + dev_new.set_usec_initialized(timestamp); Ok(()) } /// add new tags and remove deleted tags pub(crate) fn device_update_tag( - dev_new: Rc>, - dev_old: Option>>, + dev_new: Rc, + dev_old: Option>, add: bool, ) -> Result<()> { if let Some(dev_old) = dev_old { - for tag in &dev_old.borrow().tag_iter() { - if let Ok(true) = dev_new.borrow().has_tag(tag) { + for tag in &dev_old.tag_iter() { + if let Ok(true) = dev_new.has_tag(tag) { continue; } let _ = dev_new - .borrow() .update_tag(tag, false) .context(DeviceSnafu) .log_error(&format!("failed to remove old tag '{}'", tag)); } } - for tag in &dev_new.borrow().tag_iter() { + for tag in &dev_new.tag_iter() { let _ = dev_new - .borrow() .update_tag(tag, add) .context(DeviceSnafu) .log_error(&format!("failed to add new tag '{}'", tag)); @@ -578,18 +572,18 @@ pub(crate) fn device_update_tag( } /// cleanup device database -pub(crate) fn cleanup_db(dev: Rc>) -> Result<()> { - let id = dev.borrow().get_device_id().context(DeviceSnafu)?; +pub(crate) fn cleanup_db(dev: Rc) -> Result<()> { + let id = dev.get_device_id().context(DeviceSnafu)?; let db_path = format!("{}{}", DB_BASE_DIR, id); match unlink(db_path.as_str()) { - Ok(_) => log_dev!(debug, dev.borrow(), format!("unlinked '{}'", db_path)), + Ok(_) => log_dev!(debug, dev, format!("unlinked '{}'", db_path)), Err(e) => { if e != nix::Error::ENOENT { log_dev!( error, - dev.borrow(), + dev, format!("failed to unlink '{}' when cleanup db: {}", db_path, e) ); return Err(Error::Nix { source: e }); diff --git a/exts/devmaster/src/lib/utils/macros.rs b/exts/devmaster/src/lib/utils/macros.rs index e1d31cc7..d03538df 100644 --- a/exts/devmaster/src/lib/utils/macros.rs +++ b/exts/devmaster/src/lib/utils/macros.rs @@ -144,7 +144,7 @@ macro_rules! log_dev_option { ($level:ident, $dev:expr, $msg:expr) => { match $dev { Some(d) => { - $crate::log_dev!($level, d.borrow(), $msg); + $crate::log_dev!($level, d, $msg); } None => { log::$level!("{}", $msg); diff --git a/exts/devmaster/src/lib/utils/spawn.rs b/exts/devmaster/src/lib/utils/spawn.rs index b6f65040..6f47d878 100644 --- a/exts/devmaster/src/lib/utils/spawn.rs +++ b/exts/devmaster/src/lib/utils/spawn.rs @@ -57,7 +57,7 @@ pub(crate) fn spawn(cmd_str: &str, timeout: Duration, unit: &ExecuteUnit) -> Res Command::new(&cmd_tokens[0]) }; - for (key, val) in &dev.borrow().property_iter() { + for (key, val) in &dev.property_iter() { cmd.env(key, val); } @@ -137,7 +137,6 @@ mod tests { use device::Device; use log::init_log; use log::Level; - use std::cell::RefCell; use std::rc::Rc; #[test] @@ -145,7 +144,7 @@ mod tests { init_log("test_spawn", Level::Debug, vec!["console"], "", 0, 0, false); let dev = Device::from_subsystem_sysname("net", "lo").unwrap(); - let unit = ExecuteUnit::new(Rc::new(RefCell::new(dev))); + let unit = ExecuteUnit::new(Rc::new(dev)); println!( "{}", diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 9a17e90f..dca76c7d 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -478,18 +478,18 @@ pub extern "C" fn udev_device_get_property_value( #[cfg(test)] mod test { - use std::{cell::RefCell, intrinsics::transmute}; + use std::intrinsics::transmute; use super::*; use device::device_enumerator::*; - type RD = Rc>; + type RD = Rc; pub type Result = std::result::Result<(), device::error::Error>; fn test_udev_device_new_from_devnum(device: RD) -> Result { - let devnum = device.borrow().get_devnum()?; + let devnum = device.get_devnum()?; - let t = if &device.borrow().get_subsystem().unwrap() == "block" { + let t = if &device.get_subsystem().unwrap() == "block" { 'b' } else { 'c' @@ -500,10 +500,7 @@ mod test { let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(raw_udev_device)) }; - assert_eq!( - syspath.to_str().unwrap(), - &device.borrow().get_syspath().unwrap() - ); + assert_eq!(syspath.to_str().unwrap(), &device.get_syspath().unwrap()); udev_device_unref(raw_udev_device); @@ -511,12 +508,12 @@ mod test { } fn test_udev_device_new_from_subsystem_sysname(device: RD) -> Result { - let subsystem = device.borrow().get_subsystem().unwrap(); - let sysname = device.borrow().get_sysname().unwrap(); + let subsystem = device.get_subsystem().unwrap(); + let sysname = device.get_sysname().unwrap(); /* If subsystem is 'drivers', sysname should use ':'. */ let name = if subsystem == "drivers" { - format!("{}:{}", device.borrow().driver_subsystem.borrow(), sysname) + format!("{}:{}", device.driver_subsystem.borrow(), sysname) } else { sysname }; @@ -531,10 +528,7 @@ mod test { let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(raw_udev_device)) }; - assert_eq!( - syspath.to_str().unwrap(), - &device.borrow().get_syspath().unwrap() - ); + assert_eq!(syspath.to_str().unwrap(), &device.get_syspath().unwrap()); udev_device_unref(raw_udev_device); @@ -542,13 +536,13 @@ mod test { } fn test_udev_device_new_from_device_id(device: RD) -> Result { - let id = device.borrow().get_device_id().unwrap(); + let id = device.get_device_id().unwrap(); let c_id = CString::new(id).unwrap(); let udev_device = udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()); let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(udev_device)) }; assert_eq!( - device.borrow().get_syspath().unwrap(), + device.get_syspath().unwrap(), syspath.to_str().unwrap().to_string() ); @@ -558,7 +552,7 @@ mod test { } fn test_udev_device_new_from_syspath(device: RD) -> Result { - let syspath = device.borrow().get_syspath().unwrap(); + let syspath = device.get_syspath().unwrap(); let c_syspath = CString::new(syspath).unwrap(); let udev_device = udev_device_new_from_syspath(std::ptr::null_mut(), c_syspath.as_ptr()); let ret_syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(udev_device)) }; @@ -571,17 +565,15 @@ mod test { } fn from_rd(device: RD) -> *mut udev_device { - let id = device.borrow().get_device_id().unwrap(); + let id = device.get_device_id().unwrap(); let c_id = CString::new(id).unwrap(); udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()) } fn test_udev_device_has_tag(device: RD) -> Result { - let _ = device.borrow_mut().read_db_internal(true); - device - .borrow_mut() - .add_tag("test_udev_device_has_tag", true); - device.borrow_mut().update_db()?; + let _ = device.read_db_internal(true); + device.add_tag("test_udev_device_has_tag", true); + device.update_db()?; let udev_device = from_rd(device.clone()); @@ -602,12 +594,11 @@ mod test { udev_device_unref(udev_device); device - .borrow_mut() .all_tags .borrow_mut() .remove("test_udev_device_has_tag"); - device.borrow_mut().remove_tag("test_udev_device_has_tag"); - device.borrow_mut().update_db()?; + device.remove_tag("test_udev_device_has_tag"); + device.update_db()?; Ok(()) } @@ -636,7 +627,7 @@ mod test { fn test_udev_device_get_devnode(dev: RD) -> Result { let udev_device = from_rd(dev.clone()); - let devnode = dev.borrow().get_devname()?; + let devnode = dev.get_devname()?; let ptr = udev_device_get_devnode(udev_device); @@ -650,7 +641,7 @@ mod test { fn test_udev_device_get_devnum(dev: RD) -> Result { let udev_device = from_rd(dev.clone()); - let devnum = dev.borrow().get_devnum()?; + let devnum = dev.get_devnum()?; assert_eq!(udev_device_get_devnum(udev_device), devnum); @@ -660,7 +651,7 @@ mod test { fn test_udev_device_get_devpath(dev: RD) -> Result { let udev_device = from_rd(dev.clone()); - let devpath = dev.borrow().get_devpath()?; + let devpath = dev.get_devpath()?; assert_eq!( unsafe { CStr::from_ptr(udev_device_get_devpath(udev_device)) } @@ -675,7 +666,7 @@ mod test { fn test_udev_device_get_devtype(dev: RD) -> Result { let ud = from_rd(dev.clone()); - let devtype = dev.borrow().get_devtype()?; + let devtype = dev.get_devtype()?; assert_eq!( unsafe { CStr::from_ptr(udev_device_get_devtype(ud)) } @@ -690,7 +681,7 @@ mod test { fn test_udev_device_get_driver(dev: RD) -> Result { let ud = from_rd(dev.clone()); - let driver = dev.borrow().get_driver()?; + let driver = dev.get_driver()?; assert_eq!( unsafe { CStr::from_ptr(udev_device_get_driver(ud)) } @@ -705,7 +696,7 @@ mod test { fn test_udev_device_get_sysname(dev: RD) -> Result { let ud = from_rd(dev.clone()); - let sysname = dev.borrow().get_sysname()?; + let sysname = dev.get_sysname()?; assert_eq!( unsafe { CStr::from_ptr(udev_device_get_sysname(ud)) } @@ -720,7 +711,7 @@ mod test { fn test_udev_device_get_subsystem(dev: RD) -> Result { let ud = from_rd(dev.clone()); - let subsystem = dev.borrow().get_subsystem()?; + let subsystem = dev.get_subsystem()?; assert_eq!( unsafe { CStr::from_ptr(udev_device_get_subsystem(ud)) } @@ -787,17 +778,13 @@ mod test { #[test] fn test_udev_device_has_tag_ut() { - let dev = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); + let dev = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); let _ = test_udev_device_has_tag(dev); } #[test] fn test_udev_device_fake_from_monitor_ut() { - let dev = Rc::new(RefCell::new( - Device::from_subsystem_sysname("net", "lo").unwrap(), - )); + let dev = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); let _ = test_udev_device_get_action(dev.clone()); let _ = test_udev_device_get_seqnum(dev.clone()); let _ = test_udev_device_get_property_value(dev); diff --git a/libs/device/examples/enumerator.rs b/libs/device/examples/enumerator.rs index c61eb68f..a92e2a3b 100644 --- a/libs/device/examples/enumerator.rs +++ b/libs/device/examples/enumerator.rs @@ -17,7 +17,7 @@ fn main() { let mut enumerator = DeviceEnumerator::new(); for device in enumerator.iter() { - println!("{}", device.borrow_mut().get_devpath().unwrap()); - device.borrow_mut().trigger(DeviceAction::Change).unwrap(); + println!("{}", device.get_devpath().unwrap()); + device.trigger(DeviceAction::Change).unwrap(); } } diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs index 0104307c..a5f55ae0 100644 --- a/libs/device/src/device.rs +++ b/libs/device/src/device.rs @@ -54,7 +54,7 @@ pub struct Device { /// inotify handler pub watch_handle: RefCell, /// the parent device - pub parent: RefCell>>>, + pub parent: RefCell>>, /// ifindex pub ifindex: RefCell, /// device type @@ -120,7 +120,7 @@ pub struct Device { pub database_version: RefCell, /// children - pub children: RefCell>>>, + pub children: RefCell>>, /// children enumerated pub children_enumerated: RefCell, @@ -650,11 +650,11 @@ impl Device { } /// get the parent of the device - pub fn get_parent(&self) -> Result>, Error> { + pub fn get_parent(&self) -> Result, Error> { if !*self.parent_set.borrow() { match Device::new_from_child(self) { Ok(parent) => { - let _ = self.parent.replace(Some(Rc::new(RefCell::new(parent)))); + let _ = self.parent.replace(Some(Rc::new(parent))); } Err(e) => { // it is okay if no parent device is found, @@ -687,27 +687,27 @@ impl Device { &self, subsystem: &str, devtype: Option<&str>, - ) -> Result>, Error> { + ) -> Result, Error> { let mut parent = match self.get_parent() { Ok(parent) => parent, Err(e) => return Err(e), }; loop { - let parent_subsystem = parent.borrow_mut().get_subsystem(); + let parent_subsystem = parent.get_subsystem(); if parent_subsystem.is_ok() && parent_subsystem.unwrap() == subsystem { if devtype.is_none() { break; } - let parent_devtype = parent.borrow_mut().get_devtype(); + let parent_devtype = parent.get_devtype(); if parent_devtype.is_ok() && parent_devtype.unwrap() == devtype.unwrap() { break; } } - let tmp = parent.borrow_mut().get_parent()?; + let tmp = parent.get_parent()?; parent = tmp; } @@ -2218,15 +2218,15 @@ impl Device { /// The parent will try to find the child in its cache firstly. If /// it already exists in the cache, directly return it. Otherwise /// the child device will be created and be cached. - pub fn get_child(&self, child: &str) -> Result>, Error> { + pub fn get_child(&self, child: &str) -> Result, Error> { if let Some(d) = self.children.borrow().get(child) { return Ok(d.clone()); } - let dev = Rc::new(RefCell::new(Self::from_syspath( + let dev = Rc::new(Self::from_syspath( &format!("{}/{}", self.get_syspath()?, child), true, - )?)); + )?); self.children .borrow_mut() @@ -2870,7 +2870,7 @@ impl Device { } /// return the child iterator - pub fn child_iter(&self) -> HashMapRefWrapper>> { + pub fn child_iter(&self) -> HashMapRefWrapper> { if let Err(e) = self.enumerate_children() { log::debug!( "failed to enumerate children of '{}': {}", @@ -2931,7 +2931,7 @@ mod tests { } /// test a single device - fn test_device_one(device: &mut Device) { + fn test_device_one(device: Rc) { let syspath = device.get_syspath().unwrap(); assert!(syspath.starts_with("/sys")); let sysname = device.get_sysname().unwrap(); @@ -3236,7 +3236,7 @@ mod tests { std::fs::canonicalize(&format!("{}/{}", &syspath, subdir)).unwrap(); assert_eq!( canoicalized_path.to_str().unwrap(), - &child.borrow().get_syspath().unwrap() + &child.get_syspath().unwrap() ); } @@ -3297,8 +3297,8 @@ mod tests { let mut enumerator = DeviceEnumerator::new(); enumerator.set_enumerator_type(DeviceEnumerationType::All); for device in enumerator.iter() { - device.borrow().set_base_path("/tmp/devmaster"); - test_device_one(&mut device.as_ref().borrow_mut()); + device.set_base_path("/tmp/devmaster"); + test_device_one(device); } } @@ -3584,16 +3584,16 @@ mod tests { e.set_enumerator_type(DeviceEnumerationType::All); for mut dev in e.iter() { - let dev_clone = dev.borrow().shallow_clone().unwrap(); + let dev_clone = dev.shallow_clone().unwrap(); dev_clone.get_syspath().unwrap(); dev_clone.get_subsystem().unwrap(); loop { - let ret = dev.borrow().get_parent(); + let ret = dev.get_parent(); if let Ok(parent) = ret { - parent.borrow().get_syspath().unwrap(); - if let Err(e) = parent.borrow().get_subsystem() { + parent.get_syspath().unwrap(); + if let Err(e) = parent.get_subsystem() { assert_eq!(e.get_errno(), Errno::ENOENT); } dev = parent; diff --git a/libs/device/src/device_enumerator.rs b/libs/device/src/device_enumerator.rs index 78750156..6a5356aa 100644 --- a/libs/device/src/device_enumerator.rs +++ b/libs/device/src/device_enumerator.rs @@ -50,9 +50,9 @@ pub struct DeviceEnumerator { /// enumerator type pub(crate) etype: RefCell, /// key: syspath, value: device - pub(crate) devices_by_syspath: RefCell>>>, + pub(crate) devices_by_syspath: RefCell>>, /// sorted device vector - pub(crate) devices: RefCell>>>, + pub(crate) devices: RefCell>>, /// whether enumerator is up to date pub(crate) scan_up_to_date: RefCell, @@ -161,7 +161,7 @@ impl DeviceEnumerator { } impl Iterator for DeviceEnumeratorIter<'_> { - type Item = Rc>; + type Item = Rc; /// iterate over the devices or subsystems according to the enumerator type fn next(&mut self) -> Option { @@ -354,7 +354,7 @@ impl DeviceEnumerator { return Ok(()); } - let mut devices = Vec::>>::new(); + let mut devices = Vec::>::new(); let mut n_sorted = 0; for prioritized_subsystem in self.prioritized_subsystems.borrow().iter() { @@ -363,7 +363,7 @@ impl DeviceEnumerator { let m = devices.len(); // find a device with the prioritized subsystem for (syspath, device) in self.devices_by_syspath.borrow().iter() { - let subsys = match device.borrow_mut().get_subsystem() { + let subsys = match device.get_subsystem() { Ok(ret) => ret, Err(_) => { continue; @@ -393,7 +393,7 @@ impl DeviceEnumerator { // remove already sorted devices from the hashmap (self.devices_by_syspath) // avoid get repeated devices from the hashmap later for device in devices.iter().skip(m) { - let syspath = device.borrow().get_syspath()?; + let syspath = device.get_syspath()?; self.devices_by_syspath.borrow_mut().remove(&syspath); } @@ -402,7 +402,7 @@ impl DeviceEnumerator { break; } } - devices[n_sorted..].sort_by(|a, b| device_compare(&a.borrow(), &b.borrow())); + devices[n_sorted..].sort_by(|a, b| device_compare(a, b)); n_sorted = devices.len(); } @@ -414,13 +414,12 @@ impl DeviceEnumerator { // the sorted devices are removed from the hashmap previously // insert them back for device in devices[..n_sorted].iter() { - self.devices_by_syspath.borrow_mut().insert( - device.borrow().get_syspath().unwrap().to_string(), - device.clone(), - ); + self.devices_by_syspath + .borrow_mut() + .insert(device.get_syspath().unwrap().to_string(), device.clone()); } - devices[n_sorted..].sort_by(|a, b| device_compare(&a.borrow(), &b.borrow())); + devices[n_sorted..].sort_by(|a, b| device_compare(a, b)); self.devices.replace(devices); self.sorted.replace(true); @@ -428,8 +427,8 @@ impl DeviceEnumerator { } /// add device - pub(crate) fn add_device(&self, device: Rc>) -> Result { - let syspath = device.borrow().get_syspath()?; + pub(crate) fn add_device(&self, device: Rc) -> Result { + let syspath = device.get_syspath()?; match self.devices_by_syspath.borrow_mut().insert(syspath, device) { Some(_) => { @@ -448,7 +447,7 @@ impl DeviceEnumerator { } /// check whether a device matches at least one property - pub(crate) fn match_property(&self, device: &mut Device) -> Result { + pub(crate) fn match_property(&self, device: Rc) -> Result { if self.match_property.borrow().is_empty() { return Ok(true); } @@ -469,7 +468,7 @@ impl DeviceEnumerator { } /// check whether the tag of a device matches - pub(crate) fn match_tag(&self, _device: &Device) -> Result { + pub(crate) fn match_tag(&self, _device: Rc) -> Result { // todo!("device database is not available for tag"); Ok(true) } @@ -484,7 +483,7 @@ impl DeviceEnumerator { } /// check whether the initialized state of a device matches - pub(crate) fn match_initialized(&self, _device: &Device) -> Result { + pub(crate) fn match_initialized(&self, _device: Rc) -> Result { // todo!("device database is not available for initialized"); Ok(true) } @@ -499,11 +498,7 @@ impl DeviceEnumerator { } /// check whether a device matches conditions according to flags - pub(crate) fn test_matches( - &self, - device: &mut Device, - flags: MatchFlag, - ) -> Result { + pub(crate) fn test_matches(&self, device: Rc, flags: MatchFlag) -> Result { if (flags & MatchFlag::SYSNAME).bits() != 0 && !self.match_sysname(&device.get_sysname()?) { return Ok(false); } @@ -534,15 +529,15 @@ impl DeviceEnumerator { return Ok(false); } - if (flags & MatchFlag::TAG).bits() != 0 && !self.match_tag(device)? { + if (flags & MatchFlag::TAG).bits() != 0 && !self.match_tag(device.clone())? { return Ok(false); } - if !self.match_initialized(device)? { + if !self.match_initialized(device.clone())? { return Ok(false); } - if !self.match_property(device)? { + if !self.match_property(device.clone())? { return Ok(false); } @@ -559,12 +554,12 @@ impl DeviceEnumerator { /// add parent device pub(crate) fn add_parent_devices( &self, - device: Rc>, + device: Rc, flags: MatchFlag, ) -> Result<(), Error> { let mut d = device; loop { - let parent = match d.borrow_mut().get_parent() { + let parent = match d.get_parent() { Ok(ret) => ret.clone(), Err(e) => { // reach the top @@ -581,11 +576,11 @@ impl DeviceEnumerator { d = parent.clone(); - if !self.test_matches(&mut parent.borrow_mut(), flags)? { + if !self.test_matches(parent.clone(), flags)? { continue; } - if !self.add_device(parent.clone())? { + if !self.add_device(parent)? { break; } } @@ -649,7 +644,7 @@ impl DeviceEnumerator { }; let device = match Device::from_syspath(syspath.to_str().unwrap_or_default(), true) { - Ok(ret) => Rc::new(RefCell::new(ret)), + Ok(ret) => Rc::new(ret), Err(e) => { if e.get_errno() != nix::errno::Errno::ENODEV { ret = Err(Error::Nix { @@ -661,10 +656,7 @@ impl DeviceEnumerator { } }; - match self.test_matches( - &mut device.borrow_mut(), - MatchFlag::ALL & !MatchFlag::SYSNAME, - ) { + match self.test_matches(device.clone(), MatchFlag::ALL & !MatchFlag::SYSNAME) { Ok(true) => {} Ok(false) => { continue; @@ -799,8 +791,8 @@ impl DeviceEnumerator { continue; } - let mut device = match Device::from_device_id(&file_name) { - Ok(device) => device, + let device = match Device::from_device_id(&file_name) { + Ok(device) => Rc::new(device), Err(e) => { if e.get_errno() != nix::errno::Errno::ENODEV { /* this is necessarily racy, so ignore missing devices */ @@ -811,7 +803,7 @@ impl DeviceEnumerator { }; /* Generated from tag, hence not necessary to check tag again. */ - match self.test_matches(&mut device, MatchFlag::ALL & (!MatchFlag::TAG)) { + match self.test_matches(device.clone(), MatchFlag::ALL & (!MatchFlag::TAG)) { Ok(flag) => { if !flag { continue; @@ -823,7 +815,7 @@ impl DeviceEnumerator { } } - if let Err(e) = self.add_device(Rc::new(RefCell::new(device))) { + if let Err(e) = self.add_device(device) { ret = Err(e); continue; } @@ -847,7 +839,7 @@ impl DeviceEnumerator { /// parent add child pub(crate) fn parent_add_child(&mut self, path: &str, flags: MatchFlag) -> Result { let device = match Device::from_syspath(path, true) { - Ok(dev) => Rc::new(RefCell::new(dev)), + Ok(dev) => Rc::new(dev), Err(err) => { if err.get_errno() == nix::errno::Errno::ENODEV { /* this is necessarily racy, so ignore missing devices */ @@ -857,7 +849,7 @@ impl DeviceEnumerator { } }; - if !self.test_matches(&mut device.borrow_mut(), flags)? { + if !self.test_matches(device.clone(), flags)? { return Ok(false); } @@ -1126,7 +1118,7 @@ impl DeviceEnumerator { mod tests { use super::{DeviceEnumerator, MatchInitializedType}; use crate::{device_enumerator::DeviceEnumerationType, Device}; - use std::collections::HashSet; + use std::{collections::HashSet, rc::Rc}; #[test] fn test_enumerator_inialize() { @@ -1158,7 +1150,7 @@ mod tests { enumerator.set_enumerator_type(DeviceEnumerationType::Devices); for i in enumerator.iter() { - i.borrow().get_devpath().unwrap(); + i.get_devpath().unwrap(); } } @@ -1168,7 +1160,7 @@ mod tests { enumerator.set_enumerator_type(DeviceEnumerationType::Subsystems); for i in enumerator.iter() { - i.borrow().get_devpath().expect("can not get the devpath"); + i.get_devpath().expect("can not get the devpath"); } } @@ -1178,7 +1170,7 @@ mod tests { enumerator.set_enumerator_type(DeviceEnumerationType::All); for i in enumerator.iter() { - i.borrow().get_devpath().expect("can not get the devpath"); + i.get_devpath().expect("can not get the devpath"); } } @@ -1246,7 +1238,7 @@ mod tests { }; for dev in ert.iter() { - sm.trans(&dev.borrow().get_subsystem().unwrap()); + sm.trans(&dev.get_subsystem().unwrap()); } ert.sort_devices().unwrap(); @@ -1256,12 +1248,12 @@ mod tests { fn test_match_property() { let mut ert = DeviceEnumerator::new(); - let mut dev = Device::from_subsystem_sysname("net", "lo").unwrap(); + let dev = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); dev.add_property("helloxxx", "worldxxx").unwrap(); ert.add_match_property("hello*", "world*").unwrap(); - assert!(ert.match_property(&mut dev).unwrap()); + assert!(ert.match_property(dev).unwrap()); } #[test] @@ -1287,12 +1279,12 @@ mod tests { #[test] fn test_match_tag() { let mut ert = DeviceEnumerator::new(); - let dev = Device::from_subsystem_sysname("net", "lo").unwrap(); + let dev = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); dev.set_base_path("/tmp/devmaster"); dev.add_tag("devmaster", true); dev.update_tag("devmaster", true).unwrap(); ert.add_match_tag("devmaster").unwrap(); - assert!(ert.match_tag(&dev).unwrap()); + assert!(ert.match_tag(dev.clone()).unwrap()); ert.set_enumerator_type(DeviceEnumerationType::Devices); ert.scan_devices().unwrap(); @@ -1317,10 +1309,10 @@ mod tests { #[test] fn test_match_is_initialized() { let mut ert = DeviceEnumerator::new(); - let dev = Device::from_subsystem_sysname("net", "lo").unwrap(); + let dev = Rc::new(Device::from_subsystem_sysname("net", "lo").unwrap()); ert.add_match_is_initialized(MatchInitializedType::ALL) .unwrap(); - assert!(ert.match_initialized(&dev).unwrap()); + assert!(ert.match_initialized(dev).unwrap()); } #[test] -- Gitee From 4893db7a768d1df46eb527ba286f8845dc100071 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 8 Dec 2023 19:45:13 +0800 Subject: [PATCH 06/48] feature(libudev): support several ABIs Include: udev_device_get_parent udev_device_get_parent_with_subsystem_devtype --- exts/libudev/src/libudev_device.rs | 155 +++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 6 deletions(-) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index dca76c7d..18dded99 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -56,21 +56,24 @@ pub struct udev_device { pub(crate) subsystem: CString, pub(crate) properties: HashMap, + + pub(crate) parent: *mut udev_device, } impl Drop for udev_device { fn drop(&mut self) { if !self.udev.is_null() { let _ = unsafe { Rc::from_raw(self.udev) }; + let _ = unsafe { Rc::from_raw(self.parent) }; } } } impl udev_device { - fn new(udev: *mut udev, device: Device) -> Self { + fn new(udev: *mut udev, device: Rc) -> Self { Self { udev, - device: Rc::new(device), + device, syspath: CString::default(), devnode: CString::default(), devpath: CString::default(), @@ -79,6 +82,7 @@ impl udev_device { sysname: CString::default(), subsystem: CString::default(), properties: HashMap::default(), + parent: std::ptr::null_mut(), } } } @@ -97,7 +101,7 @@ pub extern "C" fn udev_device_new_from_device_id( }; let device = match Device::from_device_id(s) { - Ok(d) => d, + Ok(d) => Rc::new(d), Err(_) => return std::ptr::null_mut(), }; @@ -112,7 +116,7 @@ pub extern "C" fn udev_device_new_from_devnum( devnum: dev_t, ) -> *mut udev_device { let device = match Device::from_devnum(type_ as u8 as char, devnum) { - Ok(d) => d, + Ok(d) => Rc::new(d), Err(_) => return std::ptr::null_mut(), }; @@ -133,7 +137,7 @@ pub extern "C" fn udev_device_new_from_subsystem_sysname( .to_str() .unwrap(); let device = match Device::from_subsystem_sysname(subsystem, sysname) { - Ok(d) => d, + Ok(d) => Rc::new(d), Err(_) => { return std::ptr::null_mut(); } @@ -152,7 +156,7 @@ pub extern "C" fn udev_device_new_from_syspath( .to_str() .unwrap(); let device = match Device::from_syspath(syspath, true) { - Ok(d) => d, + Ok(d) => Rc::new(d), Err(_) => { return std::ptr::null_mut(); } @@ -476,6 +480,74 @@ pub extern "C" fn udev_device_get_property_value( } } +fn device_new_from_parent(child: *mut udev_device) -> *mut udev_device { + let ud: &mut udev_device = unsafe { mem::transmute(&mut *child) }; + + match ud.device.get_parent() { + Ok(p) => Rc::into_raw(Rc::new(udev_device::new(ud.udev, p))) as *mut udev_device, + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null_mut() + } + } +} + +#[no_mangle] +/// udev_device_get_parent +/// +/// return the reference of the innter parent field, thus don't drop it +pub extern "C" fn udev_device_get_parent(udev_device: *mut udev_device) -> *mut udev_device { + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if ud.parent.is_null() { + ud.parent = device_new_from_parent(udev_device); + } + + ud.parent +} + +#[no_mangle] +/// udev_device_get_parent_with_subsystem_devtype +pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( + udev_device: *mut udev_device, + subsystem: *const ::std::os::raw::c_char, + devtype: *const ::std::os::raw::c_char, +) -> *mut udev_device { + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + let subsystem = unsafe { CStr::from_ptr(subsystem).to_str().unwrap_or_default() }; + let devtype = unsafe { CStr::from_ptr(devtype).to_str().ok() }; + + let p = match ud + .device + .get_parent_with_subsystem_devtype(subsystem, devtype) + { + Ok(p) => p, + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + return std::ptr::null_mut(); + } + }; + + #[allow(clippy::never_loop)] + loop { + let udev_device = udev_device_get_parent(udev_device); + + if udev_device.is_null() { + break; + } + + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if ud.device == p { + return udev_device; + } + } + + errno::set_errno(errno::Errno(libc::ENOENT as i32)); + std::ptr::null_mut() +} + #[cfg(test)] mod test { use std::intrinsics::transmute; @@ -756,6 +828,65 @@ mod test { Ok(()) } + fn test_udev_device_get_parent(dev: RD) -> Result { + if &dev.get_devtype()? != "partition" { + return Ok(()); + } + + let ud = from_rd(dev.clone()); + + let p = udev_device_get_parent(ud); + + assert!(!p.is_null()); + + let p_rc = dev.get_parent().unwrap(); + + assert_eq!( + unsafe { CStr::from_ptr(udev_device_get_syspath(p)) } + .to_str() + .unwrap(), + &p_rc.get_syspath().unwrap() + ); + + Ok(()) + } + + fn test_udev_device_get_parent_with_subsystem_devtype(dev: RD) -> Result { + if &dev.get_devtype()? == "partition" { + let p = dev + .get_parent_with_subsystem_devtype("block", Some("disk")) + .unwrap(); + + assert_eq!(&p.get_devtype()?, "disk"); + + let ud = from_rd(dev); + let pud = udev_device_get_parent_with_subsystem_devtype( + ud, + "block\0".as_ptr() as *const i8, + "disk\0".as_ptr() as *const i8, + ); + + assert!(!pud.is_null()); + let ud_mut: &mut udev_device = unsafe { transmute(&mut *ud) }; + let p1 = ud_mut + .device + .get_parent_with_subsystem_devtype("block", Some("disk")) + .unwrap(); + let pud_mut: &mut udev_device = unsafe { transmute(&mut *pud) }; + let p2: Rc = pud_mut.device.clone(); + + // The parent device object of ud should be the device object of pud. + let r1 = Rc::into_raw(p1); + let r2 = Rc::into_raw(p2); + assert_eq!(r1, r2); + + let _ = unsafe { Rc::from_raw(r1) }; + let _ = unsafe { Rc::from_raw(r2) }; + } + + Ok(()) + } + #[test] fn test_udev_device_ut() { let mut e = DeviceEnumerator::new(); @@ -789,4 +920,16 @@ mod test { let _ = test_udev_device_get_seqnum(dev.clone()); let _ = test_udev_device_get_property_value(dev); } + + #[test] + fn test_enumerate_block() { + let mut e = DeviceEnumerator::new(); + e.set_enumerator_type(DeviceEnumerationType::Devices); + e.add_match_subsystem("block", true).unwrap(); + + for dev in e.iter() { + let _ = test_udev_device_get_parent_with_subsystem_devtype(dev.clone()); + let _ = test_udev_device_get_parent(dev.clone()); + } + } } -- Gitee From 4d0ac3bca447be87e8998c6cc36ea82010dd3c1c Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 9 Dec 2023 01:34:45 +0800 Subject: [PATCH 07/48] feature(libudev): support udev_device_get_is_initialized Support udev_device_get_is_initialized --- exts/libudev/src/libudev_device.rs | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 18dded99..1279ecb9 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -548,6 +548,28 @@ pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( std::ptr::null_mut() } +#[no_mangle] +/// udev_device_get_is_initialized +pub extern "C" fn udev_device_get_is_initialized( + udev_device: *mut udev_device, +) -> ::std::os::raw::c_int { + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + match ud.device.get_is_initialized() { + Ok(r) => { + if r { + 1 + } else { + 0 + } + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + 0 + } + } +} + #[cfg(test)] mod test { use std::intrinsics::transmute; @@ -887,6 +909,17 @@ mod test { Ok(()) } + fn test_udev_device_get_is_initialized(dev: RD) -> Result { + let ud = from_rd(dev); + let ud_mut: &mut udev_device = unsafe { transmute(&mut *ud) }; + + ud_mut.device.set_is_initialized(); + + assert!(udev_device_get_is_initialized(ud) > 0); + + Ok(()) + } + #[test] fn test_udev_device_ut() { let mut e = DeviceEnumerator::new(); @@ -904,6 +937,7 @@ mod test { let _ = test_udev_device_get_driver(dev.clone()); let _ = test_udev_device_get_sysname(dev.clone()); let _ = test_udev_device_get_subsystem(dev.clone()); + let _ = test_udev_device_get_is_initialized(dev.clone()); } } -- Gitee From f2ac25dfecc89e0544814ba3437439a62b471016 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Mon, 11 Dec 2023 10:16:46 +0800 Subject: [PATCH 08/48] feature(libudev): support udev_list_entry Support several ABIs: udev_list_entry_get_next udev_list_entry_get_by_name udev_list_entry_get_name udev_list_entry_get_value --- exts/libudev/src/lib.rs | 2 + exts/libudev/src/libudev_list.rs | 215 +++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 exts/libudev/src/libudev_list.rs diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index d15e2771..45794da1 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -17,3 +17,5 @@ pub mod libudev; /// libudev_device pub mod libudev_device; +/// libudev_list +pub mod libudev_list; diff --git a/exts/libudev/src/libudev_list.rs b/exts/libudev/src/libudev_list.rs new file mode 100644 index 00000000..33af8639 --- /dev/null +++ b/exts/libudev/src/libudev_list.rs @@ -0,0 +1,215 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use libudev_macro::RefUnref; +use std::{ + cell::RefCell, + cmp::Ordering, + collections, + ffi::{CStr, CString}, + rc::{Rc, Weak}, +}; + +#[repr(C)] +#[derive(Debug, Clone, RefUnref)] +/// udev_list_entry +pub struct udev_list_entry { + list: Weak, + name: CString, + value: CString, +} + +#[repr(C)] +#[derive(Debug, Clone)] +/// udev_list_entry +pub struct udev_list { + unique_entries: RefCell>>, + entries: RefCell>>, + idx: RefCell, + + unique: bool, + up_to_date: RefCell, +} + +impl udev_list { + pub(crate) fn new(unique: bool) -> Self { + Self { + unique_entries: RefCell::new(collections::HashMap::default()), + entries: RefCell::new(Vec::default()), + idx: RefCell::new(0), + unique, + up_to_date: RefCell::new(false), + } + } + + pub(crate) fn add_entry(self: &Rc, name: CString, value: CString) -> Rc { + let entry = Rc::new(udev_list_entry { + list: Rc::downgrade(self), + name: name.clone(), + value, + }); + + if self.unique { + self.unique_entries.borrow_mut().insert(name, entry.clone()); + self.up_to_date.replace(false); + } else { + self.entries.borrow_mut().push(entry.clone()); + } + + entry + } + + pub(crate) fn cleanup(&self) { + if self.unique { + self.up_to_date.replace(false); + self.unique_entries.borrow_mut().clear(); + } else { + self.entries.borrow_mut().clear(); + } + } +} + +impl Ord for udev_list_entry { + fn cmp(&self, other: &Self) -> Ordering { + self.name.cmp(&other.name) + } +} + +impl PartialOrd for udev_list_entry { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for udev_list_entry { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +impl Eq for udev_list_entry {} + +impl udev_list { + pub(crate) fn get_entry(self: &udev_list) -> *mut udev_list_entry { + if self.unique && !*self.up_to_date.borrow() { + for (_, v) in self.unique_entries.borrow().iter() { + self.entries.borrow_mut().push(v.clone()); + } + self.entries.borrow_mut().sort(); + self.up_to_date.replace(true); + } + + self.idx.replace(0); + self.get_entry_next() + } + + pub(crate) fn get_entry_next(self: &udev_list) -> *mut udev_list_entry { + let idx = *self.idx.borrow(); + self.idx.replace(idx + 1); + self.entries + .borrow() + .get(idx) + .map(|e| Rc::as_ptr(e) as *mut udev_list_entry) + .unwrap_or_else(std::ptr::null_mut) + } +} + +#[no_mangle] +/// udev_list_entry_get_next +pub extern "C" fn udev_list_entry_get_next( + list_entry: *mut udev_list_entry, +) -> *mut udev_list_entry { + /* Take the ownership of udev_list_entry */ + let entry = unsafe { Rc::from_raw(list_entry) }; + + let list = Rc::into_raw(entry.list.clone().upgrade().unwrap()) as *mut udev_list; + let list_mut: &mut udev_list = unsafe { std::mem::transmute(&mut *list) }; + let ret = list_mut.get_entry_next(); + let _ = unsafe { Rc::from_raw(list) }; + + /* Return the ownership of udev_list_entry */ + let _ = Rc::into_raw(entry); + + ret +} + +#[no_mangle] +/// udev_list_entry_get_by_name +pub extern "C" fn udev_list_entry_get_by_name( + list_entry: *mut udev_list_entry, + name: *const ::std::os::raw::c_char, +) -> *mut udev_list_entry { + if list_entry.is_null() { + return std::ptr::null_mut(); + } + + let name = unsafe { CStr::from_ptr(name) }.to_owned(); + /* Take the ownership of udev_list_entry */ + let entry = unsafe { Rc::from_raw(list_entry) }; + let list = entry.list.clone().upgrade().unwrap(); + + if !list.unique || !*list.up_to_date.borrow() { + return std::ptr::null_mut(); + } + + let ret = list + .unique_entries + .borrow() + .get(&name) + .map(|v| Rc::as_ptr(v) as *mut udev_list_entry) + .unwrap_or_else(std::ptr::null_mut); + + /* Return the ownership of udev_list_entry */ + let _ = Rc::into_raw(entry); + + ret +} + +#[no_mangle] +/// udev_list_entry_get_name +pub extern "C" fn udev_list_entry_get_name( + list_entry: *mut udev_list_entry, +) -> *const ::std::os::raw::c_char { + if list_entry.is_null() { + return std::ptr::null(); + } + + /* Take the ownership of udev_list_entry */ + let entry = unsafe { Rc::from_raw(list_entry) }; + let ret = entry.name.as_ptr(); + /* Return the ownership of udev_list_entry */ + let _ = Rc::into_raw(entry); + ret +} + +#[no_mangle] +/// udev_list_entry_get_value +pub extern "C" fn udev_list_entry_get_value( + list_entry: *mut udev_list_entry, +) -> *const ::std::os::raw::c_char { + if list_entry.is_null() { + return std::ptr::null(); + } + + /* Take the ownership of udev_list_entry */ + let entry = unsafe { Rc::from_raw(list_entry) }; + let ret = entry.value.as_ptr(); + /* Return the ownership of udev_list_entry */ + let _ = Rc::into_raw(entry); + ret +} -- Gitee From 9e7e205461c3406aea023a81b17b706870ac9c3f Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Mon, 11 Dec 2023 17:14:09 +0800 Subject: [PATCH 09/48] feature(libudev): support udev_device_get_devlinks_list_entry Support ABI udev_device_get_devlinks_list_entry --- exts/libudev/src/libudev_device.rs | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 1279ecb9..e4150621 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -24,6 +24,7 @@ use std::os::linux::raw::dev_t; use std::rc::Rc; use crate::libudev::*; +use crate::libudev_list::{udev_list, udev_list_entry}; use libudev_macro::RefUnref; const ACTION_CNT: usize = 8; @@ -57,6 +58,9 @@ pub struct udev_device { pub(crate) properties: HashMap, + pub(crate) devlinks: Rc, + pub(crate) devlinks_read: bool, + pub(crate) parent: *mut udev_device, } @@ -82,6 +86,8 @@ impl udev_device { sysname: CString::default(), subsystem: CString::default(), properties: HashMap::default(), + devlinks: Rc::new(udev_list::new(true)), + devlinks_read: false, parent: std::ptr::null_mut(), } } @@ -570,10 +576,32 @@ pub extern "C" fn udev_device_get_is_initialized( } } +#[no_mangle] +pub extern "C" fn udev_device_get_devlinks_list_entry( + udev_device: *mut udev_device, +) -> *mut udev_list_entry { + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !ud.devlinks_read { + ud.devlinks.cleanup(); + + for devlink in &ud.device.devlink_iter() { + let devlink_cstr = CString::new(devlink.as_str()).unwrap(); + ud.devlinks.add_entry(devlink_cstr, CString::default()); + } + + ud.devlinks_read = true; + } + + ud.devlinks.get_entry() +} + #[cfg(test)] mod test { use std::intrinsics::transmute; + use crate::libudev_list::{udev_list_entry_get_name, udev_list_entry_get_next}; + use super::*; use device::device_enumerator::*; @@ -920,6 +948,28 @@ mod test { Ok(()) } + fn test_udev_device_get_devlinks_list_entry(dev: RD) -> Result { + dev.read_db_internal(true)?; + let ud = from_rd(dev.clone()); + + let mut entry = udev_device_get_devlinks_list_entry(ud); + + loop { + if entry.is_null() { + break; + } + + let link_c = unsafe { CStr::from_ptr(udev_list_entry_get_name(entry)) }; + + let link = link_c.to_str().unwrap(); + assert!(dev.has_devlink(link)); + + entry = udev_list_entry_get_next(entry); + } + + Ok(()) + } + #[test] fn test_udev_device_ut() { let mut e = DeviceEnumerator::new(); @@ -964,6 +1014,7 @@ mod test { for dev in e.iter() { let _ = test_udev_device_get_parent_with_subsystem_devtype(dev.clone()); let _ = test_udev_device_get_parent(dev.clone()); + let _ = test_udev_device_get_devlinks_list_entry(dev.clone()); } } } -- Gitee From 9a995d5ed5a3a8fcb709d4aafdb5b12cf4e82eb7 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Mon, 11 Dec 2023 17:15:13 +0800 Subject: [PATCH 10/48] test(libudev): supplement test case for udev_list_entry on memory leak --- exts/libudev/src/libudev_device.rs | 1 + exts/libudev/tests/test_libudev_device_leak.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index e4150621..667ab3d5 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -577,6 +577,7 @@ pub extern "C" fn udev_device_get_is_initialized( } #[no_mangle] +/// udev_device_get_devlinks_list_entry pub extern "C" fn udev_device_get_devlinks_list_entry( udev_device: *mut udev_device, ) -> *mut udev_list_entry { diff --git a/exts/libudev/tests/test_libudev_device_leak.c b/exts/libudev/tests/test_libudev_device_leak.c index f5e981fd..afcb6e15 100644 --- a/exts/libudev/tests/test_libudev_device_leak.c +++ b/exts/libudev/tests/test_libudev_device_leak.c @@ -6,9 +6,15 @@ void dump(struct udev_device *d) { + struct udev_list_entry *list_entry; const char *s = udev_device_get_syspath(d); - printf("%s\n", s); + printf("syspath: %s\n", s); + + udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(d)) + { + printf("link: '%s'\n", udev_list_entry_get_name(list_entry)); + } udev_device_unref(d); } @@ -20,5 +26,10 @@ void main() struct udev_device *lo = udev_device_new_from_device_id(NULL, "n1"); dump(udev_device_ref(lo)); lo = udev_device_unref(lo); + + /* Require /dev/sda1 exists and its device number is 8:1. */ + struct udev_device *sda1 = udev_device_new_from_device_id(NULL, "b8:1"); + dump(udev_device_ref(sda1)); + sda1 = udev_device_unref(sda1); } } -- Gitee From 139e033254396f6de75a9c71b1d507338a1095d2 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Thu, 14 Dec 2023 17:00:43 +0800 Subject: [PATCH 11/48] feature(libudev): support udev_enumerate Support related several ABIs: udev_enumerate_new udev_enumerate_ref udev_enumerate_unref udev_enumerate_scan_devices udev_enumerate_get_list_entry udev_enumerate_add_match_subsystem udev_enumerate_add_match_property udev_enumerate_add_match_is_initialized --- exts/libudev/src/lib.rs | 2 + exts/libudev/src/libudev_enumerate.rs | 233 ++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 exts/libudev/src/libudev_enumerate.rs diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index 45794da1..8553ad60 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -17,5 +17,7 @@ pub mod libudev; /// libudev_device pub mod libudev_device; +/// libudev_enumerate +pub mod libudev_enumerate; /// libudev_list pub mod libudev_list; diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs new file mode 100644 index 00000000..ba1517b3 --- /dev/null +++ b/exts/libudev/src/libudev_enumerate.rs @@ -0,0 +1,233 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use std::cell::RefCell; +use std::ffi::{CStr, CString}; +use std::intrinsics::transmute; +use std::rc::Rc; + +use crate::libudev::*; +use crate::libudev_list::{udev_list, udev_list_entry}; +use device::device_enumerator::*; +use libudev_macro::RefUnref; + +#[repr(C)] +#[derive(Clone, RefUnref)] +/// udev_enumerate +pub struct udev_enumerate { + pub(crate) udev: *mut udev, + pub(crate) devices_list: Rc, + pub(crate) up_to_date: bool, + + pub(crate) enumerator: Rc>, +} + +impl Drop for udev_enumerate { + fn drop(&mut self) { + if !self.udev.is_null() { + let _ = unsafe { Rc::from_raw(self.udev) }; + } + } +} + +#[no_mangle] +/// udev_enumerate_new +pub extern "C" fn udev_enumerate_new(udev: *mut udev) -> *mut udev_enumerate { + let mut enumerator = DeviceEnumerator::new(); + if let Err(e) = enumerator.allow_uninitialized() { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + return std::ptr::null_mut(); + } + + Rc::into_raw(Rc::new(udev_enumerate { + udev, + devices_list: Rc::new(udev_list::new(true)), + up_to_date: false, + enumerator: Rc::new(RefCell::new(enumerator)), + })) as *mut udev_enumerate +} + +#[no_mangle] +/// udev_enumerate_scan_devices +pub extern "C" fn udev_enumerate_scan_devices( + udev_enumerate: *mut udev_enumerate, +) -> ::std::os::raw::c_int { + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + match udev_enumerate.enumerator.borrow_mut().scan_devices() { + Ok(_) => 0, + Err(e) => e.get_errno() as i32, + } +} + +#[no_mangle] +/// udev_enumerate_get_list_entry +pub extern "C" fn udev_enumerate_get_list_entry( + udev_enumerate: *mut udev_enumerate, +) -> *mut udev_list_entry { + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + if !udev_enumerate.up_to_date { + udev_enumerate.devices_list.cleanup(); + + for i in udev_enumerate.enumerator.borrow_mut().iter() { + let syspath = match i.get_syspath() { + Ok(s) => s, + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + return std::ptr::null_mut(); + } + }; + + udev_enumerate + .devices_list + .add_entry(CString::new(syspath).unwrap(), CString::default()); + } + } + + let ret = udev_enumerate.devices_list.get_entry(); + + if ret.is_null() { + errno::set_errno(errno::Errno(libc::ENODATA)); + } + + ret +} + +#[no_mangle] +/// udev_enumerate_add_match_subsystem +pub extern "C" fn udev_enumerate_add_match_subsystem( + udev_enumerate: *mut udev_enumerate, + subsystem: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + if subsystem.is_null() { + return 0; + } + + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + let subsystem = unsafe { CStr::from_ptr(subsystem) }.to_str().unwrap(); + + if let Err(e) = udev_enumerate + .enumerator + .borrow_mut() + .add_match_subsystem(subsystem, true) + { + return e.get_errno() as i32; + } + + udev_enumerate.up_to_date = false; + + 0 +} + +#[no_mangle] +/// udev_enumerate_add_match_property +pub extern "C" fn udev_enumerate_add_match_property( + udev_enumerate: *mut udev_enumerate, + property: *const ::std::os::raw::c_char, + value: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + if property.is_null() { + return 0; + } + + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + let property = unsafe { CStr::from_ptr(property) }.to_str().unwrap(); + let value = unsafe { CStr::from_ptr(value) }.to_str().unwrap(); + + if let Err(e) = udev_enumerate + .enumerator + .borrow_mut() + .add_match_property(property, value) + { + return e.get_errno() as i32; + } + + udev_enumerate.up_to_date = false; + + 0 +} + +#[no_mangle] +/// udev_enumerate_add_match_is_initialized +pub fn udev_enumerate_add_match_is_initialized( + udev_enumerate: *mut udev_enumerate, +) -> ::std::os::raw::c_int { + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + if let Err(e) = udev_enumerate + .enumerator + .borrow_mut() + .add_match_is_initialized(MatchInitializedType::Compat) + { + return e.get_errno() as i32; + } + + udev_enumerate.up_to_date = false; + + 0 +} + +#[cfg(test)] +mod tests { + use device::Device; + + use crate::libudev_list::{udev_list_entry_get_name, udev_list_entry_get_next}; + + use super::*; + + #[test] + fn test_enumerator() { + let e = udev_enumerate_new(std::ptr::null_mut()); + + assert_eq!( + udev_enumerate_add_match_subsystem(e, "block\0".as_ptr() as *const i8), + 0 + ); + assert_eq!( + udev_enumerate_add_match_property( + e, + "ID_TYPE\0".as_ptr() as *const i8, + "disk\0".as_ptr() as *const i8, + ), + 0 + ); + assert_eq!(udev_enumerate_add_match_is_initialized(e), 0); + assert_eq!(udev_enumerate_scan_devices(e), 0); + + let mut entry = udev_enumerate_get_list_entry(e); + + loop { + if entry.is_null() { + break; + } + + let syspath = unsafe { CStr::from_ptr(udev_list_entry_get_name(entry)) }; + + let syspath = syspath.to_str().unwrap(); + + let device = Device::from_syspath(syspath, true).unwrap(); + assert_eq!(&device.get_subsystem().unwrap(), "block"); + assert_eq!(&device.get_property_value("ID_TYPE").unwrap(), "disk"); + + entry = udev_list_entry_get_next(entry); + } + } +} -- Gitee From ec9f75a8b47bfcc1bea8ba83a2969c2047a26548 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Thu, 14 Dec 2023 17:08:26 +0800 Subject: [PATCH 12/48] test(libudev): test memory leak for udev_enumerate in C program --- exts/libudev/tests/test_libudev_device_leak.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/exts/libudev/tests/test_libudev_device_leak.c b/exts/libudev/tests/test_libudev_device_leak.c index afcb6e15..920fef63 100644 --- a/exts/libudev/tests/test_libudev_device_leak.c +++ b/exts/libudev/tests/test_libudev_device_leak.c @@ -31,5 +31,17 @@ void main() struct udev_device *sda1 = udev_device_new_from_device_id(NULL, "b8:1"); dump(udev_device_ref(sda1)); sda1 = udev_device_unref(sda1); + + struct udev_list_entry *list_entry; + struct udev_enumerate *e = udev_enumerate_new(NULL); + udev_enumerate_add_match_subsystem(e, "block"); + udev_enumerate_add_match_property(e, "ID_TYPE", "disk"); + udev_enumerate_add_match_is_initialized(e); + udev_enumerate_scan_devices(e); + udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(e)) + { + printf("block syspath: '%s'\n", udev_list_entry_get_name(list_entry)); + } + udev_enumerate_unref(e); } } -- Gitee From 77cd3a4792d94cae7526d834582b89b5be66219f Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 02:30:02 +0800 Subject: [PATCH 13/48] feature(device): support BPF socket filter BPF is a mechanism that lets the kernel do packets filtering instead of the userspace program itself. It can be used to increase the packets filtering efficiency. --- libs/device/src/device_monitor.rs | 142 +++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 3 deletions(-) diff --git a/libs/device/src/device_monitor.rs b/libs/device/src/device_monitor.rs index c7a488b6..713cb9bd 100644 --- a/libs/device/src/device_monitor.rs +++ b/libs/device/src/device_monitor.rs @@ -16,6 +16,7 @@ use crate::{device::Device, error::Error}; use basic::errno_is_transient; use basic::murmurhash2::murmurhash2; use basic::socket_util::next_datagram_size_fd; +use libc::*; use nix::{ errno::Errno, sys::socket::{ @@ -45,6 +46,18 @@ fn string_bloom64(s: &str) -> u64 { bits } +#[inline] +/// Generate a BPF instruction +fn bpf_inst(ins: &mut Vec, code: u32, jt: u8, jf: u8, k: u32) { + let inst = sock_filter { + code: code as u16, + jt: jt as u8, + jf: jf as u8, + k: k as u32, + }; + ins.push(inst); +} + /// netlink group of device monitor pub enum MonitorNetlinkGroup { /// none group @@ -101,7 +114,7 @@ pub struct DeviceMonitor { /// socket fd socket: RawFd, /// socket address, currently only support netlink - _sockaddr: NetlinkAddr, + sockaddr: NetlinkAddr, /// key:subsystem value:devtype subsystem_filter: HashMap, @@ -132,7 +145,7 @@ impl DeviceMonitor { DeviceMonitor { socket: sock, - _sockaddr: sa, + sockaddr: sa, subsystem_filter: HashMap::new(), tag_filter: HashSet::new(), match_sysattr_filter: HashMap::new(), @@ -251,7 +264,7 @@ impl DeviceMonitor { if tag_bloom_bits > 0 { header.filter_tag_bloom_hi = ((tag_bloom_bits >> 32) as u32).to_be(); - header.filter_tag_bloom_lo = ((tag_bloom_bits & 0xffffffff) as u32).to_be(); + header.filter_tag_bloom_lo = ((tag_bloom_bits & 0xffffffff_u64) as u32).to_be(); } let iov = [IoSlice::new(header.to_bytes()), IoSlice::new(&properties)]; @@ -361,6 +374,129 @@ impl DeviceMonitor { } false } + + /// Call this method to let the socket filter make sense + /// whenever filter conditions are updated. + pub fn bpf_filter_update(&mut self) -> Result<(), Error> { + if self.filter_uptodate { + return Ok(()); + } + + /* No need to filter uevents from kernel. */ + if self.sockaddr.groups() == MonitorNetlinkGroup::Kernel as u32 + || (self.subsystem_filter.is_empty() && self.tag_filter.is_empty()) + { + self.filter_uptodate = true; + return Ok(()); + } + + let mut ins: Vec = Vec::new(); + + /* Load magic sense code, the offset of magic is 8 bytes */ + bpf_inst(&mut ins, BPF_LD | BPF_W | BPF_ABS, 0, 0, 8); + /* Jump 1 step if magic matches */ + bpf_inst( + &mut ins, + BPF_JMP | BPF_JEQ | BPF_K, + 1, + 0, + UDEV_MONITOR_MAGIC, + ); + /* Illegal magic, pass the packet */ + bpf_inst(&mut ins, BPF_RET | BPF_K, 0, 0, 0xffffffff); + + if !self.tag_filter.is_empty() { + let mut tag_n = self.tag_filter.len(); + + for tag in self.tag_filter.iter() { + let tag_bloom_bits = string_bloom64(tag); + let hi = (tag_bloom_bits >> 32) as u32; + let lo = (tag_bloom_bits & 0xffffffff_u64) as u32; + /* Load tag high bloom bits */ + bpf_inst(&mut ins, BPF_LD | BPF_W | BPF_ABS, 0, 0, 32); + /* Bits and */ + bpf_inst(&mut ins, BPF_ALU | BPF_AND | BPF_K, 0, 0, hi); + /* Skip 3 steps to continue matching the next tag */ + bpf_inst(&mut ins, BPF_JMP | BPF_JEQ | BPF_K, 0, 3, hi); + + /* Load tag low bloom bits */ + bpf_inst(&mut ins, BPF_LD | BPF_W | BPF_ABS, 0, 0, 36); + /* Bits and */ + bpf_inst(&mut ins, BPF_ALU | BPF_AND | BPF_K, 0, 0, lo); + + tag_n -= 1; + /* Skip 3 steps to continue matching the next tag */ + bpf_inst( + &mut ins, + BPF_JMP | BPF_JEQ | BPF_K, + (1 + (tag_n * 6)) as u8, + 0, + lo, + ); + } + + /* No tag matched, drop the packet */ + bpf_inst(&mut ins, BPF_RET | BPF_K, 0, 0, 0); + } + + if !self.subsystem_filter.is_empty() { + for (subsystem, devtype) in self.subsystem_filter.iter() { + let subsystem_hash = string_hash32(subsystem); + + /* Load subsystem hash */ + bpf_inst(&mut ins, BPF_LD | BPF_W | BPF_ABS, 0, 0, 24); + if devtype.is_empty() { + /* Jump 1 step when subsystem is not matched */ + bpf_inst(&mut ins, BPF_JMP | BPF_JEQ | BPF_K, 0, 1, subsystem_hash); + } else { + /* Jump 3 steps when subsystem is not matched */ + bpf_inst(&mut ins, BPF_JMP | BPF_JEQ | BPF_K, 0, 3, subsystem_hash); + /* Load devtype hash */ + bpf_inst(&mut ins, BPF_LD | BPF_W | BPF_ABS, 0, 0, 28); + let devtype_hash = string_hash32(devtype); + /* Jump 1 step when devtype is not matched */ + bpf_inst(&mut ins, BPF_JMP | BPF_JEQ | BPF_K, 0, 1, devtype_hash); + } + + /* Subsystem matched, pass the packet */ + bpf_inst(&mut ins, BPF_RET | BPF_K, 0, 0, 0xffffffff); + } + + /* Nothing matched, drop the packet */ + bpf_inst(&mut ins, BPF_RET | BPF_K, 0, 0, 0); + } + + /* Pass the packet */ + bpf_inst(&mut ins, BPF_RET | BPF_K, 0, 0, 0xffffffff); + + let filter = sock_fprog { + len: ins.len() as u16, + filter: ins.as_ptr() as *mut libc::sock_filter, + }; + + let r = unsafe { + setsockopt( + self.socket, + SOL_SOCKET, + SO_ATTACH_FILTER, + &filter as *const sock_fprog as *const _, + size_of::() as u32, + ) + }; + + if r < 0 { + return Err(Error::Nix { + msg: "failed to set socket filter".to_string(), + source: nix::Error::from_i32( + std::io::Error::last_os_error().raw_os_error().unwrap(), + ), + }); + } + + self.filter_uptodate = true; + + Ok(()) + } } impl Drop for DeviceMonitor { -- Gitee From 0dff3bd130f53d938553d8ac61425dbf7923ee56 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 02:31:38 +0800 Subject: [PATCH 14/48] test(device): add example for using device monitor --- libs/device/examples/device_monitor.rs | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 libs/device/examples/device_monitor.rs diff --git a/libs/device/examples/device_monitor.rs b/libs/device/examples/device_monitor.rs new file mode 100644 index 00000000..b62cce30 --- /dev/null +++ b/libs/device/examples/device_monitor.rs @@ -0,0 +1,76 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +//! Example for monitoring uevent sended by devmaster. +//! +//! This example shows the different impunity whether using bpf filter or not. +//! +//! Run this example with devmaster running, and use devctl to trigger any +//! disks with partitions. +//! +//! The partition disks will be monitored and be printed, while the whole block +//! disk will be filtered. +//! +//! The monitor m1 that used bpf filter won't raise messages like 'm1 filtered', +//! while the monitor m2 that filters packets by itself will raise messages like +//! 'm2 filtered'. +//! + +use device::device_monitor::*; + +fn main() { + let mut m1 = DeviceMonitor::new(MonitorNetlinkGroup::Userspace, None); + m1.filter_add_match_subsystem_devtype("block", "partition") + .unwrap(); + + let mut m2 = DeviceMonitor::new(MonitorNetlinkGroup::Userspace, None); + m2.filter_add_match_subsystem_devtype("block", "partition") + .unwrap(); + + /* If bpf_filter_update is called, the illegal uevent packages + * are filtered inside OS and thus this example will not print + * "monitor filtered" messages. + */ + m1.bpf_filter_update().unwrap(); + + /* Run devmaster and trigger uevents for partitions */ + loop { + if let Ok(d) = m1.receive_device() { + match d { + Some(dev) => { + println!("m1 receive device: {}", dev.get_syspath().unwrap()); + } + None => { + /* m1 has called bpf_filter_update method, + * thus the following message will not be printed. + */ + println!("m1 filtered"); + } + } + } + + if let Ok(d) = m2.receive_device() { + match d { + Some(dev) => { + println!("m2 receive device: {}", dev.get_syspath().unwrap()); + } + None => { + /* m2 did not called bpf_filter_update method, + * it will filter the uevent packages by itself and + * print the following message. + */ + println!("m2 filtered"); + } + } + } + } +} -- Gitee From cb47d221bf35205a3246457b690d82c2951a8cce Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 03:16:50 +0800 Subject: [PATCH 15/48] feature(libudev): support udev_monitor Support some udev_monitor_* ABIs: udev_monitor_new_from_netlink udev_monitor_enable_receiving udev_monitor_filter_add_match_subsystem_devtype udev_monitor_filter_add_match_tag udev_monitor_get_fd udev_monitor_get_udev udev_monitor_receive_device udev_monitor_set_receive_buffer_size udev_monitor_ref udev_monitor_unref --- Cargo.lock | 1 + exts/libudev/Cargo.toml | 3 + exts/libudev/src/lib.rs | 2 + exts/libudev/src/libudev_device.rs | 2 +- exts/libudev/src/libudev_monitor.rs | 173 ++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 exts/libudev/src/libudev_monitor.rs diff --git a/Cargo.lock b/Cargo.lock index ffb523d8..a1df3bb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1010,6 +1010,7 @@ version = "0.5.1" name = "libudev" version = "0.5.1" dependencies = [ + "basic", "device", "errno 0.3.8", "libc", diff --git a/exts/libudev/Cargo.toml b/exts/libudev/Cargo.toml index bbb11fc8..cf7c31b6 100644 --- a/exts/libudev/Cargo.toml +++ b/exts/libudev/Cargo.toml @@ -14,3 +14,6 @@ libudev_macro = { path = "../libudev_macro" } libc = { default-features = false, version = "0.2.140" } nix = { default-features = false, version = "0.24" } errno = { version = "0.3.8", default-features = false } +basic = { path = "../../libs/basic", default-features = false, features = [ + "socket", +] } diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index 8553ad60..9f63830a 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -21,3 +21,5 @@ pub mod libudev_device; pub mod libudev_enumerate; /// libudev_list pub mod libudev_list; +/// libudev_monitor +pub mod libudev_monitor; diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 667ab3d5..5b331b54 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -74,7 +74,7 @@ impl Drop for udev_device { } impl udev_device { - fn new(udev: *mut udev, device: Rc) -> Self { + pub(crate) fn new(udev: *mut udev, device: Rc) -> Self { Self { udev, device, diff --git a/exts/libudev/src/libudev_monitor.rs b/exts/libudev/src/libudev_monitor.rs new file mode 100644 index 00000000..f53e77dc --- /dev/null +++ b/exts/libudev/src/libudev_monitor.rs @@ -0,0 +1,173 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use crate::libudev::*; +use crate::libudev_device::udev_device; +use device::device_monitor::*; +use libudev_macro::RefUnref; +use std::cell::RefCell; +use std::ffi::CStr; +use std::intrinsics::transmute; +use std::rc::Rc; + +#[repr(C)] +#[derive(Clone, RefUnref)] +/// udev_monitor +pub struct udev_monitor { + pub(crate) udev: *mut udev, + pub(crate) monitor: Rc>, +} + +impl Drop for udev_monitor { + fn drop(&mut self) { + let _ = unsafe { Rc::from_raw(self.udev) }; + } +} + +#[no_mangle] +/// udev_monitor_new_from_netlink +pub extern "C" fn udev_monitor_new_from_netlink( + udev: *mut udev, + name: *const ::std::os::raw::c_char, +) -> *mut udev_monitor { + let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap(); + + let g = match name { + "kernel" => MonitorNetlinkGroup::Kernel, + "udev" => MonitorNetlinkGroup::Userspace, + _ => { + if name.is_empty() { + MonitorNetlinkGroup::None + } else { + errno::set_errno(errno::Errno(libc::EINVAL)); + return std::ptr::null_mut(); + } + } + }; + + let monitor = Rc::new(RefCell::new(DeviceMonitor::new(g, None))); + + Rc::into_raw(Rc::new(udev_monitor { udev, monitor })) as *mut udev_monitor +} + +#[no_mangle] +/// udev_monitor_enable_receiving +pub extern "C" fn udev_monitor_enable_receiving( + udev_monitor: *mut udev_monitor, +) -> ::std::os::raw::c_int { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + + match m.monitor.borrow_mut().bpf_filter_update() { + Ok(_) => 0, + Err(e) => e.get_errno() as i32, + } +} + +#[no_mangle] +/// udev_monitor_filter_add_match_subsystem_devtype +pub extern "C" fn udev_monitor_filter_add_match_subsystem_devtype( + udev_monitor: *mut udev_monitor, + subsystem: *const ::std::os::raw::c_char, + devtype: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + + let subsystem = unsafe { CStr::from_ptr(subsystem) } + .to_str() + .unwrap_or_default(); + let devtype = unsafe { CStr::from_ptr(devtype) } + .to_str() + .unwrap_or_default(); + + if let Err(e) = m + .monitor + .borrow_mut() + .filter_add_match_subsystem_devtype(subsystem, devtype) + { + return e.get_errno() as i32; + } + + 0 +} + +#[no_mangle] +/// udev_monitor_filter_add_match_tag +pub extern "C" fn udev_monitor_filter_add_match_tag( + udev_monitor: *mut udev_monitor, + tag: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + + let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap_or_default(); + + if let Err(e) = m.monitor.borrow_mut().filter_add_match_tag(tag) { + return e.get_errno() as i32; + } + + 0 +} + +#[no_mangle] +/// udev_monitor_get_fd +pub extern "C" fn udev_monitor_get_fd(udev_monitor: *mut udev_monitor) -> ::std::os::raw::c_int { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + + m.monitor.borrow().fd() +} + +#[no_mangle] +/// udev_monitor_get_udev +pub extern "C" fn udev_monitor_get_udev(udev_monitor: *mut udev_monitor) -> *mut udev { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + m.udev +} + +#[no_mangle] +/// udev_monitor_receive_device +pub extern "C" fn udev_monitor_receive_device(udev_monitor: *mut udev_monitor) -> *mut udev_device { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + + loop { + match m.monitor.borrow().receive_device() { + Ok(Some(d)) => { + return Rc::into_raw(Rc::new(udev_device::new(m.udev, Rc::new(d)))) + as *mut udev_device + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + return std::ptr::null_mut(); + } + _ => continue, + } + } +} + +#[no_mangle] +/// udev_monitor_set_receive_buffer_size +pub extern "C" fn udev_monitor_set_receive_buffer_size( + udev_monitor: *mut udev_monitor, + size: ::std::os::raw::c_int, +) -> ::std::os::raw::c_int { + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; + + if let Err(e) = basic::socket_util::set_receive_buffer(m.monitor.borrow().fd(), size as usize) { + return e.get_errno() as i32; + } + + 0 +} -- Gitee From 7ca1d05defe98273e9507fba8ab7489fbb58ba25 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 03:18:10 +0800 Subject: [PATCH 16/48] test(libudev): test udev monitor in C program --- exts/libudev/tests/test_libudev_monitor.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 exts/libudev/tests/test_libudev_monitor.c diff --git a/exts/libudev/tests/test_libudev_monitor.c b/exts/libudev/tests/test_libudev_monitor.c new file mode 100644 index 00000000..9f183cc9 --- /dev/null +++ b/exts/libudev/tests/test_libudev_monitor.c @@ -0,0 +1,21 @@ +#include +#include +#include + +#include + +void main() +{ + struct udev_monitor *m = udev_monitor_new_from_netlink(NULL, "kernel"); + udev_monitor_filter_add_match_subsystem_devtype(m, "block", "partition"); + udev_monitor_enable_receiving(m); + while (1) + { + struct udev_device *d = udev_monitor_receive_device(m); + if (d != NULL) + { + printf("%s\n", udev_device_get_syspath(d)); + udev_device_unref(d); + } + } +} -- Gitee From 40bcbe0b5d52976b5b2af36bbba5aaeb2cc5b1af Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 04:51:30 +0800 Subject: [PATCH 17/48] feature(libudev): support udev_queue Add some ABIs: udev_queue_new udev_queue_get_udev_is_active udev_queue_ref udev_queue_unref --- exts/libudev/src/lib.rs | 2 ++ exts/libudev/src/libudev_queue.rs | 49 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 exts/libudev/src/libudev_queue.rs diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index 9f63830a..8dd81a9a 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -23,3 +23,5 @@ pub mod libudev_enumerate; pub mod libudev_list; /// libudev_monitor pub mod libudev_monitor; +/// libudev_queue +pub mod libudev_queue; diff --git a/exts/libudev/src/libudev_queue.rs b/exts/libudev/src/libudev_queue.rs new file mode 100644 index 00000000..2c7181e0 --- /dev/null +++ b/exts/libudev/src/libudev_queue.rs @@ -0,0 +1,49 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use crate::libudev::*; +use libudev_macro::RefUnref; +use std::path::Path; +use std::rc::Rc; + +#[repr(C)] +#[derive(Clone, RefUnref)] +/// udev_queue +pub struct udev_queue { + pub(crate) udev: *mut udev, + pub(crate) fd: i32, +} + +#[no_mangle] +/// udev_queue_new +pub extern "C" fn udev_queue_new(udev: *mut udev) -> *mut udev_queue { + Rc::into_raw(Rc::new(udev_queue { + udev, + fd: -libc::EBADF, + })) as *mut _ +} + +#[no_mangle] +/// udev_queue_get_udev_is_active +/// +/// This function detects whether devmaster is running rather than udevd. +pub extern "C" fn udev_queue_get_udev_is_active( + _udev_queue: *mut udev_queue, +) -> ::std::os::raw::c_int { + Path::new("/run/devmaster/control").exists() as i32 +} -- Gitee From 48d3af280fad8937aa01d5eea8d5524972572f69 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 04:52:26 +0800 Subject: [PATCH 18/48] test(libudev): test udev_queue --- exts/libudev/tests/test_libudev_queue.c | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 exts/libudev/tests/test_libudev_queue.c diff --git a/exts/libudev/tests/test_libudev_queue.c b/exts/libudev/tests/test_libudev_queue.c new file mode 100644 index 00000000..9ce3c7f4 --- /dev/null +++ b/exts/libudev/tests/test_libudev_queue.c @@ -0,0 +1,42 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#include +#include +#include + +#include + +/* Run this example, and it will check wether + * devmaster is running if the libudev is + * preloaded with that from devmaster. + * + * Notice the devmaster is recognized as running + * if the socket file /run/devmaster/control exists. + * + * Simplely stop devmaster daemon will not clean up + * the socket automatically. Clean the socket manually. + */ +void main() +{ + while (1) + { + int ret = udev_queue_get_udev_is_active(NULL); + + if (ret > 0) + printf("devmaster running\n"); + else + printf("heartbeat\n"); + + sleep(1); + } +} -- Gitee From 26b75d00b9358414d042af03bc53332836d072b7 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 19:16:15 +0800 Subject: [PATCH 19/48] fix(libudev): clean up entry vector when the list content is expired The entry vector of udev_list is forgot to be cleaned up, that leads to redundancy entries over repeat list iteration. --- exts/libudev/src/libudev_list.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/exts/libudev/src/libudev_list.rs b/exts/libudev/src/libudev_list.rs index 33af8639..4542cce5 100644 --- a/exts/libudev/src/libudev_list.rs +++ b/exts/libudev/src/libudev_list.rs @@ -107,6 +107,7 @@ impl Eq for udev_list_entry {} impl udev_list { pub(crate) fn get_entry(self: &udev_list) -> *mut udev_list_entry { if self.unique && !*self.up_to_date.borrow() { + self.entries.borrow_mut().clear(); for (_, v) in self.unique_entries.borrow().iter() { self.entries.borrow_mut().push(v.clone()); } -- Gitee From 2f84ed03fc22819452a165e17830b70999399386 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 19:33:01 +0800 Subject: [PATCH 20/48] feature(libudev): support udev_hwdb Add some ABIs: udev_hwdb_new udev_hwdb_get_properties_list_entry udev_hwdb_ref udev_hwdb_unref --- Cargo.lock | 1 + exts/libudev/Cargo.toml | 1 + exts/libudev/src/lib.rs | 2 + exts/libudev/src/libudev_hwdb.rs | 122 +++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 exts/libudev/src/libudev_hwdb.rs diff --git a/Cargo.lock b/Cargo.lock index a1df3bb2..ab1c1e32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1013,6 +1013,7 @@ dependencies = [ "basic", "device", "errno 0.3.8", + "hwdb", "libc", "libudev_macro", "nix 0.24.3", diff --git a/exts/libudev/Cargo.toml b/exts/libudev/Cargo.toml index cf7c31b6..33efd141 100644 --- a/exts/libudev/Cargo.toml +++ b/exts/libudev/Cargo.toml @@ -17,3 +17,4 @@ errno = { version = "0.3.8", default-features = false } basic = { path = "../../libs/basic", default-features = false, features = [ "socket", ] } +hwdb = { path = "../../libs/hwdb", default-features = false } diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index 8dd81a9a..345c555f 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -25,3 +25,5 @@ pub mod libudev_list; pub mod libudev_monitor; /// libudev_queue pub mod libudev_queue; +/// libudev_hwdb +pub mod libudev_hwdb; diff --git a/exts/libudev/src/libudev_hwdb.rs b/exts/libudev/src/libudev_hwdb.rs new file mode 100644 index 00000000..51a84239 --- /dev/null +++ b/exts/libudev/src/libudev_hwdb.rs @@ -0,0 +1,122 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(deprecated)] +#![allow(clippy::not_unsafe_ptr_arg_deref)] + +use hwdb::SdHwdb; +use libudev_macro::RefUnref; +use std::{ + cell::RefCell, + ffi::{CStr, CString}, + intrinsics::transmute, + rc::Rc, +}; + +use crate::{ + libudev::udev, + libudev_list::{udev_list, udev_list_entry}, +}; + +#[repr(C)] +#[derive(Clone, RefUnref)] +/// udev_hwdb +pub struct udev_hwdb { + pub(crate) hwdb: Rc>, + pub(crate) properties: Rc, +} + +#[no_mangle] +/// udev_hwdb_new +pub extern "C" fn udev_hwdb_new(udev: *mut udev) -> *mut udev_hwdb { + let hwdb = match SdHwdb::new() { + Ok(h) => h, + Err(e) => { + errno::set_errno(errno::Errno(e as i32)); + return std::ptr::null_mut(); + } + }; + + Rc::into_raw(Rc::new(udev_hwdb { + hwdb: Rc::new(RefCell::new(hwdb)), + properties: Rc::new(udev_list::new(true)), + })) as *mut _ +} + +#[no_mangle] +/// udev_hwdb_get_properties_list_entry +pub extern "C" fn udev_hwdb_get_properties_list_entry( + hwdb: *mut udev_hwdb, + modalias: *const ::std::os::raw::c_char, + _flags: ::std::os::raw::c_uint, +) -> *mut udev_list_entry { + let h: &mut udev_hwdb = unsafe { transmute(&mut *hwdb) }; + + h.properties.cleanup(); + + let modalias = unsafe { CStr::from_ptr(modalias) }.to_str().unwrap(); + + if let Ok(properties) = h.hwdb.borrow_mut().get_properties(modalias.to_string()) { + for (k, v) in properties.iter() { + h.properties.add_entry( + CString::new(k.as_str()).unwrap(), + CString::new(v.as_str()).unwrap(), + ); + } + } + + let e = h.properties.get_entry(); + + if e.is_null() { + errno::set_errno(errno::Errno(libc::ENODATA)); + } + + e +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::libudev_list::*; + + #[test] + fn test_udev_hwdb() { + let hwdb = udev_hwdb_new(std::ptr::null_mut()); + let mut i = 0; + loop { + let mut list = udev_hwdb_get_properties_list_entry( + hwdb, + "evdev:input:b0003v0458p07081\0".as_ptr() as *const _, + 0, + ); + loop { + if list.is_null() { + break; + } + let name = udev_list_entry_get_name(list); + let value = udev_list_entry_get_value(list); + let name = unsafe { CStr::from_ptr(name) }; + let value = unsafe { CStr::from_ptr(value) }; + println!("{:?}={:?}", name, value); + list = udev_list_entry_get_next(list); + } + i += 1; + if i == 10 { + break; + } + } + udev_hwdb_unref(hwdb); + } +} -- Gitee From 80abb543b6cd5ffaf6208d7e42b772d1136dbfba Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 19:34:41 +0800 Subject: [PATCH 21/48] test(libudev): add C test example for udev_hwdb --- exts/libudev/tests/test_libudev_hwdb.c | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 exts/libudev/tests/test_libudev_hwdb.c diff --git a/exts/libudev/tests/test_libudev_hwdb.c b/exts/libudev/tests/test_libudev_hwdb.c new file mode 100644 index 00000000..99dd1937 --- /dev/null +++ b/exts/libudev/tests/test_libudev_hwdb.c @@ -0,0 +1,40 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#include +#include +#include + +#include + +void dump(struct udev_hwdb *hwdb, const char *modalias) +{ + struct udev_list_entry *list = NULL; + udev_list_entry_foreach(list, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) + { + printf("%s=%s\n", udev_list_entry_get_name(list), udev_list_entry_get_value(list)); + } + + udev_hwdb_unref(hwdb); +} + +void main() +{ + struct udev_hwdb *hwdb = udev_hwdb_new(NULL); + while (1) + { + dump(udev_hwdb_ref(hwdb), "evdev:input:b0003v0458p07081"); + dump(udev_hwdb_ref(hwdb), "evdev:input:b0003v06CBp00091"); + sleep(1); + } + udev_hwdb_unref(hwdb); +} -- Gitee From 0d66fdc97208092299de3cf69d8fc5b9fb06a711 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 19:38:29 +0800 Subject: [PATCH 22/48] fix(libudev): append prefix of underline for unused parameter Append prefix of underline for unused parameter to avoid clippy failure. --- exts/libudev/src/libudev_hwdb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/libudev/src/libudev_hwdb.rs b/exts/libudev/src/libudev_hwdb.rs index 51a84239..6bc0b2bf 100644 --- a/exts/libudev/src/libudev_hwdb.rs +++ b/exts/libudev/src/libudev_hwdb.rs @@ -40,7 +40,7 @@ pub struct udev_hwdb { #[no_mangle] /// udev_hwdb_new -pub extern "C" fn udev_hwdb_new(udev: *mut udev) -> *mut udev_hwdb { +pub extern "C" fn udev_hwdb_new(_udev: *mut udev) -> *mut udev_hwdb { let hwdb = match SdHwdb::new() { Ok(h) => h, Err(e) => { -- Gitee From 9058643b49796c9a5f9b1de482cdb83b4e3b984e Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 19:58:31 +0800 Subject: [PATCH 23/48] feature(libudev): support udev Add some ABIs: udev_new udev_ref udev_unref --- exts/libudev/src/libudev.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/exts/libudev/src/libudev.rs b/exts/libudev/src/libudev.rs index 082b7dc7..71343f6e 100644 --- a/exts/libudev/src/libudev.rs +++ b/exts/libudev/src/libudev.rs @@ -17,21 +17,23 @@ #![allow(clippy::not_unsafe_ptr_arg_deref)] use libudev_macro::RefUnref; +use std::ffi::c_void; use std::rc::Rc; #[repr(C)] #[derive(Debug, Clone, RefUnref)] /// udev +/// +/// userdata points to an stored data object, it does not own the lifetime of the object +/// and might be useful to access from callbacks. pub struct udev { - _unused: [u8; 0], + pub(crate) userdata: *mut c_void, } #[no_mangle] /// udev_new pub extern "C" fn udev_new() -> *mut udev { - std::ptr::null_mut() -} - -impl Drop for udev { - fn drop(&mut self) {} + Rc::into_raw(Rc::new(udev { + userdata: std::ptr::null_mut(), + })) as *mut _ } -- Gitee From 143913906c9a368eb1e8bf49a25214672a9d6d47 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 20:12:06 +0800 Subject: [PATCH 24/48] feature(libudev): support udev_enumerate_get_udev Support udev_enumerate_get_udev ABI --- exts/libudev/src/libudev_enumerate.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index ba1517b3..445b751b 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -185,6 +185,14 @@ pub fn udev_enumerate_add_match_is_initialized( 0 } +#[no_mangle] +/// udev_enumerate_get_udev +pub extern "C" fn udev_enumerate_get_udev(udev_enumerate: *mut udev_enumerate) -> *mut udev { + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + e.udev +} + #[cfg(test)] mod tests { use device::Device; -- Gitee From 9ea4801f7102651d92e1276e192ada53d0b7e8b9 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 20:34:49 +0800 Subject: [PATCH 25/48] feature(libudev): support some udev_enumerate_add_match_* ABIs Add some new ABIs: udev_enumerate_add_match_parent udev_enumerate_add_match_tag --- exts/libudev/src/libudev_enumerate.rs | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 445b751b..cf7121c0 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -22,6 +22,7 @@ use std::intrinsics::transmute; use std::rc::Rc; use crate::libudev::*; +use crate::libudev_device::udev_device; use crate::libudev_list::{udev_list, udev_list_entry}; use device::device_enumerator::*; use libudev_macro::RefUnref; @@ -193,6 +194,41 @@ pub extern "C" fn udev_enumerate_get_udev(udev_enumerate: *mut udev_enumerate) - e.udev } +#[no_mangle] +/// udev_enumerate_add_match_tag +pub extern "C" fn udev_enumerate_add_match_tag( + udev_enumerate: *mut udev_enumerate, + tag: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap(); + + if let Err(e) = e.enumerator.borrow_mut().add_match_tag(tag) { + return e.get_errno() as i32; + } + + e.up_to_date = false; + 0 +} + +#[no_mangle] +pub extern "C" fn udev_enumerate_add_match_parent( + udev_enumerate: *mut udev_enumerate, + parent: *mut udev_device, +) -> ::std::os::raw::c_int { + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + let p: Rc = unsafe { Rc::from_raw(parent) }; + + if let Err(e) = e.enumerator.borrow_mut().add_match_parent(&p.device) { + return e.get_errno() as i32; + } + + let _ = Rc::into_raw(p); + + e.up_to_date = false; + 0 +} + #[cfg(test)] mod tests { use device::Device; -- Gitee From df1556c1d5b1d9c2a9a0cb52318cfd54a466a33b Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 20:36:11 +0800 Subject: [PATCH 26/48] test(libudev): test udev_enumerate_add_match_parent and udev_enumerate_add_match_tag Test the two ABIs in C program. --- exts/libudev/tests/test_libudev_device_leak.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/exts/libudev/tests/test_libudev_device_leak.c b/exts/libudev/tests/test_libudev_device_leak.c index 920fef63..fbeb4dd3 100644 --- a/exts/libudev/tests/test_libudev_device_leak.c +++ b/exts/libudev/tests/test_libudev_device_leak.c @@ -35,13 +35,17 @@ void main() struct udev_list_entry *list_entry; struct udev_enumerate *e = udev_enumerate_new(NULL); udev_enumerate_add_match_subsystem(e, "block"); - udev_enumerate_add_match_property(e, "ID_TYPE", "disk"); + udev_enumerate_add_match_property(e, "MAJOR", "8"); udev_enumerate_add_match_is_initialized(e); + struct udev_device *sda = udev_device_new_from_device_id(NULL, "b8:0"); + udev_enumerate_add_match_parent(e, sda); + udev_enumerate_add_match_tag(e, "devmaster"); udev_enumerate_scan_devices(e); udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(e)) { printf("block syspath: '%s'\n", udev_list_entry_get_name(list_entry)); } udev_enumerate_unref(e); + udev_device_unref(sda); } } -- Gitee From a14fb5e7681579ec479c48f7aa243218074f0892 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:09:33 +0800 Subject: [PATCH 27/48] feature(device): support generating device object from environment variables --- libs/device/src/device.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs index a5f55ae0..acff9f39 100644 --- a/libs/device/src/device.rs +++ b/libs/device/src/device.rs @@ -1708,6 +1708,27 @@ impl Device { Result::Ok(device) } + /// generate device object based on the environment properties + pub fn from_environment() -> Result { + let device = Device::new(); + let mut major = String::new(); + let mut minor = String::new(); + for (key, value) in std::env::vars() { + match key.as_str() { + "MINOR" => minor = value.to_string(), + "MAJOR" => major = value.to_string(), + _ => device.amend_key_value(&key, &value)?, + } + } + + if !major.is_empty() { + device.set_devnum(&major, &minor)?; + } + + device.update_properties_bufs()?; + device.verify() + } + /// set the syspath of Device /// constraint: path should start with /sys pub fn set_syspath(&self, path: &str, verify: bool) -> Result<(), Error> { @@ -3928,4 +3949,21 @@ V:100 nomatch_parent.insert("/sys/devices/virtual/net/lo".to_string()); assert!(!dev.match_parent(&HashSet::new(), &nomatch_parent)); } + + #[test] + fn test_from_environment() { + /* When generating device object from nulstr or environment properties, + * the following four properties are required: + * + * SUBSYSTEM, DEVPATH, SEQNUM, ACTION + */ + std::env::set_var("SUBSYSTEM", "net"); + let _ = Device::from_environment().unwrap_err(); + std::env::set_var("DEVPATH", "/devices/virtual/net/lo"); + let _ = Device::from_environment().unwrap_err(); + std::env::set_var("SEQNUM", "100"); + let _ = Device::from_environment().unwrap_err(); + std::env::set_var("ACTION", "add"); + let _ = Device::from_environment().unwrap(); + } } -- Gitee From 23d5ec8e42385163a13bdabdbd03fc7112ae0075 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:31:10 +0800 Subject: [PATCH 28/48] feature(libudev): support udev_device_new_from_environment --- exts/libudev/src/libudev_device.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 5b331b54..6907a73a 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -171,6 +171,20 @@ pub extern "C" fn udev_device_new_from_syspath( Rc::into_raw(Rc::new(udev_device::new(udev, device))) as *mut udev_device } +#[no_mangle] +/// udev_device_new_from_environment +pub fn udev_device_new_from_environment(udev: *mut udev) -> *mut udev_device { + let device = match Device::from_environment() { + Ok(d) => Rc::new(d), + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + return std::ptr::null_mut(); + } + }; + + Rc::into_raw(Rc::new(udev_device::new(udev, device))) as *mut _ +} + #[no_mangle] /// udev_device_get_syspath pub extern "C" fn udev_device_get_syspath( -- Gitee From aa4c9f2788228869a8aecd6d0fb3361611d3e7a8 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:39:05 +0800 Subject: [PATCH 29/48] refactor(libudev): add visibility inside crate for fields of udev_list and udev_list_entry --- exts/libudev/src/libudev_list.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/exts/libudev/src/libudev_list.rs b/exts/libudev/src/libudev_list.rs index 4542cce5..043bdd20 100644 --- a/exts/libudev/src/libudev_list.rs +++ b/exts/libudev/src/libudev_list.rs @@ -29,21 +29,21 @@ use std::{ #[derive(Debug, Clone, RefUnref)] /// udev_list_entry pub struct udev_list_entry { - list: Weak, - name: CString, - value: CString, + pub(crate) list: Weak, + pub(crate) name: CString, + pub(crate) value: CString, } #[repr(C)] #[derive(Debug, Clone)] /// udev_list_entry pub struct udev_list { - unique_entries: RefCell>>, - entries: RefCell>>, - idx: RefCell, + pub(crate) unique_entries: RefCell>>, + pub(crate) entries: RefCell>>, + pub(crate) idx: RefCell, - unique: bool, - up_to_date: RefCell, + pub(crate) unique: bool, + pub(crate) up_to_date: RefCell, } impl udev_list { -- Gitee From c90c042da42e7ef1e94931d9c0af66b88f3be4a6 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:40:34 +0800 Subject: [PATCH 30/48] feature(libudev): support udev_device_get_properties_list_entry Support udev_device_get_properties_list_entry to iterate over device properties. Also refactor udev_device struct and udev_device_get_property_value method to use udev_list to contain properties. --- exts/libudev/src/libudev_device.rs | 57 ++++++++++++++++++------------ 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 6907a73a..a21d855d 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -17,7 +17,6 @@ #![allow(clippy::not_unsafe_ptr_arg_deref)] use device::Device; -use std::collections::HashMap; use std::ffi::{CStr, CString}; use std::mem; use std::os::linux::raw::dev_t; @@ -56,7 +55,8 @@ pub struct udev_device { pub(crate) sysname: CString, pub(crate) subsystem: CString, - pub(crate) properties: HashMap, + pub(crate) properties: Rc, + pub(crate) properties_read: bool, pub(crate) devlinks: Rc, pub(crate) devlinks_read: bool, @@ -85,7 +85,8 @@ impl udev_device { driver: CString::default(), sysname: CString::default(), subsystem: CString::default(), - properties: HashMap::default(), + properties: Rc::new(udev_list::new(true)), + properties_read: false, devlinks: Rc::new(udev_list::new(true)), devlinks_read: false, parent: std::ptr::null_mut(), @@ -472,34 +473,46 @@ pub extern "C" fn udev_device_get_property_value( udev_device: *mut udev_device, key: *const ::std::os::raw::c_char, ) -> *const ::std::os::raw::c_char { - let key = unsafe { CStr::from_ptr(key) }.to_str().unwrap_or_default(); + let key = unsafe { CStr::from_ptr(key) }; let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; - if udev_device_mut - .properties - .contains_key(&CString::new(key).unwrap()) - { - return udev_device_mut - .properties - .get(&CString::new(key).unwrap()) - .unwrap() - .as_ptr(); + if !udev_device_mut.properties_read { + for (k, v) in &udev_device_mut.device.property_iter() { + let key = CString::new(k.as_str()).unwrap(); + let value = CString::new(v.as_str()).unwrap(); + udev_device_mut.properties.add_entry(key, value); + } + udev_device_mut.properties_read = true; } - match udev_device_mut.device.get_property_value(key) { - Ok(v) => { - let key_c = CString::new(key).unwrap(); - let value_c = CString::new(v).unwrap(); - udev_device_mut.properties.insert(key_c.clone(), value_c); - udev_device_mut.properties.get(&key_c).unwrap().as_ptr() - } - Err(e) => { - errno::set_errno(errno::Errno(e.get_errno() as i32)); + match udev_device_mut.properties.unique_entries.borrow().get(key) { + Some(v) => v.value.as_ptr(), + None => { + errno::set_errno(errno::Errno(libc::ENODATA as i32)); std::ptr::null() } } } +#[no_mangle] +/// udev_device_get_properties_list_entry +pub extern "C" fn udev_device_get_properties_list_entry( + udev_device: *mut udev_device, +) -> *mut udev_list_entry { + let d: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + if !d.properties_read { + for (k, v) in &d.device.property_iter() { + let key = CString::new(k.as_str()).unwrap(); + let value = CString::new(v.as_str()).unwrap(); + d.properties.add_entry(key, value); + } + d.properties_read = true; + } + + d.properties.get_entry() +} + fn device_new_from_parent(child: *mut udev_device) -> *mut udev_device { let ud: &mut udev_device = unsafe { mem::transmute(&mut *child) }; -- Gitee From afcb1e0365697593c3b1618d7763e0ce7a677044 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:42:32 +0800 Subject: [PATCH 31/48] test(libudev): add C example to use udev_device_new_from_environment --- exts/libudev/tests/test_libudev_device_new.c | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 exts/libudev/tests/test_libudev_device_new.c diff --git a/exts/libudev/tests/test_libudev_device_new.c b/exts/libudev/tests/test_libudev_device_new.c new file mode 100644 index 00000000..0b1f8300 --- /dev/null +++ b/exts/libudev/tests/test_libudev_device_new.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include + +void dump(struct udev_device *d) +{ + struct udev_list_entry *list_entry; + const char *s = udev_device_get_syspath(d); + + udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(d)) + { + printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); + } +} + +void main() +{ + /* Export environment variables before running this example: + * + * export SUBSYSTEM=net DEVPATH=/devices/virtual/net/lo SEQNUM=100 ACTION=add + * + * If the above environment variables are not exported, udev_device_new_from_environment + * will fail. + */ + struct udev_device *lo = udev_device_new_from_environment(NULL); + if (lo == NULL) + { + printf("udev_device_new_from_environment failed\n"); + } + else + { + dump(lo); + lo = udev_device_unref(lo); + } +} -- Gitee From 7f3d608c3238399f80f3f784290554d6599ce8f8 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:53:02 +0800 Subject: [PATCH 32/48] typo(libudev): correct typo in C example program --- exts/libudev/tests/test_libudev_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/libudev/tests/test_libudev_queue.c b/exts/libudev/tests/test_libudev_queue.c index 9ce3c7f4..83417725 100644 --- a/exts/libudev/tests/test_libudev_queue.c +++ b/exts/libudev/tests/test_libudev_queue.c @@ -16,7 +16,7 @@ #include -/* Run this example, and it will check wether +/* Run this example, and it will check whether * devmaster is running if the libudev is * preloaded with that from devmaster. * -- Gitee From 8f7a2fa77386a1c491ce3a2db539a1a7b2073520 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 21:54:21 +0800 Subject: [PATCH 33/48] fix(libudev): add document for public API Add document for public API to avoid clippy failure --- exts/libudev/src/libudev_enumerate.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index cf7121c0..693a7249 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -212,6 +212,7 @@ pub extern "C" fn udev_enumerate_add_match_tag( } #[no_mangle] +/// udev_enumerate_add_match_parent pub extern "C" fn udev_enumerate_add_match_parent( udev_enumerate: *mut udev_enumerate, parent: *mut udev_device, -- Gitee From 0aab533b8997ee1465bff2939e807a5f668de41f Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 22:04:40 +0800 Subject: [PATCH 34/48] fix(libudev): fix fmt clippy --- exts/libudev/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index 345c555f..cd6f7f22 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -19,11 +19,11 @@ pub mod libudev; pub mod libudev_device; /// libudev_enumerate pub mod libudev_enumerate; +/// libudev_hwdb +pub mod libudev_hwdb; /// libudev_list pub mod libudev_list; /// libudev_monitor pub mod libudev_monitor; /// libudev_queue pub mod libudev_queue; -/// libudev_hwdb -pub mod libudev_hwdb; -- Gitee From 50f353c9107f3f3123460bbb27bf5f30045f350c Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 16 Dec 2023 22:05:51 +0800 Subject: [PATCH 35/48] typo(libudev): add license for C example programs --- exts/libudev/tests/test_libudev_device_leak.c | 12 ++++++++++++ exts/libudev/tests/test_libudev_device_new.c | 12 ++++++++++++ exts/libudev/tests/test_libudev_device_thread.c | 12 +++++++++++- exts/libudev/tests/test_libudev_monitor.c | 12 ++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/exts/libudev/tests/test_libudev_device_leak.c b/exts/libudev/tests/test_libudev_device_leak.c index fbeb4dd3..b66a3ac7 100644 --- a/exts/libudev/tests/test_libudev_device_leak.c +++ b/exts/libudev/tests/test_libudev_device_leak.c @@ -1,3 +1,15 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + #include #include #include diff --git a/exts/libudev/tests/test_libudev_device_new.c b/exts/libudev/tests/test_libudev_device_new.c index 0b1f8300..bf8e88d6 100644 --- a/exts/libudev/tests/test_libudev_device_new.c +++ b/exts/libudev/tests/test_libudev_device_new.c @@ -1,3 +1,15 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + #include #include #include diff --git a/exts/libudev/tests/test_libudev_device_thread.c b/exts/libudev/tests/test_libudev_device_thread.c index 044e6eb4..e3afc0ab 100644 --- a/exts/libudev/tests/test_libudev_device_thread.c +++ b/exts/libudev/tests/test_libudev_device_thread.c @@ -1,4 +1,14 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. #include #include diff --git a/exts/libudev/tests/test_libudev_monitor.c b/exts/libudev/tests/test_libudev_monitor.c index 9f183cc9..4a3acef7 100644 --- a/exts/libudev/tests/test_libudev_monitor.c +++ b/exts/libudev/tests/test_libudev_monitor.c @@ -1,3 +1,15 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + #include #include #include -- Gitee From 19657108811009034d97926ceae31de6789c6e27 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sun, 17 Dec 2023 01:34:07 +0800 Subject: [PATCH 36/48] fix(libudev): fix cargo fmt --- exts/libudev/src/libudev.rs | 1 - exts/libudev/src/libudev_device.rs | 1 - exts/libudev/src/libudev_enumerate.rs | 1 - exts/libudev/src/libudev_hwdb.rs | 1 - exts/libudev/src/libudev_list.rs | 1 - exts/libudev/src/libudev_monitor.rs | 1 - exts/libudev/src/libudev_queue.rs | 1 - 7 files changed, 7 deletions(-) diff --git a/exts/libudev/src/libudev.rs b/exts/libudev/src/libudev.rs index 71343f6e..33625b69 100644 --- a/exts/libudev/src/libudev.rs +++ b/exts/libudev/src/libudev.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index a21d855d..79deb3b4 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 693a7249..a8d93912 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] diff --git a/exts/libudev/src/libudev_hwdb.rs b/exts/libudev/src/libudev_hwdb.rs index 6bc0b2bf..c363878a 100644 --- a/exts/libudev/src/libudev_hwdb.rs +++ b/exts/libudev/src/libudev_hwdb.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] diff --git a/exts/libudev/src/libudev_list.rs b/exts/libudev/src/libudev_list.rs index 043bdd20..171343f3 100644 --- a/exts/libudev/src/libudev_list.rs +++ b/exts/libudev/src/libudev_list.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] diff --git a/exts/libudev/src/libudev_monitor.rs b/exts/libudev/src/libudev_monitor.rs index f53e77dc..45e61610 100644 --- a/exts/libudev/src/libudev_monitor.rs +++ b/exts/libudev/src/libudev_monitor.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] diff --git a/exts/libudev/src/libudev_queue.rs b/exts/libudev/src/libudev_queue.rs index 2c7181e0..7bfb0a05 100644 --- a/exts/libudev/src/libudev_queue.rs +++ b/exts/libudev/src/libudev_queue.rs @@ -9,7 +9,6 @@ // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. - #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(non_snake_case)] -- Gitee From 7899fbafec20d2fca9a515552abdb5cb1331d66e Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Thu, 21 Dec 2023 05:55:11 +0800 Subject: [PATCH 37/48] feature(libudev): append suffix of version to be compatible with libudev The version information might be used by applications, such as NetworkManager. --- exts/libudev/build.rs | 118 +++++++++++++++++++++++ exts/libudev/libudev.sym | 133 ++++++++++++++++++++++++++ exts/libudev/src/libudev.rs | 2 + exts/libudev/src/libudev_device.rs | 98 ++++++++++++------- exts/libudev/src/libudev_enumerate.rs | 28 ++++-- exts/libudev/src/libudev_hwdb.rs | 15 +-- exts/libudev/src/libudev_list.rs | 5 + exts/libudev/src/libudev_monitor.rs | 9 ++ exts/libudev/src/libudev_queue.rs | 3 + exts/libudev_macro/src/lib.rs | 23 ++++- 10 files changed, 380 insertions(+), 54 deletions(-) create mode 100644 exts/libudev/build.rs create mode 100644 exts/libudev/libudev.sym diff --git a/exts/libudev/build.rs b/exts/libudev/build.rs new file mode 100644 index 00000000..ae7e120b --- /dev/null +++ b/exts/libudev/build.rs @@ -0,0 +1,118 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +//! libudev link options +//! + +fn main() { + let symbols = [ + "udev_device_get_action", + "udev_device_get_devlinks_list_entry", + "udev_device_get_devnode", + "udev_device_get_devnum", + "udev_device_get_devpath", + "udev_device_get_devtype", + "udev_device_get_driver", + "udev_device_get_is_initialized", + "udev_device_get_parent", + "udev_device_get_parent_with_subsystem_devtype", + "udev_device_get_properties_list_entry", + "udev_device_get_property_value", + "udev_device_get_seqnum", + "udev_device_get_subsystem", + // "udev_device_get_sysattr_list_entry", + // "udev_device_get_sysattr_value", + "udev_device_get_sysname", + // "udev_device_get_sysnum", + "udev_device_get_syspath", + // "udev_device_get_tags_list_entry", + // "udev_device_get_udev", + // "udev_device_get_usec_since_initialized", + "udev_device_has_tag", + // "udev_device_new_from_devnum", + "udev_device_new_from_environment", + "udev_device_new_from_subsystem_sysname", + "udev_device_new_from_syspath", + "udev_device_ref", + "udev_device_unref", + "udev_enumerate_add_match_is_initialized", + "udev_enumerate_add_match_parent", + "udev_enumerate_add_match_property", + "udev_enumerate_add_match_subsystem", + // "udev_enumerate_add_match_sysattr", + // "udev_enumerate_add_match_sysname", + "udev_enumerate_add_match_tag", + // "udev_enumerate_add_nomatch_subsystem", + // "udev_enumerate_add_nomatch_sysattr", + // "udev_enumerate_add_syspath", + "udev_enumerate_get_list_entry", + "udev_enumerate_get_udev", + "udev_enumerate_new", + "udev_enumerate_ref", + "udev_enumerate_scan_devices", + // "udev_enumerate_scan_subsystems", + "udev_enumerate_unref", + // "udev_get_log_priority", + // "udev_get_userdata", + "udev_list_entry_get_by_name", + "udev_list_entry_get_name", + "udev_list_entry_get_next", + "udev_list_entry_get_value", + "udev_monitor_enable_receiving", + "udev_monitor_filter_add_match_subsystem_devtype", + "udev_monitor_filter_add_match_tag", + // "udev_monitor_filter_remove", + // "udev_monitor_filter_update", + "udev_monitor_get_fd", + "udev_monitor_get_udev", + "udev_monitor_new_from_netlink", + "udev_monitor_receive_device", + "udev_monitor_ref", + "udev_monitor_set_receive_buffer_size", + "udev_monitor_unref", + "udev_new", + // "udev_queue_get_kernel_seqnum", + // "udev_queue_get_queue_is_empty", + // "udev_queue_get_queued_list_entry", + // "udev_queue_get_seqnum_is_finished", + // "udev_queue_get_seqnum_sequence_is_finished", + // "udev_queue_get_udev", + "udev_queue_get_udev_is_active", + // "udev_queue_get_udev_seqnum", + "udev_queue_new", + "udev_queue_ref", + "udev_queue_unref", + "udev_ref", + // "udev_set_log_fn", + // "udev_set_log_priority", + // "udev_set_userdata", + "udev_unref", + // "udev_util_encode_string", + "udev_device_new_from_device_id", + "udev_hwdb_new", + "udev_hwdb_ref", + "udev_hwdb_unref", + "udev_hwdb_get_properties_list_entry", + // "udev_device_set_sysattr_value", + // "udev_queue_flush", + // "udev_queue_get_fd", + "udev_device_has_current_tag", + // "udev_device_get_current_tags_list_entry", + ]; + + println!("cargo:rustc-cdylib-link-arg=-fuse-ld=lld"); + println!("cargo:rustc-link-arg=-Wl,--version-script=/root/sysmaster/exts/libudev/libudev.sym"); + + for s in symbols { + println!("cargo:rustc-link-arg=-Wl,--defsym={}={}_impl", s, s); + } +} diff --git a/exts/libudev/libudev.sym b/exts/libudev/libudev.sym new file mode 100644 index 00000000..8ae7a224 --- /dev/null +++ b/exts/libudev/libudev.sym @@ -0,0 +1,133 @@ +/*** +Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. + +sysMaster is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan +PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. + +Compatible with systemd libudev ABI version suffix. +***/ + +LIBUDEV_183 { +global: + udev_device_get_action; + udev_device_get_devlinks_list_entry; + udev_device_get_devnode; + udev_device_get_devnum; + udev_device_get_devpath; + udev_device_get_devtype; + udev_device_get_driver; + udev_device_get_is_initialized; + udev_device_get_parent; + udev_device_get_parent_with_subsystem_devtype; + udev_device_get_properties_list_entry; + udev_device_get_property_value; + udev_device_get_seqnum; + udev_device_get_subsystem; + udev_device_get_sysattr_list_entry; + udev_device_get_sysattr_value; + udev_device_get_sysname; + udev_device_get_sysnum; + udev_device_get_syspath; + udev_device_get_tags_list_entry; + udev_device_get_udev; + udev_device_get_usec_since_initialized; + udev_device_has_tag; + udev_device_new_from_devnum; + udev_device_new_from_environment; + udev_device_new_from_subsystem_sysname; + udev_device_new_from_syspath; + udev_device_ref; + udev_device_unref; + udev_enumerate_add_match_is_initialized; + udev_enumerate_add_match_parent; + udev_enumerate_add_match_property; + udev_enumerate_add_match_subsystem; + udev_enumerate_add_match_sysattr; + udev_enumerate_add_match_sysname; + udev_enumerate_add_match_tag; + udev_enumerate_add_nomatch_subsystem; + udev_enumerate_add_nomatch_sysattr; + udev_enumerate_add_syspath; + udev_enumerate_get_list_entry; + udev_enumerate_get_udev; + udev_enumerate_new; + udev_enumerate_ref; + udev_enumerate_scan_devices; + udev_enumerate_scan_subsystems; + udev_enumerate_unref; + udev_get_log_priority; + udev_get_userdata; + udev_list_entry_get_by_name; + udev_list_entry_get_name; + udev_list_entry_get_next; + udev_list_entry_get_value; + udev_monitor_enable_receiving; + udev_monitor_filter_add_match_subsystem_devtype; + udev_monitor_filter_add_match_tag; + udev_monitor_filter_remove; + udev_monitor_filter_update; + udev_monitor_get_fd; + udev_monitor_get_udev; + udev_monitor_new_from_netlink; + udev_monitor_receive_device; + udev_monitor_ref; + udev_monitor_set_receive_buffer_size; + udev_monitor_unref; + udev_new; + udev_queue_get_kernel_seqnum; + udev_queue_get_queue_is_empty; + udev_queue_get_queued_list_entry; + udev_queue_get_seqnum_is_finished; + udev_queue_get_seqnum_sequence_is_finished; + udev_queue_get_udev; + udev_queue_get_udev_is_active; + udev_queue_get_udev_seqnum; + udev_queue_new; + udev_queue_ref; + udev_queue_unref; + udev_ref; + udev_set_log_fn; + udev_set_log_priority; + udev_set_userdata; + udev_unref; + udev_util_encode_string; +local: + *; +}; + +LIBUDEV_189 { +global: + udev_device_new_from_device_id; +} LIBUDEV_183; + +LIBUDEV_196 { +global: + udev_hwdb_new; + udev_hwdb_ref; + udev_hwdb_unref; + udev_hwdb_get_properties_list_entry; +} LIBUDEV_189; + +LIBUDEV_199 { +global: + udev_device_set_sysattr_value; +} LIBUDEV_196; + +LIBUDEV_215 { +global: + udev_queue_flush; + udev_queue_get_fd; +} LIBUDEV_199; + +LIBUDEV_247 { +global: + udev_device_has_current_tag; + udev_device_get_current_tags_list_entry; +} LIBUDEV_215; diff --git a/exts/libudev/src/libudev.rs b/exts/libudev/src/libudev.rs index 33625b69..a5ad59a6 100644 --- a/exts/libudev/src/libudev.rs +++ b/exts/libudev/src/libudev.rs @@ -15,6 +15,7 @@ #![allow(deprecated)] #![allow(clippy::not_unsafe_ptr_arg_deref)] +use libudev_macro::append_impl; use libudev_macro::RefUnref; use std::ffi::c_void; use std::rc::Rc; @@ -30,6 +31,7 @@ pub struct udev { } #[no_mangle] +#[append_impl] /// udev_new pub extern "C" fn udev_new() -> *mut udev { Rc::into_raw(Rc::new(udev { diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index 79deb3b4..f9c8255a 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -23,6 +23,7 @@ use std::rc::Rc; use crate::libudev::*; use crate::libudev_list::{udev_list, udev_list_entry}; +use libudev_macro::append_impl; use libudev_macro::RefUnref; const ACTION_CNT: usize = 8; @@ -94,6 +95,7 @@ impl udev_device { } #[no_mangle] +#[append_impl] /// udev_device_new_from_device_id pub extern "C" fn udev_device_new_from_device_id( udev: *mut udev, @@ -115,6 +117,7 @@ pub extern "C" fn udev_device_new_from_device_id( } #[no_mangle] +#[append_impl] /// udev_device_new_from_devnum pub extern "C" fn udev_device_new_from_devnum( udev: *mut udev, @@ -130,6 +133,7 @@ pub extern "C" fn udev_device_new_from_devnum( } #[no_mangle] +#[append_impl] /// udev_device_new_from_subsystem_sysname pub extern "C" fn udev_device_new_from_subsystem_sysname( udev: *mut udev, @@ -153,6 +157,7 @@ pub extern "C" fn udev_device_new_from_subsystem_sysname( } #[no_mangle] +#[append_impl] /// udev_device_new_from_syspath pub extern "C" fn udev_device_new_from_syspath( udev: *mut udev, @@ -172,6 +177,7 @@ pub extern "C" fn udev_device_new_from_syspath( } #[no_mangle] +#[append_impl] /// udev_device_new_from_environment pub fn udev_device_new_from_environment(udev: *mut udev) -> *mut udev_device { let device = match Device::from_environment() { @@ -186,6 +192,7 @@ pub fn udev_device_new_from_environment(udev: *mut udev) -> *mut udev_device { } #[no_mangle] +#[append_impl] /// udev_device_get_syspath pub extern "C" fn udev_device_get_syspath( udev_device: *mut udev_device, @@ -220,6 +227,7 @@ pub extern "C" fn udev_device_get_syspath( } #[no_mangle] +#[append_impl] /// udev_device_has_tag pub extern "C" fn udev_device_has_tag( udev_device: *mut udev_device, @@ -236,6 +244,7 @@ pub extern "C" fn udev_device_has_tag( } #[no_mangle] +#[append_impl] /// udev_device_has_current_tag pub extern "C" fn udev_device_has_current_tag( udev_device: *mut udev_device, @@ -252,6 +261,7 @@ pub extern "C" fn udev_device_has_current_tag( } #[no_mangle] +#[append_impl] /// udev_device_get_action pub extern "C" fn udev_device_get_action( udev_device: *mut udev_device, @@ -267,6 +277,7 @@ pub extern "C" fn udev_device_get_action( } #[no_mangle] +#[append_impl] /// udev_device_get_devnode pub extern "C" fn udev_device_get_devnode( udev_device: *mut udev_device, @@ -292,6 +303,7 @@ pub extern "C" fn udev_device_get_devnode( } #[no_mangle] +#[append_impl] /// udev_device_get_devnum pub extern "C" fn udev_device_get_devnum(udev_device: *mut udev_device) -> dev_t { let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; @@ -309,6 +321,7 @@ pub extern "C" fn udev_device_get_devnum(udev_device: *mut udev_device) -> dev_t } #[no_mangle] +#[append_impl] /// udev_device_get_devpath pub extern "C" fn udev_device_get_devpath( udev_device: *mut udev_device, @@ -338,6 +351,7 @@ pub extern "C" fn udev_device_get_devpath( } #[no_mangle] +#[append_impl] /// udev_device_get_devtype pub extern "C" fn udev_device_get_devtype( udev_device: *mut udev_device, @@ -370,6 +384,7 @@ pub extern "C" fn udev_device_get_devtype( } #[no_mangle] +#[append_impl] /// udev_device_get_driver pub extern "C" fn udev_device_get_driver( udev_device: *mut udev_device, @@ -399,6 +414,7 @@ pub extern "C" fn udev_device_get_driver( } #[no_mangle] +#[append_impl] /// udev_device_get_sysname pub extern "C" fn udev_device_get_sysname( udev_device: *mut udev_device, @@ -428,6 +444,7 @@ pub extern "C" fn udev_device_get_sysname( } #[no_mangle] +#[append_impl] /// udev_device_get_subsystem pub extern "C" fn udev_device_get_subsystem( udev_device: *mut udev_device, @@ -457,6 +474,7 @@ pub extern "C" fn udev_device_get_subsystem( } #[no_mangle] +#[append_impl] /// udev_device_get_seqnum pub extern "C" fn udev_device_get_seqnum( udev_device: *mut udev_device, @@ -467,6 +485,7 @@ pub extern "C" fn udev_device_get_seqnum( } #[no_mangle] +#[append_impl] /// udev_device_get_property_value pub extern "C" fn udev_device_get_property_value( udev_device: *mut udev_device, @@ -494,6 +513,7 @@ pub extern "C" fn udev_device_get_property_value( } #[no_mangle] +#[append_impl] /// udev_device_get_properties_list_entry pub extern "C" fn udev_device_get_properties_list_entry( udev_device: *mut udev_device, @@ -525,6 +545,7 @@ fn device_new_from_parent(child: *mut udev_device) -> *mut udev_device { } #[no_mangle] +#[append_impl] /// udev_device_get_parent /// /// return the reference of the innter parent field, thus don't drop it @@ -539,6 +560,7 @@ pub extern "C" fn udev_device_get_parent(udev_device: *mut udev_device) -> *mut } #[no_mangle] +#[append_impl] /// udev_device_get_parent_with_subsystem_devtype pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( udev_device: *mut udev_device, @@ -563,7 +585,7 @@ pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( #[allow(clippy::never_loop)] loop { - let udev_device = udev_device_get_parent(udev_device); + let udev_device = udev_device_get_parent_impl(udev_device); if udev_device.is_null() { break; @@ -581,6 +603,7 @@ pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( } #[no_mangle] +#[append_impl] /// udev_device_get_is_initialized pub extern "C" fn udev_device_get_is_initialized( udev_device: *mut udev_device, @@ -603,6 +626,7 @@ pub extern "C" fn udev_device_get_is_initialized( } #[no_mangle] +#[append_impl] /// udev_device_get_devlinks_list_entry pub extern "C" fn udev_device_get_devlinks_list_entry( udev_device: *mut udev_device, @@ -627,7 +651,7 @@ pub extern "C" fn udev_device_get_devlinks_list_entry( mod test { use std::intrinsics::transmute; - use crate::libudev_list::{udev_list_entry_get_name, udev_list_entry_get_next}; + use crate::libudev_list::{udev_list_entry_get_name_impl, udev_list_entry_get_next_impl}; use super::*; use device::device_enumerator::*; @@ -645,13 +669,13 @@ mod test { }; let raw_udev_device = - udev_device_new_from_devnum(std::ptr::null_mut(), t as ::std::os::raw::c_char, devnum); + udev_device_new_from_devnum_impl(std::ptr::null_mut(), t as ::std::os::raw::c_char, devnum); - let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(raw_udev_device)) }; + let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath_impl(raw_udev_device)) }; assert_eq!(syspath.to_str().unwrap(), &device.get_syspath().unwrap()); - udev_device_unref(raw_udev_device); + udev_device_unref_impl(raw_udev_device); Ok(()) } @@ -669,17 +693,17 @@ mod test { let c_subsystem = CString::new(subsystem).unwrap(); let c_name = CString::new(name).unwrap(); - let raw_udev_device = udev_device_new_from_subsystem_sysname( + let raw_udev_device = udev_device_new_from_subsystem_sysname_impl( std::ptr::null_mut(), c_subsystem.as_ptr(), c_name.as_ptr(), ); - let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(raw_udev_device)) }; + let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath_impl(raw_udev_device)) }; assert_eq!(syspath.to_str().unwrap(), &device.get_syspath().unwrap()); - udev_device_unref(raw_udev_device); + udev_device_unref_impl(raw_udev_device); Ok(()) } @@ -687,15 +711,15 @@ mod test { fn test_udev_device_new_from_device_id(device: RD) -> Result { let id = device.get_device_id().unwrap(); let c_id = CString::new(id).unwrap(); - let udev_device = udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()); - let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(udev_device)) }; + let udev_device = udev_device_new_from_device_id_impl(std::ptr::null_mut(), c_id.as_ptr()); + let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath_impl(udev_device)) }; assert_eq!( device.get_syspath().unwrap(), syspath.to_str().unwrap().to_string() ); - udev_device_unref(udev_device); + udev_device_unref_impl(udev_device); Ok(()) } @@ -703,12 +727,12 @@ mod test { fn test_udev_device_new_from_syspath(device: RD) -> Result { let syspath = device.get_syspath().unwrap(); let c_syspath = CString::new(syspath).unwrap(); - let udev_device = udev_device_new_from_syspath(std::ptr::null_mut(), c_syspath.as_ptr()); - let ret_syspath = unsafe { CStr::from_ptr(udev_device_get_syspath(udev_device)) }; + let udev_device = udev_device_new_from_syspath_impl(std::ptr::null_mut(), c_syspath.as_ptr()); + let ret_syspath = unsafe { CStr::from_ptr(udev_device_get_syspath_impl(udev_device)) }; assert_eq!(c_syspath.to_str().unwrap(), ret_syspath.to_str().unwrap()); - udev_device_unref(udev_device); + udev_device_unref_impl(udev_device); Ok(()) } @@ -716,7 +740,7 @@ mod test { fn from_rd(device: RD) -> *mut udev_device { let id = device.get_device_id().unwrap(); let c_id = CString::new(id).unwrap(); - udev_device_new_from_device_id(std::ptr::null_mut(), c_id.as_ptr()) + udev_device_new_from_device_id_impl(std::ptr::null_mut(), c_id.as_ptr()) } fn test_udev_device_has_tag(device: RD) -> Result { @@ -727,20 +751,20 @@ mod test { let udev_device = from_rd(device.clone()); assert!( - udev_device_has_tag( + udev_device_has_tag_impl( udev_device, "test_udev_device_has_tag\0".as_ptr() as *const i8 ) > 0 ); assert!( - udev_device_has_current_tag( + udev_device_has_current_tag_impl( udev_device, "test_udev_device_has_tag\0".as_ptr() as *const i8 ) > 0 ); - udev_device_unref(udev_device); + udev_device_unref_impl(udev_device); device .all_tags @@ -762,13 +786,13 @@ mod test { .set_action_from_string("change") .unwrap(); - let ptr = udev_device_get_action(udev_device); + let ptr = udev_device_get_action_impl(udev_device); let action = unsafe { CStr::from_ptr(ptr) }; assert_eq!(action.to_str().unwrap(), "change"); - udev_device_unref(udev_device); + udev_device_unref_impl(udev_device); Ok(()) } @@ -778,11 +802,11 @@ mod test { let devnode = dev.get_devname()?; - let ptr = udev_device_get_devnode(udev_device); + let ptr = udev_device_get_devnode_impl(udev_device); assert_eq!(unsafe { CStr::from_ptr(ptr) }.to_str().unwrap(), &devnode); - udev_device_unref(udev_device); + udev_device_unref_impl(udev_device); Ok(()) } @@ -792,7 +816,7 @@ mod test { let devnum = dev.get_devnum()?; - assert_eq!(udev_device_get_devnum(udev_device), devnum); + assert_eq!(udev_device_get_devnum_impl(udev_device), devnum); Ok(()) } @@ -803,7 +827,7 @@ mod test { let devpath = dev.get_devpath()?; assert_eq!( - unsafe { CStr::from_ptr(udev_device_get_devpath(udev_device)) } + unsafe { CStr::from_ptr(udev_device_get_devpath_impl(udev_device)) } .to_str() .unwrap(), &devpath @@ -818,7 +842,7 @@ mod test { let devtype = dev.get_devtype()?; assert_eq!( - unsafe { CStr::from_ptr(udev_device_get_devtype(ud)) } + unsafe { CStr::from_ptr(udev_device_get_devtype_impl(ud)) } .to_str() .unwrap(), &devtype @@ -833,7 +857,7 @@ mod test { let driver = dev.get_driver()?; assert_eq!( - unsafe { CStr::from_ptr(udev_device_get_driver(ud)) } + unsafe { CStr::from_ptr(udev_device_get_driver_impl(ud)) } .to_str() .unwrap(), &driver @@ -848,7 +872,7 @@ mod test { let sysname = dev.get_sysname()?; assert_eq!( - unsafe { CStr::from_ptr(udev_device_get_sysname(ud)) } + unsafe { CStr::from_ptr(udev_device_get_sysname_impl(ud)) } .to_str() .unwrap(), &sysname @@ -863,7 +887,7 @@ mod test { let subsystem = dev.get_subsystem()?; assert_eq!( - unsafe { CStr::from_ptr(udev_device_get_subsystem(ud)) } + unsafe { CStr::from_ptr(udev_device_get_subsystem_impl(ud)) } .to_str() .unwrap(), &subsystem @@ -879,7 +903,7 @@ mod test { ud_mut.device.set_seqnum(10000); - assert_eq!(udev_device_get_seqnum(ud), 10000); + assert_eq!(udev_device_get_seqnum_impl(ud), 10000); Ok(()) } @@ -892,7 +916,7 @@ mod test { assert_eq!( unsafe { - CStr::from_ptr(udev_device_get_property_value( + CStr::from_ptr(udev_device_get_property_value_impl( ud, "hello\0".as_ptr() as *const i8, )) @@ -912,14 +936,14 @@ mod test { let ud = from_rd(dev.clone()); - let p = udev_device_get_parent(ud); + let p = udev_device_get_parent_impl(ud); assert!(!p.is_null()); let p_rc = dev.get_parent().unwrap(); assert_eq!( - unsafe { CStr::from_ptr(udev_device_get_syspath(p)) } + unsafe { CStr::from_ptr(udev_device_get_syspath_impl(p)) } .to_str() .unwrap(), &p_rc.get_syspath().unwrap() @@ -937,7 +961,7 @@ mod test { assert_eq!(&p.get_devtype()?, "disk"); let ud = from_rd(dev); - let pud = udev_device_get_parent_with_subsystem_devtype( + let pud = udev_device_get_parent_with_subsystem_devtype_impl( ud, "block\0".as_ptr() as *const i8, "disk\0".as_ptr() as *const i8, @@ -970,7 +994,7 @@ mod test { ud_mut.device.set_is_initialized(); - assert!(udev_device_get_is_initialized(ud) > 0); + assert!(udev_device_get_is_initialized_impl(ud) > 0); Ok(()) } @@ -979,19 +1003,19 @@ mod test { dev.read_db_internal(true)?; let ud = from_rd(dev.clone()); - let mut entry = udev_device_get_devlinks_list_entry(ud); + let mut entry = udev_device_get_devlinks_list_entry_impl(ud); loop { if entry.is_null() { break; } - let link_c = unsafe { CStr::from_ptr(udev_list_entry_get_name(entry)) }; + let link_c = unsafe { CStr::from_ptr(udev_list_entry_get_name_impl(entry)) }; let link = link_c.to_str().unwrap(); assert!(dev.has_devlink(link)); - entry = udev_list_entry_get_next(entry); + entry = udev_list_entry_get_next_impl(entry); } Ok(()) diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index a8d93912..06e657d0 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -24,6 +24,7 @@ use crate::libudev::*; use crate::libudev_device::udev_device; use crate::libudev_list::{udev_list, udev_list_entry}; use device::device_enumerator::*; +use libudev_macro::append_impl; use libudev_macro::RefUnref; #[repr(C)] @@ -46,6 +47,7 @@ impl Drop for udev_enumerate { } #[no_mangle] +#[append_impl] /// udev_enumerate_new pub extern "C" fn udev_enumerate_new(udev: *mut udev) -> *mut udev_enumerate { let mut enumerator = DeviceEnumerator::new(); @@ -63,6 +65,7 @@ pub extern "C" fn udev_enumerate_new(udev: *mut udev) -> *mut udev_enumerate { } #[no_mangle] +#[append_impl] /// udev_enumerate_scan_devices pub extern "C" fn udev_enumerate_scan_devices( udev_enumerate: *mut udev_enumerate, @@ -76,6 +79,7 @@ pub extern "C" fn udev_enumerate_scan_devices( } #[no_mangle] +#[append_impl] /// udev_enumerate_get_list_entry pub extern "C" fn udev_enumerate_get_list_entry( udev_enumerate: *mut udev_enumerate, @@ -110,6 +114,7 @@ pub extern "C" fn udev_enumerate_get_list_entry( } #[no_mangle] +#[append_impl] /// udev_enumerate_add_match_subsystem pub extern "C" fn udev_enumerate_add_match_subsystem( udev_enumerate: *mut udev_enumerate, @@ -137,6 +142,7 @@ pub extern "C" fn udev_enumerate_add_match_subsystem( } #[no_mangle] +#[append_impl] /// udev_enumerate_add_match_property pub extern "C" fn udev_enumerate_add_match_property( udev_enumerate: *mut udev_enumerate, @@ -166,6 +172,7 @@ pub extern "C" fn udev_enumerate_add_match_property( } #[no_mangle] +#[append_impl] /// udev_enumerate_add_match_is_initialized pub fn udev_enumerate_add_match_is_initialized( udev_enumerate: *mut udev_enumerate, @@ -186,6 +193,7 @@ pub fn udev_enumerate_add_match_is_initialized( } #[no_mangle] +#[append_impl] /// udev_enumerate_get_udev pub extern "C" fn udev_enumerate_get_udev(udev_enumerate: *mut udev_enumerate) -> *mut udev { let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; @@ -194,6 +202,7 @@ pub extern "C" fn udev_enumerate_get_udev(udev_enumerate: *mut udev_enumerate) - } #[no_mangle] +#[append_impl] /// udev_enumerate_add_match_tag pub extern "C" fn udev_enumerate_add_match_tag( udev_enumerate: *mut udev_enumerate, @@ -211,6 +220,7 @@ pub extern "C" fn udev_enumerate_add_match_tag( } #[no_mangle] +#[append_impl] /// udev_enumerate_add_match_parent pub extern "C" fn udev_enumerate_add_match_parent( udev_enumerate: *mut udev_enumerate, @@ -233,37 +243,37 @@ pub extern "C" fn udev_enumerate_add_match_parent( mod tests { use device::Device; - use crate::libudev_list::{udev_list_entry_get_name, udev_list_entry_get_next}; + use crate::libudev_list::{udev_list_entry_get_name_impl, udev_list_entry_get_next_impl}; use super::*; #[test] fn test_enumerator() { - let e = udev_enumerate_new(std::ptr::null_mut()); + let e = udev_enumerate_new_impl(std::ptr::null_mut()); assert_eq!( - udev_enumerate_add_match_subsystem(e, "block\0".as_ptr() as *const i8), + udev_enumerate_add_match_subsystem_impl(e, "block\0".as_ptr() as *const i8), 0 ); assert_eq!( - udev_enumerate_add_match_property( + udev_enumerate_add_match_property_impl( e, "ID_TYPE\0".as_ptr() as *const i8, "disk\0".as_ptr() as *const i8, ), 0 ); - assert_eq!(udev_enumerate_add_match_is_initialized(e), 0); - assert_eq!(udev_enumerate_scan_devices(e), 0); + assert_eq!(udev_enumerate_add_match_is_initialized_impl(e), 0); + assert_eq!(udev_enumerate_scan_devices_impl(e), 0); - let mut entry = udev_enumerate_get_list_entry(e); + let mut entry = udev_enumerate_get_list_entry_impl(e); loop { if entry.is_null() { break; } - let syspath = unsafe { CStr::from_ptr(udev_list_entry_get_name(entry)) }; + let syspath = unsafe { CStr::from_ptr(udev_list_entry_get_name_impl(entry)) }; let syspath = syspath.to_str().unwrap(); @@ -271,7 +281,7 @@ mod tests { assert_eq!(&device.get_subsystem().unwrap(), "block"); assert_eq!(&device.get_property_value("ID_TYPE").unwrap(), "disk"); - entry = udev_list_entry_get_next(entry); + entry = udev_list_entry_get_next_impl(entry); } } } diff --git a/exts/libudev/src/libudev_hwdb.rs b/exts/libudev/src/libudev_hwdb.rs index c363878a..56bf330d 100644 --- a/exts/libudev/src/libudev_hwdb.rs +++ b/exts/libudev/src/libudev_hwdb.rs @@ -16,6 +16,7 @@ #![allow(clippy::not_unsafe_ptr_arg_deref)] use hwdb::SdHwdb; +use libudev_macro::append_impl; use libudev_macro::RefUnref; use std::{ cell::RefCell, @@ -38,6 +39,7 @@ pub struct udev_hwdb { } #[no_mangle] +#[append_impl] /// udev_hwdb_new pub extern "C" fn udev_hwdb_new(_udev: *mut udev) -> *mut udev_hwdb { let hwdb = match SdHwdb::new() { @@ -55,6 +57,7 @@ pub extern "C" fn udev_hwdb_new(_udev: *mut udev) -> *mut udev_hwdb { } #[no_mangle] +#[append_impl] /// udev_hwdb_get_properties_list_entry pub extern "C" fn udev_hwdb_get_properties_list_entry( hwdb: *mut udev_hwdb, @@ -92,10 +95,10 @@ mod tests { #[test] fn test_udev_hwdb() { - let hwdb = udev_hwdb_new(std::ptr::null_mut()); + let hwdb = udev_hwdb_new_impl(std::ptr::null_mut()); let mut i = 0; loop { - let mut list = udev_hwdb_get_properties_list_entry( + let mut list = udev_hwdb_get_properties_list_entry_impl( hwdb, "evdev:input:b0003v0458p07081\0".as_ptr() as *const _, 0, @@ -104,18 +107,18 @@ mod tests { if list.is_null() { break; } - let name = udev_list_entry_get_name(list); - let value = udev_list_entry_get_value(list); + let name = udev_list_entry_get_name_impl(list); + let value = udev_list_entry_get_value_impl(list); let name = unsafe { CStr::from_ptr(name) }; let value = unsafe { CStr::from_ptr(value) }; println!("{:?}={:?}", name, value); - list = udev_list_entry_get_next(list); + list = udev_list_entry_get_next_impl(list); } i += 1; if i == 10 { break; } } - udev_hwdb_unref(hwdb); + udev_hwdb_unref_impl(hwdb); } } diff --git a/exts/libudev/src/libudev_list.rs b/exts/libudev/src/libudev_list.rs index 171343f3..6d088e58 100644 --- a/exts/libudev/src/libudev_list.rs +++ b/exts/libudev/src/libudev_list.rs @@ -15,6 +15,7 @@ #![allow(deprecated)] #![allow(clippy::not_unsafe_ptr_arg_deref)] +use libudev_macro::append_impl; use libudev_macro::RefUnref; use std::{ cell::RefCell, @@ -130,6 +131,7 @@ impl udev_list { } #[no_mangle] +#[append_impl] /// udev_list_entry_get_next pub extern "C" fn udev_list_entry_get_next( list_entry: *mut udev_list_entry, @@ -149,6 +151,7 @@ pub extern "C" fn udev_list_entry_get_next( } #[no_mangle] +#[append_impl] /// udev_list_entry_get_by_name pub extern "C" fn udev_list_entry_get_by_name( list_entry: *mut udev_list_entry, @@ -181,6 +184,7 @@ pub extern "C" fn udev_list_entry_get_by_name( } #[no_mangle] +#[append_impl] /// udev_list_entry_get_name pub extern "C" fn udev_list_entry_get_name( list_entry: *mut udev_list_entry, @@ -198,6 +202,7 @@ pub extern "C" fn udev_list_entry_get_name( } #[no_mangle] +#[append_impl] /// udev_list_entry_get_value pub extern "C" fn udev_list_entry_get_value( list_entry: *mut udev_list_entry, diff --git a/exts/libudev/src/libudev_monitor.rs b/exts/libudev/src/libudev_monitor.rs index 45e61610..a00749ff 100644 --- a/exts/libudev/src/libudev_monitor.rs +++ b/exts/libudev/src/libudev_monitor.rs @@ -18,6 +18,7 @@ use crate::libudev::*; use crate::libudev_device::udev_device; use device::device_monitor::*; +use libudev_macro::append_impl; use libudev_macro::RefUnref; use std::cell::RefCell; use std::ffi::CStr; @@ -39,6 +40,7 @@ impl Drop for udev_monitor { } #[no_mangle] +#[append_impl] /// udev_monitor_new_from_netlink pub extern "C" fn udev_monitor_new_from_netlink( udev: *mut udev, @@ -65,6 +67,7 @@ pub extern "C" fn udev_monitor_new_from_netlink( } #[no_mangle] +#[append_impl] /// udev_monitor_enable_receiving pub extern "C" fn udev_monitor_enable_receiving( udev_monitor: *mut udev_monitor, @@ -78,6 +81,7 @@ pub extern "C" fn udev_monitor_enable_receiving( } #[no_mangle] +#[append_impl] /// udev_monitor_filter_add_match_subsystem_devtype pub extern "C" fn udev_monitor_filter_add_match_subsystem_devtype( udev_monitor: *mut udev_monitor, @@ -105,6 +109,7 @@ pub extern "C" fn udev_monitor_filter_add_match_subsystem_devtype( } #[no_mangle] +#[append_impl] /// udev_monitor_filter_add_match_tag pub extern "C" fn udev_monitor_filter_add_match_tag( udev_monitor: *mut udev_monitor, @@ -122,6 +127,7 @@ pub extern "C" fn udev_monitor_filter_add_match_tag( } #[no_mangle] +#[append_impl] /// udev_monitor_get_fd pub extern "C" fn udev_monitor_get_fd(udev_monitor: *mut udev_monitor) -> ::std::os::raw::c_int { let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; @@ -130,6 +136,7 @@ pub extern "C" fn udev_monitor_get_fd(udev_monitor: *mut udev_monitor) -> ::std: } #[no_mangle] +#[append_impl] /// udev_monitor_get_udev pub extern "C" fn udev_monitor_get_udev(udev_monitor: *mut udev_monitor) -> *mut udev { let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; @@ -137,6 +144,7 @@ pub extern "C" fn udev_monitor_get_udev(udev_monitor: *mut udev_monitor) -> *mut } #[no_mangle] +#[append_impl] /// udev_monitor_receive_device pub extern "C" fn udev_monitor_receive_device(udev_monitor: *mut udev_monitor) -> *mut udev_device { let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; @@ -157,6 +165,7 @@ pub extern "C" fn udev_monitor_receive_device(udev_monitor: *mut udev_monitor) - } #[no_mangle] +#[append_impl] /// udev_monitor_set_receive_buffer_size pub extern "C" fn udev_monitor_set_receive_buffer_size( udev_monitor: *mut udev_monitor, diff --git a/exts/libudev/src/libudev_queue.rs b/exts/libudev/src/libudev_queue.rs index 7bfb0a05..9d11ac99 100644 --- a/exts/libudev/src/libudev_queue.rs +++ b/exts/libudev/src/libudev_queue.rs @@ -16,6 +16,7 @@ #![allow(clippy::not_unsafe_ptr_arg_deref)] use crate::libudev::*; +use libudev_macro::append_impl; use libudev_macro::RefUnref; use std::path::Path; use std::rc::Rc; @@ -29,6 +30,7 @@ pub struct udev_queue { } #[no_mangle] +#[append_impl] /// udev_queue_new pub extern "C" fn udev_queue_new(udev: *mut udev) -> *mut udev_queue { Rc::into_raw(Rc::new(udev_queue { @@ -38,6 +40,7 @@ pub extern "C" fn udev_queue_new(udev: *mut udev) -> *mut udev_queue { } #[no_mangle] +#[append_impl] /// udev_queue_get_udev_is_active /// /// This function detects whether devmaster is running rather than udevd. diff --git a/exts/libudev_macro/src/lib.rs b/exts/libudev_macro/src/lib.rs index b129403b..ff1fb681 100644 --- a/exts/libudev_macro/src/lib.rs +++ b/exts/libudev_macro/src/lib.rs @@ -29,8 +29,8 @@ pub fn derive_ref_unref(input: proc_macro::TokenStream) -> proc_macro::TokenStre // Used in the quasi-quotation below as `#name`. let name = &input.ident; - let fn_ref = syn::Ident::new(&format!("{}_ref", quote!(#name)), input.span()); - let fn_unref = syn::Ident::new(&format!("{}_unref", quote!(#name)), input.span()); + let fn_ref = syn::Ident::new(&format!("{}_ref_impl", quote!(#name)), input.span()); + let fn_unref = syn::Ident::new(&format!("{}_unref_impl", quote!(#name)), input.span()); let expanded = quote! { #[no_mangle] @@ -65,3 +65,22 @@ pub fn derive_ref_unref(input: proc_macro::TokenStream) -> proc_macro::TokenStre // Hand the output tokens back to the compiler. proc_macro::TokenStream::from(expanded) } + +#[proc_macro_attribute] +pub fn append_impl( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let mut func = parse_macro_input!(item as syn::ItemFn); + + let name = &func.sig.ident; + let new_name = format!("{}_impl", name); + + func.sig.ident = syn::Ident::new(&new_name, name.span()); + + let output = quote! { + #func + }; + + output.into() +} -- Gitee From 81cb7d160976779004d261bb0f751a06a7b70fbb Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 11:45:19 +0800 Subject: [PATCH 38/48] feature(libudev): add declarative macro to assert and return --- exts/libudev/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/exts/libudev/src/lib.rs b/exts/libudev/src/lib.rs index cd6f7f22..56c1cd6a 100644 --- a/exts/libudev/src/lib.rs +++ b/exts/libudev/src/lib.rs @@ -27,3 +27,13 @@ pub mod libudev_list; pub mod libudev_monitor; /// libudev_queue pub mod libudev_queue; + +#[macro_export] +/// if the expression is not true, return specified value +macro_rules! assert_return { + ( $x:expr, $r:expr ) => { + if !($x) { + return $r; + } + }; +} -- Gitee From 9f3ab04d6d12ee8da2f7cc626be67be411cb7081 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 12:32:58 +0800 Subject: [PATCH 39/48] feature(basic): support path_util module Add path_is_normalized function to check whether a C string is a normalized path. --- libs/basic/Cargo.toml | 2 ++ libs/basic/src/lib.rs | 2 ++ libs/basic/src/path_util.rs | 58 +++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 libs/basic/src/path_util.rs diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml index aced5a4f..e2faa0d9 100644 --- a/libs/basic/Cargo.toml +++ b/libs/basic/Cargo.toml @@ -68,6 +68,7 @@ full = [ "id128", "namespace", "time_util", + "path_util", ] capability = [] @@ -120,3 +121,4 @@ unistd = ["nix/user"] unit_name = [] uuid = ["bitflags", "random"] time_util = [] +path_util = [] diff --git a/libs/basic/src/lib.rs b/libs/basic/src/lib.rs index 5007047c..9d76b57f 100644 --- a/libs/basic/src/lib.rs +++ b/libs/basic/src/lib.rs @@ -57,6 +57,8 @@ pub mod network; pub mod os_release; #[cfg(feature = "parse")] pub mod parse; +#[cfg(feature = "path_util")] +pub mod path_util; #[cfg(feature = "process")] pub mod process; #[cfg(feature = "random")] diff --git a/libs/basic/src/path_util.rs b/libs/basic/src/path_util.rs new file mode 100644 index 00000000..9512b3f9 --- /dev/null +++ b/libs/basic/src/path_util.rs @@ -0,0 +1,58 @@ +// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysMaster is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +//! utilities for parse path string +#![allow(clippy::not_unsafe_ptr_arg_deref)] +use std::ffi::CStr; + +/// Check whether a C string is valid and normalized +pub fn path_is_normalized(p: *const ::std::os::raw::c_char) -> bool { + if p.is_null() { + return false; + } + + let p = match unsafe { CStr::from_ptr(p) }.to_str() { + Ok(p) => p, + Err(_) => { + return false; + } + }; + + if p == "." + || p.starts_with("./") + || p.ends_with("/.") + || p.contains("/./") + || p.contains("/../") + || p.contains("//") + { + return false; + } + + true +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_path_is_normalized() { + assert!(path_is_normalized("a\0".as_ptr() as *const _)); + assert!(path_is_normalized("a/b\0".as_ptr() as *const _)); + assert!(path_is_normalized("/a\0".as_ptr() as *const _)); + assert!(!path_is_normalized("./a\0".as_ptr() as *const _)); + assert!(!path_is_normalized("a/.\0".as_ptr() as *const _)); + assert!(!path_is_normalized("a/./a\0".as_ptr() as *const _)); + assert!(!path_is_normalized("a//a\0".as_ptr() as *const _)); + assert!(!path_is_normalized("a/../a\0".as_ptr() as *const _)); + } +} -- Gitee From f96ab0d6d25dc848e2b77e1fb451fe122957abe9 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 12:36:33 +0800 Subject: [PATCH 40/48] fix(libudev): check validity of the input parameters Check validity of the input parameters to avoid program panic. --- exts/libudev/src/libudev_device.rs | 165 +++++++++++++++++++++++--- exts/libudev/src/libudev_enumerate.rs | 15 ++- exts/libudev/src/libudev_hwdb.rs | 6 + exts/libudev/src/libudev_list.rs | 6 +- exts/libudev/src/libudev_monitor.rs | 28 ++++- 5 files changed, 199 insertions(+), 21 deletions(-) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index f9c8255a..cd487b65 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -18,11 +18,11 @@ use device::Device; use std::ffi::{CStr, CString}; use std::mem; -use std::os::linux::raw::dev_t; +use std::os::{linux::raw::dev_t, raw::c_char}; use std::rc::Rc; -use crate::libudev::*; use crate::libudev_list::{udev_list, udev_list_entry}; +use crate::{assert_return, libudev::*}; use libudev_macro::append_impl; use libudev_macro::RefUnref; @@ -101,7 +101,12 @@ pub extern "C" fn udev_device_new_from_device_id( udev: *mut udev, id: *const ::std::os::raw::c_char, ) -> *mut udev_device { - let id = unsafe { CStr::from_ptr(id as *const i8) }; + assert_return!(!id.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + + let id = unsafe { CStr::from_ptr(id as *const c_char) }; let s = match id.to_str() { Ok(s) => s, @@ -124,6 +129,11 @@ pub extern "C" fn udev_device_new_from_devnum( type_: ::std::os::raw::c_char, devnum: dev_t, ) -> *mut udev_device { + assert_return!(type_ == 'b' as c_char || type_ == 'c' as c_char, { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let device = match Device::from_devnum(type_ as u8 as char, devnum) { Ok(d) => Rc::new(d), Err(_) => return std::ptr::null_mut(), @@ -140,10 +150,20 @@ pub extern "C" fn udev_device_new_from_subsystem_sysname( subsystem: *const ::std::os::raw::c_char, sysname: *const ::std::os::raw::c_char, ) -> *mut udev_device { - let subsystem = unsafe { CStr::from_ptr(subsystem as *const i8) } + assert_return!(!subsystem.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + + assert_return!(!sysname.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + + let subsystem = unsafe { CStr::from_ptr(subsystem as *const c_char) } .to_str() .unwrap(); - let sysname = unsafe { CStr::from_ptr(sysname as *const i8) } + let sysname = unsafe { CStr::from_ptr(sysname as *const c_char) } .to_str() .unwrap(); let device = match Device::from_subsystem_sysname(subsystem, sysname) { @@ -163,7 +183,12 @@ pub extern "C" fn udev_device_new_from_syspath( udev: *mut udev, syspath: *const ::std::os::raw::c_char, ) -> *mut udev_device { - let syspath = unsafe { CStr::from_ptr(syspath as *const i8) } + assert_return!(!syspath.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + + let syspath = unsafe { CStr::from_ptr(syspath as *const c_char) } .to_str() .unwrap(); let device = match Device::from_syspath(syspath, true) { @@ -197,6 +222,11 @@ pub fn udev_device_new_from_environment(udev: *mut udev) -> *mut udev_device { pub extern "C" fn udev_device_get_syspath( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -233,6 +263,11 @@ pub extern "C" fn udev_device_has_tag( udev_device: *mut udev_device, tag: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!(!udev_device.is_null() && !tag.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + 0 + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap(); @@ -250,6 +285,11 @@ pub extern "C" fn udev_device_has_current_tag( udev_device: *mut udev_device, tag: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!(!udev_device.is_null() && !tag.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + 0 + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap(); @@ -266,6 +306,11 @@ pub extern "C" fn udev_device_has_current_tag( pub extern "C" fn udev_device_get_action( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if let Ok(action) = udev_device_mut.device.get_action() { @@ -282,6 +327,11 @@ pub extern "C" fn udev_device_get_action( pub extern "C" fn udev_device_get_devnode( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -306,6 +356,11 @@ pub extern "C" fn udev_device_get_devnode( #[append_impl] /// udev_device_get_devnum pub extern "C" fn udev_device_get_devnum(udev_device: *mut udev_device) -> dev_t { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + 0 + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; match udev_device_mut.device.get_devnum() { @@ -326,6 +381,11 @@ pub extern "C" fn udev_device_get_devnum(udev_device: *mut udev_device) -> dev_t pub extern "C" fn udev_device_get_devpath( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -356,6 +416,11 @@ pub extern "C" fn udev_device_get_devpath( pub extern "C" fn udev_device_get_devtype( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -389,6 +454,11 @@ pub extern "C" fn udev_device_get_devtype( pub extern "C" fn udev_device_get_driver( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -419,6 +489,11 @@ pub extern "C" fn udev_device_get_driver( pub extern "C" fn udev_device_get_sysname( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -449,6 +524,11 @@ pub extern "C" fn udev_device_get_sysname( pub extern "C" fn udev_device_get_subsystem( udev_device: *mut udev_device, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null() + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !udev_device_mut @@ -479,6 +559,11 @@ pub extern "C" fn udev_device_get_subsystem( pub extern "C" fn udev_device_get_seqnum( udev_device: *mut udev_device, ) -> ::std::os::raw::c_ulonglong { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + 0 + }); + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; udev_device_mut.device.get_seqnum().unwrap_or_default() as ::std::os::raw::c_ulonglong @@ -491,6 +576,11 @@ pub extern "C" fn udev_device_get_property_value( udev_device: *mut udev_device, key: *const ::std::os::raw::c_char, ) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null() && !key.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let key = unsafe { CStr::from_ptr(key) }; let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; @@ -518,6 +608,11 @@ pub extern "C" fn udev_device_get_property_value( pub extern "C" fn udev_device_get_properties_list_entry( udev_device: *mut udev_device, ) -> *mut udev_list_entry { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let d: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !d.properties_read { @@ -533,6 +628,11 @@ pub extern "C" fn udev_device_get_properties_list_entry( } fn device_new_from_parent(child: *mut udev_device) -> *mut udev_device { + assert_return!(!child.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let ud: &mut udev_device = unsafe { mem::transmute(&mut *child) }; match ud.device.get_parent() { @@ -550,6 +650,11 @@ fn device_new_from_parent(child: *mut udev_device) -> *mut udev_device { /// /// return the reference of the innter parent field, thus don't drop it pub extern "C" fn udev_device_get_parent(udev_device: *mut udev_device) -> *mut udev_device { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if ud.parent.is_null() { @@ -567,10 +672,24 @@ pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( subsystem: *const ::std::os::raw::c_char, devtype: *const ::std::os::raw::c_char, ) -> *mut udev_device { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + assert_return!(!subsystem.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; let subsystem = unsafe { CStr::from_ptr(subsystem).to_str().unwrap_or_default() }; - let devtype = unsafe { CStr::from_ptr(devtype).to_str().ok() }; + + let devtype = if devtype.is_null() { + None + } else { + unsafe { CStr::from_ptr(devtype).to_str().ok() } + }; let p = match ud .device @@ -608,6 +727,11 @@ pub extern "C" fn udev_device_get_parent_with_subsystem_devtype( pub extern "C" fn udev_device_get_is_initialized( udev_device: *mut udev_device, ) -> ::std::os::raw::c_int { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + -libc::EINVAL + }); + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; match ud.device.get_is_initialized() { @@ -631,6 +755,11 @@ pub extern "C" fn udev_device_get_is_initialized( pub extern "C" fn udev_device_get_devlinks_list_entry( udev_device: *mut udev_device, ) -> *mut udev_list_entry { + assert_return!(!udev_device.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let ud: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; if !ud.devlinks_read { @@ -649,7 +778,7 @@ pub extern "C" fn udev_device_get_devlinks_list_entry( #[cfg(test)] mod test { - use std::intrinsics::transmute; + use std::{intrinsics::transmute, os::raw::c_char}; use crate::libudev_list::{udev_list_entry_get_name_impl, udev_list_entry_get_next_impl}; @@ -668,8 +797,11 @@ mod test { 'c' }; - let raw_udev_device = - udev_device_new_from_devnum_impl(std::ptr::null_mut(), t as ::std::os::raw::c_char, devnum); + let raw_udev_device = udev_device_new_from_devnum_impl( + std::ptr::null_mut(), + t as ::std::os::raw::c_char, + devnum, + ); let syspath = unsafe { CStr::from_ptr(udev_device_get_syspath_impl(raw_udev_device)) }; @@ -727,7 +859,8 @@ mod test { fn test_udev_device_new_from_syspath(device: RD) -> Result { let syspath = device.get_syspath().unwrap(); let c_syspath = CString::new(syspath).unwrap(); - let udev_device = udev_device_new_from_syspath_impl(std::ptr::null_mut(), c_syspath.as_ptr()); + let udev_device = + udev_device_new_from_syspath_impl(std::ptr::null_mut(), c_syspath.as_ptr()); let ret_syspath = unsafe { CStr::from_ptr(udev_device_get_syspath_impl(udev_device)) }; assert_eq!(c_syspath.to_str().unwrap(), ret_syspath.to_str().unwrap()); @@ -753,14 +886,14 @@ mod test { assert!( udev_device_has_tag_impl( udev_device, - "test_udev_device_has_tag\0".as_ptr() as *const i8 + "test_udev_device_has_tag\0".as_ptr() as *const c_char ) > 0 ); assert!( udev_device_has_current_tag_impl( udev_device, - "test_udev_device_has_tag\0".as_ptr() as *const i8 + "test_udev_device_has_tag\0".as_ptr() as *const c_char ) > 0 ); @@ -918,7 +1051,7 @@ mod test { unsafe { CStr::from_ptr(udev_device_get_property_value_impl( ud, - "hello\0".as_ptr() as *const i8, + "hello\0".as_ptr() as *const c_char, )) } .to_str() @@ -963,8 +1096,8 @@ mod test { let ud = from_rd(dev); let pud = udev_device_get_parent_with_subsystem_devtype_impl( ud, - "block\0".as_ptr() as *const i8, - "disk\0".as_ptr() as *const i8, + "block\0".as_ptr() as *const c_char, + "disk\0".as_ptr() as *const c_char, ); assert!(!pud.is_null()); diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 06e657d0..3d7e19d3 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -20,9 +20,9 @@ use std::ffi::{CStr, CString}; use std::intrinsics::transmute; use std::rc::Rc; -use crate::libudev::*; use crate::libudev_device::udev_device; use crate::libudev_list::{udev_list, udev_list_entry}; +use crate::{assert_return, libudev::*}; use device::device_enumerator::*; use libudev_macro::append_impl; use libudev_macro::RefUnref; @@ -196,6 +196,11 @@ pub fn udev_enumerate_add_match_is_initialized( #[append_impl] /// udev_enumerate_get_udev pub extern "C" fn udev_enumerate_get_udev(udev_enumerate: *mut udev_enumerate) -> *mut udev { + assert_return!(!udev_enumerate.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; e.udev @@ -208,6 +213,8 @@ pub extern "C" fn udev_enumerate_add_match_tag( udev_enumerate: *mut udev_enumerate, tag: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap(); @@ -226,6 +233,12 @@ pub extern "C" fn udev_enumerate_add_match_parent( udev_enumerate: *mut udev_enumerate, parent: *mut udev_device, ) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + + if parent.is_null() { + return 0; + } + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; let p: Rc = unsafe { Rc::from_raw(parent) }; diff --git a/exts/libudev/src/libudev_hwdb.rs b/exts/libudev/src/libudev_hwdb.rs index 56bf330d..470be03d 100644 --- a/exts/libudev/src/libudev_hwdb.rs +++ b/exts/libudev/src/libudev_hwdb.rs @@ -25,6 +25,7 @@ use std::{ rc::Rc, }; +use crate::assert_return; use crate::{ libudev::udev, libudev_list::{udev_list, udev_list_entry}, @@ -64,6 +65,11 @@ pub extern "C" fn udev_hwdb_get_properties_list_entry( modalias: *const ::std::os::raw::c_char, _flags: ::std::os::raw::c_uint, ) -> *mut udev_list_entry { + assert_return!(!hwdb.is_null() && !modalias.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let h: &mut udev_hwdb = unsafe { transmute(&mut *hwdb) }; h.properties.cleanup(); diff --git a/exts/libudev/src/libudev_list.rs b/exts/libudev/src/libudev_list.rs index 6d088e58..e513bc36 100644 --- a/exts/libudev/src/libudev_list.rs +++ b/exts/libudev/src/libudev_list.rs @@ -136,6 +136,10 @@ impl udev_list { pub extern "C" fn udev_list_entry_get_next( list_entry: *mut udev_list_entry, ) -> *mut udev_list_entry { + if list_entry.is_null() { + return std::ptr::null_mut(); + } + /* Take the ownership of udev_list_entry */ let entry = unsafe { Rc::from_raw(list_entry) }; @@ -157,7 +161,7 @@ pub extern "C" fn udev_list_entry_get_by_name( list_entry: *mut udev_list_entry, name: *const ::std::os::raw::c_char, ) -> *mut udev_list_entry { - if list_entry.is_null() { + if list_entry.is_null() || name.is_null() { return std::ptr::null_mut(); } diff --git a/exts/libudev/src/libudev_monitor.rs b/exts/libudev/src/libudev_monitor.rs index a00749ff..02c53145 100644 --- a/exts/libudev/src/libudev_monitor.rs +++ b/exts/libudev/src/libudev_monitor.rs @@ -15,6 +15,7 @@ #![allow(deprecated)] #![allow(clippy::not_unsafe_ptr_arg_deref)] +use crate::assert_return; use crate::libudev::*; use crate::libudev_device::udev_device; use device::device_monitor::*; @@ -46,6 +47,11 @@ pub extern "C" fn udev_monitor_new_from_netlink( udev: *mut udev, name: *const ::std::os::raw::c_char, ) -> *mut udev_monitor { + assert_return!(!name.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let name = unsafe { CStr::from_ptr(name) }.to_str().unwrap(); let g = match name { @@ -72,6 +78,8 @@ pub extern "C" fn udev_monitor_new_from_netlink( pub extern "C" fn udev_monitor_enable_receiving( udev_monitor: *mut udev_monitor, ) -> ::std::os::raw::c_int { + assert_return!(!udev_monitor.is_null(), -libc::EINVAL); + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; match m.monitor.borrow_mut().bpf_filter_update() { @@ -88,14 +96,24 @@ pub extern "C" fn udev_monitor_filter_add_match_subsystem_devtype( subsystem: *const ::std::os::raw::c_char, devtype: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!( + !udev_monitor.is_null() && !subsystem.is_null(), + -libc::EINVAL + ); + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; let subsystem = unsafe { CStr::from_ptr(subsystem) } .to_str() .unwrap_or_default(); - let devtype = unsafe { CStr::from_ptr(devtype) } - .to_str() - .unwrap_or_default(); + + let devtype = if devtype.is_null() { + "" + } else { + unsafe { CStr::from_ptr(devtype) } + .to_str() + .unwrap_or_default() + }; if let Err(e) = m .monitor @@ -115,6 +133,8 @@ pub extern "C" fn udev_monitor_filter_add_match_tag( udev_monitor: *mut udev_monitor, tag: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!(!udev_monitor.is_null() && !tag.is_null(), -libc::EINVAL); + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; let tag = unsafe { CStr::from_ptr(tag) }.to_str().unwrap_or_default(); @@ -130,6 +150,8 @@ pub extern "C" fn udev_monitor_filter_add_match_tag( #[append_impl] /// udev_monitor_get_fd pub extern "C" fn udev_monitor_get_fd(udev_monitor: *mut udev_monitor) -> ::std::os::raw::c_int { + assert_return!(!udev_monitor.is_null(), -libc::EINVAL); + let m: &mut udev_monitor = unsafe { transmute(&mut *udev_monitor) }; m.monitor.borrow().fd() -- Gitee From 5f7535884a5298b2e97c8c413c8f4696c80d48e6 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 12:38:01 +0800 Subject: [PATCH 41/48] test(libudev): test whether some functions will panic if input parameters are invalid --- exts/libudev/tests/test_libudev_monitor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/exts/libudev/tests/test_libudev_monitor.c b/exts/libudev/tests/test_libudev_monitor.c index 4a3acef7..dfafafc2 100644 --- a/exts/libudev/tests/test_libudev_monitor.c +++ b/exts/libudev/tests/test_libudev_monitor.c @@ -19,6 +19,7 @@ void main() { struct udev_monitor *m = udev_monitor_new_from_netlink(NULL, "kernel"); + udev_monitor_filter_add_match_subsystem_devtype(m, "block", NULL); udev_monitor_filter_add_match_subsystem_devtype(m, "block", "partition"); udev_monitor_enable_receiving(m); while (1) -- Gitee From 6f0043235107edac884c5782de418aea9c88370a Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 15:08:04 +0800 Subject: [PATCH 42/48] fix(libudev): fix incorrect dropping The udev field contains the pointer towards a udev object. Its life time is not maintained by the container and should not be unreferenced, to be consistent with libudev. --- exts/libudev/src/libudev_device.rs | 3 +-- exts/libudev/src/libudev_enumerate.rs | 8 -------- exts/libudev/src/libudev_monitor.rs | 6 ------ 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index cd487b65..aed95ef8 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -66,8 +66,7 @@ pub struct udev_device { impl Drop for udev_device { fn drop(&mut self) { - if !self.udev.is_null() { - let _ = unsafe { Rc::from_raw(self.udev) }; + if !self.parent.is_null() { let _ = unsafe { Rc::from_raw(self.parent) }; } } diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 3d7e19d3..84c1d8b8 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -38,14 +38,6 @@ pub struct udev_enumerate { pub(crate) enumerator: Rc>, } -impl Drop for udev_enumerate { - fn drop(&mut self) { - if !self.udev.is_null() { - let _ = unsafe { Rc::from_raw(self.udev) }; - } - } -} - #[no_mangle] #[append_impl] /// udev_enumerate_new diff --git a/exts/libudev/src/libudev_monitor.rs b/exts/libudev/src/libudev_monitor.rs index 02c53145..81b8c9d1 100644 --- a/exts/libudev/src/libudev_monitor.rs +++ b/exts/libudev/src/libudev_monitor.rs @@ -34,12 +34,6 @@ pub struct udev_monitor { pub(crate) monitor: Rc>, } -impl Drop for udev_monitor { - fn drop(&mut self) { - let _ = unsafe { Rc::from_raw(self.udev) }; - } -} - #[no_mangle] #[append_impl] /// udev_monitor_new_from_netlink -- Gitee From c90e2d35cde4605c0a856a7480d15b58ad24f696 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 15:22:41 +0800 Subject: [PATCH 43/48] feature(libudev): support udev_enumerate_add_match_sysattr ABI Support udev_enumerate_add_match_sysattr ABI to satisfy some applications such as libvirt. --- exts/libudev/build.rs | 2 +- exts/libudev/src/libudev_enumerate.rs | 34 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/exts/libudev/build.rs b/exts/libudev/build.rs index ae7e120b..5bc43419 100644 --- a/exts/libudev/build.rs +++ b/exts/libudev/build.rs @@ -48,7 +48,7 @@ fn main() { "udev_enumerate_add_match_parent", "udev_enumerate_add_match_property", "udev_enumerate_add_match_subsystem", - // "udev_enumerate_add_match_sysattr", + "udev_enumerate_add_match_sysattr", // "udev_enumerate_add_match_sysname", "udev_enumerate_add_match_tag", // "udev_enumerate_add_nomatch_subsystem", diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 84c1d8b8..464f276a 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -244,6 +244,40 @@ pub extern "C" fn udev_enumerate_add_match_parent( 0 } +#[no_mangle] +#[append_impl] +pub extern "C" fn udev_enumerate_add_match_sysattr( + udev_enumerate: *mut udev_enumerate, + sysattr: *const ::std::os::raw::c_char, + value: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + + if sysattr.is_null() { + return 0; + } + + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + let sysattr = unsafe { CStr::from_ptr(sysattr) }.to_str().unwrap(); + let value = if value.is_null() { + "" + } else { + unsafe { CStr::from_ptr(value) }.to_str().unwrap() + }; + + if let Err(e) = e + .enumerator + .borrow_mut() + .add_match_sysattr(sysattr, value, true) + { + return e.get_errno() as i32; + } + + e.up_to_date = false; + 0 +} + #[cfg(test)] mod tests { use device::Device; -- Gitee From 8b353e5a876801a75878e45fd6aca82dcc765128 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 16:01:20 +0800 Subject: [PATCH 44/48] feature(libudev): support some ABIs to support libvirtd Include: udev_device_get_sysattr_value udev_enumerate_add_nomatch_subsystem udev_enumerate_add_nomatch_sysattr --- exts/libudev/build.rs | 6 +-- exts/libudev/src/libudev_device.rs | 38 ++++++++++++++++ exts/libudev/src/libudev_enumerate.rs | 63 +++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/exts/libudev/build.rs b/exts/libudev/build.rs index 5bc43419..f8017791 100644 --- a/exts/libudev/build.rs +++ b/exts/libudev/build.rs @@ -30,7 +30,7 @@ fn main() { "udev_device_get_seqnum", "udev_device_get_subsystem", // "udev_device_get_sysattr_list_entry", - // "udev_device_get_sysattr_value", + "udev_device_get_sysattr_value", "udev_device_get_sysname", // "udev_device_get_sysnum", "udev_device_get_syspath", @@ -51,8 +51,8 @@ fn main() { "udev_enumerate_add_match_sysattr", // "udev_enumerate_add_match_sysname", "udev_enumerate_add_match_tag", - // "udev_enumerate_add_nomatch_subsystem", - // "udev_enumerate_add_nomatch_sysattr", + "udev_enumerate_add_nomatch_subsystem", + "udev_enumerate_add_nomatch_sysattr", // "udev_enumerate_add_syspath", "udev_enumerate_get_list_entry", "udev_enumerate_get_udev", diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index aed95ef8..f8cfc3b9 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -61,6 +61,9 @@ pub struct udev_device { pub(crate) devlinks: Rc, pub(crate) devlinks_read: bool, + pub(crate) sysattrs: Rc, + pub(crate) sysattrs_read: bool, + pub(crate) parent: *mut udev_device, } @@ -88,6 +91,8 @@ impl udev_device { properties_read: false, devlinks: Rc::new(udev_list::new(true)), devlinks_read: false, + sysattrs: Rc::new(udev_list::new(true)), + sysattrs_read: false, parent: std::ptr::null_mut(), } } @@ -775,6 +780,39 @@ pub extern "C" fn udev_device_get_devlinks_list_entry( ud.devlinks.get_entry() } +#[no_mangle] +#[append_impl] +pub extern "C" fn udev_device_get_sysattr_value( + udev_device: *mut udev_device, + sysattr: *const ::std::os::raw::c_char, +) -> *const ::std::os::raw::c_char { + assert_return!(!udev_device.is_null() && !sysattr.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + + let sysattr = unsafe { CStr::from_ptr(sysattr) }; + let udev_device_mut: &mut udev_device = unsafe { mem::transmute(&mut *udev_device) }; + + let sysattr_string: String = sysattr.to_str().unwrap().to_string(); + match udev_device_mut + .device + .get_sysattr_value(sysattr_string.as_str()) + { + Ok(v) => { + let entry = udev_device_mut.sysattrs.add_entry( + CString::new(sysattr_string.as_str()).unwrap(), + CString::new(v.as_str()).unwrap(), + ); + entry.value.as_ptr() + } + Err(e) => { + errno::set_errno(errno::Errno(e.get_errno() as i32)); + std::ptr::null() + } + } +} + #[cfg(test)] mod test { use std::{intrinsics::transmute, os::raw::c_char}; diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 464f276a..15db6a34 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -278,6 +278,69 @@ pub extern "C" fn udev_enumerate_add_match_sysattr( 0 } +#[no_mangle] +#[append_impl] +pub extern "C" fn udev_enumerate_add_nomatch_sysattr( + udev_enumerate: *mut udev_enumerate, + sysattr: *const ::std::os::raw::c_char, + value: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + + if sysattr.is_null() { + return 0; + } + + let e: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + let sysattr = unsafe { CStr::from_ptr(sysattr) }.to_str().unwrap(); + let value = if value.is_null() { + "" + } else { + unsafe { CStr::from_ptr(value) }.to_str().unwrap() + }; + + if let Err(e) = e + .enumerator + .borrow_mut() + .add_match_sysattr(sysattr, value, false) + { + return e.get_errno() as i32; + } + + e.up_to_date = false; + 0 +} + +#[no_mangle] +#[append_impl] +pub extern "C" fn udev_enumerate_add_nomatch_subsystem( + udev_enumerate: *mut udev_enumerate, + subsystem: *const ::std::os::raw::c_char, +) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + + if subsystem.is_null() { + return 0; + } + + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; + + let subsystem = unsafe { CStr::from_ptr(subsystem) }.to_str().unwrap(); + + if let Err(e) = udev_enumerate + .enumerator + .borrow_mut() + .add_match_subsystem(subsystem, false) + { + return e.get_errno() as i32; + } + + udev_enumerate.up_to_date = false; + + 0 +} + #[cfg(test)] mod tests { use device::Device; -- Gitee From a2fc06a61f725357c420718de1a177c25af3909c Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 16:06:28 +0800 Subject: [PATCH 45/48] fix(libudev): assert validity of input parameters for udev_enumerate methods This patch is a complementary for previous commit cb3b10c5e6b0e052c893043cbe78f3604e2da1cd --- exts/libudev/src/libudev_enumerate.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index 15db6a34..f14ef5b2 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -62,6 +62,8 @@ pub extern "C" fn udev_enumerate_new(udev: *mut udev) -> *mut udev_enumerate { pub extern "C" fn udev_enumerate_scan_devices( udev_enumerate: *mut udev_enumerate, ) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; match udev_enumerate.enumerator.borrow_mut().scan_devices() { @@ -76,6 +78,11 @@ pub extern "C" fn udev_enumerate_scan_devices( pub extern "C" fn udev_enumerate_get_list_entry( udev_enumerate: *mut udev_enumerate, ) -> *mut udev_list_entry { + assert_return!(!udev_enumerate.is_null(), { + errno::set_errno(errno::Errno(libc::EINVAL)); + std::ptr::null_mut() + }); + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; if !udev_enumerate.up_to_date { @@ -112,6 +119,11 @@ pub extern "C" fn udev_enumerate_add_match_subsystem( udev_enumerate: *mut udev_enumerate, subsystem: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!( + !udev_enumerate.is_null() && !subsystem.is_null(), + -libc::EINVAL + ); + if subsystem.is_null() { return 0; } @@ -141,6 +153,11 @@ pub extern "C" fn udev_enumerate_add_match_property( property: *const ::std::os::raw::c_char, value: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int { + assert_return!( + !udev_enumerate.is_null() && !property.is_null(), + -libc::EINVAL + ); + if property.is_null() { return 0; } @@ -148,7 +165,11 @@ pub extern "C" fn udev_enumerate_add_match_property( let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; let property = unsafe { CStr::from_ptr(property) }.to_str().unwrap(); - let value = unsafe { CStr::from_ptr(value) }.to_str().unwrap(); + let value = if value.is_null() { + "" + } else { + unsafe { CStr::from_ptr(value) }.to_str().unwrap() + }; if let Err(e) = udev_enumerate .enumerator @@ -169,6 +190,8 @@ pub extern "C" fn udev_enumerate_add_match_property( pub fn udev_enumerate_add_match_is_initialized( udev_enumerate: *mut udev_enumerate, ) -> ::std::os::raw::c_int { + assert_return!(!udev_enumerate.is_null(), -libc::EINVAL); + let udev_enumerate: &mut udev_enumerate = unsafe { transmute(&mut *udev_enumerate) }; if let Err(e) = udev_enumerate -- Gitee From 470602b5a35f94c5179b1c9e91deaa77bb906449 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 18:21:57 +0800 Subject: [PATCH 46/48] docs(libudev): append missed docs for public APIs --- exts/libudev/src/libudev_device.rs | 1 + exts/libudev/src/libudev_enumerate.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/exts/libudev/src/libudev_device.rs b/exts/libudev/src/libudev_device.rs index f8cfc3b9..c820f7af 100644 --- a/exts/libudev/src/libudev_device.rs +++ b/exts/libudev/src/libudev_device.rs @@ -782,6 +782,7 @@ pub extern "C" fn udev_device_get_devlinks_list_entry( #[no_mangle] #[append_impl] +/// udev_device_get_sysattr_value pub extern "C" fn udev_device_get_sysattr_value( udev_device: *mut udev_device, sysattr: *const ::std::os::raw::c_char, diff --git a/exts/libudev/src/libudev_enumerate.rs b/exts/libudev/src/libudev_enumerate.rs index f14ef5b2..b0cc668c 100644 --- a/exts/libudev/src/libudev_enumerate.rs +++ b/exts/libudev/src/libudev_enumerate.rs @@ -269,6 +269,7 @@ pub extern "C" fn udev_enumerate_add_match_parent( #[no_mangle] #[append_impl] +/// udev_enumerate_add_match_sysattr pub extern "C" fn udev_enumerate_add_match_sysattr( udev_enumerate: *mut udev_enumerate, sysattr: *const ::std::os::raw::c_char, @@ -303,6 +304,7 @@ pub extern "C" fn udev_enumerate_add_match_sysattr( #[no_mangle] #[append_impl] +/// udev_enumerate_add_nomatch_sysattr pub extern "C" fn udev_enumerate_add_nomatch_sysattr( udev_enumerate: *mut udev_enumerate, sysattr: *const ::std::os::raw::c_char, @@ -337,6 +339,7 @@ pub extern "C" fn udev_enumerate_add_nomatch_sysattr( #[no_mangle] #[append_impl] +/// udev_enumerate_add_nomatch_subsystem pub extern "C" fn udev_enumerate_add_nomatch_subsystem( udev_enumerate: *mut udev_enumerate, subsystem: *const ::std::os::raw::c_char, -- Gitee From 39bdb522afe93f50ff6d2d5943b176d8e78b660d Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Fri, 22 Dec 2023 18:35:09 +0800 Subject: [PATCH 47/48] docs(libudev_macrO): add missing docs --- exts/libudev_macro/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/exts/libudev_macro/src/lib.rs b/exts/libudev_macro/src/lib.rs index ff1fb681..00b6d53f 100644 --- a/exts/libudev_macro/src/lib.rs +++ b/exts/libudev_macro/src/lib.rs @@ -67,6 +67,7 @@ pub fn derive_ref_unref(input: proc_macro::TokenStream) -> proc_macro::TokenStre } #[proc_macro_attribute] +/// append _impl to the original function name pub fn append_impl( _attr: proc_macro::TokenStream, item: proc_macro::TokenStream, -- Gitee From 6e66cfd77b4464c7f163662d866e65ce666e922b Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Sat, 23 Dec 2023 13:46:09 +0800 Subject: [PATCH 48/48] fix(libudev): abandon compilation for libudev temporarily Compilation for libudev requires "lld" linker, which is not provided in openeuler 22.03 right now. --- Cargo.lock | 22 ---------------------- Cargo.toml | 2 +- exts/libudev/build.rs | 5 ++++- 3 files changed, 5 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab1c1e32..9edc25d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1006,28 +1006,6 @@ dependencies = [ name = "libtests" version = "0.5.1" -[[package]] -name = "libudev" -version = "0.5.1" -dependencies = [ - "basic", - "device", - "errno 0.3.8", - "hwdb", - "libc", - "libudev_macro", - "nix 0.24.3", -] - -[[package]] -name = "libudev_macro" -version = "0.5.1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - [[package]] name = "linked-hash-map" version = "0.5.6" diff --git a/Cargo.toml b/Cargo.toml index 791ab795..03a4e3e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -126,7 +126,7 @@ members = [ "exts/hostname_setup", "exts/hwdb", "exts/machine-id-setup", - "exts/libudev", + # "exts/libudev", #internal libraries crates "libs/cmdproto", #external libraries crates diff --git a/exts/libudev/build.rs b/exts/libudev/build.rs index f8017791..e28ed7fa 100644 --- a/exts/libudev/build.rs +++ b/exts/libudev/build.rs @@ -10,8 +10,11 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. -//! libudev link options +//! Append libudev.sym version script to link options. //! +//! The 'ld' linker of gcc can not support multiple declarations of version scripts. +//! Because rustc will append rust native version script, 'ld' is unavailable. Instead, +//! we should use 'lld' linker of llvm, as it support multiple declarations of version scripts. fn main() { let symbols = [ -- Gitee