Here's the block and temporary file version. This one uses a 1MB block.
Code:
#include <stdio.h>
#include <stdlib.h>
#define BLOCK (1024 * 1024)
#define REVERSETMP "tmp_reverse"
int reverse_file(const char *filename);
void reverse_mem(unsigned char *mem, size_t size);
int main(int argc, char **argv)
{
if(argc < 2) {
fprintf(stderr, "Usage: reverse <file>\n");
return 1;
}
return reverse_file(argv[1]);
}
int reverse_file(const char *filename)
{
FILE *file;
FILE *temp;
int tempfd;
long size, offset;
unsigned char *buffer;
file = fopen(filename, "rb");
if(!file) {
return 1;
}
temp = fopen(REVERSETMP, "wb");
if(!temp) {
fclose(file);
return 1;
}
buffer = malloc(BLOCK);
if(!buffer) {
fclose(file);
fclose(temp);
return 1;
}
fseek(file, 0, SEEK_END);
size = ftell(file);
for(offset = size - BLOCK; offset >= 0; offset -= BLOCK) {
fseek(file, offset, SEEK_SET);
fread(buffer, 1, BLOCK, file);
if(ferror(file)) {
fclose(file);
fclose(temp);
free(buffer);
return 1;
}
reverse_mem(buffer, BLOCK);
fwrite(buffer, 1, BLOCK, temp);
if(ferror(temp)) {
fclose(file);
fclose(temp);
free(buffer);
return 1;
}
}
/** There may remain a bit of the file. */
if(offset < 0) {
offset += BLOCK;
rewind(file);
fread(buffer, 1, offset, file);
if(ferror(file)) {
fclose(file);
fclose(temp);
free(buffer);
return 1;
}
reverse_mem(buffer, offset);
fwrite(buffer, 1, offset, temp);
if(ferror(temp)) {
fclose(file);
fclose(temp);
free(buffer);
return 1;
}
}
fclose(file);
fclose(temp);
free(buffer);
unlink(filename);
rename(REVERSETMP, filename);
return 0;
}
void reverse_mem(unsigned char *mem, size_t size)
{
unsigned char *start = mem, *end = mem + size - 1;
unsigned char t;
for(; start < end; ++start, --end) {
t = *start;
*start = *end;
*end = t;
}
}
Takes less than 2 seconds for the 100MB file.