Răsfoiți Sursa

check_can_create_repository: deal with PermissionErrors, see #7016

borg init calls this. If there is a PermissionError, it is
usually fs permission issue at path or its parent directory.

Don't give a traceback, but rather an error msg and a specific exit code.
Thomas Waldmann 1 an în urmă
părinte
comite
45f65f7c57
3 a modificat fișierele cu 20 adăugiri și 2 ștergeri
  1. 2 0
      docs/internals/frontends.rst
  2. 2 0
      src/borg/remote.py
  3. 16 2
      src/borg/repository.py

+ 2 - 0
docs/internals/frontends.rst

@@ -587,6 +587,8 @@ Errors
         There is already something at {}.
     Repository.StorageQuotaExceeded rc: 20 traceback: no
         The storage quota ({}) has been exceeded ({}). Try deleting some archives.
+    Repository.PathPermissionDenied rc: 21 traceback: no
+        Permission denied to {}.
 
     MandatoryFeatureUnsupported rc: 25 traceback: no
         Unsupported repository feature(s) {}. A newer version of borg is required to access this repository.

+ 2 - 0
src/borg/remote.py

@@ -772,6 +772,8 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+.
                     raise PathNotAllowed('(unknown)')
                 else:
                     raise PathNotAllowed(args[0].decode())
+            elif error == 'PathPermissionDenied':
+                raise Repository.PathPermissionDenied(args[0].decode())
             elif error == 'ParentPathDoesNotExist':
                 raise Repository.ParentPathDoesNotExist(args[0].decode())
             elif error == 'ObjectNotFound':

+ 16 - 2
src/borg/repository.py

@@ -168,6 +168,10 @@ class Repository:
         """The storage quota ({}) has been exceeded ({}). Try deleting some archives."""
         exit_mcode = 20
 
+    class PathPermissionDenied(Error):
+        """Permission denied to {}."""
+        exit_mcode = 21
+
     def __init__(self, path, create=False, exclusive=False, lock_wait=None, lock=True,
                  append_only=False, storage_quota=None, check_segment_magic=True,
                  make_parent_dirs=False):
@@ -261,13 +265,23 @@ class Repository:
             st = os.stat(path)
         except FileNotFoundError:
             pass  # nothing there!
+        except PermissionError:
+            raise self.PathPermissionDenied(path) from None
         else:
             # there is something already there!
             if self.is_repository(path):
                 raise self.AlreadyExists(path)
-            if not stat.S_ISDIR(st.st_mode) or os.listdir(path):
+            if not stat.S_ISDIR(st.st_mode):
                 raise self.PathAlreadyExists(path)
-            # an empty directory is acceptable for us.
+            try:
+                files = os.listdir(path)
+            except PermissionError:
+                raise self.PathPermissionDenied(path) from None
+            else:
+                if files:  # a dir, but not empty
+                    raise self.PathAlreadyExists(path)
+                else:  # an empty directory is acceptable for us.
+                    pass
 
         while True:
             # Check all parent directories for Borg's repository README