Skip to content

Commit 5f0db52

Browse files
authored
Add shm_open/shm_unlink (POSIX shared memory) (#848)
Fixes #705.
1 parent 77c4aae commit 5f0db52

11 files changed

Lines changed: 199 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ thread = ["linux-raw-sys/prctl"]
149149
# Enable `rustix::process::*`.
150150
process = ["linux-raw-sys/prctl"]
151151

152+
# Enable `rustix::shm::*`.
153+
shm = ["fs"]
154+
152155
# Enable `rustix::time::*`.
153156
time = []
154157

@@ -198,6 +201,7 @@ all-apis = [
198201
"pty",
199202
"rand",
200203
"runtime",
204+
"shm",
201205
"system",
202206
"stdio",
203207
"termios",

src/backend/libc/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ pub(crate) mod pid;
184184
#[cfg(any(feature = "process", feature = "thread"))]
185185
#[cfg(linux_kernel)]
186186
pub(crate) mod prctl;
187+
#[cfg(not(any(
188+
windows,
189+
target_os = "android",
190+
target_os = "espidf",
191+
target_os = "wasi"
192+
)))]
193+
#[cfg(feature = "shm")]
194+
pub(crate) mod shm;
187195
#[cfg(any(feature = "fs", feature = "thread", feature = "process"))]
188196
#[cfg(not(any(windows, target_os = "wasi")))]
189197
pub(crate) mod ugid;

src/backend/libc/shm/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub(crate) mod syscalls;
2+
pub(crate) mod types;

src/backend/libc/shm/syscalls.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use crate::ffi::CStr;
2+
3+
use crate::backend::c;
4+
use crate::backend::conv::{c_str, ret, ret_owned_fd};
5+
use crate::fd::OwnedFd;
6+
use crate::fs::Mode;
7+
use crate::io;
8+
use crate::shm::ShmOFlags;
9+
10+
pub(crate) fn shm_open(name: &CStr, oflags: ShmOFlags, mode: Mode) -> io::Result<OwnedFd> {
11+
// On this platforms, `mode_t` is `u16` and can't be passed directly to a
12+
// variadic function.
13+
#[cfg(apple)]
14+
let mode: c::c_uint = mode.bits().into();
15+
16+
// Otherwise, cast to `mode_t` as that's what `open` is documented to take.
17+
#[cfg(not(apple))]
18+
let mode: c::mode_t = mode.bits() as _;
19+
20+
unsafe { ret_owned_fd(c::shm_open(c_str(name), bitflags_bits!(oflags), mode)) }
21+
}
22+
23+
pub(crate) fn shm_unlink(name: &CStr) -> io::Result<()> {
24+
unsafe { ret(c::shm_unlink(c_str(name))) }
25+
}

src/backend/libc/shm/types.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::backend::c;
2+
use bitflags::bitflags;
3+
4+
bitflags! {
5+
/// `O_*` constants for use with [`shm_open`].
6+
///
7+
/// [`shm_open`]: crate:shm::shm_open
8+
#[repr(transparent)]
9+
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
10+
pub struct ShmOFlags: u32 {
11+
/// `O_CREAT`
12+
#[doc(alias = "CREAT")]
13+
const CREATE = bitcast!(c::O_CREAT);
14+
15+
/// `O_EXCL`
16+
const EXCL = bitcast!(c::O_EXCL);
17+
18+
/// `O_RDONLY`
19+
const RDONLY = bitcast!(c::O_RDONLY);
20+
21+
/// `O_RDWR`
22+
const RDWR = bitcast!(c::O_RDWR);
23+
24+
/// `O_TRUNC`
25+
const TRUNC = bitcast!(c::O_TRUNC);
26+
27+
/// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
28+
const _ = !0;
29+
}
30+
}

src/backend/linux_raw/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ pub(crate) mod pty;
6767
pub(crate) mod rand;
6868
#[cfg(feature = "runtime")]
6969
pub(crate) mod runtime;
70+
#[cfg(feature = "shm")]
71+
pub(crate) mod shm;
7072
#[cfg(feature = "system")]
7173
pub(crate) mod system;
7274
#[cfg(feature = "termios")]

src/backend/linux_raw/shm/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub(crate) mod syscalls;
2+
pub(crate) mod types;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use crate::ffi::CStr;
2+
3+
use crate::backend::fs::{
4+
syscalls::{open, unlink},
5+
types::{Mode, OFlags},
6+
};
7+
use crate::fd::OwnedFd;
8+
use crate::io;
9+
use crate::shm::ShmOFlags;
10+
11+
const NAME_MAX: usize = 255;
12+
const SHM_DIR: &[u8] = b"/dev/shm/";
13+
14+
fn get_shm_name(name: &CStr) -> io::Result<([u8; NAME_MAX + SHM_DIR.len() + 1], usize)> {
15+
let name = name.to_bytes();
16+
17+
if name.len() > NAME_MAX {
18+
return Err(io::Errno::NAMETOOLONG);
19+
}
20+
21+
let num_slashes = name.into_iter().take_while(|x| **x == b'/').count();
22+
let after_slashes = &name[num_slashes..];
23+
if after_slashes.is_empty()
24+
|| after_slashes == b"."
25+
|| after_slashes == b".."
26+
|| after_slashes.contains(&b'/')
27+
{
28+
return Err(io::Errno::INVAL);
29+
}
30+
31+
let mut path = [0; NAME_MAX + SHM_DIR.len() + 1];
32+
path[..SHM_DIR.len()].copy_from_slice(SHM_DIR);
33+
path[SHM_DIR.len()..SHM_DIR.len() + name.len()].copy_from_slice(name);
34+
Ok((path, SHM_DIR.len() + name.len() + 1))
35+
}
36+
37+
pub(crate) fn shm_open(name: &CStr, oflags: ShmOFlags, mode: Mode) -> io::Result<OwnedFd> {
38+
let (path, len) = get_shm_name(name)?;
39+
open(
40+
CStr::from_bytes_with_nul(&path[..len]).unwrap(),
41+
OFlags::from_bits(oflags.bits()).unwrap() | OFlags::CLOEXEC,
42+
mode,
43+
)
44+
}
45+
46+
pub(crate) fn shm_unlink(name: &CStr) -> io::Result<()> {
47+
let (path, len) = get_shm_name(name)?;
48+
unlink(CStr::from_bytes_with_nul(&path[..len]).unwrap())
49+
}

src/backend/linux_raw/shm/types.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::backend::c;
2+
use bitflags::bitflags;
3+
4+
bitflags! {
5+
/// `O_*` constants for use with [`shm_open`].
6+
///
7+
/// [`shm_open`]: crate:shm::shm_open
8+
#[repr(transparent)]
9+
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
10+
pub struct ShmOFlags: c::c_uint {
11+
/// `O_CREAT`
12+
#[doc(alias = "CREAT")]
13+
const CREATE = linux_raw_sys::general::O_CREAT;
14+
15+
/// `O_EXCL`
16+
const EXCL = linux_raw_sys::general::O_EXCL;
17+
18+
/// `O_RDONLY`
19+
const RDONLY = linux_raw_sys::general::O_RDONLY;
20+
21+
/// `O_RDWR`
22+
const RDWR = linux_raw_sys::general::O_RDWR;
23+
24+
/// `O_TRUNC`
25+
const TRUNC = linux_raw_sys::general::O_TRUNC;
26+
27+
/// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
28+
const _ = !0;
29+
}
30+
}

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ pub mod pty;
246246
#[cfg(feature = "rand")]
247247
#[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
248248
pub mod rand;
249+
#[cfg(not(any(
250+
windows,
251+
target_os = "android",
252+
target_os = "espidf",
253+
target_os = "wasi"
254+
)))]
255+
#[cfg(feature = "shm")]
256+
pub mod shm;
249257
#[cfg(not(windows))]
250258
#[cfg(feature = "stdio")]
251259
#[cfg_attr(doc_cfg, doc(cfg(feature = "stdio")))]

0 commit comments

Comments
 (0)