Skip to content

Commit 0c02ee2

Browse files
bors[bot]asomers
andauthored
Merge #1639
1639: Fix Clippy warnings on FreeBSD with the latest nightly r=rtzoeller a=asomers * Better type safety for mqueue * Suppress clippy::not_unsafe_ptr_arg_deref warnings in ptrace on BSD Co-authored-by: Alan Somers <asomers@gmail.com>
2 parents c84316b + 91049bc commit 0c02ee2

File tree

5 files changed

+76
-28
lines changed

5 files changed

+76
-28
lines changed

.cirrus.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ task:
4040
freebsd_instance:
4141
image: freebsd-12-2-release-amd64
4242
setup_script:
43+
- kldload mqueuefs
4344
- fetch https://sh.rustup.rs -o rustup.sh
4445
- sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN
4546
- . $HOME/.cargo/env

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ This project adheres to [Semantic Versioning](https://semver.org/).
3939
(#[1636](https://github.com/nix-rust/nix/pull/1636))
4040

4141
### Changed
42+
43+
- `mqueue` functions now operate on a distinct type, `nix::mqueue::MqdT`.
44+
Accessors take this type by reference, not by value.
45+
(#[1639](https://github.com/nix-rust/nix/pull/1639))
46+
4247
### Fixed
4348
### Removed
4449

src/mqueue.rs

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
11
//! Posix Message Queue functions
22
//!
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+
//! ```
331
//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
432
533
use crate::Result;
634
use crate::errno::Errno;
735

836
use libc::{self, c_char, mqd_t, size_t};
9-
use std::ffi::CString;
37+
use std::ffi::CStr;
1038
use crate::sys::stat::Mode;
1139
use std::mem;
1240

@@ -34,6 +62,14 @@ pub struct MqAttr {
3462
mq_attr: libc::mq_attr,
3563
}
3664

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+
3773
// x32 compatibility
3874
// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
3975
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
@@ -87,11 +123,11 @@ impl MqAttr {
87123
/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
88124
// The mode.bits cast is only lossless on some OSes
89125
#[allow(clippy::cast_lossless)]
90-
pub fn mq_open(name: &CString,
126+
pub fn mq_open(name: &CStr,
91127
oflag: MQ_OFlag,
92128
mode: Mode,
93129
attr: Option<&MqAttr>)
94-
-> Result<mqd_t> {
130+
-> Result<MqdT> {
95131
let res = match attr {
96132
Some(mq_attr) => unsafe {
97133
libc::mq_open(name.as_ptr(),
@@ -101,32 +137,32 @@ pub fn mq_open(name: &CString,
101137
},
102138
None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
103139
};
104-
Errno::result(res)
140+
Errno::result(res).map(MqdT)
105141
}
106142

107143
/// Remove a message queue
108144
///
109145
/// 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<()> {
111147
let res = unsafe { libc::mq_unlink(name.as_ptr()) };
112148
Errno::result(res).map(drop)
113149
}
114150

115151
/// Close a message queue
116152
///
117153
/// 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) };
120156
Errno::result(res).map(drop)
121157
}
122158

123159
/// Receive a message from a message queue
124160
///
125161
/// 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> {
127163
let len = message.len() as size_t;
128164
let res = unsafe {
129-
libc::mq_receive(mqdes,
165+
libc::mq_receive(mqdes.0,
130166
message.as_mut_ptr() as *mut c_char,
131167
len,
132168
msg_prio as *mut u32)
@@ -137,9 +173,9 @@ pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Resul
137173
/// Send a message to a message queue
138174
///
139175
/// 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<()> {
141177
let res = unsafe {
142-
libc::mq_send(mqdes,
178+
libc::mq_send(mqdes.0,
143179
message.as_ptr() as *const c_char,
144180
message.len(),
145181
msq_prio)
@@ -150,9 +186,9 @@ pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
150186
/// Get message queue attributes
151187
///
152188
/// 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> {
154190
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()) };
156192
Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
157193
}
158194

@@ -161,10 +197,10 @@ pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
161197
/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
162198
///
163199
/// [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> {
165201
let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
166202
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())
168204
};
169205
Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
170206
}
@@ -173,7 +209,7 @@ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
173209
/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
174210
/// Returns the old attributes
175211
#[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> {
177213
let oldattr = mq_getattr(mqd)?;
178214
let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
179215
oldattr.mq_attr.mq_maxmsg,
@@ -185,7 +221,7 @@ pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
185221
/// Convenience function.
186222
/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
187223
/// 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> {
189225
let oldattr = mq_getattr(mqd)?;
190226
let newattr = MqAttr::new(0,
191227
oldattr.mq_attr.mq_maxmsg,

src/sys/ptrace/bsd.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
167167
}
168168

169169
/// Reads a word from a processes memory at the given address
170+
// Technically, ptrace doesn't dereference the pointer. It passes it directly
171+
// to the kernel.
172+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
170173
pub fn read(pid: Pid, addr: AddressType) -> Result<c_int> {
171174
unsafe {
172175
// Traditionally there was a difference between reading data or
@@ -176,6 +179,9 @@ pub fn read(pid: Pid, addr: AddressType) -> Result<c_int> {
176179
}
177180

178181
/// Writes a word into the processes memory at the given address
182+
// Technically, ptrace doesn't dereference the pointer. It passes it directly
183+
// to the kernel.
184+
#[allow(clippy::not_unsafe_ptr_arg_deref)]
179185
pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> {
180186
unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) }
181187
}

test/test_mq.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ fn test_mq_send_and_receive() {
4141
};
4242
let mqd0 = r0.unwrap();
4343
let msg_to_send = "msg_1";
44-
mq_send(mqd0, msg_to_send.as_bytes(), 1).unwrap();
44+
mq_send(&mqd0, msg_to_send.as_bytes(), 1).unwrap();
4545

4646
let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY;
4747
let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap();
4848
let mut buf = [0u8; 32];
4949
let mut prio = 0u32;
50-
let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
50+
let len = mq_receive(&mqd1, &mut buf, &mut prio).unwrap();
5151
assert_eq!(prio, 1);
5252

5353
mq_close(mqd1).unwrap();
@@ -71,7 +71,7 @@ fn test_mq_getattr() {
7171
};
7272
let mqd = r.unwrap();
7373

74-
let read_attr = mq_getattr(mqd).unwrap();
74+
let read_attr = mq_getattr(&mqd).unwrap();
7575
assert_attr_eq!(read_attr, initial_attr);
7676
mq_close(mqd).unwrap();
7777
}
@@ -98,20 +98,20 @@ fn test_mq_setattr() {
9898
let mqd = r.unwrap();
9999

100100
let new_attr = MqAttr::new(0, 20, MSG_SIZE * 2, 100);
101-
let old_attr = mq_setattr(mqd, &new_attr).unwrap();
101+
let old_attr = mq_setattr(&mqd, &new_attr).unwrap();
102102
assert_attr_eq!(old_attr, initial_attr);
103103

104104
// No changes here because according to the Linux man page only
105105
// O_NONBLOCK can be set (see tests below)
106106
#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))]
107107
{
108-
let new_attr_get = mq_getattr(mqd).unwrap();
108+
let new_attr_get = mq_getattr(&mqd).unwrap();
109109
assert_ne!(new_attr_get, new_attr);
110110
}
111111

112112
let new_attr_non_blocking = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0);
113-
mq_setattr(mqd, &new_attr_non_blocking).unwrap();
114-
let new_attr_get = mq_getattr(mqd).unwrap();
113+
mq_setattr(&mqd, &new_attr_non_blocking).unwrap();
114+
let new_attr_get = mq_getattr(&mqd).unwrap();
115115

116116
// now the O_NONBLOCK flag has been set
117117
#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))]
@@ -142,12 +142,12 @@ fn test_mq_set_nonblocking() {
142142
return;
143143
};
144144
let mqd = r.unwrap();
145-
mq_set_nonblock(mqd).unwrap();
146-
let new_attr = mq_getattr(mqd);
145+
mq_set_nonblock(&mqd).unwrap();
146+
let new_attr = mq_getattr(&mqd);
147147
let o_nonblock_bits = MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t;
148148
assert_eq!(new_attr.unwrap().flags() & o_nonblock_bits, o_nonblock_bits);
149-
mq_remove_nonblock(mqd).unwrap();
150-
let new_attr = mq_getattr(mqd);
149+
mq_remove_nonblock(&mqd).unwrap();
150+
let new_attr = mq_getattr(&mqd);
151151
assert_eq!(new_attr.unwrap().flags() & o_nonblock_bits, 0);
152152
mq_close(mqd).unwrap();
153153
}

0 commit comments

Comments
 (0)