|
4 | 4 |
|
5 | 5 | use {Errno, Result};
|
6 | 6 |
|
7 |
| -use libc::{c_int, c_long, c_char, size_t, mode_t}; |
| 7 | +use libc::{self, c_char, c_long, mode_t, mqd_t, size_t}; |
8 | 8 | use std::ffi::CString;
|
9 | 9 | use sys::stat::Mode;
|
10 |
| -use std::ptr; |
11 |
| - |
12 |
| -pub use self::consts::*; |
13 |
| - |
14 |
| -pub type MQd = c_int; |
15 |
| - |
16 |
| -#[cfg(target_os = "linux")] |
17 |
| -mod consts { |
18 |
| - use libc::c_int; |
19 |
| - |
20 |
| - bitflags!( |
21 |
| - flags MQ_OFlag: c_int { |
22 |
| - const O_RDONLY = 0o00000000, |
23 |
| - const O_WRONLY = 0o00000001, |
24 |
| - const O_RDWR = 0o00000002, |
25 |
| - const O_CREAT = 0o00000100, |
26 |
| - const O_EXCL = 0o00000200, |
27 |
| - const O_NONBLOCK = 0o00004000, |
28 |
| - const O_CLOEXEC = 0o02000000, |
29 |
| - } |
30 |
| - ); |
31 |
| - |
32 |
| - bitflags!( |
33 |
| - flags FdFlag: c_int { |
34 |
| - const FD_CLOEXEC = 1 |
35 |
| - } |
36 |
| - ); |
| 10 | +use std::mem; |
| 11 | + |
| 12 | +libc_bitflags!{ |
| 13 | + flags MQ_OFlag: libc::c_int { |
| 14 | + O_RDONLY, |
| 15 | + O_WRONLY, |
| 16 | + O_RDWR, |
| 17 | + O_CREAT, |
| 18 | + O_EXCL, |
| 19 | + O_NONBLOCK, |
| 20 | + O_CLOEXEC, |
| 21 | + } |
37 | 22 | }
|
38 | 23 |
|
39 |
| -mod ffi { |
40 |
| - use libc::{c_char, size_t, ssize_t, c_uint, c_int}; |
41 |
| - use super::MQd; |
42 |
| - use super::MqAttr; |
43 |
| - |
44 |
| - #[allow(improper_ctypes)] |
45 |
| - extern "C" { |
46 |
| - pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> MQd; |
47 |
| - |
48 |
| - pub fn mq_close (mqd: MQd) -> c_int; |
49 |
| - |
50 |
| - pub fn mq_unlink(name: *const c_char) -> c_int; |
51 |
| - |
52 |
| - pub fn mq_receive (mqd: MQd, msg_ptr: *const c_char, msg_len: size_t, msq_prio: *const c_uint) -> ssize_t; |
53 |
| - |
54 |
| - pub fn mq_send (mqd: MQd, msg_ptr: *const c_char, msg_len: size_t, msq_prio: c_uint) -> c_int; |
55 |
| - |
56 |
| - pub fn mq_getattr(mqd: MQd, attr: *mut MqAttr) -> c_int; |
57 |
| - |
58 |
| - pub fn mq_setattr(mqd: MQd, newattr: *const MqAttr, oldattr: *mut MqAttr) -> c_int; |
| 24 | +libc_bitflags!{ |
| 25 | + flags FdFlag: libc::c_int { |
| 26 | + FD_CLOEXEC, |
59 | 27 | }
|
60 | 28 | }
|
61 | 29 |
|
62 | 30 | #[repr(C)]
|
63 |
| -#[derive(Clone, Copy, Debug, Eq, PartialEq)] |
| 31 | +#[derive(Clone, Copy)] |
64 | 32 | pub struct MqAttr {
|
65 |
| - pub mq_flags: c_long, |
66 |
| - pub mq_maxmsg: c_long, |
67 |
| - pub mq_msgsize: c_long, |
68 |
| - pub mq_curmsgs: c_long, |
69 |
| - pad: [c_long; 4] |
| 33 | + mq_attr: libc::mq_attr, |
70 | 34 | }
|
71 | 35 |
|
72 |
| -impl MqAttr { |
73 |
| - pub fn new(mq_flags: c_long, mq_maxmsg: c_long, mq_msgsize: c_long, mq_curmsgs: c_long) -> MqAttr { |
74 |
| - MqAttr { mq_flags: mq_flags, mq_maxmsg: mq_maxmsg, mq_msgsize: mq_msgsize, mq_curmsgs: mq_curmsgs, pad: [0; 4] } |
75 |
| - } |
| 36 | +impl PartialEq<MqAttr> for MqAttr { |
| 37 | + fn eq(&self, other: &MqAttr) -> bool { |
| 38 | + let self_attr = self.mq_attr; |
| 39 | + let other_attr = other.mq_attr; |
| 40 | + self_attr.mq_flags == other_attr.mq_flags && self_attr.mq_maxmsg == other_attr.mq_maxmsg && |
| 41 | + self_attr.mq_msgsize == other_attr.mq_msgsize && |
| 42 | + self_attr.mq_curmsgs == other_attr.mq_curmsgs |
| 43 | + } |
76 | 44 | }
|
77 | 45 |
|
| 46 | +impl MqAttr { |
| 47 | + pub fn new(mq_flags: c_long, |
| 48 | + mq_maxmsg: c_long, |
| 49 | + mq_msgsize: c_long, |
| 50 | + mq_curmsgs: c_long) |
| 51 | + -> MqAttr { |
| 52 | + let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() }; |
| 53 | + attr.mq_flags = mq_flags; |
| 54 | + attr.mq_maxmsg = mq_maxmsg; |
| 55 | + attr.mq_msgsize = mq_msgsize; |
| 56 | + attr.mq_curmsgs = mq_curmsgs; |
| 57 | + MqAttr { mq_attr: attr } |
| 58 | + } |
78 | 59 |
|
79 |
| -pub fn mq_open(name: &CString, oflag: MQ_OFlag, mode: Mode, attr: Option<&MqAttr>) -> Result<MQd> { |
80 |
| - let attr_p = attr.map(|attr| attr as *const MqAttr).unwrap_or(ptr::null()); |
81 |
| - let res = unsafe { ffi::mq_open(name.as_ptr(), oflag.bits(), mode.bits() as mode_t, attr_p) }; |
| 60 | + pub fn flags(&self) -> c_long { |
| 61 | + self.mq_attr.mq_flags |
| 62 | + } |
| 63 | +} |
82 | 64 |
|
| 65 | + |
| 66 | +pub fn mq_open(name: &CString, |
| 67 | + oflag: MQ_OFlag, |
| 68 | + mode: Mode, |
| 69 | + attr: Option<&MqAttr>) |
| 70 | + -> Result<mqd_t> { |
| 71 | + let res = match attr { |
| 72 | + Some(mq_attr) => unsafe { |
| 73 | + libc::mq_open(name.as_ptr(), |
| 74 | + oflag.bits(), |
| 75 | + mode.bits() as mode_t, |
| 76 | + &mq_attr.mq_attr as *const libc::mq_attr) |
| 77 | + }, |
| 78 | + None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) }, |
| 79 | + }; |
83 | 80 | Errno::result(res)
|
84 | 81 | }
|
85 | 82 |
|
86 | 83 | pub fn mq_unlink(name: &CString) -> Result<()> {
|
87 |
| - let res = unsafe { ffi::mq_unlink(name.as_ptr()) }; |
| 84 | + let res = unsafe { libc::mq_unlink(name.as_ptr()) }; |
88 | 85 | Errno::result(res).map(drop)
|
89 | 86 | }
|
90 | 87 |
|
91 |
| -pub fn mq_close(mqdes: MQd) -> Result<()> { |
92 |
| - let res = unsafe { ffi::mq_close(mqdes) }; |
| 88 | +pub fn mq_close(mqdes: mqd_t) -> Result<()> { |
| 89 | + let res = unsafe { libc::mq_close(mqdes) }; |
93 | 90 | Errno::result(res).map(drop)
|
94 | 91 | }
|
95 | 92 |
|
96 |
| - |
97 |
| -pub fn mq_receive(mqdes: MQd, message: &mut [u8], msq_prio: u32) -> Result<usize> { |
| 93 | +pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> { |
98 | 94 | let len = message.len() as size_t;
|
99 |
| - let res = unsafe { ffi::mq_receive(mqdes, message.as_mut_ptr() as *mut c_char, len, &msq_prio) }; |
100 |
| - |
| 95 | + let res = unsafe { |
| 96 | + libc::mq_receive(mqdes, |
| 97 | + message.as_mut_ptr() as *mut c_char, |
| 98 | + len, |
| 99 | + msg_prio as *mut u32) |
| 100 | + }; |
101 | 101 | Errno::result(res).map(|r| r as usize)
|
102 | 102 | }
|
103 | 103 |
|
104 |
| -pub fn mq_send(mqdes: MQd, message: &[u8], msq_prio: u32) -> Result<()> { |
105 |
| - let res = unsafe { ffi::mq_send(mqdes, message.as_ptr() as *const c_char, message.len(), msq_prio) }; |
106 |
| - |
| 104 | +pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> { |
| 105 | + let res = unsafe { |
| 106 | + libc::mq_send(mqdes, |
| 107 | + message.as_ptr() as *const c_char, |
| 108 | + message.len(), |
| 109 | + msq_prio) |
| 110 | + }; |
107 | 111 | Errno::result(res).map(drop)
|
108 | 112 | }
|
109 | 113 |
|
110 |
| -pub fn mq_getattr(mqd: MQd) -> Result<MqAttr> { |
111 |
| - let mut attr = MqAttr::new(0, 0, 0, 0); |
112 |
| - let res = unsafe { ffi::mq_getattr(mqd, &mut attr) }; |
113 |
| - try!(Errno::result(res)); |
114 |
| - Ok(attr) |
| 114 | +pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> { |
| 115 | + let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() }; |
| 116 | + let res = unsafe { libc::mq_getattr(mqd, &mut attr) }; |
| 117 | + Errno::result(res).map(|_| MqAttr { mq_attr: attr }) |
115 | 118 | }
|
116 | 119 |
|
117 | 120 | /// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
|
118 | 121 | /// Returns the old attributes
|
119 | 122 | /// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
|
120 | 123 | ///
|
121 | 124 | /// [Further reading](http://man7.org/linux/man-pages/man3/mq_setattr.3.html)
|
122 |
| -pub fn mq_setattr(mqd: MQd, newattr: &MqAttr) -> Result<MqAttr> { |
123 |
| - let mut attr = MqAttr::new(0, 0, 0, 0); |
124 |
| - let res = unsafe { ffi::mq_setattr(mqd, newattr as *const MqAttr, &mut attr) }; |
125 |
| - try!(Errno::result(res)); |
126 |
| - Ok(attr) |
| 125 | +pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> { |
| 126 | + let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() }; |
| 127 | + let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) }; |
| 128 | + Errno::result(res).map(|_| MqAttr { mq_attr: attr }) |
127 | 129 | }
|
128 | 130 |
|
129 | 131 | /// Convenience function.
|
130 | 132 | /// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
|
131 | 133 | /// Returns the old attributes
|
132 |
| -pub fn mq_set_nonblock(mqd: MQd) -> Result<(MqAttr)> { |
| 134 | +pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> { |
133 | 135 | let oldattr = try!(mq_getattr(mqd));
|
134 |
| - let newattr = MqAttr::new(O_NONBLOCK.bits() as c_long, oldattr.mq_maxmsg, oldattr.mq_msgsize, oldattr.mq_curmsgs); |
| 136 | + let newattr = MqAttr::new(O_NONBLOCK.bits() as c_long, |
| 137 | + oldattr.mq_attr.mq_maxmsg, |
| 138 | + oldattr.mq_attr.mq_msgsize, |
| 139 | + oldattr.mq_attr.mq_curmsgs); |
135 | 140 | mq_setattr(mqd, &newattr)
|
136 | 141 | }
|
137 | 142 |
|
138 | 143 | /// Convenience function.
|
139 | 144 | /// Removes `O_NONBLOCK` attribute for a given message queue descriptor
|
140 | 145 | /// Returns the old attributes
|
141 |
| -pub fn mq_remove_nonblock(mqd: MQd) -> Result<(MqAttr)> { |
| 146 | +pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> { |
142 | 147 | let oldattr = try!(mq_getattr(mqd));
|
143 |
| - let newattr = MqAttr::new(0, oldattr.mq_maxmsg, oldattr.mq_msgsize, oldattr.mq_curmsgs); |
| 148 | + let newattr = MqAttr::new(0, |
| 149 | + oldattr.mq_attr.mq_maxmsg, |
| 150 | + oldattr.mq_attr.mq_msgsize, |
| 151 | + oldattr.mq_attr.mq_curmsgs); |
144 | 152 | mq_setattr(mqd, &newattr)
|
145 | 153 | }
|
0 commit comments