Paste: reverse a file
Author: | crest |
Mode: | c |
Date: | Wed, 16 Dec 2009 15:18:07 |
Plain Text |
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h> // Only BSD derivates define these (including Solaris as tested on pierre)
#include <sys/mman.h>
#include <sys/stat.h>
#define OUTPUT_BUFFER_SIZE 8192
const char usage[] = "Usage: kopfstand [<source>] [<target>]\n"
" <source> or <target> may be \"-\n for stdin or stdout\n";
const char failed_to_open_input[] = "Failed to open input";
const char failed_to_stat_input[] = "Failed to stat input";
const char failed_to_mmap_input[] = "Failed to mmap input";
const char failed_to_unmap_input[] = "Failed to unmap input";
const char failed_to_open_output[] = "Failed to open output";
const char failed_to_write_output[] = "Failed to write output";
#ifndef EX_USAGE
#define EX_USAGE EXIT_FAILURE
#define EX_NOINPUT EXIT_FAILURE
#define EX_IOERR EXIT_FAILURE
#endif
#define EVER 23
int main
(
int argc,
const char ** argv
) {
int input_fd;
int output_fd;
ssize_t output_index;
uint8_t output_buffer[OUTPUT_BUFFER_SIZE];
uintptr_t input_index;
struct stat input_stat;
off_t input_size;
if ( argc > 3 )
{
fputs( usage, stderr );
return EX_USAGE;
}
if ( argc > 1 && strcmp( "-", argv[1] ) )
{
close( 0 );
input_fd = open( argv[1], O_RDONLY );
if ( input_fd == -1 )
{
perror( failed_to_open_input );
return EX_NOINPUT;
}
assert( input_fd == 0 );
}
else
{
input_fd = 0;
}
if ( fstat( input_fd, &input_stat ) )
{
perror( failed_to_stat_input );
return EX_IOERR;
}
input_size = input_stat.st_size;
assert( input_size >= 0 );
uint8_t * input_map = mmap( NULL, input_size, PROT_READ, MAP_PRIVATE, input_fd, 0 );
if ( (intptr_t)input_map == -1 )
{
perror( failed_to_mmap_input );
return EX_IOERR;
}
if ( argc > 2 && strcmp( "-", argv[2] ) )
{
close( 1 );
output_fd = open( argv[2], O_CREAT | O_WRONLY | O_TRUNC );
if ( input_fd == -1 ) {
perror( failed_to_open_output );
if ( munmap( input_map, input_size ) )
{
perror( failed_to_unmap_input );
}
}
assert( output_fd == 1 );
}
else
{
output_fd = 1;
}
for ( input_index = input_size; input_index ; )
{
ssize_t delta, written = 0;
for ( output_index = 0; output_index < sizeof(output_buffer) && input_index; )
output_buffer[output_index++] = input_map[--input_index];
do {
delta = write( output_fd, output_buffer, output_index );
if ( delta < 0 )
{
perror( failed_to_write_output );
if ( munmap( output_buffer, input_size ) )
{
perror( failed_to_unmap_input );
}
return EX_IOERR;
}
written += delta;
} while ( output_index != written );
}
return EXIT_SUCCESS;
}
New Annotation