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

View File

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

View File

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

View File

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

View File

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

View File

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

94
Pkg.py
View File

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

View File

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

View File

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

View File

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

18
rpmdiff
View File

@ -37,16 +37,16 @@ TAGS = [ (rpm.RPMTAG_NAME, 'NAME'),
(rpm.RPMTAG_POSTUN, 'POSTUN'), (rpm.RPMTAG_POSTUN, 'POSTUN'),
] ]
FILEIDX = [ ('S', 4), FILEIDX = [ ('S', 'size'),
('M', 0), ('M', 'mode'),
('5', 5), ('5', 'md5'),
('D', None), ('D', None),
('L', 3), ('L', 'linkto'),
('U', 1), ('U', 'user'),
('G', 2), ('G', 'group'),
(None, None), (None, None),
] ]
FILEIDX_T = ('T', 6) FILEIDX_T = ('T', 'mtime')
DEPFORMAT = '%-11s%s %s %s %s' DEPFORMAT = '%-11s%s %s %s %s'
FORMAT = '%-11s%s' FORMAT = '%-11s%s'
@ -176,7 +176,9 @@ def main():
format = '' format = ''
for idx in range(0, len(FILEIDX)): for idx in range(0, len(FILEIDX)):
entry = FILEIDX[idx] 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] format = format + entry[0]
diff = 1 diff = 1
else: else: