コード例 #1
0
ファイル: Options.py プロジェクト: mkhon/bleachbit
def init_configuration():
    """Initialize an empty configuration, if necessary"""
    if not os.path.exists(bleachbit.options_dir):
        General.makedirs(bleachbit.options_dir)
    if os.path.lexists(bleachbit.options_file):
        logger.debug('Deleting configuration: %s ' % bleachbit.options_file)
        os.remove(bleachbit.options_file)
    with open(bleachbit.options_file, 'w', encoding='utf-8-sig') as f_ini:
        f_ini.write('[bleachbit]\n')
        if os.name == 'nt' and bleachbit.portable_mode:
            f_ini.write('[Portable]\n')
    for section in options.config.sections():
        options.config.remove_section(section)
    options.restore()
コード例 #2
0
ファイル: Action.py プロジェクト: tstenner/bleachbit
 def __init__(self, action_element, path_vars=None):
     """Initialize file search"""
     self.regex = action_element.getAttribute('regex')
     assert(isinstance(self.regex, (str, unicode, types.NoneType)))
     self.nregex = action_element.getAttribute('nregex')
     assert(isinstance(self.nregex, (str, unicode, types.NoneType)))
     self.wholeregex = action_element.getAttribute('wholeregex')
     assert(isinstance(self.wholeregex, (str, unicode, types.NoneType)))
     self.nwholeregex = action_element.getAttribute('nwholeregex')
     assert(isinstance(self.nwholeregex, (str, unicode, types.NoneType)))
     self.search = action_element.getAttribute('search')
     self.object_type = action_element.getAttribute('type')
     self._set_paths(action_element.getAttribute('path'), path_vars)
     self.ds = {}
     if 'deep' == self.search:
         self.ds['regex'] = self.regex
         self.ds['nregex'] = self.nregex
         self.ds['cache'] = General.boolstr_to_bool(
             action_element.getAttribute('cache'))
         self.ds['command'] = action_element.getAttribute('command')
         self.ds['path'] = self.paths[0]
         if not len(self.paths) == 1:
             logger.warning(
                 'deep scan does not support multi-value variables')
     if not any([self.object_type, self.regex, self.nregex,
                 self.wholeregex, self.nwholeregex]):
         # If the filter is not needed, bypass it for speed.
         self.get_paths = self._get_paths
コード例 #3
0
ファイル: Memory.py プロジェクト: ksy6278/bleachbit
def wipe_swap_linux(devices, proc_swaps):
    """Shred the Linux swap file and then reinitilize it"""
    if devices is None:
        return
    if 0 < count_swap_linux():
        raise RuntimeError('Cannot wipe swap while it is in use')
    for device in devices:
        logger.info("wiping swap device '%s'", device)
        safety_limit_bytes = 29 * 1024 ** 3  # 29 gibibytes
        actual_size_bytes = get_swap_size_linux(device, proc_swaps)
        if actual_size_bytes > safety_limit_bytes:
            raise RuntimeError(
                'swap device %s is larger (%d) than expected (%d)' %
                (device, actual_size_bytes, safety_limit_bytes))
        uuid = get_swap_uuid(device)
        // wipe 실행
        FileUtilities.wipe_contents(device, truncate=False)
        // 초기화
        logger.debug('reinitializing swap device %s', device)
        args = ['mkswap', device]
        if uuid:
            args.append("-U")
            args.append(uuid)
        (rc, _, stderr) = General.run_external(args)
        if 0 != rc:
            raise RuntimeError(stderr.replace("\n", ""))
コード例 #4
0
ファイル: Memory.py プロジェクト: DimitarTerzov/bleachbit
def wipe_swap_linux(devices, proc_swaps):
    """Shred the Linux swap file and then reinitialize it"""
    if devices is None:
        return
    if 0 < count_swap_linux():
        raise RuntimeError('Cannot wipe swap while it is in use')
    for device in devices:
        #if '/cryptswap' in device:
        #    logger.info('Skipping encrypted swap device %s.', device)
        #    continue
        # TRANSLATORS: The variable is a device like /dev/sda2
        logger.info(_("Wiping the swap device %s."), device)
        safety_limit_bytes = 29 * 1024**3  # 29 gibibytes
        actual_size_bytes = get_swap_size_linux(device, proc_swaps)
        if actual_size_bytes > safety_limit_bytes:
            raise RuntimeError(
                'swap device %s is larger (%d) than expected (%d)' %
                (device, actual_size_bytes, safety_limit_bytes))
        uuid = get_swap_uuid(device)
        # wipe
        FileUtilities.wipe_contents(device, truncate=False)
        # reinitialize
        # TRANSLATORS: The variable is a device like /dev/sda2
        logger.debug(_("Reinitializing the swap device %s."), device)
        args = ['mkswap', device]
        if uuid:
            args.append("-U")
            args.append(uuid)
        (rc, _stdout, stderr) = General.run_external(args)
        if 0 != rc:
            raise RuntimeError(stderr.replace("\n", ""))
コード例 #5
0
 def run_process():
     try:
         if self.wait:
             args = self.cmd.split(' ')
             (rc, stdout, stderr) = General.run_external(args)
         else:
             rc = 0  # unknown because we don't wait
             from subprocess import Popen
             Popen(self.cmd)
     except Exception as e:
         raise RuntimeError(
             'Exception in external command\nCommand: %s\nError: %s' %
             (self.cmd, str(e)))
     else:
         if not 0 == rc:
             msg = 'Command: %s\nReturn code: %d\nStdout: %s\nStderr: %s\n'
             if isinstance(stdout, unicode):
                 stdout = stdout.encode('utf-8')
             if isinstance(stderr, unicode):
                 stderr = stderr.encode('utf-8')
             if isinstance(self.cmd, unicode):
                 cmd = self.cmd.encode('utf-8')
             else:
                 cmd = self.cmd
             logger.warning(msg, cmd, rc, stdout, stderr)
     return 0
コード例 #6
0
ファイル: Memory.py プロジェクト: ksy6278/bleachbit
def get_proc_swaps():
    
    (rc, stdout, _) = General.run_external(['swapon', '-s'])
    if 0 == rc:
        return stdout
    logger.debug('"swapoff -s" failed so falling back to /proc/swaps')
    return open("/proc/swaps").read()
コード例 #7
0
ファイル: Memory.py プロジェクト: DimitarTerzov/bleachbit
def disable_swap_linux():
    """Disable Linux swap and return list of devices"""
    if 0 == count_swap_linux():
        return
    logger.debug(_("Disabling swap."))
    args = ["swapoff", "-a", "-v"]
    (rc, stdout, stderr) = General.run_external(args)
    if 0 != rc:
        raise RuntimeError(stderr.replace("\n", ""))
    devices = []
    for line in stdout.split('\n'):
        line = line.replace('\n', '')
        if '' == line:
            continue
        ret = parse_swapoff(line)
        if ret is None:
            raise RuntimeError(
                "Unexpected output:\nargs='%(args)s'\nstdout='%(stdout)s'\nstderr='%(stderr)s'"
                % {
                    'args': str(args),
                    'stdout': stdout,
                    'stderr': stderr
                })
        devices.append(ret)
    return devices
コード例 #8
0
ファイル: Memory.py プロジェクト: JulianVolodia/bleachbit
def wipe_swap_linux(devices, proc_swaps):
    """Shred the Linux swap file and then reinitilize it"""
    if devices is None:
        return
    if 0 < count_swap_linux():
        raise RuntimeError('Cannot wipe swap while it is in use')
    for device in devices:
        logger.info("wiping swap device '%s'", device)
        safety_limit_bytes = 16 * 1024 ** 3  # 16 gibibytes
        actual_size_bytes = get_swap_size_linux(device, proc_swaps)
        if actual_size_bytes > safety_limit_bytes:
            raise RuntimeError(
                'swap device %s is larger (%d) than expected (%d)' %
                (device, actual_size_bytes, safety_limit_bytes))
        uuid = get_swap_uuid(device)
        # wipe
        FileUtilities.wipe_contents(device, truncate=False)
        # reinitialize
        logger.debug('reinitializing swap device %s', device)
        args = ['mkswap', device]
        if uuid:
            args.append("-U")
            args.append(uuid)
        (rc, _, stderr) = General.run_external(args)
        if 0 != rc:
            raise RuntimeError(stderr.replace("\n", ""))
コード例 #9
0
ファイル: Action.py プロジェクト: zhgfly01/bleachbit
 def __init__(self, action_element):
     """Initialize file search"""
     self.regex = action_element.getAttribute('regex')
     assert (isinstance(self.regex, (str, unicode, types.NoneType)))
     self.nregex = action_element.getAttribute('nregex')
     assert (isinstance(self.nregex, (str, unicode, types.NoneType)))
     self.wholeregex = action_element.getAttribute('wholeregex')
     assert (isinstance(self.wholeregex, (str, unicode, types.NoneType)))
     self.nwholeregex = action_element.getAttribute('nwholeregex')
     assert (isinstance(self.nwholeregex, (str, unicode, types.NoneType)))
     self.search = action_element.getAttribute('search')
     self.object_type = action_element.getAttribute('type')
     self.path = expanduser(expandvars(action_element.getAttribute('path')))
     if 'nt' == os.name and self.path:
         # convert forward slash to backslash for compatibility with getsize()
         # and for display.  Do not convert an empty path, or it will become
         # the current directory (.).
         self.path = os.path.normpath(self.path)
     self.ds = {}
     if 'deep' == self.search:
         self.ds['regex'] = self.regex
         self.ds['nregex'] = self.nregex
         self.ds['cache'] = General.boolstr_to_bool(
             action_element.getAttribute('cache'))
         self.ds['command'] = action_element.getAttribute('command')
         self.ds['path'] = self.path
     if not any([
             self.object_type, self.regex, self.nregex, self.wholeregex,
             self.nwholeregex
     ]):
         # If the filter is not needed, bypass it for speed.
         self.get_paths = self._get_paths
コード例 #10
0
ファイル: Action.py プロジェクト: zoonytoons/bleachbit
 def __init__(self, action_element, path_vars=None):
     """Initialize file search"""
     self.regex = action_element.getAttribute('regex')
     assert(isinstance(self.regex, (str, unicode, types.NoneType)))
     self.nregex = action_element.getAttribute('nregex')
     assert(isinstance(self.nregex, (str, unicode, types.NoneType)))
     self.wholeregex = action_element.getAttribute('wholeregex')
     assert(isinstance(self.wholeregex, (str, unicode, types.NoneType)))
     self.nwholeregex = action_element.getAttribute('nwholeregex')
     assert(isinstance(self.nwholeregex, (str, unicode, types.NoneType)))
     self.search = action_element.getAttribute('search')
     self.object_type = action_element.getAttribute('type')
     self._set_paths(action_element.getAttribute('path'), path_vars)
     self.ds = {}
     if 'deep' == self.search:
         self.ds['regex'] = self.regex
         self.ds['nregex'] = self.nregex
         self.ds['cache'] = General.boolstr_to_bool(
             action_element.getAttribute('cache'))
         self.ds['command'] = action_element.getAttribute('command')
         self.ds['path'] = self.paths[0]
         if not len(self.paths) == 1:
             logger.warning(
                 'deep scan does not support multi-value variables')
     if not any([self.object_type, self.regex, self.nregex,
                 self.wholeregex, self.nwholeregex]):
         # If the filter is not needed, bypass it for speed.
         self.get_paths = self._get_paths
コード例 #11
0
ファイル: Options.py プロジェクト: brahmastra2016/bleachbit
 def __flush(self):
     """Write information to disk"""
     if not self.purged:
         self.__purge()
     if not os.path.exists(bleachbit.options_dir):
         General.makedirs(bleachbit.options_dir)
     mkfile = not os.path.exists(bleachbit.options_file)
     _file = open(bleachbit.options_file, 'wb')
     try:
         self.config.write(_file)
     except IOError as e:
         print(e)
         from errno import ENOSPC
         if e.errno == ENOSPC:
             logger.error("disk is full writing configuration '%s'", bleachbit.options_file)
         else:
             raise
     if mkfile and General.sudo_mode():
         General.chownself(bleachbit.options_file)
コード例 #12
0
ファイル: Memory.py プロジェクト: JulianVolodia/bleachbit
def get_proc_swaps():
    """Return the output of 'swapon -s'"""
    # Usually 'swapon -s' is identical to '/proc/swaps'
    # Here is one exception:
    # https://bugs.launchpad.net/ubuntu/+source/bleachbit/+bug/1092792
    (rc, stdout, _) = General.run_external(['swapon', '-s'])
    if 0 == rc:
        return stdout
    logger.debug('"swapoff -s" failed so falling back to /proc/swaps')
    return open("/proc/swaps").read()
コード例 #13
0
ファイル: Options.py プロジェクト: ksy6278/bleachbit
 def __flush(self):
    
     if not self.purged:
         self.__purge()
     if not os.path.exists(bleachbit.options_dir):
         General.makedirs(bleachbit.options_dir)
     mkfile = not os.path.exists(bleachbit.options_file)
     _file = open(bleachbit.options_file, 'wb')
     try:
         self.config.write(_file)
     except IOError as e:
         print(e)
         from errno import ENOSPC
         if e.errno == ENOSPC:
             logger.error("disk is full writing configuration '%s'", bleachbit.options_file)
         else:
             raise
     if mkfile and General.sudo_mode():
         General.chownself(bleachbit.options_file)
コード例 #14
0
def get_proc_swaps():
    """Return the output of 'swapon -s'"""
    # Usually 'swapon -s' is identical to '/proc/swaps'
    # Here is one exception:
    # https://bugs.launchpad.net/ubuntu/+source/bleachbit/+bug/1092792
    (rc, stdout, _) = General.run_external(['swapon', '-s'])
    if 0 == rc:
        return stdout
    logger.debug('"swapoff -s" failed so falling back to /proc/swaps')
    return open("/proc/swaps").read()
コード例 #15
0
ファイル: Options.py プロジェクト: mkhon/bleachbit
 def __flush(self):
     """Write information to disk"""
     if not self.purged:
         self.__purge()
     if not os.path.exists(bleachbit.options_dir):
         General.makedirs(bleachbit.options_dir)
     mkfile = not os.path.exists(bleachbit.options_file)
     with open(bleachbit.options_file, 'w', encoding='utf-8-sig') as _file:
         try:
             self.config.write(_file)
         except IOError as e:
             from errno import ENOSPC
             if e.errno == ENOSPC:
                 logger.error(
                     _("Disk was full when writing configuration to file %s"), bleachbit.options_file)
             else:
                 raise
     if mkfile and General.sudo_mode():
         General.chownself(bleachbit.options_file)
コード例 #16
0
ファイル: Memory.py プロジェクト: JulianVolodia/bleachbit
def get_swap_uuid(device):
    """Find the UUID for the swap device"""
    uuid = None
    args = ['blkid', device, '-s', 'UUID']
    (_, stdout, _) = General.run_external(args)
    for line in stdout.split('\n'):
        # example: /dev/sda5: UUID="ee0e85f6-6e5c-42b9-902f-776531938bbf"
        ret = re.search("^%s: UUID=\"([a-z0-9-]+)\"" % device, line)
        if ret is not None:
            uuid = ret.group(1)
    logger.debug("uuid(%s)='%s'", device, uuid)
    return uuid
コード例 #17
0
ファイル: Memory.py プロジェクト: ksy6278/bleachbit
def get_swap_uuid(device):
    
    uuid = None
    args = ['blkid', device, '-s', 'UUID']
    (_, stdout, _) = General.run_external(args)
    for line in stdout.split('\n'):
        # example: /dev/sda5: UUID="ee0e85f6-6e5c-42b9-902f-776531938bbf"
        ret = re.search("^%s: UUID=\"([a-z0-9-]+)\"" % device, line)
        if ret is not None:
            uuid = ret.group(1)
    logger.debug("uuid(%s)='%s'", device, uuid)
    return uuid
コード例 #18
0
ファイル: Memory.py プロジェクト: pan93412/bleachbit
def get_swap_uuid(device):
    """Find the UUID for the swap device"""
    uuid = None
    args = ['blkid', device, '-s', 'UUID']
    (_rc, stdout, _stderr) = General.run_external(args)
    for line in stdout.split('\n'):
        # example: /dev/sda5: UUID="ee0e85f6-6e5c-42b9-902f-776531938bbf"
        ret = re.search("^%s: UUID=\"([a-z0-9-]+)\"" % device, line)
        if ret is not None:
            uuid = ret.group(1)
    logger.debug(_("Found UUID for swap file %s is %s."), device, uuid)
    return uuid
コード例 #19
0
ファイル: Unix.py プロジェクト: brahmastra2016/bleachbit
def start_with_computer(enabled):
    """If enabled, create shortcut to start application with computer.
    If disabled, then delete the shortcut."""
    if not enabled:
        # User requests to not automatically start BleachBit
        if os.path.lexists(bleachbit.autostart_path):
            # Delete the shortcut
            FileUtilities.delete(bleachbit.autostart_path)
        return
    # User requests to automatically start BleachBit
    if os.path.lexists(bleachbit.autostart_path):
        # Already automatic, so exit
        return
    if not os.path.exists(bleachbit.launcher_path):
        logger.error('%s does not exist: ', bleachbit.launcher_path)
        return
    import shutil
    General.makedirs(os.path.dirname(bleachbit.autostart_path))
    shutil.copy(bleachbit.launcher_path, bleachbit.autostart_path)
    os.chmod(bleachbit.autostart_path, 0o755)
    if General.sudo_mode():
        General.chownself(bleachbit.autostart_path)
コード例 #20
0
ファイル: Unix.py プロジェクト: JulianVolodia/bleachbit
def start_with_computer(enabled):
    """If enabled, create shortcut to start application with computer.
    If disabled, then delete the shortcut."""
    if not enabled:
        # User requests to not automatically start BleachBit
        if os.path.lexists(bleachbit.autostart_path):
            # Delete the shortcut
            FileUtilities.delete(bleachbit.autostart_path)
        return
    # User requests to automatically start BleachBit
    if os.path.lexists(bleachbit.autostart_path):
        # Already automatic, so exit
        return
    if not os.path.exists(bleachbit.launcher_path):
        logger.error('%s does not exist: ', bleachbit.launcher_path)
        return
    import shutil
    General.makedirs(os.path.dirname(bleachbit.autostart_path))
    shutil.copy(bleachbit.launcher_path, bleachbit.autostart_path)
    os.chmod(bleachbit.autostart_path, 0o755)
    if General.sudo_mode():
        General.chownself(bleachbit.autostart_path)
コード例 #21
0
ファイル: Action.py プロジェクト: tstenner/bleachbit
 def run_process():
     try:
         if self.wait:
             args = self.cmd.split(' ')
             (rc, stdout, stderr) = General.run_external(args)
         else:
             rc = 0  # unknown because we don't wait
             from subprocess import Popen
             Popen(self.cmd)
     except Exception as e:
         raise RuntimeError(
             'Exception in external command\nCommand: %s\nError: %s' % (self.cmd, str(e)))
     else:
         if not 0 == rc:
             logger.warning('Command: %s\nReturn code: %d\nStdout: %s\nStderr: %s\n',
                            self.cmd, rc, stdout, stderr)
     return 0
コード例 #22
0
ファイル: Action.py プロジェクト: zoonytoons/bleachbit
 def run_process():
     try:
         if self.wait:
             args = self.cmd.split(' ')
             (rc, stdout, stderr) = General.run_external(args)
         else:
             rc = 0  # unknown because we don't wait
             from subprocess import Popen
             Popen(self.cmd)
     except Exception as e:
         raise RuntimeError(
             'Exception in external command\nCommand: %s\nError: %s' % (self.cmd, str(e)))
     else:
         if not 0 == rc:
             logger.warning('Command: %s\nReturn code: %d\nStdout: %s\nStderr: %s\n',
                            self.cmd, rc, stdout, stderr)
     return 0
コード例 #23
0
ファイル: Memory.py プロジェクト: ksy6278/bleachbit
def make_self_oom_target_linux():
    
    path = '/proc/%d/oom_score_adj' % os.getpid()
    if os.path.exists(path):
        open(path, 'w').write('1000')
    else:
        path = '/proc/%d/oomadj' % os.getpid()
        if os.path.exists(path):
            open(path, 'w').write('15')
    # OOM likes nice processes
    logger.debug('new nice value %d', os.nice(19))
    # OOM prefers non-privileged processes
    try:
        uid = General.getrealuid()
        if uid > 0:
            logger.debug('dropping privileges of pid %d to uid %d', os.getpid(), uid)
            os.seteuid(uid)
    except:
        traceback.print_exc()
コード例 #24
0
ファイル: Memory.py プロジェクト: JulianVolodia/bleachbit
def make_self_oom_target_linux():
    """Make the current process the primary target for Linux out-of-memory killer"""
    # In Linux 2.6.36 the system changed from oom_adj to oom_score_adj
    path = '/proc/%d/oom_score_adj' % os.getpid()
    if os.path.exists(path):
        open(path, 'w').write('1000')
    else:
        path = '/proc/%d/oomadj' % os.getpid()
        if os.path.exists(path):
            open(path, 'w').write('15')
    # OOM likes nice processes
    logger.debug('new nice value %d', os.nice(19))
    # OOM prefers non-privileged processes
    try:
        uid = General.getrealuid()
        if uid > 0:
            logger.debug('dropping privileges of pid %d to uid %d', os.getpid(), uid)
            os.seteuid(uid)
    except:
        traceback.print_exc()
コード例 #25
0
ファイル: Memory.py プロジェクト: JulianVolodia/bleachbit
def disable_swap_linux():
    """Disable Linux swap and return list of devices"""
    if 0 == count_swap_linux():
        return
    logger.debug('disabling swap"')
    args = ["swapoff", "-a", "-v"]
    (rc, stdout, stderr) = General.run_external(args)
    if 0 != rc:
        raise RuntimeError(stderr.replace("\n", ""))
    devices = []
    for line in stdout.split('\n'):
        line = line.replace('\n', '')
        if '' == line:
            continue
        ret = parse_swapoff(line)
        if ret is None:
            raise RuntimeError("Unexpected output:\nargs='%(args)s'\nstdout='%(stdout)s'\nstderr='%(stderr)s'"
                               % {'args': str(args), 'stdout': stdout, 'stderr': stderr})
        devices.append(ret)
    return devices
コード例 #26
0
ファイル: Memory.py プロジェクト: pan93412/bleachbit
def make_self_oom_target_linux():
    """Make the current process the primary target for Linux out-of-memory killer"""
    # In Linux 2.6.36 the system changed from oom_adj to oom_score_adj
    path = '/proc/%d/oom_score_adj' % os.getpid()
    if os.path.exists(path):
        open(path, 'w').write('1000')
    else:
        path = '/proc/%d/oomadj' % os.getpid()
        if os.path.exists(path):
            open(path, 'w').write('15')
    # OOM likes nice processes
    logger.debug(_("Setting nice value %d for this process."), os.nice(19))
    # OOM prefers non-privileged processes
    try:
        uid = General.getrealuid()
        if uid > 0:
            logger.debug(
                _("Dropping privileges of pid %d to uid %d."), os.getpid(), uid)
            os.seteuid(uid)
    except:
        logger.exception('Error when dropping privileges')
コード例 #27
0
ファイル: Unix.py プロジェクト: valyvalya/bleachbit
def dnf_autoremove():
    """Run 'dnf autoremove' and return size in bytes recovered."""
    if os.path.exists('/var/run/dnf.pid'):
        msg = _(
            "%s cannot be cleaned because it is currently running.  Close it, and try again.") % "Dnf"
        raise RuntimeError(msg)
    cmd = ['dnf', '-y', 'autoremove']
    (rc, stdout, stderr) = General.run_external(cmd)
    freed_bytes = 0
    allout = stdout + stderr
    if 'Error: This command has to be run under the root user.' in allout:
        raise RuntimeError('dnf autoremove >> requires root permissions')
    if rc > 0:
        raise RuntimeError('dnf raised error %s: %s' % (rc, stderr))

    cregex = re.compile("Freed space: ([\d.]+[\s]+[BkMG])")
    match = cregex.search(allout)
    if match:
        freed_bytes = parseSize(match.group(1))
    logger.debug(
        'dnf_autoremove >> total freed bytes: %s', freed_bytes)
    return freed_bytes
コード例 #28
0
ファイル: Unix.py プロジェクト: tstenner/bleachbit
def get_apt_size():
    """Return the size of the apt cache (in bytes)"""
    (rc, stdout, stderr) = General.run_external(['apt-get', '-s', 'clean'])
    paths = re.findall('/[/a-z\.\*]+', stdout)
    return get_globs_size(paths)
コード例 #29
0
ファイル: Windows.py プロジェクト: tstenner/bleachbit
 def wu_service():
     General.run_external(args)
     return 0
コード例 #30
0
 def wu_service():
     General.run_external(args)
     return 0
コード例 #31
0
def get_apt_size():
    """Return the size of the apt cache (in bytes)"""
    (rc, stdout, stderr) = General.run_external(['apt-get', '-s', 'clean'])
    paths = re.findall('/[/a-z\.\*]+', stdout)
    return get_globs_size(paths)