2002-03-25 23:16:26 +03:00
/** \ingroup python
* \ file python / db - py . c
*/
2002-06-05 15:06:46 +04:00
# include <sys/time.h>
2002-03-25 23:16:26 +03:00
# include <fcntl.h>
# include <unistd.h>
# include "Python.h"
# include "rpmio_internal.h"
# include "rpmcli.h" /* XXX for rpmCheckSig */
# include "misc.h"
# include "header_internal.h"
# include "upgrade.h"
# include "db-py.h"
# include "header-py.h"
/** \ingroup python
*/
typedef struct rpmdbMIObject_s rpmdbMIObject ;
/** \ingroup python
* \ class rpmdbMatchIterator
* \ brief A python rpmdbMatchIterator object represents the result of an RPM
* database query .
*/
/** \ingroup python
* \ name Class : rpmdbMatchIterator
*/
/*@{*/
/** \ingroup python
*/
struct rpmdbMIObject_s {
PyObject_HEAD ;
rpmdbObject * db ;
rpmdbMatchIterator mi ;
} ;
/** \ingroup python
*/
static PyObject *
rpmdbMINext ( rpmdbMIObject * s , PyObject * args ) {
/* XXX assume header? */
Header h ;
hdrObject * ho ;
if ( ! PyArg_ParseTuple ( args , " " ) ) return NULL ;
h = rpmdbNextIterator ( s - > mi ) ;
if ( ! h ) {
Py_INCREF ( Py_None ) ;
return Py_None ;
}
ho = createHeaderObject ( h ) ;
return ( PyObject * ) ho ;
}
/** \ingroup python
*/
static PyObject *
rpmdbMIpattern ( rpmdbMIObject * s , PyObject * args ) {
PyObject * index = NULL ;
int type ;
char * pattern ;
int tag ;
if ( ! PyArg_ParseTuple ( args , " Ois " , & index , & type , & pattern ) )
return NULL ;
if ( index = = NULL )
tag = 0 ;
else if ( ( tag = tagNumFromPyObject ( index ) ) = = - 1 ) {
PyErr_SetString ( PyExc_TypeError , " unknown tag type " ) ;
return NULL ;
}
rpmdbSetIteratorRE ( s - > mi , tag , type , pattern ) ;
Py_INCREF ( Py_None ) ;
return Py_None ;
}
/** \ingroup python
*/
static struct PyMethodDef rpmdbMIMethods [ ] = {
{ " next " , ( PyCFunction ) rpmdbMINext , 1 } ,
{ " pattern " , ( PyCFunction ) rpmdbMIpattern , 1 } ,
{ NULL , NULL } /* sentinel */
} ;
/** \ingroup python
*/
static PyObject * rpmdbMIGetAttr ( rpmdbObject * s , char * name ) {
return Py_FindMethod ( rpmdbMIMethods , ( PyObject * ) s , name ) ;
}
/** \ingroup python
*/
static void rpmdbMIDealloc ( rpmdbMIObject * s ) {
if ( s & & s - > mi ) {
rpmdbFreeIterator ( s - > mi ) ;
}
Py_DECREF ( s - > db ) ;
PyMem_DEL ( s ) ;
}
/** \ingroup python
*/
PyTypeObject rpmdbMIType = {
PyObject_HEAD_INIT ( NULL )
0 , /* ob_size */
" rpmdbMatchIterator " , /* tp_name */
sizeof ( rpmdbMIObject ) , /* tp_size */
0 , /* tp_itemsize */
( destructor ) rpmdbMIDealloc , /* tp_dealloc */
0 , /* tp_print */
( getattrfunc ) rpmdbMIGetAttr , /* tp_getattr */
0 , /* tp_setattr */
0 , /* tp_compare */
0 , /* tp_repr */
0 , /* tp_as_number */
0 , /* tp_as_sequence */
0 , /* tp_as_mapping */
} ;
/*@}*/
/** \ingroup python
* \ class rpmdb
* \ brief A python rpmdb object represents an RPM database .
*
* Instances of the rpmdb object provide access to the records of a
* RPM database . The records are accessed by index number . To
* retrieve the header data in the RPM database , the rpmdb object is
* subscripted as you would access members of a list .
*
* The rpmdb class contains the following methods :
*
* - firstkey ( ) Returns the index of the first record in the database .
* @ deprecated Legacy , use rpmdbMatchIterator instead .
*
* - nextkey ( index ) Returns the index of the next record after " index " in the
* database .
* @ param index current rpmdb location
* @ deprecated Legacy , use rpmdbMatchIterator instead .
*
* - findbyfile ( file ) Returns a list of the indexes to records that own file
* " file " .
* @ param file absolute path to file
*
* - findbyname ( name ) Returns a list of the indexes to records for packages
* named " name " .
* @ param name package name
*
* - findbyprovides ( dep ) Returns a list of the indexes to records for packages
* that provide " dep " .
* @ param dep provided dependency string
*
* To obtain a rpmdb object , the opendb function in the rpm module
* must be called . The opendb function takes two optional arguments .
* The first optional argument is a boolean flag that specifies if the
* database is to be opened for read / write access or read - only access .
* The second argument specifies an alternate root directory for RPM
* to use .
*
* An example of opening a database and retrieving the first header in
* the database , then printing the name of the package that the header
* represents :
* \ code
* import rpm
* rpmdb = rpm . opendb ( )
* index = rpmdb . firstkey ( )
* header = rpmdb [ index ]
* print header [ rpm . RPMTAG_NAME ]
* \ endcode
* To print all of the packages in the database that match a package
* name , the code will look like this :
* \ code
* import rpm
* rpmdb = rpm . opendb ( )
* indexes = rpmdb . findbyname ( " foo " )
* for index in indexes :
* header = rpmdb [ index ]
* print " %s-%s-%s " % ( header [ rpm . RPMTAG_NAME ] ,
* header [ rpm . RPMTAG_VERSION ] ,
* header [ rpm . RPMTAG_RELEASE ] )
* \ endcode
*/
/** \ingroup python
* \ name Class : rpmdb
*/
/*@{*/
/**
*/
static PyObject * rpmdbFirst ( rpmdbObject * s , PyObject * args ) {
int first ;
if ( ! PyArg_ParseTuple ( args , " " ) ) return NULL ;
/* Acquire all offsets in one fell swoop. */
if ( s - > offsets = = NULL | | s - > noffs < = 0 ) {
rpmdbMatchIterator mi ;
Header h ;
if ( s - > offsets )
free ( s - > offsets ) ;
s - > offsets = NULL ;
s - > noffs = 0 ;
mi = rpmdbInitIterator ( s - > db , RPMDBI_PACKAGES , NULL , 0 ) ;
while ( ( h = rpmdbNextIterator ( mi ) ) ! = NULL ) {
s - > noffs + + ;
s - > offsets = realloc ( s - > offsets , s - > noffs * sizeof ( s - > offsets [ 0 ] ) ) ;
s - > offsets [ s - > noffs - 1 ] = rpmdbGetIteratorOffset ( mi ) ;
}
rpmdbFreeIterator ( mi ) ;
}
s - > offx = 0 ;
if ( s - > offsets ! = NULL & & s - > offx < s - > noffs )
first = s - > offsets [ s - > offx + + ] ;
else
first = 0 ;
if ( ! first ) {
PyErr_SetString ( pyrpmError , " cannot find first entry in database \n " ) ;
return NULL ;
}
return Py_BuildValue ( " i " , first ) ;
}
/**
*/
static PyObject * rpmdbNext ( rpmdbObject * s , PyObject * args ) {
int where ;
if ( ! PyArg_ParseTuple ( args , " i " , & where ) ) return NULL ;
if ( s - > offsets = = NULL | | s - > offx > = s - > noffs ) {
Py_INCREF ( Py_None ) ;
return Py_None ;
}
where = s - > offsets [ s - > offx + + ] ;
if ( ! where ) {
Py_INCREF ( Py_None ) ;
return Py_None ;
}
return Py_BuildValue ( " i " , where ) ;
}
/**
*/
static PyObject * handleDbResult ( rpmdbMatchIterator mi ) {
PyObject * list , * o ;
list = PyList_New ( 0 ) ;
/* XXX FIXME: unnecessary header mallocs are side effect here */
if ( mi ! = NULL ) {
while ( rpmdbNextIterator ( mi ) ) {
PyList_Append ( list , o = PyInt_FromLong ( rpmdbGetIteratorOffset ( mi ) ) ) ;
Py_DECREF ( o ) ;
}
rpmdbFreeIterator ( mi ) ;
}
return list ;
}
/**
*/
static PyObject * rpmdbByFile ( rpmdbObject * s , PyObject * args ) {
char * str ;
if ( ! PyArg_ParseTuple ( args , " s " , & str ) ) return NULL ;
return handleDbResult ( rpmdbInitIterator ( s - > db , RPMTAG_BASENAMES , str , 0 ) ) ;
}
/**
*/
static PyObject * rpmdbByName ( rpmdbObject * s , PyObject * args ) {
char * str ;
if ( ! PyArg_ParseTuple ( args , " s " , & str ) ) return NULL ;
return handleDbResult ( rpmdbInitIterator ( s - > db , RPMTAG_NAME , str , 0 ) ) ;
}
/**
*/
static PyObject * rpmdbByProvides ( rpmdbObject * s , PyObject * args ) {
char * str ;
if ( ! PyArg_ParseTuple ( args , " s " , & str ) ) return NULL ;
return handleDbResult ( rpmdbInitIterator ( s - > db , RPMTAG_PROVIDENAME , str , 0 ) ) ;
}
/**
*/
static rpmdbMIObject *
py_rpmdbInitIterator ( rpmdbObject * s , PyObject * args ) {
PyObject * index = NULL ;
char * key = NULL ;
int len = 0 , tag = - 1 ;
rpmdbMIObject * mio ;
if ( ! PyArg_ParseTuple ( args , " |Ozi " , & index , & key , & len ) )
return NULL ;
if ( index = = NULL )
tag = 0 ;
else if ( ( tag = tagNumFromPyObject ( index ) ) = = - 1 ) {
PyErr_SetString ( PyExc_TypeError , " unknown tag type " ) ;
return NULL ;
}
mio = ( rpmdbMIObject * ) PyObject_NEW ( rpmdbMIObject , & rpmdbMIType ) ;
if ( mio = = NULL ) {
PyErr_SetString ( pyrpmError , " out of memory creating rpmdbMIObject " ) ;
return NULL ;
}
mio - > mi = rpmdbInitIterator ( s - > db , tag , key , len ) ;
mio - > db = s ;
Py_INCREF ( mio - > db ) ;
return mio ;
}
/**
*/
static struct PyMethodDef rpmdbMethods [ ] = {
{ " firstkey " , ( PyCFunction ) rpmdbFirst , 1 } ,
{ " nextkey " , ( PyCFunction ) rpmdbNext , 1 } ,
{ " findbyfile " , ( PyCFunction ) rpmdbByFile , 1 } ,
{ " findbyname " , ( PyCFunction ) rpmdbByName , 1 } ,
{ " findbyprovides " , ( PyCFunction ) rpmdbByProvides , 1 } ,
{ " match " , ( PyCFunction ) py_rpmdbInitIterator , 1 } ,
{ NULL , NULL } /* sentinel */
} ;
/**
*/
static PyObject * rpmdbGetAttr ( rpmdbObject * s , char * name ) {
return Py_FindMethod ( rpmdbMethods , ( PyObject * ) s , name ) ;
}
/**
*/
static void rpmdbDealloc ( rpmdbObject * s ) {
if ( s - > offsets ) {
free ( s - > offsets ) ;
}
if ( s - > db ) {
rpmdbClose ( s - > db ) ;
}
PyMem_DEL ( s ) ;
}
# ifndef DYINGSOON /* XXX OK, when? */
/**
*/
static int
rpmdbLength ( rpmdbObject * s ) {
int count = 0 ;
{ rpmdbMatchIterator mi ;
/* RPMDBI_PACKAGES */
mi = rpmdbInitIterator ( s - > db , RPMDBI_PACKAGES , NULL , 0 ) ;
while ( rpmdbNextIterator ( mi ) ! = NULL )
count + + ;
rpmdbFreeIterator ( mi ) ;
}
return count ;
}
/**
*/
static hdrObject *
rpmdbSubscript ( rpmdbObject * s , PyObject * key ) {
int offset ;
hdrObject * ho ;
Header h ;
rpmdbMatchIterator mi ;
if ( ! PyInt_Check ( key ) ) {
PyErr_SetString ( PyExc_TypeError , " integer expected " ) ;
return NULL ;
}
offset = ( int ) PyInt_AsLong ( key ) ;
mi = rpmdbInitIterator ( s - > db , RPMDBI_PACKAGES , & offset , sizeof ( offset ) ) ;
if ( ! ( h = rpmdbNextIterator ( mi ) ) ) {
rpmdbFreeIterator ( mi ) ;
PyErr_SetString ( pyrpmError , " cannot read rpmdb entry " ) ;
return NULL ;
}
ho = createHeaderObject ( h ) ;
2002-06-05 14:58:55 +04:00
rpmdbFreeIterator ( mi ) ;
2002-03-25 23:16:26 +03:00
return ho ;
}
/**
*/
static PyMappingMethods rpmdbAsMapping = {
( inquiry ) rpmdbLength , /* mp_length */
( binaryfunc ) rpmdbSubscript , /* mp_subscript */
( objobjargproc ) 0 , /* mp_ass_subscript */
} ;
# endif
/**
*/
PyTypeObject rpmdbType = {
PyObject_HEAD_INIT ( NULL )
0 , /* ob_size */
" rpmdb " , /* tp_name */
sizeof ( rpmdbObject ) , /* tp_size */
0 , /* tp_itemsize */
( destructor ) rpmdbDealloc , /* tp_dealloc */
0 , /* tp_print */
( getattrfunc ) rpmdbGetAttr , /* tp_getattr */
0 , /* tp_setattr */
0 , /* tp_compare */
0 , /* tp_repr */
0 , /* tp_as_number */
0 , /* tp_as_sequence */
# ifndef DYINGSOON
& rpmdbAsMapping , /* tp_as_mapping */
# else
0 ,
# endif
} ;
/*@}*/
rpmdb dbFromDb ( rpmdbObject * db ) {
return db - > db ;
}
/**
*/
rpmdbObject * rpmOpenDB ( PyObject * self , PyObject * args ) {
rpmdbObject * o ;
char * root = " " ;
int forWrite = 0 ;
if ( ! PyArg_ParseTuple ( args , " |is " , & forWrite , & root ) ) return NULL ;
o = PyObject_NEW ( rpmdbObject , & rpmdbType ) ;
o - > db = NULL ;
o - > offx = 0 ;
o - > noffs = 0 ;
o - > offsets = NULL ;
if ( rpmdbOpen ( root , & o - > db , forWrite ? O_RDWR | O_CREAT : O_RDONLY , 0644 ) ) {
char * errmsg = " cannot open database in %s " ;
char * errstr = NULL ;
int errsize ;
Py_DECREF ( o ) ;
/* PyErr_SetString should take varargs... */
errsize = strlen ( errmsg ) + * root = = ' \0 ' ? 15 /* "/var/lib/rpm" */ : strlen ( root ) ;
errstr = alloca ( errsize ) ;
snprintf ( errstr , errsize , errmsg , * root = = ' \0 ' ? " /var/lib/rpm " : root ) ;
PyErr_SetString ( pyrpmError , errstr ) ;
return NULL ;
}
return o ;
}
/**
*/
PyObject * rebuildDB ( PyObject * self , PyObject * args ) {
char * root = " " ;
if ( ! PyArg_ParseTuple ( args , " s " , & root ) ) return NULL ;
return Py_BuildValue ( " i " , rpmdbRebuild ( root ) ) ;
}