Преглед на файлове

Merge pull request #2094 from enkore/issue/2092

Fix invalid hard links
TW преди 8 години
родител
ревизия
cf0192cdd3
променени са 2 файла, в които са добавени 12 реда и са изтрити 5 реда
  1. 3 2
      borg/archive.py
  2. 9 3
      borg/fuse.py

+ 3 - 2
borg/archive.py

@@ -660,8 +660,6 @@ Number of files: {0.stats.nfiles}'''.format(
                 self.add_item(item)
                 status = 'h'  # regular file, hardlink (to already seen inodes)
                 return status
-            else:
-                self.hard_links[st.st_ino, st.st_dev] = safe_path
         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'))
@@ -709,6 +707,9 @@ Number of files: {0.stats.nfiles}'''.format(
             item[b'mode'] = stat.S_IFREG | stat.S_IMODE(item[b'mode'])
         self.stats.nfiles += 1
         self.add_item(item)
+        if st.st_nlink > 1 and source is None:
+            # Add the hard link reference *after* the file has been added to the archive.
+            self.hard_links[st.st_ino, st.st_dev] = safe_path
         return status
 
     @staticmethod

+ 9 - 3
borg/fuse.py

@@ -128,15 +128,21 @@ class FuseOperations(llfuse.Operations):
                 else:
                     self.items[inode] = item
                     continue
-                segments = prefix + os.fsencode(os.path.normpath(item[b'path'])).split(b'/')
-                del item[b'path']
+                path = item.pop(b'path')
+                segments = prefix + os.fsencode(os.path.normpath(path)).split(b'/')
                 num_segments = len(segments)
                 parent = 1
                 for i, segment in enumerate(segments, 1):
                     # Leaf segment?
                     if i == num_segments:
                         if b'source' in item and stat.S_ISREG(item[b'mode']):
-                            inode = self._find_inode(item[b'source'], prefix)
+                            try:
+                                inode = self._find_inode(item[b'source'], prefix)
+                            except KeyError:
+                                file = path.decode(errors='surrogateescape')
+                                source = item[b'source'].decode(errors='surrogateescape')
+                                logger.warning('Skipping broken hard link: %s -> %s', file, source)
+                                continue
                             item = self.cache.get(inode)
                             item[b'nlink'] = item.get(b'nlink', 1) + 1
                             self.items[inode] = item