2002-03-25 23:16:26 +03:00
/** \ingroup rpmcli
* \ file lib / query . c
* Display tag values from package metadata .
*/
# include "system.h"
# ifndef PATH_MAX
/*@-incondefs@*/ /* FIX: long int? */
# define PATH_MAX 255
/*@=incondefs@*/
# endif
2002-03-26 01:02:39 +03:00
# include "rpmcli.h"
# include "rpmbuild.h"
2002-03-25 23:16:26 +03:00
# include "manifest.h"
# include "debug.h"
/*@access rpmdbMatchIterator@*/ /* XXX compared with NULL */
/*@access Header@*/ /* XXX compared with NULL */
/*@access rpmdb@*/ /* XXX compared with NULL */
/*@access FD_t@*/ /* XXX compared with NULL */
/**
*/
static void printFileInfo ( char * te , const char * name ,
unsigned int size , unsigned short mode ,
unsigned int mtime ,
unsigned short rdev , unsigned int nlink ,
const char * owner , const char * group ,
int uid , int gid , const char * linkto )
/*@modifies *te @*/
{
char sizefield [ 15 ] ;
char ownerfield [ 9 ] , groupfield [ 9 ] ;
char timefield [ 100 ] ;
time_t when = mtime ; /* important if sizeof(int_32) ! sizeof(time_t) */
struct tm * tm ;
static time_t now ;
static struct tm nowtm ;
const char * namefield = name ;
char * perms = rpmPermsString ( mode ) ;
/* On first call, grab snapshot of now */
if ( now = = 0 ) {
now = time ( NULL ) ;
tm = localtime ( & now ) ;
if ( tm ) nowtm = * tm ; /* structure assignment */
}
if ( owner )
strncpy ( ownerfield , owner , 8 ) ;
else
sprintf ( ownerfield , " %-8d " , uid ) ;
ownerfield [ 8 ] = ' \0 ' ;
if ( group )
strncpy ( groupfield , group , 8 ) ;
else
sprintf ( groupfield , " %-8d " , gid ) ;
groupfield [ 8 ] = ' \0 ' ;
/* this is normally right */
sprintf ( sizefield , " %12u " , size ) ;
/* this knows too much about dev_t */
if ( S_ISLNK ( mode ) ) {
char * nf = alloca ( strlen ( name ) + sizeof ( " -> " ) + strlen ( linkto ) ) ;
sprintf ( nf , " %s -> %s " , name , linkto ) ;
namefield = nf ;
} else if ( S_ISCHR ( mode ) ) {
perms [ 0 ] = ' c ' ;
sprintf ( sizefield , " %3u, %3u " , ( ( unsigned ) ( rdev > > 8 ) & 0xff ) ,
( ( unsigned ) rdev & 0xff ) ) ;
} else if ( S_ISBLK ( mode ) ) {
perms [ 0 ] = ' b ' ;
sprintf ( sizefield , " %3u, %3u " , ( ( unsigned ) ( rdev > > 8 ) & 0xff ) ,
( ( unsigned ) rdev & 0xff ) ) ;
}
/* Convert file mtime to display format */
tm = localtime ( & when ) ;
timefield [ 0 ] = ' \0 ' ;
if ( tm ! = NULL )
{ const char * fmt ;
if ( now > when + 6L * 30L * 24L * 60L * 60L | | /* Old. */
now < when - 60L * 60L ) /* In the future. */
{
/* The file is fairly old or in the future.
* POSIX says the cutoff is 6 months old ;
* approximate this by 6 * 30 days .
* Allow a 1 hour slop factor for what is considered " the future " ,
* to allow for NFS server / client clock disagreement .
* Show the year instead of the time of day .
*/
fmt = " %b %e %Y " ;
} else {
fmt = " %b %e %H:%M " ;
}
( void ) strftime ( timefield , sizeof ( timefield ) - 1 , fmt , tm ) ;
}
sprintf ( te , " %s %4d %-8s%-8s %10s %s %s " , perms ,
( int ) nlink , ownerfield , groupfield , sizefield , timefield , namefield ) ;
perms = _free ( perms ) ;
}
/**
*/
static inline /*@null@*/ const char * queryHeader ( Header h , const char * qfmt )
/*@*/
{
2002-04-22 21:06:31 +04:00
const char * errstr = " (unknown error) " ;
2002-03-25 23:16:26 +03:00
const char * str ;
str = headerSprintf ( h , qfmt , rpmTagTable , rpmHeaderFormats , & errstr ) ;
if ( str = = NULL )
rpmError ( RPMERR_QFMT , _ ( " incorrect format: %s \n " ) , errstr ) ;
return str ;
}
/**
*/
static int countLinks ( int_16 * fileRdevList , int_32 * fileInodeList , int nfiles ,
int xfile )
/*@*/
{
int nlink = 0 ;
/* XXX rpm-3.3.12 has not RPMTAG_FILEINODES */
if ( ! ( fileRdevList [ xfile ] ! = 0 & & fileRdevList & &
fileInodeList [ xfile ] ! = 0 & & fileInodeList & & nfiles > 0 ) )
return 1 ;
while ( nfiles - - > 0 ) {
if ( fileRdevList [ nfiles ] = = 0 )
continue ;
if ( fileRdevList [ nfiles ] ! = fileRdevList [ xfile ] )
continue ;
if ( fileInodeList [ nfiles ] = = 0 )
continue ;
if ( fileInodeList [ nfiles ] ! = fileInodeList [ xfile ] )
continue ;
nlink + + ;
}
if ( nlink = = 0 ) nlink = 1 ;
return nlink ;
}
2006-11-19 02:17:15 +03:00
/**
*/
static void flushBuffer ( char * * tp , char * * tep , int nonewline )
/*@ modifies *tp, *tep @*/
{
char * t , * te ;
t = * tp ;
te = * tep ;
if ( te > t ) {
if ( ! nonewline ) {
* te + + = ' \n ' ;
* te = ' \0 ' ;
}
rpmMessage ( RPMMESS_NORMAL , " %s " , t ) ;
te = t ;
* t = ' \0 ' ;
* tp = t ;
* tep = te ;
}
}
2002-03-25 23:16:26 +03:00
int showQueryPackage ( QVA_t qva , /*@unused@*/ rpmdb rpmdb , Header h )
{
HGE_t hge = ( HGE_t ) headerGetEntryMinMemory ;
HFD_t hfd = headerFreeData ;
2007-05-18 04:18:28 +04:00
size_t tb = 2 * BUFSIZ ;
size_t sb ;
2002-03-25 23:16:26 +03:00
char * t , * te ;
rpmQueryFlags queryFlags = qva - > qva_flags ;
const char * queryFormat = qva - > qva_queryFormat ;
rpmTagType type ;
int_32 count ;
char * prefix = NULL ;
const char * * dirNames = NULL ;
const char * * baseNames = NULL ;
rpmTagType bnt , dnt ;
const char * * fileMD5List = NULL ;
const char * * fileOwnerList = NULL ;
const char * * fileGroupList = NULL ;
const char * * fileLinktoList = NULL ;
rpmTagType m5t , fot , fgt , ltt ;
const char * fileStatesList ;
int_32 * fileFlagsList , * fileMTimeList , * fileSizeList ;
int_32 * fileUIDList = NULL ;
int_32 * fileGIDList = NULL ;
int_32 * fileInodeList = NULL ;
uint_16 * fileModeList ;
uint_16 * fileRdevList ;
int_32 * dirIndexes ;
int rc = 0 ; /* XXX FIXME: need real return code */
int i ;
2007-05-18 04:18:28 +04:00
te = t = xmalloc ( tb ) ;
2002-03-25 23:16:26 +03:00
* te = ' \0 ' ;
if ( queryFormat = = NULL & & queryFlags = = QUERY_FOR_DEFAULT ) {
const char * name , * version , * release ;
( void ) headerNVR ( h , & name , & version , & release ) ;
te = stpcpy ( te , name ) ;
te = stpcpy ( stpcpy ( te , " - " ) , version ) ;
te = stpcpy ( stpcpy ( te , " - " ) , release ) ;
goto exit ;
}
if ( queryFormat ) {
const char * str = queryHeader ( h , queryFormat ) ;
/*@-branchstate@*/
if ( str ) {
2007-05-18 04:18:28 +04:00
size_t tx = ( te - t ) ;
2002-03-25 23:16:26 +03:00
2007-05-18 04:18:28 +04:00
sb = strlen ( str ) ;
if ( sb ) {
tb + = sb ;
t = xrealloc ( t , tb ) ;
te = t + tx ;
2002-03-25 23:16:26 +03:00
}
/*@-usereleased@*/
te = stpcpy ( te , str ) ;
/*@=usereleased@*/
str = _free ( str ) ;
2006-11-19 02:17:15 +03:00
flushBuffer ( & t , & te , 1 ) ;
2002-03-25 23:16:26 +03:00
}
/*@=branchstate@*/
}
if ( ! ( queryFlags & QUERY_FOR_LIST ) )
goto exit ;
if ( ! hge ( h , RPMTAG_BASENAMES , & bnt , ( void * * ) & baseNames , & count ) ) {
te = stpcpy ( te , _ ( " (contains no files) " ) ) ;
goto exit ;
}
if ( ! hge ( h , RPMTAG_FILESTATES , & type , ( void * * ) & fileStatesList , NULL ) )
fileStatesList = NULL ;
if ( ! hge ( h , RPMTAG_DIRNAMES , & dnt , ( void * * ) & dirNames , NULL ) )
dirNames = NULL ;
if ( ! hge ( h , RPMTAG_DIRINDEXES , NULL , ( void * * ) & dirIndexes , NULL ) )
dirIndexes = NULL ;
if ( ! hge ( h , RPMTAG_FILEFLAGS , & type , ( void * * ) & fileFlagsList , NULL ) )
fileFlagsList = NULL ;
if ( ! hge ( h , RPMTAG_FILESIZES , & type , ( void * * ) & fileSizeList , NULL ) )
fileSizeList = NULL ;
if ( ! hge ( h , RPMTAG_FILEMODES , & type , ( void * * ) & fileModeList , NULL ) )
fileModeList = NULL ;
if ( ! hge ( h , RPMTAG_FILEMTIMES , & type , ( void * * ) & fileMTimeList , NULL ) )
fileMTimeList = NULL ;
if ( ! hge ( h , RPMTAG_FILERDEVS , & type , ( void * * ) & fileRdevList , NULL ) )
fileRdevList = NULL ;
if ( ! hge ( h , RPMTAG_FILEINODES , & type , ( void * * ) & fileInodeList , NULL ) )
fileInodeList = NULL ;
if ( ! hge ( h , RPMTAG_FILELINKTOS , & ltt , ( void * * ) & fileLinktoList , NULL ) )
fileLinktoList = NULL ;
if ( ! hge ( h , RPMTAG_FILEMD5S , & m5t , ( void * * ) & fileMD5List , NULL ) )
fileMD5List = NULL ;
if ( ! hge ( h , RPMTAG_FILEUIDS , & type , ( void * * ) & fileUIDList , NULL ) )
fileUIDList = NULL ;
if ( ! hge ( h , RPMTAG_FILEGIDS , & type , ( void * * ) & fileGIDList , NULL ) )
fileGIDList = NULL ;
if ( ! hge ( h , RPMTAG_FILEUSERNAME , & fot , ( void * * ) & fileOwnerList , NULL ) )
fileOwnerList = NULL ;
if ( ! hge ( h , RPMTAG_FILEGROUPNAME , & fgt , ( void * * ) & fileGroupList , NULL ) )
fileGroupList = NULL ;
for ( i = 0 ; i < count ; i + + ) {
/* If querying only docs, skip non-doc files. */
if ( ( queryFlags & QUERY_FOR_DOCS )
& & ! ( fileFlagsList [ i ] & RPMFILE_DOC ) )
continue ;
/* If querying only configs, skip non-config files. */
if ( ( queryFlags & QUERY_FOR_CONFIG )
& & ! ( fileFlagsList [ i ] & RPMFILE_CONFIG ) )
continue ;
/* If not querying %ghost, skip ghost files. */
if ( ! ( qva - > qva_fflags & RPMFILE_GHOST )
& & ( fileFlagsList [ i ] & RPMFILE_GHOST ) )
continue ;
/*@-internalglobs@*/ /* FIX: shrug */
if ( ! rpmIsVerbose ( ) & & prefix )
te = stpcpy ( te , prefix ) ;
/*@=internalglobs@*/
if ( queryFlags & QUERY_FOR_STATE ) {
if ( fileStatesList ) {
rpmfileState fstate = fileStatesList [ i ] ;
switch ( fstate ) {
case RPMFILE_STATE_NORMAL :
te = stpcpy ( te , _ ( " normal " ) ) ;
/*@switchbreak@*/ break ;
case RPMFILE_STATE_REPLACED :
te = stpcpy ( te , _ ( " replaced " ) ) ;
/*@switchbreak@*/ break ;
case RPMFILE_STATE_NOTINSTALLED :
te = stpcpy ( te , _ ( " not installed " ) ) ;
/*@switchbreak@*/ break ;
case RPMFILE_STATE_NETSHARED :
te = stpcpy ( te , _ ( " net shared " ) ) ;
/*@switchbreak@*/ break ;
default :
sprintf ( te , _ ( " (unknown %3d) " ) , ( int ) fileStatesList [ i ] ) ;
te + = strlen ( te ) ;
/*@switchbreak@*/ break ;
}
} else {
te = stpcpy ( te , _ ( " (no state) " ) ) ;
}
}
if ( queryFlags & QUERY_FOR_DUMPFILES ) {
sprintf ( te , " %s%s %d %d %s 0%o " ,
dirNames [ dirIndexes [ i ] ] , baseNames [ i ] ,
fileSizeList [ i ] , fileMTimeList [ i ] ,
fileMD5List [ i ] , ( unsigned ) fileModeList [ i ] ) ;
te + = strlen ( te ) ;
if ( fileOwnerList & & fileGroupList ) {
sprintf ( te , " %s %s " , fileOwnerList [ i ] , fileGroupList [ i ] ) ;
te + = strlen ( te ) ;
} else if ( fileUIDList & & fileGIDList ) {
sprintf ( te , " %d %d " , fileUIDList [ i ] , fileGIDList [ i ] ) ;
te + = strlen ( te ) ;
} else {
rpmError ( RPMERR_INTERNAL ,
_ ( " package has neither file owner or id lists \n " ) ) ;
}
sprintf ( te , " %s %s %u " ,
fileFlagsList [ i ] & RPMFILE_CONFIG ? " 1 " : " 0 " ,
fileFlagsList [ i ] & RPMFILE_DOC ? " 1 " : " 0 " ,
( unsigned ) fileRdevList [ i ] ) ;
te + = strlen ( te ) ;
if ( strlen ( fileLinktoList [ i ] ) )
sprintf ( te , " %s " , fileLinktoList [ i ] ) ;
else
sprintf ( te , " X " ) ;
te + = strlen ( te ) ;
} else
/*@-internalglobs@*/ /* FIX: shrug */
if ( ! rpmIsVerbose ( ) ) {
te = stpcpy ( te , dirNames [ dirIndexes [ i ] ] ) ;
te = stpcpy ( te , baseNames [ i ] ) ;
}
/*@=internalglobs@*/
else {
char * filespec ;
int nlink ;
size_t fileSize ;
filespec = xmalloc ( strlen ( dirNames [ dirIndexes [ i ] ] )
+ strlen ( baseNames [ i ] ) + 1 ) ;
strcpy ( filespec , dirNames [ dirIndexes [ i ] ] ) ;
strcat ( filespec , baseNames [ i ] ) ;
fileSize = fileSizeList [ i ] ;
nlink = countLinks ( fileRdevList , fileInodeList , count , i ) ;
if ( S_ISDIR ( fileModeList [ i ] ) ) {
nlink + + ;
fileSize = 0 ;
}
if ( fileOwnerList & & fileGroupList ) {
printFileInfo ( te , filespec , fileSize ,
fileModeList [ i ] , fileMTimeList [ i ] ,
fileRdevList [ i ] , nlink ,
fileOwnerList [ i ] ,
fileGroupList [ i ] , - 1 ,
- 1 , fileLinktoList [ i ] ) ;
te + = strlen ( te ) ;
} else if ( fileUIDList & & fileGIDList ) {
printFileInfo ( te , filespec , fileSize ,
fileModeList [ i ] , fileMTimeList [ i ] ,
fileRdevList [ i ] , nlink ,
NULL , NULL , fileUIDList [ i ] ,
fileGIDList [ i ] ,
fileLinktoList [ i ] ) ;
te + = strlen ( te ) ;
} else {
rpmError ( RPMERR_INTERNAL ,
_ ( " package has neither file owner or id lists \n " ) ) ;
}
filespec = _free ( filespec ) ;
}
2006-11-19 02:17:15 +03:00
flushBuffer ( & t , & te , 0 ) ;
2002-03-25 23:16:26 +03:00
}
rc = 0 ;
exit :
2006-11-19 02:17:15 +03:00
flushBuffer ( & t , & te , 0 ) ;
2002-03-25 23:16:26 +03:00
t = _free ( t ) ;
dirNames = hfd ( dirNames , dnt ) ;
baseNames = hfd ( baseNames , bnt ) ;
fileLinktoList = hfd ( fileLinktoList , ltt ) ;
fileMD5List = hfd ( fileMD5List , m5t ) ;
fileOwnerList = hfd ( fileOwnerList , fot ) ;
fileGroupList = hfd ( fileGroupList , fgt ) ;
return rc ;
}
/**
*/
static void
printNewSpecfile ( Spec spec )
/*@globals fileSystem @*/
/*@modifies spec->sl->sl_lines[], fileSystem @*/
{
Header h ;
speclines sl = spec - > sl ;
spectags st = spec - > st ;
const char * msgstr = NULL ;
int i , j ;
if ( sl = = NULL | | st = = NULL )
return ;
/*@-branchstate@*/
for ( i = 0 ; i < st - > st_ntags ; i + + ) {
spectag t = st - > st_t + i ;
const char * tn = tagName ( t - > t_tag ) ;
const char * errstr ;
char fmt [ 1024 ] ;
fmt [ 0 ] = ' \0 ' ;
if ( t - > t_msgid = = NULL )
h = spec - > packages - > header ;
else {
Package pkg ;
char * fe ;
strcpy ( fmt , t - > t_msgid ) ;
for ( fe = fmt ; * fe & & * fe ! = ' ( ' ; fe + + )
{ } ;
if ( * fe = = ' ( ' ) * fe = ' \0 ' ;
h = NULL ;
for ( pkg = spec - > packages ; pkg ! = NULL ; pkg = pkg - > next ) {
const char * pkgname ;
h = pkg - > header ;
( void ) headerNVR ( h , & pkgname , NULL , NULL ) ;
if ( ! strcmp ( pkgname , fmt ) )
/*@innerbreak@*/ break ;
}
if ( pkg = = NULL | | h = = NULL )
h = spec - > packages - > header ;
}
if ( h = = NULL )
continue ;
fmt [ 0 ] = ' \0 ' ;
( void ) stpcpy ( stpcpy ( stpcpy ( fmt , " %{ " ) , tn ) , " } " ) ;
msgstr = _free ( msgstr ) ;
2002-04-22 21:06:31 +04:00
/* XXX this should use queryHeader(), but prints out tn as well. */
2002-03-25 23:16:26 +03:00
msgstr = headerSprintf ( h , fmt , rpmTagTable , rpmHeaderFormats , & errstr ) ;
if ( msgstr = = NULL ) {
rpmError ( RPMERR_QFMT , _ ( " can't query %s: %s \n " ) , tn , errstr ) ;
return ;
}
switch ( t - > t_tag ) {
case RPMTAG_SUMMARY :
case RPMTAG_GROUP :
/*@-unqualifiedtrans@*/
sl - > sl_lines [ t - > t_startx ] = _free ( sl - > sl_lines [ t - > t_startx ] ) ;
/*@=unqualifiedtrans@*/
if ( t - > t_lang & & strcmp ( t - > t_lang , RPMBUILD_DEFAULT_LANG ) )
continue ;
{ char * buf = xmalloc ( strlen ( tn ) + sizeof ( " : " ) + strlen ( msgstr ) ) ;
( void ) stpcpy ( stpcpy ( stpcpy ( buf , tn ) , " : " ) , msgstr ) ;
sl - > sl_lines [ t - > t_startx ] = buf ;
}
/*@switchbreak@*/ break ;
case RPMTAG_DESCRIPTION :
for ( j = 1 ; j < t - > t_nlines ; j + + ) {
if ( * sl - > sl_lines [ t - > t_startx + j ] = = ' % ' )
/*@innercontinue@*/ continue ;
/*@-unqualifiedtrans@*/
sl - > sl_lines [ t - > t_startx + j ] =
_free ( sl - > sl_lines [ t - > t_startx + j ] ) ;
/*@=unqualifiedtrans@*/
}
if ( t - > t_lang & & strcmp ( t - > t_lang , RPMBUILD_DEFAULT_LANG ) ) {
sl - > sl_lines [ t - > t_startx ] = _free ( sl - > sl_lines [ t - > t_startx ] ) ;
continue ;
}
sl - > sl_lines [ t - > t_startx + 1 ] = xstrdup ( msgstr ) ;
if ( t - > t_nlines > 2 )
sl - > sl_lines [ t - > t_startx + 2 ] = xstrdup ( " \n \n " ) ;
/*@switchbreak@*/ break ;
}
}
/*@=branchstate@*/
msgstr = _free ( msgstr ) ;
for ( i = 0 ; i < sl - > sl_nlines ; i + + ) {
const char * s = sl - > sl_lines [ i ] ;
if ( s = = NULL )
continue ;
printf ( " %s " , s ) ;
if ( strchr ( s , ' \n ' ) = = NULL & & s [ strlen ( s ) - 1 ] ! = ' \n ' )
printf ( " \n " ) ;
}
}
void rpmDisplayQueryTags ( FILE * fp )
{
const struct headerTagTableEntry_s * t ;
int i ;
const struct headerSprintfExtension_s * ext = rpmHeaderFormats ;
for ( i = 0 , t = rpmTagTable ; i < rpmTagTableSize ; i + + , t + + )
if ( t - > name ) fprintf ( fp , " %s \n " , t - > name + 7 ) ;
while ( ext - > name ! = NULL ) {
if ( ext - > type = = HEADER_EXT_MORE ) {
ext = ext - > u . more ;
continue ;
}
/* XXX don't print query tags twice. */
for ( i = 0 , t = rpmTagTable ; i < rpmTagTableSize ; i + + , t + + ) {
if ( t - > name = = NULL ) /* XXX programmer error. */
/*@innercontinue@*/ continue ;
if ( ! strcmp ( t - > name , ext - > name ) )
/*@innerbreak@*/ break ;
}
if ( i > = rpmTagTableSize & & ext - > type = = HEADER_EXT_TAG )
fprintf ( fp , " %s \n " , ext - > name + 7 ) ;
ext + + ;
}
}
2002-07-20 14:12:10 +04:00
int showMatches ( QVA_t qva , rpmdbMatchIterator mi , QVF_t showPackage )
2002-03-25 23:16:26 +03:00
{
Header h ;
int ec = 0 ;
while ( ( h = rpmdbNextIterator ( mi ) ) ! = NULL ) {
int rc ;
/*@-nullpass@*/
if ( ( rc = showPackage ( qva , rpmdbGetIteratorRpmDB ( mi ) , h ) ) ! = 0 )
ec = rc ;
2006-09-17 03:27:20 +04:00
if ( qva - > qva_source = = RPMQV_DBOFFSET )
break ;
2002-03-25 23:16:26 +03:00
/*@=nullpass@*/
}
mi = rpmdbFreeIterator ( mi ) ;
return ec ;
}
/**
* Convert hex to binary nibble .
* @ param c hex character
* @ return binary nibble
*/
static inline unsigned char nibble ( char c )
/*@*/
{
if ( c > = ' 0 ' & & c < = ' 9 ' )
return ( c - ' 0 ' ) ;
if ( c > = ' A ' & & c < = ' F ' )
return ( c - ' A ' ) + 10 ;
if ( c > = ' a ' & & c < = ' f ' )
return ( c - ' a ' ) + 10 ;
return 0 ;
}
/*@-redecl@*/
/**
* @ todo Eliminate linkage loop into librpmbuild . a
*/
int ( * parseSpecVec ) ( Spec * specp , const char * specFile , const char * rootdir ,
const char * buildRoot , int recursing , const char * passPhrase ,
2002-03-26 02:19:22 +03:00
char * cookie , int anyarch , int force , int preprocess ) = NULL ;
2002-03-25 23:16:26 +03:00
/**
* @ todo Eliminate linkage loop into librpmbuild . a
*/
/*@null@*/ Spec ( * freeSpecVec ) ( Spec spec ) = NULL ;
/*@=redecl@*/
int rpmQueryVerify ( QVA_t qva , rpmQVSources source , const char * arg ,
rpmdb rpmdb , QVF_t showPackage )
{
rpmdbMatchIterator mi = NULL ;
Header h ;
int rc ;
int isSource ;
int retcode = 0 ;
2002-12-10 02:11:15 +03:00
const char * * av = NULL ;
2002-03-25 23:16:26 +03:00
char * end = NULL ;
const char * s ;
int i ;
switch ( source ) {
case RPMQV_RPM :
2002-12-10 02:11:15 +03:00
if ( rpmExpandNumeric ( " %{!?_disable_glob_query:%{?_enable_glob_query:1}} " ) )
2002-12-09 17:30:30 +03:00
{
2002-12-10 02:11:15 +03:00
int ac = 0 ;
const char * fileURL = NULL ;
rpmRC rpmrc ;
rc = rpmGlob ( arg , & ac , & av ) ;
if ( rc ) return 1 ;
restart :
for ( i = 0 ; i < ac ; i + + ) {
FD_t fd ;
fileURL = _free ( fileURL ) ;
fileURL = av [ i ] ;
av [ i ] = NULL ;
/* Try to read the header from a package file. */
fd = Fopen ( fileURL , " r.ufdio " ) ;
if ( fd = = NULL | | Ferror ( fd ) ) {
rpmError ( RPMERR_OPEN , _ ( " open of %s failed: %s \n " ) , fileURL ,
Fstrerror ( fd ) ) ;
if ( fd ) ( void ) Fclose ( fd ) ;
retcode = 1 ;
/*@loopbreak@*/ break ;
}
/*@-mustmod@*/ /* LCL: segfault. */
rpmrc = rpmReadPackageHeader ( fd , & h , & isSource , NULL , NULL ) ;
/*@=mustmod@*/
( void ) Fclose ( fd ) ;
if ( ! ( rpmrc = = RPMRC_OK | | rpmrc = = RPMRC_BADMAGIC ) ) {
rpmError ( RPMERR_QUERY , _ ( " query of %s failed \n " ) , fileURL ) ;
retcode = 1 ;
/*@loopbreak@*/ break ;
}
if ( rpmrc = = RPMRC_OK & & h = = NULL ) {
rpmError ( RPMERR_QUERY ,
_ ( " old format source packages cannot be queried \n " ) ) ;
retcode = 1 ;
/*@loopbreak@*/ break ;
}
/* Query a package file. */
if ( rpmrc = = RPMRC_OK ) {
retcode = showPackage ( qva , rpmdb , h ) ;
h = headerFree ( h ) ;
continue ;
}
/* Try to read a package manifest. */
fd = Fopen ( fileURL , " r.fpio " ) ;
if ( fd = = NULL | | Ferror ( fd ) ) {
rpmError ( RPMERR_OPEN , _ ( " open of %s failed: %s \n " ) , fileURL ,
Fstrerror ( fd ) ) ;
if ( fd ) ( void ) Fclose ( fd ) ;
retcode = 1 ;
/*@loopbreak@*/ break ;
}
/* Read list of packages from manifest. */
retcode = rpmReadPackageManifest ( fd , & ac , & av ) ;
if ( retcode ) {
rpmError ( RPMERR_MANIFEST , _ ( " %s: read manifest failed: %s \n " ) ,
fileURL , Fstrerror ( fd ) ) ;
retcode = 1 ;
}
( void ) Fclose ( fd ) ;
/* If successful, restart the query loop. */
if ( retcode = = 0 )
goto restart ;
/*@loopbreak@*/ break ;
}
fileURL = _free ( fileURL ) ;
if ( av ) {
for ( i = 0 ; i < ac ; i + + )
av [ i ] = _free ( av [ i ] ) ;
av = _free ( av ) ;
}
} else {
2002-12-09 17:30:30 +03:00
const char * fileURL = arg ;
2002-03-25 23:16:26 +03:00
rpmRC rpmrc ;
/* Try to read the header from a package file. */
2002-12-09 17:30:30 +03:00
FD_t fd = Fopen ( fileURL , " r.ufdio " ) ;
2002-03-25 23:16:26 +03:00
if ( fd = = NULL | | Ferror ( fd ) ) {
rpmError ( RPMERR_OPEN , _ ( " open of %s failed: %s \n " ) , fileURL ,
Fstrerror ( fd ) ) ;
if ( fd ) ( void ) Fclose ( fd ) ;
retcode = 1 ;
2002-12-09 17:30:30 +03:00
break ;
2002-03-25 23:16:26 +03:00
}
/*@-mustmod@*/ /* LCL: segfault. */
rpmrc = rpmReadPackageHeader ( fd , & h , & isSource , NULL , NULL ) ;
/*@=mustmod@*/
( void ) Fclose ( fd ) ;
2006-09-17 03:00:55 +04:00
if ( rpmrc = = RPMRC_BADMAGIC ) {
rpmError ( RPMERR_QUERY , _ ( " %s is not an RPM package \n " ) , fileURL ) ;
retcode = 1 ;
break ;
}
if ( rpmrc ! = RPMRC_OK ) {
2002-03-25 23:16:26 +03:00
rpmError ( RPMERR_QUERY , _ ( " query of %s failed \n " ) , fileURL ) ;
retcode = 1 ;
2002-12-09 17:30:30 +03:00
break ;
2002-03-25 23:16:26 +03:00
}
2006-09-17 03:00:55 +04:00
if ( h = = NULL ) {
2002-03-25 23:16:26 +03:00
rpmError ( RPMERR_QUERY ,
_ ( " old format source packages cannot be queried \n " ) ) ;
retcode = 1 ;
2002-12-09 17:30:30 +03:00
break ;
2002-03-25 23:16:26 +03:00
}
/* Query a package file. */
if ( rpmrc = = RPMRC_OK ) {
retcode = showPackage ( qva , rpmdb , h ) ;
h = headerFree ( h ) ;
2002-12-09 17:30:30 +03:00
break ;
2002-03-25 23:16:26 +03:00
}
} break ;
case RPMQV_SPECFILE :
if ( showPackage ! = showQueryPackage )
return 1 ;
/* XXX Eliminate linkage dependency loop */
if ( parseSpecVec = = NULL | | freeSpecVec = = NULL )
return 1 ;
{ Spec spec = NULL ;
Package pkg ;
char * buildRoot = NULL ;
int recursing = 0 ;
char * passPhrase = " " ;
char * cookie = NULL ;
int anyarch = 1 ;
int force = 1 ;
2002-03-26 02:19:22 +03:00
int preprocess = 0 ;
2002-03-25 23:16:26 +03:00
rc = parseSpecVec ( & spec , arg , " / " , buildRoot , recursing , passPhrase ,
2002-03-26 02:19:22 +03:00
cookie , anyarch , force , preprocess ) ;
2002-03-25 23:16:26 +03:00
if ( rc | | spec = = NULL ) {
rpmError ( RPMERR_QUERY ,
_ ( " query of specfile %s failed, can't parse \n " ) , arg ) ;
spec = freeSpecVec ( spec ) ;
retcode = 1 ;
break ;
}
if ( specedit ) {
printNewSpecfile ( spec ) ;
spec = freeSpecVec ( spec ) ;
retcode = 0 ;
break ;
}
for ( pkg = spec - > packages ; pkg ! = NULL ; pkg = pkg - > next )
( void ) showPackage ( qva , NULL , pkg - > header ) ;
spec = freeSpecVec ( spec ) ;
} break ;
case RPMQV_ALL :
/* RPMDBI_PACKAGES */
mi = rpmdbInitIterator ( rpmdb , RPMDBI_PACKAGES , NULL , 0 ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no packages \n " ) ) ;
retcode = 1 ;
} else {
for ( av = ( const char * * ) arg ; av & & * av ; av + + ) {
if ( ! rpmdbSetIteratorRE ( mi , RPMTAG_NAME , RPMMIRE_DEFAULT , * av ) )
continue ;
mi = rpmdbFreeIterator ( mi ) ;
retcode = 1 ;
/*@loopbreak@*/ break ;
}
if ( ! retcode )
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
break ;
case RPMQV_GROUP :
mi = rpmdbInitIterator ( rpmdb , RPMTAG_GROUP , arg , 0 ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO ,
_ ( " group %s does not contain any packages \n " ) , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
break ;
case RPMQV_TRIGGEREDBY :
mi = rpmdbInitIterator ( rpmdb , RPMTAG_TRIGGERNAME , arg , 0 ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no package triggers %s \n " ) , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
break ;
case RPMQV_PKGID :
{ unsigned char md5 [ 16 ] ;
unsigned char * t ;
for ( i = 0 , s = arg ; * s & & isxdigit ( * s ) ; s + + , i + + )
{ } ;
if ( i ! = 32 ) {
rpmError ( RPMERR_QUERYINFO , _ ( " malformed %s: %s \n " ) , " pkgid " , arg ) ;
return 1 ;
}
2002-03-30 19:02:41 +03:00
md5 [ 0 ] = ' \0 ' ;
2002-03-25 23:16:26 +03:00
for ( i = 0 , t = md5 , s = arg ; i < 16 ; i + + , t + + , s + = 2 )
* t = ( nibble ( s [ 0 ] ) < < 4 ) | nibble ( s [ 1 ] ) ;
2002-03-30 19:02:41 +03:00
mi = rpmdbInitIterator ( rpmdb , RPMTAG_SIGMD5 , md5 , sizeof ( md5 ) ) ;
2002-03-25 23:16:26 +03:00
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no package matches %s: %s \n " ) ,
" pkgid " , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
} break ;
case RPMQV_HDRID :
for ( i = 0 , s = arg ; * s & & isxdigit ( * s ) ; s + + , i + + )
{ } ;
if ( i ! = 40 ) {
rpmError ( RPMERR_QUERYINFO , _ ( " malformed %s: %s \n " ) , " hdrid " , arg ) ;
return 1 ;
}
mi = rpmdbInitIterator ( rpmdb , RPMTAG_SHA1HEADER , arg , 0 ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no package matches %s: %s \n " ) ,
" hdrid " , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
break ;
case RPMQV_FILEID :
2002-03-30 19:02:41 +03:00
{ unsigned char md5 [ 16 ] ;
unsigned char * t ;
2002-03-25 23:16:26 +03:00
for ( i = 0 , s = arg ; * s & & isxdigit ( * s ) ; s + + , i + + )
{ } ;
if ( i ! = 32 ) {
rpmError ( RPMERR_QUERY , _ ( " malformed %s: %s \n " ) , " fileid " , arg ) ;
return 1 ;
}
2002-03-30 19:02:41 +03:00
md5 [ 0 ] = ' \0 ' ;
for ( i = 0 , t = md5 , s = arg ; i < 16 ; i + + , t + + , s + = 2 )
* t = ( nibble ( s [ 0 ] ) < < 4 ) | nibble ( s [ 1 ] ) ;
mi = rpmdbInitIterator ( rpmdb , RPMTAG_FILEMD5S , md5 , sizeof ( md5 ) ) ;
2002-03-25 23:16:26 +03:00
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no package matches %s: %s \n " ) ,
" fileid " , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
2002-03-30 19:02:41 +03:00
} break ;
2002-03-25 23:16:26 +03:00
case RPMQV_TID :
{ int mybase = 10 ;
const char * myarg = arg ;
unsigned iid ;
/* XXX should be in strtoul */
if ( * myarg = = ' 0 ' ) {
myarg + + ;
mybase = 8 ;
if ( * myarg = = ' x ' ) {
myarg + + ;
mybase = 16 ;
}
}
iid = strtoul ( myarg , & end , mybase ) ;
if ( ( * end ) | | ( end = = arg ) | | ( iid = = ULONG_MAX ) ) {
rpmError ( RPMERR_QUERY , _ ( " malformed %s: %s \n " ) , " tid " , arg ) ;
return 1 ;
}
mi = rpmdbInitIterator ( rpmdb , RPMTAG_INSTALLTID , & iid , sizeof ( iid ) ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no package matches %s: %s \n " ) ,
" tid " , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
} break ;
case RPMQV_WHATREQUIRES :
mi = rpmdbInitIterator ( rpmdb , RPMTAG_REQUIRENAME , arg , 0 ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " no package requires %s \n " ) , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
break ;
case RPMQV_WHATPROVIDES :
2002-03-30 19:02:41 +03:00
mi = rpmdbInitIterator ( rpmdb , RPMTAG_PROVIDENAME , arg , 0 ) ;
if ( mi = = NULL ) {
if ( arg [ 0 ] ! = ' / ' )
2002-03-25 23:16:26 +03:00
rpmError ( RPMERR_QUERYINFO , _ ( " no package provides %s \n " ) , arg ) ;
2002-03-30 19:02:41 +03:00
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-30 19:02:41 +03:00
}
2002-03-26 02:19:22 +03:00
if ( arg [ 0 ] ! = ' / ' )
2002-03-25 23:16:26 +03:00
break ;
/*@fallthrough@*/
case RPMQV_PATH :
{ char * fn ;
for ( s = arg ; * s ! = ' \0 ' ; s + + )
if ( ! ( * s = = ' . ' | | * s = = ' / ' ) )
/*@loopbreak@*/ break ;
if ( * s = = ' \0 ' ) {
char fnbuf [ PATH_MAX ] ;
fn = /*@-unrecog@*/ realpath ( arg , fnbuf ) /*@=unrecog@*/ ;
if ( fn )
fn = xstrdup ( fn ) ;
else
fn = xstrdup ( arg ) ;
} else
fn = xstrdup ( arg ) ;
( void ) rpmCleanPath ( fn ) ;
mi = rpmdbInitIterator ( rpmdb , RPMTAG_BASENAMES , fn , 0 ) ;
if ( mi = = NULL ) {
int myerrno = 0 ;
if ( access ( fn , F_OK ) ! = 0 )
myerrno = errno ;
switch ( myerrno ) {
default :
rpmError ( RPMERR_QUERY ,
_ ( " file %s: %s \n " ) , fn , strerror ( myerrno ) ) ;
break ;
case 0 :
2002-03-26 02:19:22 +03:00
switch ( source )
{
2002-07-20 14:12:10 +04:00
case RPMQV_PATH :
2002-03-26 02:19:22 +03:00
rpmError ( RPMERR_QUERYINFO ,
_ ( " file %s is not owned by any package \n " ) , fn ) ;
break ;
2002-07-20 15:02:13 +04:00
default :
if ( retcode ) rpmError ( RPMERR_QUERYINFO ,
_ ( " no package provides %s \n " ) , fn ) ;
break ;
2002-03-26 02:19:22 +03:00
}
2002-03-25 23:16:26 +03:00
break ;
}
2002-03-26 02:19:22 +03:00
if ( RPMQV_PATH = = source )
2002-03-25 23:16:26 +03:00
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
fn = _free ( fn ) ;
} break ;
case RPMQV_DBOFFSET :
{ int mybase = 10 ;
const char * myarg = arg ;
unsigned recOffset ;
/* XXX should be in strtoul */
if ( * myarg = = ' 0 ' ) {
myarg + + ;
mybase = 8 ;
if ( * myarg = = ' x ' ) {
myarg + + ;
mybase = 16 ;
}
}
recOffset = strtoul ( myarg , & end , mybase ) ;
if ( ( * end ) | | ( end = = arg ) | | ( recOffset = = ULONG_MAX ) ) {
rpmError ( RPMERR_QUERYINFO , _ ( " invalid package number: %s \n " ) , arg ) ;
return 1 ;
}
rpmMessage ( RPMMESS_DEBUG , _ ( " package record number: %u \n " ) , recOffset ) ;
mi = rpmdbInitIterator ( rpmdb , RPMDBI_PACKAGES , & recOffset , sizeof ( recOffset ) ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO ,
_ ( " record %u could not be read \n " ) , recOffset ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
} break ;
case RPMQV_PACKAGE :
/* XXX HACK to get rpmdbFindByLabel out of the API */
mi = rpmdbInitIterator ( rpmdb , RPMDBI_LABEL , arg , 0 ) ;
if ( mi = = NULL ) {
rpmError ( RPMERR_QUERYINFO , _ ( " package %s is not installed \n " ) , arg ) ;
retcode = 1 ;
} else {
2002-07-20 14:12:10 +04:00
retcode = showMatches ( qva , mi , showPackage ) ;
2002-03-25 23:16:26 +03:00
}
break ;
}
return retcode ;
}
int rpmQuery ( QVA_t qva , rpmQVSources source , const char * arg )
{
rpmdb rpmdb = NULL ;
int rc ;
switch ( source ) {
case RPMQV_RPM :
case RPMQV_SPECFILE :
break ;
default :
if ( rpmdbOpen ( qva - > qva_prefix , & rpmdb , O_RDONLY , 0644 ) )
return 1 ;
break ;
}
rc = rpmQueryVerify ( qva , source , arg , rpmdb , showQueryPackage ) ;
if ( rpmdb ! = NULL )
( void ) rpmdbClose ( rpmdb ) ;
return rc ;
}