1use crate::Result;
34use crate::errno::Errno;
35
36use libc::{self, c_char, mqd_t, size_t};
37use std::ffi::CStr;
38use crate::sys::stat::Mode;
39use std::mem;
40
41libc_bitflags!{
42 pub struct MQ_OFlag: libc::c_int {
43 O_RDONLY;
44 O_WRONLY;
45 O_RDWR;
46 O_CREAT;
47 O_EXCL;
48 O_NONBLOCK;
49 O_CLOEXEC;
50 }
51}
52
53libc_bitflags!{
54 pub struct FdFlag: libc::c_int {
55 FD_CLOEXEC;
56 }
57}
58
59#[repr(C)]
60#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
61pub struct MqAttr {
62 mq_attr: libc::mq_attr,
63}
64
65#[repr(transparent)]
69#[derive(Debug)]
70#[allow(missing_copy_implementations)]
71pub struct MqdT(mqd_t);
72
73#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
76#[cfg_attr(docsrs, doc(cfg(all())))]
77pub type mq_attr_member_t = i64;
78#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
79#[cfg_attr(docsrs, doc(cfg(all())))]
80pub type mq_attr_member_t = libc::c_long;
81
82impl MqAttr {
83 pub fn new(mq_flags: mq_attr_member_t,
84 mq_maxmsg: mq_attr_member_t,
85 mq_msgsize: mq_attr_member_t,
86 mq_curmsgs: mq_attr_member_t)
87 -> MqAttr
88 {
89 let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
90 unsafe {
91 let p = attr.as_mut_ptr();
92 (*p).mq_flags = mq_flags;
93 (*p).mq_maxmsg = mq_maxmsg;
94 (*p).mq_msgsize = mq_msgsize;
95 (*p).mq_curmsgs = mq_curmsgs;
96 MqAttr { mq_attr: attr.assume_init() }
97 }
98 }
99
100 pub const fn flags(&self) -> mq_attr_member_t {
101 self.mq_attr.mq_flags
102 }
103
104 pub const fn maxmsg(&self) -> mq_attr_member_t {
106 self.mq_attr.mq_maxmsg
107 }
108
109 pub const fn msgsize(&self) -> mq_attr_member_t {
111 self.mq_attr.mq_msgsize
112 }
113
114 pub const fn curmsgs(&self) -> mq_attr_member_t {
116 self.mq_attr.mq_curmsgs
117 }
118}
119
120
121#[allow(clippy::cast_lossless)]
126pub fn mq_open(name: &CStr,
127 oflag: MQ_OFlag,
128 mode: Mode,
129 attr: Option<&MqAttr>)
130 -> Result<MqdT> {
131 let res = match attr {
132 Some(mq_attr) => unsafe {
133 libc::mq_open(name.as_ptr(),
134 oflag.bits(),
135 mode.bits() as libc::c_int,
136 &mq_attr.mq_attr as *const libc::mq_attr)
137 },
138 None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
139 };
140 Errno::result(res).map(MqdT)
141}
142
143pub fn mq_unlink(name: &CStr) -> Result<()> {
147 let res = unsafe { libc::mq_unlink(name.as_ptr()) };
148 Errno::result(res).map(drop)
149}
150
151pub fn mq_close(mqdes: MqdT) -> Result<()> {
155 let res = unsafe { libc::mq_close(mqdes.0) };
156 Errno::result(res).map(drop)
157}
158
159pub fn mq_receive(mqdes: &MqdT, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
163 let len = message.len() as size_t;
164 let res = unsafe {
165 libc::mq_receive(mqdes.0,
166 message.as_mut_ptr() as *mut c_char,
167 len,
168 msg_prio as *mut u32)
169 };
170 Errno::result(res).map(|r| r as usize)
171}
172
173pub fn mq_send(mqdes: &MqdT, message: &[u8], msq_prio: u32) -> Result<()> {
177 let res = unsafe {
178 libc::mq_send(mqdes.0,
179 message.as_ptr() as *const c_char,
180 message.len(),
181 msq_prio)
182 };
183 Errno::result(res).map(drop)
184}
185
186pub fn mq_getattr(mqd: &MqdT) -> Result<MqAttr> {
190 let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
191 let res = unsafe { libc::mq_getattr(mqd.0, attr.as_mut_ptr()) };
192 Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
193}
194
195pub fn mq_setattr(mqd: &MqdT, newattr: &MqAttr) -> Result<MqAttr> {
201 let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
202 let res = unsafe {
203 libc::mq_setattr(mqd.0, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr())
204 };
205 Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
206}
207
208#[allow(clippy::useless_conversion)] pub fn mq_set_nonblock(mqd: &MqdT) -> Result<MqAttr> {
213 let oldattr = mq_getattr(mqd)?;
214 let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
215 oldattr.mq_attr.mq_maxmsg,
216 oldattr.mq_attr.mq_msgsize,
217 oldattr.mq_attr.mq_curmsgs);
218 mq_setattr(mqd, &newattr)
219}
220
221pub fn mq_remove_nonblock(mqd: &MqdT) -> Result<MqAttr> {
225 let oldattr = mq_getattr(mqd)?;
226 let newattr = MqAttr::new(0,
227 oldattr.mq_attr.mq_maxmsg,
228 oldattr.mq_attr.mq_msgsize,
229 oldattr.mq_attr.mq_curmsgs);
230 mq_setattr(mqd, &newattr)
231}