Skip to content

Commit 9b81000

Browse files
committed
Auto merge of #478 - conradev:sys-control, r=fiveop
Add support for system control sockets for XNU I added support for macOS and iOS system sockets, which can be used to control the kernel as described [here](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html). To do this, I had to add in support for `ioctl` on those platforms, so I added in `ioctl` support for all BSD-based platforms. The API seems to be the same between [xnu](https://opensource.apple.com/source/xnu/xnu-3248.60.10/bsd/sys/ioccom.h.auto.html), [FreeBSD](https://github.com/freebsd/freebsd/blob/master/sys/sys/ioccom.h), [NetBSD](https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/ioccom.h), [OpenBSD](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/ioccom.h?rev=1.5&content-type=text/x-cvsweb-markup) and [Dragonfly BSD](http://gitweb.dragonflybsd.org/dragonfly.git/blob/HEAD:/sys/sys/ioccom.h). I added a test that runs on macOS and iOS for the functionality. Let me know if I need to make any changes!
2 parents 5e932dc + ef257e0 commit 9b81000

16 files changed

+387
-160
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66
## [Unreleased]
77

88
### Added
9+
- Added support for XNU system control sockets
10+
([#478](https://github.com/nix-rust/nix/pull/478))
11+
- Added support for `ioctl` calls on BSD platforms
12+
([#478](https://github.com/nix-rust/nix/pull/478))
913
- Added struct `TimeSpec`
1014
([#475](https://github.com/nix-rust/nix/pull/475))
1115
- Added complete definitions for all kqueue-related constants on all supported
@@ -26,6 +30,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2630
([#491](https://github.com/nix-rust/nix/pull/491))
2731

2832
### Changed
33+
- Removed the `bad` keyword from the `ioctl!` macro
34+
([#478](https://github.com/nix-rust/nix/pull/478))
2935
- Changed `TimeVal` into an opaque Newtype
3036
([#475](https://github.com/nix-rust/nix/pull/475))
3137
- `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the

src/sys/event.rs

+33-22
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ pub struct KEvent {
1919
}
2020

2121
#[cfg(any(target_os = "openbsd", target_os = "freebsd",
22-
target_os = "dragonfly", target_os = "macos"))]
22+
target_os = "dragonfly", target_os = "macos",
23+
target_os = "ios"))]
2324
type type_of_udata = *mut ::c_void;
2425
#[cfg(any(target_os = "netbsd"))]
2526
type type_of_udata = intptr_t;
@@ -33,23 +34,24 @@ pub enum EventFilter {
3334
EVFILT_AIO = libc::EVFILT_AIO,
3435
#[cfg(target_os = "dragonfly")]
3536
EVFILT_EXCEPT = libc::EVFILT_EXCEPT,
36-
#[cfg(any(target_os = "macos",
37+
#[cfg(any(target_os = "macos", target_os = "ios",
3738
target_os = "dragonfly",
3839
target_os = "freebsd"))]
3940
EVFILT_FS = libc::EVFILT_FS,
4041
#[cfg(target_os = "freebsd")]
4142
EVFILT_LIO = libc::EVFILT_LIO,
42-
#[cfg(target_os = "macos")]
43+
#[cfg(any(target_os = "macos", target_os = "ios"))]
4344
EVFILT_MACHPORT = libc::EVFILT_MACHPORT,
4445
EVFILT_PROC = libc::EVFILT_PROC,
4546
EVFILT_READ = libc::EVFILT_READ,
4647
EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
4748
EVFILT_TIMER = libc::EVFILT_TIMER,
4849
#[cfg(any(target_os = "macos",
50+
target_os = "ios",
4951
target_os = "dragonfly",
5052
target_os = "freebsd"))]
5153
EVFILT_USER = libc::EVFILT_USER,
52-
#[cfg(target_os = "macos")]
54+
#[cfg(any(target_os = "macos", target_os = "ios"))]
5355
EVFILT_VM = libc::EVFILT_VM,
5456
EVFILT_VNODE = libc::EVFILT_VNODE,
5557
EVFILT_WRITE = libc::EVFILT_WRITE,
@@ -70,7 +72,8 @@ pub enum EventFilter {
7072
EVFILT_TIMER = libc::EVFILT_TIMER,
7173
}
7274

73-
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))]
75+
#[cfg(any(target_os = "macos", target_os = "ios",
76+
target_os = "freebsd", target_os = "dragonfly"))]
7477
pub type type_of_event_flag = u16;
7578
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
7679
pub type type_of_event_flag = u32;
@@ -86,15 +89,15 @@ libc_bitflags!{
8689
EV_ENABLE,
8790
EV_EOF,
8891
EV_ERROR,
89-
#[cfg(target_os = "macos")]
92+
#[cfg(any(target_os = "macos", target_os = "ios"))]
9093
EV_FLAG0,
9194
EV_FLAG1,
9295
#[cfg(target_os = "dragonfly")]
9396
EV_NODATA,
9497
EV_ONESHOT,
95-
#[cfg(target_os = "macos")]
98+
#[cfg(any(target_os = "macos", target_os = "ios"))]
9699
EV_OOBAND,
97-
#[cfg(target_os = "macos")]
100+
#[cfg(any(target_os = "macos", target_os = "ios"))]
98101
EV_POLL,
99102
#[cfg(not(target_os = "openbsd"))]
100103
EV_RECEIPT,
@@ -104,7 +107,7 @@ libc_bitflags!{
104107

105108
bitflags!(
106109
flags FilterFlag: u32 {
107-
#[cfg(target_os = "macos")]
110+
#[cfg(any(target_os = "macos", target_os = "ios"))]
108111
const NOTE_ABSOLUTE = libc::NOTE_ABSOLUTE,
109112
const NOTE_ATTRIB = libc::NOTE_ATTRIB,
110113
const NOTE_CHILD = libc::NOTE_CHILD,
@@ -113,32 +116,38 @@ bitflags!(
113116
const NOTE_EOF = libc::NOTE_EOF,
114117
const NOTE_EXEC = libc::NOTE_EXEC,
115118
const NOTE_EXIT = libc::NOTE_EXIT,
116-
#[cfg(target_os = "macos")]
119+
#[cfg(any(target_os = "macos", target_os = "ios"))]
117120
const NOTE_EXIT_REPARENTED = libc::NOTE_EXIT_REPARENTED,
118-
#[cfg(target_os = "macos")]
121+
#[cfg(any(target_os = "macos", target_os = "ios"))]
119122
const NOTE_EXITSTATUS = libc::NOTE_EXITSTATUS,
120123
const NOTE_EXTEND = libc::NOTE_EXTEND,
121-
#[cfg(any(target_os = "macos",
124+
#[cfg(any(target_os = "macos",
125+
target_os = "ios",
122126
target_os = "freebsd",
123127
target_os = "dragonfly"))]
124128
const NOTE_FFAND = libc::NOTE_FFAND,
125129
#[cfg(any(target_os = "macos",
130+
target_os = "ios",
126131
target_os = "freebsd",
127132
target_os = "dragonfly"))]
128133
const NOTE_FFCOPY = libc::NOTE_FFCOPY,
129134
#[cfg(any(target_os = "macos",
135+
target_os = "ios",
130136
target_os = "freebsd",
131137
target_os = "dragonfly"))]
132138
const NOTE_FFCTRLMASK = libc::NOTE_FFCTRLMASK,
133139
#[cfg(any(target_os = "macos",
140+
target_os = "ios",
134141
target_os = "freebsd",
135142
target_os = "dragonfly"))]
136143
const NOTE_FFLAGSMASK = libc::NOTE_FFLAGSMASK,
137144
#[cfg(any(target_os = "macos",
145+
target_os = "ios",
138146
target_os = "freebsd",
139147
target_os = "dragonfly"))]
140148
const NOTE_FFNOP = libc::NOTE_FFNOP,
141149
#[cfg(any(target_os = "macos",
150+
target_os = "ios",
142151
target_os = "freebsd",
143152
target_os = "dragonfly"))]
144153
const NOTE_FFOR = libc::NOTE_FFOR,
@@ -147,39 +156,40 @@ bitflags!(
147156
const NOTE_LOWAT = libc::NOTE_LOWAT,
148157
#[cfg(target_os = "freebsd")]
149158
const NOTE_MSECONDS = libc::NOTE_MSECONDS,
150-
#[cfg(target_os = "macos")]
159+
#[cfg(any(target_os = "macos", target_os = "ios"))]
151160
const NOTE_NONE = libc::NOTE_NONE,
152-
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
161+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
153162
const NOTE_NSECONDS = libc::NOTE_NSECONDS,
154163
#[cfg(target_os = "dragonfly")]
155164
const NOTE_OOB = libc::NOTE_OOB,
156165
const NOTE_PCTRLMASK = libc::NOTE_PCTRLMASK,
157166
const NOTE_PDATAMASK = libc::NOTE_PDATAMASK,
158-
#[cfg(target_os = "macos")]
167+
#[cfg(any(target_os = "macos", target_os = "ios"))]
159168
const NOTE_REAP = libc::NOTE_REAP,
160169
const NOTE_RENAME = libc::NOTE_RENAME,
161170
const NOTE_REVOKE = libc::NOTE_REVOKE,
162-
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
171+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
163172
const NOTE_SECONDS = libc::NOTE_SECONDS,
164-
#[cfg(target_os = "macos")]
173+
#[cfg(any(target_os = "macos", target_os = "ios"))]
165174
const NOTE_SIGNAL = libc::NOTE_SIGNAL,
166175
const NOTE_TRACK = libc::NOTE_TRACK,
167176
const NOTE_TRACKERR = libc::NOTE_TRACKERR,
168177
#[cfg(any(target_os = "macos",
178+
target_os = "ios",
169179
target_os = "freebsd",
170180
target_os = "dragonfly"))]
171181
const NOTE_TRIGGER = libc::NOTE_TRIGGER,
172182
#[cfg(target_os = "openbsd")]
173183
const NOTE_TRUNCATE = libc::NOTE_TRUNCATE,
174-
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
184+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
175185
const NOTE_USECONDS = libc::NOTE_USECONDS,
176-
#[cfg(target_os = "macos")]
186+
#[cfg(any(target_os = "macos", target_os = "ios"))]
177187
const NOTE_VM_ERROR = libc::NOTE_VM_ERROR,
178-
#[cfg(target_os = "macos")]
188+
#[cfg(any(target_os = "macos", target_os = "ios"))]
179189
const NOTE_VM_PRESSURE = libc::NOTE_VM_PRESSURE,
180-
#[cfg(target_os = "macos")]
190+
#[cfg(any(target_os = "macos", target_os = "ios"))]
181191
const NOTE_VM_PRESSURE_SUDDEN_TERMINATE = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
182-
#[cfg(target_os = "macos")]
192+
#[cfg(any(target_os = "macos", target_os = "ios"))]
183193
const NOTE_VM_PRESSURE_TERMINATE = libc::NOTE_VM_PRESSURE_TERMINATE,
184194
const NOTE_WRITE = libc::NOTE_WRITE,
185195
}
@@ -251,6 +261,7 @@ pub fn kevent(kq: RawFd,
251261
}
252262

253263
#[cfg(any(target_os = "macos",
264+
target_os = "ios",
254265
target_os = "freebsd",
255266
target_os = "dragonfly",
256267
target_os = "openbsd"))]

src/sys/ioctl/mod.rs

+79-28
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
//! How do I get the magic numbers?
9191
//! ===============================
9292
//!
93-
//! For Linux, look at your system's headers. For example, `/usr/include/linxu/input.h` has a lot
93+
//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
9494
//! of lines defining macros which use `_IOR`, `_IOW`, `_IOC`, and `_IORW`. These macros
9595
//! correspond to the `ior!`, `iow!`, `ioc!`, and `iorw!` macros defined in this crate.
9696
//! Additionally, there is the `ioctl!` macro for creating a wrapper around `ioctl` that is
@@ -104,33 +104,13 @@
104104
#[macro_use]
105105
mod platform;
106106

107-
#[cfg(target_os = "macos")]
108-
#[path = "platform/macos.rs"]
109-
#[macro_use]
110-
mod platform;
111-
112-
#[cfg(target_os = "ios")]
113-
#[path = "platform/ios.rs"]
114-
#[macro_use]
115-
mod platform;
116-
117-
#[cfg(target_os = "freebsd")]
118-
#[path = "platform/freebsd.rs"]
119-
#[macro_use]
120-
mod platform;
121-
122-
#[cfg(target_os = "netbsd")]
123-
#[path = "platform/netbsd.rs"]
124-
#[macro_use]
125-
mod platform;
126-
127-
#[cfg(target_os = "openbsd")]
128-
#[path = "platform/openbsd.rs"]
129-
#[macro_use]
130-
mod platform;
131-
132-
#[cfg(target_os = "dragonfly")]
133-
#[path = "platform/dragonfly.rs"]
107+
#[cfg(any(target_os = "macos",
108+
target_os = "ios",
109+
target_os = "netbsd",
110+
target_os = "openbsd",
111+
target_os = "freebsd",
112+
target_os = "dragonfly"))]
113+
#[path = "platform/bsd.rs"]
134114
#[macro_use]
135115
mod platform;
136116

@@ -145,3 +125,74 @@ extern "C" {
145125
/// A hack to get the macros to work nicely.
146126
#[doc(hidden)]
147127
pub use ::libc as libc;
128+
129+
/// Convert raw ioctl return value to a Nix result
130+
#[macro_export]
131+
macro_rules! convert_ioctl_res {
132+
($w:expr) => (
133+
{
134+
$crate::Errno::result($w)
135+
}
136+
);
137+
}
138+
139+
#[macro_export]
140+
macro_rules! ioctl {
141+
($name:ident with $nr:expr) => (
142+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
143+
data: *mut u8)
144+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
145+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, $nr as $crate::sys::ioctl::libc::c_ulong, data))
146+
}
147+
);
148+
(none $name:ident with $ioty:expr, $nr:expr) => (
149+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int)
150+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
151+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::libc::c_ulong))
152+
}
153+
);
154+
(read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
155+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
156+
val: *mut $ty)
157+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
158+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
159+
}
160+
);
161+
(write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
162+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
163+
val: *const $ty)
164+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
165+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
166+
}
167+
);
168+
(readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
169+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
170+
val: *mut $ty)
171+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
172+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
173+
}
174+
);
175+
(read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
176+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
177+
val: *mut $ty,
178+
len: usize)
179+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
180+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
181+
}
182+
);
183+
(write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
184+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
185+
val: *const $ty,
186+
len: usize) -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
187+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
188+
}
189+
);
190+
(readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
191+
pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
192+
val: *mut $ty,
193+
len: usize)
194+
-> $crate::Result<$crate::sys::ioctl::libc::c_int> {
195+
convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
196+
}
197+
);
198+
}

src/sys/ioctl/platform/bsd.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
mod consts {
2+
pub const VOID: u32 = 0x20000000;
3+
pub const OUT: u32 = 0x40000000;
4+
pub const IN: u32 = 0x80000000;
5+
pub const INOUT: u32 = (IN|OUT);
6+
pub const IOCPARM_MASK: u32 = 0x1fff;
7+
}
8+
9+
pub use self::consts::*;
10+
11+
#[macro_export]
12+
macro_rules! ioc {
13+
($inout:expr, $group:expr, $num:expr, $len:expr) => (
14+
$inout | (($len as u32 & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as u32) << 8) | ($num as u32)
15+
)
16+
}
17+
18+
#[macro_export]
19+
macro_rules! io {
20+
($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
21+
}
22+
23+
#[macro_export]
24+
macro_rules! ior {
25+
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len))
26+
}
27+
28+
#[macro_export]
29+
macro_rules! iow {
30+
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len))
31+
}
32+
33+
#[macro_export]
34+
macro_rules! iorw {
35+
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len))
36+
}

src/sys/ioctl/platform/dragonfly.rs

Whitespace-only changes.

src/sys/ioctl/platform/freebsd.rs

Whitespace-only changes.

src/sys/ioctl/platform/ios.rs

Whitespace-only changes.

0 commit comments

Comments
 (0)