Skip to content

Commit

Permalink
Add shm_open/shm_unlink (POSIX shared memory)
Browse files Browse the repository at this point in the history
Fixes #705.
  • Loading branch information
ids1024 committed Sep 26, 2023
1 parent b08519f commit b4f2bf9
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 12 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ thread = ["linux-raw-sys/prctl"]
# Enable `rustix::process::*`.
process = ["linux-raw-sys/prctl"]

# Enable `rustix::shm::*`.
shm = []

# Enable `rustix::time::*`.
time = []

Expand Down
2 changes: 1 addition & 1 deletion src/backend/libc/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub(super) fn ret_usize(raw: c::ssize_t) -> io::Result<usize> {
}

#[cfg(not(windows))]
#[cfg(feature = "fs")]
#[cfg(any(feature = "fs", feature = "shm"))]
#[inline]
pub(super) fn ret_off_t(raw: c::off_t) -> io::Result<c::off_t> {
if raw == -1 {
Expand Down
4 changes: 3 additions & 1 deletion src/backend/libc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub(crate) mod c;
#[cfg(feature = "event")]
pub(crate) mod event;
#[cfg(not(windows))]
#[cfg(feature = "fs")]
#[cfg(any(feature = "fs", feature = "shm"))]
pub(crate) mod fs;
pub(crate) mod io;
#[cfg(linux_kernel)]
Expand Down Expand Up @@ -184,6 +184,8 @@ pub(crate) mod pid;
#[cfg(any(feature = "process", feature = "thread"))]
#[cfg(linux_kernel)]
pub(crate) mod prctl;
#[cfg(feature = "shm")]
pub(crate) mod shm;
#[cfg(any(feature = "fs", feature = "thread", feature = "process"))]
#[cfg(not(any(windows, target_os = "wasi")))]
pub(crate) mod ugid;
Expand Down
1 change: 1 addition & 0 deletions src/backend/libc/shm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod syscalls;
28 changes: 28 additions & 0 deletions src/backend/libc/shm/syscalls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use std::ffi::CStr;

use crate::backend::c;
use crate::backend::conv::{c_str, ret, ret_owned_fd};
use crate::fd::OwnedFd;
use crate::fs::{Mode, OFlags};
use crate::io;

#[cfg(not(any(target_os = "android", target_os = "espidf", target_os = "wasi")))]
pub(crate) fn shm_open(name: &CStr, oflags: OFlags, mode: Mode) -> io::Result<OwnedFd> {
// On this platforms, `mode_t` is `u16` and can't be passed directly to a
// variadic function.
#[cfg(apple)]
let mode: c::c_uint = mode.bits().into();

// Otherwise, cast to `mode_t` as that's what `open` is documented to take.
#[cfg(not(apple))]
let mode: c::mode_t = mode.bits() as _;

unsafe { ret_owned_fd(c::shm_open(c_str(name), bitflags_bits!(oflags), mode)) }
}

#[cfg(not(any(target_os = "android", target_os = "espidf", target_os = "wasi")))]
pub(crate) fn shm_unlink(name: &CStr) -> io::Result<()> {
unsafe { ret(c::shm_unlink(c_str(name))) }
}


1 change: 1 addition & 0 deletions src/backend/linux_raw/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub(crate) use linux_raw_sys::general::epoll_event;

#[cfg(any(
feature = "fs",
feature = "shm",
all(
not(feature = "use-libc-auxv"),
not(feature = "use-explicitly-provided-auxv"),
Expand Down
1 change: 1 addition & 0 deletions src/backend/linux_raw/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> {

#[cfg(any(
feature = "fs",
feature = "shm",
all(
not(feature = "use-libc-auxv"),
not(feature = "use-explicitly-provided-auxv"),
Expand Down
4 changes: 4 additions & 0 deletions src/backend/linux_raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod vdso_wrappers;
pub(crate) mod event;
#[cfg(any(
feature = "fs",
feature = "shm",
all(
not(feature = "use-libc-auxv"),
not(feature = "use-explicitly-provided-auxv"),
Expand Down Expand Up @@ -67,6 +68,8 @@ pub(crate) mod pty;
pub(crate) mod rand;
#[cfg(feature = "runtime")]
pub(crate) mod runtime;
#[cfg(feature = "shm")]
pub(crate) mod shm;
#[cfg(feature = "system")]
pub(crate) mod system;
#[cfg(feature = "termios")]
Expand Down Expand Up @@ -94,6 +97,7 @@ pub(crate) mod prctl;
#[cfg(any(
feature = "fs",
feature = "process",
feature = "shm",
feature = "thread",
all(
not(feature = "use-libc-auxv"),
Expand Down
1 change: 1 addition & 0 deletions src/backend/linux_raw/shm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod syscalls;
48 changes: 48 additions & 0 deletions src/backend/linux_raw/shm/syscalls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use std::ffi::CStr;

use crate::fd::OwnedFd;
use crate::backend::fs::{
syscalls::{open, unlink},
types::{Mode, OFlags},
};
use crate::io;

const NAME_MAX: usize = 255;
const SHM_DIR: &[u8] = b"/dev/shm/";

fn get_shm_name(name: &CStr) -> io::Result<([u8; NAME_MAX + SHM_DIR.len() + 1], usize)> {
let name = name.to_bytes();

if name.len() > NAME_MAX {
return Err(io::Errno::NAMETOOLONG);
}

let num_slashes = name.into_iter().take_while(|x| **x == b'/').count();
let after_slashes = &name[num_slashes..];
if after_slashes.is_empty()
|| after_slashes == b"."
|| after_slashes == b".."
|| after_slashes.contains(&b'/')
{
return Err(io::Errno::INVAL);
}

let mut path = [0; NAME_MAX + SHM_DIR.len() + 1];
path[..SHM_DIR.len()].copy_from_slice(SHM_DIR);
path[SHM_DIR.len()..SHM_DIR.len() + name.len()].copy_from_slice(name);
Ok((path, SHM_DIR.len() + name.len() + 1))
}

pub(crate) fn shm_open(name: &CStr, oflags: OFlags, mode: Mode) -> io::Result<OwnedFd> {
let (path, len) = get_shm_name(name)?;
open(
CStr::from_bytes_with_nul(&path[..len]).unwrap(),
oflags,
mode,
)
}

pub(crate) fn shm_unlink(name: &CStr) -> io::Result<()> {
let (path, len) = get_shm_name(name)?;
unlink(CStr::from_bytes_with_nul(&path[..len]).unwrap())
}
28 changes: 18 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ pub mod net;
#[cfg_attr(doc_cfg, doc(cfg(feature = "param")))]
pub mod param;
#[cfg(not(windows))]
#[cfg(any(feature = "fs", feature = "mount", feature = "net"))]
#[cfg(any(feature = "fs", feature = "mount", feature = "net", feature = "shm"))]
#[cfg_attr(
doc_cfg,
doc(cfg(any(feature = "fs", feature = "mount", feature = "net")))
Expand All @@ -246,6 +246,9 @@ pub mod pty;
#[cfg(feature = "rand")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
pub mod rand;
#[cfg(not(any(target_os = "android", target_os = "espidf", target_os = "wasi")))]
#[cfg(feature = "shm")]
pub mod shm;
#[cfg(not(windows))]
#[cfg(feature = "stdio")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "stdio")))]
Expand Down Expand Up @@ -285,15 +288,18 @@ pub(crate) mod mount;
// reading procfs.
#[cfg(not(windows))]
#[cfg(not(feature = "fs"))]
#[cfg(all(
linux_raw,
not(feature = "use-libc-auxv"),
not(feature = "use-explicitly-provided-auxv"),
any(
feature = "param",
feature = "runtime",
feature = "time",
target_arch = "x86",
#[cfg(any(
feature = "shm",
all(
linux_raw,
not(feature = "use-libc-auxv"),
not(feature = "use-explicitly-provided-auxv"),
any(
feature = "param",
feature = "runtime",
feature = "time",
target_arch = "x86",
)
)
))]
#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))]
Expand Down Expand Up @@ -339,6 +345,7 @@ mod signal;
#[cfg(any(
feature = "fs",
feature = "runtime",
feature = "shm",
feature = "thread",
feature = "time",
all(
Expand All @@ -358,6 +365,7 @@ mod timespec;
#[cfg(any(
feature = "fs",
feature = "process",
feature = "shm",
feature = "thread",
all(
linux_raw,
Expand Down
34 changes: 34 additions & 0 deletions src/shm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! POSIX shared memory
use crate::backend::fs::types::{Mode, OFlags};
use crate::fd::OwnedFd;
use crate::{backend, io, path};

/// `shm_open(name, oflags, mode)`—Opens a shared memory object.
///
/// For portability, `name` should begin with a slash, contain no other slashes,
/// and be no longer than an implementation-defined limit (255 on Linux).
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html
/// [Linux]: https://man7.org/linux/man-pages/man3/shm_open.3.html
#[inline]
pub fn shm_open<P: path::Arg>(name: P, flags: OFlags, mode: Mode) -> io::Result<OwnedFd> {
name.into_with_c_str(|name| backend::shm::syscalls::shm_open(name, flags, mode))
}

/// `shm_unlink(name)`—Unlinks a shared memory object.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_unlink.html
/// [Linux]: https://man7.org/linux/man-pages/man3/shm_unlink.3.html
#[inline]
pub fn shm_unlink<P: path::Arg>(name: P) -> io::Result<()> {
name.into_with_c_str(|name| backend::shm::syscalls::shm_unlink(name))
}

0 comments on commit b4f2bf9

Please sign in to comment.