diff options
Diffstat (limited to 'src/io.c')
-rw-r--r-- | src/io.c | 108 |
1 files changed, 84 insertions, 24 deletions
@@ -17,27 +17,37 @@ #include "datagen.h" #include "cache.h" -static int stream_open_out(struct stream * const in, const struct settings * const s); -static int stream_open_out_lite(struct stream * const in, const struct settings * const s); -static int stream_open_in(struct stream * const in, const struct settings * const s); -static int stream_open_special(struct stream * const in); - -int stream_open(struct stream * const in, const struct settings * const s) +static int stream_open_out(struct stream * const in); +static int stream_open_out_lite(struct stream * const in); +static int stream_open_in(struct stream * const in); +static int stream_open_chardev(struct stream * const in); +static int stream_flush(struct stream * const in); +static int stream_flush_array(struct stream * const in); +static int stream_flush_list(struct stream * const in); + +int stream_open(struct stream * const in) { int ret = 0; - try(!in || in->fd > 0 || !in->name || !s, err, EINVAL, "invalid argunent"); + try(!in || in->fd > 0 || !in->name, err, EINVAL, "invalid argunent"); - if (in->out == 2) { - ret = stream_open_out_lite(in, s); - } else if (in->out == 1) { + switch (in->type) { + case (stream_outlite): + ret = stream_open_out_lite(in); + break; + case (stream_out): try(!in->name, err, EINVAL, "no filename given"); - ret = stream_open_out(in, s); - } else if (!in->out) { + ret = stream_open_out(in); + break; + case (stream_in): try(!in->name, err, EINVAL, "no filename given"); - ret = stream_open_in(in, s); - } else { - ret = stream_open_special(in); + ret = stream_open_in(in); + break; + case (stream_chardev): + ret = stream_open_chardev(in); + break; + default: + try(0, err, EINVAL, "cannot open stream: stream is invalid"); } err: @@ -50,7 +60,7 @@ int stream_close(struct stream * const in) try(!in || in->fd < 0, early_err, EINVAL, "invalid argunent"); - if (in->out != 1) { + if (in->type != stream_out) { goto out; } @@ -58,6 +68,8 @@ int stream_close(struct stream * const in) char path[PATH_MAX]; struct stat st; + try_s((ret = stream_flush(in)), err); + snprintf(path, PATH_MAX, "/proc/self/fd/%i", in->fd); if (!stat(in->name, &st)) { @@ -85,7 +97,7 @@ early_err: return ret; } -static int stream_open_out(struct stream * const in, const struct settings * const s) +static int stream_open_out(struct stream * const in) { struct stat st; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP; @@ -108,14 +120,14 @@ static int stream_open_out(struct stream * const in, const struct settings * con in->fd = open(dname, O_TMPFILE | O_RDWR, mode); try(in->fd < 0, err, errno, "failed creating temporary output file: %s", strerror(ret)); - try(ftruncate(in->fd, s->stride * in->n), err, errno, "failed setting output file size: %s", strerror(ret)); + try(ftruncate(in->fd, in->settings->stride * in->n), err, errno, "failed setting output file size: %s", strerror(ret)); err: free(dname); return ret; } -static int stream_open_out_lite(struct stream * const in, const struct settings * const s) +static int stream_open_out_lite(struct stream * const in) { struct stat st; char *dname = NULL; @@ -132,21 +144,21 @@ static int stream_open_out_lite(struct stream * const in, const struct settings in->fd = open(dname, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR); try(in->fd < 0, err, errno, "failed creating temporary output file: %s", strerror(ret)); - try(ftruncate(in->fd, s->stride * in->n), err, errno, "failed setting output file size: %s", strerror(ret)); + try(ftruncate(in->fd, in->settings->stride * in->n), err, errno, "failed setting output file size: %s", strerror(ret)); err: free(dname); return ret; } -static int stream_open_in(struct stream * const in, const struct settings * const s) +static int stream_open_in(struct stream * const in) { struct stat st; int ret = 0; try(stat(in->name, &st), err, errno, "stat failed: %s", strerror(ret)); - try(!(st.st_mode & S_IFREG) || !st.st_size || (st.st_size % s->stride), err, EINVAL, "invalid input file"); - in->n = st.st_size / s->stride; + try(!(st.st_mode & S_IFREG) || !st.st_size || (st.st_size % in->settings->stride), err, EINVAL, "invalid input file"); + in->n = st.st_size / in->settings->stride; in->fd = open(in->name, O_RDONLY | O_NOATIME); try(in->fd < 0, err, errno, "failed opening input file: %s", strerror(ret)); @@ -154,7 +166,7 @@ err: return ret; } -static int stream_open_special(struct stream * const in) +static int stream_open_chardev(struct stream * const in) { struct stat st; int ret = 0; @@ -166,3 +178,51 @@ static int stream_open_special(struct stream * const in) err: return ret; } + +int stream_flush(struct stream * const in) +{ + int ret = 0; + + try(in->settings->access != cached, err, EINVAL, "cannot flush an uncached stream"); + try(in->type != stream_out, err, EINVAL, "cannot flush a non-output cache"); + + if (in->settings->format == array) { + ret = stream_flush_array(in); + } else { + ret = stream_flush_list(in); + } +err: + return ret; +} + +int stream_flush_array(struct stream * const in) +{ + ssize_t ret = 0; + size_t remaining = in->n * in->settings->stride; + ssize_t written = 0; + + do { + ret = write(in->fd, in->cache + written, remaining); + if (ret < 0) { + try(errno != EAGAIN, err, errno, "Writing to stream failed with %zi", ret); + } else { + written += ret; + remaining -= ret; + ret = 0; + } + } while (remaining); + +err: + return ret; +} + +int stream_flush_list(struct stream * const in) +{ + int ret = ENOSYS; + + (void) in; + + rin_warn("stub!"); + + return ret; +} |