For bug #182428, make quickpkg exclude config files that are protected by CONFIG_PROT...
authorZac Medico <zmedico@gentoo.org>
Fri, 22 Jun 2007 08:47:02 +0000 (08:47 -0000)
committerZac Medico <zmedico@gentoo.org>
Fri, 22 Jun 2007 08:47:02 +0000 (08:47 -0000)
svn path=/main/trunk/; revision=6945

bin/quickpkg
pym/portage/dbapi/vartree.py

index 17611d6ed66dccbaae84ba3cfdd2eef1de8a9415..0ae9fd61b8281a99b07841793330b5114b1b8e92 100755 (executable)
@@ -8,9 +8,10 @@ import errno, signal, sys, os
 def quickpkg_main(options, args, eout):
        from portage import catsplit, dep_expand, flatten, isvalidatom, xpak
        from portage.dep import use_reduce, paren_reduce
-       from portage.util import ensure_dirs
+       from portage.util import ConfigProtect, ensure_dirs
        from portage.exception import InvalidData, InvalidDependString
        from portage.dbapi.vartree import dblink, tar_contents
+       from portage.checksum import perform_md5
        import tarfile
        import portage
        root = portage.settings["ROOT"]
@@ -23,6 +24,9 @@ def quickpkg_main(options, args, eout):
                return errno.EACCES
        successes = []
        missing = []
+       config_files_excluded = 0
+       include_config = options.include_config == "y"
+       include_unmodified_config = options.include_unmodified_config == "y"
        for arg in args:
                try:
                        atom = dep_expand(arg, mydb=vardb, settings=vartree.settings)
@@ -45,6 +49,7 @@ def quickpkg_main(options, args, eout):
                matches = vardb.match(atom)
                pkgs_for_arg = 0
                for cpv in matches:
+                       excluded_config_files = []
                        bintree.prevent_collision(cpv)
                        cat, pkg = catsplit(cpv)
                        dblnk = dblink(cat, pkg, root,
@@ -76,12 +81,29 @@ def quickpkg_main(options, args, eout):
                                eout.ebegin("Building package for %s" % cpv)
                                pkgs_for_arg += 1
                                contents = dblnk.getcontents()
+                               protect = None
+                               if not include_config:
+                                       confprot = ConfigProtect(root,
+                                               portage.settings.get("CONFIG_PROTECT","").split(),
+                                               portage.settings.get("CONFIG_PROTECT_MASK","").split())
+                                       def protect(filename):
+                                               if not confprot.isprotected(filename):
+                                                       return False
+                                               if include_unmodified_config:
+                                                       file_data = contents[filename]
+                                                       if file_data[0] == "obj":
+                                                               orig_md5 = file_data[2].lower()
+                                                               cur_md5 = perform_md5(filename, calc_prelink=1)
+                                                               if orig_md5 == cur_md5:
+                                                                       return False
+                                               excluded_config_files.append(filename)
+                                               return True
                                xpdata = xpak.xpak(dblnk.dbdir)
                                binpkg_tmpfile = os.path.join(bintree.pkgdir,
                                        cpv + ".tbz2." + str(os.getpid()))
                                ensure_dirs(os.path.dirname(binpkg_tmpfile))
                                tar = tarfile.open(binpkg_tmpfile, "w:bz2")
-                               tar_contents(contents, root, tar)
+                               tar_contents(contents, root, tar, protect=protect)
                                tar.close()
                                xpak.tbz2(binpkg_tmpfile).recompose_mem(xpdata)
                        finally:
@@ -99,6 +121,9 @@ def quickpkg_main(options, args, eout):
                        else:
                                eout.eend(0)
                                successes.append((cpv, s.st_size))
+                               config_files_excluded += len(excluded_config_files)
+                               for filename in excluded_config_files:
+                                       eout.ewarn("Excluded config: '%s'" % filename)
                if not pkgs_for_arg:
                        eout.eerror("Could not find anything " + \
                                "to match '%s'; skipping" % arg)
@@ -129,6 +154,10 @@ def quickpkg_main(options, args, eout):
                        else:
                                size_str = str(size)
                eout.einfo("%s: %s" % (cpv, size_str))
+       if config_files_excluded:
+               print
+               eout.ewarn("Excluded config files: %d" % config_files_excluded)
+               eout.ewarn("See --help if you would like to include config files.")
        if missing:
                print
                eout.ewarn("The following packages could not be found:")
@@ -146,6 +175,18 @@ if __name__ == "__main__":
        parser.add_option("--ignore-default-opts",
                action="store_true",
                help="do not use the QUICKPKG_DEFAULT_OPTS environment variable")
+       parser.add_option("--include-config",
+               type="choice",
+               choices=["y","n"],
+               default="n",
+               metavar="<y|n>",
+               help="include all files protected by CONFIG_PROTECT (as a security precaution, default is 'n')")
+       parser.add_option("--include-unmodified-config",
+               type="choice",
+               choices=["y","n"],
+               default="n",
+               metavar="<y|n>",
+               help="include files protected by CONFIG_PROTECT that have not been modified since installation (as a security precaution, default is 'n')")
        options, args = parser.parse_args(sys.argv[1:])
        if not options.ignore_default_opts:
                from portage import settings
index 50b9d9d9415da0d6c5573d956913bbb110960431..641d4942b59892b38b1e89cfc32f0b0efdc4af66 100644 (file)
@@ -2127,8 +2127,8 @@ class dblink(object):
                "Is this a regular package (does it have a CATEGORY file?  A dblink can be virtual *and* regular)"
                return os.path.exists(os.path.join(self.dbdir, "CATEGORY"))
 
-def tar_contents(contents, root, tar, onProgress=None):
-       from portage import normalize_path
+def tar_contents(contents, root, tar, protect=None, onProgress=None):
+       from portage.util import normalize_path
        root = normalize_path(root).rstrip(os.path.sep) + os.path.sep
        id_strings = {}
        maxval = len(contents)
@@ -2168,11 +2168,17 @@ def tar_contents(contents, root, tar, onProgress=None):
                tarinfo.gname = id_strings.setdefault(tarinfo.gid, str(tarinfo.gid))
 
                if stat.S_ISREG(lst.st_mode):
-                       f = file(path)
-                       try:
-                               tar.addfile(tarinfo, f)
-                       finally:
-                               f.close()
+                       if protect and protect(path):
+                               # Create an empty file as a place holder in order to avoid
+                               # potential collision-protect issues.
+                               tarinfo.size = 0
+                               tar.addfile(tarinfo)
+                       else:
+                               f = open(path)
+                               try:
+                                       tar.addfile(tarinfo, f)
+                               finally:
+                                       f.close()
                else:
                        tar.addfile(tarinfo)
                if onProgress: