📄 bdiff.c
字号:
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 + -