From 29a5c87299dfb450fe0c2379543229acaa7c1c3e Mon Sep 17 00:00:00 2001 From: Dominic Grimm Date: Thu, 14 Nov 2024 20:44:02 +0100 Subject: [PATCH] Init --- .gitignore | 1 + Cargo.lock | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 +++ src/lib.rs | 208 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 468 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7f818c4 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,249 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +dependencies = [ + "backtrace", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote", + "syn", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.162" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "openlipc_dyn" +version = "0.1.0" +dependencies = [ + "anyhow", + "dlopen", + "dlopen_derive", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c8824d9 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "openlipc_dyn" +version = "0.1.0" +authors = ["Dominic Grimm "] +edition = "2021" + +[dependencies] +anyhow = { version = "1.0.93", features = ["backtrace"] } +dlopen = "0.1.8" +dlopen_derive = "0.1.4" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..02a4669 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,208 @@ +use anyhow::{bail, Result}; +use dlopen::wrapper::{Container, WrapperApi}; +use dlopen_derive::WrapperApi; +use std::ffi::{CStr, CString}; +use std::os::raw::{c_char, c_int, c_uint, c_void}; + +type LipcType = c_void; + +type LipcCode = c_uint; + +const LIPC_CODE_LIPC_OK: LipcCode = 0; +// const LIPC_CODE_LIPC_ERROR_UNKNOWN: LIPCcode = 1; +// const LIPC_CODE_LIPC_ERROR_INTERNAL: LIPCcode = 2; +// const LIPC_CODE_LIPC_ERROR_NO_SUCH_SOURCE: LIPCcode = 3; +// const LIPC_CODE_LIPC_ERROR_OPERATION_NOT_SUPPORTED: LIPCcode = 4; +// const LIPC_CODE_LIPC_ERROR_OUT_OF_MEMORY: LIPCcode = 5; +// const LIPC_CODE_LIPC_ERROR_SUBSCRIPTION_FAILED: LIPCcode = 6; +// const LIPC_CODE_LIPC_ERROR_NO_SUCH_PARAM: LIPCcode = 7; +// const LIPC_CODE_LIPC_ERROR_NO_SUCH_PROPERTY: LIPCcode = 8; +// const LIPC_CODE_LIPC_ERROR_ACCESS_NOT_ALLOWED: LIPCcode = 9; +// const LIPC_CODE_LIPC_ERROR_BUFFER_TOO_SMALL: LIPCcode = 10; +// const LIPC_CODE_LIPC_ERROR_INVALID_HANDLE: LIPCcode = 11; +// const LIPC_CODE_LIPC_ERROR_INVALID_ARG: LIPCcode = 12; +// const LIPC_CODE_LIPC_ERROR_OPERATION_NOT_ALLOWED: LIPCcode = 13; +// const LIPC_CODE_LIPC_ERROR_PARAMS_SIZE_EXCEEDED: LIPCcode = 14; +// const LIPC_CODE_LIPC_ERROR_TIMED_OUT: LIPCcode = 15; +// const LIPC_CODE_LIPC_ERROR_SERVICE_NAME_TOO_LONG: LIPCcode = 16; +// const LIPC_CODE_LIPC_ERROR_DUPLICATE_SERVICE_NAME: LIPCcode = 17; +// const LIPC_CODE_LIPC_ERROR_INIT_DBUS: LIPCcode = 18; +// const LIPC_CODE_LIPC_PROP_ERROR_INVALID_STATE: LIPCcode = 256; +// const LIPC_CODE_LIPC_PROP_ERROR_NOT_INITIALIZED: LIPCcode = 257; +// const LIPC_CODE_LIPC_PROP_ERROR_INTERNAL: LIPCcode = 258; + +#[derive(WrapperApi)] +pub struct LipcApi { + #[dlopen_name = "LipcOpenNoName"] + lipc_open_no_name: unsafe extern "C" fn() -> *mut LipcType, + + #[dlopen_name = "LipcClose"] + lipc_close: unsafe extern "C" fn(lipc: *mut LipcType), + + #[dlopen_name = "LipcGetErrorString"] + lipc_get_error_string: unsafe extern "C" fn(code: LipcCode) -> *const c_char, + + #[dlopen_name = "LipcFreeString"] + lipc_free_string: unsafe extern "C" fn(string: *mut c_char), + + #[dlopen_name = "LipcGetStringProperty"] + lipc_get_string_property: unsafe extern "C" fn( + lipc: *mut LipcType, + service: *const c_char, + property: *const c_char, + value: *mut *mut c_char, + ) -> LipcCode, + + #[dlopen_name = "LipcSetStringProperty"] + lipc_set_string_property: unsafe extern "C" fn( + lipc: *mut LipcType, + service: *const c_char, + property: *const c_char, + value: *const c_char, + ) -> LipcCode, + + #[dlopen_name = "LipcGetIntProperty"] + lipc_get_int_property: unsafe extern "C" fn( + lipc: *mut LipcType, + service: *const c_char, + property: *const c_char, + value: *mut c_int, + ) -> LipcCode, + + #[dlopen_name = "LipcSetIntProperty"] + lipc_set_int_property: unsafe extern "C" fn( + lipc: *mut LipcType, + service: *const c_char, + property: *const c_char, + value: c_int, + ) -> LipcCode, +} + +impl LipcApi { + const DEFAULT_NAME: &str = "liblipc.so"; + + pub fn load(path: Option<&str>) -> Result> { + let name = match path { + Some(x) => x, + None => Self::DEFAULT_NAME, + }; + let cont: Container = unsafe { Container::load(name) }?; + + Ok(cont) + } +} + +pub struct Lipc { + api: Container, + conn: *mut LipcType, +} + +impl Lipc { + pub fn new(api: Container) -> Result { + let lipc = unsafe { (api.lipc_open_no_name)() }; + if lipc == (std::ptr::null_mut() as *mut c_void) { + bail!("Failed to create connection!"); + } + + Ok(Self { api, conn: lipc }) + } + + pub fn load(name: Option<&str>) -> Result { + let api = LipcApi::load(name)?; + Self::new(api) + } + + fn code_to_result(&self, code: LipcCode) -> Result<()> { + if code == LIPC_CODE_LIPC_OK { + Ok(()) + } else { + bail!("LIPC error code: {} ({})", self.code_to_string(code)?, code); + } + } + + fn code_to_string(&self, code: LipcCode) -> Result { + let cstr = unsafe { + let str_ptr = (self.api.lipc_get_error_string)(code); + CStr::from_ptr(str_ptr) + }; + + Ok(String::from(cstr.to_str()?)) + } + + pub fn get_int_prop(&self, service: &str, prop: &str) -> Result { + let mut val: c_int = 0; + let service = CString::new(service)?; + let prop = CString::new(prop)?; + + let code = unsafe { + (self.api.lipc_get_int_property)(self.conn, service.as_ptr(), prop.as_ptr(), &mut val) + }; + self.code_to_result(code)?; + + Ok(val) + } + + pub fn set_int_prop(&self, service: &str, prop: &str, value: c_int) -> Result<()> { + let service = CString::new(service)?; + let prop = CString::new(prop)?; + + let code = unsafe { + (self.api.lipc_set_int_property)(self.conn, service.as_ptr(), prop.as_ptr(), value) + }; + self.code_to_result(code)?; + + Ok(()) + } + + pub fn get_str_prop(&self, service: &str, prop: &str) -> Result { + let mut handle: *mut c_char = std::ptr::null_mut(); + let handle_ptr: *mut *mut c_char = &mut handle; + + let service = CString::new(service)?; + let prop = CString::new(prop)?; + + let code = unsafe { + (self.api.lipc_get_string_property)( + self.conn, + service.as_ptr(), + prop.as_ptr(), + handle_ptr, + ) + }; + self.code_to_result(code)?; + + let val: String; + unsafe { + val = CStr::from_ptr(handle).to_str()?.to_string(); + (self.api.lipc_free_string)(handle); + } + + Ok(val) + } + + pub fn set_str_prop(&self, service: &str, prop: &str, value: &str) -> Result<()> { + let service = CString::new(service)?; + let prop = CString::new(prop)?; + let value = CString::new(value)?; + + let code = unsafe { + (self.api.lipc_set_string_property)( + self.conn, + service.as_ptr(), + prop.as_ptr(), + value.as_ptr(), + ) + }; + self.code_to_result(code)?; + + Ok(()) + } +} + +impl Drop for Lipc { + fn drop(&mut self) { + unsafe { + (self.api.lipc_close)(self.conn); + } + } +}