aboutsummaryrefslogtreecommitdiff
path: root/src/util_rt.h
blob: 818ad5d52e771f036734529ddb131d098dfa8ab6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
/** \file
 * \brief Runtime utility and convenience functions
 */
/*
* Copyright (c) 2019-2022 David Timber <dxdt@dev.snart.me>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include "pack.h"

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>

#include <sys/poll.h>

#include <mbedtls/ctr_drbg.h>


/**
 * \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);

/**
 * \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,
	const size_t se,
	size_t *old,
	const size_t req);

/* 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);
/**
 * \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);

/**
 * \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);
/**
 * \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);

/**
 * \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,
	const size_t len);