⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bdiff.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                    OutPatch( CMD_ITER_HOLES, patch_cmd );
                    OutPatch( curr->new_start, foff );
                    OutPatch( diff, hole );
                    OutPatch( iters, foff );
                    OutPatch( incr, foff );
                }
                first = 0;
                curr = end_iters - 1;
                curr_start = curr->new_start;
                curr_diff = 0;
                curr_header = curr;
            } else if( first || diff != curr_diff ) {
                if( write_holes ) {
                    if( !first ) {
                        OutPatch( 0, byte );
                    }
                    first = 0;
                    HoleHeaders++;
                    OutPatch( CMD_HOLES, patch_cmd );
                    OutPatch( curr->new_start, foff );
                    OutPatch( diff, hole );
                }
                curr_start = curr->new_start;
                curr_diff = diff;
                curr->size = sizeof( hole ) + sizeof( foff )
                           + sizeof( patch_cmd ) + sizeof( byte );
                curr_header = curr;
            } else {
                size = OutVar( curr->new_start - curr_start, write_holes );
                if( write_holes ) {
                    HoleCount[ size ]++;
                } else {
                    curr->size = size;
                    curr_header->dependants++;
                }
                curr_start = curr->new_start;
            }
        }
        if( write_holes ) OutPatch( 0, byte );
    }
}

void WriteSimilars( void )
{
    /* write similar regions out to the patch file */

    region      *curr;
    region      *junk;

    for( curr = SimilarRegions; curr != NULL; ) {
        OutPatch( CMD_SAMES, patch_cmd );
        OutPatch( curr->new_start, foff );
        OutPatch( curr->old_start, foff );
        OutPatch( curr->size, foff );
        junk = curr;
        curr = curr->next;
        _free( junk );
    }
}

void WriteDiffs( void )
{
    /* write difference regions out to the patch file */

    region      *curr;
    region      *junk;
    foff        curr_start;
    foff        size;

    for( curr = DiffRegions; curr != NULL; ) {
        curr_start = curr->new_start;
        size = curr->size;
        OutPatch( CMD_DIFFS, patch_cmd );
        OutPatch( curr_start, foff );
        OutPatch( size, foff );
        while( size != 0 ) {
            OutPatch( NewFile[ curr_start ], byte );
            --size;
            ++curr_start;
        }
        junk = curr;
        curr = curr->next;
        _free( junk );
    }
}


void AddLevel( char *name )
{
    memcpy( LevelBuff, LEVEL, sizeof( LEVEL ) );
    _splitpath( name, NULL, NULL, NULL, LevelBuff+LEVEL_HEAD_SIZE );
    memcpy( NewFile + EndNew, LevelBuff, sizeof( LEVEL ) );
}


void WriteLevel( void )
{
    char        *buff;
    int         size;

    OutPatch( CMD_DIFFS, patch_cmd );
    OutPatch( EndNew, foff );
    OutPatch( sizeof( LEVEL ), foff );
    size = sizeof( LEVEL );
    buff = LevelBuff;
    while( size != 0 ) {
        OutPatch( *buff, char );
        --size;
        ++buff;
    }
}

foff Sum( void )
{
    foff        sum;
    foff        i;
    foff        end;

    sum = 0;
    end = EndNew;
    if( AppendPatchLevel ) end += sizeof( LEVEL );
    for( i = 0; i != end; ++i ) {
        sum += NewFile[ i ];
    }
    return( sum );
}


void CopyComment( void )
{
    int         fd;
    foff        size;
    byte        *comment;

    if( CommentFile != NULL ) {
        fd = open( CommentFile, O_RDONLY | O_BINARY, 0 );
        FileCheck( fd, CommentFile );
        size = lseek( fd, 0, SEEK_END );
        SeekCheck( size, CommentFile );
        SeekCheck( lseek( fd, 0, SEEK_SET ), CommentFile );
        comment = _allocate( size+1 );
        NotNull( comment, "comment file" );
        if( read( fd, comment, size ) != size ) {
            FilePatchError( ERR_CANT_READ, CommentFile );
        }
        close( fd );
        comment[ size ] = '\0';
        OutStr( comment );
    }
}

void CheckPatch( int size )
{
    byte *oldpatch;

    if( CurrPatch - PatchFile + size >= PatchSize ) {
        oldpatch = PatchFile;
        PatchSize += 10*1024;
        PatchFile = _reallocate( PatchFile, PatchSize );
        NotNull( PatchFile, "patch file" );
        CurrPatch = PatchFile + ( CurrPatch - oldpatch );
    }
}

void WritePatchFile( char *name )
{

    foff        size;
    int         fd;

    PatchSize = EndNew;
    PatchFile = _allocate( PatchSize );
    NotNull( PatchFile, "patch file" );
    CurrPatch = PatchFile;

    if( AppendPatchLevel ) AddLevel( name );

    OutStr( SIGNATURE );
    CopyComment();

    OutPatch( EOF_CHAR, byte );
    OutStr( NewName );
    OutPatch( '\0', char );
    OutPatch( EndOld + OldCorrection, foff );
    size = EndNew;
    if( AppendPatchLevel ) size += sizeof( LEVEL );
    OutPatch( size, foff );
    OutPatch( Sum(), foff );

    WriteSimilars();
    WriteDiffs();
    if( AppendPatchLevel ) WriteLevel();
    ProcessHoleArray( 1 );

    OutPatch( CMD_DONE, byte );

    fd = open( name, O_BINARY+O_TRUNC+O_WRONLY+O_CREAT, 0 );
    FileCheck( fd, name );
    size = CurrPatch - PatchFile;
    if( write( fd, PatchFile, size ) != size ) {
        FilePatchError( ERR_CANT_WRITE, name );
    }
    close( fd );
}


void MakeHoleArray(void)
{
    region      *reg;
    region      *new_hole;
    region      *curr;

    if( NumHoles == 0 ) return;
    HoleArray = _allocate( sizeof( region ) * NumHoles );
    NotNull( HoleArray, "sorted holes" );
    new_hole = HoleArray;
    for( reg = HoleRegions; reg != NULL; ) {
        curr = reg;
        reg = reg->next;
        *new_hole = *curr;
        _free( curr );
        ++new_hole;
    }
    HoleRegions = reg;
}

void SortHoleArray( void )
{
    qsort( HoleArray, NumHoles, sizeof( region ), HoleCompare );
}


void FreeHoleArray( void )
{
    if( NumHoles != 0 ) {
        _free( HoleArray );
    }
}

algorithm ParseArgs( int argc, char **argv )
{
    char        **arg;
    char        *curr;
    algorithm   alg;

    NewName = NULL;
    if( argc < 4 ) {
        Usage( argv[0] );
    }
    arg = argv + 4;
    OldSymName = NULL;
    NewSymName = NULL;
    CommentFile = NULL;
    NewName = argv[1];
    Verbose = 0;
    AppendPatchLevel = 1;
    while( *arg ) {
        curr = *arg;
        if( *curr != '-' && *curr != '/' ) Usage( argv[0] );
        ++curr;
        switch( tolower( curr[0] ) ) {
        case 's':
            SyncString = strdup( curr+1 );
            break;
        case 'p':
            NewName = curr + 1;
            break;
        case 'c':
            CommentFile = curr + 1;
            break;
        case 'v':
            Verbose = 1;
            break;
        case 'l':
            AppendPatchLevel = 0;
            break;
        case 'd':
            if( tolower( curr[1] ) == 'o' ) {
                OldSymName = curr + 2;
                break;
            } else if( tolower( curr[1] ) == 'n' ) {
                NewSymName = curr + 2;
                break;
            }
            /* fall through */
        default:
            Usage( argv[0] );
            break;
        }
        ++arg;
    }
    alg = ALG_NOTHING;
#ifdef USE_DBGINFO
    if( NewSymName && access( NewSymName, ACCESS_RD ) != -1 ) {
        alg = ALG_ONLY_NEW;
        if( OldSymName && access( OldSymName, ACCESS_RD ) != -1 ) {
            alg = ALG_BOTH;
        }
    }
#endif
    return( alg );
}


foff FindSyncString( byte *file, foff end )
{
    foff        i;
    int         len;

    len = strlen( SyncString );
    end -= len;
    for( i = 0; i < end; ++i ) {
        if( file[i] != SyncString[0] ) continue;
        if( memcmp( SyncString, file+i, len ) != 0 ) continue;
        return( i );
    }
    return( -1 );
}

void ScanSyncString( void )
{
    if( SyncString == NULL ) return;
    SyncOld = FindSyncString( OldFile, EndOld );
    SyncNew = FindSyncString( NewFile, EndNew );
    if( SyncOld == (foff)-1 || SyncNew == (foff)-1 ) {
        fatal( ERR_NO_SYNCSTRING );
    }
    while( OldFile[SyncOld] == NewFile[SyncNew] ) {
        ++SyncOld; ++SyncNew;
        if( SyncOld == EndOld ) break;
        if( SyncNew == EndNew ) break;
    }
}


void main( int argc, char **argv )
{
    long savings;
    foff        buffsize;
    foff        best_from_new;
    algorithm   alg;

    if( !MsgInit() ) exit( EXIT_FAILURE );
    alg = ParseArgs( argc, argv );

    EndOld = FileSize( argv[1], &OldCorrection );
    EndNew = FileSize( argv[2], &NewCorrection );

    buffsize = ( EndOld > EndNew ) ? ( EndOld ) : ( EndNew );
    buffsize += sizeof( LEVEL );
    OldFile = ReadIn( argv[1], buffsize, EndOld );
    NewFile = ReadIn( argv[2], buffsize, EndNew );

    ScanSyncString();

    switch( alg ) {
    case ALG_NOTHING:
        FindRegions();
        break;
#ifdef USE_DBGINFO
    case ALG_ONLY_NEW:
    case ALG_BOTH:
        SymbolicDiff( alg, argv[1], argv[2] );
        break;
#endif
    }

    if( NumHoles == 0 && DiffSize == 0 && EndOld == EndNew ) {
        printf( "Patch file not created - files are identical\n" );
        MsgFini();
        exit( EXIT_SUCCESS );
    }
    MakeHoleArray();
    SortHoleArray();
    ProcessHoleArray( 0 );
    savings = HolesToDiffs();
    WritePatchFile( argv[3] );
    FreeHoleArray();
    VerifyCorrect( argv[2] );

    stats( "similar regions:    %8lu bytes (%lu chunks)\n",
            SimilarSize, NumSimilarities);
    stats( "different regions:  %8lu bytes (%lu chunks)\n",
            DiffSize, NumDiffs );
    stats( "hole->diff savings: %8lu bytes\n", savings );
    stats( "number of holes:    %8lu\n", NumHoles );
    stats( "(%lu headers + %lu single + %lu double + %lu triple)\n\n",
           HoleHeaders, HoleCount[0], HoleCount[1], HoleCount[2] );
    stats( "old file: %8lu bytes   new file: %8lu bytes\n", EndOld, EndNew );
    stats( "%lu%% of old executable referenced in patch file (largest amount is 100%%)\n",
           (SimilarSize*100) / EndOld );
    best_from_new = 0;
    if( EndNew > EndOld ) {
        best_from_new = EndNew - EndOld;
    }
    stats( "%lu%% of new executable output to patch file (least amount is %lu%%)\n",
           (DiffSize*100) / EndNew, (best_from_new*100) / EndNew );
    stats( "%lu total patch file size (%lu%%)\n", CurrPatch - PatchFile,
           ( ( CurrPatch - PatchFile ) * 100 ) / EndNew );

    MsgFini();
    exit( EXIT_SUCCESS );
}

/*
 * For debugging purposes only (In debugger issue "CALL DUMP" command)
 */

void dump( void )
{
    region *reg;

    printf( "        Similarities\n"
            "        ============\n" );
    printf( "O Offset  N Offset      Size\n" );
    for( reg = SimilarRegions; reg; reg = reg->next ) {
        printf( "%8lx  %8lx  %8lx\n",reg->old_start,reg->new_start,reg->size);
    }
    printf( "    Differences\n"
            "    ===========\n" );
    printf( "N Offset      Size\n" );
    for( reg = DiffRegions; reg; reg = reg->next ) {
        printf( "%8lx  %8lx\n",reg->new_start,reg->size);
    }
    printf( "           Holes\n"
            "           =====\n" );
    printf( "O Offset  N Offset  Difference\n" );
    for( reg = HoleRegions; reg; reg = reg->next ) {
        printf( "%8lx  %8lx  %8lx\n",reg->old_start,reg->new_start,reg->diff);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -