]> git.proxmox.com Git - rustc.git/blob - src/vendor/fuchsia-zircon/src/lib.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / fuchsia-zircon / src / lib.rs
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 {
125 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
166 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 {
175 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 {
203 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 {
251 fn from(err: io::Error) -> Status {
252 err.kind().into()
253 }
254 }
255
256 impl From<Status> for io::Error {
257 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.
363 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.
374 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.
383 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.
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.
401 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.
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.
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
436 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> {
459 pub fn raw_handle(&self) -> sys::zx_handle_t {
460 self.handle
461 }
462
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
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
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
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`.
500 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).
505 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.
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.
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.
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> {
534 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.
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.
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.
564 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.
571 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.
576 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.
582 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.
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.
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.
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
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.
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 {
663 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 {
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.
679 pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle {
680 Handle(raw)
681 }
682
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
890 fn cprng_add() {
891 let buffer = [0, 1, 2];
892 assert_eq!(cprng_add_entropy(&buffer), Ok(()));
893 }
894 }
895
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
903 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 }