From ab0b111af0843234143f9d2167200b1df032e4b1 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Tue, 16 Jan 2024 23:24:25 +0100 Subject: [PATCH] give clean error msg for invalid nonce file, see #7967 this is a fwd port from 1.4-maint. as we don't have nonce files any more in master, only the generally useful stuff has been ported. - add Error / ErrorWithTraceback exception classes to RPC layer. - add hex_to_bin helper --- src/borg/helpers/__init__.py | 2 +- src/borg/helpers/parseformat.py | 15 +++++++++++++-- src/borg/remote.py | 8 ++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/borg/helpers/__init__.py b/src/borg/helpers/__init__.py index 0f4f98e51..82364613d 100644 --- a/src/borg/helpers/__init__.py +++ b/src/borg/helpers/__init__.py @@ -25,7 +25,7 @@ from .fs import HardLinkManager from .misc import sysinfo, log_multi, consume from .misc import ChunkIteratorFileWrapper, open_item, chunkit, iter_separated, ErrorIgnoringTextIOWrapper -from .parseformat import bin_to_hex, safe_encode, safe_decode +from .parseformat import bin_to_hex, hex_to_bin, safe_encode, safe_decode from .parseformat import text_to_json, binary_to_json, remove_surrogates, join_cmd from .parseformat import eval_escapes, decode_dict, positive_int_validator, interval from .parseformat import PathSpec, SortBySpec, ChunkerParams, FilesCacheMode, partial_format, DatetimeWrapper diff --git a/src/borg/helpers/parseformat.py b/src/borg/helpers/parseformat.py index e5752d34a..c82769730 100644 --- a/src/borg/helpers/parseformat.py +++ b/src/borg/helpers/parseformat.py @@ -1,6 +1,7 @@ import abc import argparse import base64 +import binascii import hashlib import json import os @@ -10,7 +11,6 @@ import stat import uuid from typing import Dict, Set, Tuple, ClassVar, Any, TYPE_CHECKING, Literal -from binascii import hexlify from collections import Counter, OrderedDict from datetime import datetime, timezone from functools import partial @@ -33,7 +33,18 @@ def bin_to_hex(binary): - return hexlify(binary).decode("ascii") + return binascii.hexlify(binary).decode("ascii") + + +def hex_to_bin(hex, length=None): + try: + binary = binascii.unhexlify(hex) + binary_len = len(binary) + if length is not None and binary_len != length: + raise ValueError(f"Expected {length} bytes ({2 * length} hex digits), got {binary_len} bytes.") + except binascii.Error as e: + raise ValueError(str(e)) from None + return binary def safe_decode(s, coding="utf-8", errors="surrogateescape"): diff --git a/src/borg/remote.py b/src/borg/remote.py index 5d9cb1af9..0aa636220 100644 --- a/src/borg/remote.py +++ b/src/borg/remote.py @@ -21,7 +21,7 @@ from . import __version__ from .compress import Compressor from .constants import * # NOQA -from .helpers import Error, IntegrityError +from .helpers import Error, ErrorWithTraceback, IntegrityError from .helpers import bin_to_hex from .helpers import get_limited_unpacker from .helpers import replace_placeholders @@ -766,7 +766,11 @@ def handle_error(unpacked): error = unpacked["exception_class"] args = unpacked["exception_args"] - if error == "DoesNotExist": + if error == "Error": + raise Error(args[0]) + elif error == "ErrorWithTraceback": + raise ErrorWithTraceback(args[0]) + elif error == "DoesNotExist": raise Repository.DoesNotExist(self.location.processed) elif error == "AlreadyExists": raise Repository.AlreadyExists(self.location.processed)