All pastes #565171 Raw Edit

Someone

public text v1 · immutable
·published 2007-06-13 22:09 UTC
rendered paste body
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

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;
}