📄 bdiff.c
字号:
TestOld += size; \
TestNew += size;
/* check boundary conditions */
if( OldCurr < OldFile + backup_amt ) return( 0 );
if( NewCurr < NewFile + backup_amt ) return( 0 );
TestOld = OldCurr - backup_amt;
TestNew = NewCurr - backup_amt;
TestNew -= adjust;
if( TestOld < OldFile || TestOld >= OldCurr ) return( 0 );
if( TestNew < NewFile || TestNew >= NewCurr ) return( 0 );
if( TheSameIgnoringHoles() ) {
if( TestOld >= OldCurr ) return( 0 );
if( TestNew >= NewCurr ) return( 0 );
lastold = TestOld;
lastnew = TestNew;
/* Move forward as long as two files are similar */
for(;;) {
if( *TestOld == *TestNew ) {
lastold = TestOld;
lastnew = TestNew;
AddAndCheck( 1 );
continue;
}
if( TestOld[sizeof(hole)] == TestNew[sizeof(hole)] ) {
AddAndCheck( sizeof( hole ) );
continue;
}
if( TestOld[2*sizeof(hole)] == TestNew[2*sizeof(hole)] ) {
AddAndCheck( 2*sizeof( hole ) );
continue;
}
if( TestOld[3*sizeof(hole)] == TestNew[3*sizeof(hole)] ) {
AddAndCheck( 3*sizeof( hole ) );
continue;
}
break;
}
OldCurr = lastold;
NewCurr = lastnew;
return( 1 );
}
return( 0 );
}
static void CheckSyncPoint( void )
{
if( SyncOld == (foff)-1 ) return;
if( SaveOld >= OldFile+SyncOld && OldCurr < OldFile+SyncOld ||
SaveNew >= NewFile+SyncNew && NewCurr < NewFile+SyncNew ) {
OldCurr = OldFile+SyncOld;
NewCurr = NewFile+SyncNew;
stats( "\r\nJumped SyncPoint\r\n" );
}
}
int ReSync( void )
{
/* Try to resync the two file pointer by finding similar areas */
foff_diff i;
foff_diff backup;
char j;
char *spin = "-\\|/";
SaveOld = OldCurr; SaveNew = NewCurr;
j = 0;
for( backup = MIN_DIFF; backup <= MAX_DIFF; backup += backup ) {
if( backup > OldCurr-OldFile || backup > NewCurr-NewFile ) return( 0 );
stats( "\rResync %8.8lx:%8.8lx %c ", OldCurr-OldFile, NewCurr-NewFile, spin[j] );
++j; j &= 3;
for( i = 0; i <= backup; ++i ) {
if( AreasAreSimilar( i, backup ) ) {
CheckSyncPoint();
return( 1 );
}
}
for( i = -1; i >= -backup; --i ) {
if( AreasAreSimilar( i, backup ) ) {
CheckSyncPoint();
return( 1 );
}
}
}
return( 0 );
}
int TryBackingUp( int backup )
{
int i;
if( OldCurr-backup < OldFile ) return( 0 );
if( NewCurr-backup < NewFile ) return( 0 );
for( i = 0; ; ++i ) {
if( i == sizeof( hole ) ) {
return( 0 );
}
if( *(OldCurr-backup-i) == *(NewCurr-backup-i) ) break;
}
++OldCurr;
++NewCurr;
while( backup >= sizeof( hole ) ) {
OldCurr -= sizeof( hole );
NewCurr -= sizeof( hole );
AddHole( OldCurr - OldFile, NewCurr - NewFile );
backup -= sizeof( hole );
}
if( backup != 0 ) {
OldCurr -= backup;
NewCurr -= backup;
AddDiff( NewCurr - NewFile, backup );
}
return( 1 );
}
void FindRegions( void )
{
/*
* classify the differences between the two files into regions;
* similar, different, and hole
*/
byte *old_hi;
OldCurr = OldFile + EndOld + 1;
NewCurr = NewFile + EndNew + 1;
AddSimilarDiff( EndOld + 1, EndNew + 1, 0 );
OldCurr = OldFile + (EndOld-1);
NewCurr = NewFile + (EndNew-1);
old_hi = OldCurr;
for(;;) {
if( *OldCurr != *NewCurr ) {
if( !TryBackingUp(sizeof(hole))
&& !TryBackingUp(2*sizeof(hole))
&& !TryBackingUp(3*sizeof(hole)) ) {
++OldCurr;
++NewCurr;
AddSimilarDiff(OldCurr-OldFile, NewCurr-NewFile,
(old_hi-OldCurr)+1);
if( !ReSync() ) break;
stats( "%8.8lx:%8.8lx\n", OldCurr-OldFile, NewCurr-NewFile );
old_hi = OldCurr;
continue;
}
}
if( OldCurr == OldFile || NewCurr == NewFile ) {
AddSimilarDiff( OldCurr - OldFile,
NewCurr - NewFile, (old_hi-OldCurr) + 1 );
break;
}
--OldCurr;
--NewCurr;
}
OldCurr = OldFile;
NewCurr = NewFile;
if( SimilarRegions->new_start != 0 ) {
AddSimilarDiff( 0, 0, 0 );
}
putchar( '\n' );
}
/***************************************************************
Routines that use debugging information to guide the analysis
***************************************************************/
void printd( char *p )
{
int i;
for( i = *(p++); i != 0; --i ) {
stats( "%c", *(p++) );
}
}
void fatal( int p )
{
char msgbuf[80];
GetMsg( msgbuf, p );
puts( msgbuf );
MsgFini();
exit( EXIT_FAILURE );
}
void IOError( char *file )
{
char msgbuf[80];
GetMsg( msgbuf, MSG_IO_ERROR );
printf( msgbuf, file );
MsgFini();
exit( EXIT_FAILURE );
}
void xseek( int fd, fpos_t pos, int how )
{
if( lseek( fd, pos, how ) < 0 ) {
fatal( MSG_IO_ERR );
}
}
void xread( int fd, void *p, size_t size )
{
if( read( fd, p, size ) != size ) {
fatal( MSG_IO_ERR );
}
}
int cmp_blk( exe_blk *b1, exe_blk *b2 )
{
if( b1->start == b2->start ) {
return( 0 );
} else if( b1->start < b2->start ) {
return( -1 );
}
return( 1 );
}
int cmp_mod_offset( exe_mod *m1, exe_mod *m2 )
{
if( m1->mod_offset == m2->mod_offset ) {
return( 0 );
} else if( m1->mod_offset < m2->mod_offset ) {
return( -1 );
}
return( 1 );
}
int cmp_mod_name( exe_mod *m1, exe_mod *m2 )
{
int comp;
if( m1->name[0] == m2->name[0] ) {
return( memcmp( &(m1->name[1]), &(m2->name[1]), m2->name[0] ) );
} else if( m1->name[0] < m2->name[0] ) {
comp = memcmp( &(m1->name[1]), &(m2->name[1]), m1->name[0] );
if( comp == 0 ) {
comp = -1;
}
} else {
comp = memcmp( &(m1->name[1]), &(m2->name[1]), m2->name[0] );
if( comp == 0 ) {
comp = 1;
}
}
return( comp );
}
int TestBlock( foff old_off, foff new_off, foff len )
{
byte *pold;
byte *pnew;
byte *o;
byte *n;
byte *old_stop;
byte *new_stop;
foff matches;
foff holes;
pold = &OldFile[ old_off ];
pnew = &NewFile[ new_off ];
matches = 0;
holes = 0;
o = pold;
n = pnew;
old_stop = &pold[ len ];
new_stop = &pnew[ len ];
for(;;) {
if( o >= old_stop || n >= new_stop ) break;
if( *o == *n ) {
++o;
++n;
++matches;
continue;
}
o += sizeof( hole );
n += sizeof( hole );
if( o >= old_stop || n >= new_stop ) break;
if( *o == *n ) {
++holes;
}
}
if( matches + holes * sizeof( hole ) > len / 2 ) {
AddSimilar( old_off, new_off, len );
o = pold;
n = pnew;
for(;;) {
if( o >= old_stop || n >= new_stop ) break;
if( *o == *n ) {
++o;
++n;
continue;
}
o += sizeof( hole );
n += sizeof( hole );
if( o >= old_stop || n >= new_stop ) {
n -= sizeof( hole );
AddDiff( n - NewFile, new_stop - n );
break;
}
AddHole( (o-sizeof(hole)) - OldFile, (n-sizeof(hole)) - NewFile );
}
return( 1 );
}
return( 0 );
}
int FindBlockInOld( foff new_off, foff len )
{
byte *pold;
byte *pnew;
byte *o;
byte *n;
byte *old_stop;
byte *new_stop;
pnew = &NewFile[ new_off ];
new_stop = &pnew[ len ];
pold = &OldFile[ 0 ];
old_stop = &OldFile[ EndOld ];
for(;;) {
if( pold >= old_stop ) break;
o = memchr( pold, *pnew, old_stop - pold );
if( o == NULL ) break;
pold = o + 1;
n = pnew;
for(;;) {
if( o >= old_stop || n >= new_stop ) {
if( TestBlock( ( pold - 1 ) - OldFile, new_off, len ) ) {
return( 1 );
}
break;
}
if( *o == *n ) {
++o;
++n;
continue;
}
o += sizeof( hole );
n += sizeof( hole );
if( o >= old_stop || n >= new_stop ) {
if( TestBlock( ( pold - 1 ) - OldFile, new_off, len ) ) {
return( 1 );
}
break;
}
if( *o != *n ) break;
}
}
AddDiff( new_off, len );
return( 0 );
}
#ifdef USE_DBGINFO
int both_walker( exe_blk *new_blk, void *parm )
{
fpos_t len;
walker_data *last;
exe_blk *old_blk;
exe_mod *old_mod;
exe_mod *new_mod;
auto exe_mod tmp_mod;
last = parm;
tmp_mod.mod_offset = new_blk->mod_offset;
new_mod = SymFind( new.mods_by_offset, &tmp_mod );
if( new_mod == NULL ) {
fatal( MSG_DEBUG_INFO );
}
if( last->last_offset != new_blk->start ) {
len = new_blk->start - last->last_offset;
stats( "[%lx-%lx) ???",last->last_offset, last->last_offset + len );
if( FindBlockInOld( last->last_offset, len ) ) {
stats( "\n" );
} else {
stats( " (NOT found)\n" );
}
}
last->last_offset = new_blk->start + new_blk->length;
stats( "[%lx-%lx) ", new_blk->start, last->last_offset );
printd( new_mod->name );
if( new_blk->start >= EndNew ) {
stats( " (BSS block ignored)\n" );
return( 0 );
}
old_mod = SymFind( old.mods_by_name, new_mod );
if( old_mod == NULL ) {
stats( " (NOT found)\n" );
AddDiff( new_blk->start, new_blk->length );
return( 0 );
}
/* find an exact match in length if possible */
for( old_blk = old_mod->blocks; old_blk; old_blk = old_blk->next ) {
if( old_blk->length == -1 ) {
continue;
}
if( old_blk->length == new_blk->length ) {
if( TestBlock( old_blk->start, new_blk->start, old_blk->length ) ) {
old_blk->length = -1; /* don't test this one again */
stats( "\n" );
return( 0 );
}
}
}
for( old_blk = old_mod->blocks; old_blk; old_blk = old_blk->next ) {
if( old_blk->length == -1 || old_blk->length == new_blk->length ) {
continue;
}
if( old_blk->length > new_blk->length ) {
if( TestBlock( old_blk->start, new_blk->start, new_blk->length ) ) {
AddDiff( new_blk->start + new_blk->length,
old_blk->length - new_blk->length );
old_blk->length = -1; /* don't test this one again */
stats( "\n" );
return( 0 );
}
} else { /* old_blk->length < new_blk->length */
if( TestBlock( old_blk->start, new_blk->start, old_blk->length ) ) {
AddDiff( new_blk->start + old_blk->length,
new_blk->length - old_blk->length );
old_blk->length = -1; /* don't test this one again */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -