
/* Corrupt is written by Tom 7 and is in the public domain. 
   Use or abuse as you please.
*/

#include "stdafx.h"
#include "stdlib.h"
#include "stdio.h"
#include "time.h"
#include "string.h"

/* MSVC++: ...? undefine for standard posix action... */
#define strdup _strdup
#define snprintf _snprintf

inline float crand() {
  return rand()/(float)RAND_MAX;
}

FILE * cp_fopen (char * file) {
  /* make a copy in a .# file and return a rw pointer into it. */
  FILE * old = fopen (file, "rb");
  char ff[1024];
  int i;

  if (!old) {
    printf("file not found: %s\n", file);
    exit(-1);
  }

  /* "clever" */

  char xt[] = {0,0};
  char * ext = &(xt[0]);

  char * fn = strdup (file);

  for(i=0;fn[i];i++) if (fn[i] == '.') { *ext = '.'; *(ext = &(fn[i])) = 0; }

  for (i=0;i<999;i++) {
    snprintf(ff, 1024, "%s.%d.%s", fn, i, ext + 1);
    FILE * test = fopen (ff, "rb");
    if (!test) break; /* got one */
    fclose(test);
  }
  
  FILE * nnn = fopen (ff, "wb");

  /* now copy... */

  while (EOF != (i = fgetc(old))) fputc(i, nnn);

  fseek(nnn,0,SEEK_SET);
  fclose(old);
  free (fn);
  return nnn;
}


int main(int argc, char* argv[]) {

  int len = 1;
  int pct = 100;
  int files = 0, bytes = 0;

  srand(time(0));

  if (argc < 2) {

    printf("usage: %s [-p n] [-l x] filename filename filename ...\n"
	   "\ncorrupts a file (new file is filename.#.ext)\n"
	   "corrupts n (default 100) out of 10,000 bytes,\n"
	   "each corruption site being x bytes (default 1) long.\n"
	   "\n\ndo not use this program unless you are stupid.\n",*argv);

  } else {

    for(int i=1;i<argc;i++) {
      if (*argv[i] == '-') {
	switch (argv[i][1]) {
	case 'p':
	case 'P':
	  if (!argv[++i]) { printf("expected n\n"); exit(-1); }
	  pct = atoi(argv[i]);
	  continue;
	case 'l':
	case 'L':
	  if (!argv[++i]) { printf("expected n\n"); exit(-1); }
	  len = atoi(argv[i]);
	  continue;
	default:
	  printf("unrecognized switch: %c\n", argv[i][1]);
	  exit(-1);

	}
      } else {
	/* found file */

	files++;
	FILE * f = cp_fopen (argv[i]);

	fseek(f, 0, SEEK_END);
	
	int flen = ftell(f);

	int sites = (int) ((flen + (10000 * crand())) * (pct / 10000.0) );

	while(sites--) {
	  int start = crand () * (flen-len);
	  fseek(f, start, SEEK_SET);
	  for(int x = 0;x < len; x++) {
	    fputc(rand()&0xFF, f);
	    bytes++;
	  }
	}

      }
    }

  }

  printf("corrupted %d bytes in %d files.\n", bytes, files);

  return 0;
}
