1999-10-01 15:15:25 +08:00
|
|
|
#############################################################################
|
2005-11-28 05:49:15 +08:00
|
|
|
# File : Pkg.py
|
|
|
|
# Package : rpmlint
|
|
|
|
# Author : Frederic Lepied
|
|
|
|
# Created on : Tue Sep 28 07:18:06 1999
|
|
|
|
# Version : $Id$
|
|
|
|
# Purpose : provide an API to handle a rpm package either by accessing
|
2006-04-01 16:09:17 +08:00
|
|
|
# the rpm file or by accessing the files contained inside.
|
1999-10-01 15:15:25 +08:00
|
|
|
#############################################################################
|
|
|
|
|
|
|
|
import os
|
|
|
|
import rpm
|
|
|
|
import os.path
|
|
|
|
import stat
|
|
|
|
import commands
|
2006-09-15 06:18:32 +08:00
|
|
|
import popen2
|
1999-10-01 15:15:25 +08:00
|
|
|
import re
|
|
|
|
import string
|
2007-05-14 03:15:39 +08:00
|
|
|
import tempfile
|
2000-02-28 22:35:17 +08:00
|
|
|
import types
|
2005-09-11 07:23:20 +08:00
|
|
|
import sys
|
1999-10-01 15:15:25 +08:00
|
|
|
|
2006-08-26 21:22:08 +08:00
|
|
|
from Filter import printWarning
|
|
|
|
|
1999-10-06 20:35:40 +08:00
|
|
|
RPMFILE_CONFIG=(1 << 0)
|
|
|
|
RPMFILE_DOC=(1 << 1)
|
|
|
|
RPMFILE_DONOTUSE=(1 << 2)
|
|
|
|
RPMFILE_MISSINGOK=(1 << 3)
|
|
|
|
RPMFILE_NOREPLACE=(1 << 4)
|
|
|
|
RPMFILE_SPECFILE=(1 << 5)
|
|
|
|
RPMFILE_GHOST=(1 << 6)
|
|
|
|
RPMFILE_LICENSE=(1 << 7)
|
|
|
|
RPMFILE_README=(1 << 8)
|
|
|
|
|
2000-02-23 14:40:36 +08:00
|
|
|
# check if we use a rpm version compatible with 3.0.4
|
|
|
|
try:
|
|
|
|
if rpm.RPMTAG_OLDFILENAMES:
|
|
|
|
v304=1
|
|
|
|
except AttributeError:
|
|
|
|
v304=0
|
2000-06-15 20:07:22 +08:00
|
|
|
|
2005-06-18 21:02:56 +08:00
|
|
|
try:
|
|
|
|
if rpm.RPMSENSE_SCRIPT_PRE:
|
2005-08-10 13:05:21 +08:00
|
|
|
PREREQ_FLAG=rpm.RPMSENSE_PREREQ|rpm.RPMSENSE_SCRIPT_PRE|rpm.RPMSENSE_SCRIPT_POST|rpm.RPMSENSE_SCRIPT_PREUN|rpm.RPMSENSE_SCRIPT_POSTUN
|
2005-06-18 21:02:56 +08:00
|
|
|
except AttributeError:
|
2005-08-10 13:05:21 +08:00
|
|
|
PREREQ_FLAG=rpm.RPMSENSE_PREREQ
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2003-02-01 06:05:01 +08:00
|
|
|
# check if we use a rpm version compatible with 4.2
|
2006-06-21 02:09:45 +08:00
|
|
|
v42 = 0
|
2003-02-01 06:05:01 +08:00
|
|
|
try:
|
2006-06-21 02:09:45 +08:00
|
|
|
if rpm.RPMTAG_DISTTAG: # in >= 4.4
|
|
|
|
v42 = 1
|
2003-02-01 06:05:01 +08:00
|
|
|
except AttributeError:
|
2006-06-21 02:09:45 +08:00
|
|
|
try:
|
|
|
|
if rpm.RPMTAG_SOURCEPACKAGE: # in 4.2 but not in 4.4.something (6?)
|
|
|
|
v42 = 1
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2001-11-26 05:32:34 +08:00
|
|
|
# utilities
|
|
|
|
|
2006-10-12 00:53:41 +08:00
|
|
|
var_regex=re.compile('^(.*)\${?(\w+)}?(.*)$')
|
|
|
|
|
2001-11-26 05:32:34 +08:00
|
|
|
def shell_var_value(var, script):
|
2006-10-12 00:52:20 +08:00
|
|
|
assign_regex=re.compile('\\b' + re.escape(var) + '\s*=\s*(.+)\s*(#.*)*$',
|
2003-07-23 03:31:39 +08:00
|
|
|
re.MULTILINE)
|
2001-11-26 05:32:34 +08:00
|
|
|
res=assign_regex.search(script)
|
|
|
|
if res:
|
2006-10-12 00:53:41 +08:00
|
|
|
res2 = var_regex.search(res.group(1))
|
|
|
|
if res2:
|
|
|
|
if res2.group(2) == var: # infinite loop
|
|
|
|
return None
|
2001-11-26 05:32:34 +08:00
|
|
|
return substitute_shell_vars(res.group(1), script)
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def substitute_shell_vars(val, script):
|
|
|
|
res=var_regex.search(val)
|
|
|
|
if res:
|
|
|
|
value=shell_var_value(res.group(2), script)
|
|
|
|
if not value:
|
|
|
|
value=''
|
|
|
|
return res.group(1) + value + substitute_shell_vars(res.group(3), script)
|
|
|
|
else:
|
|
|
|
return val
|
|
|
|
|
2006-09-15 06:18:32 +08:00
|
|
|
def getstatusoutput(cmd, stdoutonly=0):
|
|
|
|
'''A version of commands.getstatusoutput() which can take cmd as a
|
|
|
|
sequence, thus making it potentially more secure. See popen2.'''
|
|
|
|
if stdoutonly:
|
|
|
|
proc = popen2.Popen3(cmd)
|
|
|
|
else:
|
|
|
|
proc = popen2.Popen4(cmd)
|
|
|
|
proc.tochild.close()
|
|
|
|
text = proc.fromchild.read()
|
|
|
|
sts = proc.wait()
|
|
|
|
if sts is None: sts = 0
|
|
|
|
if text[-1:] == '\n': text = text[:-1]
|
|
|
|
return sts, text
|
|
|
|
|
2006-01-15 17:59:04 +08:00
|
|
|
bz2_regex=re.compile('\.t?bz2?$')
|
|
|
|
|
2007-03-16 03:15:27 +08:00
|
|
|
# TODO: is_utf8 could probably be implemented natively without iconv...
|
2006-01-15 17:59:04 +08:00
|
|
|
|
|
|
|
def is_utf8(fname):
|
|
|
|
cat='gzip -dcf'
|
|
|
|
if bz2_regex.search(fname): cat='bzip2 -dcf'
|
2006-09-15 06:18:32 +08:00
|
|
|
# TODO: better shell escaping or sequence based command invocation
|
|
|
|
cmd = commands.getstatusoutput('%s "%s" | iconv -f utf-8 -t utf-8 -o /dev/null' % (cat, fname))
|
2006-01-15 17:59:04 +08:00
|
|
|
return not cmd[0]
|
|
|
|
|
|
|
|
def is_utf8_str(s):
|
2007-03-16 03:15:27 +08:00
|
|
|
try:
|
|
|
|
s.decode('UTF-8')
|
|
|
|
except:
|
|
|
|
return 0
|
|
|
|
return 1
|
2006-01-15 17:59:04 +08:00
|
|
|
|
2007-05-14 03:15:39 +08:00
|
|
|
def readlines(path):
|
|
|
|
fobj = open(file, "r")
|
|
|
|
try:
|
|
|
|
return fobj.readlines()
|
|
|
|
finally:
|
|
|
|
fobj.close()
|
|
|
|
|
|
|
|
def mktemp():
|
|
|
|
suffix = ".rpmlint%s" % os.getpid()
|
|
|
|
if hasattr(tempfile, "mkstemp"): # Python >= 2.3
|
|
|
|
tmpfd, tmpname = tempfile.mkstemp(suffix)
|
|
|
|
tmpfile = os.fdopen(tmpfd, 'w')
|
|
|
|
else:
|
|
|
|
tmpname = tempfile.mktemp(suffix)
|
|
|
|
tmpfile = open(tmpname, 'w')
|
|
|
|
return tmpfile, tmpname
|
|
|
|
|
2001-11-26 05:32:34 +08:00
|
|
|
# classes representing package
|
|
|
|
|
1999-10-01 15:15:25 +08:00
|
|
|
class Pkg:
|
2002-06-04 12:07:34 +08:00
|
|
|
file_regex=re.compile('(?:\.)?([^:]+):\s+(.*)')
|
1999-10-01 15:15:25 +08:00
|
|
|
|
2001-06-07 00:18:31 +08:00
|
|
|
def __init__(self, filename, dirname, header=None, is_source=0):
|
2005-11-28 05:49:15 +08:00
|
|
|
self.filename=filename
|
|
|
|
self.extracted=0
|
|
|
|
self.dirname=dirname
|
|
|
|
self.file_info=None
|
|
|
|
self._config_files=None
|
|
|
|
self._doc_files=None
|
|
|
|
self._ghost_files=None
|
|
|
|
self._files=None
|
|
|
|
self._requires=None
|
2001-02-17 00:36:10 +08:00
|
|
|
self._req_names=-1
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-10-17 02:51:12 +08:00
|
|
|
if header:
|
|
|
|
self.header=header
|
2001-06-07 00:18:31 +08:00
|
|
|
self.is_source=is_source
|
2000-10-17 02:51:12 +08:00
|
|
|
else:
|
|
|
|
# Create a package object from the file name
|
2003-02-01 06:05:01 +08:00
|
|
|
if v42:
|
|
|
|
ts=rpm.TransactionSet()
|
2003-04-23 21:32:46 +08:00
|
|
|
# Don't check signatures here...
|
|
|
|
ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES)
|
2007-05-14 03:15:39 +08:00
|
|
|
fd = os.open(filename, os.O_RDONLY)
|
|
|
|
try:
|
|
|
|
self.header = ts.hdrFromFdno(fd)
|
|
|
|
finally:
|
|
|
|
os.close(fd)
|
2006-06-21 02:09:45 +08:00
|
|
|
self.is_source = not self.header[rpm.RPMTAG_SOURCERPM]
|
2003-02-01 06:05:01 +08:00
|
|
|
else:
|
2007-05-14 03:15:39 +08:00
|
|
|
fd = os.open(filename, os.O_RDONLY)
|
|
|
|
try:
|
|
|
|
(self.header, self.is_source) = rpm.headerFromPackage(fd)
|
|
|
|
finally:
|
|
|
|
os.close(fd)
|
2000-10-17 02:51:12 +08:00
|
|
|
|
2000-08-18 13:39:25 +08:00
|
|
|
self._lang_files=None
|
1999-10-01 15:15:25 +08:00
|
|
|
|
2005-11-28 05:49:15 +08:00
|
|
|
self.name=self.header[rpm.RPMTAG_NAME]
|
1999-10-06 21:00:23 +08:00
|
|
|
|
2003-03-25 20:11:32 +08:00
|
|
|
# Return true if the package is a source package
|
1999-10-01 15:15:25 +08:00
|
|
|
def isSource(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
return self.is_source
|
1999-10-06 21:00:23 +08:00
|
|
|
|
2003-03-25 20:11:32 +08:00
|
|
|
# Return true if the package is a nosource package.
|
|
|
|
# NoSource files are ghosts in source packages.
|
|
|
|
def isNoSource(self):
|
|
|
|
return self.is_source and self.ghostFiles()
|
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# access the tags like an array
|
1999-10-01 15:15:25 +08:00
|
|
|
def __getitem__(self, key):
|
2006-01-09 21:19:34 +08:00
|
|
|
try:
|
|
|
|
val = self.header[key]
|
|
|
|
except:
|
|
|
|
val = []
|
2004-01-19 19:25:36 +08:00
|
|
|
if val == []:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return val
|
1999-10-01 15:15:25 +08:00
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# return the name of the directory where the package is extracted
|
1999-10-01 15:15:25 +08:00
|
|
|
def dirName(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if not self.extracted:
|
|
|
|
self._extract()
|
|
|
|
return self.dirname
|
1999-10-01 15:15:25 +08:00
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# handle the extract phasis
|
1999-10-01 15:15:25 +08:00
|
|
|
def _extract(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
s=os.stat(self.dirname)
|
1999-10-01 15:15:25 +08:00
|
|
|
if not stat.S_ISDIR(s[stat.ST_MODE]):
|
2005-09-11 07:23:20 +08:00
|
|
|
sys.stderr.write('unable to access dir %s\n' % self.dirname)
|
2001-11-15 00:34:02 +08:00
|
|
|
return None
|
1999-10-01 15:15:25 +08:00
|
|
|
else:
|
2002-06-04 12:07:34 +08:00
|
|
|
self.dirname = '%s/%s.%d' % (self.dirname, os.path.basename(self.filename), os.getpid())
|
1999-10-01 15:15:25 +08:00
|
|
|
os.mkdir(self.dirname)
|
2006-09-15 06:18:32 +08:00
|
|
|
# TODO: better shell escaping or sequence based command invocation
|
|
|
|
command_str='rpm2cpio "%s" | (cd "%s"; cpio -id); chmod -R +rX "%s"' % (self.filename, self.dirname, self.dirname)
|
2006-07-06 20:41:25 +08:00
|
|
|
cmd=commands.getstatusoutput(command_str)
|
2005-11-28 05:49:15 +08:00
|
|
|
self.extracted=1
|
2001-11-15 00:34:02 +08:00
|
|
|
return cmd
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2001-06-07 00:18:31 +08:00
|
|
|
def checkSignature(self):
|
2006-09-15 06:18:32 +08:00
|
|
|
return getstatusoutput(('env', 'LC_ALL=C', 'rpm', '-K', self.filename))
|
2005-11-28 05:49:15 +08:00
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# return the array of info returned by the file command on each file
|
1999-10-01 15:15:25 +08:00
|
|
|
def getFilesInfo(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self.file_info == None:
|
|
|
|
self.file_info=[]
|
2006-09-15 06:18:32 +08:00
|
|
|
olddir = os.getcwd()
|
|
|
|
os.chdir(self.dirName())
|
|
|
|
lines = commands.getoutput('find . -type f -print0 | LC_ALL=C xargs -0r file')
|
|
|
|
os.chdir(olddir)
|
2005-11-28 05:49:15 +08:00
|
|
|
lines=string.split(lines, '\n')
|
|
|
|
for l in lines:
|
|
|
|
#print l
|
|
|
|
res=Pkg.file_regex.search(l)
|
|
|
|
if res:
|
|
|
|
self.file_info.append([res.group(1), res.group(2)])
|
|
|
|
#print self.file_info
|
|
|
|
return self.file_info
|
1999-10-06 21:00:23 +08:00
|
|
|
|
|
|
|
# remove the extracted files from the package
|
1999-10-01 15:15:25 +08:00
|
|
|
def cleanup(self):
|
2006-09-15 06:18:32 +08:00
|
|
|
if self.extracted and self.dirname:
|
|
|
|
getstatusoutput(('rm', '-rf', self.dirname))
|
1999-10-06 20:35:40 +08:00
|
|
|
|
2006-08-26 21:22:08 +08:00
|
|
|
def grep(self, regex, filename):
|
|
|
|
"""Grep regex from a file, return matching line numbers."""
|
|
|
|
ret = []
|
|
|
|
lineno = 0
|
|
|
|
in_file = None
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
in_file = open(self.dirName() + '/' + filename)
|
|
|
|
line = in_file.readline()
|
|
|
|
while line:
|
|
|
|
lineno += 1
|
|
|
|
if regex.search(line):
|
|
|
|
ret.append(str(lineno))
|
|
|
|
break
|
|
|
|
line = in_file.readline()
|
|
|
|
except Exception, e:
|
|
|
|
printWarning(self, 'read-error', filename, e)
|
|
|
|
finally:
|
|
|
|
if in_file:
|
|
|
|
in_file.close()
|
|
|
|
return ret
|
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# return the associative array indexed on file names with
|
|
|
|
# the values as: (file perm, file owner, file group, file link to)
|
|
|
|
def files(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self._files != None:
|
|
|
|
return self._files
|
|
|
|
self._gatherFilesInfo()
|
|
|
|
return self._files
|
1999-10-06 21:00:23 +08:00
|
|
|
|
|
|
|
# return the list of config files
|
1999-10-06 20:35:40 +08:00
|
|
|
def configFiles(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self._config_files != None:
|
|
|
|
return self._config_files
|
|
|
|
self._gatherFilesInfo()
|
|
|
|
return self._config_files
|
1999-10-06 21:00:23 +08:00
|
|
|
|
2000-08-10 20:24:45 +08:00
|
|
|
# return the list of noreplace files
|
|
|
|
def noreplaceFiles(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self._noreplace_files != None:
|
|
|
|
return self._noreplace_files
|
|
|
|
self._gatherFilesInfo()
|
|
|
|
return self._noreplace_files
|
2000-08-10 20:24:45 +08:00
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# return the list of documentation files
|
|
|
|
def docFiles(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self._doc_files != None:
|
|
|
|
return self._doc_files
|
|
|
|
self._gatherFilesInfo()
|
|
|
|
return self._doc_files
|
1999-10-06 21:00:23 +08:00
|
|
|
|
1999-10-12 12:38:55 +08:00
|
|
|
# return the list of ghost files
|
|
|
|
def ghostFiles(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self._ghost_files != None:
|
|
|
|
return self._ghost_files
|
|
|
|
self._gatherFilesInfo()
|
|
|
|
return self._ghost_files
|
1999-10-12 12:38:55 +08:00
|
|
|
|
1999-10-06 21:00:23 +08:00
|
|
|
# extract information about the files
|
|
|
|
def _gatherFilesInfo(self):
|
2000-02-23 14:40:36 +08:00
|
|
|
global v304
|
2005-11-28 05:49:15 +08:00
|
|
|
|
|
|
|
self._config_files=[]
|
|
|
|
self._doc_files=[]
|
|
|
|
self._noreplace_files=[]
|
|
|
|
self._ghost_files=[]
|
|
|
|
self._files={}
|
2000-08-18 13:39:25 +08:00
|
|
|
self._files_array=[]
|
2005-11-28 05:49:15 +08:00
|
|
|
flags=self.header[rpm.RPMTAG_FILEFLAGS]
|
|
|
|
modes=self.header[rpm.RPMTAG_FILEMODES]
|
|
|
|
users=self.header[rpm.RPMTAG_FILEUSERNAME]
|
|
|
|
groups=self.header[rpm.RPMTAG_FILEGROUPNAME]
|
|
|
|
links=self.header[rpm.RPMTAG_FILELINKTOS]
|
|
|
|
sizes=self.header[rpm.RPMTAG_FILESIZES]
|
|
|
|
md5s=self.header[rpm.RPMTAG_FILEMD5S]
|
2002-03-04 10:31:21 +08:00
|
|
|
mtimes=self.header[rpm.RPMTAG_FILEMTIMES]
|
|
|
|
rdevs=self.header[rpm.RPMTAG_FILERDEVS]
|
2000-02-23 14:40:36 +08:00
|
|
|
# Get files according to rpm version
|
|
|
|
if v304:
|
|
|
|
files=self.header[rpm.RPMTAG_OLDFILENAMES]
|
|
|
|
if files == None:
|
|
|
|
basenames=self.header[rpm.RPMTAG_BASENAMES]
|
|
|
|
if basenames:
|
|
|
|
dirnames=self.header[rpm.RPMTAG_DIRNAMES]
|
|
|
|
dirindexes=self.header[rpm.RPMTAG_DIRINDEXES]
|
|
|
|
files=[]
|
2000-02-28 20:37:56 +08:00
|
|
|
# The rpmlib or the python module doesn't report a list for RPMTAG_DIRINDEXES
|
|
|
|
# if the list has one element...
|
2000-02-28 22:35:17 +08:00
|
|
|
if type(dirindexes) == types.IntType:
|
2000-02-28 20:37:56 +08:00
|
|
|
files.append(dirnames[dirindexes] + basenames[0])
|
|
|
|
else:
|
2000-02-28 22:35:17 +08:00
|
|
|
for idx in range(0, len(dirindexes)):
|
2000-02-28 20:37:56 +08:00
|
|
|
files.append(dirnames[dirindexes[idx]] + basenames[idx])
|
2000-02-23 14:40:36 +08:00
|
|
|
else:
|
|
|
|
files=self.header[rpm.RPMTAG_FILENAMES]
|
|
|
|
|
2005-11-28 05:49:15 +08:00
|
|
|
if files:
|
2000-08-18 13:39:25 +08:00
|
|
|
self._files_array=files
|
2005-11-28 05:49:15 +08:00
|
|
|
for idx in range(0, len(files)):
|
|
|
|
if flags[idx] & RPMFILE_CONFIG:
|
|
|
|
self._config_files.append(files[idx])
|
|
|
|
if flags[idx] & RPMFILE_DOC:
|
|
|
|
self._doc_files.append(files[idx])
|
|
|
|
if flags[idx] & RPMFILE_NOREPLACE:
|
|
|
|
self._noreplace_files.append(files[idx])
|
|
|
|
if flags[idx] & RPMFILE_GHOST:
|
|
|
|
self._ghost_files.append(files[idx])
|
|
|
|
self._files[files[idx]]=(modes[idx], users[idx],
|
|
|
|
groups[idx], links[idx],
|
2002-03-04 10:31:21 +08:00
|
|
|
sizes[idx], md5s[idx],
|
|
|
|
mtimes[idx], rdevs[idx])
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-08-18 13:39:25 +08:00
|
|
|
def langFiles(self):
|
|
|
|
if self._lang_files == None:
|
|
|
|
self._lang_files={}
|
|
|
|
array=self.header[rpm.RPMTAG_FILELANGS]
|
|
|
|
if array:
|
|
|
|
for idx in range(0, len(array)):
|
|
|
|
self._lang_files[self._files_array[idx]] = array[idx]
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-08-18 13:39:25 +08:00
|
|
|
return self._lang_files
|
|
|
|
|
|
|
|
def fileLang(self, f):
|
|
|
|
return self.langFiles()[f]
|
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
# API to access dependency information
|
2001-08-22 00:53:05 +08:00
|
|
|
def obsoletes(self):
|
|
|
|
self._gatherDepInfo()
|
|
|
|
return self._obsoletes
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
def requires(self):
|
|
|
|
self._gatherDepInfo()
|
|
|
|
return self._requires
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
def prereq(self):
|
|
|
|
self._gatherDepInfo()
|
|
|
|
return self._prereq
|
|
|
|
|
2001-02-17 00:36:10 +08:00
|
|
|
def req_names(self):
|
|
|
|
if self._req_names == -1:
|
|
|
|
self._req_names = map(lambda x: x[0], self.requires() + self.prereq())
|
|
|
|
return self._req_names
|
2002-02-08 04:06:50 +08:00
|
|
|
|
|
|
|
def check_versioned_dep(self, name, version):
|
|
|
|
for d in self.requires()+self.prereq():
|
|
|
|
if d[0] == name:
|
2005-02-08 23:54:34 +08:00
|
|
|
current_version=d[1]
|
2005-02-15 01:39:32 +08:00
|
|
|
if current_version.find(':') > 0:
|
2005-11-28 05:49:15 +08:00
|
|
|
current_version=''.join(current_version.split(':')[1:])
|
2005-02-08 23:54:34 +08:00
|
|
|
if d[2] & rpm.RPMSENSE_EQUAL != rpm.RPMSENSE_EQUAL or current_version != version:
|
2002-02-08 04:06:50 +08:00
|
|
|
return 0
|
|
|
|
else:
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
def conflicts(self):
|
|
|
|
self._gatherDepInfo()
|
|
|
|
return self._conflicts
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
def provides(self):
|
|
|
|
self._gatherDepInfo()
|
|
|
|
return self._provides
|
|
|
|
|
|
|
|
# internal function to gather dependency info used by the above ones
|
2001-08-22 00:53:05 +08:00
|
|
|
def _gather_aux(self, header, list, nametag, versiontag, flagstag, prereq=None):
|
|
|
|
names = header[nametag]
|
|
|
|
versions = header[versiontag]
|
|
|
|
flags = header[flagstag]
|
2005-08-10 13:05:21 +08:00
|
|
|
|
2001-08-22 00:53:05 +08:00
|
|
|
if versions:
|
|
|
|
# workaroung buggy rpm python module that doesn't return a list
|
|
|
|
if type(flags) != types.ListType:
|
|
|
|
flags=[flags]
|
|
|
|
for loop in range(len(versions)):
|
2005-08-10 13:05:21 +08:00
|
|
|
if prereq != None and flags[loop] & PREREQ_FLAG:
|
|
|
|
prereq.append((names[loop], versions[loop], flags[loop] & PREREQ_FLAG))
|
2001-08-22 00:53:05 +08:00
|
|
|
else:
|
|
|
|
list.append((names[loop], versions[loop], flags[loop]))
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
def _gatherDepInfo(self):
|
2005-08-10 13:05:21 +08:00
|
|
|
if self._requires == None:
|
2000-06-15 20:07:22 +08:00
|
|
|
self._requires = []
|
|
|
|
self._prereq = []
|
|
|
|
self._provides = []
|
2000-06-27 16:12:48 +08:00
|
|
|
self._conflicts = []
|
2001-08-22 00:53:05 +08:00
|
|
|
self._obsoletes = []
|
|
|
|
|
|
|
|
self._gather_aux(self.header, self._requires,
|
|
|
|
rpm.RPMTAG_REQUIRENAME,
|
|
|
|
rpm.RPMTAG_REQUIREVERSION,
|
|
|
|
rpm.RPMTAG_REQUIREFLAGS,
|
|
|
|
self._prereq)
|
|
|
|
self._gather_aux(self.header, self._conflicts,
|
|
|
|
rpm.RPMTAG_CONFLICTNAME,
|
|
|
|
rpm.RPMTAG_CONFLICTVERSION,
|
|
|
|
rpm.RPMTAG_CONFLICTFLAGS)
|
|
|
|
self._gather_aux(self.header, self._provides,
|
|
|
|
rpm.RPMTAG_PROVIDENAME,
|
|
|
|
rpm.RPMTAG_PROVIDEVERSION,
|
|
|
|
rpm.RPMTAG_PROVIDEFLAGS)
|
|
|
|
self._gather_aux(self.header, self._obsoletes,
|
|
|
|
rpm.RPMTAG_OBSOLETENAME,
|
|
|
|
rpm.RPMTAG_OBSOLETEVERSION,
|
|
|
|
rpm.RPMTAG_OBSOLETEFLAGS)
|
2001-06-07 00:18:31 +08:00
|
|
|
|
2006-06-06 04:45:07 +08:00
|
|
|
def getInstalledPkgs(name):
|
|
|
|
"""Get list of installed package objects by name."""
|
|
|
|
pkgs = []
|
|
|
|
if v42:
|
|
|
|
ts = rpm.TransactionSet()
|
|
|
|
tab = ts.dbMatch("name", name)
|
|
|
|
if not tab:
|
|
|
|
raise KeyError, name
|
|
|
|
for hdr in tab:
|
|
|
|
pkgs.append(InstalledPkg(name, hdr))
|
|
|
|
else:
|
|
|
|
db = rpm.opendb()
|
|
|
|
ixs = db.findbyname(name)
|
|
|
|
if not ixs:
|
|
|
|
del db
|
|
|
|
raise KeyError, name
|
|
|
|
for ix in ixs:
|
|
|
|
pkgs.append(InstalledPkg(name, db[ix]))
|
|
|
|
del db
|
|
|
|
return pkgs
|
|
|
|
|
2001-06-07 00:18:31 +08:00
|
|
|
# Class to provide an API to an installed package
|
|
|
|
class InstalledPkg(Pkg):
|
2001-07-16 00:58:50 +08:00
|
|
|
def __init__(self, name, h=None):
|
|
|
|
if h:
|
|
|
|
Pkg.__init__(self, name, '/', h)
|
|
|
|
else:
|
2003-04-23 21:32:46 +08:00
|
|
|
if v42:
|
|
|
|
ts = rpm.TransactionSet()
|
|
|
|
tab = ts.dbMatch('name', name)
|
|
|
|
if not tab:
|
|
|
|
raise KeyError, name
|
|
|
|
theHdr = tab.next()
|
|
|
|
else:
|
|
|
|
db = rpm.opendb()
|
|
|
|
tab = db.findbyname(name)
|
|
|
|
if not tab:
|
|
|
|
del db
|
|
|
|
raise KeyError, name
|
|
|
|
theHdr = db[tab[0]]
|
2001-07-16 00:58:50 +08:00
|
|
|
del db
|
2003-04-23 21:32:46 +08:00
|
|
|
Pkg.__init__(self, name, '/', theHdr)
|
2001-06-07 00:18:31 +08:00
|
|
|
self.extracted = 1
|
2002-04-25 04:03:00 +08:00
|
|
|
# create a fake filename to satisfy some checks on the filename
|
2006-06-16 04:21:19 +08:00
|
|
|
self.filename = '%s-%s-%s.%s.rpm' % (self.name, self[rpm.RPMTAG_VERSION], self[rpm.RPMTAG_RELEASE], self[rpm.RPMTAG_ARCH])
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2001-06-07 00:18:31 +08:00
|
|
|
def cleanup(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def checkSignature(self):
|
|
|
|
return (0, 'fake: pgp md5 OK')
|
|
|
|
|
|
|
|
# return the array of info returned by the file command on each file
|
|
|
|
def getFilesInfo(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
if self.file_info == None:
|
|
|
|
self.file_info=[]
|
2006-09-15 06:18:32 +08:00
|
|
|
cmd = ['env', 'LC_ALL=C', 'file']
|
|
|
|
cmd.extend(self.files().keys())
|
|
|
|
sts, lines = getstatusoutput(cmd)
|
2001-06-07 00:18:31 +08:00
|
|
|
#print lines
|
2005-11-28 05:49:15 +08:00
|
|
|
lines=string.split(lines, '\n')
|
|
|
|
for l in lines:
|
|
|
|
#print l
|
|
|
|
res=Pkg.file_regex.search(l)
|
|
|
|
if res:
|
|
|
|
self.file_info.append([res.group(1), res.group(2)])
|
2001-06-07 00:18:31 +08:00
|
|
|
#print self.file_info
|
2005-11-28 05:49:15 +08:00
|
|
|
return self.file_info
|
2001-06-07 00:18:31 +08:00
|
|
|
|
2000-06-15 20:07:22 +08:00
|
|
|
if __name__ == '__main__':
|
|
|
|
for p in sys.argv[1:]:
|
2002-06-04 12:07:34 +08:00
|
|
|
pkg=Pkg(sys.argv[1], '/tmp')
|
2005-09-11 07:23:20 +08:00
|
|
|
sys.stdout.write('Requires: %s\n' % pkg.requires())
|
|
|
|
sys.stdout.write('Prereq: %s\n' % pkg.prereq())
|
|
|
|
sys.stdout.write('Conflicts: %s\n' % pkg.conflicts())
|
|
|
|
sys.stdout.write('Provides: %s\n' % pkg.provides())
|
|
|
|
sys.stdout.write('Obsoletes: %s\n' % pkg.obsoletes())
|
2000-06-15 20:07:22 +08:00
|
|
|
pkg.cleanup()
|
2005-11-28 05:49:15 +08:00
|
|
|
|
1999-10-01 15:15:25 +08:00
|
|
|
# Pkg.py ends here
|
2006-04-01 16:09:17 +08:00
|
|
|
|
|
|
|
# Local variables:
|
|
|
|
# indent-tabs-mode: nil
|
|
|
|
# py-indent-offset: 4
|
|
|
|
# End:
|
|
|
|
# ex: ts=4 sw=4 et
|