/* brev - reverse bytes in a file ** ** Copyright (C) 1990 by Jef Poskanzer . ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. */ #include #include #include #define INITIAL_CHUNKSIZE 65536 void main( int argc, char** argv ) { struct stat sb; int i, r, chunksize, filesize; register char c; register char* cp1; register char* cp2; char* chunk; if ( argc == 2 ) { if ( freopen( argv[1], "r", stdin ) == NULL ) { perror( argv[1] ); exit( 1 ); } } else if ( argc != 1 ) { (void) fprintf( stderr, "%d\n", argc ); (void) fprintf( stderr, "usage: %s \n", argv[0] ); exit( 1 ); } chunksize = INITIAL_CHUNKSIZE; chunk = (char*) malloc( chunksize ); if ( chunk == (char*) 0 ) { (void) fprintf( stderr, "brev: out of memory\n" ); exit( 1 ); } if ( fstat( fileno(stdin), &sb ) == -1 ) { perror( "brev: fstat" ); exit( 1 ); } if ( ( sb.st_mode & S_IFMT ) == S_IFIFO ) { /* File is a pipe. Read in the whole thing. */ filesize = 0; for ( ; ; ) { r = fread( &chunk[filesize], 1, chunksize - filesize, stdin ); if ( r == 0 ) break; filesize += r; if ( filesize == chunksize ) { chunksize *= 2; chunk = (char*) realloc( chunk, chunksize ); if ( chunk == (char*) 0 ) { (void) fprintf( stderr, "brev: out of memory\n" ); exit( 1 ); } } } for ( cp1 = chunk, cp2 = &chunk[filesize - 1]; cp1 < cp2; ++cp1, --cp2 ) { c = *cp1; *cp1 = *cp2; *cp2 = c; } if ( fwrite( chunk, 1, filesize, stdout ) != filesize ) { perror( "brev: fwrite" ); exit( 1 ); } } else { /* Not a pipe. Use seeks and read it in a chunk at a time. */ filesize = sb.st_size; for ( i = filesize / chunksize * chunksize; i >= 0; i -= chunksize ) { if ( fseek( stdin, i, 0 ) == -1 ) { perror( "brev: fseek" ); exit( 1 ); } r = fread( chunk, 1, chunksize, stdin ); if ( r == 0 ) { perror( "brev: fread" ); exit( 1 ); } for ( cp1 = chunk, cp2 = &(chunk[r - 1]); cp1 < cp2; ++cp1, --cp2 ) { c = *cp1; *cp1 = *cp2; *cp2 = c; } if ( fwrite( chunk, 1, r, stdout ) != r ) { perror( "brev: fwrite" ); exit( 1 ); } } } (void) fclose( stdin ); (void) fclose( stdout ); exit( 0 ); }