]> git.scottworley.com Git - overonion/blobdiff - reverse_lib.c
Accept streams as input. Use a temp file
[overonion] / reverse_lib.c
index 46563562f3b3833d44a67b0809e5887c2abb949e..20837ee5f65fe95b237436b0d1685fd2d497a69d 100644 (file)
@@ -1,8 +1,10 @@
+#define _GNU_SOURCE
 #define _FILE_OFFSET_BITS 64
 
 #include <err.h>
 #include <fcntl.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -29,3 +31,47 @@ void reverse_file(const char* input_filename, FILE* output_stream) {
   if (munmap(m, map_size) == -1) err(EX_IOERR, "Could not unmap input");
   if (close(fd) == -1) err(EX_IOERR, "Could not close input");
 }
+
+/* Create a temporary file in $TMPDIR, or /tmp if TMPDIR is not set.
+ * Caller must free temp_filename and fclose temp_file.  Succeeds or terminates
+ * the process. */
+static void make_temporary_file(char** temp_filename, FILE** temp_file) {
+  char* TMPDIR = getenv("TMPDIR");
+  if (TMPDIR == NULL) {
+    TMPDIR = "/tmp";
+  }
+  if (asprintf(temp_filename, "%s/reverse.XXXXXX", TMPDIR) == -1) {
+    errx(EX_OSERR, "Could not assemble temporary filename");
+  }
+  int fd = mkstemp(*temp_filename);
+  if (fd == -1) err(EX_IOERR, "Could not make a temporary file");
+  *temp_file = fdopen(fd, "w");
+  if (*temp_file == NULL) err(EX_IOERR, "Could not open temporary file");
+}
+
+/* Copy data from input to output until EOF is reached. */
+static void copy(FILE* input, FILE* output) {
+  for (;;) {
+    int c = fgetc(input);
+    if (c == EOF) {
+      if (ferror(input)) errx(EX_IOERR, "Could not read");
+      if (!feof(input)) errx(EX_IOERR, "Unexpected end of file");
+      break;
+    }
+    if (fputc(c, output) == EOF) errx(EX_IOERR, "Could not write");
+  }
+}
+
+void reverse_stream(FILE* input_stream, FILE* output_stream) {
+  char* temp_filename;
+  FILE* temp_file;
+  make_temporary_file(&temp_filename, &temp_file);
+
+  copy(input_stream, temp_file);
+  if (fclose(temp_file) != 0) err(EX_IOERR, "Could not close temporary file");
+
+  reverse_file(temp_filename, output_stream);
+
+  if (unlink(temp_filename) == -1) err(EX_IOERR, "Could not remove temporary file");
+  free(temp_filename);
+}