1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Type-safe bindings for Zircon kernel
6 //! [syscalls](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls.md).
7 
8 extern crate fuchsia_zircon_sys as zircon_sys;
9 
10 use std::io;
11 use std::marker::PhantomData;
12 
13 macro_rules! impl_handle_based {
14     ($type_name:path) => {
15         impl AsHandleRef for $type_name {
16             fn as_handle_ref(&self) -> HandleRef {
17                 self.0.as_handle_ref()
18             }
19         }
20 
21         impl From<Handle> for $type_name {
22             fn from(handle: Handle) -> Self {
23                 $type_name(handle)
24             }
25         }
26 
27         impl From<$type_name> for Handle {
28             fn from(x: $type_name) -> Handle {
29                 x.0
30             }
31         }
32 
33         impl HandleBased for $type_name {}
34     }
35 }
36 
37 mod channel;
38 mod event;
39 mod eventpair;
40 mod fifo;
41 mod job;
42 mod port;
43 mod process;
44 mod socket;
45 mod timer;
46 mod thread;
47 mod vmo;
48 
49 pub use channel::{Channel, ChannelOpts, MessageBuf};
50 pub use event::{Event, EventOpts};
51 pub use eventpair::{EventPair, EventPairOpts};
52 pub use fifo::{Fifo, FifoOpts};
53 pub use job::Job;
54 pub use port::{Packet, PacketContents, Port, PortOpts, SignalPacket, UserPacket, WaitAsyncOpts};
55 pub use process::Process;
56 pub use socket::{Socket, SocketOpts, SocketReadOpts, SocketWriteOpts};
57 pub use timer::{Timer, TimerOpts};
58 pub use thread::Thread;
59 pub use vmo::{Vmo, VmoCloneOpts, VmoOp, VmoOpts};
60 
61 use zircon_sys as sys;
62 
63 type Duration = sys::zx_duration_t;
64 type Time = sys::zx_time_t;
65 pub use zircon_sys::ZX_TIME_INFINITE;
66 
67 // A placeholder value used for handles that have been taken from the message buf.
68 // We rely on the kernel never to produce any actual handles with this value.
69 const INVALID_HANDLE: sys::zx_handle_t = 0;
70 
71 /// A status code returned from the Zircon kernel.
72 ///
73 /// See
74 /// [errors.md](https://fuchsia.googlesource.com/zircon/+/master/docs/errors.md)
75 /// in the Zircon documentation for more information about the meaning of these
76 /// codes.
77 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
78 #[repr(i32)]
79 // Auto-generated using tools/gen_status.py
80 pub enum Status {
81     NoError = 0,
82     ErrInternal = -1,
83     ErrNotSupported = -2,
84     ErrNoResources = -3,
85     ErrNoMemory = -4,
86     ErrCallFailed = -5,
87     ErrInterruptedRetry = -6,
88     ErrInvalidArgs = -10,
89     ErrBadHandle = -11,
90     ErrWrongType = -12,
91     ErrBadSyscall = -13,
92     ErrOutOfRange = -14,
93     ErrBufferTooSmall = -15,
94     ErrBadState = -20,
95     ErrTimedOut = -21,
96     ErrShouldWait = -22,
97     ErrCanceled = -23,
98     ErrPeerClosed = -24,
99     ErrNotFound = -25,
100     ErrAlreadyExists = -26,
101     ErrAlreadyBound = -27,
102     ErrUnavailable = -28,
103     ErrAccessDenied = -30,
104     ErrIo = -40,
105     ErrIoRefused = -41,
106     ErrIoDataIntegrity = -42,
107     ErrIoDataLoss = -43,
108     ErrBadPath = -50,
109     ErrNotDir = -51,
110     ErrNotFile = -52,
111     ErrFileBig = -53,
112     ErrNoSpace = -54,
113     ErrStop = -60,
114     ErrNext = -61,
115 
116     /// Any zx_status_t not in the set above will map to the following:
117     UnknownOther = -32768,
118 
119     // used to prevent exhaustive matching
120     #[doc(hidden)]
121     __Nonexhaustive = -32787,
122 }
123 
124 impl Status {
from_raw(raw: sys::zx_status_t) -> Self125     pub fn from_raw(raw: sys::zx_status_t) -> Self {
126         match raw {
127             // Auto-generated using tools/gen_status.py
128             sys::ZX_OK => Status::NoError,
129             sys::ZX_ERR_INTERNAL => Status::ErrInternal,
130             sys::ZX_ERR_NOT_SUPPORTED => Status::ErrNotSupported,
131             sys::ZX_ERR_NO_RESOURCES => Status::ErrNoResources,
132             sys::ZX_ERR_NO_MEMORY => Status::ErrNoMemory,
133             sys::ZX_ERR_CALL_FAILED => Status::ErrCallFailed,
134             sys::ZX_ERR_INTERRUPTED_RETRY => Status::ErrInterruptedRetry,
135             sys::ZX_ERR_INVALID_ARGS => Status::ErrInvalidArgs,
136             sys::ZX_ERR_BAD_HANDLE => Status::ErrBadHandle,
137             sys::ZX_ERR_WRONG_TYPE => Status::ErrWrongType,
138             sys::ZX_ERR_BAD_SYSCALL => Status::ErrBadSyscall,
139             sys::ZX_ERR_OUT_OF_RANGE => Status::ErrOutOfRange,
140             sys::ZX_ERR_BUFFER_TOO_SMALL => Status::ErrBufferTooSmall,
141             sys::ZX_ERR_BAD_STATE => Status::ErrBadState,
142             sys::ZX_ERR_TIMED_OUT => Status::ErrTimedOut,
143             sys::ZX_ERR_SHOULD_WAIT => Status::ErrShouldWait,
144             sys::ZX_ERR_CANCELED => Status::ErrCanceled,
145             sys::ZX_ERR_PEER_CLOSED => Status::ErrPeerClosed,
146             sys::ZX_ERR_NOT_FOUND => Status::ErrNotFound,
147             sys::ZX_ERR_ALREADY_EXISTS => Status::ErrAlreadyExists,
148             sys::ZX_ERR_ALREADY_BOUND => Status::ErrAlreadyBound,
149             sys::ZX_ERR_UNAVAILABLE => Status::ErrUnavailable,
150             sys::ZX_ERR_ACCESS_DENIED => Status::ErrAccessDenied,
151             sys::ZX_ERR_IO => Status::ErrIo,
152             sys::ZX_ERR_IO_REFUSED => Status::ErrIoRefused,
153             sys::ZX_ERR_IO_DATA_INTEGRITY => Status::ErrIoDataIntegrity,
154             sys::ZX_ERR_IO_DATA_LOSS => Status::ErrIoDataLoss,
155             sys::ZX_ERR_BAD_PATH => Status::ErrBadPath,
156             sys::ZX_ERR_NOT_DIR => Status::ErrNotDir,
157             sys::ZX_ERR_NOT_FILE => Status::ErrNotFile,
158             sys::ZX_ERR_FILE_BIG => Status::ErrFileBig,
159             sys::ZX_ERR_NO_SPACE => Status::ErrNoSpace,
160             sys::ZX_ERR_STOP => Status::ErrStop,
161             sys::ZX_ERR_NEXT => Status::ErrNext,
162             _ => Status::UnknownOther,
163         }
164     }
165 
into_io_err(self) -> io::Error166     pub fn into_io_err(self) -> io::Error {
167         self.into()
168     }
169 
170     // Note: no to_raw, even though it's easy to implement, partly because
171     // handling of UnknownOther would be tricky.
172 }
173 
174 impl From<io::ErrorKind> for Status {
from(kind: io::ErrorKind) -> Self175     fn from(kind: io::ErrorKind) -> Self {
176         use io::ErrorKind::*;
177         use Status::*;
178 
179         match kind {
180             NotFound => ErrNotFound,
181             PermissionDenied => ErrAccessDenied,
182             ConnectionRefused => ErrIoRefused,
183             ConnectionAborted => ErrPeerClosed,
184             AddrInUse => ErrAlreadyBound,
185             AddrNotAvailable => ErrUnavailable,
186             BrokenPipe => ErrPeerClosed,
187             AlreadyExists => ErrAlreadyExists,
188             WouldBlock => ErrShouldWait,
189             InvalidInput => ErrInvalidArgs,
190             TimedOut => ErrTimedOut,
191             Interrupted => ErrInterruptedRetry,
192 
193             UnexpectedEof |
194             WriteZero |
195             ConnectionReset |
196             NotConnected |
197             Other | _ => ErrIo,
198         }
199     }
200 }
201 
202 impl From<Status> for io::ErrorKind {
from(status: Status) -> io::ErrorKind203     fn from(status: Status) -> io::ErrorKind {
204         use io::ErrorKind::*;
205         use Status::*;
206 
207         match status {
208             ErrInterruptedRetry => Interrupted,
209             ErrBadHandle => BrokenPipe,
210             ErrTimedOut => TimedOut,
211             ErrShouldWait => WouldBlock,
212             ErrPeerClosed => ConnectionAborted,
213             ErrNotFound => NotFound,
214             ErrAlreadyExists => AlreadyExists,
215             ErrAlreadyBound => AlreadyExists,
216             ErrUnavailable => AddrNotAvailable,
217             ErrAccessDenied => PermissionDenied,
218             ErrIoRefused => ConnectionRefused,
219             ErrIoDataIntegrity => InvalidData,
220 
221             ErrBadPath |
222             ErrInvalidArgs |
223             ErrOutOfRange |
224             ErrWrongType => InvalidInput,
225 
226             Status::__Nonexhaustive |
227             UnknownOther |
228             NoError |
229             ErrNext |
230             ErrStop |
231             ErrNoSpace |
232             ErrFileBig |
233             ErrNotFile |
234             ErrNotDir |
235             ErrIoDataLoss |
236             ErrIo |
237             ErrCanceled |
238             ErrBadState |
239             ErrBufferTooSmall |
240             ErrBadSyscall |
241             ErrInternal |
242             ErrNotSupported |
243             ErrNoResources |
244             ErrNoMemory |
245             ErrCallFailed => Other,
246         }
247     }
248 }
249 
250 impl From<io::Error> for Status {
from(err: io::Error) -> Status251     fn from(err: io::Error) -> Status {
252         err.kind().into()
253     }
254 }
255 
256 impl From<Status> for io::Error {
from(status: Status) -> io::Error257     fn from(status: Status) -> io::Error {
258         io::Error::from(io::ErrorKind::from(status))
259     }
260 }
261 
262 /// Rights associated with a handle.
263 ///
264 /// See [rights.md](https://fuchsia.googlesource.com/zircon/+/master/docs/rights.md)
265 /// for more information.
266 pub type Rights = sys::zx_rights_t;
267 pub use zircon_sys::{
268     ZX_RIGHT_NONE,
269     ZX_RIGHT_DUPLICATE,
270     ZX_RIGHT_TRANSFER,
271     ZX_RIGHT_READ,
272     ZX_RIGHT_WRITE,
273     ZX_RIGHT_EXECUTE,
274     ZX_RIGHT_MAP,
275     ZX_RIGHT_GET_PROPERTY,
276     ZX_RIGHT_SET_PROPERTY,
277     ZX_RIGHT_DEBUG,
278     ZX_RIGHT_SAME_RIGHTS,
279 };
280 
281 /// Signals that can be waited upon.
282 ///
283 /// See
284 /// [Objects and signals](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Objects-and-Signals)
285 /// in the Zircon kernel documentation. Note: the names of signals are still in flux.
286 pub type Signals = sys::zx_signals_t;
287 
288 pub use zircon_sys::{
289         ZX_SIGNAL_NONE,
290 
291         ZX_SIGNAL_HANDLE_CLOSED,
292         ZX_SIGNAL_LAST_HANDLE,
293 
294         ZX_USER_SIGNAL_0,
295         ZX_USER_SIGNAL_1,
296         ZX_USER_SIGNAL_2,
297         ZX_USER_SIGNAL_3,
298         ZX_USER_SIGNAL_4,
299         ZX_USER_SIGNAL_5,
300         ZX_USER_SIGNAL_6,
301         ZX_USER_SIGNAL_7,
302 
303         // Event
304         ZX_EVENT_SIGNALED,
305 
306         // EventPair
307         ZX_EPAIR_SIGNALED,
308         ZX_EPAIR_CLOSED,
309 
310         // Task signals (process, thread, job)
311         ZX_TASK_TERMINATED,
312 
313         // Channel
314         ZX_CHANNEL_READABLE,
315         ZX_CHANNEL_WRITABLE,
316         ZX_CHANNEL_PEER_CLOSED,
317 
318         // Socket
319         ZX_SOCKET_READABLE,
320         ZX_SOCKET_WRITABLE,
321         ZX_SOCKET_PEER_CLOSED,
322 
323         // Timer
324         ZX_TIMER_SIGNALED,
325 };
326 
327 /// A "wait item" containing a handle reference and information about what signals
328 /// to wait on, and, on return from `object_wait_many`, which are pending.
329 #[repr(C)]
330 #[derive(Debug)]
331 pub struct WaitItem<'a> {
332     /// The handle to wait on.
333     pub handle: HandleRef<'a>,
334     /// A set of signals to wait for.
335     pub waitfor: Signals,
336     /// The set of signals pending, on return of `object_wait_many`.
337     pub pending: Signals,
338 }
339 
340 
341 /// An identifier to select a particular clock. See
342 /// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md)
343 /// for more information about the possible values.
344 #[repr(u32)]
345 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
346 pub enum ClockId {
347     /// The number of nanoseconds since the system was powered on. Corresponds to
348     /// `ZX_CLOCK_MONOTONIC`.
349     Monotonic = 0,
350     /// The number of wall clock nanoseconds since the Unix epoch (midnight on January 1 1970) in
351     /// UTC. Corresponds to ZX_CLOCK_UTC.
352     UTC = 1,
353     /// The number of nanoseconds the current thread has been running for. Corresponds to
354     /// ZX_CLOCK_THREAD.
355     Thread = 2,
356 }
357 
358 /// Get the current time, from the specific clock id.
359 ///
360 /// Wraps the
361 /// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md)
362 /// syscall.
time_get(clock_id: ClockId) -> Time363 pub fn time_get(clock_id: ClockId) -> Time {
364     unsafe { sys::zx_time_get(clock_id as u32) }
365 }
366 
367 /// Read the number of high-precision timer ticks since boot. These ticks may be processor cycles,
368 /// high speed timer, profiling timer, etc. They are not guaranteed to continue advancing when the
369 /// system is asleep.
370 ///
371 /// Wraps the
372 /// [zx_ticks_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/ticks_get.md)
373 /// syscall.
ticks_get() -> u64374 pub fn ticks_get() -> u64 {
375     unsafe { sys::zx_ticks_get() }
376 }
377 
378 /// Compute a deadline for the time in the future that is the given `Duration` away.
379 ///
380 /// Wraps the
381 /// [zx_deadline_after](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/deadline_after.md)
382 /// syscall.
deadline_after(nanos: Duration) -> Time383 pub fn deadline_after(nanos: Duration) -> Time {
384     unsafe { sys::zx_deadline_after(nanos) }
385 }
386 
387 /// Sleep until the given deadline.
388 ///
389 /// Wraps the
390 /// [zx_nanosleep](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/nanosleep.md)
391 /// syscall.
nanosleep(deadline: Time)392 pub fn nanosleep(deadline: Time) {
393     unsafe { sys::zx_nanosleep(deadline); }
394 }
395 
396 /// Return the number of high-precision timer ticks in a second.
397 ///
398 /// Wraps the
399 /// [zx_ticks_per_second](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/ticks_per_second.md)
400 /// syscall.
ticks_per_second() -> u64401 pub fn ticks_per_second() -> u64 {
402     unsafe { sys::zx_ticks_per_second() }
403 }
404 
405 pub use zircon_sys::{
406     ZX_CPRNG_DRAW_MAX_LEN,
407     ZX_CPRNG_ADD_ENTROPY_MAX_LEN,
408 };
409 
410 /// Draw random bytes from the kernel's CPRNG to fill the given buffer. Returns the actual number of
411 /// bytes drawn, which may sometimes be less than the size of the buffer provided.
412 ///
413 /// The buffer must have length less than `ZX_CPRNG_DRAW_MAX_LEN`.
414 ///
415 /// Wraps the
416 /// [zx_cprng_draw](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md)
417 /// syscall.
cprng_draw(buffer: &mut [u8]) -> Result<usize, Status>418 pub fn cprng_draw(buffer: &mut [u8]) -> Result<usize, Status> {
419     let mut actual = 0;
420     let status = unsafe { sys::zx_cprng_draw(buffer.as_mut_ptr(), buffer.len(), &mut actual) };
421     into_result(status, || actual)
422 }
423 
424 /// Mix the given entropy into the kernel CPRNG.
425 ///
426 /// The buffer must have length less than `ZX_CPRNG_ADD_ENTROPY_MAX_LEN`.
427 ///
428 /// Wraps the
429 /// [zx_cprng_add_entropy](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_add_entropy.md)
430 /// syscall.
cprng_add_entropy(buffer: &[u8]) -> Result<(), Status>431 pub fn cprng_add_entropy(buffer: &[u8]) -> Result<(), Status> {
432     let status = unsafe { sys::zx_cprng_add_entropy(buffer.as_ptr(), buffer.len()) };
433     into_result(status, || ())
434 }
435 
into_result<T, F>(status: sys::zx_status_t, f: F) -> Result<T, Status> where F: FnOnce() -> T436 fn into_result<T, F>(status: sys::zx_status_t, f: F) -> Result<T, Status>
437     where F: FnOnce() -> T {
438     // All non-negative values are assumed successful. Note: calls that don't try
439     // to multiplex success values into status return could be more strict here.
440     if status >= 0 {
441         Ok(f())
442     } else {
443         Err(Status::from_raw(status))
444     }
445 }
446 
447 // Handles
448 
449 /// A borrowed reference to a `Handle`.
450 ///
451 /// Mostly useful as part of a `WaitItem`.
452 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
453 pub struct HandleRef<'a> {
454     handle: sys::zx_handle_t,
455     phantom: PhantomData<&'a sys::zx_handle_t>,
456 }
457 
458 impl<'a> HandleRef<'a> {
raw_handle(&self) -> sys::zx_handle_t459     pub fn raw_handle(&self) -> sys::zx_handle_t {
460         self.handle
461     }
462 
duplicate(&self, rights: Rights) -> Result<Handle, Status>463     pub fn duplicate(&self, rights: Rights) -> Result<Handle, Status> {
464         let handle = self.handle;
465         let mut out = 0;
466         let status = unsafe { sys::zx_handle_duplicate(handle, rights, &mut out) };
467         into_result(status, || Handle(out))
468     }
469 
signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status>470     pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
471         let handle = self.handle;
472         let status = unsafe { sys::zx_object_signal(handle, clear_mask.bits(), set_mask.bits()) };
473         into_result(status, || ())
474     }
475 
wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status>476     pub fn wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
477         let handle = self.handle;
478         let mut pending = sys::zx_signals_t::empty();
479         let status = unsafe {
480             sys::zx_object_wait_one(handle, signals, deadline, &mut pending)
481         };
482         into_result(status, || pending)
483     }
484 
wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts) -> Result<(), Status>485     pub fn wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
486         -> Result<(), Status>
487     {
488         let handle = self.handle;
489         let status = unsafe {
490             sys::zx_object_wait_async(handle, port.raw_handle(), key, signals, options as u32)
491         };
492         into_result(status, || ())
493     }
494 }
495 
496 /// A trait to get a reference to the underlying handle of an object.
497 pub trait AsHandleRef {
498     /// Get a reference to the handle. One important use of such a reference is
499     /// for `object_wait_many`.
as_handle_ref(&self) -> HandleRef500     fn as_handle_ref(&self) -> HandleRef;
501 
502     /// Interpret the reference as a raw handle (an integer type). Two distinct
503     /// handles will have different raw values (so it can perhaps be used as a
504     /// key in a data structure).
raw_handle(&self) -> sys::zx_handle_t505     fn raw_handle(&self) -> sys::zx_handle_t {
506         self.as_handle_ref().raw_handle()
507     }
508 
509     /// Set and clear userspace-accessible signal bits on an object. Wraps the
510     /// [zx_object_signal](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
511     /// syscall.
signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status>512     fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
513         self.as_handle_ref().signal(clear_mask, set_mask)
514     }
515 
516     /// Waits on a handle. Wraps the
517     /// [zx_object_wait_one](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_one.md)
518     /// syscall.
wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status>519     fn wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
520         self.as_handle_ref().wait(signals, deadline)
521     }
522 
523     /// Causes packet delivery on the given port when the object changes state and matches signals.
524     /// [zx_object_wait_async](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_async.md)
525     /// syscall.
wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts) -> Result<(), Status>526     fn wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
527         -> Result<(), Status>
528     {
529         self.as_handle_ref().wait_async(port, key, signals, options)
530     }
531 }
532 
533 impl<'a> AsHandleRef for HandleRef<'a> {
as_handle_ref(&self) -> HandleRef534     fn as_handle_ref(&self) -> HandleRef { *self }
535 }
536 
537 /// A trait implemented by all handle-based types.
538 ///
539 /// Note: it is reasonable for user-defined objects wrapping a handle to implement
540 /// this trait. For example, a specific interface in some protocol might be
541 /// represented as a newtype of `Channel`, and implement the `as_handle_ref`
542 /// method and the `From<Handle>` trait to facilitate conversion from and to the
543 /// interface.
544 pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
545     /// Duplicate a handle, possibly reducing the rights available. Wraps the
546     /// [zx_handle_duplicate](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_duplicate.md)
547     /// syscall.
duplicate_handle(&self, rights: Rights) -> Result<Self, Status>548     fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
549         self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
550     }
551 
552     /// Create a replacement for a handle, possibly reducing the rights available. This invalidates
553     /// the original handle. Wraps the
554     /// [zx_handle_replace](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_replace.md)
555     /// syscall.
replace_handle(self, rights: Rights) -> Result<Self, Status>556     fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
557         <Self as Into<Handle>>::into(self)
558             .replace(rights).map(|handle| Self::from(handle))
559     }
560 
561     /// Converts the value into its inner handle.
562     ///
563     /// This is a convenience function which simply forwards to the `Into` trait.
into_handle(self) -> Handle564     fn into_handle(self) -> Handle {
565         self.into()
566     }
567 
568     /// Creates an instance of this type from a handle.
569     ///
570     /// This is a convenience function which simply forwards to the `From` trait.
from_handle(handle: Handle) -> Self571     fn from_handle(handle: Handle) -> Self {
572         Self::from(handle)
573     }
574 
575     /// Creates an instance of another handle-based type from this value's inner handle.
into_handle_based<H: HandleBased>(self) -> H576     fn into_handle_based<H: HandleBased>(self) -> H {
577         H::from_handle(self.into_handle())
578     }
579 
580     /// Creates an instance of this type from the inner handle of another
581     /// handle-based type.
from_handle_based<H: HandleBased>(h: H) -> Self582     fn from_handle_based<H: HandleBased>(h: H) -> Self {
583         Self::from_handle(h.into_handle())
584     }
585 }
586 
587 /// A trait implemented by all handles for objects which have a peer.
588 pub trait Peered: HandleBased {
589     /// Set and clear userspace-accessible signal bits on the object's peer. Wraps the
590     /// [zx_object_signal_peer](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
591     /// syscall.
signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status>592     fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
593         let handle = self.as_handle_ref().handle;
594         let status = unsafe {
595             sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits())
596         };
597         into_result(status, || ())
598     }
599 }
600 
601 /// A trait implemented by all handles for objects which can have a cookie attached.
602 pub trait Cookied: HandleBased {
603     /// Get the cookie attached to this object, if any. Wraps the
604     /// [zx_object_get_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_get_cookie.md)
605     /// syscall.
get_cookie(&self, scope: &HandleRef) -> Result<u64, Status>606     fn get_cookie(&self, scope: &HandleRef) -> Result<u64, Status> {
607         let handle = self.as_handle_ref().handle;
608         let mut cookie = 0;
609         let status = unsafe { sys::zx_object_get_cookie(handle, scope.handle, &mut cookie) };
610         into_result(status, || cookie)
611     }
612 
613     /// Attach an opaque cookie to this object with the given scope. The cookie may be read or
614     /// changed in future only with the same scope. Wraps the
615     /// [zx_object_set_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_set_cookie.md)
616     /// syscall.
set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status>617     fn set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status> {
618         let handle = self.as_handle_ref().handle;
619         let status = unsafe { sys::zx_object_set_cookie(handle, scope.handle, cookie) };
620         into_result(status, || ())
621     }
622 }
623 
handle_drop(handle: sys::zx_handle_t)624 fn handle_drop(handle: sys::zx_handle_t) {
625     let _ = unsafe { sys::zx_handle_close(handle) };
626 }
627 
628 /// Wait on multiple handles.
629 /// The success return value is a bool indicating whether one or more of the
630 /// provided handle references was closed during the wait.
631 ///
632 /// Wraps the
633 /// [zx_object_wait_many](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_many.md)
634 /// syscall.
object_wait_many(items: &mut [WaitItem], deadline: Time) -> Result<bool, Status>635 pub fn object_wait_many(items: &mut [WaitItem], deadline: Time) -> Result<bool, Status>
636 {
637     let len = try!(usize_into_u32(items.len()).map_err(|_| Status::ErrOutOfRange));
638     let items_ptr = items.as_mut_ptr() as *mut sys::zx_wait_item_t;
639     let status = unsafe { sys::zx_object_wait_many( items_ptr, len, deadline) };
640     if status == sys::ZX_ERR_CANCELED {
641         return Ok((true))
642     }
643     into_result(status, || false)
644 }
645 
646 // An untyped handle
647 
648 /// An object representing a Zircon
649 /// [handle](https://fuchsia.googlesource.com/zircon/+/master/docs/handles.md).
650 ///
651 /// Internally, it is represented as a 32-bit integer, but this wrapper enforces
652 /// strict ownership semantics. The `Drop` implementation closes the handle.
653 ///
654 /// This type represents the most general reference to a kernel object, and can
655 /// be interconverted to and from more specific types. Those conversions are not
656 /// enforced in the type system; attempting to use them will result in errors
657 /// returned by the kernel. These conversions don't change the underlying
658 /// representation, but do change the type and thus what operations are available.
659 #[derive(Debug, Eq, PartialEq, Hash)]
660 pub struct Handle(sys::zx_handle_t);
661 
662 impl AsHandleRef for Handle {
as_handle_ref(&self) -> HandleRef663     fn as_handle_ref(&self) -> HandleRef {
664         HandleRef { handle: self.0, phantom: Default::default() }
665     }
666 }
667 
668 impl HandleBased for Handle {}
669 
670 impl Drop for Handle {
drop(&mut self)671     fn drop(&mut self) {
672         handle_drop(self.0)
673     }
674 }
675 
676 impl Handle {
677     /// If a raw handle is obtained from some other source, this method converts
678     /// it into a type-safe owned handle.
from_raw(raw: sys::zx_handle_t) -> Handle679     pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle {
680         Handle(raw)
681     }
682 
replace(self, rights: Rights) -> Result<Handle, Status>683     pub fn replace(self, rights: Rights) -> Result<Handle, Status> {
684         let handle = self.0;
685         let mut out = 0;
686         let status = unsafe { sys::zx_handle_replace(handle, rights, &mut out) };
687         into_result(status, || Handle(out))
688     }
689 }
690 
691 #[cfg(test)]
692 mod tests {
693     use super::*;
694 
695     #[test]
monotonic_time_increases()696     fn monotonic_time_increases() {
697         let time1 = time_get(ClockId::Monotonic);
698         nanosleep(deadline_after(1_000));
699         let time2 = time_get(ClockId::Monotonic);
700         assert!(time2 > time1);
701     }
702 
703     #[test]
utc_time_increases()704     fn utc_time_increases() {
705         let time1 = time_get(ClockId::UTC);
706         nanosleep(deadline_after(1_000));
707         let time2 = time_get(ClockId::UTC);
708         assert!(time2 > time1);
709     }
710 
711     #[test]
thread_time_increases()712     fn thread_time_increases() {
713         let time1 = time_get(ClockId::Thread);
714         nanosleep(deadline_after(1_000));
715         let time2 = time_get(ClockId::Thread);
716         assert!(time2 > time1);
717     }
718 
719     #[test]
ticks_increases()720     fn ticks_increases() {
721         let ticks1 = ticks_get();
722         nanosleep(deadline_after(1_000));
723         let ticks2 = ticks_get();
724         assert!(ticks2 > ticks1);
725     }
726 
727     #[test]
tick_length()728     fn tick_length() {
729         let sleep_ns = 1_000_000;  // 1ms
730         let one_second_ns = 1_000_000_000; // 1 second in ns
731         let ticks1 = ticks_get();
732         nanosleep(deadline_after(sleep_ns));
733         let ticks2 = ticks_get();
734         // The number of ticks should have increased by at least 1 ms worth
735         assert!(ticks2 > ticks1 + sleep_ns * ticks_per_second() / one_second_ns);
736     }
737 
738     #[test]
sleep()739     fn sleep() {
740         let sleep_ns = 1_000_000;  // 1ms
741         let time1 = time_get(ClockId::Monotonic);
742         nanosleep(deadline_after(sleep_ns));
743         let time2 = time_get(ClockId::Monotonic);
744         assert!(time2 > time1 + sleep_ns);
745     }
746 
747     /// Test duplication by means of a VMO
748     #[test]
duplicate()749     fn duplicate() {
750         let hello_length: usize = 5;
751 
752         // Create a VMO and write some data to it.
753         let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
754         assert!(vmo.write(b"hello", 0).is_ok());
755 
756         // Replace, reducing rights to read.
757         let readonly_vmo = vmo.duplicate_handle(ZX_RIGHT_READ).unwrap();
758         // Make sure we can read but not write.
759         let mut read_vec = vec![0; hello_length];
760         assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
761         assert_eq!(read_vec, b"hello");
762         assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ErrAccessDenied));
763 
764         // Write new data to the original handle, and read it from the new handle
765         assert!(vmo.write(b"bye", 0).is_ok());
766         assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
767         assert_eq!(read_vec, b"byelo");
768     }
769 
770     // Test replace by means of a VMO
771     #[test]
replace()772     fn replace() {
773         let hello_length: usize = 5;
774 
775         // Create a VMO and write some data to it.
776         let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
777         assert!(vmo.write(b"hello", 0).is_ok());
778 
779         // Replace, reducing rights to read.
780         let readonly_vmo = vmo.replace_handle(ZX_RIGHT_READ).unwrap();
781         // Make sure we can read but not write.
782         let mut read_vec = vec![0; hello_length];
783         assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
784         assert_eq!(read_vec, b"hello");
785         assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ErrAccessDenied));
786     }
787 
788     #[test]
wait_and_signal()789     fn wait_and_signal() {
790         let event = Event::create(EventOpts::Default).unwrap();
791         let ten_ms: Duration = 10_000_000;
792 
793         // Waiting on it without setting any signal should time out.
794         assert_eq!(event.wait_handle(
795             ZX_USER_SIGNAL_0, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
796 
797         // If we set a signal, we should be able to wait for it.
798         assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
799         assert_eq!(event.wait_handle(ZX_USER_SIGNAL_0, deadline_after(ten_ms)).unwrap(),
800             ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
801 
802         // Should still work, signals aren't automatically cleared.
803         assert_eq!(event.wait_handle(ZX_USER_SIGNAL_0, deadline_after(ten_ms)).unwrap(),
804             ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
805 
806         // Now clear it, and waiting should time out again.
807         assert!(event.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());
808         assert_eq!(event.wait_handle(
809             ZX_USER_SIGNAL_0, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
810     }
811 
812     #[test]
wait_many_and_signal()813     fn wait_many_and_signal() {
814         let ten_ms: Duration = 10_000_000;
815         let e1 = Event::create(EventOpts::Default).unwrap();
816         let e2 = Event::create(EventOpts::Default).unwrap();
817 
818         // Waiting on them now should time out.
819         let mut items = vec![
820           WaitItem { handle: e1.as_handle_ref(), waitfor: ZX_USER_SIGNAL_0, pending: ZX_SIGNAL_NONE },
821           WaitItem { handle: e2.as_handle_ref(), waitfor: ZX_USER_SIGNAL_1, pending: ZX_SIGNAL_NONE },
822         ];
823         assert_eq!(object_wait_many(&mut items, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
824         assert_eq!(items[0].pending, ZX_SIGNAL_LAST_HANDLE);
825         assert_eq!(items[1].pending, ZX_SIGNAL_LAST_HANDLE);
826 
827         // Signal one object and it should return success.
828         assert!(e1.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
829         assert!(object_wait_many(&mut items, deadline_after(ten_ms)).is_ok());
830         assert_eq!(items[0].pending, ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
831         assert_eq!(items[1].pending, ZX_SIGNAL_LAST_HANDLE);
832 
833         // Signal the other and it should return both.
834         assert!(e2.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_1).is_ok());
835         assert!(object_wait_many(&mut items, deadline_after(ten_ms)).is_ok());
836         assert_eq!(items[0].pending, ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
837         assert_eq!(items[1].pending, ZX_USER_SIGNAL_1 | ZX_SIGNAL_LAST_HANDLE);
838 
839         // Clear signals on both; now it should time out again.
840         assert!(e1.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());
841         assert!(e2.signal_handle(ZX_USER_SIGNAL_1, ZX_SIGNAL_NONE).is_ok());
842         assert_eq!(object_wait_many(&mut items, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
843         assert_eq!(items[0].pending, ZX_SIGNAL_LAST_HANDLE);
844         assert_eq!(items[1].pending, ZX_SIGNAL_LAST_HANDLE);
845     }
846 
847     #[test]
cookies()848     fn cookies() {
849         let event = Event::create(EventOpts::Default).unwrap();
850         let scope = Event::create(EventOpts::Default).unwrap();
851 
852         // Getting a cookie when none has been set should fail.
853         assert_eq!(event.get_cookie(&scope.as_handle_ref()), Err(Status::ErrAccessDenied));
854 
855         // Set a cookie.
856         assert_eq!(event.set_cookie(&scope.as_handle_ref(), 42), Ok(()));
857 
858         // Should get it back....
859         assert_eq!(event.get_cookie(&scope.as_handle_ref()), Ok(42));
860 
861         // but not with the wrong scope!
862         assert_eq!(event.get_cookie(&event.as_handle_ref()), Err(Status::ErrAccessDenied));
863 
864         // Can change it, with the same scope...
865         assert_eq!(event.set_cookie(&scope.as_handle_ref(), 123), Ok(()));
866 
867         // but not with a different scope.
868         assert_eq!(event.set_cookie(&event.as_handle_ref(), 123), Err(Status::ErrAccessDenied));
869     }
870 
871     #[test]
cprng()872     fn cprng() {
873         let mut buffer = [0; 20];
874         assert_eq!(cprng_draw(&mut buffer), Ok(20));
875         assert_ne!(buffer[0], 0);
876         assert_ne!(buffer[19], 0);
877     }
878 
879     #[test]
cprng_too_large()880     fn cprng_too_large() {
881         let mut buffer = [0; ZX_CPRNG_DRAW_MAX_LEN + 1];
882         assert_eq!(cprng_draw(&mut buffer), Err(Status::ErrInvalidArgs));
883 
884         for mut s in buffer.chunks_mut(ZX_CPRNG_DRAW_MAX_LEN) {
885             assert_eq!(cprng_draw(&mut s), Ok(s.len()));
886         }
887     }
888 
889     #[test]
cprng_add()890     fn cprng_add() {
891         let buffer = [0, 1, 2];
892         assert_eq!(cprng_add_entropy(&buffer), Ok(()));
893     }
894 }
895 
usize_into_u32(n: usize) -> Result<u32, ()>896 pub fn usize_into_u32(n: usize) -> Result<u32, ()> {
897     if n > ::std::u32::MAX as usize || n < ::std::u32::MIN as usize {
898         return Err(())
899     }
900     Ok(n as u32)
901 }
902 
size_to_u32_sat(n: usize) -> u32903 pub fn size_to_u32_sat(n: usize) -> u32 {
904     if n > ::std::u32::MAX as usize {
905         return ::std::u32::MAX;
906     }
907     if n < ::std::u32::MIN as usize {
908         return ::std::u32::MIN;
909     }
910     n as u32
911 }
912