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.
| Rust | XPC |
|---|---|
| i64/i32 | _xpc_type_int64 |
| u64/u32 | _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>. XPCShmem and file descriptors have their own constructors:
use DictBuilder;
let fd = unsafe ;
let shmem = allocate_task_self?;
// pub type XPCHashMap = HashMap<String, Arc<XPCObject>>
let dict: XPCHashMap = new
.entry
.entry;
Go from an XPC object to value via to_rust() from the TryXPCIntoRust trait. Object types are checked with xpc_get_type() to yield a clear error if trying to read as the wrong type:
Object lifecycle
XPCObject wraps a xpc_object_t:
;
When it is dropped, xpc_release is called.
XPC Dictionary
Go from a HashMap to xpc_object_t:
use DictBuilder;
// pub type XPCHashMap = HashMap<String, Arc<XPCObject>>
let dict: XPCHashMap = new
.entry;
.entry;
.entry;
.entry;
.entry;
let xpc_object: XPCObject = dict.into
let ptr: xpc_object_t = xpc_object.as_ptr;
Go from XPCObject back to HashMap:
let xpc_object: XPCObject = unsafe ;
// Error if something is wrong during conversion (e.g. the pointer is not a XPC dictionary)
match xpc_object.to_rust
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 _xpc_type_shmem value in XPC Dictionary
let response = new
.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;
API
The following XPC functions have Rust friendly wrappers, all of which return Result<XPCObject, XPCError>:
| Function | Rust API |
|---|---|
| xpc_pipe_routine | api::pipe_routine::pipe_routine |
| xpc_pipe_routine_with_flags | api::pipe_routine::pipe_routine_with_flags |
| _xpc_pipe_interface_routine | api::pipe_routine::pipe_interface_routine |
If desired, errors in the XPC reply can be handled by chaining api::handle_reply_dict_errors onto the pipe routine call.
This is an example of sending launchctl bootout via the XPC bootstrap pipe:
let dict = new
.entry
.entry
// Current user UID
.entry
// Domain
.entry;
let reply: XPCHashMap = pipe_interface_routine
// Check for errors in response XPC dictionary (if desired)
.and_then
// Convert reply to a Rust hash map
.and_then
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.