diff options
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 150 |
1 files changed, 84 insertions, 66 deletions
@@ -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; |