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 28, 2023
1 parent 77c4aae commit 6050931
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 0 deletions.
4 changes: 4 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 = ["fs"]

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

Expand Down Expand Up @@ -198,6 +201,7 @@ all-apis = [
"pty",
"rand",
"runtime",
"shm",
"system",
"stdio",
"termios",
Expand Down
8 changes: 8 additions & 0 deletions src/backend/libc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ pub(crate) mod pid;
#[cfg(any(feature = "process", feature = "thread"))]
#[cfg(linux_kernel)]
pub(crate) mod prctl;
#[cfg(not(any(
windows,
target_os = "android",
target_os = "espidf",
target_os = "wasi"
)))]
#[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
2 changes: 2 additions & 0 deletions src/backend/libc/shm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub(crate) mod syscalls;
pub(crate) mod types;
25 changes: 25 additions & 0 deletions src/backend/libc/shm/syscalls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::ffi::CStr;

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

pub(crate) fn shm_open(name: &CStr, oflags: ShmOFlags, 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)) }
}

pub(crate) fn shm_unlink(name: &CStr) -> io::Result<()> {
unsafe { ret(c::shm_unlink(c_str(name))) }
}
30 changes: 30 additions & 0 deletions src/backend/libc/shm/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::backend::c;
use bitflags::bitflags;

bitflags! {
/// `O_*` constants for use with [`shm_open`].
///
/// [`shm_open`]: crate:shm::shm_open
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct ShmOFlags: u32 {
/// `O_CREAT`
#[doc(alias = "CREAT")]
const CREATE = bitcast!(c::O_CREAT);

/// `O_EXCL`
const EXCL = bitcast!(c::O_EXCL);

/// `O_RDONLY`
const RDONLY = bitcast!(c::O_RDONLY);

/// `O_RDWR`
const RDWR = bitcast!(c::O_RDWR);

/// `O_TRUNC`
const TRUNC = bitcast!(c::O_TRUNC);

/// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
const _ = !0;
}
}
2 changes: 2 additions & 0 deletions src/backend/linux_raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,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
2 changes: 2 additions & 0 deletions src/backend/linux_raw/shm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub(crate) mod syscalls;
pub(crate) mod types;
49 changes: 49 additions & 0 deletions src/backend/linux_raw/shm/syscalls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::ffi::CStr;

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

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: ShmOFlags, mode: Mode) -> io::Result<OwnedFd> {
let (path, len) = get_shm_name(name)?;
open(
CStr::from_bytes_with_nul(&path[..len]).unwrap(),
OFlags::from_bits(oflags.bits()).unwrap() | OFlags::CLOEXEC,
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())
}
30 changes: 30 additions & 0 deletions src/backend/linux_raw/shm/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::backend::c;
use bitflags::bitflags;

bitflags! {
/// `O_*` constants for use with [`shm_open`].
///
/// [`shm_open`]: crate:shm::shm_open
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct ShmOFlags: c::c_uint {
/// `O_CREAT`
#[doc(alias = "CREAT")]
const CREATE = linux_raw_sys::general::O_CREAT;

/// `O_EXCL`
const EXCL = linux_raw_sys::general::O_EXCL;

/// `O_RDONLY`
const RDONLY = linux_raw_sys::general::O_RDONLY;

/// `O_RDWR`
const RDWR = linux_raw_sys::general::O_RDWR;

/// `O_TRUNC`
const TRUNC = linux_raw_sys::general::O_TRUNC;

/// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
const _ = !0;
}
}
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ pub mod pty;
#[cfg(feature = "rand")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))]
pub mod rand;
#[cfg(not(any(
windows,
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
39 changes: 39 additions & 0 deletions src/shm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//! POSIX shared memory
use crate::fd::OwnedFd;
use crate::{backend, io, path};

pub use crate::backend::fs::types::Mode;
pub use crate::backend::shm::types::ShmOFlags;

/// `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).
///
/// Exactly one of [ShmOFlags::RDONLY] and [ShmOFlags::RDWR] should be passed. The file
/// descriptor will be opened with `FD_CLOEXEC` set.
///
/// # 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: ShmOFlags, 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 6050931

Please sign in to comment.