#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
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 --;
}
}
Comments