Skip to content

Commit 45e3170

Browse files
committed
Auto merge of #392 - fiveop:less_ffi, r=@fiveop
Replace ffi module by libc functions in mqueue.rs This is almost finished. I still need to check if I introduced any breaking changes by changing signatures. I would want to record this in the change log, however, for that we still need to merge #391. - [x] update change log - [x] run rustfmt on `src/mqueue.rs`
2 parents 9140e62 + 8ed5521 commit 45e3170

File tree

4 files changed

+111
-89
lines changed

4 files changed

+111
-89
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4040
`::nix::sched` to `Result<bool>` and `Result<()>`, respectively. They now
4141
return `EINVAL`, if an invalid argument for the `field` parameter is passed.
4242
([#402](https://github.com/nix-rust/nix/pull/402))
43+
- `MqAttr` in `::nix::mqueue` is now an opaque proxy for `::libc::mq_attr`,
44+
which has the same structure as the old `MqAttr`. The field `mq_flags` of
45+
`::libc::mq_attr` is readable using the new method `flags()` of `MqAttr`.
46+
`MqAttr` also no longer implements `Debug`.
47+
([#0](https://github.com/nix-rust/nix/pull/0))
48+
- The parameter `msq_prio` of `mq_receive` with type `u32` in `::nix::mqueue`
49+
was replaced by a parameter named `msg_prio` with type `&mut u32`, so that
50+
the message priority can be obtained by the caller.
51+
([#0](https://github.com/nix-rust/nix/pull/0))
52+
- The type alias `MQd` in `::nix::queue` was replaced by the type alias
53+
`libc::mqd_t`, both of which are aliases for the same type.
54+
([#0](https://github.com/nix-rust/nix/pull/0))
4355

4456
### Removed
4557
- Type alias `SigNum` from `::nix::sys::signal`.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub mod fcntl;
4040
#[cfg(any(target_os = "linux", target_os = "android"))]
4141
pub mod mount;
4242

43-
#[cfg(any(target_os = "linux"))]
43+
#[cfg(target_os = "linux")]
4444
pub mod mqueue;
4545

4646
#[cfg(any(target_os = "linux", target_os = "macos"))]

src/mqueue.rs

Lines changed: 93 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -4,142 +4,150 @@
44
55
use {Errno, Result};
66

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};
88
use std::ffi::CString;
99
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+
}
3722
}
3823

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,
5927
}
6028
}
6129

6230
#[repr(C)]
63-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31+
#[derive(Clone, Copy)]
6432
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,
7034
}
7135

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+
}
7644
}
7745

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+
}
7859

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+
}
8264

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+
};
8380
Errno::result(res)
8481
}
8582

8683
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()) };
8885
Errno::result(res).map(drop)
8986
}
9087

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) };
9390
Errno::result(res).map(drop)
9491
}
9592

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> {
9894
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+
};
101101
Errno::result(res).map(|r| r as usize)
102102
}
103103

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+
};
107111
Errno::result(res).map(drop)
108112
}
109113

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 })
115118
}
116119

117120
/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
118121
/// Returns the old attributes
119122
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
120123
///
121124
/// [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 })
127129
}
128130

129131
/// Convenience function.
130132
/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
131133
/// 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)> {
133135
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);
135140
mq_setattr(mqd, &newattr)
136141
}
137142

138143
/// Convenience function.
139144
/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
140145
/// 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)> {
142147
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);
144152
mq_setattr(mqd, &newattr)
145153
}

test/test_mq.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ fn test_mq_send_and_receive() {
3333
let mq_name_in_child = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
3434
let mqd_in_child = mq_open(mq_name_in_child, O_CREAT | O_RDONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, Some(&attr)).unwrap();
3535
let mut buf = [0u8; 32];
36-
mq_receive(mqd_in_child, &mut buf, 1).unwrap();
36+
let mut prio = 0u32;
37+
mq_receive(mqd_in_child, &mut buf, &mut prio).unwrap();
38+
assert!(prio == 1);
3739
write(writer, &buf).unwrap(); // pipe result to parent process. Otherwise cargo does not report test failures correctly
3840
mq_close(mqd_in_child).unwrap();
3941
}
@@ -99,10 +101,10 @@ fn test_mq_set_nonblocking() {
99101
let mqd = mq_open(mq_name, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, Some(&initial_attr)).unwrap();
100102
mq_set_nonblock(mqd).unwrap();
101103
let new_attr = mq_getattr(mqd);
102-
assert!(new_attr.unwrap().mq_flags == O_NONBLOCK.bits() as c_long);
104+
assert!(new_attr.unwrap().flags() == O_NONBLOCK.bits() as c_long);
103105
mq_remove_nonblock(mqd).unwrap();
104106
let new_attr = mq_getattr(mqd);
105-
assert!(new_attr.unwrap().mq_flags == 0);
107+
assert!(new_attr.unwrap().flags() == 0);
106108
mq_close(mqd).unwrap();
107109
}
108110

0 commit comments

Comments
 (0)