From 23cc6796177568f1ba2b3d56d823e4b0d7ed8043 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 26 Mar 2017 14:25:33 +0200 Subject: [PATCH] no hardlinking for directories and symlinks - nlink > 1 for dirs does not mean hardlinking (at least not everywhere, wondering how apple does it) - we can not archive hardlinked symlinks due to item.source dual-use, see issue #2343. likely nobody uses this anyway. --- src/borg/archive.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index d602faf45..8d1c8b954 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -835,11 +835,11 @@ Utilization of max. archive size: {csize_max:.0%} return attrs @contextmanager - def create_helper(self, path, st, status=None): + def create_helper(self, path, st, status=None, hardlinkable=True): safe_path = make_path_safe(path) item = Item(path=safe_path) hardlink_master = False - hardlinked = st.st_nlink > 1 + hardlinked = hardlinkable and st.st_nlink > 1 if hardlinked: source = self.hard_links.get((st.st_ino, st.st_dev)) if source is not None: @@ -855,7 +855,7 @@ Utilization of max. archive size: {csize_max:.0%} self.hard_links[(st.st_ino, st.st_dev)] = safe_path def process_dir(self, path, st): - with self.create_helper(path, st, 'd') as (item, status, hardlinked, hardlink_master): # directory + with self.create_helper(path, st, 'd', hardlinkable=False) as (item, status, hardlinked, hardlink_master): item.update(self.stat_attrs(st, path)) return status @@ -871,12 +871,14 @@ Utilization of max. archive size: {csize_max:.0%} return status def process_symlink(self, path, st): - with self.create_helper(path, st, 's') as (item, status, hardlinked, hardlink_master): # symlink + # note: using hardlinkable=False because we can not support hardlinked symlinks, + # due to the dual-use of item.source, see issue #2343: + with self.create_helper(path, st, 's', hardlinkable=False) as (item, status, hardlinked, hardlink_master): with backup_io('readlink'): source = os.readlink(path) - item.source = source # XXX this overwrites hardlink slave's usage of item.source - if hardlinked: - logger.warning('hardlinked symlinks will be extracted as non-hardlinked symlinks!') + item.source = source + if st.st_nlink > 1: + logger.warning('hardlinked symlinks will be archived as non-hardlinked symlinks!') item.update(self.stat_attrs(st, path)) return status