#include #include #include #include void compute_xor(FILE *, FILE **, unsigned); inline void xor(void *, const void *, unsigned); int main (int argc, char ** argv) { if (argc < 3) { fprintf(stderr, "usage: %s outfile infile1 [infile2 [infile3 [... ]]]\n", *argv); return 1; } FILE ** infiles = malloc(sizeof(FILE *) * (argc - 2)); int fileno; for (fileno = 0; fileno < (argc - 2); fileno ++) { infiles[fileno] = fopen(argv[fileno + 2], "rb"); if (!infiles[fileno]) { fprintf(stderr, "%s: could not open file %s for reading\n", *argv, argv[fileno + 2]); for (fileno --; fileno >= 0; fileno --) fclose(infiles[fileno]); return 2; } } FILE * outfile = fopen(argv[1], "wb"); if (!outfile) { fprintf(stderr, "%s: could not open file %s for writing\n", *argv, argv[1]); for (fileno --; fileno >= 0; fileno --) fclose(infiles[fileno]); return 2; } compute_xor(outfile, infiles, fileno); free(infiles); return 0; } void compute_xor (FILE * out, FILE ** in, unsigned count) { unsigned buffer_size = 2 << 20; char * buffer = NULL; while (!buffer) { buffer = malloc(buffer_size); buffer_size >>= 1; if (!buffer_size) abort(); } unsigned last_read, current_file; int rv; while (1) { memset(buffer, 0, buffer_size); last_read = 0; for (current_file = 0; current_file < count; current_file ++) { if (!in[current_file]) continue; rv = fread(buffer + buffer_size, 1, buffer_size, in[current_file]); if (rv < buffer_size) { fclose(in[current_file]); in[current_file] = NULL; } if (rv) xor(buffer, buffer + buffer_size, rv); if (rv > last_read) last_read = rv; } if (!last_read) break; fwrite(buffer, 1, last_read, out); } fclose(out); free(buffer); } inline void xor (void * destination, const void * source, unsigned length) { uint_fast8_t * dstfast = destination; const uint_fast8_t * srcfast = source; while (length > sizeof(uint_fast8_t)) { *(dstfast ++) ^= *(srcfast ++); length -= sizeof(uint_fast8_t); } unsigned char * dstbyte = (unsigned char *) dstfast; const unsigned char * srcbyte = (const unsigned char *) srcfast; while (length) { *(dstbyte ++) ^= *(srcbyte ++); length --; } }