#include #include #include typedef long s32; typedef unsigned long u32; typedef s32 dword; typedef short s16; typedef unsigned short u16; typedef u16 word; typedef signed char s8; typedef unsigned char u8; typedef u8 byte; static const byte vpc_signature [] = { 'V', 'P', 'C', ' ', 176, 221, 128, 133 }; typedef enum { INVALID, ADD, REMOVE, EXTRACT, LIST, CREATE } VPCCommand; static void usage( void ) { fprintf( stdout, "Usage: vpc CONTAINER_FILE COMMAND [FILE]\n" ); } static VPCCommand fetch_cmd( char* arg ) { // Just check against every string: if( !strcmp( arg, "add" ) ) return ADD; if( !strcmp( arg, "remove" ) ) return REMOVE; if( !strcmp( arg, "extract" ) ) return EXTRACT; if( !strcmp( arg, "list" ) ) return LIST; if( !strcmp( arg, "create" ) ) return CREATE; return INVALID; } static int vpc_insert( FILE* cfile, char const* file ) { if( !cfile || !file ) return 0; FILE* datafile = fopen( file, "r" ); if( !datafile ) return 0; byte b; for( ; fread( &b, 1, 1, datafile ); fwrite( &b, 1, 1, cfile ) ); return 1; } static int vpc_validate_signature( FILE* file ) { if( !file ) return 0; unsigned char read_signature[ 8 ]; if( fread( read_signature, 8, 1, file ) != 1 ) { fprintf( stderr, "Input/Output error in signature validation\n" ); return 0; } for( u32 i = 0; i < 8; ++i ) if( vpc_signature[ i ] != read_signature[ i ] ) { fprintf( stderr, "Wrong signature\n" ); return 0; } return 1; } static int vpc_add( char const* container, char const* file ) { FILE* cfile = fopen( container, "r" ); if( !cfile ) { fprintf( stderr, "%s: No such file\n", container ); return 1; } if( !vpc_validate_signature( cfile ) ) return 1; unsigned int first = 0; if( fread( &first, 4, 1, cfile ) != 1 ) { fprintf( stderr, "Input/Output error\n" ); fclose( cfile ); return 1; } if( first == 0 ) { unsigned int pos; fgetpos( cfile, &pos ); pos = pos - 4; fsetpos( cfile, &pos ); first = 1; fwrite( &first, 4, 1, cfile ); return vpc_insert( cfile, file ); } return 0; } static int vpc_remove( char const* container, char const* file ) { return 0; } static int vpc_extract( char const* container, char const* file ) { return 0; } static int vpc_list( char const* container ) { return 0; } static int vpc_create( char const* container ) { FILE* cfile = fopen( container, "w" ); if( !cfile ) { fprintf( stderr, "%s: Failed to access\n", container ); return 1; } // Write signature: if( fwrite( vpc_signature, 8, 1, cfile ) != 1 ) { fprintf( stderr, "Input/Output error\n" ); fclose( cfile ); return 1; } // Write first field (0=empty): dword first = 0; if( fwrite( &first, sizeof( dword ), 1, cfile ) != 1 ) { fprintf( stderr, "Input/Output error\n" ); fclose( cfile ); return 1; } // Close and exit: fclose( cfile ); return 0; } int main( int argc, char** argv ) { // Number of arguments is fix: if( argc < 3 || argc > 4 ) { usage(); return 0; } // Read the command: VPCCommand command = fetch_cmd( argv[ 2 ] ); if( command == INVALID ) { usage(); return 0; } // Check number of parameters: if( ( command == ADD && argc != 4 ) || ( command == REMOVE && argc != 4 ) || ( command == EXTRACT && argc != 4 ) || ( command == LIST && argc != 3 ) || ( command == CREATE && argc != 3 ) ) { usage(); return 0; } // Do what told to do: if( command == ADD ) return vpc_add( argv[ 1 ], argv[ 3 ] ); if( command == REMOVE ) return vpc_remove( argv[ 1 ], argv[ 3 ] ); if( command == EXTRACT ) return vpc_extract( argv[ 1 ], argv[ 3 ] ); if( command == LIST ) return vpc_list( argv[ 1 ] ); if( command == CREATE ) return vpc_create( argv[ 1 ] ); return 0; }