aboutsummaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c150
1 files changed, 84 insertions, 66 deletions
diff --git a/src/util.c b/src/util.c
index 9c06e73..f9fb8ca 100644
--- a/src/util.c
+++ b/src/util.c
@@ -23,6 +23,7 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <sys/wait.h>
#include <syslog.h>
#include <time.h>
@@ -136,30 +137,34 @@ drop_privs_to (const char *user, const char *group)
}
#ifdef ENABLE_RTC
-struct rtc_handle
+int rtc_open(struct rtc_handle *h)
{
- int fd;
-};
-
-void *rtc_open()
-{
- struct rtc_handle *h = malloc(sizeof *h);
+ if (!h)
+ return -1;
+ h->fd = -1;
+ /* TODO: Use platform->file_open but drop NOFOLLOW? */
h->fd = open(DEFAULT_RTC_DEVICE, O_RDONLY);
if (h->fd < 0)
- {
+ {
pinfo("can't open rtc");
- free(h);
- return NULL;
+ return -1;
}
- return h;
+ return 0;
}
-int rtc_write(void *handle, const struct timeval *tv)
+/*
+ * Set the hardware clock referred to by fd (which should be a descriptor to
+ * some device that implements the interface documented in rtc(4)) to the system
+ * time. See hwclock(8) for details of why this is important. If we fail, we
+ * just return - there's nothing the caller can really do about a failure of
+ * this function except try later.
+ */
+int rtc_write(struct rtc_handle *handle, const struct timeval *tv)
{
struct tm tmr;
struct tm *tm;
struct rtc_time rtctm;
- int fd = ((struct rtc_handle *)handle)->fd;
+ int fd = handle->fd;
tm = gmtime_r (&tv->tv_sec, &tmr);
@@ -184,11 +189,11 @@ int rtc_write(void *handle, const struct timeval *tv)
return 0;
}
-int rtc_read(void *handle, struct timeval *tv)
+int rtc_read(struct rtc_handle *handle, struct timeval *tv)
{
struct tm tm;
struct rtc_time rtctm;
- int fd = ((struct rtc_handle *)handle)->fd;
+ int fd = handle->fd;
if (ioctl (fd, RTC_RD_TIME, &rtctm))
{
@@ -212,75 +217,72 @@ int rtc_read(void *handle, struct timeval *tv)
return 0;
}
-int rtc_close(void *handle)
+int rtc_close(struct rtc_handle *handle)
{
struct rtc_handle *h = handle;
- close(h->fd);
- free(h);
+ platform->file_close(h->fd);
+ h->fd = -1;
return 0;
}
#endif
-int file_write(const char *path, void *buf, size_t sz)
+int file_write(int fd, void *buf, size_t sz)
{
- char tmp[PATH_MAX];
- int oflags = O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC;
- int perms = S_IRUSR | S_IWUSR;
- int fd;
-
- if (snprintf(tmp, sizeof(tmp), path, kTempSuffix) >= sizeof(tmp))
- {
- pinfo("path %s too long to use", path);
- exit(1);
- }
-
- if ((fd = open(tmp, oflags, perms)) < 0)
- {
- pinfo("open(%s) failed", tmp);
- return 1;
- }
-
- if (write(fd, buf, sz) != sz)
- {
- pinfo("write() failed");
- close(fd);
- return 1;
- }
-
- if (close(fd))
- {
- pinfo("close() failed");
- return 1;
- }
-
- if (rename(tmp, path))
- {
- pinfo("rename() failed");
- return 1;
+ struct iovec iov[1];
+ ssize_t ret;
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sz;
+ ret = IGNORE_EINTR (pwritev (fd, iov, 1, 0));
+ if (ret != sz)
+ {
+ return -1;
}
-
return 0;
}
-int file_read(const char *path, void *buf, size_t sz)
+int file_open(const char *path, int write, int cloexec)
{
- int fd = open(path, O_RDONLY | O_NOFOLLOW);
+ int fd;
+ int oflags = cloexec ? O_CLOEXEC : 0;
+ if (write)
+ {
+ int perms = S_IRUSR | S_IWUSR;
+ oflags |= O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC;
+ /* Rely on atomic write calls rather than rename() calls. */
+ fd = open(path, oflags, perms);
+ }
+ else
+ {
+ oflags |= O_RDONLY | O_NOFOLLOW;
+ fd = open(path, oflags);
+ }
if (fd < 0)
- {
+ {
pinfo("open(%s) failed", path);
- return 1;
- }
-
- if (read(fd, buf, sz) != sz)
- {
- pinfo("read() failed");
- close(fd);
- return 1;
+ return -1;
}
+ return fd;
+}
+int file_close(int fd)
+{
return close(fd);
}
+int file_read(int fd, void *buf, size_t sz)
+{
+ struct iovec iov[1];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sz;
+ if (preadv (fd, iov, 1, 0) != sz)
+ {
+ /* Returns -1 on read failure */
+ return -1;
+ }
+ /* Returns 0 on a successful buffer fill. */
+ return 0;
+}
+
int time_get(struct timeval *tv)
{
return gettimeofday(tv, NULL);
@@ -297,6 +299,17 @@ int pgrp_kill(void)
return kill(-grp, SIGKILL);
}
+int process_signal(pid_t pid, int signal)
+{
+ return kill (pid, signal);
+}
+
+pid_t process_wait(pid_t pid, int *status, int forever)
+{
+ int flag = forever ? 0 : WNOHANG;
+ return waitpid (pid, status, flag);
+}
+
static struct platform default_platform = {
#ifdef ENABLE_RTC
.rtc_open = rtc_open,
@@ -305,13 +318,18 @@ static struct platform default_platform = {
.rtc_close = rtc_close,
#endif
+ .file_open = file_open,
+ .file_close = file_close,
.file_write = file_write,
.file_read = file_read,
.time_get = time_get,
.pgrp_enter = pgrp_enter,
- .pgrp_kill = pgrp_kill
+ .pgrp_kill = pgrp_kill,
+
+ .process_signal = process_signal,
+ .process_wait = process_wait
};
struct platform *platform = &default_platform;