fix crash on unaccessible input files
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Wed, 4 Jul 2018 08:05:57 +0000 (10:05 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Sat, 1 Feb 2020 14:14:06 +0000 (15:14 +0100)
Fix i2n bug #6440: race condition between access(3) and open(2).

This flaw exists in both the full and diff backup code. Deltatar
must not assume that the verdict returned by access() will hold
true later. Emit a warning if we receive ENOENT on later calls to
open(), but continue regardless.

deltatar/deltatar.py

index e1b78ad..e66c687 100644 (file)
@@ -733,7 +733,15 @@ class DeltaTar(object):
             statd['volume'] = self.vol_no
 
             # backup file
-            tarobj.add(path, arcname = statd['path'], recursive=False)
+
+            try: # backup file
+                tarobj.add(path, arcname = statd['path'], recursive=False)
+            except FileNotFoundError as exn:
+                # file vanished since the call to access(3) above
+                self.logger.warning ("object [%s] no longer available in "
+                                     "file system (error: %s); skipping"
+                                     % (path, str (exn)))
+                continue # prevent indexing
 
             # retrieve file offset
             statd['offset'] = tarobj.get_last_member_offset()
@@ -935,11 +943,17 @@ class DeltaTar(object):
 
                 self.logger.debug("[STORE] %s" % dpath['path'])
 
-                # backup file
-                tarobj.add(dpath['path'], arcname=stat['path'], recursive=False)
+                try: # backup file
+                    tarobj.add(dpath['path'], arcname=stat['path'], recursive=False)
+                    # retrieve file offset
+                    stat['offset'] = tarobj.get_last_member_offset()
+                except FileNotFoundError as exn:
+                    # file vanished since the call to access(3) above
+                    self.logger.warning ("object [%s] no longer available in "
+                                         "file system (error: %s); skipping"
+                                         % (dpath ["path"], str (exn)))
+                    stat = None # prevent indexing
 
-                # retrieve file offset
-                stat['offset'] = tarobj.get_last_member_offset()
             elif action == 'delete':
                 path = self.unprefixed(ipath['path'])
                 stat = {