summaryrefslogtreecommitdiffstats
path: root/src/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/io.c')
-rw-r--r--src/io.c241
1 files changed, 0 insertions, 241 deletions
diff --git a/src/io.c b/src/io.c
deleted file mode 100644
index 5f86678..0000000
--- a/src/io.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-
-/* Copyright (C) 2020 Gediminas Jakutis */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <linux/limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <libgen.h>
-#include "io.h"
-#include "defs.h"
-#include "datagen.h"
-#include "cache.h"
-
-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_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 && in->type != stream_randread), err, EINVAL, "invalid argunent");
-
- 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);
- break;
- case (stream_in):
- try(!in->name, err, EINVAL, "no filename given");
- ret = stream_open_in(in);
- break;
- case (stream_randread):
- ; /* NOOP */
- break;
- default:
- try(0, err, EINVAL, "cannot open stream: stream is invalid");
- }
-
-err:
- return ret;
-}
-
-int stream_close(struct stream * const in)
-{
- int ret = 0;
-
- try(!in || (in->fd < 0 && in->type != stream_randread), early_err, EINVAL, "invalid argunent");
-
- if (in->type != stream_out) {
- goto out;
- }
-
- if (in->name) {
- 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)) {
- if (st.st_mode & S_IFREG) {
- unlink(in->name);
- } else {
- ret = EINVAL;
- rin_err("the given output file already exists and is not a regular file");
- goto err;
- }
- }
-
- try(linkat(AT_FDCWD, path, AT_FDCWD, in->name, AT_SYMLINK_FOLLOW), err, errno, "error linking output file to filesystem: %s", strerror(ret));
- } else {
- rin_err("no output filename given");
- ret = EINVAL;
- goto err;
- }
-
-out:
- if (in->settings->access == cached) {
- cache_destroy(in);
- }
-err:
- close(in->fd);
- in->fd = -1;
-early_err:
- return ret;
-}
-
-static int stream_open_out(struct stream * const in)
-{
- struct stat st;
- mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP;
- char *dname = NULL;
- char *tmp[2];
- int ret = 0;
-
- tmp[0] = strdup(in->name);
- tmp[1] = dirname(tmp[0]);
- dname = strdup(tmp[1]);
- free(tmp[0]);
-
- try(stat(dname, &st), err, errno, "stat failed: %s", strerror(ret));
- try(!(st.st_mode & S_IFDIR), err, EINVAL, "invalid output path");
-
- if (!stat(in->name, &st)) {
- try(!(st.st_mode & S_IFREG), err, EINVAL, "the given output file already exists and is not a regular file");
- mode = st.st_mode;
- }
-
- 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, 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)
-{
- struct stat st;
- char *dname = NULL;
- char *tmp[2];
- int ret = 0;
-
- tmp[0] = strdup(in->name);
- tmp[1] = dirname(tmp[0]);
- dname = strdup(tmp[1]);
- free(tmp[0]);
-
- try(stat(dname, &st), err, errno, "stat failed: %s", strerror(ret));
- try(!(st.st_mode & S_IFDIR), err, EINVAL, "invalid output path");
-
- 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, 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)
-{
- 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 % 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));
-
-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)
-{
- ssize_t ret = 0;
- size_t remaining;
- ssize_t written;
- size_t i;
-
- /* adjust pointers to have a base starting at 0, to cater to disk storage format.
- * File offsets are otherwise 1:1 to memory addresses, which is neat.
- * Just don't process the last offset, as that is always NULL/zero.
- * */
-
- for (i = 0; i < (in->n - 1); ++i) {
- in->cache_l[i].offset = (char *) in->cache_l[i].next - in->cache;
- }
-
- /* dump the bloody list */
- written = 0;
- remaining = in->n * in->settings->stride;
-
- 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;
-}