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()
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
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", ""))
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", ""))
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
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()
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
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", ""))
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
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)
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()
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)
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)
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
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
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
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)
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
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()
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()
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
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')
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
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)
def wu_service(): General.run_external(args) return 0