From cc19087195e332ff7a30e2d909db6c7062b773d3 Mon Sep 17 00:00:00 2001 From: finga Date: Wed, 7 Jul 2021 20:48:07 +0200 Subject: [PATCH] Implement deletion of SysV IPC message queues As usual also the readme and the man page are updated. --- README.md | 8 +++++++- mqrs.1 | 35 +++++++++++++++++++++++++++++++++-- src/main.rs | 2 ++ src/sysv.rs | 2 ++ src/sysv/unlink.rs | 35 +++++++++++++++++++++++++++++++++++ sysvmq/src/lib.rs | 27 ++++++++++++++++++++++++--- 6 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 src/sysv/unlink.rs diff --git a/README.md b/README.md index 4f82cfa..e7251f7 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,16 @@ queue. Following optional arguments are supported: - `-o,` `--timeout `: As for example in "5h 23min 42ms" ### SysV IPC message queues -The SysV IPC backend supports one command: `create`. +The SysV IPC backend supports two commands: `create` and `unlink`. #### Create a message queue Use the `create` command to create a new SysV IPC message queue. Following optional arguments are supported: - `-m`, `--mode`: Permissions (octal) to create the queue with. Default: 0644. + +#### Delete a message queue +Use the `unlink` command to delete a message queue. This can either be +done by providing a `key` or an `id` of the queue: +- `-i`, `--id `: Id of the queue +- `-k`, `--key `: Key of the queue diff --git a/mqrs.1 b/mqrs.1 index 0058957..eb7b912 100644 --- a/mqrs.1 +++ b/mqrs.1 @@ -192,7 +192,7 @@ Set a different priority than default, priority >= 0 [default: 0] Timeout as for example in "5h 23min 42ms" .RE .SS unlink [FLAGS] \fI\fP -Deletes an existing POSIX message queue. +Delete an existing POSIX message queue. .TP 8 .SS ARGS .RS @@ -211,8 +211,10 @@ Prints help information Produce verbose output .RE .SH SYSV IPC MESSAGE QUEUE SUBCOMMANDS -The SysV IPC backend supports one command: +The SysV IPC backend supports two commands: .B create\ +and +.B unlink\ . .SS create [FLAGS] [OPTIONS] \fI\fP Create a new SysV IPC message queue. @@ -239,6 +241,35 @@ Produce verbose output .B \-m, \-\-mode \fI\fP Permissions (octal) to create the queue with (default: 0644) .RE +.SS unlink [FLAGS] [OPTIONS] +Delete an existing SysV IPC message queue. It is mandatory to pass +exactly one OPTION. +.TP 8 +.SS ARGS +.RS +.TP 8 +.B \fI\fP +Key of the new queue +.RE +.TP 8 +.SS FLAGS +.RS +.TP 8 +.B \-h, \-\-help +Prints help information +.TP 8 +.B \-v, \-\-verbose +Produce verbose output +.TP 8 +.SS OPTIONS +.RS +.TP 8 +.B \-i, \-\-id \fI\fP +Id of the queue +.TP 8 +.B \-k, \-\-key \fI\fP +Key of the queue +.RE .SH SEE ALSO mq_overview(7) .SH BUGS diff --git a/src/main.rs b/src/main.rs index 78109dd..5e4db83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ enum PosixCommand { #[derive(Clap, Debug)] enum SysvCommand { Create(sysv::Create), + Unlink(sysv::Unlink), } #[derive(Clap, Debug)] @@ -68,6 +69,7 @@ fn main() -> Result<()> { }, Backend::Sysv(s) => match s { SysvCommand::Create(c) => c.run()?, + SysvCommand::Unlink(u) => u.run()?, }, } diff --git a/src/sysv.rs b/src/sysv.rs index 5ed245c..91ee1a5 100644 --- a/src/sysv.rs +++ b/src/sysv.rs @@ -1,3 +1,5 @@ mod create; +mod unlink; pub use create::Create; +pub use unlink::Unlink; diff --git a/src/sysv/unlink.rs b/src/sysv/unlink.rs new file mode 100644 index 0000000..277edb6 --- /dev/null +++ b/src/sysv/unlink.rs @@ -0,0 +1,35 @@ +use anyhow::Result; +use clap::Clap; +use log::info; + +/// Delete a message queue +#[derive(Clap, Debug)] +pub struct Unlink { + /// Id of the queue + #[clap( + long, + short, + required_unless_present_any = &["key"], + conflicts_with = "key" + )] + pub id: Option, + /// Key of the queue + #[clap(long, short, required_unless_present_any = &["id"], conflicts_with = "id")] + pub key: Option, +} + +impl Unlink { + pub fn run(&self) -> Result<()> { + if let Some(id) = self.id { + sysvmq::unlink_id(id)?; + + info!("Removed message queue with id: {}", id); + } else if let Some(key) = self.key { + sysvmq::unlink_key(key)?; + + info!("Removed message queue key: {}", key); + } + + Ok(()) + } +} diff --git a/sysvmq/src/lib.rs b/sysvmq/src/lib.rs index 7f7e4e3..bb2c21d 100644 --- a/sysvmq/src/lib.rs +++ b/sysvmq/src/lib.rs @@ -1,9 +1,9 @@ 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, + msgctl, msgget, msqid_ds, 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 std::{marker::PhantomData, num::ParseIntError, ptr}; use thiserror::Error; #[derive(Debug, Error)] @@ -54,6 +54,27 @@ pub enum ControlCommands { MsgInfo = MSG_INFO, } +pub fn unlink_id(id: i32) -> Result<(), SysvMqError> { + let res = unsafe { + msgctl( + id, + ControlCommands::Remove as i32, + ptr::null::() as *mut msqid_ds, + ) + }; + + match res { + -1 => Err(SysvMqError::ErrnoError(Errno::from_i32(errno()).desc())), + _ => Ok(()), + } +} + +pub fn unlink_key(key: i32) -> Result<(), SysvMqError> { + let id = unsafe { msgget(key, 0) }; + + unlink_id(id) +} + pub struct SysvMq { pub id: i32, pub key: i32,