core: add utils for file handling

Copied and adjusted from systemd code.
This commit is contained in:
Thomas Haller 2016-06-03 13:56:18 +02:00
parent dab657043c
commit dcc8de16b2
2 changed files with 124 additions and 0 deletions

View file

@ -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)
{

View file

@ -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);