#include #include #include #include #include #include #include #include #include #include #include "io.h" int stream_open(struct stream *in) { struct stat st; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP; char *dname = NULL; int ret = 0; if (!in || in->fd > 0 || !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; } int stream_close(struct stream *in) { char path[PATH_MAX]; int ret = 0; if (!in || in->fd < 0) { ret = EINVAL; goto early_err; } if (in->out && in->name) { snprintf(path, PATH_MAX, "/proc/self/fd/%i", in->fd); if (linkat(AT_FDCWD, path, AT_FDCWD, in->name, AT_SYMLINK_FOLLOW)) { ret = errno; /* TODO: error message */ goto err; } } else { ret = EINVAL; goto err; } err: close(in->fd); in->fd = -1; early_err: return ret; }