1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2025-01-30 11:11:28 +00:00

symlink processing for --read-special mode

processing depends on symlink target:
- if target is a special file: process the symlink as a regular file
- if target is anything else: process the symlink as symlink

refactor code a little to avoid duplication.
This commit is contained in:
Thomas Waldmann 2016-07-02 21:04:51 +02:00
parent 5476ece81e
commit 00a5470125
2 changed files with 19 additions and 7 deletions

View file

@ -46,6 +46,11 @@
flags_noatime = flags_normal | getattr(os, 'O_NOATIME', 0)
def is_special(mode):
# file types that get special treatment in --read-special mode
return stat.S_ISBLK(mode) or stat.S_ISCHR(mode) or stat.S_ISFIFO(mode)
class BackupOSError(Exception):
"""
Wrapper for OSError raised while accessing backup files.
@ -589,8 +594,8 @@ def process_file(self, path, st, cache, ignore_inode=False):
return status
else:
self.hard_links[st.st_ino, st.st_dev] = safe_path
is_regular_file = stat.S_ISREG(st.st_mode)
if is_regular_file:
is_special_file = is_special(st.st_mode)
if not is_special_file:
path_hash = self.key.id_hash(os.path.join(self.cwd, path).encode('utf-8', 'surrogateescape'))
ids = cache.file_known_and_unchanged(path_hash, st, ignore_inode)
else:
@ -623,16 +628,16 @@ def process_file(self, path, st, cache, ignore_inode=False):
chunks.append(cache.add_chunk(self.key.id_hash(chunk), chunk, self.stats))
if self.show_progress:
self.stats.show_progress(item=item, dt=0.2)
if is_regular_file:
if not is_special_file:
# we must not memorize special files, because the contents of e.g. a
# block or char device will change without its mtime/size/inode changing.
cache.memorize_file(path_hash, st, [c[0] for c in chunks])
status = status or 'M' # regular file, modified (if not 'A' already)
item[b'chunks'] = chunks
item.update(self.stat_attrs(st, path))
if not is_regular_file:
if is_special_file:
# we processed a special file like a regular file. reflect that in mode,
# so it can be extracted / accessed in fuse mount like a regular file:
# so it can be extracted / accessed in FUSE mount like a regular file:
item[b'mode'] = stat.S_IFREG | stat.S_IMODE(item[b'mode'])
self.stats.nfiles += 1
self.add_item(item)

View file

@ -29,7 +29,7 @@
from .repository import Repository
from .cache import Cache
from .key import key_creator, RepoKey, PassphraseKey
from .archive import backup_io, BackupOSError, Archive, ArchiveChecker, CHUNKER_PARAMS
from .archive import backup_io, BackupOSError, Archive, ArchiveChecker, CHUNKER_PARAMS, is_special
from .remote import RepositoryServer, RemoteRepository, cache_if_remote
has_lchflags = hasattr(os, 'lchflags')
@ -301,7 +301,14 @@ def _process(self, archive, cache, matcher, exclude_caches, exclude_if_present,
read_special=read_special, dry_run=dry_run)
elif stat.S_ISLNK(st.st_mode):
if not dry_run:
status = archive.process_symlink(path, st)
if not read_special:
status = archive.process_symlink(path, st)
else:
st_target = os.stat(path)
if is_special(st_target.st_mode):
status = archive.process_file(path, st_target, cache)
else:
status = archive.process_symlink(path, st)
elif stat.S_ISFIFO(st.st_mode):
if not dry_run:
if not read_special: