diff options
Diffstat (limited to 'shared/nm-glib-aux/nm-io-utils.c')
| -rw-r--r-- | shared/nm-glib-aux/nm-io-utils.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/shared/nm-glib-aux/nm-io-utils.c b/shared/nm-glib-aux/nm-io-utils.c index ec0cd4c8..776c63e1 100644 --- a/shared/nm-glib-aux/nm-io-utils.c +++ b/shared/nm-glib-aux/nm-io-utils.c @@ -11,6 +11,7 @@ #include <sys/stat.h> #include <fcntl.h> +#include "nm-str-buf.h" #include "nm-shared-utils.h" #include "nm-secret-utils.h" #include "nm-errno.h" @@ -51,32 +52,6 @@ _get_contents_error (GError **error, int errsv, int *out_errsv, const char *form _get_contents_error (error, _errsv, out_errsv, __VA_ARGS__); \ }) -static char * -_mem_realloc (char *old, gboolean do_bzero_mem, gsize cur_len, gsize new_len) -{ - char *new; - - /* re-allocating to zero bytes is an odd case. We don't need it - * and it's not supported. */ - nm_assert (new_len > 0); - - /* regardless of success/failure, @old will always be freed/consumed. */ - - if (do_bzero_mem && cur_len > 0) { - new = g_try_malloc (new_len); - if (new) - memcpy (new, old, NM_MIN (cur_len, new_len)); - nm_explicit_bzero (old, cur_len); - g_free (old); - } else { - new = g_try_realloc (old, new_len); - if (!new) - g_free (old); - } - - return new; -} - /** * nm_utils_fd_get_contents: * @fd: open file descriptor to read. The fd will not be closed, @@ -161,7 +136,7 @@ nm_utils_fd_get_contents (int fd, str[n_read] = '\0'; if (n_read < n_stat) { - if (!(str = _mem_realloc (str, do_bzero_mem, n_stat + 1, n_read + 1))) + if (!(str = nm_secret_mem_try_realloc_take (str, do_bzero_mem, n_stat + 1, n_read + 1))) return _get_contents_error (error, ENOMEM, out_errsv, "failure to reallocate buffer with %zu bytes", n_read + 1); } NM_SET_OUT (length, n_read); @@ -222,7 +197,7 @@ nm_utils_fd_get_contents (int fd, n_alloc = NM_MIN (n_read + 1, sizeof (buf)); } - if (!(str = _mem_realloc (str, do_bzero_mem, old_n_alloc, n_alloc))) { + if (!(str = nm_secret_mem_try_realloc_take (str, do_bzero_mem, old_n_alloc, n_alloc))) { if (do_bzero_mem) nm_explicit_bzero (buf, sizeof (buf)); return _get_contents_error (error, ENOMEM, out_errsv, "failure to allocate buffer of %zu bytes", n_alloc); @@ -241,7 +216,7 @@ nm_utils_fd_get_contents (int fd, else { str[n_have] = '\0'; if (n_have + 1 < n_alloc) { - if (!(str = _mem_realloc (str, do_bzero_mem, n_alloc, n_have + 1))) + if (!(str = nm_secret_mem_try_realloc_take (str, do_bzero_mem, n_alloc, n_have + 1))) return _get_contents_error (error, ENOMEM, out_errsv, "failure to truncate buffer to %zu bytes", n_have + 1); } } @@ -438,3 +413,46 @@ nm_utils_file_stat (const char *filename, struct stat *out_st) return -NM_ERRNO_NATIVE (errno); return 0; } + +/** + * nm_utils_fd_read: + * @fd: the fd to read from. + * @out_string: (out): output string where read bytes will be stored. + * + * Returns: <0 on failure, which is -(errno). + * 0 on EOF. + * >0 on success, which is the number of bytes read. */ +gssize +nm_utils_fd_read (int fd, NMStrBuf *out_string) +{ + gsize buf_available; + gssize n_read; + int errsv; + + g_return_val_if_fail (fd >= 0, -1); + g_return_val_if_fail (out_string, -1); + + /* If the buffer size is 0, we allocate NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 (1000 bytes) + * the first time. Afterwards, the buffer grows exponentially. + * + * Note that with @buf_available, we always would read as much buffer as we actually + * have reserved. */ + nm_str_buf_maybe_expand (out_string, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE); + + buf_available = out_string->allocated - out_string->len; + + n_read = read (fd, + &((nm_str_buf_get_str_unsafe (out_string))[out_string->len]), + buf_available); + if (n_read < 0) { + errsv = errno; + return -NM_ERRNO_NATIVE (errsv); + } + + if (n_read > 0) { + nm_assert ((gsize) n_read <= buf_available); + nm_str_buf_set_size (out_string, out_string->len + (gsize) n_read, TRUE, FALSE); + } + + return n_read; +} |