Implement creation of SysV IPC message queues
This adds the `sysvmq` package which handles SysV IPC message queues. For consistency the parameter for `permissions` is renamed to `mode` also for POSIX message queues.
This commit is contained in:
commit
060b6ac88d
3 changed files with 125 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "sysvmq"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
authors = ["finga <mqrs@onders.org>"]
|
||||||
|
repository = "https://git.onders.org/finga/mqrs"
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.98"
|
||||||
|
thiserror = "1.0.26"
|
||||||
|
nix = "0.21.0"
|
111
src/lib.rs
Normal file
111
src/lib.rs
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
use libc::{
|
||||||
|
msgget, IPC_CREAT, IPC_EXCL, IPC_INFO, IPC_NOWAIT, IPC_PRIVATE, IPC_RMID, IPC_SET, IPC_STAT,
|
||||||
|
MSG_COPY, MSG_EXCEPT, MSG_INFO, MSG_NOERROR, MSG_STAT,
|
||||||
|
};
|
||||||
|
use nix::errno::{errno, Errno};
|
||||||
|
use std::{marker::PhantomData, num::ParseIntError};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum SysvMqError {
|
||||||
|
#[error("SysV message queue: {0}")]
|
||||||
|
ErrnoError(&'static str),
|
||||||
|
#[error("No message queue found with key {0}")]
|
||||||
|
KeyNotFound(i32),
|
||||||
|
#[error("IO Error: {0}")]
|
||||||
|
IoError(#[from] std::io::Error),
|
||||||
|
#[error("Parse Error: {0}")]
|
||||||
|
ParserError(#[from] ParseIntError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// IPC bit flags
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum Flags {
|
||||||
|
/// Create key if key does not exist.
|
||||||
|
CreateKey = IPC_CREAT,
|
||||||
|
/// Fail if key exists.
|
||||||
|
Exclusive = IPC_EXCL,
|
||||||
|
/// Return error on wait.
|
||||||
|
NoWait = IPC_NOWAIT,
|
||||||
|
/// No error if message is too big.
|
||||||
|
NoError = MSG_NOERROR,
|
||||||
|
/// Receive any message except of specified type.
|
||||||
|
Except = MSG_EXCEPT,
|
||||||
|
/// Copy (not remove) all queue messages.
|
||||||
|
Copy = MSG_COPY,
|
||||||
|
/// Private key (Special key value).
|
||||||
|
Private = IPC_PRIVATE,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Commands for `msgctl()`
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum ControlCommands {
|
||||||
|
/// Remove identifier (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||||
|
Remove = IPC_RMID,
|
||||||
|
/// Set `ipc_perm` options (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||||
|
SetPerm = IPC_SET,
|
||||||
|
/// Get `ipc_perm` options (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||||
|
GetPerm = IPC_STAT,
|
||||||
|
/// See ipcs (Control command for `msgctl`, `semctl`, and `shmctl`).
|
||||||
|
IpcInfo = IPC_INFO,
|
||||||
|
/// IPCS control command.
|
||||||
|
Stat = MSG_STAT,
|
||||||
|
/// IPCS control command.
|
||||||
|
MsgInfo = MSG_INFO,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SysvMq<T> {
|
||||||
|
pub id: i32,
|
||||||
|
pub key: i32,
|
||||||
|
message_mask: i32,
|
||||||
|
mode: i32,
|
||||||
|
types: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> SysvMq<T> {
|
||||||
|
pub fn create(&mut self, key: i32) -> Result<&Self, SysvMqError> {
|
||||||
|
self.key = key;
|
||||||
|
self.id = unsafe { msgget(self.key, Flags::CreateKey as i32 | self.mode) };
|
||||||
|
|
||||||
|
match self.id {
|
||||||
|
-1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())),
|
||||||
|
_ => Ok(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(mut self, key: i32) -> Result<Self, SysvMqError> {
|
||||||
|
self.key = key;
|
||||||
|
self.id = unsafe { msgget(self.key, self.mode) };
|
||||||
|
|
||||||
|
match self.id {
|
||||||
|
-1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())),
|
||||||
|
_ => Ok(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode(&mut self, mode: i32) -> &Self {
|
||||||
|
self.mode = mode;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nonblocking(&mut self) -> &Self {
|
||||||
|
self.message_mask |= Flags::NoWait as i32;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
SysvMq {
|
||||||
|
id: -1,
|
||||||
|
key: 0,
|
||||||
|
message_mask: 0,
|
||||||
|
mode: 0o644,
|
||||||
|
types: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for SysvMq<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue