[yum-git] yum/packages.py

James Antill james at linux.duke.edu
Tue Feb 26 22:28:41 UTC 2008


 yum/packages.py |  111 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 95 insertions(+), 16 deletions(-)

New commits:
commit 92d0aa1485b02ac095fbe307bcfc3ad935fd8352
Author: James Antill <james at and.org>
Date:   Tue Feb 26 16:55:46 2008 -0500

     Add file_types, add some logic to match rpm verify.
     Fix size calcs. when using prelink.

diff --git a/yum/packages.py b/yum/packages.py
index 3e5451a..f22ed57 100644
--- a/yum/packages.py
+++ b/yum/packages.py
@@ -835,6 +835,20 @@ class YumHeaderPackage(YumAvailablePackage):
                        self.hdr['changelogtext'])
         return []
 
+class _CountedReadFile:
+    """ Has just a read() method, and keeps a count so we can find out how much
+        has been read. Implemented so we can get the real size of the file from
+        prelink. """
+    
+    def __init__(self, fp):
+        self.fp = fp
+        self.read_size = 0
+
+    def read(self, size):
+        ret = self.fp.read(size)
+        self.read_size += len(ret)
+        return ret
+
 _installed_repo = FakeRepository('installed')
 _installed_repo.cost = 0
 class YumInstalledPackage(YumHeaderPackage):
@@ -843,7 +857,7 @@ class YumInstalledPackage(YumHeaderPackage):
         fakerepo = _installed_repo
         YumHeaderPackage.__init__(self, fakerepo, hdr)
         
-    def verify(self, patterns=[]):
+    def verify(self, patterns=[], all=False):
         """verify that the installed files match the packaged checksum
            optionally verify they match only if they are in the 'pattern' list
            returns a tuple """
@@ -867,6 +881,31 @@ class YumInstalledPackage(YumHeaderPackage):
                         break
                 if not matched: 
                     continue
+
+            if not all and flags & rpm.RPMFILE_GHOST:
+                continue
+            if not all and flags & rpm.RPMFILE_MISSINGOK:
+                continue # rpm just skips missing ok, so we do too
+
+            ftypes = []
+            if flags & rpm.RPMFILE_CONFIG:
+                ftypes.append('config')
+            if flags & rpm.RPMFILE_DOC:
+                ftypes.append('documentation')
+            if flags & rpm.RPMFILE_GHOST:
+                ftypes.append('ghost')
+            if flags & rpm.RPMFILE_LICENSE:
+                ftypes.append('license')
+            if flags & rpm.RPMFILE_PUBKEY:
+                ftypes.append('public key')
+            if flags & rpm.RPMFILE_README:
+                ftypes.append('README')
+            if flags & rpm.RPMFILE_MISSINGOK:
+                ftypes.append('missing ok')
+            # not in python rpm bindings yet
+            # elif flags & rpm.RPMFILE_POLICY:
+            #    ftypes.append('policy')
+                
             # do check of file status on system
             problems = []
             if os.path.exists(fn):
@@ -882,12 +921,23 @@ class YumInstalledPackage(YumHeaderPackage):
 
                 isdir = stat.S_ISDIR(my_st.st_mode)
                 islnk = stat.S_ISLNK(my_st.st_mode)
-                if my_st.st_mtime != mtime and not isdir and not islnk:
+                check_content = True
+                if (isdir or islnk or stat.S_ISFIFO(my_st.st_mode) or
+                    stat.S_ISCHR(my_st.st_mode) or
+                    stat.S_ISBLK(my_st.st_mode) or 'ghost' in ftypes):
+                    check_content = False
+
+                # FIXME: We don't have rpmfiFLink() so we can't verify
+                # symlinks "correctly", as rpm does. So we check the csum of
+                # what it points to.
+
+                if check_content and my_st.st_mtime != mtime:
                     thisproblem = misc.GenericHolder()
                     thisproblem.type = 'mtime' # maybe replace with a constants type
                     thisproblem.message = 'mtime does not match'
                     thisproblem.database_value = mtime
                     thisproblem.disk_value = my_st[stat.ST_MTIME]
+                    thisproblem.file_types = ftypes
                     problems.append(thisproblem)
 
                 if my_group != group and not islnk:
@@ -896,6 +946,7 @@ class YumInstalledPackage(YumHeaderPackage):
                     thisproblem.message = 'group does not match'
                     thisproblem.database_value = group
                     thisproblem.disk_value = my_group
+                    thisproblem.file_types = ftypes
                     problems.append(thisproblem)
                 if my_user != user and not islnk:
                     thisproblem = misc.GenericHolder()
@@ -903,48 +954,76 @@ class YumInstalledPackage(YumHeaderPackage):
                     thisproblem.message = 'user does not match'
                     thisproblem.database_value = user
                     thisproblem.disk_value = my_user
+                    thisproblem.file_types = ftypes
                     problems.append(thisproblem)
 
-                if my_st.st_size != size and not isdir and not islnk:
-                    thisproblem = misc.GenericHolder()
-                    thisproblem.type = 'size'
-                    thisproblem.message = 'size does not match'
-                    thisproblem.database_value = size
-                    thisproblem.disk_value = my_st.st_size
-                    problems.append(thisproblem)
-                    
-                if my_st.st_mode != mode and not islnk:
+                my_mode = my_st.st_mode
+                if 'ghost' in ftypes: # This is what rpm does
+                    my_mode &= 0777
+                    mode    &= 0777
+                if my_mode != mode and not islnk:
                     thisproblem = misc.GenericHolder()
                     thisproblem.type = 'mode'
                     thisproblem.message = 'mode does not match'
                     thisproblem.database_value = mode
                     thisproblem.disk_value = my_st.st_mode
+                    thisproblem.file_types = ftypes
                     problems.append(thisproblem)
 
+                my_st_size = my_st.st_size
                 # don't checksum files that don't have a csum in the rpmdb :)
-                if csum and not isdir:
-                    my_csum = misc.checksum('md5', fn)
-                    if my_csum != csum and have_prelink:
+                if check_content and csum:
+                    try:
+                        my_csum = misc.checksum('md5', fn)
+                        gen_csum = True
+                    except Errors.MiscError:
+                        # Don't have permission?
+                        gen_csum = False
+
+                    if not gen_csum:
+                        thisproblem = misc.GenericHolder()
+                        thisproblem.type = 'genchecksum'
+                        thisproblem.message = 'checksum not available'
+                        thisproblem.database_value = csum
+                        thisproblem.disk_value = None
+                        thisproblem.file_types = ftypes
+                        problems.append(thisproblem)
+                        
+                    if gen_csum and my_csum != csum and have_prelink:
                         #  This is how rpm -V works, try and if that fails try
                         # again with prelink.
                         (ig, fp,er) = os.popen3([prelink_cmd, "-y", fn])
                         # er.read(1024 * 1024) # Try and get most of the stderr
+                        fp = _CountedReadFile(fp)
                         my_csum = misc.checksum('md5', fp)
+                        my_st_size = fp.read_size
 
-                    if my_csum != csum:
+                    if gen_csum and my_csum != csum:
                         thisproblem = misc.GenericHolder()
                         thisproblem.type = 'checksum' # maybe replace with a constants type
                         thisproblem.message = 'checksum does not match'
                         thisproblem.database_value = csum
                         thisproblem.disk_value = my_csum
+                        thisproblem.file_types = ftypes
                         problems.append(thisproblem)
-                    
+
+                # Size might be got from prelink ... *sigh*
+                if check_content and my_st_size != size:
+                    thisproblem = misc.GenericHolder()
+                    thisproblem.type = 'size'
+                    thisproblem.message = 'size does not match'
+                    thisproblem.database_value = size
+                    thisproblem.disk_value = my_st.st_size
+                    thisproblem.file_types = ftypes
+                    problems.append(thisproblem)
+
             else:
                 thisproblem = misc.GenericHolder()
                 thisproblem.type = 'missing' # maybe replace with a constants type
                 thisproblem.message = 'file is missing'
                 thisproblem.disk_value = None
                 thisproblem.database_value = None
+                thisproblem.file_types = ftypes
                 problems.append(thisproblem)
                 
             if problems:



More information about the Yum-cvs-commits mailing list