diff options
Diffstat (limited to 'src/io.c')
-rw-r--r-- | src/io.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/io.c b/src/io.c new file mode 100644 index 0000000..74ea274 --- /dev/null +++ b/src/io.c @@ -0,0 +1,91 @@ +#include <sys/types.h> +#include <sys/stat.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" + +int openstream(struct stream *in) +{ + struct stat st; + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP; + char *dname = NULL; + int ret = 0; + + in->fd = -1; + + if (!in->name) { + ret = EINVAL; + goto err; + } + + if (in->out) { + char *tmp[2]; + + tmp[0] = strdup(in->name); + tmp[1] = dirname(tmp[0]); + dname = strdup(tmp[1]); + free(tmp[0]); + + if (stat(dname, &st)) { + ret = errno; + /* TODO: error message */ + goto err; + } + + if(!(st.st_mode & S_IFDIR)) { + ret = EINVAL; + /* TODO: error message */ + goto err; + } + + if (!stat(in->name, &st)) { + if (!(st.st_mode & S_IFREG)) { + ret = EINVAL; + /* TODO: error message */ + goto err; + } + mode = st.st_mode; + } + } else if (stat(in->name, &st)) { + ret = errno; + /* TODO: error message */ + goto err; + } else if (!(st.st_mode & S_IFREG) || !st.st_size || (st.st_size % in->stride)) { + ret = EINVAL; + /* TODO: error message */ + goto err; + } else { + in->n = st.st_size / in->stride; + } + + if (in->out) { + in->fd = open(dname, O_TMPFILE | O_WRONLY, mode); + if (in->fd < 0) { + ret = errno; + /* TODO: error message */ + goto err; + } + + if (ftruncate(in->fd, in->stride * in->n)) { + ret = errno; + /* TODO: error message */ + goto err; + } + } else { + in->fd = open(in->name, O_RDONLY | O_NOATIME); + if (in->fd < 0) { + ret = errno; + /* TODO: error message */ + goto err; + } + } + +err: + free(dname); + return ret; +} |