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:
parent
ee8d1ae115
commit
68731ec1c8
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
94
Pkg.py
|
@ -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())
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
18
rpmdiff
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue