rpmlint/DuplicatesCheck.py

108 lines
3.3 KiB
Python
Raw Normal View History

# vim:sw=4:et
#############################################################################
# File : DuplicatesCheck.py
# Package : rpmlint
# Author : Stephan Kulow
# Purpose : Check for duplicate files being packaged separately
#############################################################################
from Filter import *
import AbstractCheck
import rpm
import re
import commands
import stat
import Config
import os
import string
def get_prefix(file):
pathlist = string.split(file, '/')
if len(pathlist) == 3:
return "/".join(pathlist[0:2])
return "/".join(pathlist[0:3])
class DuplicatesCheck(AbstractCheck.AbstractCheck):
def __init__(self):
self.map = []
AbstractCheck.AbstractCheck.__init__(self, "DuplicatesCheck")
def check(self, pkg):
if pkg.isSource():
return
md5s = {}
sizes = {}
files = pkg.files()
configFiles = pkg.configFiles()
for f in files:
if f in pkg.ghostFiles():
continue
enreg = files[f]
mode = enreg[0]
links = enreg[3]
size = enreg[4]
md5 = enreg[5]
rdev = enreg[7]
if not stat.S_ISREG(mode):
continue
md5s.setdefault(md5, set()).add(f)
sizes[md5] = size
#print f, links, size, md5, rdev
sum=0
for f in md5s:
duplicates=md5s[f]
if len(duplicates) == 1: continue
one=duplicates.pop()
one_is_config = False
if one in configFiles:
one_is_config = True
partition=get_prefix(one)
st = os.stat(pkg.dirName() + '/' + one)
diff = 1 + len(duplicates) - st[stat.ST_NLINK]
if diff <= 0:
for dupe in duplicates:
if partition != get_prefix(dupe):
printError(pkg,"hardlink-across-partition",one,dupe)
if one_is_config and dupe in configFiles:
printError(pkg,"hardlink-across-config-files",one,dupe)
continue
for dupe in duplicates:
if partition != get_prefix(dupe):
diff = diff - 1
sum += sizes[f] * diff
if sizes[f] and diff > 0:
printWarning(pkg, 'files-duplicate', one,":".join(duplicates))
if sum > 100000:
printError(pkg, 'files-duplicated-waste', sum)
check=DuplicatesCheck()
if Config.info:
addDetails(
'files-duplicated-waste',
"""Your package contains duplicated files that are not hard- or symlinks.
You should use the %fdupes macro to link the files to one.""",
'hardlink-across-partition',
"""Your package contains two files that are apparently hardlinked and
that are likely on different partitions. Installation of such an RPM will fail
due to RPM being unable to unpack the hardlink. do not hardlink across
the first two levels of a path, e.g. between /srv/ftp and /srv/www or
/etc and /usr. """,
'hardlink-across-config-files',
"""Your package contains two config files that are apparently hardlinked.
Hardlinking a config file is probably not what you want. Please double
check and report false positives."""
)