// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Bindings for the Zircon fdio library

mod fdio_sys;

mod spawn_builder;

pub use spawn_builder::{Error as SpawnBuilderError, SpawnBuilder};

use {
    bitflags::bitflags,
    fidl_fuchsia_device::ControllerSynchronousProxy,
    fidl_fuchsia_io as fio,
    fuchsia_zircon::{
        self as zx,
        prelude::*,
        sys::{self, zx_handle_t, zx_status_t},
    },
    std::{
        ffi::{self, CStr, CString},
        fs::File,
        marker::PhantomData,
        mem::MaybeUninit,
        os::{
            raw,
            unix::{
                ffi::OsStrExt,
                io::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
            },
        },
        path::Path,
        ptr,
    },
};

/// Connects a channel to a named service.
pub fn service_connect(service_path: &str, channel: zx::Channel) -> Result<(), zx::Status> {
    let c_service_path = CString::new(service_path).map_err(|_| zx::Status::INVALID_ARGS)?;

    // TODO(raggi): this should be convered to an asynchronous FDIO
    // client protocol as soon as that is available (post fidl2) as this
    // call can block indefinitely.
    //
    // fdio_service connect takes a *const c_char service path and a channel.
    // On success, the channel is connected, and on failure, it is closed.
    // In either case, we do not need to clean up the channel so we use
    // `into_raw` so that Rust forgets about it.
    zx::ok(unsafe { fdio_sys::fdio_service_connect(c_service_path.as_ptr(), channel.into_raw()) })
}

/// Connects a channel to a named service relative to a directory `dir`.
/// `dir` must be a directory protocol channel.
pub fn service_connect_at(
    dir: &zx::Channel,
    service_path: &str,
    channel: zx::Channel,
) -> Result<(), zx::Status> {
    let c_service_path = CString::new(service_path).map_err(|_| zx::Status::INVALID_ARGS)?;

    // TODO(raggi): this should be convered to an asynchronous FDIO
    // client protocol as soon as that is available (post fidl2) as this
    // call can block indefinitely.
    //
    // fdio_service_connect_at takes a directory handle,
    // a *const c_char service path, and a channel to connect.
    // The directory handle is never consumed, so we borrow the raw handle.
    // On success, the channel is connected, and on failure, it is closed.
    // In either case, we do not need to clean up the channel so we use
    // `into_raw` so that Rust forgets about it.
    zx::ok(unsafe {
        fdio_sys::fdio_service_connect_at(
            dir.raw_handle(),
            c_service_path.as_ptr(),
            channel.into_raw(),
        )
    })
}

/// Opens the remote object at the given `path` with the given `flags` asynchronously.
/// ('asynchronous' here is refering to fuchsia.io.Directory.Open not having a return value).
///
/// Wraps fdio_open.
pub fn open(path: &str, flags: fio::OpenFlags, channel: zx::Channel) -> Result<(), zx::Status> {
    let c_path = CString::new(path).map_err(|_| zx::Status::INVALID_ARGS)?;

    // fdio_open_at takes a directory handle, a *const c_char service path,
    // flags, and a channel to connect.
    // The directory handle is never consumed, so we borrow the raw handle.
    // On success, the channel is connected, and on failure, it is closed.
    // In either case, we do not need to clean up the channel so we use
    // `into_raw` so that Rust forgets about it.
    zx::ok(unsafe { fdio_sys::fdio_open(c_path.as_ptr(), flags.bits(), channel.into_raw()) })
}

/// Opens the remote object at the given `path` relative to the given `dir` with the given `flags`
/// asynchronously. ('asynchronous' here is refering to fuchsia.io.Directory.Open not having a
/// return value).
///
/// `dir` must be a directory protocol channel.
///
/// Wraps fdio_open_at.
pub fn open_at(
    dir: &zx::Channel,
    path: &str,
    flags: fio::OpenFlags,
    channel: zx::Channel,
) -> Result<(), zx::Status> {
    let c_path = CString::new(path).map_err(|_| zx::Status::INVALID_ARGS)?;

    // fdio_open_at takes a directory handle, a *const c_char service path,
    // flags, and a channel to connect.
    // The directory handle is never consumed, so we borrow the raw handle.
    // On success, the channel is connected, and on failure, it is closed.
    // In either case, we do not need to clean up the channel so we use
    // `into_raw` so that Rust forgets about it.
    zx::ok(unsafe {
        fdio_sys::fdio_open_at(dir.raw_handle(), c_path.as_ptr(), flags.bits(), channel.into_raw())
    })
}

/// Opens the remote object at the given `path` with the given `flags` synchronously, and on
/// success, binds that channel to a file descriptor and returns it.
///
/// Wraps fdio_open_fd.
pub fn open_fd(path: &str, flags: fio::OpenFlags) -> Result<File, zx::Status> {
    let c_path = CString::new(path).map_err(|_| zx::Status::INVALID_ARGS)?;

    // fdio_open_fd takes a *const c_char service path, flags, and on success returns the opened
    // file descriptor through the provided pointer arguument.
    let mut raw_fd = -1;
    unsafe {
        let status = fdio_sys::fdio_open_fd(c_path.as_ptr(), flags.bits(), &mut raw_fd);
        zx::Status::ok(status)?;
        Ok(File::from_raw_fd(raw_fd))
    }
}

/// Opens the remote object at the given `path` relative to the given `dir` with the given `flags`
/// synchronously, and on success, binds that channel to a file descriptor and returns it.
///
/// `dir` must be backed by a directory protocol channel (even though it is
/// wrapped in a std::fs::File).
///
/// Wraps fdio_open_fd_at.
pub fn open_fd_at(dir: &File, path: &str, flags: fio::OpenFlags) -> Result<File, zx::Status> {
    let c_path = CString::new(path).map_err(|_| zx::Status::INVALID_ARGS)?;

    // fdio_open_fd_at takes a directory file descriptor, a *const c_char service path,
    // flags, and on success returns the opened file descriptor through the provided pointer
    // arguument.
    // The directory file descriptor is never consumed, so we borrow the raw handle.
    let dir_fd = dir.as_raw_fd();
    let mut raw_fd = -1;
    unsafe {
        let status = fdio_sys::fdio_open_fd_at(dir_fd, c_path.as_ptr(), flags.bits(), &mut raw_fd);
        zx::Status::ok(status)?;
        Ok(File::from_raw_fd(raw_fd))
    }
}

/// Clones an object's underlying handle.
pub fn clone_fd<F: AsRawFd>(f: F) -> Result<zx::Handle, zx::Status> {
    let fd = f.as_raw_fd();
    let mut handle = MaybeUninit::uninit();
    let status = {
        let handle = handle.as_mut_ptr();
        unsafe { fdio_sys::fdio_fd_clone(fd, handle) }
    };
    let () = zx::Status::ok(status)?;
    let handle = unsafe { handle.assume_init() };
    let handle = unsafe { zx::Handle::from_raw(handle) };
    Ok(handle)
}

/// Removes an object from the file descriptor table and returns its underlying handle.
pub fn transfer_fd<F: AsRawFd>(f: F) -> Result<zx::Handle, zx::Status> {
    let fd = f.as_raw_fd();
    let mut handle = MaybeUninit::uninit();
    let status = {
        let handle = handle.as_mut_ptr();
        unsafe { fdio_sys::fdio_fd_transfer(fd, handle) }
    };
    let () = zx::Status::ok(status)?;
    let handle = unsafe { handle.assume_init() };
    let handle = unsafe { zx::Handle::from_raw(handle) };
    Ok(handle)
}

/// Create an object from a handle.
///
/// Afterward, the handle is owned by fdio, and will close with `F`.
/// See `transfer_fd` for a way to get it back.
pub fn create_fd<F: FromRawFd>(handle: zx::Handle) -> Result<F, zx::Status> {
    let handle = handle.into_raw();
    let mut fd = MaybeUninit::uninit();
    let status = {
        let fd = fd.as_mut_ptr();
        unsafe { fdio_sys::fdio_fd_create(handle, fd) }
    };
    let () = zx::Status::ok(status)?;
    let fd = unsafe { fd.assume_init() };
    let f = unsafe { F::from_raw_fd(fd) };
    Ok(f)
}

/// Bind a handle to a specific file descriptor.
///
/// Afterward, the handle is owned by fdio, and will close when the file descriptor is closed.
/// See `transfer_fd` for a way to get it back.
pub fn bind_to_fd(handle: zx::Handle, fd: RawFd) -> Result<(), zx::Status> {
    if fd < 0 {
        // fdio_bind_to_fd supports finding the next available fd when provided with a negative
        // number, but due to lack of use-cases for this in Rust this is currently unsupported by
        // this function.
        return Err(zx::Status::INVALID_ARGS);
    }

    let mut fdio_t_out_ptr: *mut fdio_sys::fdio_t = ptr::null_mut();
    let status = unsafe {
        // This call is safe because the fdio_create function will return an error code, instead of
        // crashing, when an error is found. The handle is always consumed, and thus does not need
        // to be manually freed on error.
        fdio_sys::fdio_create(handle.into_raw(), &mut fdio_t_out_ptr as *mut *mut fdio_sys::fdio_t)
    };
    zx::Status::ok(status)?;
    let out_fd = unsafe {
        // This call is safe because the fdio_bind_to_fd function will return an invlid file
        // descriptor, instead of crashing, when an error is found. On error the fdio_t* is _not_
        // consumed, and must be freed manually.
        fdio_sys::fdio_bind_to_fd(fdio_t_out_ptr, fd, 0)
    };
    if out_fd != fd {
        unsafe {
            // An error has occurred, and thus the fdio library did not take ownership of
            // fdio_t_out_ptr. Manually free it. This is safe because if fdio_t_out_ptr was
            // invalid, the function would not have progressed to this point.
            fdio_sys::fdio_unsafe_release(fdio_t_out_ptr);
        };
        return Err(zx::Status::BAD_STATE);
    }
    Ok(())
}

/// Open a new connection to `file` by sending a request to open
/// a new connection to the sever.
pub fn clone_channel(file: &impl AsRawFd) -> Result<zx::Channel, zx::Status> {
    unsafe {
        // First, we must open a new connection to the handle, since
        // we must return a newly owned copy.
        let fdio = fdio_sys::fdio_unsafe_fd_to_io(file.as_raw_fd());
        let unowned_handle = fdio_sys::fdio_unsafe_borrow_channel(fdio);
        let handle = fdio_sys::fdio_service_clone(unowned_handle);
        fdio_sys::fdio_unsafe_release(fdio);

        match handle {
            zx::sys::ZX_HANDLE_INVALID => Err(zx::Status::NOT_SUPPORTED),
            _ => Ok(zx::Channel::from(zx::Handle::from_raw(handle))),
        }
    }
}

/// Retrieves the topological path for a device node.
pub fn device_get_topo_path(dev: &File) -> Result<String, zx::Status> {
    let channel = clone_channel(dev)?;
    let interface = ControllerSynchronousProxy::new(channel);
    interface
        .get_topological_path(fuchsia_zircon::Time::INFINITE)
        .map_err(|_| zx::Status::IO)?
        .map_err(|e| zx::Status::from_raw(e))
}

/// Creates a named pipe and returns one end as a zx::Socket.
pub fn pipe_half() -> Result<(std::fs::File, zx::Socket), zx::Status> {
    unsafe {
        let mut fd = -1;
        let mut handle = zx::sys::ZX_HANDLE_INVALID;
        let status =
            fdio_sys::fdio_pipe_half(&mut fd as *mut i32, &mut handle as *mut zx::sys::zx_handle_t);
        if status != zx::sys::ZX_OK {
            return Err(zx::Status::from_raw(status));
        }
        Ok((std::fs::File::from_raw_fd(fd), zx::Socket::from(zx::Handle::from_raw(handle))))
    }
}

bitflags! {
    /// Options to allow some or all of the environment of the running process
    /// to be shared with the process being spawned.
    pub struct SpawnOptions: u32 {
        /// Provide the spawned process with the job in which the process was created.
        ///
        /// The job will be available to the new process as the PA_JOB_DEFAULT argument
        /// (exposed in Rust as `fuchsia_runtim::job_default()`).
        const CLONE_JOB = fdio_sys::FDIO_SPAWN_CLONE_JOB;

        /// Provide the spawned process with the shared library loader via the
        /// PA_LDSVC_LOADER argument.
        const DEFAULT_LOADER = fdio_sys::FDIO_SPAWN_DEFAULT_LDSVC;

        /// Clones the filesystem namespace into the spawned process.
        const CLONE_NAMESPACE = fdio_sys::FDIO_SPAWN_CLONE_NAMESPACE;

        /// Clones file descriptors 0, 1, and 2 into the spawned process.
        ///
        /// Skips any of these file descriptors that are closed without
        /// generating an error.
        const CLONE_STDIO = fdio_sys::FDIO_SPAWN_CLONE_STDIO;

        /// Clones the environment into the spawned process.
        const CLONE_ENVIRONMENT = fdio_sys::FDIO_SPAWN_CLONE_ENVIRON;

        /// Clones the namespace, stdio, and environment into the spawned process.
        const CLONE_ALL = fdio_sys::FDIO_SPAWN_CLONE_ALL;
    }
}

// TODO: someday we'll have custom DSTs which will make this unnecessary.
fn nul_term_from_slice(argv: &[&CStr]) -> Vec<*const raw::c_char> {
    argv.iter().map(|cstr| cstr.as_ptr()).chain(std::iter::once(0 as *const raw::c_char)).collect()
}

/// Spawn a process in the given `job`.
pub fn spawn(
    job: &zx::Job,
    options: SpawnOptions,
    path: &CStr,
    argv: &[&CStr],
) -> Result<zx::Process, zx::Status> {
    let job = job.raw_handle();
    let flags = options.bits();
    let path = path.as_ptr();
    let argv = nul_term_from_slice(argv);
    let mut process_out = 0;

    // Safety: spawn consumes no handles and frees no pointers, and only
    // produces a valid process upon success.
    let status = unsafe { fdio_sys::fdio_spawn(job, flags, path, argv.as_ptr(), &mut process_out) };
    zx::ok(status)?;
    Ok(zx::Process::from(unsafe { zx::Handle::from_raw(process_out) }))
}

/// An action to take in `spawn_etc`.
#[repr(transparent)]
pub struct SpawnAction<'a>(fdio_sys::fdio_spawn_action_t, PhantomData<&'a ()>);

impl<'a> SpawnAction<'a> {
    pub const USE_FOR_STDIO: i32 = fdio_sys::FDIO_FLAG_USE_FOR_STDIO as i32;

    /// Clone a file descriptor into the new process.
    ///
    /// `local_fd`: File descriptor within the current process.
    /// `target_fd`: File descriptor within the new process that will receive the clone.
    pub fn clone_fd(local_fd: &'a impl AsRawFd, target_fd: i32) -> Self {
        // Safety: `local_fd` is a valid file descriptor so long as we're inside the
        // 'a lifetime.
        Self(
            fdio_sys::fdio_spawn_action_t {
                action_tag: fdio_sys::FDIO_SPAWN_ACTION_CLONE_FD,
                action_value: fdio_sys::fdio_spawn_action_union_t {
                    fd: fdio_sys::fdio_spawn_action_fd_t {
                        local_fd: local_fd.as_raw_fd(),
                        target_fd,
                    },
                },
            },
            PhantomData,
        )
    }

    /// Transfer a file descriptor into the new process.
    ///
    /// `local_fd`: File descriptor within the current process.
    /// `target_fd`: File descriptor within the new process that will receive the transfer.
    pub fn transfer_fd(local_fd: impl IntoRawFd, target_fd: i32) -> Self {
        // Safety: ownership of `local_fd` is consumed, so `Self` can live arbitrarily long.
        // When the action is executed, the fd will be transferred.
        Self(
            fdio_sys::fdio_spawn_action_t {
                action_tag: fdio_sys::FDIO_SPAWN_ACTION_TRANSFER_FD,
                action_value: fdio_sys::fdio_spawn_action_union_t {
                    fd: fdio_sys::fdio_spawn_action_fd_t {
                        local_fd: local_fd.into_raw_fd(),
                        target_fd,
                    },
                },
            },
            PhantomData,
        )
    }

    /// Add the given entry to the namespace of the spawned process.
    ///
    /// If `SpawnOptions::CLONE_NAMESPACE` is set, the namespace entry is added
    /// to the cloned namespace from the calling process.
    pub fn add_namespace_entry(prefix: &'a CStr, handle: zx::Handle) -> Self {
        // Safety: ownership of the `handle` is consumed.
        // The prefix string must stay valid through the 'a lifetime.
        Self(
            fdio_sys::fdio_spawn_action_t {
                action_tag: fdio_sys::FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
                action_value: fdio_sys::fdio_spawn_action_union_t {
                    ns: fdio_sys::fdio_spawn_action_ns_t {
                        prefix: prefix.as_ptr(),
                        handle: handle.into_raw(),
                    },
                },
            },
            PhantomData,
        )
    }

    /// Add the given handle to the process arguments of the spawned process.
    pub fn add_handle(kind: fuchsia_runtime::HandleInfo, handle: zx::Handle) -> Self {
        // Safety: ownership of the `handle` is consumed.
        // The prefix string must stay valid through the 'a lifetime.
        Self(
            fdio_sys::fdio_spawn_action_t {
                action_tag: fdio_sys::FDIO_SPAWN_ACTION_ADD_HANDLE,
                action_value: fdio_sys::fdio_spawn_action_union_t {
                    h: fdio_sys::fdio_spawn_action_h_t {
                        id: kind.as_raw(),
                        handle: handle.into_raw(),
                    },
                },
            },
            PhantomData,
        )
    }

    /// Sets the name of the spawned process to the given name.
    pub fn set_name(name: &'a CStr) -> Self {
        // Safety: the `name` pointer must be valid at least as long as `Self`.
        Self(
            fdio_sys::fdio_spawn_action_t {
                action_tag: fdio_sys::FDIO_SPAWN_ACTION_SET_NAME,
                action_value: fdio_sys::fdio_spawn_action_union_t {
                    name: fdio_sys::fdio_spawn_action_name_t { data: name.as_ptr() },
                },
            },
            PhantomData,
        )
    }

    fn is_null(&self) -> bool {
        self.0.action_tag == 0
    }

    /// Nullifies the action to prevent the inner contents from being dropped.
    fn nullify(&mut self) {
        // Assert that our null value doesn't conflict with any "real" actions.
        debug_assert!(
            (fdio_sys::FDIO_SPAWN_ACTION_CLONE_FD != 0)
                && (fdio_sys::FDIO_SPAWN_ACTION_TRANSFER_FD != 0)
                && (fdio_sys::FDIO_SPAWN_ACTION_ADD_NS_ENTRY != 0)
                && (fdio_sys::FDIO_SPAWN_ACTION_ADD_HANDLE != 0)
                && (fdio_sys::FDIO_SPAWN_ACTION_SET_NAME != 0)
        );
        self.0.action_tag = 0;
    }
}

fn spawn_with_actions(
    job: &zx::Job,
    options: SpawnOptions,
    argv: &[&CStr],
    environ: Option<&[&CStr]>,
    actions: &mut [SpawnAction<'_>],
    spawn_fn: impl FnOnce(
        zx_handle_t,                                                          // job
        u32,                                                                  // flags
        *const *const raw::c_char,                                            // argv
        *const *const raw::c_char,                                            // environ
        usize,                                                                // action_count
        *const fdio_sys::fdio_spawn_action_t,                                 // actions
        *mut zx_handle_t,                                                     // process_out,
        *mut [raw::c_char; fdio_sys::FDIO_SPAWN_ERR_MSG_MAX_LENGTH as usize], // err_msg_out
    ) -> zx_status_t,
) -> Result<zx::Process, (zx::Status, String)> {
    let job = job.raw_handle();
    let flags = options.bits();
    let argv = nul_term_from_slice(argv);
    let environ_vec;
    let environ_ptr = match environ {
        Some(e) => {
            environ_vec = nul_term_from_slice(e);
            environ_vec.as_ptr()
        }
        None => std::ptr::null(),
    };

    if actions.iter().any(|a| a.is_null()) {
        return Err((zx::Status::INVALID_ARGS, "null SpawnAction".to_string()));
    }
    // Safety: actions are repr(transparent) wrappers around fdio_spawn_action_t
    let action_count = actions.len();
    let actions_ptr: *const SpawnAction<'_> = actions.as_ptr();
    let actions_ptr = actions_ptr as *const fdio_sys::fdio_spawn_action_t;

    let mut process_out = 0;
    let mut err_msg_out = [0 as raw::c_char; fdio_sys::FDIO_SPAWN_ERR_MSG_MAX_LENGTH as usize];

    let status = spawn_fn(
        job,
        flags,
        argv.as_ptr(),
        environ_ptr,
        action_count,
        actions_ptr,
        &mut process_out,
        &mut err_msg_out,
    );

    zx::ok(status).map_err(|status| {
        let err_msg =
            unsafe { CStr::from_ptr(err_msg_out.as_ptr()) }.to_string_lossy().into_owned();
        (status, err_msg)
    })?;

    // Clear out the actions so we can't unsafely re-use them in a future call.
    actions.iter_mut().for_each(|a| a.nullify());
    Ok(zx::Process::from(unsafe { zx::Handle::from_raw(process_out) }))
}

/// Spawn a process in the given `job` using a series of `SpawnAction`s.
/// All `SpawnAction`s are nullified after their use in this function.
pub fn spawn_etc(
    job: &zx::Job,
    options: SpawnOptions,
    path: &CStr,
    argv: &[&CStr],
    environ: Option<&[&CStr]>,
    actions: &mut [SpawnAction<'_>],
) -> Result<zx::Process, (zx::Status, String)> {
    let path = path.as_ptr();
    spawn_with_actions(
        job,
        options,
        argv,
        environ,
        actions,
        |job, flags, argv, environ, action_count, actions_ptr, process_out, err_msg_out| unsafe {
            fdio_sys::fdio_spawn_etc(
                job,
                flags,
                path,
                argv,
                environ,
                action_count,
                actions_ptr,
                process_out,
                err_msg_out,
            )
        },
    )
}

/// Spawn a process in the given job using an executable VMO.
pub fn spawn_vmo(
    job: &zx::Job,
    options: SpawnOptions,
    executable_vmo: zx::Vmo,
    argv: &[&CStr],
    environ: Option<&[&CStr]>,
    actions: &mut [SpawnAction<'_>],
) -> Result<zx::Process, (zx::Status, String)> {
    let executable_vmo = executable_vmo.into_raw();
    spawn_with_actions(
        job,
        options,
        argv,
        environ,
        actions,
        |job, flags, argv, environ, action_count, actions_ptr, process_out, err_msg_out| unsafe {
            fdio_sys::fdio_spawn_vmo(
                job,
                flags,
                executable_vmo,
                argv,
                environ,
                action_count,
                actions_ptr,
                process_out,
                err_msg_out,
            )
        },
    )
}

/// Events that can occur while watching a directory, including files that already exist prior to
/// running a Watcher.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum WatchEvent {
    /// A file was added.
    AddFile,

    /// A file was removed.
    RemoveFile,

    /// The Watcher has enumerated all the existing files and has started to wait for new files to
    /// be added.
    Idle,

    Unknown(i32),
}

impl From<raw::c_int> for WatchEvent {
    fn from(i: raw::c_int) -> WatchEvent {
        match i {
            fdio_sys::WATCH_EVENT_ADD_FILE => WatchEvent::AddFile,
            fdio_sys::WATCH_EVENT_REMOVE_FILE => WatchEvent::RemoveFile,
            fdio_sys::WATCH_EVENT_IDLE => WatchEvent::Idle,
            i => WatchEvent::Unknown(i),
        }
    }
}

impl From<WatchEvent> for raw::c_int {
    fn from(i: WatchEvent) -> raw::c_int {
        match i {
            WatchEvent::AddFile => fdio_sys::WATCH_EVENT_ADD_FILE,
            WatchEvent::RemoveFile => fdio_sys::WATCH_EVENT_REMOVE_FILE,
            WatchEvent::Idle => fdio_sys::WATCH_EVENT_IDLE,
            WatchEvent::Unknown(i) => i as raw::c_int,
        }
    }
}

unsafe extern "C" fn watcher_cb<F>(
    _dirfd: raw::c_int,
    event: raw::c_int,
    fn_: *const raw::c_char,
    watcher: *mut raw::c_void,
) -> sys::zx_status_t
where
    F: Sized + FnMut(WatchEvent, &Path) -> Result<(), zx::Status>,
{
    let cb: &mut F = &mut *(watcher as *mut F);
    let filename = ffi::OsStr::from_bytes(CStr::from_ptr(fn_).to_bytes());
    match cb(WatchEvent::from(event), Path::new(filename)) {
        Ok(()) => sys::ZX_OK,
        Err(e) => e.into_raw(),
    }
}

/// Runs the given callback for each file in the directory and each time a new file is
/// added to the directory.
///
/// If the callback returns an error, the watching stops, and the zx::Status is returned.
///
/// This function blocks for the duration of the watch operation. The deadline parameter will stop
/// the watch at the given (absolute) time and return zx::Status::TIMED_OUT. A deadline of
/// zx::ZX_TIME_INFINITE will never expire.
///
/// The callback may use zx::Status::STOP as a way to signal to the caller that it wants to
/// stop because it found what it was looking for. Since this error code is not returned by
/// syscalls or public APIs, the callback does not need to worry about it turning up normally.
pub fn watch_directory<F>(dir: &File, deadline: sys::zx_time_t, mut f: F) -> zx::Status
where
    F: Sized + FnMut(WatchEvent, &Path) -> Result<(), zx::Status>,
{
    let cb_ptr: *mut raw::c_void = &mut f as *mut _ as *mut raw::c_void;
    unsafe {
        zx::Status::from_raw(fdio_sys::fdio_watch_directory(
            dir.as_raw_fd(),
            Some(watcher_cb::<F>),
            deadline,
            cb_ptr,
        ))
    }
}

/// Gets a read-only VMO containing the whole contents of the file. This function
/// creates a clone of the underlying VMO when possible, falling back to eagerly
/// reading the contents into a freshly-created VMO.
pub fn get_vmo_copy_from_file(file: &File) -> Result<zx::Vmo, zx::Status> {
    unsafe {
        let mut vmo_handle: zx::sys::zx_handle_t = zx::sys::ZX_HANDLE_INVALID;
        match fdio_sys::fdio_get_vmo_copy(file.as_raw_fd(), &mut vmo_handle) {
            0 => Ok(zx::Vmo::from(zx::Handle::from_raw(vmo_handle))),
            error_code => Err(zx::Status::from_raw(error_code)),
        }
    }
}

/// Gets a read-exec VMO containing the whole contents of the file.
pub fn get_vmo_exec_from_file(file: &File) -> Result<zx::Vmo, zx::Status> {
    unsafe {
        let mut vmo_handle: zx::sys::zx_handle_t = zx::sys::ZX_HANDLE_INVALID;
        match fdio_sys::fdio_get_vmo_exec(file.as_raw_fd(), &mut vmo_handle) {
            0 => Ok(zx::Vmo::from(zx::Handle::from_raw(vmo_handle))),
            error_code => Err(zx::Status::from_raw(error_code)),
        }
    }
}

pub struct Namespace {
    ns: *mut fdio_sys::fdio_ns_t,
}

impl Namespace {
    /// Get the currently installed namespace.
    pub fn installed() -> Result<Self, zx::Status> {
        let mut ns_ptr: *mut fdio_sys::fdio_ns_t = ptr::null_mut();
        let status = unsafe { fdio_sys::fdio_ns_get_installed(&mut ns_ptr) };
        zx::Status::ok(status)?;
        Ok(Namespace { ns: ns_ptr })
    }

    /// Create a channel that is connected to a service bound in this namespace at path. The path
    /// must be an absolute path, like "/x/y/z", containing no "." nor ".." entries. It is relative
    /// to the root of the namespace.
    ///
    /// This corresponds with fdio_ns_connect in C.
    pub fn connect(
        &self,
        path: &str,
        flags: fio::OpenFlags,
        channel: zx::Channel,
    ) -> Result<(), zx::Status> {
        let cstr = CString::new(path)?;
        let status = unsafe {
            fdio_sys::fdio_ns_connect(self.ns, cstr.as_ptr(), flags.bits(), channel.into_raw())
        };
        zx::Status::ok(status)?;
        Ok(())
    }

    /// Create a new directory within the namespace, bound to the provided
    /// directory-protocol-compatible channel. The path must be an absolute path, like "/x/y/z",
    /// containing no "." nor ".." entries. It is relative to the root of the namespace.
    ///
    /// This corresponds with fdio_ns_bind in C.
    pub fn bind(&self, path: &str, channel: zx::Channel) -> Result<(), zx::Status> {
        let cstr = CString::new(path)?;
        let status = unsafe { fdio_sys::fdio_ns_bind(self.ns, cstr.as_ptr(), channel.into_raw()) };
        zx::Status::ok(status)
    }

    /// Unbind the channel at path, closing the associated handle when all references to the node go
    /// out of scope. The path must be an absolute path, like "/x/y/z", containing no "." nor ".."
    /// entries. It is relative to the root of the namespace.
    ///
    /// This corresponds with fdio_ns_unbind in C.
    pub fn unbind(&self, path: &str) -> Result<(), zx::Status> {
        let cstr = CString::new(path)?;
        let status = unsafe { fdio_sys::fdio_ns_unbind(self.ns, cstr.as_ptr()) };
        zx::Status::ok(status)
    }

    pub fn into_raw(self) -> *mut fdio_sys::fdio_ns_t {
        self.ns
    }
}

/// Returns the handle for the given FIDL service, or a Zircon Error Status. This function takes
/// ownership of 'service' because the File is released when acquiring the service handle.
///
/// This corresponds with fdio_get_service_handle in C.
pub fn get_service_handle(service: File) -> Result<zx::Channel, zx::Status> {
    let fd = std::os::unix::io::IntoRawFd::into_raw_fd(service);
    let mut handle = 0;
    // Safety: fdio_get_service_handle() is an unsafe function because its 'out' parameter is a raw
    // pointer and because it closes the given file descriptor. This invocation is safe because:
    // 1) the supplied 'out' value, "&mut handle", is guaranteed to be valid,
    // 2) fdio_get_service_handle() does not retain a copy of `out`, and
    // 3) 'fd' is not used following this invocation.
    zx::Status::ok(unsafe { fdio_sys::fdio_get_service_handle(fd, &mut handle) })?;
    // Safety: from_raw() is an unsafe function because it assumes the given raw handle is valid.
    // Above, fdio_get_service_handle()'s return value was ok, so 'handle' must be valid.
    Ok(zx::Channel::from(unsafe { zx::Handle::from_raw(handle) }))
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        assert_matches::assert_matches,
        fuchsia_zircon::{object_wait_many, Signals, Status, Time, WaitItem},
    };

    #[test]
    fn namespace_get_installed() {
        let namespace = Namespace::installed().expect("failed to get installed namespace");
        assert!(!namespace.into_raw().is_null());
    }

    #[test]
    fn namespace_bind_connect_unbind() {
        let namespace = Namespace::installed().unwrap();
        // client => ns_server => ns_client => server
        //        ^            ^            ^-- zx channel connection
        //        |            |-- connected through namespace bind/connect
        //        |-- zx channel connection
        let (ns_client, _server) = zx::Channel::create().unwrap();
        let (_client, ns_server) = zx::Channel::create().unwrap();
        let path = "/test_path1";

        assert_eq!(namespace.bind(path, ns_client), Ok(()));
        assert_eq!(namespace.connect(path, fio::OpenFlags::empty(), ns_server), Ok(()));
        assert_eq!(namespace.unbind(path), Ok(()));
    }

    #[test]
    fn namespace_double_bind_error() {
        let namespace = Namespace::installed().unwrap();
        let (ns_client1, _server1) = zx::Channel::create().unwrap();
        let (ns_client2, _server2) = zx::Channel::create().unwrap();
        let path = "/test_path2";

        assert_eq!(namespace.bind(path, ns_client1), Ok(()));
        assert_eq!(namespace.bind(path, ns_client2), Err(zx::Status::ALREADY_EXISTS));
        assert_eq!(namespace.unbind(path), Ok(()));
    }

    #[test]
    fn namespace_connect_error() {
        let namespace = Namespace::installed().unwrap();
        let (_client, ns_server) = zx::Channel::create().unwrap();
        let path = "/test_path3";

        assert_eq!(
            namespace.connect(path, fio::OpenFlags::empty(), ns_server),
            Err(zx::Status::NOT_FOUND)
        );
    }

    #[test]
    fn namespace_unbind_error() {
        let namespace = Namespace::installed().unwrap();
        let path = "/test_path4";

        assert_eq!(namespace.unbind(path), Err(zx::Status::NOT_FOUND));
    }

    fn cstr(orig: &str) -> CString {
        CString::new(orig).expect("CString::new failed")
    }

    #[test]
    fn fdio_spawn_run_target_bin_no_env() {
        let job = zx::Job::from(zx::Handle::invalid());
        let cpath = cstr("/pkg/bin/spawn_test_target");
        let (stdout_file, stdout_sock) = pipe_half().expect("Failed to make pipe");
        let mut spawn_actions = [SpawnAction::clone_fd(&stdout_file, 1)];

        let cstrags: Vec<CString> = vec![cstr("test_arg")];
        let mut cargs: Vec<&CStr> = cstrags.iter().map(|x| x.as_c_str()).collect();
        cargs.insert(0, cpath.as_c_str());
        let process = spawn_etc(
            &job,
            SpawnOptions::CLONE_ALL,
            cpath.as_c_str(),
            cargs.as_slice(),
            None,
            &mut spawn_actions,
        )
        .expect("Unable to spawn process");

        let mut output = vec![];
        loop {
            let mut items = vec![
                WaitItem {
                    handle: process.as_handle_ref(),
                    waitfor: Signals::PROCESS_TERMINATED,
                    pending: Signals::NONE,
                },
                WaitItem {
                    handle: stdout_sock.as_handle_ref(),
                    waitfor: Signals::SOCKET_READABLE | Signals::SOCKET_PEER_CLOSED,
                    pending: Signals::NONE,
                },
            ];

            let signals_result =
                object_wait_many(&mut items, Time::INFINITE).expect("unable to wait");

            if items[1].pending.contains(Signals::SOCKET_READABLE) {
                let bytes_len = stdout_sock.outstanding_read_bytes().expect("Socket error");
                let mut buf: Vec<u8> = vec![0; bytes_len];
                let read_len = stdout_sock
                    .read(&mut buf[..])
                    .or_else(|status| match status {
                        Status::SHOULD_WAIT => Ok(0),
                        _ => Err(status),
                    })
                    .expect("Unable to read buff");
                output.extend_from_slice(&buf[0..read_len]);
            }

            // read stdout buffer until test process dies or the socket is closed
            if items[1].pending.contains(Signals::SOCKET_PEER_CLOSED) {
                break;
            }

            if items[0].pending.contains(Signals::PROCESS_TERMINATED) {
                break;
            }

            if signals_result {
                break;
            };
        }

        assert_eq!(String::from_utf8(output).expect("unable to decode stdout"), "hello world\n");
    }

    // Simple tests of the fdio_open and fdio_open_at wrappers. These aren't intended to
    // exhaustively test the fdio functions - there are separate tests for that - but they do
    // exercise one success and one failure case for each function.
    #[test]
    fn fdio_open_and_open_at() {
        // fdio_open requires paths to be absolute
        let (_, pkg_server) = zx::Channel::create().unwrap();
        assert_eq!(
            open("pkg", fio::OpenFlags::RIGHT_READABLE, pkg_server),
            Err(zx::Status::NOT_FOUND)
        );

        let (pkg_client, pkg_server) = zx::Channel::create().unwrap();
        assert_eq!(open("/pkg", fio::OpenFlags::RIGHT_READABLE, pkg_server), Ok(()));

        // fdio_open/fdio_open_at do not support OPEN_FLAG_DESCRIBE
        let (_, bin_server) = zx::Channel::create().unwrap();
        assert_eq!(
            open_at(
                &pkg_client,
                "bin",
                fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DESCRIBE,
                bin_server
            ),
            Err(zx::Status::INVALID_ARGS)
        );

        let (_, bin_server) = zx::Channel::create().unwrap();
        assert_eq!(open_at(&pkg_client, "bin", fio::OpenFlags::RIGHT_READABLE, bin_server), Ok(()));
    }

    // Simple tests of the fdio_open_fd and fdio_open_fd_at wrappers. These aren't intended to
    // exhaustively test the fdio functions - there are separate tests for that - but they do
    // exercise one success and one failure case for each function.
    #[test]
    fn fdio_open_fd_and_open_fd_at() {
        // fdio_open_fd requires paths to be absolute
        assert_matches!(open_fd("pkg", fio::OpenFlags::RIGHT_READABLE), Err(zx::Status::NOT_FOUND));

        let pkg_fd = open_fd("/pkg", fio::OpenFlags::RIGHT_READABLE)
            .expect("Failed to open /pkg using fdio_open_fd");

        // Trying to open a non-existent directory should fail.
        assert_matches!(
            open_fd_at(&pkg_fd, "blahblah", fio::OpenFlags::RIGHT_READABLE),
            Err(zx::Status::NOT_FOUND)
        );

        let _: File = open_fd_at(&pkg_fd, "bin", fio::OpenFlags::RIGHT_READABLE)
            .expect("Failed to open bin/ subdirectory using fdio_open_fd_at");
    }

    // Tests success & error handling of the get_service_handle function. This does not exhaustively
    // test the underlying FDIO function, as that is tested alongside its C implementation.
    #[test]
    fn fdio_get_service_handle() {
        // Setup two handles to the same underlying file.
        let service = File::open("/svc").expect("failed to open /svc");
        let clone = service.try_clone().expect("failed to clone /svc service");

        // 'service' keeps the file busy during 'get_service_handle(clone)'.
        assert_eq!(get_service_handle(clone), Err(zx::Status::UNAVAILABLE));
        // 'clone' released its handle to the file above; 'service' now holds the sole handle.
        let _: zx::Channel =
            get_service_handle(service).expect("failed to get fdio service handle");
    }
}
