Merge pull request #8959 from ThomasWaldmann/files-changed-option

create --files-changed=MODE option
This commit is contained in:
TW 2025-08-03 15:49:23 +02:00 committed by GitHub
commit ebfe007cba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 3 deletions

View file

@ -1302,7 +1302,8 @@ class FilesystemObjectProcessors:
def __init__(self, *, metadata_collector, cache, key,
add_item, process_file_chunks,
chunker_params, show_progress, sparse,
log_json, iec, file_status_printer=None):
log_json, iec, file_status_printer=None,
files_changed='ctime'):
self.metadata_collector = metadata_collector
self.cache = cache
self.key = key
@ -1310,6 +1311,7 @@ class FilesystemObjectProcessors:
self.process_file_chunks = process_file_chunks
self.show_progress = show_progress
self.print_file_status = file_status_printer or (lambda *args: None)
self.files_changed = files_changed
self.hard_links = {}
self.stats = Statistics(output_json=log_json, iec=iec) # threading: done by cache (including progress)
@ -1482,7 +1484,14 @@ class FilesystemObjectProcessors:
# special files:
# - fifos change naturally, because they are fed from the other side. no problem.
# - blk/chr devices don't change ctime anyway.
changed_while_backup = not is_special_file and st.st_ctime_ns != st2.st_ctime_ns
if self.files_changed == 'disabled' or is_special_file:
changed_while_backup = False
elif self.files_changed == 'ctime':
changed_while_backup = st.st_ctime_ns != st2.st_ctime_ns
elif self.files_changed == 'mtime':
changed_while_backup = st.st_mtime_ns != st2.st_mtime_ns
else:
raise ValueError('invalid files_changed value: %r' % self.files_changed)
if changed_while_backup:
status = 'C' # regular file changed while we backed it up, might be inconsistent/corrupt!
if not is_special_file and not changed_while_backup:

View file

@ -692,7 +692,8 @@ class Archiver:
fso = FilesystemObjectProcessors(metadata_collector=metadata_collector, cache=cache, key=key,
process_file_chunks=cp.process_file_chunks, add_item=archive.add_item,
chunker_params=args.chunker_params, show_progress=args.progress, sparse=args.sparse,
log_json=args.log_json, iec=args.iec, file_status_printer=self.print_file_status)
log_json=args.log_json, iec=args.iec, file_status_printer=self.print_file_status,
files_changed=args.files_changed)
create_inner(archive, cache, fso)
else:
create_inner(None, None, None)
@ -3563,6 +3564,14 @@ class Archiver:
it had before a content change happened. This can be used maliciously as well as
well-meant, but in both cases mtime based cache modes can be problematic.
The ``--files-changed`` option controls how Borg detects if a file has changed during backup:
- ctime (default): Use ctime to detect changes. This is the safest option.
- mtime: Use mtime to detect changes.
- disabled: Disable the "file has changed while we backed it up" detection completely.
This is not recommended unless you know what you're doing, as it could lead to
inconsistent backups if files change during the backup process.
The mount points of filesystems or filesystem snapshots should be the same for every
creation of a new archive to ensure fast operation. This is because the file cache that
is used to determine changed files quickly uses absolute filenames.
@ -3776,6 +3785,9 @@ class Archiver:
fs_group.add_argument('--files-cache', metavar='MODE', dest='files_cache_mode', action=Highlander,
type=FilesCacheMode, default=FILES_CACHE_MODE_UI_DEFAULT,
help='operate files cache in MODE. default: %s' % FILES_CACHE_MODE_UI_DEFAULT)
fs_group.add_argument('--files-changed', metavar='MODE', dest='files_changed', action=Highlander,
choices=['ctime', 'mtime', 'disabled'], default='ctime',
help='specify how to detect if a file has changed during backup (ctime, mtime, disabled). default: ctime')
fs_group.add_argument('--read-special', dest='read_special', action='store_true',
help='open and read block and char device files as well as FIFOs as if they were '
'regular files. Also follows symlinks pointing to these kinds of files.')