/* This file is part of GNUnet. Copyright (C) 2009 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . SPDX-License-Identifier: AGPL3.0-or-later */ /** * @author Christian Grothoff * * @file * Buffered IO library * * @defgroup bio BIO library * Buffered binary disk IO (with endianness conversion) * @{ */ #ifndef GNUNET_BIO_LIB_H #define GNUNET_BIO_LIB_H #include "gnunet_container_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /****************************** READING API *******************************/ /** * Handle for buffered reading. */ struct GNUNET_BIO_ReadHandle; /** * Open a file for reading. * * @param fn file name to be opened * @return IO handle on success, NULL on error */ struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open_file (const char *fn); /** * Create a handle from an existing allocated buffer. * * @param buffer the buffer to use as source * @param size the total size in bytes of the buffer * @return IO handle on success, NULL on error */ struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open_buffer (void *buffer, size_t size); /** * Close an open handle. Reports if any errors reading * from the file were encountered. * * @param h file handle * @param emsg set to the error message * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, char **emsg); /** * Read some contents into a buffer. * * @param h the IO handle to read from * @param what describes what is being read (for error message creation) * @param result the buffer to write the result to * @param len the number of bytes to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len); /** * Read 0-terminated string. * * @param h the IO handle to read from * @param what describes what is being read (for error message creation) * @param result where to store the pointer to the (allocated) string * (note that *result could be set to NULL as well) * @param max_length maximum allowed length for the string * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, const char *what, char **result, size_t max_length); /** * Read a metadata container. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) metadata * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, const char *what, struct GNUNET_CONTAINER_MetaData **result); /** * Read a float. * * @param h the IO handle to read from * @param what describes what is being read (for error message creation) * @param f address of float to read */ int GNUNET_BIO_read_float (struct GNUNET_BIO_ReadHandle *h, const char *what, float *f); /** * Read a double. * * @param h the IO handle to read from * @param what describes what is being read (for error message creation) * @param f address of double to read */ int GNUNET_BIO_read_double (struct GNUNET_BIO_ReadHandle *h, const char *what, double *f); /** * Read an (u)int32_t. * * @param h the IO handle to read from * @param what describes what is being read (for error message creation) * @param i where to store the data * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_read_int32 (struct GNUNET_BIO_ReadHandle *h, const char *what, int32_t *i); /** * Read an (u)int64_t. * * @param h the IO handle to read from * @param what describes what is being read (for error message creation) * @param i where to store the data * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_read_int64 (struct GNUNET_BIO_ReadHandle *h, const char *what, int64_t *i); /****************************** WRITING API *******************************/ /** * Handle for buffered writing. */ struct GNUNET_BIO_WriteHandle; /** * Open a file for writing. * * @param fn name of the file to be opened * @return IO handle on success, NULL on error */ struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open_file (const char *fn); /** * Create a handle backed by an in-memory buffer. * * @return IO handle on success, NULL on error */ struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open_buffer (void); /** * Force a file-based buffered writer to flush its buffer. * If the handle does not use a file, this function returns #GNUNET_OK * without doing anything. * * @param h the IO handle * @return #GNUNET_OK upon success. Upon failure #GNUNET_SYSERR is returned * and the file is closed */ int GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h); /** * Get the IO handle's contents. * If the handle doesn't use an in-memory buffer, this function returns * #GNUNET_SYSERR. * * @param h the IO handle * @param emsg set to the (allocated) error message * if the handle has an error message the return value is #GNUNET_SYSERR * @param contents where to store the pointer to the handle's contents * @param size where to store the size of @e contents * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_get_buffer_contents (struct GNUNET_BIO_WriteHandle *h, char **emsg, void **contents, size_t *size); /** * Close an IO handle. * If the handle was using a file, the file will be closed. * * @param h file handle * @param emsg set to the (allocated) error message * if the handle has an error message, the return value is #GNUNET_SYSERR * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h, char **emsg); /** * Write a buffer to a handle. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param buffer the data to write * @param n number of bytes to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, const char *what, const void *buffer, size_t n); /** * Write a 0-terminated string. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param s string to write (can be NULL) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, const char *what, const char *s); /** * Write a metadata container. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param m metadata to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, const char *what, const struct GNUNET_CONTAINER_MetaData *m); /** * Write a float. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param f float to write (must be a variable) */ int GNUNET_BIO_write_float (struct GNUNET_BIO_WriteHandle *h, const char *what, float f); /** * Write a double. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param f double to write (must be a variable) */ int GNUNET_BIO_write_double (struct GNUNET_BIO_WriteHandle *h, const char *what, double f); /** * Write an (u)int32_t. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param i 32-bit integer to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, const char *what, int32_t i); /** * Write an (u)int64_t. * * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param i 64-bit integer to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, const char *what, int64_t i); /****************************** READ SPEC API ***************************/ /** * Function used to deserialize data read from @a h and store it into @a * target. * * @param cls closure (can be NULL) * @param h the IO handle to read from * @param what what is being read (for error message creation) * @param target where to store the data * @param target_size how many bytes can be written in @a target * can be 0 if the size is unknown or is not fixed * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ typedef int (*GNUNET_BIO_ReadHandler)(void *cls, struct GNUNET_BIO_ReadHandle *h, const char *what, void *target, size_t target_size); /** * Structure specifying a reading operation on an IO handle. */ struct GNUNET_BIO_ReadSpec { /** * Function performing data deserialization. */ GNUNET_BIO_ReadHandler rh; /** * Closure for @e rh. Can be NULL. */ void *cls; /** * What is being read (for error message creation) */ const char *what; /** * Destination buffer. Can also be a pointer to a pointer, especially for * dynamically allocated structures. */ void *target; /** * Size of @e target. Can be 0 if unknown or not fixed. */ size_t size; }; /** * End of specifications marker. */ #define GNUNET_BIO_read_spec_end() \ { NULL, NULL, NULL, NULL, 0 } /** * Create the specification to read a certain amount of bytes. * * @param what describes what is being read (for error message creation) * @param result the buffer to write the result to * @param len the number of bytes to read * @return the read spec */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_object (const char *what, void *result, size_t size); /** * Create the specification to read a 0-terminated string. * * @param what describes what is being read (for error message creation) * @param result where to store the pointer to the (allocated) string * (note that *result could be set to NULL as well) * @param max_length maximum allowed length for the string * @return the read spec */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_string (const char *what, char **result, size_t max_length); /** * Create the specification to read a metadata container. * * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) metadata * @return the read spec */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_meta_data (const char *what, struct GNUNET_CONTAINER_MetaData **result); /** * Create the specification to read an (u)int32_t. * * @param what describes what is being read (for error message creation) * @param i where to store the data * @return the read spec */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_int32 (const char *what, int32_t *i); /** * Create the specification to read an (u)int64_t. * * @param what describes what is being read (for error message creation) * @param i where to store the data * @return the read spec */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_int64 (const char *what, int64_t *i); /** * Create the specification to read a float. * * @param what describes what is being read (for error message creation) * @param f address of float to read */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_float (const char *what, float *f); /** * Create the specification to read a double. * * @param what describes what is being read (for error message creation) * @param f address of double to read */ struct GNUNET_BIO_ReadSpec GNUNET_BIO_read_spec_double (const char *what, double *f); /** * Execute the read specifications in order. * * @param h the IO handle to read from * @param rs array of read specs * the last element must be #GNUNET_BIO_read_spec_end * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_read_spec_commit (struct GNUNET_BIO_ReadHandle *h, struct GNUNET_BIO_ReadSpec *rs); /******************************* WRITE SPEC API *****************************/ /** * Function used to serialize data from a buffer and write it to @a h. * * @param cls closure (can be NULL) * @param h the IO handle to write to * @param what what is being written (for error message creation) * @param source the data to write * @param source_size how many bytes should be written * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ typedef int (*GNUNET_BIO_WriteHandler) (void *cls, struct GNUNET_BIO_WriteHandle *h, const char *what, void *source, size_t source_size); /** * Structure specifying a writing operation on an IO handle. */ struct GNUNET_BIO_WriteSpec { /** * Function performing data serialization. */ GNUNET_BIO_WriteHandler wh; /** * Closure for @e rh. Can be NULL. */ void *cls; /** * What is being read (for error message creation) */ const char *what; /** * Source buffer. The data in this buffer will be written to the handle. */ void *source; /** * Size of @e source. If it's smaller than the real size of @e source, only * this many bytes will be written. */ size_t source_size; }; /** * End of specifications marker. */ #define GNUNET_BIO_write_spec_end() \ { NULL, NULL, NULL, NULL, 0 } /** * Create the specification to read some bytes. * * @param what describes what is being written (for error message creation) * @param source the data to write * @param size how many bytes should be written * @return the write spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_object (const char *what, void *source, size_t size); /** * Create the specification to write a 0-terminated string. * * @param what describes what is being read (for error message creation) * @param s string to write (can be NULL) * @return the read spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_string (const char *what, const char *s); /** * Create the specification to write a metadata container. * * @param what what is being written (for error message creation) * @param m metadata to write * @return the write spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_meta_data (const char *what, const struct GNUNET_CONTAINER_MetaData *m); /** * Create the specification to write an (u)int32_t. * * @param what describes what is being written (for error message creation) * @param i pointer to a 32-bit integer * @return the write spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_int32 (const char *what, int32_t *i); /** * Create the specification to write an (u)int64_t. * * @param what describes what is being written (for error message creation) * @param i pointer to a 64-bit integer * @return the write spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_int64 (const char *what, int64_t *i); /** * Create the specification to write a float. * * @param what describes what is being written (for error message creation) * @param f pointer to a float * @return the write spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_float (const char *what, float *f); /** * Create the specification to write an double. * * @param what describes what is being written (for error message creation) * @param f pointer to a double * @return the write spec */ struct GNUNET_BIO_WriteSpec GNUNET_BIO_write_spec_double (const char *what, double *f); /** * Execute the write specifications in order. * * @param h the IO handle to write to * @param ws array of write specs * the last element must be #GNUNET_BIO_write_spec_end * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_write_spec_commit (struct GNUNET_BIO_WriteHandle *h, struct GNUNET_BIO_WriteSpec *ws); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_BIO_LIB_H */ #endif /** @} */ /* end of group bio */ /* end of gnunet_bio_lib.h */