From: Scott Worley Date: Mon, 1 May 2017 08:20:54 +0000 (-0700) Subject: Reverse a file X-Git-Url: http://git.scottworley.com/overonion/commitdiff_plain/9571ed09bf5c97e104eae36ed323c2cd2d4c09b7 Reverse a file --- 9571ed09bf5c97e104eae36ed323c2cd2d4c09b7 diff --git a/reverse.c b/reverse.c new file mode 100644 index 0000000..ac55a10 --- /dev/null +++ b/reverse.c @@ -0,0 +1,70 @@ +#define _FILE_OFFSET_BITS 64 + +#define BUFFER_SIZE 4096 + +#include +#include +#include +#include +#include +#include +#include + +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; + } +} + + +int main(int argc, char** argv) { + if (argc != 2) { + errx(EX_USAGE, "Usage: reverse filename"); + } + + int fd = open(argv[1], 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"); + } + + return 0; +}