1
1
//! Posix Message Queue functions
2
2
//!
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
+ //! ```
3
31
//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
4
32
5
33
use crate :: Result ;
6
34
use crate :: errno:: Errno ;
7
35
8
36
use libc:: { self , c_char, mqd_t, size_t} ;
9
- use std:: ffi:: CString ;
37
+ use std:: ffi:: CStr ;
10
38
use crate :: sys:: stat:: Mode ;
11
39
use std:: mem;
12
40
@@ -34,6 +62,14 @@ pub struct MqAttr {
34
62
mq_attr : libc:: mq_attr ,
35
63
}
36
64
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
+
37
73
// x32 compatibility
38
74
// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
39
75
#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "32" ) ) ]
@@ -87,11 +123,11 @@ impl MqAttr {
87
123
/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
88
124
// The mode.bits cast is only lossless on some OSes
89
125
#[ allow( clippy:: cast_lossless) ]
90
- pub fn mq_open ( name : & CString ,
126
+ pub fn mq_open ( name : & CStr ,
91
127
oflag : MQ_OFlag ,
92
128
mode : Mode ,
93
129
attr : Option < & MqAttr > )
94
- -> Result < mqd_t > {
130
+ -> Result < MqdT > {
95
131
let res = match attr {
96
132
Some ( mq_attr) => unsafe {
97
133
libc:: mq_open ( name. as_ptr ( ) ,
@@ -101,32 +137,32 @@ pub fn mq_open(name: &CString,
101
137
} ,
102
138
None => unsafe { libc:: mq_open ( name. as_ptr ( ) , oflag. bits ( ) ) } ,
103
139
} ;
104
- Errno :: result ( res)
140
+ Errno :: result ( res) . map ( MqdT )
105
141
}
106
142
107
143
/// Remove a message queue
108
144
///
109
145
/// 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 < ( ) > {
111
147
let res = unsafe { libc:: mq_unlink ( name. as_ptr ( ) ) } ;
112
148
Errno :: result ( res) . map ( drop)
113
149
}
114
150
115
151
/// Close a message queue
116
152
///
117
153
/// 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 ) } ;
120
156
Errno :: result ( res) . map ( drop)
121
157
}
122
158
123
159
/// Receive a message from a message queue
124
160
///
125
161
/// 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 > {
127
163
let len = message. len ( ) as size_t ;
128
164
let res = unsafe {
129
- libc:: mq_receive ( mqdes,
165
+ libc:: mq_receive ( mqdes. 0 ,
130
166
message. as_mut_ptr ( ) as * mut c_char ,
131
167
len,
132
168
msg_prio as * mut u32 )
@@ -137,9 +173,9 @@ pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Resul
137
173
/// Send a message to a message queue
138
174
///
139
175
/// 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 < ( ) > {
141
177
let res = unsafe {
142
- libc:: mq_send ( mqdes,
178
+ libc:: mq_send ( mqdes. 0 ,
143
179
message. as_ptr ( ) as * const c_char ,
144
180
message. len ( ) ,
145
181
msq_prio)
@@ -150,9 +186,9 @@ pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
150
186
/// Get message queue attributes
151
187
///
152
188
/// 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 > {
154
190
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 ( ) ) } ;
156
192
Errno :: result ( res) . map ( |_| unsafe { MqAttr { mq_attr : attr. assume_init ( ) } } )
157
193
}
158
194
@@ -161,10 +197,10 @@ pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
161
197
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
162
198
///
163
199
/// [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 > {
165
201
let mut attr = mem:: MaybeUninit :: < libc:: mq_attr > :: uninit ( ) ;
166
202
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 ( ) )
168
204
} ;
169
205
Errno :: result ( res) . map ( |_| unsafe { MqAttr { mq_attr : attr. assume_init ( ) } } )
170
206
}
@@ -173,7 +209,7 @@ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
173
209
/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
174
210
/// Returns the old attributes
175
211
#[ 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 > {
177
213
let oldattr = mq_getattr ( mqd) ?;
178
214
let newattr = MqAttr :: new ( mq_attr_member_t:: from ( MQ_OFlag :: O_NONBLOCK . bits ( ) ) ,
179
215
oldattr. mq_attr . mq_maxmsg ,
@@ -185,7 +221,7 @@ pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
185
221
/// Convenience function.
186
222
/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
187
223
/// 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 > {
189
225
let oldattr = mq_getattr ( mqd) ?;
190
226
let newattr = MqAttr :: new ( 0 ,
191
227
oldattr. mq_attr . mq_maxmsg ,
0 commit comments