11//! Posix Message Queue functions
22//!
3+ //! # Example
4+ //!
5+ // no_run because a kernel module may be required.
6+ //! ```no_run
7+ //! # use std::ffi::CString;
8+ //! # use nix::mqueue::*;
9+ //! use nix::sys::stat::Mode;
10+ //!
11+ //! const MSG_SIZE: mq_attr_member_t = 32;
12+ //! let mq_name= CString::new("/a_nix_test_queue").unwrap();
13+ //!
14+ //! let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
15+ //! let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
16+ //! let mqd0 = mq_open(&mq_name, oflag0, mode, None).unwrap();
17+ //! let msg_to_send = b"msg_1";
18+ //! mq_send(&mqd0, msg_to_send, 1).unwrap();
19+ //!
20+ //! let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY;
21+ //! let mqd1 = mq_open(&mq_name, oflag1, mode, None).unwrap();
22+ //! let mut buf = [0u8; 32];
23+ //! let mut prio = 0u32;
24+ //! let len = mq_receive(&mqd1, &mut buf, &mut prio).unwrap();
25+ //! assert_eq!(prio, 1);
26+ //! assert_eq!(msg_to_send, &buf[0..len]);
27+ //!
28+ //! mq_close(mqd1).unwrap();
29+ //! mq_close(mqd0).unwrap();
30+ //! ```
331//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
432
533use crate :: Result ;
634use crate :: errno:: Errno ;
735
836use libc:: { self , c_char, mqd_t, size_t} ;
9- use std:: ffi:: CString ;
37+ use std:: ffi:: CStr ;
1038use crate :: sys:: stat:: Mode ;
1139use std:: mem;
1240
@@ -34,6 +62,14 @@ pub struct MqAttr {
3462 mq_attr : libc:: mq_attr ,
3563}
3664
65+ /// Identifies an open POSIX Message Queue
66+ // A safer wrapper around libc::mqd_t, which is a pointer on some platforms
67+ // Deliberately is not Clone to prevent use-after-close scenarios
68+ #[ repr( transparent) ]
69+ #[ derive( Debug ) ]
70+ #[ allow( missing_copy_implementations) ]
71+ pub struct MqdT ( mqd_t ) ;
72+
3773// x32 compatibility
3874// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
3975#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "32" ) ) ]
@@ -87,11 +123,11 @@ impl MqAttr {
87123/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
88124// The mode.bits cast is only lossless on some OSes
89125#[ allow( clippy:: cast_lossless) ]
90- pub fn mq_open ( name : & CString ,
126+ pub fn mq_open ( name : & CStr ,
91127 oflag : MQ_OFlag ,
92128 mode : Mode ,
93129 attr : Option < & MqAttr > )
94- -> Result < mqd_t > {
130+ -> Result < MqdT > {
95131 let res = match attr {
96132 Some ( mq_attr) => unsafe {
97133 libc:: mq_open ( name. as_ptr ( ) ,
@@ -101,32 +137,32 @@ pub fn mq_open(name: &CString,
101137 } ,
102138 None => unsafe { libc:: mq_open ( name. as_ptr ( ) , oflag. bits ( ) ) } ,
103139 } ;
104- Errno :: result ( res)
140+ Errno :: result ( res) . map ( MqdT )
105141}
106142
107143/// Remove a message queue
108144///
109145/// See also [`mq_unlink(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
110- pub fn mq_unlink ( name : & CString ) -> Result < ( ) > {
146+ pub fn mq_unlink ( name : & CStr ) -> Result < ( ) > {
111147 let res = unsafe { libc:: mq_unlink ( name. as_ptr ( ) ) } ;
112148 Errno :: result ( res) . map ( drop)
113149}
114150
115151/// Close a message queue
116152///
117153/// See also [`mq_close(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
118- pub fn mq_close ( mqdes : mqd_t ) -> Result < ( ) > {
119- let res = unsafe { libc:: mq_close ( mqdes) } ;
154+ pub fn mq_close ( mqdes : MqdT ) -> Result < ( ) > {
155+ let res = unsafe { libc:: mq_close ( mqdes. 0 ) } ;
120156 Errno :: result ( res) . map ( drop)
121157}
122158
123159/// Receive a message from a message queue
124160///
125161/// See also [`mq_receive(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
126- pub fn mq_receive ( mqdes : mqd_t , message : & mut [ u8 ] , msg_prio : & mut u32 ) -> Result < usize > {
162+ pub fn mq_receive ( mqdes : & MqdT , message : & mut [ u8 ] , msg_prio : & mut u32 ) -> Result < usize > {
127163 let len = message. len ( ) as size_t ;
128164 let res = unsafe {
129- libc:: mq_receive ( mqdes,
165+ libc:: mq_receive ( mqdes. 0 ,
130166 message. as_mut_ptr ( ) as * mut c_char ,
131167 len,
132168 msg_prio as * mut u32 )
@@ -137,9 +173,9 @@ pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Resul
137173/// Send a message to a message queue
138174///
139175/// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
140- pub fn mq_send ( mqdes : mqd_t , message : & [ u8 ] , msq_prio : u32 ) -> Result < ( ) > {
176+ pub fn mq_send ( mqdes : & MqdT , message : & [ u8 ] , msq_prio : u32 ) -> Result < ( ) > {
141177 let res = unsafe {
142- libc:: mq_send ( mqdes,
178+ libc:: mq_send ( mqdes. 0 ,
143179 message. as_ptr ( ) as * const c_char ,
144180 message. len ( ) ,
145181 msq_prio)
@@ -150,9 +186,9 @@ pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
150186/// Get message queue attributes
151187///
152188/// See also [`mq_getattr(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
153- pub fn mq_getattr ( mqd : mqd_t ) -> Result < MqAttr > {
189+ pub fn mq_getattr ( mqd : & MqdT ) -> Result < MqAttr > {
154190 let mut attr = mem:: MaybeUninit :: < libc:: mq_attr > :: uninit ( ) ;
155- let res = unsafe { libc:: mq_getattr ( mqd, attr. as_mut_ptr ( ) ) } ;
191+ let res = unsafe { libc:: mq_getattr ( mqd. 0 , attr. as_mut_ptr ( ) ) } ;
156192 Errno :: result ( res) . map ( |_| unsafe { MqAttr { mq_attr : attr. assume_init ( ) } } )
157193}
158194
@@ -161,10 +197,10 @@ pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
161197/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
162198///
163199/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
164- pub fn mq_setattr ( mqd : mqd_t , newattr : & MqAttr ) -> Result < MqAttr > {
200+ pub fn mq_setattr ( mqd : & MqdT , newattr : & MqAttr ) -> Result < MqAttr > {
165201 let mut attr = mem:: MaybeUninit :: < libc:: mq_attr > :: uninit ( ) ;
166202 let res = unsafe {
167- libc:: mq_setattr ( mqd, & newattr. mq_attr as * const libc:: mq_attr , attr. as_mut_ptr ( ) )
203+ libc:: mq_setattr ( mqd. 0 , & newattr. mq_attr as * const libc:: mq_attr , attr. as_mut_ptr ( ) )
168204 } ;
169205 Errno :: result ( res) . map ( |_| unsafe { MqAttr { mq_attr : attr. assume_init ( ) } } )
170206}
@@ -173,7 +209,7 @@ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
173209/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
174210/// Returns the old attributes
175211#[ allow( clippy:: useless_conversion) ] // Not useless on all OSes
176- pub fn mq_set_nonblock ( mqd : mqd_t ) -> Result < MqAttr > {
212+ pub fn mq_set_nonblock ( mqd : & MqdT ) -> Result < MqAttr > {
177213 let oldattr = mq_getattr ( mqd) ?;
178214 let newattr = MqAttr :: new ( mq_attr_member_t:: from ( MQ_OFlag :: O_NONBLOCK . bits ( ) ) ,
179215 oldattr. mq_attr . mq_maxmsg ,
@@ -185,7 +221,7 @@ pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
185221/// Convenience function.
186222/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
187223/// Returns the old attributes
188- pub fn mq_remove_nonblock ( mqd : mqd_t ) -> Result < MqAttr > {
224+ pub fn mq_remove_nonblock ( mqd : & MqdT ) -> Result < MqAttr > {
189225 let oldattr = mq_getattr ( mqd) ?;
190226 let newattr = MqAttr :: new ( 0 ,
191227 oldattr. mq_attr . mq_maxmsg ,
0 commit comments