#include <radamsa.h>
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

size_t filesize(char* filename) {
    struct stat st;
    stat(filename, &st);
    return st.st_size;
}

#define BUFSIZE 1024*1024

void fail(char *why) {
   printf("fail: %s\n", why);
   exit(1);
}

void write_output(char *data, size_t len, int num) {
   char path[32];
   int fd;
   int wrote;
   sprintf(path, "tmp/lib-%d.fuzz", num); 
   fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
   printf("Opened %s -> %d\n", path, fd);
   if (fd < 0) {
      fail("failed to open output file");
   }
   wrote = write(fd, data, len);
   printf("wrote %d of %zu bytes\n", wrote, len);
   if (wrote != len) {
      fail("failed to write all of output at once");
   }
   close(fd);
   printf("Wrote %zu bytes to %s\n", len, path);
}

int main(int nargs, char **argv) {
   char *spath = argv[1];
   int fd = open(spath, O_RDONLY, 0);
   size_t len;
   char *input;
   char *output;
   int seed = 0;
   if (fd < 0) {
      fail("cannot open input file");
   }
   len = filesize(spath);
   input = malloc(len);
   output = malloc(BUFSIZE);
   if (!input || !output) {
      fail("failed to allocate buffers\n");
   }
   radamsa_init();
   if (len != read(fd, input, len)) {
      fail("failed to read the entire sample at once");
   }
   while(seed++ < 100) {
      size_t n;
      n = radamsa((uint8_t *) input, len, (uint8_t *) output, BUFSIZE, seed);
      write_output(output, n, seed);
      printf("Fuzzed %zu -> %zu bytes\n", len, n);
   }
   printf("library test passed\n");
   free(output);
   free(input);
   return 0;
}

