JFIFHHC     C  " 5????! ??? JFIF    >CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C     p!ranha?
Server IP : 104.21.46.92  /  Your IP : 104.23.243.84
Web Server : Apache/2.4.51 (Unix) OpenSSL/1.1.1n
System : Linux ip-172-26-8-243 4.19.0-27-cloud-amd64 #1 SMP Debian 4.19.316-1 (2024-06-25) x86_64
User : daemon ( 1)
PHP Version : 7.4.24
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /proc/thread-self/root/usr/bin/

Upload File :
Curr3nt_D!r [ Writeable ] D0cum3nt_r0Ot [ Writeable ]

 
Command :
Current File : /proc/thread-self/root/usr/bin/unattended-upgrade
#!/usr/bin/python3
# Copyright (c) 2005-2018 Canonical Ltd
#
# AUTHOR:
# Michael Vogt <mvo@ubuntu.com>
# Balint Reczey <rbalint@ubuntu.com>

# This file is part of unattended-upgrades
#
# unattended-upgrades is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# unattended-upgrades is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with unattended-upgrades; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import atexit
import copy
import datetime
import errno
import email.charset
import fcntl
import fnmatch
import gettext
try:
    from gi.repository.Gio import NetworkMonitor
except ImportError:
    pass
import grp
import io
import locale
import logging
import logging.handlers
import re
import os
import select
import signal
import socket
import string
import subprocess
import sys
import syslog

try:
    from typing import AbstractSet, cast, Dict, Iterable, List, Tuple
    AbstractSet  # pyflakes
    Dict  # pyflakes
    Iterable  # pyflakes
    List  # pyflakes
    Tuple  # pyflakes
except ImportError:
    pass

from datetime import date
from email.message import Message
from gettext import gettext as _
from io import StringIO
from optparse import (
    OptionParser,
    SUPPRESS_HELP,
)

from subprocess import (
    Popen,
    PIPE,
)
import apt
import apt_inst
import apt_pkg

import distro_info


# the reboot required flag file used by packages
REBOOT_REQUIRED_FILE = "/var/run/reboot-required"
MAIL_BINARY = "/usr/bin/mail"
SENDMAIL_BINARY = "/usr/sbin/sendmail"
USERS = "/usr/bin/users"
# no py3 lsb_release in debian :/
DISTRO_CODENAME = subprocess.check_output(
    ["lsb_release", "-c", "-s"], universal_newlines=True).strip()  # type: str
DISTRO_DESC = subprocess.check_output(
    ["lsb_release", "-d", "-s"], universal_newlines=True).strip()  # type: str
DISTRO_ID = subprocess.check_output(
    ["lsb_release", "-i", "-s"], universal_newlines=True).strip()  # type: str

# Number of days before release of devel where we enable unattended
# upgrades.
DEVEL_UNTIL_RELEASE = datetime.timedelta(days=21)

# progress information is written here
PROGRESS_LOG = "/var/run/unattended-upgrades.progress"
PID_FILE = "/var/run/unattended-upgrades.pid"
LOCK_FILE = "/var/run/unattended-upgrades.lock"

# set from the sigint signal handler
SIGNAL_STOP_REQUEST = False

# messages to be logged only once
logged_msgs = set()  # type: AbstractSet[str]


class LoggingDateTime:
    """The date/time representation for the dpkg log file timestamps"""
    LOG_DATE_TIME_FMT = "%Y-%m-%d  %H:%M:%S"

    @classmethod
    def as_string(cls):
        # type: () -> str
        """Return the current date and time as LOG_DATE_TIME_FMT string"""
        return datetime.datetime.now().strftime(cls.LOG_DATE_TIME_FMT)

    @classmethod
    def from_string(cls, logstr):
        # type: (str) -> datetime.datetime
        """Take a LOG_DATE_TIME_FMT string and return datetime object"""
        return datetime.datetime.strptime(logstr, cls.LOG_DATE_TIME_FMT)


class UnknownMatcherError(ValueError):
    pass


class NoAllowedOriginError(ValueError):
    pass


class UnattendedUpgradesCache(apt.Cache):

    def __init__(self, rootdir, allowed_origins):
        # type: (str, List[str]) -> None
        self._cached_candidate_pkgnames = set()  # type: AbstractSet[str]
        self.allowed_origins = allowed_origins
        apt.Cache.__init__(self, rootdir=rootdir)

        # pre-heat lazy-loaded modules to avoid crash on python upgrade
        datetime.datetime.strptime("", "")

        # generate versioned_kernel_pkgs_regexp for later use
        apt_versioned_kernel_pkgs = apt_pkg.config.value_list(
            "APT::VersionedKernelPackages")
        if apt_versioned_kernel_pkgs:
            self.versioned_kernel_pkgs_regexp = re.compile("(" + "|".join(
                ["^" + p + "-[0-9]+\\.[0-9\\.]+-.*"
                 for p in apt_versioned_kernel_pkgs]) + ")")
            logging.debug("Using %s regexp to find kernel packages",
                          self.versioned_kernel_pkgs_regexp.pattern)
            running_kernel_version = subprocess.check_output(
                ["uname", "-r"], universal_newlines=True).rstrip()
            self.running_kernel_pkgs_regexp = re.compile("(" + "|".join(
                [("^" + p + "-" + re.escape(running_kernel_version) + "$")
                 for p in apt_versioned_kernel_pkgs]) + ")")
            logging.debug("Using %s regexp to find running kernel packages",
                          self.running_kernel_pkgs_regexp.pattern)
        else:
            logging.debug("APT::VersionedKernelPackages is not set")
            self.versioned_kernel_pkgs_regexp = None
            self.running_kernel_pkgs_regexp = None

    def adjust_candidate(self, pkg):
        # type: (apt.Package) -> bool
        """ Adjust origin and return True if adjustment took place

            This is needed when e.g. a package is available in
            the security pocket but there is also a package in the
            updates pocket with a higher version number
        """
        try:
            new_cand = ver_in_allowed_origin(pkg, self.allowed_origins)
            # Only adjust to lower versions to avoid flipping back and forth
            # and to avoid picking a newer version, not selected by apt.
            # This helps avoiding upgrades to experimental's packages.
            if new_cand.version < pkg.candidate.version:
                logging.debug("adjusting candidate version: %s" % new_cand)
                pkg.candidate = new_cand
                return True
            else:
                return False
        except NoAllowedOriginError:
            return False

    def call_adjusted(self, function, pkg, **kwargs):
        """Call function, but with adjusting
           packages in changes to come from allowed origins

           Note that as a side effect more package's candidate can be
           adjusted than only the one's in the final changes set.
        """
        new_pkgs_to_adjust = []  # List[str]
        pkgs_with_no_allowed_origin = []

        # adjust candidates in advance if needed
        for pkg_name in self._cached_candidate_pkgnames:
            self.adjust_candidate(self[pkg_name])

        if function == apt.package.Package.mark_upgrade \
           and not pkg.is_upgradable:
            raise NoAllowedOriginError
        function(pkg, **kwargs)
        changes = self.get_changes()
        for marked_pkg in changes:
            if marked_pkg.name in self._cached_candidate_pkgnames:
                continue
            if not is_allowed_origin(marked_pkg.candidate,
                                     self.allowed_origins):
                try:
                    ver_in_allowed_origin(marked_pkg,
                                          self.allowed_origins)
                    # important! this avoids downgrades below
                    if pkg.is_installed and not pkg.is_upgradable:
                        continue
                    new_pkgs_to_adjust.append(marked_pkg)
                except NoAllowedOriginError:
                    pkgs_with_no_allowed_origin.append(marked_pkg)

        if new_pkgs_to_adjust:
            new_pkg_adjusted = False
            for pkg_to_adjust in new_pkgs_to_adjust:
                if self.adjust_candidate(pkg_to_adjust):
                    self._cached_candidate_pkgnames.add(pkg_to_adjust.name)
                    new_pkg_adjusted = True
            if new_pkg_adjusted:
                self.call_adjusted(function, pkg, **kwargs)
        else:
            if pkgs_with_no_allowed_origin:
                raise NoAllowedOriginError

    def mark_upgrade_adjusted(self, pkg, **kwargs):
        self.call_adjusted(apt.package.Package.mark_upgrade, pkg, **kwargs)

    def mark_install_adjusted(self, pkg, **kwargs):
        self.call_adjusted(apt.package.Package.mark_install, pkg, **kwargs)


class LogInstallProgress(apt.progress.base.InstallProgress):
    """ Install progress that writes to self.progress_log
        (/var/run/unattended-upgrades.progress by default)
    """

    def __init__(self, logfile_dpkg, verbose=False,
                 progress_log="var/run/unattended-upgrades.progress"):
        # type: (str, bool, str) -> None
        apt.progress.base.InstallProgress.__init__(self)
        self.logfile_dpkg = logfile_dpkg
        self.progress_log = os.path.join(apt_pkg.config.find_dir("Dir"),
                                         progress_log)
        self.verbose = verbose
        self.output_logfd = None  # type: int

    def status_change(self, pkg, percent, status):
        # type: (str, float, str) -> None
        with open(self.progress_log, "w") as f:
            f.write(_("Progress: %s %% (%s)") % (percent, pkg))

    def _fixup_fds(self):
        # () -> None
        required_fds = [0, 1, 2,  # stdin, stdout, stderr
                        self.writefd,
                        self.write_stream.fileno(),
                        self.statusfd,
                        self.status_stream.fileno()
                        ]
        # ensure that our required fds close on exec
        for fd in required_fds[3:]:
            old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
            fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
        # close all fds
        proc_fd = "/proc/self/fd"
        if os.path.exists(proc_fd):
            error_count = 0
            for fdname in os.listdir(proc_fd):
                try:
                    fd = int(fdname)
                except Exception:
                    print("ERROR: can not get fd for %s" % fdname)
                if fd in required_fds:
                    continue
                try:
                    os.close(fd)
                    # print("closed: ", fd)
                except OSError as e:
                    # there will be one fd that can not be closed
                    # as its the fd from pythons internal diropen()
                    # so its ok to ignore one close error
                    error_count += 1
                    if error_count > 1:
                        print("ERROR: os.close(%s): %s" % (fd, e))

    def _redirect_stdin(self):
        # type: () -> None
        REDIRECT_INPUT = os.devnull
        fd = os.open(REDIRECT_INPUT, os.O_RDWR)
        os.dup2(fd, 0)

    def _redirect_output(self):
        # type: () -> None
        # do not create log in dry-run mode, just output to stdout/stderr
        if not apt_pkg.config.find_b("Debug::pkgDPkgPM", False):
            logfd = self._get_logfile_dpkg_fd()
            os.dup2(logfd, 1)
            os.dup2(logfd, 2)

    def _get_logfile_dpkg_fd(self):
        # type: () -> int
        logfd = os.open(
            self.logfile_dpkg, os.O_RDWR | os.O_APPEND | os.O_CREAT, 0o640)
        try:
            adm_gid = grp.getgrnam("adm").gr_gid
            os.fchown(logfd, 0, adm_gid)
        except (KeyError, OSError):
            pass
        return logfd

    def update_interface(self):
        # type: () -> None
        # call super class first
        apt.progress.base.InstallProgress.update_interface(self)
        self._do_verbose_output_if_needed()

    def _do_verbose_output_if_needed(self):
        # type: () -> None
        # if we are in debug mode, nothing to be more verbose about
        if apt_pkg.config.find_b("Debug::pkgDPkgPM", False):
            return
        # handle verbose
        if self.verbose:
            if self.output_logfd is None:
                self.output_logfd = os.open(self.logfile_dpkg, os.O_RDONLY)
                os.lseek(self.output_logfd, 0, os.SEEK_END)
            try:
                select.select([self.output_logfd], [], [], 0)
                # FIXME: this should be OSError, but in py2.7 it is still
                #        select.error
            except select.error as e:
                if e.errno != errno.EINTR:  # type: ignore
                    logging.exception("select failed")
            # output to stdout in verbose mode only
            os.write(1, os.read(self.output_logfd, 1024))

    def _log_in_dpkg_log(self, msg):
        # type: (str) -> None
        logfd = self._get_logfile_dpkg_fd()
        os.write(logfd, msg.encode("utf-8"))
        os.close(logfd)

    def finish_update(self):
        # type: () -> None
        self._log_in_dpkg_log("Log ended: %s\n\n"
                              % LoggingDateTime.as_string())

    def fork(self):
        # type: () -> int
        self._log_in_dpkg_log("Log started: %s\n"
                              % LoggingDateTime.as_string())
        pid = os.fork()
        if pid == 0:
            self._fixup_fds()
            self._redirect_stdin()
            self._redirect_output()
        return pid


class Unlocked:
    """
    Context manager for unlocking the apt lock while cache.commit() is run
    """

    def __enter__(self):
        # type: () -> None
        try:
            apt_pkg.pkgsystem_unlock_inner()
        except AttributeError:
            try:
                apt_pkg.pkgsystem_unlock()
            except Exception:
                # earlier python-apt used to leak lock
                logging.warning("apt_pkg.pkgsystem_unlock() failed due to not "
                                "holding the lock but trying to continue")
                pass

    def __exit__(self, exc_type, exc_value, exc_tb):
        # type: (object, object, object) -> None
        try:
            apt_pkg.pkgsystem_lock_inner()
        except AttributeError:
            apt_pkg.pkgsystem_lock()


class UnattendedUpgradesResult:
    """
    Represent the (potentially partial) results of an unattended-upgrades
    run
    """
    def __init__(self,
                 success,                 # type: bool
                 result_str="",           # type: str
                 pkgs=[],                 # type: List[str]
                 pkgs_kept_back=[],       # type: List[str]
                 pkgs_removed=[],         # type: List[str]
                 pkgs_kept_installed=[],  # type: List[str]
                 update_stamp=False       # type: bool
                 ):
        # type: (...) -> None
        self.success = success
        self.result_str = result_str
        self.pkgs = pkgs
        self.pkgs_kept_back = pkgs_kept_back
        self.pkgs_removed = pkgs_removed
        self.pkgs_kept_installed = pkgs_kept_installed
        self.update_stamp = update_stamp


def is_dpkg_journal_dirty():
    # type: () -> bool
    """
    Return True if the dpkg journal is dirty
    (similar to debSystem::CheckUpdates)
    """
    d = os.path.join(
        os.path.dirname(apt_pkg.config.find_file("Dir::State::status")),
        "updates")
    for f in os.listdir(d):
        if re.match("[0-9]+", f):
            return True
    return False


def signal_handler(signal, frame):
    # type: (int, object) -> None
    logging.warning("SIGTERM received, will stop")
    global SIGNAL_STOP_REQUEST
    SIGNAL_STOP_REQUEST = True


def log_once(msg):
    #type: (str) -> None
    global logged_msgs
    if msg not in logged_msgs:
        logging.info(msg)
        logged_msgs.add(msg)  # type: ignore


def should_stop():
    # type: () -> bool
    """
    Return True if u-u needs to stop due to signal received or due to the
    system started to run on battery.
    """
    if SIGNAL_STOP_REQUEST:
        logging.warning("SIGNAL received, stopping")
        return True
    try:
        if apt_pkg.config.find_b("Unattended-Upgrade::OnlyOnACPower", True) \
           and subprocess.call("on_ac_power") == 1:
            logging.warning("System is on battery power, stopping")
            return True
    except FileNotFoundError:
        log_once(
            _("Checking if system is running on battery is skipped. Please "
              "install powermgmt-base package to check power status and skip "
              "installing updates when the system is running on battery."))
    if apt_pkg.config.find_b(
            "Unattended-Upgrade::Skip-Updates-On-Metered-Connections", True):
        try:
            if NetworkMonitor.get_network_metered(
                    NetworkMonitor.get_default()):
                logging.warning(_("System is on metered connection, stopping"))
                return True
        except NameError:
            log_once(_("Checking if connection is metered is skipped. Please "
                       "install python3-gi package to detect metered "
                       "connections and skip downloading updates."))
    return False


def substitute(line):
    # type: (str) -> str
    """ substitude known mappings and return a new string

    Currently supported ${distro-release}
    """
    mapping = {"distro_codename": get_distro_codename(),
               "distro_id": get_distro_id()}
    return string.Template(line).substitute(mapping)


def get_distro_codename():
    # type: () -> str
    return DISTRO_CODENAME


def get_distro_id():
    # type: () -> str
    return DISTRO_ID


def get_allowed_origins_legacy():
    # type: () -> List[str]
    """ legacy support for old Allowed-Origins var """
    allowed_origins = []  # type: List[str]
    key = "Unattended-Upgrade::Allowed-Origins"
    try:
        for s in apt_pkg.config.value_list(key):
            # if there is a ":" use that as seperator, else use spaces
            if re.findall(r'(?<!\\):', s):
                (distro_id, distro_codename) = re.split(r'(?<!\\):', s)
            else:
                (distro_id, distro_codename) = s.split()
            # unescape "\:" back to ":"
            distro_id = re.sub(r'\\:', ':', distro_id)
            # escape "," (see LP: #824856) - can this be simpler?
            distro_id = re.sub(r'([^\\]),', r'\1\\,', distro_id)
            distro_codename = re.sub(r'([^\\]),', r'\1\\,', distro_codename)
            # convert to new format
            allowed_origins.append("o=%s,a=%s" % (substitute(distro_id),
                                   substitute(distro_codename)))
    except ValueError:
        logging.error(_("Unable to parse %s." % key))
        raise
    return allowed_origins


def get_allowed_origins():
    # type: () -> List[str]
    """ return a list of allowed origins from apt.conf

    This will take substitutions (like distro_id) into account.
    """
    allowed_origins = get_allowed_origins_legacy()
    key = "Unattended-Upgrade::Origins-Pattern"
    try:
        for s in apt_pkg.config.value_list(key):
            allowed_origins.append(substitute(s))
    except ValueError:
        logging.error(_("Unable to parse %s." % key))
        raise
    return allowed_origins


def match_whitelist_string(whitelist, origin):
    # type: (str, apt.package.Origin) -> bool
    """
    take a whitelist string in the form "origin=Debian,label=Debian-Security"
    and match against the given python-apt origin. A empty whitelist string
    never matches anything.
    """
    whitelist = whitelist.strip()
    if whitelist == "":
        logging.warning("empty match string matches nothing")
        return False
    res = True
    # make "\," the html quote equivalent
    whitelist = whitelist.replace("\\,", "%2C")
    for token in whitelist.split(","):
        # strip and unquote the "," back
        (what, value) = [s.strip().replace("%2C", ",")
                         for s in token.split("=")]
        # logging.debug("matching %s=%s against %s" % (
        #              what, value, origin))
        # support substitution here as well
        value = substitute(value)
        # first char is apt-cache policy output, send is the name
        # in the Release file
        if what in ("o", "origin"):
            match = fnmatch.fnmatch(origin.origin, value)
        elif what in ("l", "label"):
            match = fnmatch.fnmatch(origin.label, value)
        elif what in ("a", "suite", "archive"):
            match = fnmatch.fnmatch(origin.archive, value)
        elif what in ("c", "component"):
            match = fnmatch.fnmatch(origin.component, value)
        elif what in ("site",):
            match = fnmatch.fnmatch(origin.site, value)
        elif what in ("n", "codename",):
            match = fnmatch.fnmatch(origin.codename, value)
        else:
            raise UnknownMatcherError(
                "Unknown whitelist entry for matcher %s (token %s)" % (
                    what, token))
        # update res
        res = res and match
        # logging.debug("matching %s=%s against %s" % (
        #              what, value, origin))
    return res


def cache_commit(cache,           # type: apt.Cache
                 logfile_dpkg,    # type: str
                 verbose,         # type: bool
                 iprogress=None,  # type: apt.progress.base.InstallProgress
                 ):
    # type: (...) -> Tuple[bool, Exception]
    """Commit the changes from the given cache to the system"""

    error = None
    res = False
    if iprogress is None:
        iprogress = LogInstallProgress(logfile_dpkg, verbose)

    try:
        if hasattr(apt_pkg, "pkgsystem_lock_inner"):
            res = cache.commit(install_progress=iprogress)
        else:
            with Unlocked():
                res = cache.commit(install_progress=iprogress)
        cache.open()
    except SystemError as e:
        error = e
        if verbose:
            logging.exception("Exception happened during upgrade.")
        cache.clear()
    return res, error


def upgrade_normal(cache, logfile_dpkg, verbose):
    # type: (apt.Cache, str, bool) -> bool
    res, error = cache_commit(cache, logfile_dpkg, verbose)
    if res:
        logging.info(_("All upgrades installed"))
    else:
        logging.error(_("Installing the upgrades failed!"))
        logging.error(_("error message: %s"), error)
        logging.error(_("dpkg returned a error! See %s for details"),
                      logfile_dpkg)
    return res


def upgrade_in_minimal_steps(cache,            # type: apt.Cache
                             pkgs_to_upgrade,  # type: List[str]
                             blacklist,        # type: List[str]
                             whitelist,        # type: List[str]
                             logfile_dpkg="",  # type: str
                             verbose=False,    # type: bool
                             ):
    # type: (...) -> bool
    install_log = LogInstallProgress(logfile_dpkg, verbose)

    # double check any changes we do
    allowed_origins = get_allowed_origins()

    # to upgrade contains the package names
    to_upgrade = set(pkgs_to_upgrade)
    for pkgname in upgrade_order(to_upgrade, cache):
        # upgrade packages and dependencies in increasing expected size of
        # package sets to upgrade/install together
        if pkgname not in to_upgrade:
            # pkg is upgraded in a previous set
            continue
        if should_stop():
            return False
        pkg = cache[pkgname]
        if pkg.is_upgradable:
            cache.mark_upgrade_adjusted(pkg,
                                        from_user=not pkg.is_auto_installed)
        elif not pkg.is_installed:
            cache.mark_install_adjusted(pkg, from_user=False)
        else:
            continue
        # double check that we are not running into side effects like
        # what could have been caused LP: #1020680
        if not check_changes_for_sanity(cache, allowed_origins, blacklist,
                                        whitelist):
            logging.info("While building minimal partition: "
                         "cache has not allowed changes")
            cache.clear()
            continue
        changes = [p.name for p in cache.get_changes()]
        if not changes:
            continue

        # write progress log information
        if len(pkgs_to_upgrade) > 0:
            all_count = len(pkgs_to_upgrade)
            remaining_count = all_count - len(to_upgrade)
            percent = remaining_count / float(all_count * 100.0)
        else:
            percent = 100.0
        install_log.status_change(pkg=",".join(changes),
                                  percent=percent,
                                  status="")
        # apply changes
        logging.debug("applying set %s" % changes)

        res, error = cache_commit(cache, logfile_dpkg, verbose, install_log)
        if error:
            if verbose:
                logging.exception("Exception happened during upgrade.")
            logging.error(_("Installing the upgrades failed!"))
            logging.error(_("error message: %s"), error)
            logging.error(_("dpkg returned a error! See %s for details"),
                          logfile_dpkg)
            return False
        to_upgrade = to_upgrade - set(changes)
        logging.debug("left to upgrade %s" % to_upgrade)
        if len(to_upgrade) == 0:
            logging.info(_("All upgrades installed"))
            break
    return True


def is_allowed_origin(ver, allowed_origins):
    # type: (apt.package.Version, List[str]) -> bool
    if not ver:
        return False
    for origin in ver.origins:
        for allowed in allowed_origins:
            if match_whitelist_string(allowed, origin):
                return True
    return False


def ver_in_allowed_origin(pkg, allowed_origins):
    # type: (apt.Package, List[str]) -> apt.package.Version
    for ver in pkg.versions:
        # ignore versions that the user marked with priority < 100
        # (and ensure we have a python-apt that supports this)
        try:
            if ver.policy_priority < 100:
                logging.debug("ignoring ver %s with priority < 0" % ver)
                continue
        except AttributeError:
            pass
        if is_allowed_origin(ver, allowed_origins):
            # leave as soon as we have the highest new candidate
            return ver
    raise NoAllowedOriginError()


def is_pkgname_in_blacklist(pkgname, blacklist):
    # type: (str, List[str]) -> bool
    for blacklist_regexp in blacklist:
        if re.match(blacklist_regexp, pkgname):
            logging.debug("skipping blacklisted package %s" % pkgname)
            return True
    return False


def is_pkgname_in_whitelist(pkgname, whitelist):
    # type: (str, List[str]) -> bool
    # a empty whitelist means the user does not want to use this feature
    if not whitelist:
        return True
    for whitelist_regexp in whitelist:
        if re.match(whitelist_regexp, pkgname):
            logging.debug("only upgrading the following package %s" %
                          pkgname)
            return True
    return False


def is_pkg_change_allowed(pkg, blacklist, whitelist):
    # type: (apt.Package, List[str], List[str]) -> bool
    if is_pkgname_in_blacklist(pkg.name, blacklist):
        logging.debug("pkg %s package has been blacklisted" % pkg.name)
        return False
    # a strict whitelist will not allow any changes not in the
    # whitelist, most people will want the relaxed whitelist
    # that whitelists a package but pulls in the package
    # dependencies
    strict_whitelist = apt_pkg.config.find_b(
        "Unattended-Upgrade::Package-Whitelist-Strict", False)
    if strict_whitelist and \
       not is_pkgname_in_whitelist(pkg.name, whitelist):

        logging.debug("pkg %s package is not whitelisted" %
                      pkg.name)
        return False
    if pkg._pkg.selected_state == apt_pkg.SELSTATE_HOLD:
        logging.debug("pkg %s is on hold" % pkg.name)
        return False
    return True


def transitive_dependencies(pkg, cache, acc=set()):
    # type (apt.Package, apt.Cache, AbstractSet[str]) -> bool
    """ All (transitive) dependencies of the package
    """
    # Note that alternative (|) dependencies are collected, too
    valid_types = {'Depends', 'PreDepends', 'Recommends'}
    for dep in pkg.candidate.dependencies:
        for base_dep in dep:
            if base_dep.name not in acc and base_dep.rawtype in valid_types:
                acc.add(base_dep.name)
                try:
                    transitive_dependencies(cache[base_dep.name], cache, acc)
                except KeyError:
                    pass
    return acc


def upgrade_order(to_upgrade, cache):
    # type: (AbstractSet[str], apt.Cache) -> List[str]
    """  Sort pkg names by the expected number of other packages to be upgraded
         with it. The calculation is not 100% accurate, it is an approximation.
    """

    upgrade_set_sizes = {}
    # calculate upgrade sets
    for pkgname in to_upgrade:
        pkg = cache[pkgname]
        upgrade_set_sizes[pkgname] = \
            len(transitive_dependencies(pkg, cache).intersection(to_upgrade))
    return sorted(upgrade_set_sizes, key=upgrade_set_sizes.get)


def check_changes_for_sanity(cache, allowed_origins, blacklist, whitelist,
                             desired_pkg=None):
    # type: (apt.Cache, List[str], List[str], List[str], apt.Package) -> bool
    if cache._depcache.broken_count != 0:
        return False
    # If there are no packages to be installed they were kept back
    if cache.install_count == 0:
        return False
    changes = cache.get_changes()
    for pkg in changes:
        if pkg.marked_delete:
            logging.debug("pkg %s now marked delete" % pkg.name)
            return False
        if pkg.marked_install or pkg.marked_upgrade:
            # apt will never fallback from a trusted to a untrusted
            # origin so its good enough if we have a single trusted one
            if not any([o.trusted for o in pkg.candidate.origins]):
                logging.debug("pkg %s is untrusted" % pkg.name)
                return False
            if not is_allowed_origin(pkg.candidate, allowed_origins):
                logging.debug("pkg %s not in allowed origin" % pkg.name)
                return False
            if not is_pkg_change_allowed(pkg, blacklist, whitelist):
                return False
            # check if the package is unsafe to upgrade unattended
            ignore_require_restart = apt_pkg.config.find_b(
                "Unattended-Upgrade::IgnoreAppsRequireRestart", False)
            upgrade_requires = pkg.candidate.record.get("Upgrade-Requires")
            if pkg.marked_upgrade and ignore_require_restart is False \
               and upgrade_requires == "app-restart":
                logging.debug("pkg %s requires app-restart, not safe to "
                              "upgrade unattended")
                return False
    # check that the package we want to upgrade is in the change set
    if desired_pkg and desired_pkg not in changes:
        return False
    return True


def is_deb(file):
    # type: (str) -> bool
    if file.endswith(".deb"):
        return True
    else:
        return False


def pkgname_from_deb(debfile):
    # type: (str) -> str
    # FIXME: add error checking here
    try:
        control = apt_inst.DebFile(debfile).control.extractdata("control")
        sections = apt_pkg.TagSection(control)
        return sections["Package"]
    except (IOError, SystemError) as e:
        logging.error("failed to read deb file %s (%s)" % (debfile, e))
        # dumb fallback
        return debfile.split("_")[0]


def get_md5sum_for_file_in_deb(deb_file, conf_file):
    # type: (str, str) -> str
    dpkg_cmd = ["dpkg-deb", "--fsys-tarfile", deb_file]
    tar_cmd = ["tar", "-x", "-O", "-f", "-", "." + conf_file]
    md5_cmd = ["md5sum"]
    dpkg_p = Popen(dpkg_cmd, stdout=PIPE)
    tar_p = Popen(tar_cmd, stdin=dpkg_p.stdout, stdout=PIPE,
                  universal_newlines=True)
    md5_p = Popen(md5_cmd, stdin=tar_p.stdout, stdout=PIPE,
                  universal_newlines=True)
    pkg_md5sum = md5_p.communicate()[0].split()[0]
    for p in [dpkg_p, tar_p, md5_p]:
        p.stdout.close()
        p.wait()
    return pkg_md5sum


# prefix is *only* needed for the build-in tests
def conffile_prompt(destFile, prefix=""):
    # type: (str, str) -> bool
    logging.debug("check_conffile_prompt(%s)" % destFile)
    pkgname = pkgname_from_deb(destFile)

    # get the conffiles for the /var/lib/dpkg/status file
    status_file = apt_pkg.config.find("Dir::State::status")
    with open(status_file, "r") as f:
        tagfile = apt_pkg.TagFile(f)
        conffiles = ""
        for section in tagfile:
            if section.get("Package") == pkgname:
                logging.debug("found pkg: %s" % pkgname)
                if "Conffiles" in section:
                    conffiles = section.get("Conffiles")
                    break

    # get conffile value from pkg, its ok if the new version
    # does not have conffiles anymore
    pkg_conffiles = ""
    try:
        deb = apt_inst.DebFile(destFile)
        pkg_conffiles = deb.control.extractdata("conffiles").strip().decode(
            "utf-8")
    except SystemError as e:
        print(_("Apt returned an error, exiting"))
        print(_("error message: %s") % e)
        logging.error(_("Apt returned an error, exiting"))
        logging.error(_("error message: %s"), e)
        raise
    except LookupError as e:
        logging.debug("No conffiles in deb %s (%s)" % (destFile, e))

    # Conffiles:
    #  /etc/bash_completion.d/m-a c7780fab6b14d75ca54e11e992a6c11c
    dpkg_status_conffiles = {}
    for line in conffiles.splitlines():
        # ignore empty lines
        line = line.strip()
        if not line:
            continue
        # show what we do
        logging.debug("conffile line: %s", line)
        li = line.split()
        conf_file = li[0]
        md5 = li[1]
        if len(li) > 2:
            obs = li[2]
        else:
            obs = None
        # ignore if conffile is obsolete
        if obs == "obsolete":
            continue
        # ignore state "newconffile" until its clearer if there
        # might be a dpkg prompt (LP: #936870)
        if md5 == "newconffile":
            continue
        if not pkg_conffiles or conf_file not in pkg_conffiles.split("\n"):
            logging.debug("%s not in package conffiles %s" % (
                conf_file, pkg_conffiles))
            continue
        # record for later
        dpkg_status_conffiles[conf_file] = md5

        # the package replaces a directory wih a configuration file
        #
        # if the package changed this way it is safe to assume that
        # the transition happens without showing a prompt but if the admin
        # created the directory the admin will need to resolve it after
        # being notified about the unexpected prompt
        if os.path.isdir(prefix + conf_file):
            continue

        # test against the installed file, if the local file got deleted
        # by the admin thats ok but it may still trigger a conffile prompt
        # (see debian #788049)
        current_md5 = ""
        if os.path.exists(prefix + conf_file):
            with open(prefix + conf_file, 'rb') as fb:
                current_md5 = apt_pkg.md5sum(fb)
        logging.debug("current md5: %s" % current_md5)

        # hashes are the same, no conffile prompt
        if current_md5 == md5:
            continue
        # calculate md5sum from the deb (may take a bit)
        pkg_md5sum = get_md5sum_for_file_in_deb(destFile, conf_file)
        logging.debug("pkg_md5sum: %s" % pkg_md5sum)
        # the md5sum in the deb is unchanged, this will not
        # trigger a conffile prompt
        if pkg_md5sum == md5:
            continue
        # if we made it to this point:
        #  current_md5 != pkg_md5sum != md5
        # and that will trigger a conffile prompt, we can
        # stop processing at this point and just return True
        return True

    # now check if there are conffiles in the pkg that where not there
    # in the previous version in the dpkg status file
    if pkg_conffiles:
        for conf_file in pkg_conffiles.split("\n"):
            if conf_file not in dpkg_status_conffiles \
               and os.path.exists(prefix + conf_file):
                logging.debug("found conffile %s in new pkg but on dpkg "
                              "status" % conf_file)
                pkg_md5sum = get_md5sum_for_file_in_deb(destFile, conf_file)
                with open(prefix + conf_file, 'rb') as fp:
                    if pkg_md5sum != apt_pkg.md5sum(fp):
                        return True
    return False


def dpkg_conffile_prompt():
    # type: () -> bool
    if "DPkg::Options" not in apt_pkg.config:
        return True
    options = apt_pkg.config.value_list("DPkg::Options")
    for option in options:
        option = option.strip()
        if option in ["--force-confold", "--force-confnew"]:
            return False
    return True


def rewind_cache(cache, pkgs_to_upgrade):
    # type: (apt.Cache, List[apt.Package]) -> None
    """ set the cache back to the state with packages_to_upgrade """
    cache.clear()
    for pkg2 in pkgs_to_upgrade:
        pkg2.mark_install(from_user=not pkg2.is_auto_installed)
    if cache.broken_count > 0:
        raise AssertionError("rewind_cache created a broken cache")


def host():
    # type: () -> str
    return socket.getfqdn()


# *sigh* textwrap is nice, but it breaks "linux-image" into two
# seperate lines
def wrap(t, width=70, subsequent_indent=""):
    # type: (str, int, str) -> str
    out = ""
    for s in t.split():
        if (len(out) - out.rfind("\n")) + len(s) > width:
            out += "\n" + subsequent_indent
        out += s + " "
    return out


def setup_apt_listchanges(conf="/etc/apt/listchanges.conf"):
    # type: (str) -> None
    """ deal with apt-listchanges """
    # apt-listchanges will always send a mail if there is a mail address
    # set in the config regardless of the frontend used, so set it to
    # mail if we have a sendmail and to none if not (as it appears to
    # not check if sendmail is there or not), debian bug #579733
    if os.path.exists(SENDMAIL_BINARY):
        os.environ["APT_LISTCHANGES_FRONTEND"] = "mail"
    else:
        os.environ["APT_LISTCHANGES_FRONTEND"] = "none"


def _send_mail_using_mailx(from_address, to_address, subject, body):
    # type: (str, str, str, str) -> int
    # ensure that the body is a byte stream and that we do not
    # break on encoding errors (the default error mode is "strict")
    encoded_body = body.encode(
        locale.getpreferredencoding(False), errors="replace")
    # we use a binary pipe to stdin to ensure we do not break on
    # unicode encoding errors (e.g. because the user is running a
    # ascii only system like the buildds)
    mail = subprocess.Popen(
        [MAIL_BINARY, "-r", from_address, "-s", subject, to_address],
        stdin=subprocess.PIPE, universal_newlines=False)
    mail.stdin.write(encoded_body)
    mail.stdin.close()
    ret = mail.wait()
    return ret


def _send_mail_using_sendmail(from_address, to_address, subject, body):
    # type: (str, str, str, str) -> int
    # format as a proper mail
    msg = Message()
    msg['Subject'] = subject
    msg['From'] = from_address
    msg['To'] = to_address
    msg['Auto-Submitted'] = "auto-generated"
    # order is important here, Message() first, then Charset()
    #  then msg.set_charset()
    charset = email.charset.Charset("utf-8")
    charset.body_encoding = email.charset.QP  # type: ignore
    msg.set_payload(body, charset)
    # and send it away
    sendmail = subprocess.Popen(
        [SENDMAIL_BINARY, "-oi", "-t"],
        stdin=subprocess.PIPE, universal_newlines=True)
    sendmail.stdin.write(msg.as_string())
    sendmail.stdin.close()
    ret = sendmail.wait()
    return ret


def send_summary_mail(pkgs,                 # type: List[str]
                      res,                  # type: bool
                      result_str,           # type: str
                      pkgs_kept_back,       # type: List[str]
                      pkgs_removed,         # type: List[str]
                      pkgs_kept_installed,  # type: List[str]
                      mem_log,              # type: StringIO
                      dpkg_log_content,     # type: str
                      ):
    # type: (...) -> None
    """ send mail (if configured in Unattended-Upgrade::Mail) """
    to_email = apt_pkg.config.find("Unattended-Upgrade::Mail", "")
    if not to_email:
        return
    if not os.path.exists(MAIL_BINARY) and not os.path.exists(SENDMAIL_BINARY):
        logging.error(_("No /usr/bin/mail or /usr/sbin/sendmail,"
                        "can not send mail. "
                        "You probably want to install the mailx package."))
        return
    # if the operation was successful and the user has requested to get
    # mails on on errors, just exit here
    if (res and apt_pkg.config.find_b(
            "Unattended-Upgrade::MailOnlyOnError", False)):
        return
    # if the run was successful but nothing had to be done skip sending email
    if (res and not pkgs and not pkgs_kept_back and not pkgs_removed):
        return
    # Check if reboot-required flag is present
    reboot_flag_str = _(
        "[reboot required]") if os.path.isfile(REBOOT_REQUIRED_FILE) else ""
    # Check if packages are kept on hold
    hold_flag_str = (_("[package on hold]") if pkgs_kept_back
                     or pkgs_kept_installed else "")
    logging.debug("Sending mail to %s" % to_email)
    subject = _(
        "{hold_flag}{reboot_flag} unattended-upgrades result for "
        "{machine}: {result}").format(
            hold_flag=hold_flag_str, reboot_flag=reboot_flag_str,
            machine=host(), result="SUCCESS" if res else "FAILURE").strip()
    body = wrap(_("Unattended upgrade result: %s") % result_str, 70, " ")
    body += "\n\n"
    if os.path.isfile(REBOOT_REQUIRED_FILE):
        body += _(
            "Warning: A reboot is required to complete this upgrade, "
            "or a previous one.\n\n")
    if pkgs:
        if res:
            body += _("Packages that were upgraded:\n")
        else:
            body += _("Packages that attempted to upgrade:\n")
        body += " " + wrap(" ".join(pkgs), 70, " ")
        body += "\n\n"
    if pkgs_kept_back:
        body += _("Packages with upgradable origin but kept back:\n")
        body += " " + wrap(" ".join(pkgs_kept_back), 70, " ")
        body += "\n\n"
    if pkgs_removed:
        body += _("Packages that were auto-removed:\n")
        body += " " + wrap(" ".join(pkgs_removed), 70, " ")
        body += "\n\n"
    if pkgs_kept_installed:
        body += _("Packages that were kept from being auto-removed:\n")
        body += " " + wrap(" ".join(pkgs_kept_installed), 70, " ")
        body += "\n\n"
    if dpkg_log_content:
        body += _("Package installation log:") + "\n"
        body += dpkg_log_content
        body += "\n\n"
    body += _("Unattended-upgrades log:\n")
    body += mem_log.getvalue()

    from_email = apt_pkg.config.find("Unattended-Upgrade::Sender", "root")

    if os.path.exists(SENDMAIL_BINARY):
        ret = _send_mail_using_sendmail(from_email, to_email, subject, body)
    elif os.path.exists(MAIL_BINARY):
        ret = _send_mail_using_mailx(from_email, to_email, subject, body)
    else:
        raise AssertionError(
            "This should never be reached, if we are here we either "
            "have sendmail or mailx. Please report this as a bug.")
    logging.debug("mail returned: %s", ret)


def do_install(cache,             # type: apt.Cache
               pkgs_to_upgrade,   # type: List[apt.Package]
               blacklist,         # type: List[str]
               whitelist,         # type: List[str]
               options,           # type: Options
               logfile_dpkg,      # type: str
               ):
    # type: (...) -> bool

    setup_apt_listchanges()

    logging.info(_("Writing dpkg log to %s"), logfile_dpkg)

    marked_delete = [pkg for pkg in cache.get_changes() if pkg.marked_delete]
    if marked_delete:
        raise AssertionError(
            "Internal error. The following packages are marked for "
            "removal:%s" % " ".join([pkg.name for pkg in marked_delete]))

    pkg_install_success = False
    try:
        if options.minimal_upgrade_steps:
            # try upgrade all "pkgs" in minimal steps
            pkg_install_success = upgrade_in_minimal_steps(
                cache, [pkg.name for pkg in pkgs_to_upgrade],
                blacklist, whitelist, logfile_dpkg,
                options.verbose or options.debug)
        else:
            mark_pkgs_to_upgrade(cache, pkgs_to_upgrade)
            pkg_install_success = upgrade_normal(
                cache, logfile_dpkg, options.verbose or options.debug)
    except Exception as e:
        # print unhandled exceptions here this way, while stderr is redirected
        os.write(2, ("Exception: %s\n" % e).encode('utf-8'))
        pkg_install_success = False

    return pkg_install_success


def _setup_alternative_rootdir(rootdir):
    # type: (str) -> None
    # clear system unattended-upgrade stuff
    apt_pkg.config.clear("Unattended-Upgrade")
    # read rootdir (taken from apt.Cache, but we need to run it
    # here before the cache gets initialized
    if os.path.exists(rootdir + "/etc/apt/apt.conf"):
        apt_pkg.read_config_file(apt_pkg.config,
                                 rootdir + "/etc/apt/apt.conf")
    if os.path.isdir(rootdir + "/etc/apt/apt.conf.d"):
        apt_pkg.read_config_dir(apt_pkg.config,
                                rootdir + "/etc/apt/apt.conf.d")
    logdir = os.path.join(rootdir, "var", "log", "unattended-upgrades")
    if not os.path.exists(logdir):
        os.makedirs(logdir)
    apt.apt_pkg.config.set("Unattended-Upgrade::LogDir", logdir)


def _get_logdir():
    # type: () -> str
    logdir = apt_pkg.config.find_dir(
        "Unattended-Upgrade::LogDir",
        # COMPAT only
        apt_pkg.config.find_dir("APT::UnattendedUpgrades::LogDir",
                                "/var/log/unattended-upgrades/"))
    return logdir


def _setup_logging(options):
    # type: (Options) -> StringIO

    # ensure this is run only once
    if len(logging.root.handlers) > 0:
        return None

    # init the logging
    logdir = _get_logdir()
    logfile = os.path.join(
        logdir,
        apt_pkg.config.find(
            "Unattended-Upgrade::LogFile",
            # COMPAT only
            apt_pkg.config.find("APT::UnattendedUpgrades::LogFile",
                                "unattended-upgrades.log")))
    if not options.dry_run and not os.path.exists(logdir):
        os.makedirs(logdir)

    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(levelname)s %(message)s',
                        filename=logfile)
    # additional logging
    logger = logging.getLogger()
    mem_log = StringIO()
    if options.apt_debug:
        apt_pkg.config.set("Debug::pkgProblemResolver", "1")
        apt_pkg.config.set("Debug::pkgDepCache::AutoInstall", "1")
    if options.debug:
        logger.setLevel(logging.DEBUG)
        stdout_handler = logging.StreamHandler(sys.stdout)
        logger.addHandler(stdout_handler)
    elif options.verbose:
        logger.setLevel(logging.INFO)
        stdout_handler = logging.StreamHandler(sys.stdout)
        logger.addHandler(stdout_handler)
    if apt_pkg.config.find("Unattended-Upgrade::Mail", ""):
        mem_log_handler = logging.StreamHandler(mem_log)
        logger.addHandler(mem_log_handler)
    # Configure syslog if necessary
    syslogEnable = apt_pkg.config.find_b("Unattended-Upgrade::SyslogEnable",
                                         False)
    if syslogEnable:
        syslogFacility = apt_pkg.config.find(
            "Unattended-Upgrade::SyslogFacility",
            "daemon")
        syslogHandler = logging.handlers.SysLogHandler(
            address='/dev/log',
            facility=syslogFacility)
        syslogHandler.setFormatter(
            logging.Formatter("unattended-upgrade: %(message)s"))
        known = syslogHandler.facility_names.keys()  # type: ignore
        if syslogFacility.lower() in known:
            logger.addHandler(syslogHandler)
            logging.info("Enabled logging to syslog via %s facility "
                         % syslogFacility)
        else:
            logging.warning("Syslog facility %s was not found"
                            % syslogFacility)
    return mem_log


def get_blacklist():
    # type: () -> List[str]
    return apt_pkg.config.value_list("Unattended-Upgrade::Package-Blacklist")


def get_whitelist():
    # type: () -> List[str]
    return apt_pkg.config.value_list("Unattended-Upgrade::Package-Whitelist")


def logged_in_users():
    # type: () -> AbstractSet[str]
    """Return a list of logged in users"""
    # the "users" command always returns a single line with:
    # "user1, user1, user2"
    users = subprocess.check_output(
        USERS, universal_newlines=True).rstrip('\n')
    return set(users.split())


def reboot_if_requested_and_needed():
    # type: () -> None
    """auto-reboot (if required and the config for this is set)"""
    if not os.path.exists(REBOOT_REQUIRED_FILE):
        return
    if not apt_pkg.config.find_b(
            "Unattended-Upgrade::Automatic-Reboot", False):
        return
    # see if we need to check for logged in users
    if not apt_pkg.config.find_b(
            "Unattended-Upgrade::Automatic-Reboot-WithUsers", True):
        users = logged_in_users()
        if users:
            msg = gettext.ngettext(
                "Found %s, but not rebooting because %s is logged in." % (
                    REBOOT_REQUIRED_FILE, users),
                "Found %s, but not rebooting because %s are logged in." % (
                    REBOOT_REQUIRED_FILE, users),
                len(users))
            logging.warning(msg)
            return
    # reboot at the specified time
    when = apt_pkg.config.find(
        "Unattended-Upgrade::Automatic-Reboot-Time", "now")
    logging.warning("Found %s, rebooting" % REBOOT_REQUIRED_FILE)
    cmd = ["/sbin/shutdown", "-r", when]
    try:
        shutdown_msg = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
        if shutdown_msg.strip():
            logging.warning("Shutdown msg: %s", shutdown_msg.strip())
    except Exception as e:
        logging.error("Failed to issue shutdown: %s", e)


def write_stamp_file():
    # type: () -> None
    statedir = os.path.join(apt_pkg.config.find_dir("Dir::State"), "periodic")
    if not os.path.exists(statedir):
        os.makedirs(statedir)
    with open(os.path.join(statedir, "unattended-upgrades-stamp"), "w"):
        pass


def try_to_upgrade(pkg,               # type: apt.Package
                   pkgs_to_upgrade,   # type: List[apt.Package]
                   pkgs_kept_back,    # type: List[str]
                   cache,             # type: apt.Cache
                   allowed_origins,   # type: List[str]
                   blacklist,         # type: List[str]
                   whitelist,         # type: List[str]
                   ):
    # type: (...) -> None
    try:
        try:
            # try to adjust pkg itself first, if that throws an exception it
            # can't be upgraded on its own
            cache.adjust_candidate(pkg)
            if not pkg.is_upgradable:
                return
        except NoAllowedOriginError:
            return
        cache._cached_candidate_pkgnames.add(pkg.name)
        cache.mark_upgrade_adjusted(pkg, from_user=not pkg.is_auto_installed)
        if check_changes_for_sanity(cache, allowed_origins, blacklist,
                                    whitelist, pkg):
            # add to packages to upgrade
            pkgs_to_upgrade.append(pkg)
            # re-eval pkgs_kept_back as the resolver may fail to
            # directly upgrade a pkg, but that may work during
            # a subsequent operation, see debian bug #639840
            for pkgname in pkgs_kept_back:
                if cache[pkgname].marked_install \
                   or cache[pkgname].marked_upgrade:
                    pkgs_kept_back.remove(pkgname)
                    pkgs_to_upgrade.append(cache[pkgname])
        else:
            logging.debug("sanity check failed")
            rewind_cache(cache, pkgs_to_upgrade)
            pkgs_kept_back.append(pkg.name)
    except (SystemError, NoAllowedOriginError) as e:
        # can't upgrade
        logging.warning(
            _("package %s upgradable but fails to "
                "be marked for upgrade (%s)"), pkg.name, e)
        rewind_cache(cache, pkgs_to_upgrade)
        pkgs_kept_back.append(pkg.name)


def calculate_upgradable_pkgs(cache,             # type: apt.Cache
                              options,           # type: Options
                              allowed_origins,   # type: List[str]
                              blacklist,         # type: List[str]
                              whitelist,         # type: List[str]
                              ):
    # type: (...) -> Tuple[List[apt.Package], List[str]]
    pkgs_to_upgrade = []  # type: List[apt.Package]
    pkgs_kept_back = []   # type: List[str]

    # now do the actual upgrade
    for pkg in cache:
        if options.debug and pkg.is_upgradable:
            logging.debug("Checking: %s (%s)" % (
                pkg.name, getattr(pkg.candidate, "origins", [])))

        if (pkg.is_upgradable
                and is_pkgname_in_whitelist(pkg.name, whitelist)):
            try:
                ver_in_allowed_origin(pkg, allowed_origins)
            except NoAllowedOriginError:
                continue

            try_to_upgrade(pkg,
                           pkgs_to_upgrade,
                           pkgs_kept_back,
                           cache,
                           allowed_origins,
                           blacklist,
                           whitelist)

    if cache.get_changes():
        cache.clear()

    return pkgs_to_upgrade, pkgs_kept_back


def get_dpkg_log_content(logfile_dpkg, install_start_time):
    # type: (str, datetime.datetime) -> str
    logging.debug("Extracting content from %s since %s" % (
        logfile_dpkg, install_start_time))
    content = []
    found_start = False
    try:
        with io.open(logfile_dpkg, encoding='utf-8', errors='replace') as fp:
            # read until we find the last "Log started: "
            for line in fp.readlines():
                # scan for the first entry we need (minimal-step mode
                # creates a new stanza for each individual install)
                if not found_start and line.startswith("Log started: "):
                    stanza_start = LoggingDateTime.from_string(
                        line[len("Log started: "):-1])
                    if stanza_start >= install_start_time:
                        found_start = True
                if found_start:
                    # skip progress indicator until #860931 is fixed in apt
                    # and dpkg
                    if re.match(
                            "^\\(Reading database \\.\\.\\. ()|([0-9]+%)$",
                            line):
                        continue
                    content.append(line)
        return "".join(content)
    except FileNotFoundError:
        return ""


def get_auto_removable(cache):
    # type: (apt.Cache) -> AbstractSet[str]
    return {pkg.name for pkg in cache
            if pkg.is_auto_removable}


def is_autoremove_valid(cache, pkgname, auto_removable, blacklist, whitelist):
    # type: (apt.Cache, str, AbstractSet[str], List[str], List[str]) -> bool
    changes = cache.get_changes()
    if not changes:
        # package is already removed
        return True
    pkgnames = {pkg.name for pkg in changes}
    for pkg in changes:
        if not is_pkg_change_allowed(pkg, blacklist, whitelist):
            logging.warning(
                _("Keeping the following auto-removable package(s) because "
                  "they include %s which is set to be kept unmodified: %s"),
                pkg.name, " ".join(sorted(pkgnames)))
            return False
    if not pkgnames.issubset(auto_removable):
        if pkgname != "":
            logging.warning(
                _("Keeping auto-removable %s package(s) because it would"
                  " also remove the following packages which should "
                  "be kept in this step: %s"), pkgname,
                " ".join(sorted(pkgnames - auto_removable)))
        else:
            logging.warning(
                _("Keeping %s auto-removable package(s) because it would"
                  " also remove the following packages which should "
                  "be kept in this step: %s"), len(auto_removable),
                " ".join(sorted(pkgnames - auto_removable)))

        return False
    for packagename in pkgnames:
        if cache.running_kernel_pkgs_regexp and \
           cache.running_kernel_pkgs_regexp.match(packagename):
            logging.warning(
                _("Keeping the following auto-removable package(s) because "
                  "they include %s which package is related to the running "
                  "kernel: %s"), packagename, " ".join(sorted(pkgnames)))
            return False
    return True


def do_auto_remove(cache,             # type: apt.Cache
                   auto_removable,    # type: AbstractSet[str]
                   logfile_dpkg,      # type: str
                   minimal_steps,     # type: bool
                   blacklist,         # type: List[str]
                   whitelist,         # type: List[str]
                   verbose=False,     # type: bool
                   dry_run=False      # type: bool
                   ):
    # type: (...) -> Tuple[bool, List[str], List[str]]
    res = True
    if not auto_removable:
        return (res, [], [])

    pkgs_removed = []         # type: List[str]
    pkgs_kept_installed = []  # type: List[str]
    if minimal_steps:
        for pkgname in auto_removable:
            if should_stop():
                pkgs_kept_installed = list(auto_removable - set(pkgs_removed))
                return (False, pkgs_removed, pkgs_kept_installed)
            logging.debug("marking %s for removal" % pkgname)
            if pkgname in pkgs_removed:
                continue
            cache[pkgname].mark_delete()
            if not is_autoremove_valid(cache, pkgname, auto_removable,
                                       blacklist, whitelist):
                # this situation can occur when removing newly unused packages
                # would also remove old unused packages which are not set
                # for removal, thus getting there is not handled as an error
                pkgs_kept_installed.append(pkgname)
                cache.clear()
                continue
            if not dry_run:
                changes = cache.get_changes()
                pkgnames = {pkg.name for pkg in changes}
                res, error = cache_commit(cache, logfile_dpkg, verbose)
                if not res:
                    break
                pkgs_removed.extend(pkgnames)
            else:
                cache.clear()
    else:
        for pkgname in auto_removable:
            cache[pkgname].mark_delete()
        if is_autoremove_valid(cache, "", auto_removable, blacklist,
                               whitelist):
            # do it in one step
            if not dry_run:
                res, error = cache_commit(cache, logfile_dpkg, verbose)
            else:
                cache.clear()
        else:
            cache.clear()

    if res:
        logging.info(_("Packages that were successfully auto-removed: %s"),
                     " ".join(sorted(pkgs_removed)))
        logging.info(_("Packages that are kept back: %s"),
                     " ".join(sorted(pkgs_kept_installed)))
    if not res:
        cache.clear()
        logging.error(_("Auto-removing the packages failed!"))
        logging.error(_("Error message: %s"), error)
        logging.error(_("dpkg returned an error! See %s for details"),
                      logfile_dpkg)
    return (res, pkgs_removed, pkgs_kept_installed)


def clean_downloaded_packages(fetcher):
    # type: (apt_pkg.Acquire) -> None
    archivedir = os.path.dirname(
        apt_pkg.config.find_dir("Dir::Cache::archives"))
    for item in fetcher.items:
        if os.path.dirname(os.path.abspath(item.destfile)) == archivedir:
            try:
                os.unlink(item.destfile)
            except OSError:
                pass


def is_update_day():
    # type: () -> bool
    # check if patch days are configured
    patch_days = apt_pkg.config.value_list("Unattended-Upgrade::Update-Days")
    if not patch_days:
        return True
    # validate patch days
    today = date.today()
    # abbreviated localized dayname
    if today.strftime("%a") in patch_days:
        return True
    # full localized dayname
    if today.strftime("%A") in patch_days:
        return True
    # by number (Sun: 0, Mon: 1, ...)
    if today.strftime("%w") in patch_days:
        return True
    # today is not a patch day
    logging.info(
        "Skipping update check: today is %s,%s,%s but patch days are %s",
        today.strftime("%w"), today.strftime("%a"), today.strftime("%A"),
        ", ".join(patch_days))
    return False


def main(options, rootdir=""):
    # type: (Options, str) -> int
    # useful for testing
    if rootdir:
        _setup_alternative_rootdir(rootdir)

    # see debian #776752
    install_start_time = datetime.datetime.now().replace(microsecond=0)

    # setup logging
    mem_log = _setup_logging(options)
    # get log
    logfile_dpkg = os.path.join(_get_logdir(), 'unattended-upgrades-dpkg.log')
    if not os.path.exists(logfile_dpkg):
        with open(logfile_dpkg, 'w'):
            pass

    # lock for the shutdown check
    shutdown_lock = apt_pkg.get_lock(LOCK_FILE)
    if shutdown_lock < 0:
        logging.error("Lock file is already taken, exiting")
        return 1

    try:
        res = run(options, rootdir, mem_log, logfile_dpkg,
                  install_start_time)
        if res.result_str and not options.dry_run:
            # there is some meaningful result which is worth an email
            log_content = get_dpkg_log_content(logfile_dpkg,
                                               install_start_time)
            send_summary_mail(res.pkgs, res.success, res.result_str,
                              res.pkgs_kept_back, res.pkgs_removed,
                              res.pkgs_kept_installed, mem_log,
                              log_content)
        if res.update_stamp:
            # write timestamp file
            write_stamp_file()
            if not options.dry_run:
                # check if the user wants a reboot
                reboot_if_requested_and_needed()
        os.close(shutdown_lock)
        if res.success:
            return 0
        else:
            return 1

    except Exception as e:
        logger = logging.getLogger()
        logger.exception(_("An error occurred: %s"), e)
        log_content = get_dpkg_log_content(logfile_dpkg,
                                           install_start_time)
        if not options.dry_run:
            send_summary_mail(["<unknown>"], False, _("An error occurred"), [],
                              [], [],
                              mem_log, log_content)
        # Re-raise exceptions for apport
        raise


def mark_pkgs_to_upgrade(cache, pkgs_to_upgrade):
    # type (apt.Cache, List[apt.Package]) -> None
    for pkg in pkgs_to_upgrade:
        if pkg.is_upgradable:
            cache.mark_upgrade_adjusted(pkg,
                                        from_user=not pkg.is_auto_installed)
        elif not pkg.is_installed:
            cache.mark_install_adjusted(pkg, from_user=False)


def run(options,             # type: Options
        rootdir,             # type: str
        mem_log,             # type: StringIO
        logfile_dpkg,        # type: str
        install_start_time,  # type: datetime.datetime
        ):
    # type: (...) -> UnattendedUpgradesResult

    # check if today is a patch day
    if not is_update_day():
        return UnattendedUpgradesResult(True)

    # check if u-u should be stopped already
    if should_stop():
        return UnattendedUpgradesResult(False)

    # check to see if want to auto-upgrade the devel release
    if apt_pkg.config.find("Unattended-Upgrade::DevRelease") == "auto":
        try:
            if DISTRO_ID.lower() == 'ubuntu':
                devel = (distro_info.UbuntuDistroInfo() .
                         devel(result="object"))
            elif DISTRO_ID.lower() == 'debian':
                devel = (distro_info.DebianDistroInfo() .
                         devel(result="object"))
            else:
                devel = (distro_info.DistroInfo(DISTRO_ID) .
                         devel(result="object"))
        except Exception as e:
            logging.warning("Could not figure out development release: %s" % e)
        else:
            if ((devel.series == DISTRO_CODENAME
                 and devel.release is not None
                 and devel.release - date.today() > DEVEL_UNTIL_RELEASE)):
                syslog.syslog((_("Not running on this development "
                                 "release before %s") %
                              (devel.release - DEVEL_UNTIL_RELEASE
                               - datetime.timedelta(days=1))))
                logging.warning(_("Not running on this development "
                                  "release before %s") %
                                (devel.release - DEVEL_UNTIL_RELEASE
                                 - datetime.timedelta(days=1)))
                return UnattendedUpgradesResult(True)

            logging.debug("Running on the development release")
    elif "(development branch)" in DISTRO_DESC and not\
            apt_pkg.config.find_b("Unattended-Upgrade::DevRelease", True):
        syslog.syslog(_("Not running on the development release."))
        logging.info(_("Not running on the development release."))
        return UnattendedUpgradesResult(True)
    # format (origin, archive), e.g. ("Ubuntu","dapper-security")
    allowed_origins = get_allowed_origins()

    # pkgs that are (for some reason) not safe to install
    blacklist = get_blacklist()
    logging.info(_("Initial blacklist : %s"),
                 " ".join(blacklist))

    # install only these packages regardless of other upgrades available
    whitelist = get_whitelist()
    logging.info(_("Initial whitelist: %s"),
                 " ".join(whitelist))

    logging.info(_("Starting unattended upgrades script"))

    # display available origin
    logging.info(_("Allowed origins are: %s"), ", ".join(allowed_origins))

    # check and get lock
    try:
        apt_pkg.pkgsystem_lock()
    except SystemError:
        logging.error(_("Lock could not be acquired (another package "
                        "manager running?)"))
        print(_("Cache lock can not be acquired, exiting"))
        return UnattendedUpgradesResult(
            False, _("Lock could not be acquired"))

    # check if the journal is dirty and if so, take emergceny action
    # the alternative is to leave the system potentially unsecure until
    # the user comes in and fixes
    if is_dpkg_journal_dirty() and \
       apt_pkg.config.find_b("Unattended-Upgrade::AutoFixInterruptedDpkg",
                             True):
        logging.warning(
            _("Unclean dpkg state detected, trying to correct"))
        print(_("Unclean dpkg state detected, trying to correct"))
        env = copy.copy(os.environ)
        env["DPKG_FRONTEND_LOCKED"] = "1"
        try:
            with Unlocked():
                output = subprocess.check_output(
                    ["dpkg", "--force-confold", "--configure", "-a"],
                    env=env,
                    universal_newlines=True)
        except subprocess.CalledProcessError as e:
            output = e.output
        logging.warning(_("dpkg --configure -a output:\n%s"), output)

    # get a cache
    try:
        cache = UnattendedUpgradesCache(rootdir=rootdir,
                                        allowed_origins=allowed_origins)
    except SystemError as error:
        print(_("Apt returned an error, exiting"))
        print(_("error message: %s") % error)
        logging.error(_("Apt returned an error, exiting"))
        logging.error(_("error message: %s"), error)
        return UnattendedUpgradesResult(
            False, _("Apt returned an error, exiting"))

    if cache._depcache.broken_count > 0:
        print(_("Cache has broken packages, exiting"))
        logging.error(_("Cache has broken packages, exiting"))
        return UnattendedUpgradesResult(
            False, _("Cache has broken packages, exiting"))

    # FIXME: make this into a ContextManager
    # be nice when calculating the upgrade as its pretty CPU intensive
    old_priority = os.nice(0)
    try:
        # Check that we will be able to restore the priority
        os.nice(-1)
        os.nice(20)
    except OSError as e:
        if e.errno in (errno.EPERM, errno.EACCES):
            pass
        else:
            raise

    auto_removable = get_auto_removable(cache)

    # find out about the packages that are upgradable (in an allowed_origin)
    pkgs_to_upgrade, pkgs_kept_back = calculate_upgradable_pkgs(
        cache, options, allowed_origins, blacklist, whitelist)
    pkgs_to_upgrade.sort(key=lambda p: p.name)
    pkgs = [pkg.name for pkg in pkgs_to_upgrade]
    logging.debug("pkgs that look like they should be upgraded: %s"
                  % "\n".join(pkgs))

    # FIXME: make this into a ContextManager
    # stop being nice
    os.nice(old_priority - os.nice(0))

    # download what looks good
    mark_pkgs_to_upgrade(cache, pkgs_to_upgrade)

    if options.debug:
        fetcher = apt_pkg.Acquire(apt.progress.text.AcquireProgress())
    else:
        fetcher = apt_pkg.Acquire()
    list = apt_pkg.SourceList()
    list.read_main_list()
    recs = cache._records
    pm = apt_pkg.PackageManager(cache._depcache)
    # don't start downloading during shutdown
    # TODO: download files one by one and check for stop request after each of
    # them
    if should_stop():
        return UnattendedUpgradesResult(False, _("Upgrade was interrupted"))
    try:
        pm.get_archives(fetcher, list, recs)
    except SystemError as e:
        logging.error(_("GetArchives() failed: %s"), e)
    try:
        res = fetcher.run()
        logging.debug("fetch.run() result: %s", res)
    except SystemError as e:
        logging.error("fetch.run() result: %s", e)

    if cache.get_changes():
        cache.clear()

    if options.download_only:
        return UnattendedUpgradesResult(True)

    pkg_conffile_prompt = False
    if dpkg_conffile_prompt():
        # now check the downloaded debs for conffile conflicts and build
        # a blacklist
        for item in fetcher.items:
            logging.debug("%s" % item)
            if item.status == item.STAT_ERROR:
                print(_("An error occurred: %s") % item.error_text)
                logging.error(_("An error occurred: %s"), item.error_text)
            if not item.complete:
                print(_("The URI %s failed to download, aborting") %
                      item.desc_uri)
                logging.error(_("The URI %s failed to download, aborting"),
                              item.desc_uri)
                return UnattendedUpgradesResult(
                    False, (_("The URI %s failed to download, aborting") %
                            item.desc_uri))
            if not os.path.exists(item.destfile):
                print(_("Download finished, but file %s not there?!?") %
                      item.destfile)
                logging.error("Download finished, but file %s not "
                              "there?!?", item.destfile)
                return UnattendedUpgradesResult(
                    False, (_("Download finished, but file %s not there?!?") %
                            item.destfile))
            if not item.is_trusted and not apt_pkg.config.find_b(
                    "APT::Get::AllowUnauthenticated", False):
                logging.debug("%s is blacklisted because it is not trusted")
                pkg_name = pkgname_from_deb(item.destfile)
                if not is_pkgname_in_blacklist(pkg_name, blacklist):
                    blacklist.append("%s$" % re.escape(pkg_name))
            if not is_deb(item.destfile):
                logging.debug("%s is not a .deb file" % item)
                continue
            if conffile_prompt(item.destfile):
                # skip package (means to re-run the whole marking again
                # and making sure that the package will not be pulled in by
                # some other package again!)
                #
                # print to stdout to ensure that this message is part of
                # the cron mail (only if no summary mail is requested)
                email = apt_pkg.config.find("Unattended-Upgrade::Mail", "")
                if not email:
                    print(_("Package %s has conffile prompt and needs "
                            "to be upgraded manually") %
                          pkgname_from_deb(item.destfile))
                # log to the logfile
                logging.warning(_("Package %s has conffile prompt and "
                                  "needs to be upgraded manually"),
                                pkgname_from_deb(item.destfile))
                pkg_name = pkgname_from_deb(item.destfile)
                if not is_pkgname_in_blacklist(pkg_name, blacklist):
                    blacklist.append("%s$" % re.escape(pkg_name))
                pkgs_kept_back.append(pkgname_from_deb(pkg_name))
                pkg_conffile_prompt = True

        # redo the selection about the packages to upgrade based on the new
        # blacklist
        logging.debug("blacklist: %s" % blacklist)
        # whitelist
        logging.debug("whitelist: %s" % whitelist)
        # find out about the packages that are upgradable (in a allowed_origin)
        if len(blacklist) > 0 or len(whitelist) > 0:
            old_pkgs_to_upgrade = pkgs_to_upgrade[:]
            pkgs_to_upgrade = []
            for pkg in old_pkgs_to_upgrade:
                logging.debug("Checking the black and whitelist: %s" %
                              (pkg.name))
                cache.mark_upgrade_adjusted(
                    pkg, from_user=not pkg.is_auto_installed)
                if check_changes_for_sanity(cache,
                                            allowed_origins,
                                            blacklist,
                                            whitelist):
                    pkgs_to_upgrade.append(pkg)
                else:
                    if not (pkg.name in pkgs_kept_back):
                        pkgs_kept_back.append(pkg.name)
                    logging.info(_("package %s not upgraded"), pkg.name)
                    cache.clear()
                    for pkg2 in pkgs_to_upgrade:
                        cache.call_adjusted(
                            apt.package.Package.mark_upgrade, pkg2,
                            from_user=not pkg2.is_auto_installed)
            if cache.get_changes():
                cache.clear()

    else:
        logging.debug("dpkg is configured not to cause conffile prompts")

    # auto-removals
    kernel_pkgs_remove_success = True  # type: bool
    kernel_pkgs_removed = []           # type: List[str]
    kernel_pkgs_kept_installed = []    # type: List[str]
    if (auto_removable and apt_pkg.config.find_b(
            "Unattended-Upgrade::Remove-Unused-Kernel-Packages", True)):
        # remove unused kernels before installing new ones because the newly
        # installed ones may fill up /boot and break the system right before
        # removing old ones could take place
        #
        # this step may also remove _auto-removable_ reverse dependencies
        # of kernel packages
        auto_removable_kernel_pkgs = {
            p for p in auto_removable
            if (cache.versioned_kernel_pkgs_regexp
                and cache.versioned_kernel_pkgs_regexp.match(p)
                and not cache.running_kernel_pkgs_regexp.match(p))}
        if auto_removable_kernel_pkgs:
            logging.info(_("Removing unused kernel packages: %s"),
                         " ".join(auto_removable_kernel_pkgs))
            (kernel_pkgs_remove_success,
             kernel_pkgs_removed,
             kernel_pkgs_kept_installed) = do_auto_remove(
                cache, auto_removable_kernel_pkgs, logfile_dpkg,
                options.minimal_upgrade_steps, blacklist, whitelist,
                options.verbose or options.debug, options.dry_run)
            auto_removable = get_auto_removable(cache)

    previous_autoremovals = auto_removable
    if apt_pkg.config.find_b(
            "Unattended-Upgrade::Remove-Unused-Dependencies", False):
        pending_autoremovals = previous_autoremovals
    else:
        pending_autoremovals = set()

    # exit if there is nothing to do and nothing to report
    if (len(pending_autoremovals) == 0
            and len(pkgs_to_upgrade) == 0
            and len(pkgs_kept_back) == 0):
        logging.info(_("No packages found that can be upgraded unattended "
                       "and no pending auto-removals"))
        return UnattendedUpgradesResult(
            kernel_pkgs_remove_success,
            _("No packages found that can be upgraded unattended and no "
              "pending auto-removals"),
            pkgs_removed=kernel_pkgs_removed,
            pkgs_kept_installed=kernel_pkgs_kept_installed,
            update_stamp=True)

    # check if its configured for install on shutdown, if so, the
    # environment UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN will
    # be set by the unatteded-upgrades-shutdown script
    if ("UNATTENDED_UPGRADES_FORCE_INSTALL_ON_SHUTDOWN" not in os.environ
        and apt_pkg.config.find_b(
            "Unattended-Upgrade::InstallOnShutdown", False)):
        logger = logging.getLogger()
        logger.debug("Configured to install on shutdown, so exiting now")
        return UnattendedUpgradesResult(True)

    # check if we are in dry-run mode
    if options.dry_run:
        logging.info("Option --dry-run given, *not* performing real actions")
        apt_pkg.config.set("Debug::pkgDPkgPM", "1")

    # do the install based on the new list of pkgs
    pkgs = [pkg.name for pkg in pkgs_to_upgrade]
    logging.info(_("Packages that will be upgraded: %s"), " ".join(pkgs))

    # only perform install step if we actually have packages to install
    pkg_install_success = True
    if len(pkgs_to_upgrade) > 0:
        # do install
        pkg_install_success = do_install(cache,
                                         pkgs_to_upgrade,
                                         blacklist,
                                         whitelist,
                                         options,
                                         logfile_dpkg)
    # Was the overall run succesful: only if everything installed
    # fine and nothing was held back because of a conffile prompt.
    successful_run = (kernel_pkgs_remove_success and pkg_install_success
                      and not pkg_conffile_prompt)

    # now check if any auto-removing needs to be done
    if cache._depcache.broken_count > 0:
        print(_("Cache has broken packages, exiting"))
        logging.error(_("Cache has broken packages, exiting"))
        return UnattendedUpgradesResult(
            False, _("Cache has broken packages, exiting"), pkgs=pkgs)

    # the user wants *all* auto-removals to be removed
    # (unless u-u got signalled to stop gracefully quickly)
    pkgs_removed = []         # type: List[str]
    pkgs_kept_installed = []  # type: List[str]
    if ((apt_pkg.config.find_b(
            "Unattended-Upgrade::Remove-Unused-Dependencies", False)
         and not SIGNAL_STOP_REQUEST)):
        auto_removals = get_auto_removable(cache)
        (pkg_remove_success,
         pkgs_removed,
         pkgs_kept_installed) = do_auto_remove(
            cache, auto_removals, logfile_dpkg, options.minimal_upgrade_steps,
            blacklist, whitelist, options.verbose or options.debug,
            options.dry_run)
        successful_run = successful_run and pkg_remove_success
    # the user wants *only new* auto-removals to be removed
    elif apt_pkg.config.find_b(
            "Unattended-Upgrade::Remove-New-Unused-Dependencies", True):
        # calculate the new auto-removals
        new_pending_autoremovals = get_auto_removable(cache)
        auto_removals = new_pending_autoremovals - previous_autoremovals
        (pkg_remove_success,
         pkgs_removed,
         pkgs_kept_installed) = do_auto_remove(
            cache, auto_removals, logfile_dpkg, options.minimal_upgrade_steps,
            blacklist, whitelist, options.verbose or options.debug,
            options.dry_run)
        successful_run = successful_run and pkg_remove_success

    logging.debug("InstCount=%i DelCount=%i BrokenCount=%i"
                  % (cache._depcache.inst_count,
                     cache._depcache.del_count,
                     cache._depcache.broken_count))

    # clean after success install (if needed)
    keep_key = "Unattended-Upgrade::Keep-Debs-After-Install"
    if (not apt_pkg.config.find_b(keep_key, False)
            and not options.dry_run
            and pkg_install_success):
        clean_downloaded_packages(fetcher)

    return UnattendedUpgradesResult(
        successful_run, _("All upgrades installed"), pkgs,
        pkgs_kept_back,
        kernel_pkgs_removed + pkgs_removed,
        kernel_pkgs_kept_installed + pkgs_kept_installed,
        update_stamp=True)


class Options:
    def __init__(self):
        self.download_only = False
        self.dry_run = False
        self.debug = False
        self.apt_debug = False
        self.verbose = False
        self.minimal_upgrade_steps = False


if __name__ == "__main__":
    localesApp = "unattended-upgrades"
    localesDir = "/usr/share/locale"
    gettext.bindtextdomain(localesApp, localesDir)
    gettext.textdomain(localesApp)

    # set debconf to NON_INTERACTIVE
    os.environ["DEBIAN_FRONTEND"] = "noninteractive"

    # this ensures the commandline is logged in /var/log/apt/history.log
    apt_pkg.config.set("Commandline::AsString", " ".join(sys.argv))

    # COMPAT with the mispelling
    minimal_steps_default = (
        apt_pkg.config.find_b("Unattended-Upgrades::MinimalSteps", True)
        and apt_pkg.config.find_b("Unattended-Upgrade::MinimalSteps", True))

    # init the options
    parser = OptionParser()
    parser.add_option("-d", "--debug",
                      action="store_true",
                      default=apt_pkg.config.find_b(
                          "Unattended-Upgrade::Debug", False),
                      help=_("print debug messages"))
    parser.add_option("", "--apt-debug",
                      action="store_true", default=False,
                      help=_("make apt/libapt print verbose debug messages"))
    parser.add_option("-v", "--verbose",
                      action="store_true",
                      default=apt_pkg.config.find_b(
                          "Unattended-Upgrade::Verbose", False),
                      help=_("print info messages"))
    parser.add_option("", "--dry-run",
                      action="store_true", default=False,
                      help=_("Simulation, download but do not install"))
    parser.add_option("", "--download-only",
                      action="store_true", default=False,
                      help=_("Only download, do not even try to install."))
    parser.add_option("", "--minimal-upgrade-steps",
                      action="store_true", default=minimal_steps_default,
                      help=_("Upgrade in minimal steps (and allow "
                             "interrupting with SIGTERM) (default)"))
    parser.add_option("", "--no-minimal-upgrade-steps",
                      action="store_false", default=minimal_steps_default,
                      dest="minimal_upgrade_steps",
                      help=_("Upgrade in minimal steps (and allow "
                             "interrupting with SIGTERM"))
    parser.add_option("", "--minimal_upgrade_steps",
                      action="store_true",
                      help=SUPPRESS_HELP,
                      default=minimal_steps_default)
    options = cast(Options, (parser.parse_args())[0])

    if os.getuid() != 0:
        print(_("You need to be root to run this application"))
        sys.exit(1)

    # ensure that we are not killed when the terminal goes away e.g. on
    # shutdown
    signal.signal(signal.SIGHUP, signal.SIG_IGN)

    # setup signal handler for graceful stopping
    signal.signal(signal.SIGTERM, signal_handler)

    # write pid to let other processes find this one
    pidf = os.path.join(apt_pkg.config.find_dir("Dir"),
                        "var", "run", "unattended-upgrades.pid")
    # clean up pid file on exit
    with open(pidf, "w") as fp:
        fp.write("%s" % os.getpid())
    atexit.register(os.remove, pidf)

    # run the main code
    sys.exit(main(options))
N4m3
5!z3
L45t M0d!f!3d
0wn3r / Gr0up
P3Rm!55!0n5
0pt!0n5
..
--
April 29 2020 04:21:46
root / root
0755
X11
--
July 01 2024 06:14:58
root / root
0755
2to3-2.7
0.094 KB
March 23 2024 18:55:36
root / root
0755
[
58.656 KB
February 28 2019 15:30:31
root / root
0755
aa-enabled
30.211 KB
March 30 2019 13:23:11
root / root
0755
aa-exec
30.211 KB
March 30 2019 13:23:11
root / root
0755
add-apt-repository
6.207 KB
March 30 2019 19:45:34
root / root
0755
addpart
26.078 KB
April 06 2024 22:33:55
root / root
0755
addr2line
31.094 KB
March 21 2019 14:49:23
root / root
0755
apropos
54.977 KB
February 01 2024 13:35:20
root / root
0755
apt
18.086 KB
April 19 2021 16:41:13
root / root
0755
apt-add-repository
6.207 KB
March 30 2019 19:45:34
root / root
0755
apt-cache
82.156 KB
April 19 2021 16:41:13
root / root
0755
apt-cdrom
26.156 KB
April 19 2021 16:41:13
root / root
0755
apt-config
26.086 KB
April 19 2021 16:41:13
root / root
0755
apt-extracttemplates
22.156 KB
April 19 2021 16:41:13
root / root
0755
apt-ftparchive
238.156 KB
April 19 2021 16:41:13
root / root
0755
apt-get
46.156 KB
April 19 2021 16:41:13
root / root
0755
apt-key
27.08 KB
April 19 2021 16:41:13
root / root
0755
apt-listchanges
10.613 KB
March 17 2019 22:48:06
root / root
0755
apt-mark
54.156 KB
April 19 2021 16:41:13
root / root
0755
apt-sortpkgs
46.086 KB
April 19 2021 16:41:13
root / root
0755
ar
63.07 KB
March 21 2019 14:49:23
root / root
0755
arch
38.656 KB
February 28 2019 15:30:31
root / root
0755
as
872.93 KB
March 21 2019 14:49:23
root / root
0755
at
54.258 KB
July 24 2018 09:17:21
daemon / daemon
6755
atq
54.258 KB
July 24 2018 09:17:21
daemon / daemon
6755
atrm
54.258 KB
July 24 2018 09:17:21
daemon / daemon
6755
autoconf
14.422 KB
August 20 2017 18:17:16
root / root
0755
autoheader
8.336 KB
August 20 2017 18:17:16
root / root
0755
autom4te
31.905 KB
August 20 2017 18:17:16
root / root
0755
autoreconf
20.667 KB
August 20 2017 18:17:16
root / root
0755
autoscan
16.73 KB
August 20 2017 18:17:16
root / root
0755
autoupdate
33.08 KB
August 20 2017 18:17:16
root / root
0755
awk
119.117 KB
March 23 2012 20:15:00
root / root
0755
aws
0.796 KB
February 27 2019 07:44:49
root / root
0755
aws_completer
1.109 KB
February 27 2019 07:44:49
root / root
0755
b2sum
58.781 KB
February 28 2019 15:30:31
root / root
0755
base32
42.688 KB
February 28 2019 15:30:31
root / root
0755
base64
42.688 KB
February 28 2019 15:30:31
root / root
0755
basename
38.594 KB
February 28 2019 15:30:31
root / root
0755
bash
1.11 MB
April 18 2019 04:12:36
root / root
0755
bashbug
6.634 KB
April 18 2019 04:12:36
root / root
0755
batch
0.148 KB
July 24 2018 09:17:21
root / root
0755
bootctl
46.234 KB
June 29 2023 13:57:02
root / root
0755
bsd-from
10.242 KB
May 04 2018 12:24:31
root / root
0755
bsd-write
14.391 KB
May 04 2018 12:24:31
root / tty
2755
bunzip2
38.07 KB
July 21 2020 08:36:47
root / root
0755
busctl
78.188 KB
June 29 2023 13:57:02
root / root
0755
bzcat
38.07 KB
July 21 2020 08:36:47
root / root
0755
bzcmp
2.173 KB
July 21 2020 08:36:47
root / root
0755
bzdiff
2.173 KB
July 21 2020 08:36:47
root / root
0755
bzegrep
3.556 KB
July 21 2020 08:36:47
root / root
0755
bzexe
4.763 KB
June 24 2019 20:16:40
root / root
0755
bzfgrep
3.556 KB
July 21 2020 08:36:47
root / root
0755
bzgrep
3.556 KB
July 21 2020 08:36:47
root / root
0755
bzip2
38.07 KB
July 21 2020 08:36:47
root / root
0755
bzip2recover
13.992 KB
July 21 2020 08:36:47
root / root
0755
bzless
1.267 KB
July 21 2020 08:36:47
root / root
0755
bzmore
1.267 KB
July 21 2020 08:36:47
root / root
0755
c++
1.05 MB
April 06 2019 14:44:55
root / root
0755
c++filt
30.688 KB
March 21 2019 14:49:23
root / root
0755
c89
0.418 KB
June 12 2013 21:03:20
root / root
0755
c89-gcc
0.418 KB
June 12 2013 21:03:20
root / root
0755
c99
0.443 KB
June 12 2013 21:03:20
root / root
0755
c99-gcc
0.443 KB
June 12 2013 21:03:20
root / root
0755
c_rehash
6.13 KB
August 15 2023 19:14:44
root / root
0755
cal
29.148 KB
May 04 2018 12:24:31
root / root
0755
calendar
31.148 KB
May 04 2018 12:24:31
root / root
0755
captoinfo
86.109 KB
December 03 2023 15:31:37
root / root
0755
cat
42.719 KB
February 28 2019 15:30:31
root / root
0755
catchsegv
3.226 KB
June 29 2024 10:27:34
root / root
0755
catman
38.461 KB
February 01 2024 13:35:20
root / root
0755
cc
1.05 MB
April 06 2019 14:44:55
root / root
0755
certbot
0.376 KB
December 05 2020 02:33:11
root / root
0755
chacl
13.992 KB
March 01 2019 22:22:21
root / root
0755
chage
70.133 KB
July 27 2018 08:07:37
root / shadow
2755
chardet
0.38 KB
January 22 2019 00:46:22
root / root
0755
chardet3
0.38 KB
January 22 2019 00:46:22
root / root
0755
chardetect
0.38 KB
January 22 2019 00:46:22
root / root
0755
chardetect3
0.38 KB
January 22 2019 00:46:22
root / root
0755
chattr
14 KB
January 10 2020 01:19:57
root / root
0755
chcon
62.906 KB
February 28 2019 15:30:31
root / root
0755
chfn
52.828 KB
July 27 2018 08:07:37
root / root
4755
chgrp
62.813 KB
February 28 2019 15:30:31
root / root
0755
chmod
62.781 KB
February 28 2019 15:30:31
root / root
0755
choom
50.078 KB
April 06 2024 22:33:55
root / root
0755
chown
70.813 KB
February 28 2019 15:30:31
root / root
0755
chronyc
83.016 KB
March 15 2022 12:45:14
root / root
0755
chrt
34.078 KB
April 06 2024 22:33:55
root / root
0755
chsh
43.484 KB
July 27 2018 08:07:37
root / root
4755
cksum
38.625 KB
February 28 2019 15:30:31
root / root
0755
clear
14 KB
December 03 2023 15:31:37
root / root
0755
clear_console
14.305 KB
April 18 2019 04:12:36
root / root
0755
cloud-id
0.381 KB
March 19 2021 16:43:23
root / root
0755
cloud-init
0.385 KB
March 19 2021 16:43:23
root / root
0755
cloud-init-per
2.059 KB
April 29 2020 22:17:14
root / root
0755
cloud-localds
7.232 KB
July 21 2016 18:23:53
root / root
0755
cmp
50.641 KB
April 08 2019 12:04:00
root / root
0755
col
10.227 KB
May 04 2018 12:24:31
root / root
0755
colcrt
10.195 KB
May 04 2018 12:24:31
root / root
0755
colrm
10.188 KB
May 04 2018 12:24:31
root / root
0755
column
10.336 KB
May 04 2018 12:24:31
root / root
0755
comm
42.688 KB
February 28 2019 15:30:31
root / root
0755
compose
17.735 KB
February 09 2019 12:32:33
root / root
0755
corelist
14.734 KB
July 21 2020 19:27:00
root / root
0755
cp
143.438 KB
February 28 2019 15:30:31
root / root
0755
cpan
7.965 KB
July 21 2020 19:27:00
root / root
0755
cpan5.28-x86_64-linux-gnu
7.985 KB
July 21 2020 19:27:00
root / root
0755
cpio
154.609 KB
June 04 2023 15:01:54
root / root
0755
cpp
1.05 MB
April 06 2019 14:44:55
root / root
0755
cpp-8
1.05 MB
April 06 2019 14:44:55
root / root
0755
crontab
42.547 KB
October 11 2019 07:58:52
root / crontab
2755
csplit
54.844 KB
February 28 2019 15:30:31
root / root
0755
ctstat
22.742 KB
December 03 2020 18:42:49
root / root
0755
curl
226.07 KB
January 28 2024 21:15:21
root / root
0755
cut
42.75 KB
February 28 2019 15:30:31
root / root
0755
cvtsudoers
250.289 KB
January 21 2024 20:52:36
root / root
0755
dash
118.617 KB
January 17 2019 19:08:32
root / root
0755
date
106.844 KB
February 28 2019 15:30:31
root / root
0755
dbus-cleanup-sockets
13.984 KB
October 23 2023 08:29:25
root / root
0755
dbus-daemon
235.039 KB
October 23 2023 08:29:25
root / root
0755
dbus-monitor
25.992 KB
October 23 2023 08:29:25
root / root
0755
dbus-run-session
13.984 KB
October 23 2023 08:29:25
root / root
0755
dbus-send
29.984 KB
October 23 2023 08:29:25
root / root
0755
dbus-update-activation-environment
13.984 KB
October 23 2023 08:29:25
root / root
0755
dbus-uuidgen
13.984 KB
October 23 2023 08:29:25
root / root
0755
dd
74.914 KB
February 28 2019 15:30:31
root / root
0755
deb-systemd-helper
20.828 KB
November 21 2018 23:15:24
root / root
0755
deb-systemd-invoke
4.326 KB
November 21 2018 23:15:24
root / root
0755
debconf
2.792 KB
October 01 2021 09:39:27
root / root
0755
debconf-apt-progress
11.271 KB
October 01 2021 09:39:27
root / root
0755
debconf-communicate
0.594 KB
October 01 2021 09:39:27
root / root
0755
debconf-copydb
1.679 KB
October 01 2021 09:39:27
root / root
0755
debconf-escape
0.632 KB
October 01 2021 09:39:27
root / root
0755
debconf-set-selections
2.866 KB
October 01 2021 09:39:27
root / root
0755
debconf-show
1.784 KB
October 01 2021 09:39:27
root / root
0755
debianbts
0.403 KB
December 31 2018 14:34:02
root / root
0755
delpart
26.078 KB
April 06 2024 22:33:55
root / root
0755
delv
44.828 KB
May 17 2024 15:43:53
root / root
0755
devdump
167.977 KB
July 21 2014 23:56:34
root / root
0755
df
91.547 KB
February 28 2019 15:30:31
root / root
0755
dh_autotools-dev_restoreconfig
1.793 KB
February 24 2018 16:00:57
root / root
0755
dh_autotools-dev_updateconfig
1.806 KB
February 24 2018 16:00:57
root / root
0755
dh_bash-completion
2.389 KB
February 11 2019 23:36:02
root / root
0755
dh_installxmlcatalogs
9.223 KB
February 27 2019 00:18:49
root / root
0755
dh_python2
1.031 KB
March 04 2019 15:48:56
root / root
0755
diff
215.281 KB
April 08 2019 12:04:00
root / root
0755
diff3
66.844 KB
April 08 2019 12:04:00
root / root
0755
dig
146.508 KB
May 17 2024 15:43:53
root / root
0755
dir
135.602 KB
February 28 2019 15:30:31
root / root
0755
dircolors
46.664 KB
February 28 2019 15:30:31
root / root
0755
dirname
34.594 KB
February 28 2019 15:30:31
root / root
0755
dirsplit
16.741 KB
November 25 2006 23:13:29
root / root
0755
dmesg
82.313 KB
April 06 2024 22:33:55
root / root
0755
dnsdomainname
26.07 KB
September 27 2018 08:45:17
root / root
0755
dnstap-read
18.008 KB
May 17 2024 15:43:53
root / root
0755
domainname
26.07 KB
September 27 2018 08:45:17
root / root
0755
dpkg
298.531 KB
May 24 2022 11:40:09
root / root
0755
dpkg-architecture
12.551 KB
May 24 2022 11:40:09
root / root
0755
dpkg-buildflags
7.388 KB
May 24 2022 11:40:09
root / root
0755
dpkg-buildpackage
29.893 KB
May 24 2022 11:40:09
root / root
0755
dpkg-checkbuilddeps
7.445 KB
May 24 2022 11:40:09
root / root
0755
dpkg-deb
162.383 KB
May 24 2022 11:40:09
root / root
0755
dpkg-distaddfile
2.717 KB
May 24 2022 11:40:09
root / root
0755
dpkg-divert
150.438 KB
May 24 2022 11:40:09
root / root
0755
dpkg-genbuildinfo
16.401 KB
May 24 2022 11:40:09
root / root
0755
dpkg-genchanges
17.082 KB
May 24 2022 11:40:09
root / root
0755
dpkg-gencontrol
13.823 KB
May 24 2022 11:40:09
root / root
0755
dpkg-gensymbols
10.646 KB
May 24 2022 11:40:09
root / root
0755
dpkg-maintscript-helper
20.033 KB
May 24 2022 11:40:09
root / root
0755
dpkg-mergechangelogs
8.347 KB
May 24 2022 11:40:09
root / root
0755
dpkg-name
6.63 KB
May 24 2022 11:40:09
root / root
0755
dpkg-parsechangelog
4.46 KB
May 24 2022 11:40:09
root / root
0755
dpkg-query
158.43 KB
May 24 2022 11:40:09
root / root
0755
dpkg-scanpackages
8.494 KB
May 24 2022 11:40:09
root / root
0755
dpkg-scansources
8.952 KB
May 24 2022 11:40:09
root / root
0755
dpkg-shlibdeps
30.68 KB
May 24 2022 11:40:09
root / root
0755
dpkg-source
22.482 KB
May 24 2022 11:40:09
root / root
0755
dpkg-split
122.336 KB
May 24 2022 11:40:09
root / root
0755
dpkg-statoverride
62.117 KB
May 24 2022 11:40:09
root / root
0755
dpkg-trigger
78.336 KB
May 24 2022 11:40:09
root / root
0755
dpkg-vendor
3.186 KB
May 24 2022 11:40:09
root / root
0755
du
107.094 KB
February 28 2019 15:30:31
root / root
0755
dwp
2.74 MB
March 21 2019 14:49:23
root / root
0755
ec2metadata
7.126 KB
July 21 2016 18:23:53
root / root
0755
echo
38.594 KB
February 28 2019 15:30:31
root / root
0755
edit
17.735 KB
February 09 2019 12:32:33
root / root
0755
editor
240.391 KB
June 11 2024 18:30:35
root / root
0755
egrep
0.027 KB
January 07 2019 15:04:36
root / root
0755
elfedit
38.836 KB
March 21 2019 14:49:23
root / root
0755
enc2xs
41.124 KB
July 21 2020 19:27:00
root / root
0755
encguess
2.994 KB
July 21 2020 19:27:00
root / root
0755
env
42.656 KB
February 28 2019 15:30:31
root / root
0755
envsubst
42.641 KB
November 10 2018 17:34:46
root / root
0755
eqn
201.188 KB
March 19 2021 10:36:25
root / root
0755
ex
2.58 MB
September 27 2023 19:47:00
root / root
0755
expand
42.688 KB
February 28 2019 15:30:31
root / root
0755
expiry
30.273 KB
July 27 2018 08:07:37
root / shadow
2755
expr
50.719 KB
February 28 2019 15:30:31
root / root
0755
factor
74.75 KB
February 28 2019 15:30:31
root / root
0755
faillog
22.289 KB
July 27 2018 08:07:37
root / root
0755
fallocate
30.078 KB
April 06 2024 22:33:55
root / root
0755
false
34.594 KB
February 28 2019 15:30:31
root / root
0755
fgrep
0.027 KB
January 07 2019 15:04:36
root / root
0755
filan
83.781 KB
November 19 2017 13:56:10
root / root
0755
file
26.313 KB
January 25 2021 21:40:17
root / root
0755
fincore
30.125 KB
April 06 2024 22:33:55
root / root
0755
find
308.5 KB
February 16 2019 12:14:53
root / root
0755
findmnt
67.266 KB
April 06 2024 22:33:55
root / root
0755
flock
34.156 KB
April 06 2024 22:33:55
root / root
0755
fmt
42.656 KB
February 28 2019 15:30:31
root / root
0755
fold
38.656 KB
February 28 2019 15:30:31
root / root
0755
free
18.078 KB
May 31 2018 09:42:46
root / root
0755
from
10.242 KB
May 04 2018 12:24:31
root / root
0755
funzip
22.258 KB
September 22 2022 16:25:09
root / root
0755
fuser
39.625 KB
August 16 2021 09:17:53
root / root
0755
futurize
0.375 KB
January 30 2019 20:47:52
root / root
0755
g++
1.05 MB
April 06 2019 14:44:55
root / root
0755
g++-8
1.05 MB
April 06 2019 14:44:55
root / root
0755
gapplication
22.07 KB
May 10 2024 14:33:34
root / root
0755
gcc
1.05 MB
April 06 2019 14:44:55
root / root
0755
gcc-8
1.05 MB
April 06 2019 14:44:55
root / root
0755
gcc-ar
34.469 KB
April 06 2019 14:44:55
root / root
0755
gcc-ar-8
34.469 KB
April 06 2019 14:44:55
root / root
0755
gcc-nm
34.469 KB
April 06 2019 14:44:55
root / root
0755
gcc-nm-8
34.469 KB
April 06 2019 14:44:55
root / root
0755
gcc-ranlib
34.469 KB
April 06 2019 14:44:55
root / root
0755
gcc-ranlib-8
34.469 KB
April 06 2019 14:44:55
root / root
0755
gcov
672.086 KB
April 06 2019 14:44:55
root / root
0755
gcov-8
672.086 KB
April 06 2019 14:44:55
root / root
0755
gcov-dump
511.953 KB
April 06 2019 14:44:55
root / root
0755
gcov-dump-8
511.953 KB
April 06 2019 14:44:55
root / root
0755
gcov-tool
548.016 KB
April 06 2019 14:44:55
root / root
0755
gcov-tool-8
548.016 KB
April 06 2019 14:44:55
root / root
0755
gdbus
50.078 KB
May 10 2024 14:33:34
root / root
0755
gencat
26.602 KB
June 29 2024 10:27:34
root / root
0755
genisoimage
619.008 KB
July 21 2014 23:56:34
root / root
0755
geqn
201.188 KB
March 19 2021 10:36:25
root / root
0755
getconf
34.367 KB
June 29 2024 10:27:34
root / root
0755
geteltorito
6.064 KB
July 21 2014 23:56:34
root / root
0755
getent
35.344 KB
June 29 2024 10:27:34
root / root
0755
getfacl
30.617 KB
March 01 2019 22:22:21
root / root
0755
getopt
22.07 KB
April 06 2024 22:33:55
root / root
0755
gettext
42.617 KB
November 10 2018 17:34:46
root / root
0755
gettext.sh
4.521 KB
November 10 2018 17:34:46
root / root
0755
gio
86.086 KB
May 10 2024 14:33:34
root / root
0755
gio-querymodules
13.992 KB
May 10 2024 14:33:34
root / root
0755
glib-compile-schemas
46.07 KB
May 10 2024 14:33:34
root / root
0755
gold
2.97 MB
March 21 2019 14:49:23
root / root
0755
gonit
8.52 MB
May 18 2021 09:22:15
root / root
0755
gpasswd
82.047 KB
July 27 2018 08:07:37
root / root
4755
gpgv
434.992 KB
July 01 2022 16:06:43
root / root
0755
gpic
208.031 KB
March 19 2021 10:36:25
root / root
0755
gprof
96.391 KB
March 21 2019 14:49:23
root / root
0755
grep
194.313 KB
January 07 2019 15:04:36
root / root
0755
gresource
21.992 KB
May 10 2024 14:33:34
root / root
0755
groff
117.219 KB
March 19 2021 10:36:25
root / root
0755
grog
2.711 KB
March 19 2021 10:36:25
root / root
0755
grops
177.625 KB
March 19 2021 10:36:25
root / root
0755
grotty
129.25 KB
March 19 2021 10:36:25
root / root
0755
groups
38.656 KB
February 28 2019 15:30:31
root / root
0755
growpart
20.926 KB
July 21 2016 18:23:53
root / root
0755
grub-editenv
369.961 KB
October 02 2023 14:11:34
root / root
0755
grub-file
801.211 KB
October 02 2023 14:11:34
root / root
0755
grub-fstest
922.898 KB
October 02 2023 14:11:34
root / root
0755
grub-glue-efi
244.773 KB
October 02 2023 14:11:34
root / root
0755
grub-kbdcomp
1.642 KB
October 02 2023 14:11:34
root / root
0755
grub-menulst2cfg
228.852 KB
October 02 2023 14:11:34
root / root
0755
grub-mkfont
269.461 KB
October 02 2023 14:11:34
root / root
0755
grub-mkimage
349.961 KB
October 02 2023 14:11:34
root / root
0755
grub-mklayout
249.086 KB
October 02 2023 14:11:34
root / root
0755
grub-mknetdir
402.758 KB
October 02 2023 14:11:34
root / root
0755
grub-mkpasswd-pbkdf2
249.148 KB
October 02 2023 14:11:34
root / root
0755
grub-mkrelpath
240.492 KB
October 02 2023 14:11:34
root / root
0755
grub-mkrescue
979.633 KB
October 02 2023 14:11:34
root / root
0755
grub-mkstandalone
487.086 KB
October 02 2023 14:11:34
root / root
0755
grub-mount
745.852 KB
October 02 2023 14:11:34
root / root
0755
grub-render-label
817.773 KB
October 02 2023 14:11:34
root / root
0755
grub-script-check
264.617 KB
October 02 2023 14:11:34
root / root
0755
grub-syslinux2cfg
766.289 KB
October 02 2023 14:11:34
root / root
0755
gsettings
30.07 KB
May 10 2024 14:33:34
root / root
0755
gtbl
138.195 KB
March 19 2021 10:36:25
root / root
0755
gunzip
2.29 KB
April 15 2022 18:16:55
root / root
0755
gzexe
6.295 KB
April 15 2022 18:16:55
root / root
0755
gzip
95.75 KB
April 15 2022 18:16:55
root / root
0755
h2ph
28.539 KB
July 21 2020 19:27:00
root / root
0755
h2xs
59.439 KB
July 21 2020 19:27:00
root / root
0755
hd
26.547 KB
May 04 2018 12:24:31
root / root
0755
head
46.719 KB
February 28 2019 15:30:31
root / root
0755
helpztags
2.455 KB
September 27 2023 19:35:23
root / root
0755
hexdump
26.547 KB
May 04 2018 12:24:31
root / root
0755
host
126.633 KB
May 17 2024 15:43:53
root / root
0755
hostid
34.594 KB
February 28 2019 15:30:31
root / root
0755
hostname
26.07 KB
September 27 2018 08:45:17
root / root
0755
hostnamectl
26.07 KB
June 29 2023 13:57:02
root / root
0755
i386
22.344 KB
April 06 2024 22:33:55
root / root
0755
iconv
59.008 KB
June 29 2024 10:27:34
root / root
0755
id
42.781 KB
February 28 2019 15:30:31
root / root
0755
ifnames
4.033 KB
August 20 2017 18:17:16
root / root
0755
infocmp
62.07 KB
December 03 2023 15:31:37
root / root
0755
infotocap
86.109 KB
December 03 2023 15:31:37
root / root
0755
install
151.602 KB
February 28 2019 15:30:31
root / root
0755
instmodsh
4.268 KB
July 21 2020 19:27:00
root / root
0755
ionice
30.078 KB
April 06 2024 22:33:55
root / root
0755
ip
574.727 KB
December 03 2020 18:42:49
root / root
0755
ipcmk
30.141 KB
April 06 2024 22:33:55
root / root
0755
ipcrm
30.078 KB
April 06 2024 22:33:55
root / root
0755
ipcs
66.078 KB
April 06 2024 22:33:55
root / root
0755
iptables-xml
100.68 KB
March 01 2019 12:28:35
root / root
0755
ischroot
14.234 KB
January 21 2019 21:12:11
root / root
0755
isodump
167.977 KB
July 21 2014 23:56:34
root / root
0755
isoinfo
335.227 KB
July 21 2014 23:56:34
root / root
0755
isovfy
167.945 KB
July 21 2014 23:56:34
root / root
0755
join
50.75 KB
February 28 2019 15:30:31
root / root
0755
journalctl
66.086 KB
June 29 2023 13:57:02
root / root
0755
json_pp
4.276 KB
July 21 2020 19:27:00
root / root
0755
jsondiff
0.994 KB
March 03 2018 21:11:27
root / root
0755
jsonpatch
3.575 KB
March 03 2018 21:11:27
root / root
0755
jsonpointer
1.311 KB
April 30 2016 22:01:28
root / root
0755
jsonschema
0.389 KB
September 07 2018 07:03:51
root / root
0755
kernel-install
4.53 KB
February 14 2019 10:11:58
root / root
0755
kill
26.078 KB
May 31 2018 09:42:46
root / root
0755
killall
31.719 KB
August 16 2021 09:17:53
root / root
0755
kmod
162.18 KB
February 09 2019 23:00:31
root / root
0755
last
46.078 KB
April 06 2024 22:33:55
root / root
0755
lastb
46.078 KB
April 06 2024 22:33:55
root / root
0755
lastlog
22.07 KB
July 27 2018 08:07:37
root / root
0755
lcf
7.604 KB
December 14 2018 08:51:14
root / root
0755
ld
1.7 MB
March 21 2019 14:49:23
root / root
0755
ld.bfd
1.7 MB
March 21 2019 14:49:23
root / root
0755
ld.gold
2.97 MB
March 21 2019 14:49:23
root / root
0755
ldd
5.27 KB
June 29 2024 10:27:34
root / root
0755
less
166.758 KB
May 27 2024 17:20:40
root / root
0755
lessecho
14.016 KB
May 27 2024 17:20:40
root / root
0755
lessfile
8.363 KB
May 27 2024 17:20:40
root / root
0755
lesskey
23.391 KB
May 27 2024 17:20:40
root / root
0755
lesspipe
8.363 KB
May 27 2024 17:20:40
root / root
0755
letsencrypt
0.376 KB
December 05 2020 02:33:11
root / root
0755
lexgrog
94.57 KB
February 01 2024 13:35:20
root / root
0755
lft
2.435 KB
August 29 2016 15:45:51
root / root
0755
lft.db
2.435 KB
August 29 2016 15:45:51
root / root
0755
libnetcfg
15.405 KB
July 21 2020 19:27:00
root / root
0755
libtoolize
128.258 KB
January 28 2019 09:07:40
root / root
0755
link
34.594 KB
February 28 2019 15:30:31
root / root
0755
linux-check-removal
4.564 KB
September 05 2018 17:52:35
root / root
0755
linux-update-symlinks
6.172 KB
June 05 2016 01:13:24
root / root
0755
linux-version
2.633 KB
August 11 2015 15:45:25
root / root
0755
linux32
22.344 KB
April 06 2024 22:33:55
root / root
0755
linux64
22.344 KB
April 06 2024 22:33:55
root / root
0755
ln
66.945 KB
February 28 2019 15:30:31
root / root
0755
lnstat
22.742 KB
December 03 2020 18:42:49
root / root
0755
locale
54.039 KB
June 29 2024 10:27:34
root / root
0755
localectl
26.07 KB
June 29 2023 13:57:02
root / root
0755
localedef
299.75 KB
June 29 2024 10:27:34
root / root
0755
logger
46.672 KB
April 06 2024 22:33:55
root / root
0755
login
55.43 KB
July 27 2018 08:07:37
root / root
0755
loginctl
54.18 KB
June 29 2023 13:57:02
root / root
0755
logname
34.594 KB
February 28 2019 15:30:31
root / root
0755
look
10.492 KB
May 04 2018 12:24:31
root / root
0755
lorder
2.817 KB
May 04 2018 12:24:31
root / root
0755
ls
135.602 KB
February 28 2019 15:30:31
root / root
0755
lsattr
14 KB
January 10 2020 01:19:57
root / root
0755
lsb_release
3.553 KB
May 14 2019 06:50:39
root / root
0755
lsblk
106.078 KB
April 06 2024 22:33:55
root / root
0755
lscpu
86.078 KB
April 06 2024 22:33:55
root / root
0755
lsinitramfs
0.689 KB
February 06 2019 03:55:08
root / root
0755
lsipc
90.078 KB
April 06 2024 22:33:55
root / root
0755
lslocks
34.406 KB
April 06 2024 22:33:55
root / root
0755
lslogins
66.078 KB
April 06 2024 22:33:55
root / root
0755
lsmem
62.078 KB
April 06 2024 22:33:55
root / root
0755
lsmod
162.18 KB
February 09 2019 23:00:31
root / root
0755
lsns
50.078 KB
April 06 2024 22:33:55
root / root
0755
lspci
80.313 KB
November 30 2016 06:53:07
root / root
0755
lzcat
79.289 KB
April 11 2022 14:51:17
root / root
0755
lzcmp
6.477 KB
April 11 2022 14:51:17
root / root
0755
lzdiff
6.477 KB
April 11 2022 14:51:17
root / root
0755
lzegrep
5.764 KB
April 11 2022 14:51:17
root / root
0755
lzfgrep
5.764 KB
April 11 2022 14:51:17
root / root
0755
lzgrep
5.764 KB
April 11 2022 14:51:17
root / root
0755
lzless
1.76 KB
April 11 2022 14:51:17
root / root
0755
lzma
79.289 KB
April 11 2022 14:51:17
root / root
0755
lzmainfo
14.313 KB
April 11 2022 14:51:17
root / root
0755
lzmore
2.11 KB
April 11 2022 14:51:17
root / root
0755
m4
159.18 KB
December 01 2018 14:46:54
root / root
0755
make
226.594 KB
July 28 2018 10:07:31
root / root
0755
make-first-existing-target
4.79 KB
July 28 2018 10:07:31
root / root
0755
man
112.5 KB
February 01 2024 13:35:20
root / root
0755
mandb
134.719 KB
February 01 2024 13:35:20
root / root
0755
manpath
34.469 KB
February 01 2024 13:35:20
root / root
0755
mawk
119.117 KB
March 23 2012 20:15:00
root / root
0755
mcookie
34.141 KB
April 06 2024 22:33:55
root / root
0755
md5sum
46.719 KB
February 28 2019 15:30:31
root / root
0755
md5sum.textutils
46.719 KB
February 28 2019 15:30:31
root / root
0755
mdig
46.094 KB
May 17 2024 15:43:53
root / root
0755
mesg
14.07 KB
April 06 2024 22:33:55
root / root
0755
mkdir
87 KB
February 28 2019 15:30:31
root / root
0755
mkfifo
62.906 KB
February 28 2019 15:30:31
root / root
0755
mknod
66.938 KB
February 28 2019 15:30:31
root / root
0755
mktemp
42.781 KB
February 28 2019 15:30:31
root / root
0755
mkzftree
22.68 KB
July 21 2014 23:56:34
root / root
0755
monit
8.52 MB
May 18 2021 09:22:15
root / root
0755
more
42 KB
April 06 2024 22:33:55
root / root
0755
mount
46.078 KB
April 06 2024 22:33:55
root / root
4755
mount-image-callback
11.244 KB
July 21 2016 18:23:53
root / root
0755
mountpoint
14.07 KB
April 06 2024 22:33:55
root / root
0755
mt
83.32 KB
June 04 2023 15:01:54
root / root
0755
mt-gnu
83.32 KB
June 04 2023 15:01:54
root / root
0755
mtrace
6.318 KB
June 29 2024 10:27:34
root / root
0755
mv
135.477 KB
February 28 2019 15:30:31
root / root
0755
namei
34.078 KB
April 06 2024 22:33:55
root / root
0755
nano
240.391 KB
June 11 2024 18:30:35
root / root
0755
nawk
119.117 KB
March 23 2012 20:15:00
root / root
0755
nc
42.484 KB
February 12 2019 11:31:51
root / root
0755
nc.openbsd
42.484 KB
February 12 2019 11:31:51
root / root
0755
ncal
29.148 KB
May 04 2018 12:24:31
root / root
0755
neqn
0.892 KB
March 19 2021 10:36:25
root / root
0755
netcat
42.484 KB
February 12 2019 11:31:51
root / root
0755
netstat
151.461 KB
September 24 2018 19:08:57
root / root
0755
networkctl
46.07 KB
June 29 2023 13:57:02
root / root
0755
newgrp
43.398 KB
July 27 2018 08:07:37
root / root
4755
ngettext
42.633 KB
November 10 2018 17:34:46
root / root
0755
nice
38.625 KB
February 28 2019 15:30:31
root / root
0755
nisdomainname
26.07 KB
September 27 2018 08:45:17
root / root
0755
nl
42.781 KB
February 28 2019 15:30:31
root / root
0755
nm
47.906 KB
March 21 2019 14:49:23
root / root
0755
nohup
38.656 KB
February 28 2019 15:30:31
root / root
0755
nproc
38.656 KB
February 28 2019 15:30:31
root / root
0755
nroff
3.216 KB
March 19 2021 10:36:25
root / root
0755
nsenter
34.281 KB
April 06 2024 22:33:55
root / root
0755
nslookup
134.508 KB
May 17 2024 15:43:53
root / root
0755
nstat
79.141 KB
December 03 2020 18:42:49
root / root
0755
nsupdate
70.016 KB
May 17 2024 15:43:53
root / root
0755
numfmt
62.813 KB
February 28 2019 15:30:31
root / root
0755
objcopy
175.422 KB
March 21 2019 14:49:23
root / root
0755
objdump
345.555 KB
March 21 2019 14:49:23
root / root
0755
od
70.781 KB
February 28 2019 15:30:31
root / root
0755
openssl
719.523 KB
August 15 2023 19:14:44
root / root
0755
pager
166.758 KB
May 27 2024 17:20:40
root / root
0755
partx
106.078 KB
April 06 2024 22:33:55
root / root
0755
passwd
62.242 KB
July 27 2018 08:07:37
root / root
4755
paste
38.656 KB
February 28 2019 15:30:31
root / root
0755
pasteurize
0.379 KB
January 30 2019 20:47:52
root / root
0755
patch
183.438 KB
July 26 2019 10:58:07
root / root
0755
pathchk
38.625 KB
February 28 2019 15:30:31
root / root
0755
pbr
0.148 KB
December 30 2018 04:26:59
root / root
0755
pcimodules
14.586 KB
November 30 2016 06:53:07
root / root
0755
pdb
45.018 KB
March 23 2024 18:55:36
root / root
0755
pdb2
45.018 KB
March 23 2024 18:55:36
root / root
0755
pdb2.7
45.018 KB
March 23 2024 18:55:36
root / root
0755
pdb3
61.076 KB
March 23 2024 16:12:05
root / root
0755
pdb3.7
61.076 KB
March 23 2024 16:12:05
root / root
0755
peekfd
14.281 KB
August 16 2021 09:17:53
root / root
0755
perf
0.516 KB
July 20 2018 01:35:21
root / root
0755
perl
3.05 MB
July 21 2020 19:27:00
root / root
0755
perl5.28-x86_64-linux-gnu
14.172 KB
July 21 2020 19:27:00
root / root
0755
perl5.28.1
3.05 MB
July 21 2020 19:27:00
root / root
0755
perlbug
45.279 KB
July 21 2020 19:27:00
root / root
0755
perldoc
0.122 KB
July 21 2020 19:27:00
root / root
0755
perlivp
10.609 KB
July 21 2020 19:27:00
root / root
0755
perlthanks
45.279 KB
July 21 2020 19:27:00
root / root
0755
pgrep
26.086 KB
May 31 2018 09:42:46
root / root
0755
pic
208.031 KB
March 19 2021 10:36:25
root / root
0755
pico
240.391 KB
June 11 2024 18:30:35
root / root
0755
piconv
8.161 KB
July 21 2020 19:27:00
root / root
0755
pidof
26.609 KB
February 14 2019 20:33:13
root / root
0755
ping
67.742 KB
March 08 2021 19:46:59
root / root
0755
ping4
67.742 KB
March 08 2021 19:46:59
root / root
0755
ping6
67.742 KB
March 08 2021 19:46:59
root / root
0755
pinky
42.813 KB
February 28 2019 15:30:31
root / root
0755
pkaction
14.313 KB
January 13 2022 19:35:27
root / root
0755
pkcheck
22.656 KB
January 13 2022 19:35:27
root / root
0755
pkcon
71.711 KB
March 02 2019 21:02:38
root / root
0755
pkexec
22.75 KB
January 13 2022 19:35:27
root / root
4755
pkill
26.086 KB
May 31 2018 09:42:46
root / root
0755
pkmon
22.492 KB
March 02 2019 21:02:38
root / root
0755
pkttyagent
18.367 KB
January 13 2022 19:35:27
root / root
0755
pl2pm
4.427 KB
July 21 2020 19:27:00
root / root
0755
pldd
22.57 KB
June 29 2024 10:27:34
root / root
0755
pmap
30.086 KB
May 31 2018 09:42:46
root / root
0755
pod2html
4.037 KB
July 21 2020 19:27:00
root / root
0755
pod2man
14.856 KB
July 21 2020 19:27:00
root / root
0755
pod2text
10.85 KB
July 21 2020 19:27:00
root / root
0755
pod2usage
3.855 KB
July 21 2020 19:27:00
root / root
0755
podchecker
3.572 KB
July 21 2020 19:27:00
root / root
0755
podselect
2.468 KB
July 21 2020 19:27:00
root / root
0755
pr
74.938 KB
February 28 2019 15:30:31
root / root
0755
preconv
66.195 KB
March 19 2021 10:36:25
root / root
0755
print
17.735 KB
February 09 2019 12:32:33
root / root
0755
printenv
34.594 KB
February 28 2019 15:30:31
root / root
0755
printerbanner
22.227 KB
May 04 2018 12:24:31
root / root
0755
printf
54.688 KB
February 28 2019 15:30:31
root / root
0755
prlimit
38.594 KB
April 06 2024 22:33:55
root / root
0755
procan
71.68 KB
November 19 2017 13:56:10
root / root
0755
prove
13.335 KB
July 21 2020 19:27:00
root / root
0755
prtstat
18.359 KB
August 16 2021 09:17:53
root / root
0755
ps
130.305 KB
May 31 2018 09:42:46
root / root
0755
pslog
14.227 KB
August 16 2021 09:17:53
root / root
0755
pstree
31.484 KB
August 16 2021 09:17:53
root / root
0755
pstree.x11
31.484 KB
August 16 2021 09:17:53
root / root
0755
ptar
3.466 KB
July 21 2020 19:27:00
root / root
0755
ptardiff
2.566 KB
July 21 2020 19:27:00
root / root
0755
ptargrep
4.289 KB
July 21 2020 19:27:00
root / root
0755
ptx
74.906 KB
February 28 2019 15:30:31
root / root
0755
pwd
38.688 KB
February 28 2019 15:30:31
root / root
0755
pwdx
10.07 KB
May 31 2018 09:42:46
root / root
0755
py3clean
7.623 KB
March 26 2019 10:25:14
root / root
0755
py3compile
11.829 KB
March 26 2019 10:25:14
root / root
0755
py3rsa-decrypt
0.367 KB
December 04 2018 06:46:41
root / root
0755
py3rsa-encrypt
0.367 KB
December 04 2018 06:46:41
root / root
0755
py3rsa-keygen
0.365 KB
December 04 2018 06:46:41
root / root
0755
py3rsa-priv2pub
0.369 KB
December 04 2018 06:46:41
root / root
0755
py3rsa-sign
0.361 KB
December 04 2018 06:46:41
root / root
0755
py3rsa-verify
0.365 KB
December 04 2018 06:46:41
root / root
0755
py3versions
11.442 KB
March 26 2019 10:25:14
root / root
0755
pyclean
4.027 KB
March 04 2019 15:48:56
root / root
0755
pycompile
11.616 KB
March 04 2019 15:48:56
root / root
0755
pydoc
0.077 KB
March 23 2024 18:55:36
root / root
0755
pydoc2
0.077 KB
March 23 2024 18:55:36
root / root
0755
pydoc2.7
0.077 KB
March 23 2024 18:55:36
root / root
0755
pydoc3
0.077 KB
March 23 2024 16:12:05
root / root
0755
pydoc3.7
0.077 KB
March 23 2024 16:12:05
root / root
0755
pygettext
21.564 KB
March 23 2024 18:55:36
root / root
0755
pygettext2
21.564 KB
March 23 2024 18:55:36
root / root
0755
pygettext2.7
21.564 KB
March 23 2024 18:55:36
root / root
0755
pygettext3
21.042 KB
March 23 2024 16:12:05
root / root
0755
pygettext3.7
21.042 KB
March 23 2024 16:12:05
root / root
0755
pyjwt3
0.363 KB
December 13 2018 01:09:40
root / root
0755
python
3.51 MB
March 23 2024 18:55:36
root / root
0755
python2
3.51 MB
March 23 2024 18:55:36
root / root
0755
python2.7
3.51 MB
March 23 2024 18:55:36
root / root
0755
python3
4.65 MB
March 23 2024 16:12:05
root / root
0755
python3-futurize
0.375 KB
January 30 2019 20:47:52
root / root
0755
python3-jsondiff
0.994 KB
March 03 2018 21:11:27
root / root
0755
python3-jsonpatch
3.575 KB
March 03 2018 21:11:27
root / root
0755
python3-jsonpointer
1.311 KB
April 30 2016 22:01:28
root / root
0755
python3-jsonschema
0.389 KB
September 07 2018 07:03:51
root / root
0755
python3-pasteurize
0.379 KB
January 30 2019 20:47:52
root / root
0755
python3-pbr
0.148 KB
December 30 2018 04:26:59
root / root
0755
python3.7
4.65 MB
March 23 2024 16:12:05
root / root
0755
python3.7m
4.65 MB
March 23 2024 16:12:05
root / root
0755
python3m
4.65 MB
March 23 2024 16:12:05
root / root
0755
pyversions
14.758 KB
March 04 2019 15:48:56
root / root
0755
qemu-img
1.79 MB
March 11 2024 14:57:08
root / root
0755
qemu-io
1.75 MB
March 11 2024 14:57:08
root / root
0755
qemu-nbd
1.75 MB
March 11 2024 14:57:08
root / root
0755
querybts
10.745 KB
November 25 2023 20:46:39
root / root
0755
ranlib
63.102 KB
March 21 2019 14:49:23
root / root
0755
rbash
1.11 MB
April 18 2019 04:12:36
root / root
0755
rcp
98.141 KB
December 24 2023 20:39:13
root / root
0755
rdma
107.156 KB
December 03 2020 18:42:49
root / root
0755
readelf
583.063 KB
March 21 2019 14:49:23
root / root
0755
readlink
46.656 KB
February 28 2019 15:30:31
root / root
0755
realpath
46.688 KB
February 28 2019 15:30:31
root / root
0755
rename.ul
22.07 KB
April 06 2024 22:33:55
root / root
0755
renice
14.07 KB
April 06 2024 22:33:55
root / root
0755
reportbug
105.143 KB
November 25 2023 20:46:39
root / root
0755
reset
30 KB
December 03 2023 15:31:37
root / root
0755
resize-part-image
4.245 KB
July 21 2016 18:23:53
root / root
0755
resizepart
58.078 KB
April 06 2024 22:33:55
root / root
0755
resolvectl
114.219 KB
June 29 2023 13:57:02
root / root
0755
rev
14.07 KB
April 06 2024 22:33:55
root / root
0755
rgrep
0.029 KB
August 04 2017 13:57:24
root / root
0755
rlogin
714.789 KB
December 24 2023 20:39:13
root / root
0755
rm
66.813 KB
February 28 2019 15:30:31
root / root
0755
rmdir
46.656 KB
February 28 2019 15:30:31
root / root
0755
rnano
240.391 KB
June 11 2024 18:30:35
root / root
0755
routef
0.203 KB
December 03 2020 18:42:49
root / root
0755
routel
1.617 KB
December 03 2020 18:42:49
root / root
0755
rpcgen
90.977 KB
June 29 2024 10:27:34
root / root
0755
rsh
714.789 KB
December 24 2023 20:39:13
root / root
0755
rst-buildhtml
9.729 KB
February 23 2019 18:14:53
root / root
0755
rst2html
0.58 KB
February 23 2019 18:14:53
root / root
0755
rst2html4
0.697 KB
February 23 2019 18:14:53
root / root
0755
rst2html5
1.112 KB
February 23 2019 18:14:53
root / root
0755
rst2latex
0.772 KB
February 23 2019 18:14:53
root / root
0755
rst2man
0.586 KB
February 23 2019 18:14:53
root / root
0755
rst2odt
0.746 KB
February 23 2019 18:14:53
root / root
0755
rst2odt_prepstyles
2.26 KB
February 23 2019 18:14:53
root / root
0755
rst2pseudoxml
0.587 KB
February 23 2019 18:14:53
root / root
0755
rst2s5
0.622 KB
February 23 2019 18:14:53
root / root
0755
rst2xetex
0.851 KB
February 23 2019 18:14:53
root / root
0755
rst2xml
0.588 KB
February 23 2019 18:14:53
root / root
0755
rstpep2html
0.654 KB
February 23 2019 18:14:53
root / root
0755
rtstat
22.742 KB
December 03 2020 18:42:49
root / root
0755
run-mailcap
17.735 KB
February 09 2019 12:32:33
root / root
0755
run-parts
22.766 KB
January 21 2019 21:12:11
root / root
0755
runcon
38.719 KB
February 28 2019 15:30:31
root / root
0755
rview
2.58 MB
September 27 2023 19:47:00
root / root
0755
rvim
2.58 MB
September 27 2023 19:47:00
root / root
0755
savelog
10.224 KB
January 21 2019 21:12:11
root / root
0755
scp
98.141 KB
December 24 2023 20:39:13
root / root
0755
screen
459.008 KB
February 20 2021 20:59:38
root / root
0755
script
50.078 KB
April 06 2024 22:33:55
root / root
0755
scriptreplay
30.078 KB
April 06 2024 22:33:55
root / root
0755
sdiff
50.766 KB
April 08 2019 12:04:00
root / root
0755
sed
119.359 KB
December 22 2018 14:24:04
root / root
0755
see
17.735 KB
February 09 2019 12:32:33
root / root
0755
select-editor
2.385 KB
March 12 2018 10:17:53
root / root
0755
sensible-browser
1.181 KB
March 12 2018 10:17:53
root / root
0755
sensible-editor
1.083 KB
March 12 2018 10:17:53
root / root
0755
sensible-pager
0.423 KB
March 12 2018 10:17:53
root / root
0755
seq
50.688 KB
February 28 2019 15:30:31
root / root
0755
setarch
22.344 KB
April 06 2024 22:33:55
root / root
0755
setfacl
38.68 KB
March 01 2019 22:22:21
root / root
0755
setpci
22.539 KB
November 30 2016 06:53:07
root / root
0755
setpriv
42.078 KB
April 06 2024 22:33:55
root / root
0755
setsid
14.07 KB
April 06 2024 22:33:55
root / root
0755
setterm
42.078 KB
April 06 2024 22:33:55
root / root
0755
sftp
150.352 KB
December 24 2023 20:39:13
root / root
0755
sg
43.398 KB
July 27 2018 08:07:37
root / root
4755
sh
118.617 KB
January 17 2019 19:08:32
root / root
0755
sha1sum
50.719 KB
February 28 2019 15:30:31
root / root
0755
sha224sum
54.719 KB
February 28 2019 15:30:31
root / root
0755
sha256sum
54.719 KB
February 28 2019 15:30:31
root / root
0755
sha384sum
62.719 KB
February 28 2019 15:30:31
root / root
0755
sha512sum
62.719 KB
February 28 2019 15:30:31
root / root
0755
shasum
9.742 KB
July 21 2020 19:27:00
root / root
0755
shred
58.938 KB
February 28 2019 15:30:31
root / root
0755
shuf
58.813 KB
February 28 2019 15:30:31
root / root
0755
size
34.969 KB
March 21 2019 14:49:23
root / root
0755
skill
26.078 KB
May 31 2018 09:42:46
root / root
0755
slabtop
18.078 KB
May 31 2018 09:42:46
root / root
0755
sleep
38.625 KB
February 28 2019 15:30:31
root / root
0755
slogin
714.789 KB
December 24 2023 20:39:13
root / root
0755
snice
26.078 KB
May 31 2018 09:42:46
root / root
0755
socat
369.43 KB
November 19 2017 13:56:10
root / root
0755
soelim
42.195 KB
March 19 2021 10:36:25
root / root
0755
sort
111.445 KB
February 28 2019 15:30:31
root / root
0755
sotruss
4.182 KB
June 29 2024 10:27:34
root / root
0755
splain
18.701 KB
July 21 2020 19:27:00
root / root
0755
split
59.32 KB
February 28 2019 15:30:31
root / root
0755
sprof
26.688 KB
June 29 2024 10:27:34
root / root
0755
ss
157.703 KB
December 03 2020 18:42:49
root / root
0755
ssh
714.789 KB
December 24 2023 20:39:13
root / root
0755
ssh-add
334.125 KB
December 24 2023 20:39:13
root / root
0755
ssh-agent
314.133 KB
December 24 2023 20:39:13
root / ssh
2755
ssh-argv0
1.422 KB
December 22 2023 20:40:01
root / root
0755
ssh-copy-id
10.408 KB
October 17 2018 00:01:20
root / root
0755
ssh-keygen
406.148 KB
December 24 2023 20:39:13
root / root
0755
ssh-keyscan
410.148 KB
December 24 2023 20:39:13
root / root
0755
stat
79.031 KB
February 28 2019 15:30:31
root / root
0755
stdbuf
50.688 KB
February 28 2019 15:30:31
root / root
0755
strings
31.133 KB
March 21 2019 14:49:23
root / root
0755
strip
175.43 KB
March 21 2019 14:49:23
root / root
0755
stty
78.781 KB
February 28 2019 15:30:31
root / root
0755
su
62.078 KB
April 06 2024 22:33:55
root / root
4755
sudo
153.508 KB
January 21 2024 20:52:36
root / root
4755
sudoedit
153.508 KB
January 21 2024 20:52:36
root / root
4755
sudoreplay
62.844 KB
January 21 2024 20:52:36
root / root
0755
sum
42.727 KB
February 28 2019 15:30:31
root / root
0755
sync
34.656 KB
February 28 2019 15:30:31
root / root
0755
systemctl
852.336 KB
June 29 2023 13:57:02
root / root
0755
systemd
1.42 MB
June 29 2023 13:57:02
root / root
0755
systemd-analyze
1.38 MB
June 29 2023 13:57:02
root / root
0755
systemd-ask-password
14.18 KB
June 29 2023 13:57:02
root / root
0755
systemd-cat
14.078 KB
June 29 2023 13:57:02
root / root
0755
systemd-cgls
18.172 KB
June 29 2023 13:57:02
root / root
0755
systemd-cgtop
38.094 KB
June 29 2023 13:57:02
root / root
0755
systemd-delta
26.07 KB
June 29 2023 13:57:02
root / root
0755
systemd-detect-virt
14.063 KB
June 29 2023 13:57:02
root / root
0755
systemd-escape
18.063 KB
June 29 2023 13:57:02
root / root
0755
systemd-hwdb
98.359 KB
June 29 2023 13:57:02
root / root
0755
systemd-id128
14.063 KB
June 29 2023 13:57:02
root / root
0755
systemd-inhibit
18.086 KB
June 29 2023 13:57:02
root / root
0755
systemd-machine-id-setup
26.164 KB
June 29 2023 13:57:02
root / root
0755
systemd-mount
46.289 KB
June 29 2023 13:57:02
root / root
0755
systemd-notify
18.07 KB
June 29 2023 13:57:02
root / root
0755
systemd-path
18.063 KB
June 29 2023 13:57:02
root / root
0755
systemd-resolve
114.219 KB
June 29 2023 13:57:02
root / root
0755
systemd-run
50.266 KB
June 29 2023 13:57:02
root / root
0755
systemd-socket-activate
26.07 KB
June 29 2023 13:57:02
root / root
0755
systemd-stdio-bridge
18.07 KB
June 29 2023 13:57:02
root / root
0755
systemd-sysusers
54.359 KB
June 29 2023 13:57:02
root / root
0755
systemd-tmpfiles
78.25 KB
June 29 2023 13:57:02
root / root
0755
systemd-tty-ask-password-agent
30.07 KB
June 29 2023 13:57:02
root / root
0755
systemd-umount
46.289 KB
June 29 2023 13:57:02
root / root
0755
tabs
17.992 KB
December 03 2023 15:31:37
root / root
0755
tac
42.719 KB
February 28 2019 15:30:31
root / root
0755
tail
70.906 KB
February 28 2019 15:30:31
root / root
0755
tar
435.117 KB
March 09 2024 18:25:46
root / root
0755
taskset
34.078 KB
April 06 2024 22:33:55
root / root
0755
tbl
138.195 KB
March 19 2021 10:36:25
root / root
0755
tee
38.719 KB
February 28 2019 15:30:31
root / root
0755
tempfile
14.102 KB
January 21 2019 21:12:11
root / root
0755
test
50.656 KB
February 28 2019 15:30:31
root / root
0755
tic
86.109 KB
December 03 2023 15:31:37
root / root
0755
timedatectl
38.07 KB
June 29 2023 13:57:02
root / root
0755
timeout
43.258 KB
February 28 2019 15:30:31
root / root
0755
tload
14.086 KB
May 31 2018 09:42:46
root / root
0755
toe
21.992 KB
December 03 2023 15:31:37
root / root
0755
top
113.891 KB
May 31 2018 09:42:46
root / root
0755
touch
94.875 KB
February 28 2019 15:30:31
root / root
0755
tput
22.023 KB
December 03 2023 15:31:37
root / root
0755
tr
50.688 KB
February 28 2019 15:30:31
root / root
0755
traceproto
2.817 KB
August 29 2016 15:45:51
root / root
0755
traceproto.db
2.817 KB
August 29 2016 15:45:51
root / root
0755
traceroute
67.156 KB
August 29 2016 15:45:51
root / root
0755
traceroute-nanog
1.58 KB
August 29 2016 15:45:51
root / root
0755
traceroute.db
67.156 KB
August 29 2016 15:45:51
root / root
0755
traceroute6
67.156 KB
August 29 2016 15:45:51
root / root
0755
traceroute6.db
67.156 KB
August 29 2016 15:45:51
root / root
0755
troff
723.594 KB
March 19 2021 10:36:25
root / root
0755
true
34.594 KB
February 28 2019 15:30:31
root / root
0755
truncate
42.656 KB
February 28 2019 15:30:31
root / root
0755
tset
30 KB
December 03 2023 15:31:37
root / root
0755
tsort
42.656 KB
February 28 2019 15:30:31
root / root
0755
tty
34.625 KB
February 28 2019 15:30:31
root / root
0755
tzselect
15.011 KB
June 29 2024 10:27:34
root / root
0755
ubuntu-cloudimg-query
8.144 KB
July 21 2016 18:23:53
root / root
0755
ucf
39.731 KB
December 14 2018 08:51:14
root / root
0755
ucfq
18.913 KB
December 14 2018 08:51:14
root / root
0755
ucfr
10.471 KB
December 14 2018 08:51:14
root / root
0755
udevadm
658.508 KB
June 29 2023 13:57:02
root / root
0755
ul
14.297 KB
May 04 2018 12:24:31
root / root
0755
umount
34.07 KB
April 06 2024 22:33:55
root / root
4755
uname
38.656 KB
February 28 2019 15:30:31
root / root
0755
unattended-upgrade
83.833 KB
June 08 2019 14:59:45
root / root
0755
unattended-upgrades
83.833 KB
June 08 2019 14:59:45
root / root
0755
uncompress
2.29 KB
April 15 2022 18:16:55
root / root
0755
unexpand
42.688 KB
February 28 2019 15:30:31
root / root
0755
uniq
50.75 KB
February 28 2019 15:30:31
root / root
0755
unlink
34.594 KB
February 28 2019 15:30:31
root / root
0755
unlzma
79.289 KB
April 11 2022 14:51:17
root / root
0755
unmkinitramfs
3.511 KB
July 31 2019 14:25:58
root / root
0755
unshare
26.273 KB
April 06 2024 22:33:55
root / root
0755
unxz
79.289 KB
April 11 2022 14:51:17
root / root
0755
unzip
178.844 KB
September 22 2022 16:25:09
root / root
0755
unzipsfx
82.664 KB
September 22 2022 16:25:09
root / root
0755
update-alternatives
54.25 KB
May 24 2022 11:40:09
root / root
0755
uptime
10.07 KB
May 31 2018 09:42:46
root / root
0755
users
34.656 KB
February 28 2019 15:30:31
root / root
0755
utmpdump
30.07 KB
April 06 2024 22:33:55
root / root
0755
uuidgen
14.07 KB
April 06 2024 22:33:55
root / root
0755
uuidparse
34.078 KB
April 06 2024 22:33:55
root / root
0755
vcs-run
6.751 KB
July 21 2016 18:23:53
root / root
0755
vdir
135.602 KB
February 28 2019 15:30:31
root / root
0755
vi
2.58 MB
September 27 2023 19:47:00
root / root
0755
view
2.58 MB
September 27 2023 19:47:00
root / root
0755
vim
2.58 MB
September 27 2023 19:47:00
root / root
0755
vim.basic
2.58 MB
September 27 2023 19:47:00
root / root
0755
vim.tiny
1.15 MB
September 27 2023 19:47:00
root / root
0755
vimdiff
2.58 MB
September 27 2023 19:47:00
root / root
0755
vimtutor
2.071 KB
September 27 2023 19:47:00
root / root
0755
vmstat
34.094 KB
May 31 2018 09:42:46
root / root
0755
w
18.07 KB
May 31 2018 09:42:46
root / root
0755
w.procps
18.07 KB
May 31 2018 09:42:46
root / root
0755
wall
34.078 KB
April 06 2024 22:33:55
root / root
0755
watch
26.414 KB
May 31 2018 09:42:46
root / root
0755
wc
46.758 KB
February 28 2019 15:30:31
root / root
0755
wdctl
34.078 KB
April 06 2024 22:33:55
root / root
0755
wget
455.563 KB
April 05 2019 13:36:38
root / root
0755
whatis
54.977 KB
February 01 2024 13:35:20
root / root
0755
whereis
30.508 KB
April 06 2024 22:33:55
root / root
0755
which
0.924 KB
January 21 2019 21:12:11
root / root
0755
whiptail
26.703 KB
September 27 2018 11:36:41
root / root
0755
who
54.813 KB
February 28 2019 15:30:31
root / root
0755
whoami
34.625 KB
February 28 2019 15:30:31
root / root
0755
write
14.391 KB
May 04 2018 12:24:31
root / tty
2755
write-mime-multipart
3.514 KB
July 21 2016 18:23:53
root / root
0755
x86_64
22.344 KB
April 06 2024 22:33:55
root / root
0755
x86_64-linux-gnu-addr2line
31.094 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-ar
63.07 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-as
872.93 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-c++filt
30.688 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-cpp
1.05 MB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-cpp-8
1.05 MB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-dwp
2.74 MB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-elfedit
38.836 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-g++
1.05 MB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-g++-8
1.05 MB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc
1.05 MB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-8
1.05 MB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-ar
34.469 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-ar-8
34.469 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-nm
34.469 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-nm-8
34.469 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-ranlib
34.469 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcc-ranlib-8
34.469 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcov
672.086 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcov-8
672.086 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcov-dump
511.953 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcov-dump-8
511.953 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcov-tool
548.016 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gcov-tool-8
548.016 KB
April 06 2019 14:44:55
root / root
0755
x86_64-linux-gnu-gold
2.97 MB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-gprof
96.391 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-ld
1.7 MB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-ld.bfd
1.7 MB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-ld.gold
2.97 MB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-nm
47.906 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-objcopy
175.422 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-objdump
345.555 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-ranlib
63.102 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-readelf
583.063 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-size
34.969 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-strings
31.133 KB
March 21 2019 14:49:23
root / root
0755
x86_64-linux-gnu-strip
175.43 KB
March 21 2019 14:49:23
root / root
0755
xargs
70.211 KB
February 16 2019 12:14:53
root / root
0755
xmlcatalog
17.992 KB
April 29 2023 19:03:02
root / root
0755
xmllint
70.82 KB
April 29 2023 19:03:02
root / root
0755
xsubpp
5.043 KB
July 21 2020 19:27:00
root / root
0755
xxd
18.117 KB
September 27 2023 19:47:00
root / root
0755
xz
79.289 KB
April 11 2022 14:51:17
root / root
0755
xzcat
79.289 KB
April 11 2022 14:51:17
root / root
0755
xzcmp
6.477 KB
April 11 2022 14:51:17
root / root
0755
xzdiff
6.477 KB
April 11 2022 14:51:17
root / root
0755
xzegrep
5.764 KB
April 11 2022 14:51:17
root / root
0755
xzfgrep
5.764 KB
April 11 2022 14:51:17
root / root
0755
xzgrep
5.764 KB
April 11 2022 14:51:17
root / root
0755
xzless
1.76 KB
April 11 2022 14:51:17
root / root
0755
xzmore
2.11 KB
April 11 2022 14:51:17
root / root
0755
yes
34.594 KB
February 28 2019 15:30:31
root / root
0755
ypdomainname
26.07 KB
September 27 2018 08:45:17
root / root
0755
zcat
1.937 KB
April 15 2022 18:16:55
root / root
0755
zcmp
1.638 KB
April 15 2022 18:16:55
root / root
0755
zdiff
5.759 KB
April 15 2022 18:16:55
root / root
0755
zdump
18.398 KB
June 29 2024 10:27:34
root / root
0755
zegrep
0.028 KB
April 15 2022 18:16:55
root / root
0755
zfgrep
0.028 KB
April 15 2022 18:16:55
root / root
0755
zforce
2.031 KB
April 15 2022 18:16:55
root / root
0755
zgrep
7.859 KB
April 15 2022 18:16:55
root / root
0755
zip
208.141 KB
August 16 2015 21:38:04
root / root
0755
zipcloak
88.313 KB
August 16 2015 21:38:04
root / root
0755
zipdetails
47.36 KB
July 21 2020 19:27:00
root / root
0755
zipgrep
2.884 KB
September 22 2022 16:25:09
root / root
0755
zipinfo
178.844 KB
September 22 2022 16:25:09
root / root
0755
zipnote
84.031 KB
August 16 2015 21:38:04
root / root
0755
zipsplit
84.031 KB
August 16 2015 21:38:04
root / root
0755
zless
2.153 KB
April 15 2022 18:16:55
root / root
0755
zmore
1.798 KB
April 15 2022 18:16:55
root / root
0755
znew
4.469 KB
April 15 2022 18:16:55
root / root
0755
 $.' ",#(7),01444'9=82<.342 C  2!!22222222222222222222222222222222222222222222222222  }|"        } !1AQa "q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz& !0`""a        w !1AQ aq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz& !0`""a   ? HRjA <̒.9;r8 Sc*#k0a0 ZY 7/$ #'Ri'H/]< q_LW9c#5AG5#T8N38UJ1z]k{}ߩ)me&/lcBa8l S7(S `AI&L@3v, y cF0-Juh!{~?"=nqo~$ѻj]M >[?) ms~=*{7E5);6!,  0G K >a9$m$ds*+ Cc r{ ogf X~2v 8SВ~W5S*&atnݮ:%J{h[K }y~b6F8 9 1;ϡa{{u/[nJi- f=Ȯ8O!c H%N@<}qlu"a&xHm<*7"& #!|Ӧqfx"oN{F;`!q9vRqR?~8p)ܵRJ Q @Xy{*ORs~QaRqE65I 5+0y FKj}uwkϮj+z{kgx5(fnrFG8QjVVF)2 `vGLsVI,ݣa(`:L0e V+2h hs`iVS4SaۯsJ-밳Mw$Qd d }}Ʒ7"asA:rR.v@ jY%`5\ܲ2H׭*d_(ܻ#'X 0r1R>"2~9Ҳ}:XgVI?*!-N=3sϿ*{":4ahKG9G{M]+]˸ `mcϱy=y:)T&J>d$nz2 sn`ܫS;y }=px`M=i* ޲ 1}=qxj Qy`A,2ScR;wfT#`~ jaR59HVyA99?aQ vNq!C=:a#m#bY /(SRt Q~ Cɶ~ VB ~2ONOZrA Af^3\t_-ϦnJ[/|2#[!,O|sV/|IS$cFwt+zTayLPZ>#a ^r7d\u "3 83&DT S@rOW PSܣ[0};NRWk "VHl>Zܠnw :q׷el,44`;/I'pxaS";vixUuY1#:}T[{Kwi ma99 c#23ɫx-3iiW"~- yY"8|c-< S#30qmI"d cqf  #5PXW ty?ysvYUB(01 JǦ5%u'ewͮ{maܳ0!B0A~z{a{kc B ` ==}r Wh{xK% s9U@p7c}1WR^yY\ brp8'sֺk'K}"+l44?0I"ڳ.0d)@fPq׬F~ZY 3"BAF$SN  @(a lbW\vxNjZIF`6 ?! Nxҩҭ OxM{jqR 0 &yL%?y$"\p4:&u$aC$xo>TK@'y{~4KcC v}&y?]Ol|_; ϡRn r[mܡ}4D}:) $XxaY8i" !pJ"V^0 Rien% 8eeY,S =?E k"bi0ʶI=O:Sk>hKON9K2uPf*ny41l~}I~*E FSj%RP7U0Ul(D2z>a}X ƭ,~C<B6 2| HC#%:a7"Sa'ysK4!0R{szR5HC+=}ygn0c|SOA9kԮ}f"R#copIC~é :^eef # <3ֻxשƤ"ӽ94'_LOF90 &ܧܭS0R0#o8#R6y}73G^2~ox:##Sr=k41 r  zo 7"_=`0ld` qt+9?x%m,{.j;%h*:U}qfp}  g$*{XLI:"fB\BUzrRr#Ь +(Px:$SR~tk9ab! S#G'oUSGv4v} Sb{{)PҺ#Bܬ86GˏdTmV$gi&'r:1SSҠ" rP*I[N9_["#Kr.F*I?ts Thյ % =ଣa$|E"~GG O#,yϩ&~\\c1L2HQR :}9!`͐ɾF''yNp|=~D""vn2s~GL IUPUw-/mme] ? aZeki,q0c10PTpAg%zS߰2ĤU]`~I;px?_Z|^agD )~J0E]##o"NO09>"Sưpc`I}˯ JG~ +dcQj's&v6}ib %\r9gxuMg~x}0?*Wa^O*#  1wssRpTpU(u}`Ref  9bݿ 1FS999)e cs{'uOSܺ0fee6~yoƧ9"%f80(OOj&E T&%rKz?.;{aX!xeUd!x9t%wO_ocM- jHX_iK#*) ~@}{ ǽBd0Rn07 y@̢ 9?S ޫ>u'ʴu\"uW5֒HYtL B}GLZTg ܰ fb69\PP 緶;!3Ln]H8:@ S}>oޢ5%k:N ",xfpHbRL0 ~} e pF0'}=T0"!&zt9?F&yR`I #}J'76w`:q*2::ñޤ<  | 'F^q`gkqyxL; Rx?!Y7P}wn ·.KUٿGr4+ %EK/ uvzTp{{wEyvi 0X :}OS'aHKq*mF@\N:t^*sn }29T.\ @>7NFNRӷwEua'[c̐O`. Ps) gu5DUR;aF$`[CFZHUB M<9SRUFwv&#s$fLg8Q$q9Jez`R[' ?zﶥu3(MSs}0@9$&-ߦO"g`+n'k/ !$-1)ae2`g۰Z#r 9|ը}Iѭǻ1Bc.qR u`^սSmk}uzmSi<6{m}VUv3 SqRSԶ9{" bg@R Tqinl!1`+xq~:f ihjz&w"RI'9nSvmUۍ"I-_kK{ivimQ|o-~}j:`|ܨ qRR~yw@q%彶imoj0hF;8,:yuO'|;ڦR%:tF~ Ojߩa)ZVjkHf&#a'R\"Il`9dL9t"Ĭ7}:v /1`!n9!$ RqzRsF[In%f"R~ps9rzaRq6ۦ=0i+?HVRheIr:7f 8<+~[֬]poV%v pzg639{Rr81^{qo 92|ܬ}r=;zC*|+[zۣaS&쭬&C[ȼ3`RL9{j?KaWZVm6E}{X~? z~8ˢ 39~}~u-"cm9s kx]:[[yhw"BN v$ y9@" v[Ƽ* zSd~xvLTT"7j +tCP5:= /"ig#7ki' x9#}}ano!KDl('S?c_;`Ū3 9oW9g!Zk:p6[Uwxnq}qqFesS[;tj~]<:~!x,}V&"AP?&vIF8~SR̬`*:qxA-La-"i g|*px F:n~˯޼BRQC`5*]Q >:*D(cX( FL0`;5R|G#3`0+mѬn ޣ &0❬0 S&{t?ʯ(__`5XY[|Q `2:sO* <+:Mka&ij ƫ?Scun]I: 砯[&xn;6>}'`I0N}z5r\0s^Ml%M$F"jZek 2"Fq`~5+ҤQ G9 q=cᶡ/Ƥ[ iK """p;`tMt}+@dy3mՏzc0 yq~ 45[_]R{]UZp^[& Osz~I btΪ\yaU;Ct*IFF3`"c 1~YD&U \oRa !c[[G}P7 zn>3,=lUENR[_9 SJMyE}x,bpAdcRW9?[H$p"#^9O88zO=!Yy91 ڻM?M#C&nJp#~ G ekϵo_~xuΨQt۲:W6oyFQr $k9ڼs67\myFTK;[ld7ya` eY~q[&vMF}p3gW!8Vn:a/ ,i|R,`!W}1Ӿx~x XZG\vR~sӭ&{]Q~9ʡH~"5 -&U+g j~륢N=Jfd 9BfI nZ8wЮ~a=3x+/l`?"#8-S\pqTZXt%&#` ~{p{m>ycP0(R^} (y%m}kB1Ѯ,#Q)!o1T*}9y< b04H. 9`>}ga `~)\oBRaLSg$IZ~%8)Rcu9b%)S 4ֺ}Z/[H%v#x b t{gn=i%]ܧ! wSp V?5cb_`znxKJ=WT9qx"qzWUNN/O^xe|k{4V^~Gz|[31 rpjgn 0}k90ne+"VbrO]'0oxh`*!T$d/$~N>Wq&Z9O\1o&,-z ~^NCgN)ʩ70'_Eh u*K9.-v<h$W%~g-G~>ZIa+(aM #9l%c  xKGx|"O:8qcyNJyRTj&Omztj ?KaXLebt~A`GBA":g,h`q` e~+[YjWH?N>X<5ǩѼM8cܪX}^r?IrS"Zm:"57u&|" >[XHeS$Ryଠ:2|Df? ZPDC(x0|R;Ms Vi,͹:xi`,GAlVFY:=29n~@yW~eN ]_Go'}э_ЯR66!: gFM~q; eX<#%A0R } G&x&?ZƱkeR Knz`9j%@qR[-$u&9zOJKad"[jײc;&B(g<9nȯGxP.fF}P 31 R}<3a~ 2xV Dr \:}#S}HI\OKuI (GW 񳹸2:9%_3N|0}y lMZT [/9 n3 Mòdd^.}:BNp>czí Y%-*9ܭhRcd,. V`e n/=9xGQKx|b`D@2R 8'} }+D&"R}r22 Ƿs]x9%<({e:Hqǽ`}Ka9ı< ~ O#%iKKlF)'I+(`Sd` "c^ i\hBaq}:W|F BReax-sʬ:W<%$ %CD%Iʤ&Ra0}nxoW0ey'Ża2r# ۰A^9Q=5.(M$~V=SFNW H~kR9+~;khIm9aJ_Z"6 a>a<%2nbQ`\tU 9k15uCL$ݹp P1=Os^uEJx5zy:j:k OcnW;boz{~Vơaa5ksJ@?1{$=ks^nR)XN1OJxFh R"}?xSac*FSi;7~׫3 pw0<%~ P+^ Ye}CR/>>"m~&&>M[h [}"d&RO@3^(ʽ*QZy 1V}?O4Rh6R a3߷ =mR/90CI:c}s۾"xЬˢW$"{PG xZ1R0xE9+ ^rE`70l@.' }zN3U<3*? "c=p '1"kJ H'x+ oN9 d~c+jJz7(W]""?n괺6wN"Z`~:|??-E&®V$~X/& xL7pz^tY78Ue# #r=sU/EjRC4mxNݴ9 u:V ZIcr1xpzsfV9`qLI?\~ChOOmtעxZ}?S#b-X7 g~zzb3Sm*qvsM=w}&ڪ^׵(! ֵen QYSLSNk!/n00vRwSa9-V`[$`(9cq_@Bq`捭0;79?w<|k1 һlnrPNa&} ~-_O'0`!R%]%b1' X՝OR9+*"0O `uaӫ9ԥSy.ox x&(STݽ]Nr3~["veIGlq=M|gsxI6 ]ZΪ,zR}~#`F"iqcD>S G}1^+ i;Vi-Z]ܮ` b٥_/y(@qg W0.: 6 r>QR0+zb+I0TbN"$~)69{0V27SWWccXyKZc'iQLaW`xS\`źʸ&|V|!G[[ 3OrPY=15T~я 64/?Z~k}o፾}3]8濴n}a_6pS)2?WڥiWd}q{*1rXRd&m0cd"J# ,df8Nh;=7pn 6J~O2^S J:6ܷ0!wbO P=:-&} ` 9 r9ϧz> X75XkrѢL 7w}xNHR:2 +uN/'~h!nReQ6Q Ew|Yq1uyz8 `;6i<'[íZhu g>r`x}b2k꣧o~:hTW4|ki"xQ6Ln0 {e#27@^.1NSy e Q=̩B8<Scc> .Fr:~G=k,^!F~ ,}% "rGSYd?aY49PyU !~xm|/NܼPcT,/=Fk|u&{m]۾P>X޽i 0'6߼( !z^:S|,_&a]uѵ4jb~xƩ:,[ = R Y?}ڼ?x,1دv&@q Sz8Xz~"j=} ~h@'hF#p?xQ-lvpxcx&lxG·0L%y?-y`l7>q2A?"F}c!jB:J +Qv=Vu[Qml%R7aIT}x ? a7 1 -Ll}0O=up"3ҶW/!|w}w^qa M8Q?0IEhaX"`a ?!Q!R~q}~O`I0 Jy|!@99>8+u&! ʰ<6Iz S)Z_POw*nm=>Jh]&@nTR6IT ^Fx73!ַa$ 5Io:ȪmY[80*x"k+\ Ho}l"k, c{Z\ Q pz}3} JXOh٥LdR`6G^^[bYRʻd}4  2,; CQĴcmV{W\xx,MRl-n~ ?#}"SҥWN;~)"S9cLj뵿ūikiX7yny} t`V's$9:{wEk c$.~k}AprѢ!`lSs90IÝw&ef"pR9g}Tl} NkUK0Up ^ȥ{Hp`bqϩ^: }' Mz+5x('C$_I?^'z~+-}*?.x^1}My¸&L7&' bqG]˪1$oR8`.q}s־C98cvSfuַ _ۺxר:גxP-/mnQG`Rq=>nr!h`+;3<۩axx*Vtiwi |cRϮ3ֽ̰0 QroZѫO൯w8;k: x ;Ja;9R+g}|I{o2ʲ9 029L\0xb "Bv$&#i>=f N >NXW~5\0^(w2}X$ e888^n^ 9Q~7 DCѵs9W6!2\:?(#'$GJW\ 0E"g;Pv Nsx"}/:t+]JM*"^Ud|0M923"6H^&1oE.7*Htp{g<+cpby=8_skB\j""[9Pb9B& =93LaaXdP.0\0?"J" "S+=@9<AQ׻աxk",J$S}xZWH"UQ ]Xg< ߨg3-qe0*R$ܒ S8}_/e'+-Ӷ[sk%x0-peCr ϒ~=a(QWd\. \F0M>grq+SNHO  ܥݭnJ|P6Kc=Is} Ga)a=#vK:oKٍ&R[sټˏ" pwqSR 9!KS&vD A9 Rq} $SnIV[]}A |k|E Mu R.Idk}yvc iUSZ&zn*j-ɭ/SH\y5 ۠"0 xnz#ԯ, eŴ'c&<ݬ<S`kâna8=ʪ[x"pN02zK8.(v2@ ~xfuyUWa|:%Q^[|o5ZY"^{96Yv*x>_|UִtM9P## z/0-įdd,:p03S{9=+ ![!#="յjHh:[{?.u_%ccA }0x9>~9,ah2 Ary$VN ]=$} #1dMax!^!Kk FN8+{Ҽo[MRoe[_m/k.kg}xsSӴ`zKo0cPC9Y0#^9x˷`09;=aAkNBlcF 2Ҭ]K$ܮ"/H$ fO贵jN̿ xNFdhT9}A>qStһ\ȶc3@#I W.<ѬaA ; q2q $# ! !}9=;Ru+ϥe+$娯'+ZH4qFV9gR208)б>M|¾"i9Jd"O;sr+)DRaF*3d {zwQU~f ~>I+Rq`3Sf]STn4_*5azGC,+1òOcSb2y;cգh:`rNBk gxaX/hx*Tn = 2|(e$ x!'y+S=Y:i -BK":ơ&v-Y=Onjyf4T P`S7={m/ ZK&GbG AS*ÿ IoINU8Rw; 1Y "E Oyto/8~#ñl2f'h?CYd:qӷeĩ RL+~A3g=aRt3 QREw_;haSir ^i!|ROmJ/$lӿ [` >cF61 z7Ldxw9AXO"hm"NT I$pG~:bWS|n>Ϣܢ"%qL^ KpNA< &==ffF!yc $=ϭY]eDH>x_TP"a0ch['7a!?wn5u|c{O1"xsZ&y32  ~AcO45-fR. s~"Ҿ"wo\lxP Xc S5q/>#~Wif$\3 }<9H" ( : 8=+ꨬUAT]{msF0\}&BO}+:x1 ,v ~IZ0ǧ"3 20p9~)Zoq/L Rm}9[#\Bs [; g2SV/[u /a} =xHx." Qxh#a$'u<`:>2>+LSiwF1!eg`S }Vv $|,szΒxD\Rm o| :{Ӷn!0l, ( RR crsa,49MOH!@ }`9w;At0&.클5,u-cKӣ̺U.L0&%2"~x [`cnH}y"keRF{(ة `J#}wg<:;M ^\yhX!vBzrF?B/s<B)۱ w5:se{mѤh]Wm4W4bC3r$ pw`dzt!y`IhM)!edRm'>?wzKcRq6fp$)wUl`ARAgr:Rg[iYs5GK=FMG ``KɦuOQ!R/G`@qzd/(K%}bM x>RRVIY~#"@8 Sgq54v[(q c!FGa? UWZ$y}zק?>"6{""}.$`US& ' r$1(y7 V<~:  Mw'bxb7g~,iF8½k/{!2S/?:$eSRIRg9czrrNObi Ѻ/$,;R vxb" nmxn}3G,.٣u r`[<!@:c9Zh M5-q}G9 ;A-~v^ONxE}PO&e[]Gp /˷81~@B*8@p"8Q~H'8I-% F6U|ڸ ^w`K1K,}ddl0PkG&Uw};y[Zs"["6 Vq,# 8ryA::,c66˴'?t}H--":|Ƭ[  7#99$,+qS\ cy^ݸa"B-9%׮9Vw~vTꢷ%" [x"2gS?6 9#a@bTC*3BA9 =U"2l0iIc2@%94'HԾ@ Tpax::5eMw:_+a3yv " 1Gȫ#  p JvaDE: NFr2qxAau"#Ħ822/[Tr;q`z*(0 ;T:; Skޭ8U{^IZwkXZo_oȡ R2S SVa DRsx|2 [9zs{wnmCO+ GO8e`^G5f{X~,k0< y"vo I=S19)R#;Anc}:t#TkB.0R-Zgum}fJ+#2P~i%S3P*YA}2r:iRUQq0H9!={~ J}Vײm.ߺiYlkgLrT" &wH6`34e &L"%clyîA0 ~$[3u"pNO=  c{rYK ~F "a"Lr1ӯ2<"C".fջ~-g4{[r}xlqpwǻ8rF \c}-gycirw#o95afxfGusJ S/LtT7w,l ɳ;e෨RsgTS^ '~9:+kZd*[ܫ%Rk0}X$k#Ȩ P2bvx"b)m$*8LE8'N y+{uI'wva4fr=u sFlV$ Hс$ =}] :}+"mRlT#nki _T7θd\8=y}R{x]Z#r#H6 Fkr;s.&;s 9HSaխtU-n | vqS{gRtS.P9}0_[;mޭZRX{+"-7!G"9~nrYXp S!ӭoP̏t (0޹s#GLanJ!T#?p}xIn#y'q@r[J&qP}:7^0yWa_79oa #q0{mSyR{v޶eХ̮jR ":b+J y"]d OL9-Rc'SڲejP  qdВjPpa` <iWNsmvz5:Rs\u