diff --git a/borg/archive.py b/borg/archive.py index a7ecc8d8d..0bb65e099 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -18,7 +18,7 @@ from . import xattr from .compress import Compressor, COMPR_BUFFER from .constants import * # NOQA from .helpers import Chunk, Error, uid2user, user2uid, gid2group, group2gid, \ - parse_timestamp, to_localtime, format_time, format_timedelta, \ + parse_timestamp, to_localtime, format_time, format_timedelta, safe_encode, safe_decode, \ Manifest, Statistics, decode_dict, make_path_safe, StableDict, int_to_bigint, bigint_to_int, bin_to_hex, \ ProgressIndicatorPercent, ChunkIteratorFileWrapper, remove_surrogates, log_multi, \ PathPrefixPattern, FnmatchPattern, open_item, file_status, format_file_size, consume @@ -175,7 +175,7 @@ class Archive: self.id = id self.metadata = self._load_meta(self.id) decode_dict(self.metadata, ARCHIVE_TEXT_KEYS) - self.metadata[b'cmdline'] = [arg.decode('utf-8', 'surrogateescape') for arg in self.metadata[b'cmdline']] + self.metadata[b'cmdline'] = [safe_decode(arg) for arg in self.metadata[b'cmdline']] self.name = self.metadata[b'name'] @property @@ -566,7 +566,7 @@ Number of files: {0.stats.nfiles}'''.format( return status else: self.hard_links[st.st_ino, st.st_dev] = safe_path - path_hash = self.key.id_hash(os.path.join(self.cwd, path).encode('utf-8', 'surrogateescape')) + path_hash = self.key.id_hash(safe_encode(os.path.join(self.cwd, path))) first_run = not cache.files ids = cache.file_known_and_unchanged(path_hash, st, ignore_inode) if first_run: @@ -794,7 +794,7 @@ class ArchiveChecker: for chunk_id, size, csize in item[b'chunks']: if chunk_id not in self.chunks: # If a file chunk is missing, create an all empty replacement chunk - logger.error('{}: Missing file chunk detected (Byte {}-{})'.format(item[b'path'].decode('utf-8', 'surrogateescape'), offset, offset + size)) + logger.error('{}: Missing file chunk detected (Byte {}-{})'.format(safe_decode(item[b'path']), offset, offset + size)) self.error_found = True data = bytes(size) chunk_id = self.key.id_hash(data) @@ -881,7 +881,7 @@ class ArchiveChecker: if archive[b'version'] != 1: raise Exception('Unknown archive metadata version') decode_dict(archive, ARCHIVE_TEXT_KEYS) - archive[b'cmdline'] = [arg.decode('utf-8', 'surrogateescape') for arg in archive[b'cmdline']] + archive[b'cmdline'] = [safe_decode(arg) for arg in archive[b'cmdline']] items_buffer = ChunkBuffer(self.key) items_buffer.write_chunk = add_callback for item in robust_iterator(archive): @@ -1186,7 +1186,7 @@ class ArchiveRecreater: logger.info('Found %s, will resume interrupted operation', target_name) old_target = self.open_archive(target_name) resume_id = old_target.metadata[b'recreate_source_id'] - resume_args = [arg.decode('utf-8', 'surrogateescape') for arg in old_target.metadata[b'recreate_args']] + resume_args = [safe_decode(arg) for arg in old_target.metadata[b'recreate_args']] if resume_id != archive.id: logger.warning('Source archive changed, will discard %s and start over', target_name) logger.warning('Saved fingerprint: %s', bin_to_hex(resume_id)) diff --git a/borg/archiver.py b/borg/archiver.py index a4666a73e..e0b52bc83 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -19,7 +19,7 @@ import traceback from . import __version__ from .helpers import Error, location_validator, archivename_validator, format_time, format_file_size, \ parse_pattern, PathPrefixPattern, to_localtime, timestamp, \ - get_cache_dir, prune_within, prune_split, bin_to_hex, \ + get_cache_dir, prune_within, prune_split, bin_to_hex, safe_encode, \ Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \ dir_is_tagged, ChunkerParams, CompressionSpec, is_slow_msgpack, yes, sysinfo, \ log_multi, PatternMatcher, ItemFormatter @@ -739,7 +739,7 @@ class Archiver: else: write = sys.stdout.buffer.write for item in archive.iter_items(lambda item: matcher.match(item[b'path'])): - write(formatter.format_item(item).encode('utf-8', errors='surrogateescape')) + write(safe_encode(formatter.format_item(item))) else: for archive_info in manifest.list_archive_infos(sort_by='ts'): if args.prefix and not archive_info.name.startswith(args.prefix):