maolan_plugin_protocol/
shm.rs1use std::ffi::CString;
2
3pub struct ShmMapping {
5 ptr: *mut u8,
6 size: usize,
7 #[allow(dead_code)]
8 name: String,
9}
10
11unsafe impl Send for ShmMapping {}
13unsafe impl Sync for ShmMapping {}
14
15impl ShmMapping {
16 #[cfg(unix)]
18 pub fn create(name: &str, size: usize) -> Result<Self, String> {
19 let c_name = CString::new(name).map_err(|e| e.to_string())?;
20 let fd = unsafe { libc::shm_open(c_name.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o644) };
21 if fd < 0 {
22 return Err(format!(
23 "shm_open({}, O_CREAT|O_RDWR) failed: {:?}",
24 name,
25 std::io::Error::last_os_error()
26 ));
27 }
28 if unsafe { libc::ftruncate(fd, size as libc::off_t) } < 0 {
29 unsafe { libc::close(fd) };
30 return Err(format!(
31 "ftruncate failed: {:?}",
32 std::io::Error::last_os_error()
33 ));
34 }
35 let ptr = unsafe {
36 libc::mmap(
37 std::ptr::null_mut(),
38 size,
39 libc::PROT_READ | libc::PROT_WRITE,
40 libc::MAP_SHARED,
41 fd,
42 0,
43 )
44 };
45 unsafe { libc::close(fd) };
46 if ptr == libc::MAP_FAILED {
47 unsafe { libc::shm_unlink(c_name.as_ptr()) };
48 return Err(format!(
49 "mmap failed: {:?}",
50 std::io::Error::last_os_error()
51 ));
52 }
53 Ok(Self {
54 ptr: ptr as *mut u8,
55 size,
56 name: name.to_string(),
57 })
58 }
59
60 #[cfg(unix)]
62 pub fn open_existing(name: &str, size: usize) -> Result<Self, String> {
63 let c_name = CString::new(name).map_err(|e| e.to_string())?;
64 let fd = unsafe { libc::shm_open(c_name.as_ptr(), libc::O_RDWR, 0) };
65 if fd < 0 {
66 return Err(format!(
67 "shm_open({}, O_RDWR) failed: {:?}",
68 name,
69 std::io::Error::last_os_error()
70 ));
71 }
72 let ptr = unsafe {
73 libc::mmap(
74 std::ptr::null_mut(),
75 size,
76 libc::PROT_READ | libc::PROT_WRITE,
77 libc::MAP_SHARED,
78 fd,
79 0,
80 )
81 };
82 unsafe { libc::close(fd) };
83 if ptr == libc::MAP_FAILED {
84 return Err(format!(
85 "mmap failed: {:?}",
86 std::io::Error::last_os_error()
87 ));
88 }
89 Ok(Self {
90 ptr: ptr as *mut u8,
91 size,
92 name: name.to_string(),
93 })
94 }
95
96 #[cfg(windows)]
98 pub fn create(name: &str, size: usize) -> Result<Self, String> {
99 let _ = (name, size);
100 Err("Shared memory creation not yet implemented on Windows".to_string())
101 }
102
103 #[cfg(windows)]
104 pub fn open_existing(name: &str, size: usize) -> Result<Self, String> {
105 let _ = (name, size);
106 Err("Shared memory open not yet implemented on Windows".to_string())
107 }
108
109 pub fn as_ptr(&self) -> *mut u8 {
111 self.ptr
112 }
113
114 pub fn size(&self) -> usize {
116 self.size
117 }
118
119 pub fn name(&self) -> &str {
121 &self.name
122 }
123
124 #[cfg(unix)]
126 pub fn unlink(name: &str) -> Result<(), String> {
127 let c_name = CString::new(name).map_err(|e| e.to_string())?;
128 let res = unsafe { libc::shm_unlink(c_name.as_ptr()) };
129 if res < 0 {
130 Err(format!(
131 "shm_unlink failed: {:?}",
132 std::io::Error::last_os_error()
133 ))
134 } else {
135 Ok(())
136 }
137 }
138
139 #[cfg(windows)]
140 pub fn unlink(_name: &str) -> Result<(), String> {
141 Ok(())
142 }
143}
144
145#[cfg(unix)]
146impl Drop for ShmMapping {
147 fn drop(&mut self) {
148 if !self.ptr.is_null() && self.ptr != libc::MAP_FAILED as *mut u8 {
149 unsafe { libc::munmap(self.ptr as *mut libc::c_void, self.size) };
150 }
151 }
152}