|
4 | 4 | from ..archive import ArchiveChecker |
5 | 5 | from ..constants import * # NOQA |
6 | 6 | from ..crypto.key import key_factory |
7 | | -from ..helpers import set_ec, EXIT_WARNING, CancelledByUser, CommandError, Error |
| 7 | +from ..helpers import set_ec, EXIT_WARNING, CancelledByUser, CommandError, Error, IntegrityError |
8 | 8 | from ..helpers import relative_time_marker_validator, yes, ArchiveFormatter, sig_int |
9 | 9 | from ..helpers.argparsing import ArgumentParser |
10 | 10 | from ..helpers.time import archive_ts_now, calculate_relative_offset |
11 | 11 | from ..repoobj import RepoObj, object_validator |
| 12 | +from ..repository import Repository, DEFAULTS_NAME |
12 | 13 |
|
13 | 14 | from ..logger import create_logger |
14 | 15 |
|
15 | 16 | logger = create_logger() |
16 | 17 |
|
17 | 18 |
|
| 19 | +def check_repository_defaults(repository, *, repair): |
| 20 | + """Verify the repository defaults object (config/defaults, see Repository.load_defaults). |
| 21 | +
|
| 22 | + "borg repo-create" always writes it, so a missing object was removed (or lost), like one that fails |
| 23 | + the authentication of the key's envelope or does not deserialize. Such an object is an error: the |
| 24 | + commands using the defaults refuse to run. With repair, empty defaults are stored instead, so the |
| 25 | + repository can be used again (with the built-in defaults). |
| 26 | +
|
| 27 | + Returns False if a problem was found and not repaired. |
| 28 | + """ |
| 29 | + try: |
| 30 | + repository.load_defaults() |
| 31 | + except Repository.DefaultsMissing: |
| 32 | + problem = "is missing" |
| 33 | + except IntegrityError: |
| 34 | + problem = "fails the authentication" |
| 35 | + except Repository.InvalidRepositoryConfig: |
| 36 | + problem = "is malformed" |
| 37 | + else: |
| 38 | + return True |
| 39 | + if not repair: |
| 40 | + logger.error( |
| 41 | + f'Repository defaults object {DEFAULTS_NAME} {problem}. Run "borg check --repair" to store empty defaults.' |
| 42 | + ) |
| 43 | + return False |
| 44 | + logger.warning( |
| 45 | + f"Repository defaults object {DEFAULTS_NAME} {problem}, storing empty defaults. " |
| 46 | + "The defaults set by borg repo-create are lost, the built-in defaults are used now." |
| 47 | + ) |
| 48 | + repository.save_defaults({}) |
| 49 | + return True |
| 50 | + |
| 51 | + |
18 | 52 | class CheckMixIn: |
19 | 53 | @with_repository(exclusive=True, manifest=False) |
20 | 54 | def do_check(self, args, repository): |
@@ -91,6 +125,8 @@ def do_check(self, args, repository): |
91 | 125 | set_ec(EXIT_WARNING) |
92 | 126 | if sig_int: # repository check interrupted; skip the archive check |
93 | 127 | raise Error("Got Ctrl-C / SIGINT.") |
| 128 | + if not check_repository_defaults(repository, repair=args.repair): |
| 129 | + set_ec(EXIT_WARNING) |
94 | 130 | if not args.repo_only and not archive_checker.check( |
95 | 131 | repository, |
96 | 132 | verify_data=args.verify_data, |
@@ -128,7 +164,9 @@ def build_parser_check(self, subparsers, common_parser, mid_common_parser): |
128 | 164 | not a MAC, this step does not detect tampering of the packs. The index objects |
129 | 165 | are also authenticated with the key when they are loaded for that cross-check. |
130 | 166 | A corrupt index ends the check after this step, as the archives check needs it, |
131 | | - unless ``--repair`` is given (see below). Running the repository check can |
| 167 | + unless ``--repair`` is given (see below). This step also verifies the repository |
| 168 | + defaults object (see ``borg repo-create``): it must be present and authenticate |
| 169 | + with the key. Running the repository check can |
132 | 170 | be split into multiple partial checks using ``--max-duration``. |
133 | 171 | For ssh:// repositories, the server computes the hashes, so the pack contents do |
134 | 172 | not have to travel over the network. For other remote backends, borg usually has |
@@ -269,6 +307,8 @@ def build_parser_check(self, subparsers, common_parser, mid_common_parser): |
269 | 307 | index entries of the chunks stored in missing packs (packs the index references, |
270 | 308 | but that are absent from the repository). Only a full ``borg check --repair`` |
271 | 309 | repairs the archives that reference these chunks, ``--repository-only`` does not. |
| 310 | + A missing or corrupt repository defaults object is replaced by empty defaults, so |
| 311 | + the repository can be used again; the commands then use the built-in defaults. |
272 | 312 |
|
273 | 313 | 2. When checking the consistency and correctness of archives, repair mode might |
274 | 314 | remove whole archives from the manifest if their archive metadata chunk is |
|
0 commit comments