1use crate::Result;
6use crate::errno::Errno;
7
8use libc::{self, c_char, mqd_t, size_t};
9use std::ffi::CString;
10use crate::sys::stat::Mode;
11use std::mem;
12
13libc_bitflags!{
14 pub struct MQ_OFlag: libc::c_int {
15 O_RDONLY;
16 O_WRONLY;
17 O_RDWR;
18 O_CREAT;
19 O_EXCL;
20 O_NONBLOCK;
21 O_CLOEXEC;
22 }
23}
24
25libc_bitflags!{
26 pub struct FdFlag: libc::c_int {
27 FD_CLOEXEC;
28 }
29}
30
31#[repr(C)]
32#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
33pub struct MqAttr {
34 mq_attr: libc::mq_attr,
35}
36
37#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
40pub type mq_attr_member_t = i64;
41#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
42pub type mq_attr_member_t = libc::c_long;
43
44impl MqAttr {
45 pub fn new(mq_flags: mq_attr_member_t,
46 mq_maxmsg: mq_attr_member_t,
47 mq_msgsize: mq_attr_member_t,
48 mq_curmsgs: mq_attr_member_t)
49 -> MqAttr
50 {
51 let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
52 unsafe {
53 let p = attr.as_mut_ptr();
54 (*p).mq_flags = mq_flags;
55 (*p).mq_maxmsg = mq_maxmsg;
56 (*p).mq_msgsize = mq_msgsize;
57 (*p).mq_curmsgs = mq_curmsgs;
58 MqAttr { mq_attr: attr.assume_init() }
59 }
60 }
61
62 pub const fn flags(&self) -> mq_attr_member_t {
63 self.mq_attr.mq_flags
64 }
65}
66
67
68#[allow(clippy::cast_lossless)]
73pub fn mq_open(name: &CString,
74 oflag: MQ_OFlag,
75 mode: Mode,
76 attr: Option<&MqAttr>)
77 -> Result<mqd_t> {
78 let res = match attr {
79 Some(mq_attr) => unsafe {
80 libc::mq_open(name.as_ptr(),
81 oflag.bits(),
82 mode.bits() as libc::c_int,
83 &mq_attr.mq_attr as *const libc::mq_attr)
84 },
85 None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
86 };
87 Errno::result(res)
88}
89
90pub fn mq_unlink(name: &CString) -> Result<()> {
94 let res = unsafe { libc::mq_unlink(name.as_ptr()) };
95 Errno::result(res).map(drop)
96}
97
98pub fn mq_close(mqdes: mqd_t) -> Result<()> {
102 let res = unsafe { libc::mq_close(mqdes) };
103 Errno::result(res).map(drop)
104}
105
106pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
110 let len = message.len() as size_t;
111 let res = unsafe {
112 libc::mq_receive(mqdes,
113 message.as_mut_ptr() as *mut c_char,
114 len,
115 msg_prio as *mut u32)
116 };
117 Errno::result(res).map(|r| r as usize)
118}
119
120pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
124 let res = unsafe {
125 libc::mq_send(mqdes,
126 message.as_ptr() as *const c_char,
127 message.len(),
128 msq_prio)
129 };
130 Errno::result(res).map(drop)
131}
132
133pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
137 let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
138 let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) };
139 Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
140}
141
142pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
148 let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
149 let res = unsafe {
150 libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr())
151 };
152 Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
153}
154
155#[allow(clippy::useless_conversion)] pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
160 let oldattr = mq_getattr(mqd)?;
161 let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
162 oldattr.mq_attr.mq_maxmsg,
163 oldattr.mq_attr.mq_msgsize,
164 oldattr.mq_attr.mq_curmsgs);
165 mq_setattr(mqd, &newattr)
166}
167
168pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<MqAttr> {
172 let oldattr = mq_getattr(mqd)?;
173 let newattr = MqAttr::new(0,
174 oldattr.mq_attr.mq_maxmsg,
175 oldattr.mq_attr.mq_msgsize,
176 oldattr.mq_attr.mq_curmsgs);
177 mq_setattr(mqd, &newattr)
178}