Represent files inside packages as PkgFile objects.

git-svn-id: svn+ssh://rpmlint.zarb.org/home/projects/rpmlint/svn/trunk@1543 9bc8b190-ac0f-0410-8968-dc7d1f502856
This commit is contained in:
Ville Skyttä 2009-02-01 21:58:38 +00:00
parent ee8d1ae115
commit 68731ec1c8
11 changed files with 99 additions and 68 deletions

View File

@ -218,7 +218,7 @@ class BinariesCheck(AbstractCheck.AbstractCheck):
multi_pkg = 0
for f in files:
if usr_lib_regex.search(f) and not usr_lib_exception_regex.search(f) and not stat.S_ISDIR(files[f][0]):
if usr_lib_regex.search(f) and not usr_lib_exception_regex.search(f) and not stat.S_ISDIR(files[f].mode):
has_usr_lib_file = f
break
@ -269,8 +269,7 @@ class BinariesCheck(AbstractCheck.AbstractCheck):
(directory, base) = dir_base(i[0])
try:
symlink = directory + bin_info.soname
(perm, owner, group, link, size, md5, mtime, rdev, lang, inode, deps) = files[symlink]
if link != i[0] and link != base and link != '':
if files[symlink].linkto not in (i[0], base, ''):
printError(pkg, 'invalid-ldconfig-symlink', i[0], link)
except KeyError:
printError(pkg, 'no-ldconfig-symlink', i[0])

View File

@ -42,8 +42,8 @@ class DocFilesCheck(AbstractCheck.AbstractCheck):
doc_files = pkg.docFiles()
reqs = {}
for fname, fattrs in files.items():
tmp = fattrs[10].split()
for fname, pkgfile in files.items():
tmp = pkgfile.deps.split()
tmp = _stripVersionedDeps(tmp)
reqs[fname] = tmp

View File

@ -309,14 +309,14 @@ class FilesCheck(AbstractCheck.AbstractCheck):
# Unique (rdev, inode) combinations
hardlinks = {}
for f, fattrs in files.items():
mode = fattrs[0]
user = fattrs[1]
group = fattrs[2]
link = fattrs[3]
size = fattrs[4]
rdev = fattrs[7]
inode = fattrs[9]
for f, pkgfile in files.items():
mode = pkgfile.mode
user = pkgfile.user
group = pkgfile.group
link = pkgfile.linkto
size = pkgfile.size
rdev = pkgfile.rdev
inode = pkgfile.inode
is_doc = f in doc_files
nonexec_file = 0
@ -587,7 +587,7 @@ class FilesCheck(AbstractCheck.AbstractCheck):
# relative link
else:
if not is_so:
extractedfile = '%s%s/%s' % (pkg.dirName(), os.path.dirname(f), link)
extractedfile = os.path.join(os.path.dirname(pkgfile.path), link)
extractedfile = os.path.normpath(extractedfile)
pkgfile = '%s/%s' % (os.path.dirname(f), link)
pkgfile = os.path.normpath(pkgfile)
@ -637,7 +637,7 @@ class FilesCheck(AbstractCheck.AbstractCheck):
# check text file
if stat.S_ISREG(mode):
path = pkg.dirName() + '/' + f
path = pkgfile.path
if os.access(path, os.R_OK):
if istextfile(path, pkg):
fobj = open(path, 'r')

View File

@ -148,12 +148,12 @@ class I18NCheck(AbstractCheck.AbstractCheck):
subdir = None
if f.endswith('.mo') or subdir:
if pkg.fileLang(f) == '' and not webapp:
if pkg.files()[f].lang == '' and not webapp:
printWarning(pkg, 'file-not-in-%lang', f)
main_dir, main_lang = ("", "")
for f in files:
lang = pkg.fileLang(f)
lang = pkg.files()[f].lang
if main_lang and lang == "" and is_prefix(main_dir + '/', f):
printError(pkg, 'subfile-not-in-%lang', f)
if main_lang != lang:

View File

@ -48,11 +48,11 @@ class InitScriptCheck(AbstractCheck.AbstractCheck):
return
initscript_list = []
for fname, fattrs in pkg.files().items():
for fname, pkgfile in pkg.files().items():
if rc_regex.search(fname):
basename = os.path.basename(fname)
initscript_list.append(basename)
if fattrs[0] & 0500 != 0500:
if pkgfile.mode & 0500 != 0500:
printError(pkg, 'init-script-non-executable', fname)
if dot_in_name_regex.match(basename):
@ -83,7 +83,7 @@ class InitScriptCheck(AbstractCheck.AbstractCheck):
# check common error in file content
content = None
try:
content = Pkg.readlines(pkg.dirName() + '/' + fname)
content = Pkg.readlines(pkgfile.path)
except Exception, e:
printWarning(pkg, 'read-error', e)
continue

View File

@ -170,10 +170,10 @@ class MenuCheck(AbstractCheck.AbstractCheck):
files = pkg.files()
menus = []
for fname, fattrs in files.items():
for fname, pkgfile in files.items():
# Check menu files
res = menu_file_regex.search(fname)
mode = fattrs[0]
mode = pkgfile.mode
if res:
basename = res.group(1)
if not stat.S_ISREG(mode):

94
Pkg.py
View File

@ -197,8 +197,9 @@ class Pkg:
self.current_linenum = None
self._config_files = None
self._doc_files = None
self._noreplace_files = None
self._ghost_files = None
self._missing_ok_files = None
self._missingok_files = None
self._files = None
self._requires = None
self._req_names = -1
@ -321,6 +322,7 @@ class Pkg:
def files(self):
if self._files is not None:
return self._files
self._gatherFilesInfo()
return self._files
@ -328,45 +330,49 @@ class Pkg:
def configFiles(self):
if self._config_files is not None:
return self._config_files
self._gatherFilesInfo()
self._config_files = [x.name for x in self.files().values()
if x.is_config]
return self._config_files
# return the list of noreplace files
def noreplaceFiles(self):
if self._noreplace_files is not None:
return self._noreplace_files
self._gatherFilesInfo()
self._noreplace_files = [x.name for x in self.files().values()
if x.is_noreplace]
return self._noreplace_files
# return the list of documentation files
def docFiles(self):
if self._doc_files is not None:
return self._doc_files
self._gatherFilesInfo()
self._doc_files = [x.name for x in self.files().values() if x.is_doc]
return self._doc_files
# return the list of ghost files
def ghostFiles(self):
if self._ghost_files is not None:
return self._ghost_files
self._gatherFilesInfo()
self._ghost_files = [x.name for x in self.files().values()
if x.is_ghost]
return self._ghost_files
def missingOkFiles(self):
if self._missing_ok_files is not None:
return self._missing_ok_files
self._gatherFilesInfo()
return self._missing_ok_files
if self._missingok_files is not None:
return self._missingok_files
self._missingok_files = [x.name for x in self.files().values()
if x.is_missingok]
return self._missingok_files
# extract information about the files
def _gatherFilesInfo(self):
global v304
self._config_files = []
self._doc_files = []
self._noreplace_files = []
self._ghost_files = []
self._missing_ok_files = []
self._files = {}
flags = self.header[rpm.RPMTAG_FILEFLAGS]
modes = self.header[rpm.RPMTAG_FILEMODES]
@ -407,24 +413,21 @@ class Pkg:
if files:
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])
if flags[idx] & RPMFILE_MISSINGOK:
self._missing_ok_files.append(files[idx])
self._files[files[idx]] = (modes[idx], users[idx],
groups[idx], links[idx],
sizes[idx], md5s[idx],
mtimes[idx], rdevs[idx],
langs[idx], inodes[idx], deps[idx])
def fileLang(self, f):
return self.files()[f][8]
pkgfile = PkgFile(files[idx])
pkgfile.path = os.path.join(self.dirName(), pkgfile.name)
pkgfile.flags = flags[idx]
pkgfile.mode = modes[idx]
pkgfile.user = users[idx]
pkgfile.group = groups[idx]
pkgfile.linkto = links[idx]
pkgfile.size = sizes[idx]
pkgfile.md5 = md5s[idx]
pkgfile.mtime = mtimes[idx]
pkgfile.rdev = rdevs[idx]
pkgfile.inode = inodes[idx]
pkgfile.deps = deps[idx]
pkgfile.lang = langs[idx]
self._files[pkgfile.name] = pkgfile
# API to access dependency information
def obsoletes(self):
@ -592,6 +595,33 @@ class FakePkg:
def cleanup(self):
pass
# Class for files in packages
class PkgFile(object):
def __init__(self, name):
self.name = name
# Real path to the file (taking extract dir into account)
self.path = name
self.flags = 0
self.mode = 0
self.user = None
self.group = None
self.linkto = ''
self.size = None
self.md5 = None
self.mtime = 0
self.rdev = ''
self.inode = 0
self.deps = ''
self.lang = ''
is_config = property(lambda self: self.flags & RPMFILE_CONFIG)
is_doc = property(lambda self: self.flags & RPMFILE_DOC)
is_noreplace = property(lambda self: self.flags & RPMFILE_NOREPLACE)
is_ghost = property(lambda self: self.flags & RPMFILE_GHOST)
is_missingok = property(lambda self: self.flags & RPMFILE_MISSINGOK)
if __name__ == '__main__':
for p in sys.argv[1:]:
pkg = Pkg(sys.argv[1], tempfile.gettempdir())

View File

@ -34,7 +34,7 @@ class SourceCheck(AbstractCheck.AbstractCheck):
# process file list
spec_file = None
for fname, fattrs in pkg.files().items():
for fname, pkgfile in pkg.files().items():
if fname.endswith('.spec'):
if spec_file:
printError(pkg, 'multiple-specfiles', spec_file, fname)
@ -47,7 +47,7 @@ class SourceCheck(AbstractCheck.AbstractCheck):
else:
if not fname.endswith('gz'):
printWarning(pkg, 'source-or-patch-not-gzipped', fname)
perm = fattrs[0] & 07777
perm = pkgfile.mode & 07777
if perm not in valid_src_perms:
printWarning(pkg, 'strange-permission', fname, oct(perm))

View File

@ -154,9 +154,9 @@ class SpecCheck(AbstractCheck.AbstractCheck):
wrong_spec = False
# lookup spec file
for fname in pkg.files():
for fname, pkgfile in pkg.files().items():
if fname.endswith('.spec'):
self._spec_file = pkg.dirName() + "/" + fname
self._spec_file = pkgfile.path
if fname == pkg.name + ".spec":
wrong_spec = False
break

View File

@ -31,8 +31,8 @@ class ZipCheck(AbstractCheck.AbstractCheck):
AbstractCheck.AbstractCheck.__init__(self, "ZipCheck")
def check(self, pkg):
for fname in pkg.files():
path = pkg.dirName() + fname
for fname, pkgfile in pkg.files().items():
path = pkgfile.path
if zip_regex.search(fname) and os.path.exists(path) and \
stat.S_ISREG(os.lstat(path)[stat.ST_MODE]) and \
zipfile.is_zipfile(path):

18
rpmdiff
View File

@ -37,16 +37,16 @@ TAGS = [ (rpm.RPMTAG_NAME, 'NAME'),
(rpm.RPMTAG_POSTUN, 'POSTUN'),
]
FILEIDX = [ ('S', 4),
('M', 0),
('5', 5),
FILEIDX = [ ('S', 'size'),
('M', 'mode'),
('5', 'md5'),
('D', None),
('L', 3),
('U', 1),
('G', 2),
('L', 'linkto'),
('U', 'user'),
('G', 'group'),
(None, None),
]
FILEIDX_T = ('T', 6)
FILEIDX_T = ('T', 'mtime')
DEPFORMAT = '%-11s%s %s %s %s'
FORMAT = '%-11s%s'
@ -176,7 +176,9 @@ def main():
format = ''
for idx in range(0, len(FILEIDX)):
entry = FILEIDX[idx]
if entry[1] is not None and old_file[entry[1]] != new_file[entry[1]]:
prop = entry[1]
if entry[1] is not None and \
getattr(old_file, prop) != getattr(new_file, prop):
format = format + entry[0]
diff = 1
else: