aboutsummaryrefslogtreecommitdiff
path: root/src/util_rt.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/util_rt.h')
-rw-r--r--src/util_rt.h411
1 files changed, 395 insertions, 16 deletions
diff --git a/src/util_rt.h b/src/util_rt.h
index b60bedd..48af5b6 100644
--- a/src/util_rt.h
+++ b/src/util_rt.h
@@ -1,3 +1,6 @@
+/** \file
+ * \brief Runtime utility and convenience functions
+ */
/*
* Copyright (c) 2019-2021 David Timber <mieabby@gmail.com>
*
@@ -32,29 +35,183 @@
#include <mbedtls/ctr_drbg.h>
-void prne_empty_func (void);
-void prne_close (const int fd);
+/**
+ * \brief Call \c close() only if the \p fd is zero or greater to preserve
+ * \c errno
+ * \retval 0 if \p fd is less than zero (no op)
+ * \return the value returned from \c close() otherwise
+ * \see \c close()
+ * \see [/doc/impl.md#Resource Allocation Hook](/doc/impl.md#resource_allocation_hook)
+ */
+int prne_close (const int fd);
+/**
+ * \brief Call \c shutdown() only if the \p fd is zero or greater to preserve
+ * \c errno
+ * \see \c shutdown()
+ */
void prne_shutdown (const int fd, const int how);
/* prne_sck_fcntl(fd)
*
* Sets FD_CLOEXEC and O_NONBLOCK. Failure to set FD_CLOEXEC is ignored.
*/
+
+/**
+ * \brief Set the commmon socket flags associated with the fd. The common flags
+ * are \c FD_CLOEXEC and \c O_NONBLOCK
+ * \retval true if the mission critial flags(O_NONBLOCK) are successfully set
+ * \retval false otherwise. \c errno is set by \c fcntl()
+ * \warning The error occurred setting \c FD_CLOEXEC is ignored as the flag is
+ * considered non mission critial.
+ * \see \c fcntl()
+ */
bool prne_sck_fcntl (const int fd);
+/**
+ * \brief Convenience function for changing the fd to a new fd using \c dup2()
+ * Upon successful \c dup2() call, the old fd is closed and the new fd is
+ * returned.
+ * \param old The old fd
+ * \param ny The desired value for the new fd
+ * \retval -1 on error
+ * \return The new fd returned by \c dup2()
+ * \see \c dup2()
+ * \warning This function assumes that as long as the new fd stays open, closing
+ * the old fd won't block the calling thread. There might be cases where close()
+ * fails or blocks regardless?
+ * \note As per the behaviour of \c dup2(), the new fd is silently closed if if
+ * is a valid fd. Use this function if you're absolutely sure that the new fd is
+ * not used. Like setting up a pipe as standard IO(fd 0, 1 and 2).
+ */
int prne_chfd (const int old, const int ny);
+/**
+ * \brief Zero-fill the region of memory - call \c memset() with zero
+ */
void prne_memzero(void *addr, const size_t len);
-void *prne_malloc (const size_t se, const size_t cnt);
+/**
+ * \brief Safe \c malloc() - do overflow check and return NULL for zero length
+ * allocation
+ * \param se the size of an element
+ * \param cnt the number of elements
+ * \retval NULL if the size calculated is zero. \c errno left untouched
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer returned from \c malloc()
+ * \note The purpose of the functions including \c prne_realloc()
+ * \c prne_calloc() is following.
+ * - To have a version of \c malloc() that always returns NULL for zero-length
+ * allocation. A valid pointer is returned on most platforms and NULL is
+ * returned on some platforms.
+ * - Integer overflow check (especially for 16-bit machines)
+ * - To implement a memory allocation event system in the future. Valgrind might
+ * not be a suitable candidate to debug Proone and a different approach(like
+ * the one chosen for MSVCRT) could be desired.
+ * \see \c malloc()
+ */
+void *prne_malloc (const size_t se, const size_t cnt);\
+/**
+ * \brief Do \c reallocarray() See \c prne_malloc()
+ * \param ptr the pointer to the previously dynamically allocated memory
+ * acceptable by \c realloc()
+ * \param se the size of an element
+ * \param cnt the number of elements
+ * \retval NULL if the size calculated is zero. \c errno is left untouched. If
+ * \p ptr is not NULL, free() has been performed to free the memory.
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer returned from \c realloc()
+ * \note Unlike \c realloc() using this function with \p ptr to dynamically
+ * allocated memory and either of \p se or \p cnt zero has the same effect as
+ * \c free()
+ * \see \c prne_malloc()
+ */
void *prne_realloc (void *ptr, const size_t se, const size_t cnt);
+/**
+ * \brief Call \c calloc() but ensure that NULL is always returned for
+ * zero-length allocation
+ * \param se the size of an element
+ * \param cnt the number of elements
+ * \retval NULL if the size calculated is zero. \c errno left untouched
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer returned from \c calloc()
+ * \see \c prne_malloc()
+ */
void *prne_calloc (const size_t se, const size_t cnt);
+/**
+ * \brief Dynamically allocate memory for a string of the specified length. This
+ * is a convenience function for performing \c malloc(strlen(str)+1)
+ * \param len the byte length of the string excluding the null-terminator
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer to the dynamically allocated memory for storing the
+ * string of the specified length
+ * \see \c prne_realloc_str()
+ * \note Implemented using \c prne_realloc_str()
+ */
char *prne_alloc_str (const size_t len);
+/**
+ * \brief Dynamically allocate memory for a string of the specified length. This
+ * is a convenience function for performing \c realloc(ptr,strlen(str)+1)
+ * \param old the pointer to the previously dynamically allocated memory
+ * \param len the new byte length of the string excluding the null-terminator
+ * \retval NULL on allocation failure or integer overflow. \c errno set to
+ * \c ENOMEM
+ * \return The pointer to the newly dynamically allocated memory for storing the
+ * string of the specified length
+ * \note Unlike \c prne_realloc() calling this function with zero \p len won't
+ * free \p old since the length of the new string is calculated as len + 1
+ */
char *prne_realloc_str (char *old, const size_t len);
+/**
+ * \brief Make a new copy of the string. This is a convenience function for
+ * performing \c malloc(strlen(str)+1) and then \c strcpy()
+ * \retval NULL on memory allocation error, \c errno set to \c ENOMEM
+ * \return The pointer to the new copy of the string
+ * \see \c prne_redup_str()
+ * \note Implemented using \c prne_redup_str()
+ */
char *prne_dup_str (const char *str);
+/**
+ * \brief Make a new copy of the string. This is a convenience function for
+ * performing \c realloc(ptr,strlen(str)+1) and then \c strcpy()
+ * \retval NULL on memory allocation error, \c errno set to \c ENOMEM
+ * \return The pointer to the new copy of the string
+ * \see \c prne_redup_str()
+ * \note Implemented using \c prne_redup_str()
+ */
char *prne_redup_str (char *old, const char *str);
+/**
+ * \brief Scrub and free the string. For freeing strings containing sensitive
+ * data
+ */
void prne_sfree_str (char *s);
+/**
+ * \brief Do \c free()
+ * \see [/doc/impl.md#Resource Allocation Hook](/doc/impl.md#resource_allocation_hook)
+ */
void prne_free (void *ptr);
+/**
+ * \brief Do \c sysconf(_SC_PAGESIZE) Call \c abort() on failure
+ */
size_t prne_getpagesize (void);
+/**
+ * \brief Assume the ownership of the memory by doing \c realloc() if necessary.
+ * If \p ownership is unset, the function allocates new memory and copies the
+ * content of the original memory to the new memory, leaving the original memory
+ * intact. The \p ownership will always be set upon successful operation. If the
+ * flag is set, calling the function is equivalent to calling \c realloc()
+ *
+ * \param p The pointer to the pointer holding the address
+ * \param ownership The pointer to the the current ownership flag
+ * \param se The byte size of each element
+ * \param old The current number of elements
+ * \param req The number of elements requested
+ * \retval true if the operation was successful
+ * \retval false otherwise, \c errno set
+ * \see [/doc/impl.md#Ownership of Dynamically Resources](/doc/impl.md#ownership_of_dynamically_resources)
+ */
bool prne_own_realloc (
void **p,
bool *ownership,
@@ -62,101 +219,323 @@ bool prne_own_realloc (
size_t *old,
const size_t req);
-/* Locale "C" character category functions
-*/
+/* Locale "C" character category functions */
+/**
+ * \brief The POSIX locale \c toupper() that does not use any global
+ */
char prne_ctoupper (const char c);
+/**
+ * \brief The POSIX locale \c tolower() that does not use any global
+ */
char prne_ctolower (const char c);
+/**
+ * \brief The POSIX locale \c isspace() that does not use any global
+ */
bool prne_cisspace (const char c);
+/**
+ * \brief The POSIX locale \c isprint() that does not use any global
+ */
bool prne_cisprint (const char c);
-
+/**
+ * \brief Test if \p c is zero
+ */
bool prne_ciszero (const char c);
+/**
+ * \brief Test if two strings are equal, treating a null pointer as an empty
+ * string
+ */
bool prne_nstreq (const char *a, const char *b);
+/**
+ * \brief Calculate the number of non-zero characters in the string. A null
+ * pointer is treated as an empty string
+ */
size_t prne_nstrlen (const char *s);
+/**
+ * \brief Find the first occurence of a character in the string
+ *
+ * \param p The string
+ * \param c The character to look for. A null character is valid
+ * \param n The number of characters in the string
+ * \return The pointer to the original string offset to the first character
+ * found in the string
+ * \retval NULL if the character is not found in the string or a null terminator
+ * was encountered
+ */
char *prne_strnchr (const char *p, const char c, const size_t n);
-size_t prne_str_shift_spaces (char *str, const size_t len);
+/**
+ * \brief Test the string with \p chk_f
+ *
+ * \param str The string
+ * \param chk_f The test function
+ * \retval true if \p chk_f returned true for all characters in the string
+ * \retval false otherwise
+ */
bool prne_chkcstr (const char *str, bool(*chk_f)(const char));
+/**
+ * \brief Test the memory with \c chk_f
+ *
+ * \param m The memory
+ * \param len The byte length of the memory
+ * \param chk_f The test function
+ * \retval true if \p chk_f returned true for all bytes in the memory
+ * \retval false otherwise
+ */
bool prne_chkcmem (const void *m, size_t len, bool(*chk_f)(const char));
+/**
+ * \brief Transform the string using \p trans_f
+ */
void prne_transstr (char *str, int(*trans_f)(int));
+/**
+ * \brief Transform the string using \p trans_f
+ */
void prne_transcstr (char *str, char(*trans_f)(char));
+/**
+ * \brief Transform the memory using \p trans_f
+ */
void prne_transmem (void *m, size_t len, int(*trans_f)(int));
+/**
+ * \brief Transform the memory using \p trans_f
+ */
void prne_transcmem (void *m, size_t len, char(*trans_f)(char));
+/**
+ * \brief Find the last occurrence of the character in the memory
+ *
+ * \param haystack The memory
+ * \param c The character
+ * \param hs_len The byte length of the memory
+ * \return The pointer to the original string offset to the last character found
+ * in the string
+ * \retval NULL if the character is not found in the string
+ */
void *prne_memrchr (
const void *haystack,
const int c,
const size_t hs_len);
+/**
+ * \brief Find the last occurrence of the data in the memory
+ *
+ * \param haystack The memory
+ * \param hs_len The byte length of the memory
+ * \param needle The data
+ * \param n_len The byte length of the data
+ * \return The pointer to the original memory offset to the last occurrence of
+ * the data found in the memory
+ * \retval NULL if the data is not found in the memory
+ */
void *prne_memrmem (
const void *haystack,
const size_t hs_len,
const void *const needle,
const size_t n_len);
+/**
+ * \brief Find the first occurrence of the data in the memory
+ *
+ * \param haystack The memory
+ * \param hs_len The byte length of the memory
+ * \param needle The data
+ * \param n_len The byte length of the data
+ * \return The pointer to the original memory offset to the first occurrence of
+ * the data found in the memory
+ * \retval NULL if the data is not found in the memory
+ */
void *prne_memmem (
const void *haystack,
const size_t hs_len,
const void *const needle,
const size_t n_len);
+/**
+ * \brief Concatenate strings to build a new string
+ *
+ * \param arr The pointer to the array of null-terminated strings
+ * \param cnt The number of elements in \p arr
+ * \return The new string
+ * \retval NULL on error, \c errno set
+ * \see \c prne_rebuild_str()
+ */
char *prne_build_str (const char **const arr, const size_t cnt);
+/**
+ * \brief Concatenate strings to build a new string, doing \c realloc() if
+ * necessary
+ *
+ * \param arr The pointer to the array of null-terminated strings
+ * \param cnt The number of elements in \p arr
+ * \return The new/reallocated string
+ * \retval NULL on error, \c errno set
+ * \see \c prne_build_str()
+ */
char *prne_rebuild_str (void *prev, const char **const arr, const size_t cnt);
+/**
+ * \brief Scrub the string. Do nothing if \p str is NULL
+ */
void prne_strzero (char *str);
+/**
+ * \brief Parse an \c uint8_t from the hex characters
+ *
+ * \param str The pointer to an array of characters at least 2 in length
+ * \param out The output
+ * \retval true on success
+ * \retval false if the array contains invalid characters, \c errno set to
+ * \c EINVAL
+ */
bool prne_hex_fromstr (const char *str, uint_fast8_t *out);
+/**
+ * \brief Convert an \c uint8_t to hex characters
+ *
+ * \param in The value
+ * \param out The pointer to an array of characters at least 2 in length
+ * \param upper The uppercase flag. If set, uppercase characters will be used.
+ * Lowercase characters will be used otherwise.
+ */
void prne_hex_tochar (const uint_fast8_t in, char *out, const bool upper);
-/*
-* \param str: at least 36 bytes
-* \param out: at least 16 bytes
-*/
+/**
+ * \brief Parse a UUID from the string
+ *
+ * \param str The string containing a UUID, at least 36 characters long
+ * \param out The output memory, at least 16 bytes long
+ * \retval true on success
+ * \retval false on format error, \c errno set to EINVAL
+ */
bool prne_uuid_fromstr (const char *str, uint8_t *out);
-/*
-* \param in: at least 16 bytes
-* \param out: at least 37 bytes (null-terminated)
-*/
+/**
+ * \brief Convert the UUID to a null-terminated string
+ *
+ * \param in The memory of the UUID, at least 16 bytes long
+ * \param out The preallocated string for output, at least 37 characters long
+ */
void prne_uuid_tostr (const uint8_t *in, char *out);
+/**
+ * \brief Compare two UUIDs
+ *
+ * \param a The pointer to memory at least 16 bytes long
+ * \param b The pointer to memory at least 16 bytes long
+ * \return an integer less than, equal to, or greater than zero if \p a is found
+ * respectively, to be less than, to match, or be greater than \p b
+ */
int prne_cmp_uuid_asc (const void *a, const void *b);
+/**
+ * \brief Reverse function of \c prne_cmp_uuid_asc()
+ * \see \c prne_cmp_uuid_asc()
+ */
int prne_cmp_uuid_desc (const void *a, const void *b);
+/**
+ * \brief Calculate the addition of two timespec structures
+ */
struct timespec prne_add_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Calculate the subtraction of two timespec structures
+ */
struct timespec prne_sub_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Convert the timespec structure to seconds
+ */
double prne_real_timespec (const struct timespec ts);
+/**
+ * \brief Convert the timespec structure to milliseconds
+ */
long prne_timespec_ms (const struct timespec ts);
+/**
+ * \brief Construct a timespec structure from milliseconds
+ */
struct timespec prne_ms_timespec (const long ms);
+/**
+ * \brief Compare two timespec strucrures
+ * \return an integer less than, equal to, or greater than zero if \p a is found
+ * respectively, to be less than, to match, or be greater than \p b
+ */
int prne_cmp_timespec (const struct timespec a, const struct timespec b);
+/**
+ * \brief Return the timespec structure with the smallest value
+ */
struct timespec prne_min_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Return the timespec structure with the largest value
+ */
struct timespec prne_max_timespec (
const struct timespec a,
const struct timespec b);
+/**
+ * \brief Do \c clock_gettime() call, \c abort() on error
+ */
struct timespec prne_gettime (const clockid_t cid);
+/**
+ * \brief Convert a timespec structure to a timeval structure
+ */
struct timeval prne_ts2tv (const struct timespec ts);
+/**
+ * \brief Construct a timeval structure from milliseconds
+ */
struct timeval prne_ms_timeval (const long ms);
+/**
+ * \brief Encode data in Base64 in memory. Allocates memory for output
+ *
+ * \param data The data to encode
+ * \param size The byte length of the data
+ * \return The pointer to a newly allocated string containing encoded data
+ */
char *prne_enc_base64_mem (const uint8_t *data, const size_t size);
+/**
+ * \brief Decode the base64 string. Allocates memory for output
+ *
+ * \param str The input string containing base64 encoded data
+ * \param str_len The length of the input string
+ * \param data The pointer for output data
+ * \param size The pointer for the byte length of the output data
+ * \retval true on success
+ * \retval false on memory error(ENOMEM) or parsing error(EINVAL)
+ */
bool prne_dec_base64_mem (
const char *str,
const size_t str_len,
uint8_t **data,
size_t *size);
-// getrandom polyfill
+/**
+ * \brief Read \c /dev/urandom directly.
+ *
+ * \param buf The pointer to memory for output
+ * \param len The number of bytes to read
+ * \return The value returned from \c read() function. \c errno set to the value
+ * from the \c read() function
+ * \note This function is made to avoid the use of \c getrandom() which can
+ * potentially block the caller thread in the event of insufficient entropy
+ */
ssize_t prne_geturandom (void *buf, const size_t len);
+/**
+ * \brief Output the result of bitwise AND operation of the contents of two byte
+ * arrays to \p c
+ */
void prne_bitop_and (
const uint8_t *a,
const uint8_t *b,
uint8_t *c,
const size_t len);
+/**
+ * \brief Output the result of bitwise OR operation of the contents of two byte
+ * arrays to \p c
+ */
void prne_bitop_or (
const uint8_t *a,
const uint8_t *b,
uint8_t *c,
const size_t len);
+/**
+ * \brief Output the result of bitwise NOT operation of the contents of the byte
+ * array \p x to \p y
+ */
void prne_bitop_inv (
const uint8_t *x,
uint8_t *y,