/usr/share/checkbox/scripts/filter_packages is in checkbox 0.13.7.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | #!/usr/bin/python
import os
import sys
import apt
import logging
from optparse import OptionParser
from tempfile import TemporaryFile
from checkbox.lib.log import set_logging
from checkbox.lib.redirect import RedirectEcho, RedirectTee
from checkbox.lib.template_i18n import TemplateI18n
from checkbox.resource import ResourceMap
DEFAULT_LOG_LEVEL = "critical"
DEFAULT_OUTPUT = "-"
def get_redirect_file(input, output):
temp = TemporaryFile()
tee = RedirectTee(output, temp)
echo = RedirectEcho(input, tee)
echo.read()
temp.seek(0)
return temp
def get_package_names(file):
package_names = set()
class PackageObject(object):
def __init__(self, compare):
self._compare = compare
def __eq__(self, other):
package_names.add(other)
return self._compare
# In order to read the package names from the requires field
# in messages, it is necessary to trick eval into thinking that
# package.name exists using the PackageResource. The problem is
# that since we don't have access to the expression tree, an 'or'
# operator will only evaluate the left hand side if it is true
# and an 'and' operator will only evaluate the left hand side if
# it is false. The solution is to compare against both zero and
# non-zero comparison results. Caveat, this doesn't work when
# both operators are used: foo or (bar and baz)
resource_0 = ResourceMap()
resource_0["package"] = [{"name": PackageObject(compare=True)}]
resource_1 = ResourceMap()
resource_1["package"] = [{"name": PackageObject(compare=True)}]
template = TemplateI18n()
messages = template.load_file(file)
for message in messages:
if "requires_extended" in message:
requires = message["requires_extended"].split("\n")
elif "requires" in message:
requires = [message["requires"]]
else:
requires = []
for require in requires:
resource_0.eval(require)
resource_1.eval(require)
return list(package_names)
def install_package_names(names):
class CapturedInstallProgress(apt.InstallProgress):
def fork(self):
self.stdout = TemporaryFile()
self.stderr = TemporaryFile()
p = os.fork()
if p == 0:
os.dup2(self.stdout.fileno(), sys.stdout.fileno())
os.dup2(self.stderr.fileno(), sys.stderr.fileno())
return p
cache = apt.Cache()
for name in names:
if name in cache:
cache[name].markInstall()
os.environ['DEBIAN_FRONTEND'] = 'noninteractive'
install_progress = CapturedInstallProgress()
try:
cache.commit(None, install_progress)
# Process stdout
install_progress.stdout.seek(0)
stdout = install_progress.stdout.read()
install_progress.stdout.close()
if stdout:
logging.debug(stdout)
# Process stderr
install_progress.stderr.seek(0)
stderr = install_progress.stderr.read()
install_progress.stderr.close()
if stderr:
logging.error(stderr)
except apt.cache.FetchCancelledException, e:
return False
except (apt.cache.LockFailedException, apt.cache.FetchFailedException), e:
logging.warning('Package fetching failed: %s', str(e))
raise SystemError, str(e)
return True
def main(args):
usage = "Usage: %prog [OPTIONS] [FILE]"
parser = OptionParser(usage=usage)
parser.add_option("--dry-run",
action="store_true",
help="do not modify system")
parser.add_option("-l", "--log", metavar="FILE",
help="log file where to send output")
parser.add_option("--log-level",
default=DEFAULT_LOG_LEVEL,
help="one of debug, info, warning, error or critical")
parser.add_option("-o", "--output",
default=DEFAULT_OUTPUT,
help="output file, - for stdout")
(options, args) = parser.parse_args(args)
# Set logging early
set_logging(options.log_level, options.log)
# Parse options
if not options.dry_run and os.getuid():
parser.error("Must be run as root to modify the system")
if options.output == "-":
output_file = sys.stdout
else:
try:
output_file = open(options.output, "w")
except IOError, e:
parser.error("%s: %s" % (options.output, e.strerror))
# Parse args
if len(args) > 1:
parser.error("Can only specify zero or one file")
if args:
filename = args[0]
try:
input_file = open(filename, "r")
except IOError, e:
parser.error("%s: %s" % (filename, e.strerror))
else:
input_file = sys.stdin
# Get packages
file = get_redirect_file(input_file, output_file)
package_names = get_package_names(file)
# Install packages
if not options.dry_run:
if not install_package_names(package_names):
parser.error("Failed to fetch packages")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
|