2011-01-10 13:02:49 +03:00
/*
* interdep . c - inter - package analysis and optimizations based on
* strict dependencies between subpackages ( Requires : N = [ E : ] V - R ) .
*
* Written by Alexey Tourbin < at @ altlinux . org > .
* License : GPLv2 + .
*/
# include "system.h"
2011-01-14 07:06:46 +03:00
# include "psm.h" // TFI_t
2011-01-10 13:02:49 +03:00
# include "rpmbuild.h"
# include "interdep.h"
2011-01-14 07:06:46 +03:00
static
const char * pkgName ( Package pkg )
{
TFI_t fi = pkg - > cpioList ;
if ( fi )
return fi - > name ;
const char * name ;
headerNVR ( pkg - > header , & name , NULL , NULL ) ;
return name ;
}
2011-01-10 13:02:49 +03:00
static
const char * skipPrefixDash ( const char * str , const char * prefix )
{
int len = strlen ( prefix ) ;
if ( strncmp ( str , prefix , len ) )
return NULL ;
if ( str [ len ] ! = ' - ' )
return NULL ;
return str + len + 1 ;
}
struct Req {
int c ;
struct Pair {
Package pkg1 ;
Package pkg2 ;
} * v ;
} ;
static
int Requires ( struct Req * r , Package pkg1 , Package pkg2 )
{
int i ;
for ( i = 0 ; i < r - > c ; i + + )
if ( pkg1 = = r - > v [ i ] . pkg1 & & pkg2 = = r - > v [ i ] . pkg2 )
return 1 ;
return 0 ;
}
static
2013-01-25 05:31:40 +04:00
int addRequires ( struct Req * r , Package pkg1 , Package pkg2 )
2011-01-10 13:02:49 +03:00
{
2011-02-03 23:10:49 +03:00
if ( pkg1 = = pkg2 )
2013-01-25 05:31:40 +04:00
return 0 ;
2011-01-10 13:02:49 +03:00
if ( Requires ( r , pkg1 , pkg2 ) )
2013-01-25 05:31:40 +04:00
return 0 ;
2011-01-10 13:02:49 +03:00
AUTO_REALLOC ( r - > v , r - > c , 8 ) ;
r - > v [ r - > c + + ] = ( struct Pair ) { pkg1 , pkg2 } ;
2013-01-25 05:31:40 +04:00
return 1 ;
2011-01-10 13:02:49 +03:00
}
2013-01-25 09:00:10 +04:00
static void
propagateRequires ( struct Req * r )
{
unsigned propagated ;
do {
propagated = 0 ;
int i1 , i2 ;
for ( i1 = 0 ; i1 < r - > c ; i1 + + )
for ( i2 = i1 ; i2 < r - > c ; i2 + + ) {
struct Pair r1 = r - > v [ i1 ] ;
struct Pair r2 = r - > v [ i2 ] ;
if ( r1 . pkg2 = = r2 . pkg1 & & addRequires ( r , r1 . pkg1 , r2 . pkg2 ) )
propagated = 1 ;
if ( r2 . pkg2 = = r1 . pkg1 & & addRequires ( r , r2 . pkg1 , r1 . pkg2 ) )
propagated = 1 ;
}
}
while ( propagated ) ;
}
static void
addDeps1 ( struct Req * r , Package pkg1 , Package pkg2 )
{
if ( Requires ( r , pkg1 , pkg2 ) )
return ;
const char * name = pkgName ( pkg2 ) ;
const char * evr = headerSprintf ( pkg2 - > header ,
" %|epoch?{%{epoch}:}|%{version}-%{release} " ,
rpmTagTable , rpmHeaderFormats , NULL ) ;
assert ( evr ) ;
int flags = RPMSENSE_EQUAL | RPMSENSE_FIND_REQUIRES ;
int added = ! addReqProv ( NULL , pkg1 - > header , flags , name , evr , 0 ) ;
if ( added ) {
addRequires ( r , pkg1 , pkg2 ) ;
propagateRequires ( r ) ;
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL , " Adding to %s a strict dependency on %s \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2013-01-25 09:00:10 +04:00
}
evr = _free ( evr ) ;
}
2011-01-10 13:02:49 +03:00
static
2013-01-25 09:00:10 +04:00
void makeReq1 ( struct Req * r , Package pkg1 , Package pkg2 , int warn )
2011-01-10 13:02:49 +03:00
{
int c = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
int ok =
hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & c ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv , NULL ) ;
if ( ! ok )
return ;
const char * provN , * provV , * provR ;
headerNVR ( pkg2 - > header , & provN , & provV , & provR ) ;
int i ;
for ( i = 0 ; i < c ; i + + ) {
if ( strcmp ( reqNv [ i ] , provN ) )
continue ;
if ( ( reqFv [ i ] & RPMSENSE_SENSEMASK ) ! = RPMSENSE_EQUAL )
continue ;
const char * reqVR = reqVv [ i ] ;
if ( * reqVR = = ' \0 ' )
continue ;
2011-02-08 05:21:38 +03:00
const char * colon = NULL ;
2011-01-10 13:02:49 +03:00
const char * reqR = skipPrefixDash ( reqVR , provV ) ;
2011-02-08 05:21:38 +03:00
if ( reqR = = NULL & & xisdigit ( * reqVR ) ) {
colon = strchr ( reqVR , ' : ' ) ;
2011-01-10 13:02:49 +03:00
if ( colon )
reqR = skipPrefixDash ( colon + 1 , provV ) ;
}
if ( reqR = = NULL )
continue ;
if ( strcmp ( reqR , provR ) )
continue ;
2013-01-24 11:04:14 +04:00
if ( warn & & colon = = NULL & & headerIsEntry ( pkg2 - > header , RPMTAG_EPOCH ) ) {
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_WARNING , " %s: dependency on %s needs Epoch \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2013-01-25 09:00:10 +04:00
addDeps1 ( r , pkg1 , pkg2 ) ;
} else {
addRequires ( r , pkg1 , pkg2 ) ;
2013-01-24 11:04:14 +04:00
}
2011-01-10 13:02:49 +03:00
break ;
}
const HFD_t hfd = ( HFD_t ) headerFreeData ;
reqNv = hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
}
2011-02-08 06:57:03 +03:00
# include "al.h"
// check if pkg1 has (possibly non-strict) dependency on pkg2
static
int depRequires ( Package pkg1 , Package pkg2 )
{
2013-01-25 09:00:10 +04:00
if ( pkg1 = = pkg2 )
return 0 ;
2011-02-08 06:57:03 +03:00
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
int ok =
hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv , NULL ) ;
if ( ! ok )
return 0 ;
2013-01-25 09:00:10 +04:00
struct availableList_s proval ;
alCreate ( & proval ) ;
alAddPackage ( & proval , pkg2 - > header , NULL , NULL , NULL ) ;
2011-02-08 06:57:03 +03:00
int i ;
struct availablePackage * ap = NULL ;
for ( i = 0 ; i < reqc ; i + + ) {
2013-01-25 09:00:10 +04:00
ap = alSatisfiesDepend ( & proval , reqNv [ i ] , reqVv [ i ] , reqFv [ i ] ) ;
2011-02-08 06:57:03 +03:00
if ( ap )
break ;
}
const HFD_t hfd = ( HFD_t ) headerFreeData ;
reqNv = hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
2013-01-25 09:00:10 +04:00
alFree ( & proval ) ;
2011-02-08 06:57:03 +03:00
return ap ? 1 : 0 ;
}
2013-01-25 09:00:10 +04:00
static
struct Req * freeRequires ( struct Req * r )
2013-01-24 06:42:31 +04:00
{
2013-01-25 09:00:10 +04:00
r - > v = _free ( r - > v ) ;
return _free ( r ) ;
2013-01-24 06:42:31 +04:00
}
2013-01-25 09:00:10 +04:00
/*
* For every subpackage pkg2 in the set , pkg1 will get a strict dep
2013-01-27 00:09:15 +04:00
* on pkg2 if at least one of these conditions is met :
* - pkg1 has a RPMSENSE_FIND_REQUIRES dep on pkg2 ;
* - pkg1 has a manual dep on pkg2 and
* this dep has no ~ RPMSENSE_EQUAL sense flags ;
2013-01-25 09:00:10 +04:00
* - pkg1 has a RPMSENSE_FIND_REQUIRES dep on X , and
2013-01-27 00:09:15 +04:00
* pkg2 is the only subpackage in the set that satisfies X .
2013-01-25 09:00:10 +04:00
*/
2013-01-24 06:42:31 +04:00
static void
2013-01-25 09:00:10 +04:00
fix_weak_deps ( struct Req * r , Package pkg1 , Package packages )
2013-01-24 06:42:31 +04:00
{
2013-01-25 09:00:10 +04:00
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
int ok =
hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv , NULL ) ;
if ( ! ok )
return ;
int i ;
Package pkg2 ;
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next )
; ;
Package * provs = xcalloc ( i , sizeof ( * provs ) ) ;
availableList proval = xcalloc ( i , sizeof ( * proval ) ) ;
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList ) {
2013-01-25 09:00:10 +04:00
alCreate ( & proval [ i ] ) ;
alAddPackage ( & proval [ i ] , pkg2 - > header , NULL , NULL , NULL ) ;
}
}
for ( i = 0 ; i < reqc ; + + i ) {
2013-01-27 00:09:15 +04:00
if ( reqFv [ i ] & RPMSENSE_SENSEMASK & ~ RPMSENSE_EQUAL & &
! ( reqFv [ i ] & RPMSENSE_FIND_REQUIRES ) )
continue ;
int j ;
for ( j = 0 , pkg2 = packages ; pkg2 ; + + j , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList & & ! strcmp ( reqNv [ i ] , pkgName ( pkg2 ) ) ) {
2013-01-27 00:09:15 +04:00
provs [ j ] = pkg2 ;
break ;
}
}
int k ;
2013-01-25 09:00:10 +04:00
Package prov = NULL ;
for ( j = 0 , pkg2 = packages ; pkg2 ; + + j , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList ) {
2013-01-25 09:00:10 +04:00
if ( alSatisfiesDepend ( & proval [ j ] , reqNv [ i ] , reqVv [ i ] , reqFv [ i ] ) ) {
if ( prov ) {
prov = NULL ;
break ;
}
prov = pkg2 ;
k = j ;
}
}
}
2013-01-27 00:09:15 +04:00
if ( prov & & reqFv [ i ] & RPMSENSE_FIND_REQUIRES )
provs [ k ] = prov ;
2013-01-25 09:00:10 +04:00
}
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next ) {
2013-04-03 05:06:36 +04:00
if ( pkg1 ! = pkg2 & & pkg2 - > cpioList )
2013-01-25 09:00:10 +04:00
alFree ( & proval [ i ] ) ;
}
proval = _free ( proval ) ;
const HFD_t hfd = ( HFD_t ) headerFreeData ;
reqNv = hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
for ( i = 0 , pkg2 = packages ; pkg2 ; + + i , pkg2 = pkg2 - > next ) {
if ( provs [ i ] )
addDeps1 ( r , pkg1 , provs [ i ] ) ;
}
provs = _free ( provs ) ;
2013-01-24 06:42:31 +04:00
}
2011-01-10 13:02:49 +03:00
static
2013-01-25 09:00:10 +04:00
struct Req * makeRequires ( Spec spec , int warn )
2011-01-10 13:02:49 +03:00
{
2013-01-24 06:42:31 +04:00
struct Req * r = xcalloc ( 1 , sizeof * r ) ;
2011-01-10 13:02:49 +03:00
Package pkg1 , pkg2 ;
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
2011-01-10 13:02:49 +03:00
for ( pkg2 = pkg1 - > next ; pkg2 ; pkg2 = pkg2 - > next ) {
2013-01-28 21:49:48 +04:00
if ( ! pkg2 - > cpioList )
continue ;
2013-01-25 09:00:10 +04:00
makeReq1 ( r , pkg1 , pkg2 , warn & 1 ) ;
makeReq1 ( r , pkg2 , pkg1 , warn & 1 ) ;
2011-01-10 13:02:49 +03:00
}
2013-01-28 21:49:48 +04:00
}
2013-01-25 09:00:10 +04:00
propagateRequires ( r ) ;
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
2013-01-25 09:00:10 +04:00
fix_weak_deps ( r , pkg1 , spec - > packages ) ;
2013-01-28 21:49:48 +04:00
}
2011-02-08 06:57:03 +03:00
if ( ( warn & 2 ) = = 0 )
return r ;
2013-01-24 06:42:31 +04:00
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
2011-02-08 06:57:03 +03:00
for ( pkg2 = pkg1 - > next ; pkg2 ; pkg2 = pkg2 - > next ) {
2013-01-28 21:49:48 +04:00
if ( ! pkg2 - > cpioList )
continue ;
2011-02-08 06:57:03 +03:00
if ( ! Requires ( r , pkg1 , pkg2 ) & & depRequires ( pkg1 , pkg2 ) )
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_WARNING , " %s: non-strict dependency on %s \n " ,
pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2011-02-08 06:57:03 +03:00
if ( ! Requires ( r , pkg2 , pkg1 ) & & depRequires ( pkg2 , pkg1 ) )
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_WARNING , " %s: non-strict dependency on %s \n " ,
pkgName ( pkg2 ) , pkgName ( pkg1 ) ) ;
2011-02-08 06:57:03 +03:00
}
2013-01-28 21:49:48 +04:00
}
2011-01-10 13:02:49 +03:00
return r ;
}
2011-01-14 07:10:39 +03:00
# include "checkFiles.h" // fiIntersect
static
void fiPrune ( TFI_t fi , char pruned [ ] )
{
2011-01-12 15:00:25 +03:00
int * dil_ ;
const char * * bnl , * * dnl ;
int bnc , dnc , dic ;
int ok =
fi - > hge ( fi - > h , RPMTAG_BASENAMES , NULL , ( void * * ) & bnl , & bnc ) & &
fi - > hge ( fi - > h , RPMTAG_DIRNAMES , NULL , ( void * * ) & dnl , & dnc ) & &
fi - > hge ( fi - > h , RPMTAG_DIRINDEXES , NULL , ( void * * ) & dil_ , & dic ) ;
assert ( ok ) ;
assert ( fi - > fc = = bnc ) ;
assert ( bnc = = dic ) ;
2011-01-13 10:57:30 +03:00
int i , j , k ;
2011-01-12 15:00:25 +03:00
// dil must be copied, cf. relocateFileList
int dil [ dic ] ;
for ( i = 0 ; i < dic ; i + + )
dil [ i ] = dil_ [ i ] ;
// mark used dirnames
int dirused [ dnc ] ;
bzero ( dirused , dnc * sizeof * dirused ) ;
for ( i = 0 ; i < bnc ; i + + )
if ( ! pruned [ i ] )
dirused [ dil [ i ] ] + + ;
int propagated ;
do {
propagated = 0 ;
// for each unused dirname
for ( i = 0 ; i < dnc ; i + + ) {
if ( dirused [ i ] )
continue ;
// find its corresponding parent_dir+name entry
for ( j = 0 ; j < bnc ; j + + ) {
if ( pruned [ j ] )
continue ;
const char * D = dnl [ i ] ;
const char * d = dnl [ dil [ j ] ] ;
int dlen = strlen ( d ) ;
if ( strncmp ( D , d , dlen ) )
continue ;
const char * b = bnl [ j ] ;
int blen = strlen ( b ) ;
if ( strncmp ( D + dlen , b , blen ) )
continue ;
if ( strncmp ( D + dlen + blen , " / " , 2 ) )
continue ;
// makr parent_dir+name for removal
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL , " also prunning dir %s%s \n " , d , b ) ;
2011-01-12 15:00:25 +03:00
pruned [ j ] = 1 ;
// decrement parent_dir usage
if ( - - dirused [ dil [ j ] ] = = 0 )
propagated + + ;
}
}
}
while ( propagated ) ;
2011-01-13 10:57:30 +03:00
// new count for bnc-like values
int oldc = bnc ;
int newc = 0 ;
for ( i = 0 ; i < oldc ; i + + )
if ( ! pruned [ i ] )
newc + + ;
// establish new dirnames and dirindexes
for ( i = 0 , j = 0 ; i < dnc ; i + + ) {
if ( ! dirused [ i ] )
continue ;
if ( i = = j )
goto skip ;
dnl [ j ] = dnl [ i ] ;
for ( k = 0 ; k < dic ; k + + )
if ( dil [ k ] = = i )
dil [ k ] = j ;
skip :
j + + ;
}
dnc = j ;
// handle bnl, dnl and dil
# define PruneV(v) \
for ( i = 0 , j = 0 ; i < oldc ; i + + ) \
if ( ! pruned [ i ] ) \
v [ j + + ] = v [ i ]
PruneV ( bnl ) ;
PruneV ( dil ) ;
PruneV ( fi - > bnl ) ;
PruneV ( fi - > dil ) ;
fi - > hme ( fi - > h , RPMTAG_BASENAMES , RPM_STRING_ARRAY_TYPE , bnl , newc ) ;
fi - > hme ( fi - > h , RPMTAG_DIRNAMES , RPM_STRING_ARRAY_TYPE , dnl , dnc ) ;
fi - > hme ( fi - > h , RPMTAG_DIRINDEXES , RPM_INT32_TYPE , dil , newc ) ;
bnl = fi - > hfd ( bnl , RPM_STRING_ARRAY_TYPE ) ;
dnl = fi - > hfd ( dnl , RPM_STRING_ARRAY_TYPE ) ;
// prune header tags
rpmTagType tagt ;
int tagc ;
const char * * strv ;
# define PruneStrTag(tag) \
if ( fi - > hge ( fi - > h , tag , & tagt , ( void * * ) & strv , & tagc ) ) { \
assert ( tagt = = RPM_STRING_ARRAY_TYPE ) ; \
assert ( tagc = = oldc ) ; \
PruneV ( strv ) ; \
fi - > hme ( fi - > h , tag , RPM_STRING_ARRAY_TYPE , strv , newc ) ; \
fi - > hfd ( strv , RPM_STRING_ARRAY_TYPE ) ; \
}
short * INT16p , INT16v [ oldc ] ;
int * INT32p , INT32v [ oldc ] ;
# define PruneIntTag(INT, tag) \
if ( fi - > hge ( fi - > h , tag , & tagt , ( void * * ) & INT # # p , & tagc ) ) { \
assert ( tagt = = RPM_ # # INT # # _TYPE ) ; \
assert ( tagc = = oldc ) ; \
for ( i = 0 ; i < oldc ; i + + ) \
INT # # v [ i ] = INT # # p [ i ] ; \
PruneV ( INT # # v ) ; \
fi - > hme ( fi - > h , tag , RPM_ # # INT # # _TYPE , INT # # v , newc ) ; \
}
# define PruneI16Tag(tag) PruneIntTag(INT16, tag)
# define PruneI32Tag(tag) PruneIntTag(INT32, tag)
PruneI32Tag ( RPMTAG_FILESIZES ) ;
PruneStrTag ( RPMTAG_FILEUSERNAME ) ;
PruneStrTag ( RPMTAG_FILEGROUPNAME ) ;
PruneI32Tag ( RPMTAG_FILEMTIMES ) ;
PruneI16Tag ( RPMTAG_FILEMODES ) ;
PruneI16Tag ( RPMTAG_FILERDEVS ) ;
PruneI32Tag ( RPMTAG_FILEDEVICES ) ;
PruneI32Tag ( RPMTAG_FILEINODES ) ;
PruneStrTag ( RPMTAG_FILELANGS ) ;
PruneStrTag ( RPMTAG_FILEMD5S ) ;
PruneStrTag ( RPMTAG_FILELINKTOS ) ;
PruneI32Tag ( RPMTAG_FILEVERIFYFLAGS ) ;
PruneI32Tag ( RPMTAG_FILEFLAGS ) ;
// update fi, cf. genCpioListAndHeader
PruneV ( fi - > apath ) ;
PruneV ( fi - > actions ) ;
PruneV ( fi - > fmapflags ) ;
PruneV ( fi - > fuids ) ;
PruneV ( fi - > fgids ) ;
2011-02-05 03:29:28 +03:00
PruneV ( fi - > fsts ) ;
2011-01-13 10:57:30 +03:00
struct transactionFileInfo_s save_fi ;
# define MV(a) save_fi.a = fi->a; fi->a = NULL
MV ( bnl ) ; MV ( dnl ) ; MV ( dil ) ;
2011-02-05 03:29:28 +03:00
MV ( apath ) ; MV ( actions ) ; MV ( fmapflags ) ; MV ( fuids ) ; MV ( fgids ) ; MV ( fsts ) ;
2011-01-13 10:57:30 +03:00
save_fi . h = fi - > h ;
save_fi . astriplen = fi - > astriplen ;
freeFi ( fi ) ;
bzero ( fi , sizeof * fi ) ;
fi - > type = TR_ADDED ;
loadFi ( save_fi . h , fi ) ;
assert ( fi - > fc = = newc ) ;
fi - > dnl = _free ( fi - > dnl ) ;
fi - > bnl = _free ( fi - > bnl ) ;
# undef MV
# define MV(a) fi->a = save_fi.a
MV ( bnl ) ; MV ( dnl ) ; MV ( dil ) ;
2011-02-05 03:29:28 +03:00
MV ( apath ) ; MV ( actions ) ; MV ( fmapflags ) ; MV ( fuids ) ; MV ( fgids ) ; MV ( fsts ) ;
2011-01-13 10:57:30 +03:00
fi - > astriplen = save_fi . astriplen ;
2011-01-14 07:10:39 +03:00
}
// prune src dups from pkg1 and add dependency on pkg2
2011-01-14 07:06:46 +03:00
static
2013-01-25 09:00:10 +04:00
void pruneSrc1 ( struct Req * r , Package pkg1 , Package pkg2 )
2011-01-14 07:06:46 +03:00
{
2011-01-14 07:10:39 +03:00
TFI_t fi1 = pkg1 - > cpioList ;
TFI_t fi2 = pkg2 - > cpioList ;
if ( fi1 = = NULL ) return ;
if ( fi2 = = NULL ) return ;
int npruned = 0 ;
char pruned [ fi1 - > fc ] ;
bzero ( pruned , fi1 - > fc ) ;
void cb ( char * f , int i1 , int i2 )
{
( void ) i2 ;
2011-01-12 15:00:25 +03:00
if ( S_ISDIR ( fi1 - > fmodes [ i1 ] ) )
return ;
2011-01-14 07:10:39 +03:00
const char src [ ] = " /usr/src/debug/ " ;
if ( strncmp ( f , src , sizeof ( src ) - 1 ) )
return ;
pruned [ i1 ] = 1 ;
npruned + + ;
}
fiIntersect ( fi1 , fi2 , cb ) ;
if ( npruned = = 0 )
return ;
2013-01-28 20:22:44 +04:00
addDeps1 ( r , pkg1 , pkg2 ) ;
2013-01-29 02:48:10 +04:00
rpmMessage ( RPMMESS_NORMAL , " Removing from %s %d sources provided by %s \n " ,
pkgName ( pkg1 ) , npruned , pkgName ( pkg2 ) ) ;
2011-01-14 07:10:39 +03:00
fiPrune ( fi1 , pruned ) ;
2011-01-14 07:06:46 +03:00
}
2011-02-04 02:41:05 +03:00
static void
processDependentDebuginfo ( struct Req * r , Spec spec ,
2013-01-25 09:00:10 +04:00
void ( * cb ) ( struct Req * r , Package pkg1 , Package pkg2 ) , int mutual )
2011-01-14 07:06:46 +03:00
{
int i1 , i2 ;
struct Pair r1 , r2 ;
const char * Nd , * Np ;
const char * suf ;
// r1 = { pkg1-debuginfo, pkg1 }
for ( i1 = 0 ; i1 < r - > c ; i1 + + ) {
r1 = r - > v [ i1 ] ;
Nd = pkgName ( r1 . pkg1 ) ;
Np = pkgName ( r1 . pkg2 ) ;
suf = skipPrefixDash ( Nd , Np ) ;
if ( suf = = NULL | | strcmp ( suf , " debuginfo " ) )
continue ;
// r2 = { pkg2-debuginfo, pkg2 }
for ( i2 = i1 ; i2 < r - > c ; i2 + + ) {
r2 = r - > v [ i2 ] ;
Nd = pkgName ( r2 . pkg1 ) ;
Np = pkgName ( r2 . pkg2 ) ;
suf = skipPrefixDash ( Nd , Np ) ;
if ( suf = = NULL | | strcmp ( suf , " debuginfo " ) )
continue ;
// (pkg1 <-> pkg2) => (pkg1-debuginfo <-> pkg2-debuginfo)
2011-02-04 02:41:05 +03:00
if ( Requires ( r , r1 . pkg2 , r2 . pkg2 ) ) {
2013-01-25 09:00:10 +04:00
cb ( r , r1 . pkg1 , r2 . pkg1 ) ;
2011-02-04 02:41:05 +03:00
if ( ! mutual )
continue ;
}
if ( Requires ( r , r2 . pkg2 , r1 . pkg2 ) )
2013-01-25 09:00:10 +04:00
cb ( r , r2 . pkg1 , r1 . pkg1 ) ;
2011-01-14 07:06:46 +03:00
}
}
}
2011-02-04 02:41:05 +03:00
static
void pruneDebuginfoSrc ( struct Req * r , Spec spec )
{
processDependentDebuginfo ( r , spec , pruneSrc1 , 0 ) ;
}
2011-02-04 05:06:48 +03:00
// if pkg1 implicitly requires pkg2, add strict dependency
2013-01-25 09:00:10 +04:00
static void
liftDeps1 ( struct Req * r , Package pkg1 , Package pkg2 )
2011-02-04 05:06:48 +03:00
{
2013-01-25 09:00:10 +04:00
if ( ! Requires ( r , pkg1 , pkg2 ) & & depRequires ( pkg1 , pkg2 ) )
addDeps1 ( r , pkg1 , pkg2 ) ;
2011-02-04 05:06:48 +03:00
}
static
void liftDebuginfoDeps ( struct Req * r , Spec spec )
{
processDependentDebuginfo ( r , spec , liftDeps1 , 1 ) ;
}
2011-02-06 04:50:32 +03:00
// assuming pkg1 has strict dependency on pkg2, prune deps provided by pkg2
2011-02-04 09:12:08 +03:00
static
void pruneDeps1 ( Package pkg1 , Package pkg2 )
{
TFI_t fi = pkg1 - > cpioList ;
if ( fi = = NULL )
return ;
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv_ = NULL ;
int ok =
fi - > hge ( pkg1 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
fi - > hge ( pkg1 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
fi - > hge ( pkg1 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv_ , NULL ) ;
if ( ! ok )
return ;
assert ( reqc > 0 ) ;
int i , j ;
int reqFv [ reqc ] ;
for ( i = 0 ; i < reqc ; i + + )
reqFv [ i ] = reqFv_ [ i ] ;
2013-01-25 09:00:10 +04:00
struct availableList_s proval ;
alCreate ( & proval ) ;
alAddPackage ( & proval , pkg2 - > header , NULL , NULL , NULL ) ;
2011-02-04 09:12:08 +03:00
int flags = 0 , * flagsp = NULL ;
struct availablePackage * ap = NULL ;
2011-02-05 07:25:46 +03:00
int rpmlibSetVersions = - 1 ;
int hasSetVersions = 0 ;
2011-02-04 09:12:08 +03:00
int npruned = 0 ;
char pruned [ reqc ] ;
bzero ( pruned , reqc ) ;
for ( i = 0 ; i < reqc ; i + + ) {
if ( ( reqFv [ i ] & RPMSENSE_SENSEMASK ) = = RPMSENSE_EQUAL & &
strcmp ( reqNv [ i ] , pkgName ( pkg2 ) ) = = 0 )
{
if ( flagsp = = NULL )
flagsp = & reqFv [ i ] ;
continue ;
}
2011-02-05 07:25:46 +03:00
if ( ( reqFv [ i ] & RPMSENSE_RPMLIB ) & &
strcmp ( reqNv [ i ] , " rpmlib(SetVersions) " ) = = 0 )
{
if ( rpmlibSetVersions = = - 1 )
rpmlibSetVersions = i ;
continue ;
}
2013-01-25 09:00:10 +04:00
ap = alSatisfiesDepend ( & proval , reqNv [ i ] , reqVv [ i ] , reqFv [ i ] ) ;
2011-02-05 07:25:46 +03:00
if ( ap = = NULL ) {
if ( ( reqFv [ i ] & RPMSENSE_SENSEMASK ) )
if ( strncmp ( reqVv [ i ] , " set: " , 4 ) = = 0 )
hasSetVersions + + ;
2011-02-04 09:12:08 +03:00
continue ;
2011-02-05 07:25:46 +03:00
}
2011-02-04 09:12:08 +03:00
pruned [ i ] = 1 ;
npruned + + ;
flags | = reqFv [ i ] ;
}
2013-01-25 09:00:10 +04:00
alFree ( & proval ) ;
2011-02-04 09:12:08 +03:00
if ( npruned = = 0 ) {
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
return ;
}
2011-02-05 07:25:46 +03:00
if ( hasSetVersions = = 0 & & rpmlibSetVersions > = 0 ) {
pruned [ rpmlibSetVersions ] = 1 ;
npruned + + ;
}
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL ,
" Removing %d extra deps from %s due to dependency on %s \n " ,
npruned , pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2011-02-04 09:12:08 +03:00
if ( flagsp )
* flagsp | = ( flags & RPMSENSE_PREREQ ) ;
for ( i = 0 , j = 0 ; i < reqc ; i + + ) {
if ( pruned [ i ] )
continue ;
if ( i = = j )
goto skip ;
reqNv [ j ] = reqNv [ i ] ;
reqVv [ j ] = reqVv [ i ] ;
reqFv [ j ] = reqFv [ i ] ;
skip :
j + + ;
}
reqc = j ;
fi - > hme ( fi - > h , RPMTAG_REQUIRENAME , RPM_STRING_ARRAY_TYPE , reqNv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREVERSION , RPM_STRING_ARRAY_TYPE , reqVv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREFLAGS , RPM_INT32_TYPE , reqFv , reqc ) ;
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
}
static
void pruneExtraDeps ( struct Req * r , Spec spec )
{
int i ;
for ( i = 0 ; i < r - > c ; i + + )
pruneDeps1 ( r - > v [ i ] . pkg1 , r - > v [ i ] . pkg2 ) ;
}
2011-02-06 04:50:32 +03:00
// assuming pkg1 has strict dependency on pkg2, prune deps required by pkg2
static
2011-03-14 05:27:17 +03:00
void pruneRDeps1 ( struct Req * r , Spec spec , Package pkg1 , Package pkg2 )
2011-02-06 04:50:32 +03:00
{
TFI_t fi = pkg1 - > cpioList ;
if ( fi = = NULL )
return ;
int reqc = 0 ;
const char * * reqNv = NULL ;
const char * * reqVv = NULL ;
const int * reqFv_ = NULL ;
int ok =
fi - > hge ( fi - > h , RPMTAG_REQUIRENAME , NULL , ( void * * ) & reqNv , & reqc ) & &
fi - > hge ( fi - > h , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & reqVv , NULL ) & &
fi - > hge ( fi - > h , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & reqFv_ , NULL ) ;
if ( ! ok )
return ;
int i , j ;
int reqFv [ reqc ] ;
for ( i = 0 ; i < reqc ; i + + )
reqFv [ i ] = reqFv_ [ i ] ;
int provc = 0 ;
const char * * provNv = NULL ;
const char * * provVv = NULL ;
const int * provFv = NULL ;
const HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
const HFD_t hfd = ( HFD_t ) headerFreeData ;
ok =
hge ( pkg2 - > header , RPMTAG_REQUIRENAME , NULL , ( void * * ) & provNv , & provc ) & &
hge ( pkg2 - > header , RPMTAG_REQUIREVERSION , NULL , ( void * * ) & provVv , NULL ) & &
hge ( pkg2 - > header , RPMTAG_REQUIREFLAGS , NULL , ( void * * ) & provFv , NULL ) ;
if ( ! ok ) {
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
return ;
}
int npruned = 0 ;
char pruned [ reqc ] ;
bzero ( pruned , reqc ) ;
2011-03-14 05:27:17 +03:00
// check if pkg2 is part of a cycle
2011-02-07 06:57:43 +03:00
int cycle = 0 ;
Package pkg3 ;
2011-03-14 05:27:17 +03:00
for ( pkg3 = spec - > packages ; pkg3 ; pkg3 = pkg3 - > next ) {
if ( pkg3 = = pkg1 | | pkg3 = = pkg2 )
2011-02-07 06:57:43 +03:00
continue ;
if ( Requires ( r , pkg2 , pkg3 ) & & Requires ( r , pkg3 , pkg2 ) ) {
cycle = 1 ;
break ;
}
}
2011-02-06 04:50:32 +03:00
void prune ( int i , int j )
{
if ( strcmp ( reqNv [ i ] , provNv [ j ] ) )
return ;
2011-02-07 06:57:43 +03:00
if ( cycle & & ( reqFv [ i ] & RPMSENSE_SENSEMASK ) = = RPMSENSE_EQUAL )
return ;
2011-02-06 04:50:32 +03:00
dep_compare_t cmp = compare_deps ( RPMTAG_REQUIRENAME ,
provVv [ j ] , provFv [ j ] , reqVv [ i ] , reqFv [ i ] ) ;
if ( ! ( cmp = = DEP_ST | | cmp = = DEP_EQ ) )
return ;
pruned [ i ] = 1 ;
npruned + + ;
}
for ( i = 0 ; i < reqc ; i + + )
for ( j = 0 ; j < provc ; j + + )
prune ( i , j ) ;
if ( npruned = = 0 )
goto free ;
2013-01-27 02:31:44 +04:00
rpmMessage ( RPMMESS_NORMAL ,
" Removing %d extra deps from %s due to repentancy on %s \n " ,
npruned , pkgName ( pkg1 ) , pkgName ( pkg2 ) ) ;
2011-02-06 04:50:32 +03:00
for ( i = 0 , j = 0 ; i < reqc ; i + + ) {
if ( pruned [ i ] )
continue ;
if ( i = = j )
goto skip ;
reqNv [ j ] = reqNv [ i ] ;
reqVv [ j ] = reqVv [ i ] ;
reqFv [ j ] = reqFv [ i ] ;
skip :
j + + ;
}
reqc = j ;
fi - > hme ( fi - > h , RPMTAG_REQUIRENAME , RPM_STRING_ARRAY_TYPE , reqNv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREVERSION , RPM_STRING_ARRAY_TYPE , reqVv , reqc ) ;
fi - > hme ( fi - > h , RPMTAG_REQUIREFLAGS , RPM_INT32_TYPE , reqFv , reqc ) ;
free :
reqNv = fi - > hfd ( reqNv , RPM_STRING_ARRAY_TYPE ) ;
reqVv = fi - > hfd ( reqVv , RPM_STRING_ARRAY_TYPE ) ;
provNv = hfd ( provNv , RPM_STRING_ARRAY_TYPE ) ;
provVv = hfd ( provVv , RPM_STRING_ARRAY_TYPE ) ;
}
static
void pruneExtraRDeps ( struct Req * r , Spec spec )
{
Package pkg1 , pkg2 ;
2013-01-28 21:49:48 +04:00
for ( pkg1 = spec - > packages ; pkg1 ; pkg1 = pkg1 - > next ) {
if ( ! pkg1 - > cpioList )
continue ;
for ( pkg2 = pkg1 - > next ; pkg2 ; pkg2 = pkg2 - > next ) {
if ( ! pkg2 - > cpioList )
continue ;
2011-02-06 04:50:32 +03:00
if ( Requires ( r , pkg1 , pkg2 ) )
2011-03-14 05:27:17 +03:00
pruneRDeps1 ( r , spec , pkg1 , pkg2 ) ;
2011-02-06 04:50:32 +03:00
// "else" guards against mutual deletions
else if ( Requires ( r , pkg2 , pkg1 ) )
2011-03-14 05:27:17 +03:00
pruneRDeps1 ( r , spec , pkg2 , pkg1 ) ;
2013-01-28 21:49:48 +04:00
}
}
2011-02-06 04:50:32 +03:00
}
2011-01-10 13:02:49 +03:00
int processInterdep ( Spec spec )
{
2013-01-25 09:00:10 +04:00
struct Req * r = makeRequires ( spec , 1 ) ;
2011-01-14 07:06:46 +03:00
pruneDebuginfoSrc ( r , spec ) ;
2011-02-04 05:06:48 +03:00
liftDebuginfoDeps ( r , spec ) ;
2011-01-10 13:02:49 +03:00
r = freeRequires ( r ) ;
2013-01-24 06:42:31 +04:00
2013-01-25 09:00:10 +04:00
r = makeRequires ( spec , 2 ) ;
2011-02-07 06:10:37 +03:00
int optlevel = rpmExpandNumeric ( " %{?_deps_optimization}%{?!_deps_optimization:2} " ) ;
2013-01-24 06:42:31 +04:00
if ( optlevel > = 2 ) {
pruneExtraDeps ( r , spec ) ;
pruneExtraRDeps ( r , spec ) ;
}
2011-02-04 09:12:08 +03:00
r = freeRequires ( r ) ;
2011-01-10 13:02:49 +03:00
return 0 ;
}
// ex: set ts=8 sts=4 sw=4 noet: