2002-03-25 20:16:26 +00:00
/** \ingroup rpmbuild
* \ file build / reqprov . c
* Add dependency tags to package header ( s ) .
*/
# include "system.h"
# include "rpmbuild.h"
# include "debug.h"
2004-01-26 18:01:37 +00:00
typedef enum {
2004-01-27 12:45:26 +00:00
DEP_UN = 0 , /* uncomparable */
DEP_ST = 1 , /* stronger */
DEP_WK = - 1 , /* weaker */
DEP_EQ = 2 /* same */
2004-01-26 18:01:37 +00:00
} dep_compare_t ;
static dep_compare_t compare_sense_flags ( rpmTag tag , int cmp ,
rpmsenseFlags a , rpmsenseFlags b )
{
if ( cmp < 0 )
{
/* Aevr < Bevr */
switch ( tag )
{
case RPMTAG_REQUIREFLAGS :
if ( ( a = = 0 ) & & ( b ! = 0 ) )
2004-01-27 12:45:26 +00:00
return DEP_WK ;
2004-01-26 18:01:37 +00:00
if ( ! ( a & RPMSENSE_GREATER ) & & ( b & RPMSENSE_LESS ) )
2004-01-27 12:45:26 +00:00
return DEP_ST ;
2004-01-26 18:01:37 +00:00
if ( ! ( b & RPMSENSE_LESS ) & & ( a & RPMSENSE_GREATER ) )
2004-01-27 12:45:26 +00:00
return DEP_WK ;
return DEP_UN ;
2004-01-26 18:01:37 +00:00
case RPMTAG_PROVIDEFLAGS :
if ( ( a = = 0 ) & & ( b ! = 0 ) )
2004-01-27 12:45:26 +00:00
return DEP_WK ;
2004-01-26 18:01:37 +00:00
if ( ! ( b & RPMSENSE_LESS ) & & ( a & RPMSENSE_GREATER ) )
2004-01-27 12:45:26 +00:00
return DEP_ST ;
2004-01-26 18:01:37 +00:00
if ( ! ( a & RPMSENSE_GREATER ) & & ( b & RPMSENSE_LESS ) )
2004-01-27 12:45:26 +00:00
return DEP_WK ;
return DEP_UN ;
2004-01-26 18:01:37 +00:00
default :
if ( ( a = = 0 ) & & ( b ! = 0 ) )
2004-01-27 12:45:26 +00:00
return DEP_ST ;
2004-01-26 18:01:37 +00:00
if ( ! ( b & RPMSENSE_LESS ) & & ( a & RPMSENSE_GREATER ) )
2004-01-27 12:45:26 +00:00
return DEP_ST ;
2004-01-26 18:01:37 +00:00
if ( ! ( a & RPMSENSE_GREATER ) & & ( b & RPMSENSE_LESS ) )
2004-01-27 12:45:26 +00:00
return DEP_WK ;
return DEP_UN ;
2004-01-26 18:01:37 +00:00
}
} else if ( cmp > 0 )
{
/* Aevr > Bevr */
return - compare_sense_flags ( tag , - cmp , b , a ) ;
} else /* cmp == 0 */
{
/* Aevr == Bevr */
2004-01-27 12:45:26 +00:00
if ( a = = b )
return DEP_EQ ;
2004-01-26 18:01:37 +00:00
if ( ( a & b ) = = a )
2004-01-27 12:45:26 +00:00
return ( tag = = RPMTAG_REQUIREFLAGS ) ? DEP_ST : DEP_WK ;
2004-01-26 18:01:37 +00:00
if ( ( a & b ) = = b )
2004-01-27 12:45:26 +00:00
return ( tag = = RPMTAG_REQUIREFLAGS ) ? DEP_WK : DEP_ST ;
return DEP_UN ;
2004-01-26 18:01:37 +00:00
}
}
static dep_compare_t compare_deps ( rpmTag tag ,
const char * Aevr , rpmsenseFlags Aflags ,
const char * Bevr , rpmsenseFlags Bflags )
{
2004-01-27 12:45:26 +00:00
dep_compare_t rc = DEP_UN , cmp_rc ;
2004-01-26 18:01:37 +00:00
rpmsenseFlags Asense , Bsense ;
int sense ;
char * aEVR , * bEVR ;
const char * aE , * aV , * aR , * bE , * bV , * bR ;
2004-01-27 12:45:26 +00:00
/* 1. filter out noise */
Aflags & = ~ ( RPMSENSE_FIND_REQUIRES | RPMSENSE_FIND_PROVIDES ) ;
Bflags & = ~ ( RPMSENSE_FIND_REQUIRES | RPMSENSE_FIND_PROVIDES ) ;
/* 2. identical? */
if ( Aflags = = Bflags & & ! strcmp ( Aevr , Bevr ) )
return DEP_EQ ;
2004-01-26 18:01:37 +00:00
Asense = Aflags & RPMSENSE_SENSEMASK ;
Bsense = Bflags & RPMSENSE_SENSEMASK ;
2004-01-27 12:45:26 +00:00
/* 3. check for supported tags. */
2004-01-26 18:01:37 +00:00
switch ( tag ) {
case RPMTAG_PROVIDEFLAGS :
case RPMTAG_OBSOLETEFLAGS :
case RPMTAG_CONFLICTFLAGS :
case RPMTAG_REQUIREFLAGS :
break ;
default :
/* no way to optimize this case. */
2004-01-27 12:45:26 +00:00
return DEP_UN ;
2004-01-26 18:01:37 +00:00
}
2004-01-27 12:45:26 +00:00
/* 4. sanity checks */
2004-01-26 18:01:37 +00:00
if (
( ( Asense & RPMSENSE_LESS ) & & ( Asense & RPMSENSE_GREATER ) ) | |
( ( Bsense & RPMSENSE_LESS ) & & ( Bsense & RPMSENSE_GREATER ) ) | |
( ( Asense = = 0 ) ^ ( Aevr [ 0 ] = = 0 ) ) | |
( ( Bsense = = 0 ) ^ ( Bevr [ 0 ] = = 0 ) )
)
2004-01-27 12:45:26 +00:00
return DEP_UN ;
2004-01-26 18:01:37 +00:00
2004-01-27 12:45:26 +00:00
/* 5. filter out essentialy differ versions. */
2004-01-26 18:01:37 +00:00
if (
( ( Asense & RPMSENSE_LESS ) & & ( Bsense & RPMSENSE_GREATER ) ) | |
( ( Bsense & RPMSENSE_LESS ) & & ( Asense & RPMSENSE_GREATER ) )
)
2004-01-27 12:45:26 +00:00
return DEP_UN ;
2004-01-26 18:01:37 +00:00
2004-01-27 12:45:26 +00:00
/* 6. filter out essentialy differ flags. */
2004-01-26 18:01:37 +00:00
if ( ( Aflags & ~ RPMSENSE_SENSEMASK ) ! = ( Bflags & ~ RPMSENSE_SENSEMASK ) )
{
rpmsenseFlags Areq , Breq ;
2004-01-27 12:45:26 +00:00
/* 6a. additional check for REQUIREFLAGS */
2004-01-26 18:01:37 +00:00
if ( tag ! = RPMTAG_REQUIREFLAGS )
2004-01-27 12:45:26 +00:00
return DEP_UN ;
2004-01-26 18:01:37 +00:00
2004-01-27 12:45:26 +00:00
/* 6b. filter out essentialy differ requires. */
2004-01-26 18:01:37 +00:00
if ( ( Aflags & ~ RPMSENSE_SENSEMASK & ~ _ALL_REQUIRES_MASK ) ! =
( Bflags & ~ RPMSENSE_SENSEMASK & ~ _ALL_REQUIRES_MASK ) )
2004-01-27 12:45:26 +00:00
return DEP_UN ;
2004-01-26 18:01:37 +00:00
Areq = Aflags & _ALL_REQUIRES_MASK ;
Breq = Bflags & _ALL_REQUIRES_MASK ;
2004-01-27 12:45:26 +00:00
/* 6c. Aflags is legacy PreReq? */
if ( isLegacyPreReq ( Areq ) )
{
if ( Breq = = 0 )
rc = DEP_ST ;
else if ( ( Breq & RPMSENSE_SCRIPT_PRE ) = = RPMSENSE_SCRIPT_PRE & &
( Breq & RPMSENSE_SCRIPT_POSTUN ) = = RPMSENSE_SCRIPT_POSTUN )
rc = DEP_WK ;
else
return DEP_UN ;
}
2004-01-26 18:01:37 +00:00
2004-01-27 12:45:26 +00:00
/* 6d. Bflags is legacy PreReq? */
else if ( isLegacyPreReq ( Breq ) )
{
if ( Areq = = 0 )
rc = DEP_WK ;
else if ( ( Areq & RPMSENSE_SCRIPT_PRE ) = = RPMSENSE_SCRIPT_PRE & &
( Areq & RPMSENSE_SCRIPT_POSTUN ) = = RPMSENSE_SCRIPT_POSTUN )
rc = DEP_ST ;
else
return DEP_UN ;
}
/* 6e. Aflags contains Bflags? */
else if ( ( Areq & Breq ) = = Breq )
rc = DEP_ST ;
/* 6f. Bflags contains Aflags? */
2004-01-26 18:01:37 +00:00
else if ( ( Areq & Breq ) = = Areq )
2004-01-27 12:45:26 +00:00
rc = DEP_WK ;
2004-01-26 18:01:37 +00:00
else
2004-01-27 12:45:26 +00:00
return DEP_UN ;
2004-01-26 18:01:37 +00:00
}
2004-01-27 12:45:26 +00:00
/* 7. compare versions. */
2004-01-26 18:01:37 +00:00
aEVR = xstrdup ( Aevr ) ;
parseEVR ( aEVR , & aE , & aV , & aR ) ;
bEVR = xstrdup ( Bevr ) ;
parseEVR ( bEVR , & bE , & bV , & bR ) ;
sense = rpmEVRcmp ( aE , aV , aR , Aevr , bE , bV , bR , Bevr ) ;
aEVR = _free ( aEVR ) ;
bEVR = _free ( bEVR ) ;
2004-01-27 12:45:26 +00:00
/* 8. detect overlaps. */
2004-01-26 18:01:37 +00:00
cmp_rc = compare_sense_flags ( tag , sense , Asense , Bsense ) ;
2004-01-27 12:45:26 +00:00
/* 9. EVRs with serial are stronger. */
if ( cmp_rc = = DEP_EQ )
2004-01-26 18:01:37 +00:00
{
2004-01-27 12:45:26 +00:00
if ( ( aE & & * aE ) & & ! ( bE & & * bE ) )
cmp_rc = DEP_ST ;
else if ( ( bE & & * bE ) & & ! ( aE & & * aE ) )
cmp_rc = DEP_WK ;
2004-01-26 18:01:37 +00:00
}
2004-01-27 12:45:26 +00:00
#if 0
fprintf ( stderr , " D: compare_sense_flags=%d: tag=%d, sense=%d, Asense=%#x, Bsense=%#x \n " ,
cmp_rc , tag , sense , Asense , Bsense ) ;
# endif
if ( cmp_rc = = DEP_UN | | rc = = DEP_UN )
return cmp_rc ;
/* 10. compare expected with received. */
if ( cmp_rc ! = rc & & cmp_rc ! = DEP_EQ )
return DEP_UN ;
2004-01-26 18:01:37 +00:00
return rc ;
}
2002-03-25 20:16:26 +00:00
int addReqProv ( /*@unused@*/ Spec spec , Header h ,
rpmsenseFlags depFlags , const char * depName , const char * depEVR ,
int index )
{
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
HFD_t hfd = headerFreeData ;
const char * * names ;
rpmTagType dnt ;
rpmTag nametag = 0 ;
rpmTag versiontag = 0 ;
rpmTag flagtag = 0 ;
rpmTag indextag = 0 ;
int len ;
rpmsenseFlags extra = RPMSENSE_ANY ;
int xx ;
if ( depFlags & RPMSENSE_PROVIDES ) {
nametag = RPMTAG_PROVIDENAME ;
versiontag = RPMTAG_PROVIDEVERSION ;
flagtag = RPMTAG_PROVIDEFLAGS ;
extra = depFlags & RPMSENSE_FIND_PROVIDES ;
} else if ( depFlags & RPMSENSE_OBSOLETES ) {
nametag = RPMTAG_OBSOLETENAME ;
versiontag = RPMTAG_OBSOLETEVERSION ;
flagtag = RPMTAG_OBSOLETEFLAGS ;
} else if ( depFlags & RPMSENSE_CONFLICTS ) {
nametag = RPMTAG_CONFLICTNAME ;
versiontag = RPMTAG_CONFLICTVERSION ;
flagtag = RPMTAG_CONFLICTFLAGS ;
} else if ( depFlags & RPMSENSE_PREREQ ) {
nametag = RPMTAG_REQUIRENAME ;
versiontag = RPMTAG_REQUIREVERSION ;
flagtag = RPMTAG_REQUIREFLAGS ;
extra = depFlags & _ALL_REQUIRES_MASK ;
} else if ( depFlags & RPMSENSE_TRIGGER ) {
nametag = RPMTAG_TRIGGERNAME ;
versiontag = RPMTAG_TRIGGERVERSION ;
flagtag = RPMTAG_TRIGGERFLAGS ;
indextag = RPMTAG_TRIGGERINDEX ;
extra = depFlags & RPMSENSE_TRIGGER ;
} else {
nametag = RPMTAG_REQUIRENAME ;
versiontag = RPMTAG_REQUIREVERSION ;
flagtag = RPMTAG_REQUIREFLAGS ;
extra = depFlags & _ALL_REQUIRES_MASK ;
}
2004-01-27 12:45:26 +00:00
depFlags = ( depFlags & ( RPMSENSE_SENSEMASK ) ) | extra ;
2002-03-25 20:16:26 +00:00
/*@-branchstate@*/
if ( depEVR = = NULL )
depEVR = " " ;
/*@=branchstate@*/
/* Check for duplicate dependencies. */
2004-01-27 12:45:26 +00:00
if ( hge ( h , nametag , & dnt , ( void * * ) & names , & len ) & & len > 0 ) {
2002-03-25 20:16:26 +00:00
const char * * versions = NULL ;
rpmTagType dvt = RPM_STRING_ARRAY_TYPE ;
int * flags = NULL ;
int * indexes = NULL ;
2004-01-27 14:54:15 +00:00
int i , o_cnt = 0 , duplicate = 0 ;
char obsolete [ len ] ;
memset ( obsolete , 0 , sizeof obsolete ) ;
2002-03-25 20:16:26 +00:00
if ( flagtag ) {
xx = hge ( h , versiontag , & dvt , ( void * * ) & versions , NULL ) ;
xx = hge ( h , flagtag , NULL , ( void * * ) & flags , NULL ) ;
}
if ( indextag )
xx = hge ( h , indextag , NULL , ( void * * ) & indexes , NULL ) ;
2004-01-27 12:45:26 +00:00
for ( i = len - 1 ; i > = 0 ; - - i ) {
if ( indextag & & indexes & & indexes [ i ] ! = index )
2002-03-25 20:16:26 +00:00
continue ;
2004-01-24 19:05:04 +00:00
2004-01-27 12:45:26 +00:00
if ( strcmp ( names [ i ] , depName ) )
2002-03-25 20:16:26 +00:00
continue ;
2004-01-26 18:01:37 +00:00
if ( flagtag & & flags & & versions ) {
2004-01-27 12:45:26 +00:00
dep_compare_t rc = compare_deps ( flagtag , versions [ i ] , flags [ i ] , depEVR , depFlags ) ;
2004-01-24 19:05:04 +00:00
2004-01-26 18:01:37 +00:00
#if 0
2004-01-27 12:45:26 +00:00
fprintf ( stderr , " D: name=%s, compare_deps=%d: tag=%d, AEVR=%s, Aflags=%#x, BEVR=%s, Bflags=%#x \n " ,
depName , rc , flagtag , versions [ i ] , flags [ i ] , depEVR , depFlags ) ;
2004-01-26 18:01:37 +00:00
# endif
switch ( rc )
{
2004-01-27 12:45:26 +00:00
case DEP_EQ :
rpmMessage ( RPMMESS_DEBUG ,
" new dep %s already exists, optimized out \n " ,
depName ) ;
2004-01-26 18:01:37 +00:00
break ;
2004-01-27 12:45:26 +00:00
case DEP_ST :
rpmMessage ( RPMMESS_DEBUG ,
" new dep %s is weaker, optimized out \n " ,
depName ) ;
break ;
case DEP_WK :
2004-01-27 14:54:15 +00:00
+ + o_cnt ;
obsolete [ i ] = 1 ;
2004-01-26 18:01:37 +00:00
default :
continue ;
}
2004-01-24 19:05:04 +00:00
}
2002-03-25 20:16:26 +00:00
/* This is a duplicate dependency. */
duplicate = 1 ;
2004-01-27 14:54:15 +00:00
if ( o_cnt ) {
rpmMessage ( RPMMESS_WARNING , " %d obsolete deps left " , o_cnt ) ;
o_cnt = 0 ;
}
2002-03-25 20:16:26 +00:00
break ;
2004-01-27 14:54:15 +00:00
} /* end of main loop */
if ( o_cnt )
{
int new_len = len - o_cnt ;
const char * new_names [ new_len ] ;
const char * new_versions [ new_len ] ;
int new_flags [ new_len ] ;
int j ;
rpmMessage ( RPMMESS_DEBUG , " %d old deps to be optimized out \n " , o_cnt ) ;
for ( i = 0 , j = 0 ; i < len ; + + i )
{
char * p ;
if ( obsolete [ i ] )
{
rpmMessage ( RPMMESS_DEBUG ,
" old dep %s optimized out \n " , names [ i ] ) ;
continue ;
}
p = alloca ( 1 + strlen ( names [ i ] ) ) ;
strcpy ( p , names [ i ] ) ;
new_names [ j ] = p ;
p = alloca ( 1 + strlen ( versions [ i ] ) ) ;
strcpy ( p , versions [ i ] ) ;
new_versions [ j ] = p ;
new_flags [ j ] = flags [ i ] ;
+ + j ;
}
if ( ! headerModifyEntry ( h , nametag , RPM_STRING_ARRAY_TYPE , new_names , new_len ) | |
! headerModifyEntry ( h , versiontag , RPM_STRING_ARRAY_TYPE , new_versions , new_len ) | |
! headerModifyEntry ( h , flagtag , RPM_INT32_TYPE , new_flags , new_len ) )
rpmError ( RPMERR_BADHEADER , " addReqProv: error modifying entry for dep %s \n " , depName ) ;
rpmMessage ( RPMMESS_DEBUG , " %d old deps optimized out, %d left \n " , o_cnt , new_len ) ;
2002-03-25 20:16:26 +00:00
}
2004-01-27 14:54:15 +00:00
2002-03-25 20:16:26 +00:00
versions = hfd ( versions , dvt ) ;
2004-01-25 10:50:18 +00:00
names = hfd ( names , dnt ) ;
2002-03-25 20:16:26 +00:00
if ( duplicate )
return 0 ;
}
2004-01-24 23:31:06 +00:00
/* Do not add provided requires. */
if ( ( nametag = = RPMTAG_REQUIRENAME ) & &
( flagtag = = RPMTAG_REQUIREFLAGS ) & &
! ( depFlags & _notpre ( RPMSENSE_RPMLIB | RPMSENSE_KEYRING | RPMSENSE_SCRIPT_PRE | RPMSENSE_SCRIPT_POSTUN ) ) & &
! isLegacyPreReq ( depFlags ) & &
hge ( h , RPMTAG_PROVIDENAME , & dnt , ( void * * ) & names , & len ) ) {
int skip = 0 ;
int * flags = 0 ;
const char * * versions = 0 ;
rpmTagType dvt = RPM_STRING_ARRAY_TYPE ;
hge ( h , RPMTAG_PROVIDEVERSION , & dvt , ( void * * ) & versions , NULL ) ;
hge ( h , RPMTAG_PROVIDEFLAGS , NULL , ( void * * ) & flags , NULL ) ;
while ( flags & & versions & & ( len > 0 ) ) {
- - len ;
if ( strcmp ( depName , names [ len ] ) )
continue ;
if ( ! ( depFlags & RPMSENSE_SENSEMASK ) ) {
skip = 1 ;
break ;
}
if ( ! ( flags [ len ] & RPMSENSE_SENSEMASK ) )
continue ;
2004-01-25 22:26:23 +00:00
if ( rpmRangesOverlap ( " " , versions [ len ] , flags [ len ] , " " , depEVR , depFlags ) ) {
2004-01-27 14:54:15 +00:00
rpmMessage ( RPMMESS_DEBUG , " new dep %s already provided, optimized out \n " , depName ) ;
2004-01-24 23:31:06 +00:00
skip = 1 ;
break ;
}
}
versions = hfd ( versions , dvt ) ;
names = hfd ( names , dnt ) ;
if ( skip ) return 0 ;
}
2002-03-25 20:16:26 +00:00
/* Add this dependency. */
xx = headerAddOrAppendEntry ( h , nametag , RPM_STRING_ARRAY_TYPE , & depName , 1 ) ;
if ( flagtag ) {
xx = headerAddOrAppendEntry ( h , versiontag ,
RPM_STRING_ARRAY_TYPE , & depEVR , 1 ) ;
xx = headerAddOrAppendEntry ( h , flagtag ,
RPM_INT32_TYPE , & depFlags , 1 ) ;
}
if ( indextag )
xx = headerAddOrAppendEntry ( h , indextag , RPM_INT32_TYPE , & index , 1 ) ;
return 0 ;
}
int rpmlibNeedsFeature ( Header h , const char * feature , const char * featureEVR )
{
char * reqname = alloca ( sizeof ( " rpmlib() " ) + strlen ( feature ) ) ;
( void ) stpcpy ( stpcpy ( stpcpy ( reqname , " rpmlib( " ) , feature ) , " ) " ) ;
/* XXX 1st arg is unused */
return addReqProv ( NULL , h , RPMSENSE_RPMLIB | ( RPMSENSE_LESS | RPMSENSE_EQUAL ) ,
reqname , featureEVR , 0 ) ;
}