Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
xpc-sys
Various utilities for conveniently dealing with XPC in Rust.
Getting Started
Conversions to/from Rust/XPC objects uses the xpc.h functions documented on Apple Developer using the From trait. Complex types such as arrays and shared memory objects described in greater detail below.
| Rust | XPC |
|---|---|
| i64 | _xpc_type_int64 |
| u64 | _xpc_type_uint64 |
| f64 | _xpc_type_double |
| bool | _xpc_bool_true/false |
| Into | _xpc_type_string |
| HashMap<Into, Into> | _xpc_type_dictionary |
| Vec<Into> | _xpc_type_array |
| std::os::unix::prelude::RawFd | _xpc_type_fd |
| (MachPortType::Send, mach_port_t) | _xpc_type_mach_send |
| (MachPortType::Recv, mach_port_t) | _xpc_type_mach_recv |
| XPCShmem | _xpc_type_shmem |
Make XPC objects for anything with From<T>. Make sure to use the correct type for file descriptors and Mach ports:
let mut message: = new;
message.insert;
Go from an XPC object to value via the TryXPCValue trait. It checks your object's type via xpc_get_type() and yields a clear error if you're using the wrong type:
Object lifecycle
XPCObject wraps a xpc_object_t:
;
When it is dropped, xpc_release is called.
QueryBuilder
While we can go from HashMap<&str, XPCObject> to XPCObject, it can be a little verbose. A QueryBuilder trait exposes some builder methods to make building an XPC dictionary a little easier (without all of the into()s, and some additional error checking).
To write the query for launchctl list:
let LIST_SERVICES: XPCDictionary = new
// "list com.apple.Spotlight" (if specified)
// .entry("name", "com.apple.Spotlight");
.entry
.entry
.entry
.entry;
let reply: = new
// LIST_SERVICES is a proto
.extend
// Specify the domain type, or fall back on requester domain
.with_domain_type_or_default
.entry_if_present
.pipe_routine_with_error_handling;
In addition to checking errno is 0, pipe_routine_with_error_handling also looks for possible error and errors keys in the response dictionary and provides an Err() with xpc_strerror contents.
XPC Dictionary
Go from a HashMap to xpc_object_t with the XPCObject type:
let mut message: = new;
message.insert;
message.insert;
message.insert;
message.insert;
message.insert;
let xpc_object: XPCObject = message.into;
Call xpc_pipe_routine and receive Result<XPCObject, XPCError>:
let xpc_object: XPCObject = message.into;
match xpc_object.pipe_routine
The response is likely an XPC dictionary -- go back to a HashMap:
let xpc_object: XPCObject = message.into;
let response: = xpc_object
.pipe_routine
.and_then;
let XPCDictionary = response.unwrap;
let whatever = hm.get;
Response dictionaries can be nested, so XPCDictionary has a helper included for this scenario:
let xpc_object: XPCObject = message.into;
// A string: either "Aqua", "StandardIO", "Background", "LoginWindow", "System"
let response: = xpc_object
.pipe_routine
.and_then;
.and_then
Or, retrieve the service key (a child XPC Dictionary) from this response:
let xpc_object: XPCObject = message.into;
// A string: either "Aqua", "StandardIO", "Background", "LoginWindow", "System"
let response: = xpc_object
.pipe_routine
.and_then;
.and_then
XPC Array
An XPC array can be made from either Vec<XPCObject> or Vec<Into<XPCObject>>:
let xpc_array = from;
let xpc_array = from;
Go back to Vec using xpc_value:
let rs_vec: = xpc_array.xpc_value.unwrap;
XPC Shmem
Make XPC shared memory objects by providing a size and vm_allocate/mmap flags. vm_allocate is used to create the memory region, and vm_deallocate when XPCShmem is dropped.
let shmem = new_task_self?;
// Use as _xpc_type_shmem argument in XPCDictionary
let response = new
.extend
.entry
.pipe_routine_with_error_handling?;
To work with the shmem region, use slice_from_raw_parts:
let bytes: & = unsafe ;
// Make a string from bytes in the shmem
let mut hey_look_a_string = Stringnew;
bytes.read_to_string;
Credits
A big thanks to these open source projects and general resources:
- block Obj-C block support, necessary for any XPC function taking
xpc_*_applier_t - Cursive
- tokio
- plist
- notify
- bitflags
- libc
- lazy_static
- xcrun
- Apple Developer XPC services
- Apple Developer XPC API reference
- MOXIL / launjctl
- geosnow - A Long Evening With macOS' sandbox
- Bits of launchd - @5aelo
- Audit tokens explained (e.g. ASID)
- objc.io XPC guide
- Fortinet XPC RE article
- The various source links found in comments, from Chrome's sandbox and other headers with definitions for private API functions.
- After all, it is Apple's launchd :>)
Everything else (C) David Stancu & Contributors 2021