Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/borg/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,14 +1302,16 @@ 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
self.add_item = add_item
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)
Expand Down Expand Up @@ -1482,7 +1484,14 @@ def process_file(self, *, path, parent_fd, name, st, cache, flags=flags_normal,
# 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:
Expand Down
14 changes: 13 additions & 1 deletion src/borg/archiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,8 @@ def create_inner(archive, cache, fso):
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)
Expand Down Expand Up @@ -3563,6 +3564,14 @@ def define_borg_mount(parser):
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.
Expand Down Expand Up @@ -3776,6 +3785,9 @@ def define_borg_mount(parser):
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.')
Expand Down
Loading