diff options
author | Thomas Haller <thaller@redhat.com> | 2016-06-03 13:56:18 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-06-30 08:29:54 +0200 |
commit | dcc8de16b2acc43b2a9155fcfb91fa2602f3a401 (patch) | |
tree | e9b0cdfc519c68e91be8c8a330ea751db444d293 | |
parent | dab657043caf65afcf3e8c2e639d4e977d25ba6f (diff) | |
download | NetworkManager-dcc8de16b2acc43b2a9155fcfb91fa2602f3a401.tar.gz |
core: add utils for file handling
Copied and adjusted from systemd code.
-rw-r--r-- | src/nm-core-utils.c | 118 | ||||
-rw-r--r-- | src/nm-core-utils.h | 6 |
2 files changed, 124 insertions, 0 deletions
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index eb85fa0eb7..0a913e9c8e 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -26,6 +26,7 @@ #include <errno.h> #include <fcntl.h> #include <string.h> +#include <poll.h> #include <unistd.h> #include <stdlib.h> #include <resolv.h> @@ -2711,6 +2712,123 @@ nm_utils_machine_id_read (void) /*****************************************************************************/ +/* taken from systemd's fd_wait_for_event(). Note that the timeout + * is here in nano-seconds, not micro-seconds. */ +int +nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns) +{ + struct pollfd pollfd = { + .fd = fd, + .events = event, + }; + struct timespec ts, *pts; + int r; + + if (timeout_ns < 0) + pts = NULL; + else { + ts.tv_sec = (time_t) (timeout_ns / NM_UTILS_NS_PER_SECOND); + ts.tv_nsec = (long int) (timeout_ns % NM_UTILS_NS_PER_SECOND); + pts = &ts; + } + + r = ppoll (&pollfd, 1, pts, NULL); + if (r < 0) + return -errno; + if (r == 0) + return 0; + return pollfd.revents; +} + +/* taken from systemd's loop_read() */ +ssize_t +nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll) +{ + uint8_t *p = buf; + ssize_t n = 0; + + g_return_val_if_fail (fd >= 0, -EINVAL); + g_return_val_if_fail (buf, -EINVAL); + + /* If called with nbytes == 0, let's call read() at least + * once, to validate the operation */ + + if (nbytes > (size_t) SSIZE_MAX) + return -EINVAL; + + do { + ssize_t k; + + k = read (fd, p, nbytes); + if (k < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN && do_poll) { + + /* We knowingly ignore any return value here, + * and expect that any error/EOF is reported + * via read() */ + + (void) nm_utils_fd_wait_for_event (fd, POLLIN, -1); + continue; + } + + return n > 0 ? n : -errno; + } + + if (k == 0) + return n; + + g_assert ((size_t) k <= nbytes); + + p += k; + nbytes -= k; + n += k; + } while (nbytes > 0); + + return n; +} + +/* taken from systemd's loop_read_exact() */ +int +nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll) +{ + ssize_t n; + + n = nm_utils_fd_read_loop (fd, buf, nbytes, do_poll); + if (n < 0) + return (int) n; + if ((size_t) n != nbytes) + return -EIO; + + return 0; +} + +/* taken from systemd's dev_urandom(). */ +int +nm_utils_read_urandom (void *p, size_t nbytes) +{ + int fd = -1; + int r; + +again: + fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + r = errno; + if (r == EINTR) + goto again; + return r == ENOENT ? -ENOSYS : -r; + } + + r = nm_utils_fd_read_loop_exact (fd, p, nbytes, TRUE); + close (fd); + + return r; +} + +/*****************************************************************************/ + guint8 * nm_utils_secret_key_read (gsize *out_key_len, GError **error) { diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 154e88331e..86b4fe6ad2 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -310,6 +310,12 @@ const char *nm_utils_ip4_property_path (const char *ifname, const char *property gboolean nm_utils_is_specific_hostname (const char *name); +int nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns); +ssize_t nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll); +int nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll); + +int nm_utils_read_urandom (void *p, size_t n); + char *nm_utils_machine_id_read (void); gboolean nm_utils_machine_id_parse (const char *id_str, /*uuid_t*/ guchar *out_uuid); |