X-Git-Url: http://git.scottworley.com/overonion/blobdiff_plain/fc795c1bb267737820c2059ca8aaa7bcb2848a10..b398ee5ae7abfa019f84628204f3c1cd146ed39e:/reverse_lib.c diff --git a/reverse_lib.c b/reverse_lib.c new file mode 100644 index 0000000..a800db8 --- /dev/null +++ b/reverse_lib.c @@ -0,0 +1,63 @@ +#define _FILE_OFFSET_BITS 64 + +#define BUFFER_SIZE 4096 + +#include +#include +#include +#include +#include +#include +#include + +static void write_all(int fd, const void *buf, size_t count) { + const char* cbuf = buf; + size_t written = 0; + while (written < count) { + int ret = write(fd, &cbuf[written], count - written); + if (ret == -1) { + err(EX_IOERR, "Could not write"); + } + written += ret; + } +} + +void reverse_file(const char* input_filename) { + int fd = open(input_filename, O_RDONLY); + if (fd == -1) { + err(EX_NOINPUT, "Could not open specified file"); + } + + struct stat stats; + if (fstat(fd, &stats) == -1) { + err(EX_NOINPUT, "Could not stat input"); + } + + long page_size = sysconf(_SC_PAGE_SIZE); + off_t pages = (stats.st_size - 1) / page_size + 1; + long map_size = pages * page_size; + char *m = mmap(NULL, map_size, PROT_READ, MAP_SHARED, fd, 0); + if (m == MAP_FAILED) { + err(EX_NOINPUT, "Could not mmap input"); + } + + char buf[BUFFER_SIZE]; + off_t buf_offset = 0; + for (off_t p = stats.st_size - 1; p >= 0; p--) { + buf[buf_offset++] = m[p]; + if (buf_offset >= BUFFER_SIZE) { + write_all(1, buf, buf_offset); + buf_offset = 0; + } + } + if (buf_offset) { + write_all(1, buf, buf_offset); + } + + if (munmap(m, map_size) == -1) { + err(EX_IOERR, "Could not unmap input"); + } + if (close(fd) == -1) { + err(EX_IOERR, "Could not close input"); + } +}