summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-06-03 13:56:18 +0200
committerThomas Haller <thaller@redhat.com>2016-06-30 08:29:54 +0200
commitdcc8de16b2acc43b2a9155fcfb91fa2602f3a401 (patch)
treee9b0cdfc519c68e91be8c8a330ea751db444d293
parentdab657043caf65afcf3e8c2e639d4e977d25ba6f (diff)
downloadNetworkManager-dcc8de16b2acc43b2a9155fcfb91fa2602f3a401.tar.gz
core: add utils for file handling
Copied and adjusted from systemd code.
-rw-r--r--src/nm-core-utils.c118
-rw-r--r--src/nm-core-utils.h6
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);