blob: 9d0d13ab6d194916267e2c9b94d276ce4bbef338 [file] [log] [blame] [edit]
// Copyright 2018 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.
#ifndef LIB_ZXIO_ZXIO_H_
#define LIB_ZXIO_ZXIO_H_
#include <lib/zxio/types.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
__BEGIN_CDECLS
// An IO object.
//
// Provides an ergonomic C interface to the fuchsia.io family of protocols.
// These protocols are optimized for efficiency at the cost of ergonomics. This
// object provides a more ergonomic interface to the same underlying protocol
// without sacrificing (much) performance.
//
// A zxio_t also abstracts over several related protocols (e.g., vmofile,
// file, and directory) to provide a uniform interface. Advanced clients can
// also provide their own implementation of the underlying ops table to
// provide drop-in replacements for zxio_t with different backends.
//
// # Threading model
//
// Most operations on zxio_t objects can be called concurrently from any thread.
// However, the caller needs to synchronize |zxio_close| with other operations.
// Specifically, no operations may be called concurrently with |zxio_close| on
// the same |zxio_t|.
typedef struct zxio_tag zxio_t;
// Node
// Attempt to close |io|.
//
// Where applicable, waits for an acknowledgement from the server which may communicate any I/O
// errors.
//
// Always consumes |io|.
zx_status_t zxio_close(zxio_t* io);
// Extracts the underlying |zx_handle_t| for |io| if one exists. Does not
// terminate the connection with the server.
//
// Does not block.
//
// Does not consume |io|. However, after this method returns, future I/O on this
// object are guaranteed to return |ZX_ERR_BAD_HANDLE|.
zx_status_t zxio_release(zxio_t* io, zx_handle_t* out_handle);
// Attempt to create a |zx_handle_t| that represents another session with |io|.
//
// The returned |zx_handle_t| is suitable for transfer to another process or for
// use within this process.
//
// Does not block.
//
// Does not consume |io|.
zx_status_t zxio_clone(zxio_t* io, zx_handle_t* out_handle);
// Wait for |signals| to be asserted for |io|.
//
// Returns |ZX_ERR_TIMED_OUT| if |deadline| passes before any of the |signals|
// are asserted for |io|. Returns the set of signals that were actually observed
// via |observed|.
zx_status_t zxio_wait_one(zxio_t* io, zxio_signals_t signals, zx_time_t deadline,
zxio_signals_t* out_observed);
// Translate |zxio_signals_t| into |zx_signals_t| for |io|.
//
// The client should wait on |handle| for |zx_signals| in order to observe the
// given |zxio_signals|.
//
// Use |zxio_wait_end| to translate the observed |zx_signals_t| back into
// |zxio_signals_t|.
void zxio_wait_begin(zxio_t* io, zxio_signals_t zxio_signals, zx_handle_t* out_handle,
zx_signals_t* out_zx_signals);
// Translate |zx_signals_t| into |zxio_signals_t| for |io|.
//
// Typically used with |zxio_wait_begin| to wait asynchronously on a
// |zx_handle_t| and to interpret the observed |zx_signals|.
void zxio_wait_end(zxio_t* io, zx_signals_t zx_signals, zxio_signals_t* out_zxio_signals);
// Synchronizes updates to the file to the underlying media, if it exists.
zx_status_t zxio_sync(zxio_t* io);
// Returns information about the file.
zx_status_t zxio_attr_get(zxio_t* io, zxio_node_attributes_t* out_attr);
// Update information about the file.
//
// The presence of a particular field in |attr| indicates it is to be updated.
zx_status_t zxio_attr_set(zxio_t* io, const zxio_node_attributes_t* attr);
// File
// Attempt to read |capacity| bytes into |buffer| at the current seek offset.
//
// The seek offset is moved forward by the actual number of bytes read.
//
// The actual number of bytes read is returned in |out_actual|.
zx_status_t zxio_read(zxio_t* io, void* buffer, size_t capacity, zxio_flags_t flags,
size_t* out_actual);
// Attempt to read |capacity| bytes into |buffer| at |offset|.
//
// Does not affect the seek offset.
//
// The actual number of bytes read is returned in |out_actual|.
zx_status_t zxio_read_at(zxio_t* io, zx_off_t offset, void* buffer, size_t capacity,
zxio_flags_t flags, size_t* out_actual);
// Attempt to write |capacity| bytes into |buffer| at the current seek offset.
//
// The seek offset is moved forward by the actual number of bytes written.
//
// The actual number of bytes written is returned in |out_actual|.
zx_status_t zxio_write(zxio_t* io, const void* buffer, size_t capacity, zxio_flags_t flags,
size_t* out_actual);
// Attempt to write |capacity| bytes into |buffer| at |offset|.
//
// Does not affect the seek offset.
//
// The actual number of bytes written is returned in |out_actual|.
zx_status_t zxio_write_at(zxio_t* io, zx_off_t offset, const void* buffer, size_t capacity,
zxio_flags_t flags, size_t* out_actual);
// Attempt to read bytes into the buffers described by |vector|.
//
// The seek offset is moved forward by the actual number of bytes read.
//
// The actual number of bytes read is returned in |out_actual|.
zx_status_t zxio_readv(zxio_t* io, const zx_iovec_t* vector, size_t vector_count,
zxio_flags_t flags, size_t* out_actual);
// Attempt to read bytes into the buffers described by |vector| at |offest|.
//
// Does not affect the seek offset.
//
// The actual number of bytes read is returned in |out_actual|.
zx_status_t zxio_readv_at(zxio_t* io, zx_off_t offset, const zx_iovec_t* vector,
size_t vector_count, zxio_flags_t flags, size_t* out_actual);
// Attempt to write bytes into the buffers described by |vector|.
//
// The seek offset is moved forward by the actual number of bytes written.
//
// The actual number of bytes written is returned in |out_actual|.
zx_status_t zxio_writev(zxio_t* io, const zx_iovec_t* vector, size_t vector_count,
zxio_flags_t flags, size_t* out_actual);
// Attempt to write bytes into the buffers described by |vector| at |offest|.
//
// Does not affect the seek offset.
//
// The actual number of bytes written is returned in |out_actual|.
zx_status_t zxio_writev_at(zxio_t* io, zx_off_t offset, const zx_iovec_t* vector,
size_t vector_count, zxio_flags_t flags, size_t* out_actual);
// Modify the seek offset.
//
// The seek offset for the file is modified by |offset| relative to |start|.
//
// The resulting seek offset relative to the start of the file is returned in
// |out_offset|.
zx_status_t zxio_seek(zxio_t* io, zxio_seek_origin_t start, int64_t offset, size_t* out_offset);
// Shrink the file size to |length| bytes.
zx_status_t zxio_truncate(zxio_t* io, size_t length);
// Returns the flags associated with the file.
//
// These flags are typically set when the file is opened but can be modified by
// |zxio_flags_set|.
//
// See io.fidl for the available |flags|.
zx_status_t zxio_flags_get(zxio_t* io, uint32_t* out_flags);
// Modifies the flags associated with the file.
//
// This function can modify the following flags:
//
// * |fuchsia::io::OPEN_FLAG_APPEND|.
//
// See io.fidl for the available |flags|.
zx_status_t zxio_flags_set(zxio_t* io, uint32_t flags);
// Gets a token associated with a directory connection.
//
// This token can be used to identify a directory at a later time, for use
// in operations involving multiple nodes e.g. rename.
//
// See the io.fidl documentation on |fuchsia.io/Directory.GetToken|.
zx_status_t zxio_token_get(zxio_t* io, zx_handle_t* out_token);
// Acquires a VMO representing this file, if there is one, with the requested
// access rights.
//
// |flags| are |fuchsia.io/VMO_FLAG_*|.
zx_status_t zxio_vmo_get(zxio_t* io, uint32_t flags, zx_handle_t* out_vmo, size_t* out_size);
// Get a read-only VMO containing the whole contents of the file.
//
// This function creates a clone of the underlying VMO when possible. If the
// function cannot create a clone, the function will eagerly read the contents
// of the file into a freshly-created VMO.
//
// If non-null, |out_size| will hold the size of the file. Note that the size of
// the vmo as queried from the kernel would be rounded up to the page boundary.
zx_status_t zxio_vmo_get_copy(zxio_t* io, zx_handle_t* out_vmo, size_t* out_size);
// Get a read-only VMO containing the whole contents of the file.
//
// This function creates a clone of the underlying VMO when possible. If the
// function cannot create a clone, the function will return an error.
//
// If non-null, |out_size| will hold the size of the file. Note that the size of
// the vmo as queried from the kernel would be rounded up to the page boundary.
zx_status_t zxio_vmo_get_clone(zxio_t* io, zx_handle_t* out_vmo, size_t* out_size);
// Get a read-only handle to the exact VMO used by the file system server to
// represent the file.
//
// This function fails if the server does not have an exact VMO representation
// of the file.
//
// If non-null, |out_size| will hold the size of the file. Note that the size of
// the vmo as queried from the kernel would be rounded up to the page boundary.
zx_status_t zxio_vmo_get_exact(zxio_t* io, zx_handle_t* out_vmo, size_t* out_size);
// Get a read + execute VMO as a clone of the underlying VMO in this file.
// This function will fail rather than copying the contents if it cannot clone,
// or if the particular |io| does not support / allow a read + execute VMO
// representation.
//
// If non-null, |out_size| will hold the size of the file. Note that the size of
// the vmo as queried from the kernel would be rounded up to the page boundary.
zx_status_t zxio_vmo_get_exec(zxio_t* io, zx_handle_t* out_vmo, size_t* out_size);
// Directory
// Open a new file relative to the given |directory|.
//
// The connection is represented as a |zxio_t|. This call blocks until the
// remote server is able to describe the new connection.
//
// See io.fidl for the available |flags| and |mode|.
zx_status_t zxio_open(zxio_t* directory, uint32_t flags, uint32_t mode, const char* path,
zxio_t** out_io);
// Open a new file relative to the given |directory|.
//
// The connection is represented as a |zx_handle_t|. The caller is responsible
// for creating the |zx_handle_t|, which must be a channel. This call does not
// block on the remote server.
//
// See io.fidl for the available |flags| and |mode|.
zx_status_t zxio_open_async(zxio_t* directory, uint32_t flags, uint32_t mode, const char* path,
size_t path_len, zx_handle_t request);
// Remove an file relative to the given directory.
zx_status_t zxio_unlink(zxio_t* directory, const char* path);
// Attempts to rename |old_path| relative to |old_directory| to |new_path|
// relative to the directory represented by |new_directory_token|.
//
// |old_directory| and |new_directory_token| may be aliased.
zx_status_t zxio_rename(zxio_t* old_directory, const char* old_path,
zx_handle_t new_directory_token, const char* new_path);
// Attempts to link |src_path| relative to |src_directory| to |dst_path| relative to
// the directory represented by |dst_directory_token|.
//
// |src_directory| and |dst_directory_token| may be aliased.
zx_status_t zxio_link(zxio_t* src_directory, const char* src_path, zx_handle_t dst_directory_token,
const char* dst_path);
// Directory iterator
// An iterator for |zxio_dirent_t| objects.
//
// To start iterating directory entries, call |zxio_dirent_iterator_init| to
// initialize the contents of the iterator. Then, call
// |zxio_dirent_iterator_next| to advance the iterator.
//
// Typically allocated on the stack.
typedef struct zxio_dirent_iterator {
zxio_t* io;
uint64_t opaque[7];
} zxio_dirent_iterator_t;
// Initializes a |zxio_dirent_iterator_t| for the given |directory|.
//
// At most one |zxio_dirent_iterator_t| can be active for a given |directory|
// at a time. The lifetime of |directory| must be greater than that of |iterator|.
//
// The initialized iterator should be destroyed by calling
// |zxio_dirent_iterator_destroy| when no longer used.
zx_status_t zxio_dirent_iterator_init(zxio_dirent_iterator_t* iterator, zxio_t* directory);
// Read a |zxio_dirent_t| from the given |iterator|.
//
// The |zxio_dirent_t| returned via |out_entry| is valid until either (a) the
// next call to |zxio_dirent_iterator_next| or the |iterator| passed to
// |zxio_dirent_iterator_init| is destroyed.
//
// This function reads |zxio_directory_entry_t| from the server in chunks, but this
// function returns the entries one at a time. When this function crosses into
// a new chunk, the function will block on the remote server to retrieve the
// next chunk.
//
// When there are no more directory entries to enumerate, this function will
// return |ZX_ERR_NOT_FOUND|.
//
// |iterator| must have been previously initialized via
// |zxio_dirent_iterator_init|.
zx_status_t zxio_dirent_iterator_next(zxio_dirent_iterator_t* iterator, zxio_dirent_t** out_entry);
// Destroys a |zxio_dirent_iterator_t|, freeing associated resources.
//
// After destruction, another |zxio_dirent_iterator_init| call might be made on
// the corresponding directory.
void zxio_dirent_iterator_destroy(zxio_dirent_iterator_t* iterator);
// Return in |tty| whether or not |io| represents a TTY object (should
// line buffer for stdio, etc).
zx_status_t zxio_isatty(zxio_t* io, bool* tty);
__END_CDECLS
#endif // LIB_ZXIO_ZXIO_H_