浏览代码

Merge pull request #8106 from ThomasWaldmann/more-errors-msgids-master

more specific errors / msgids (master)
TW 1 年之前
父节点
当前提交
f94cdee94a
共有 3 个文件被更改,包括 33 次插入3 次删除
  1. 4 0
      docs/internals/frontends.rst
  2. 12 1
      src/borg/remote.py
  3. 17 2
      src/borg/repository.py

+ 4 - 0
docs/internals/frontends.rst

@@ -612,6 +612,8 @@ Errors
         There is already something at {}.
         There is already something at {}.
     Repository.StorageQuotaExceeded rc: 20 traceback: no
     Repository.StorageQuotaExceeded rc: 20 traceback: no
         The storage quota ({}) has been exceeded ({}). Try deleting some archives.
         The storage quota ({}) has been exceeded ({}). Try deleting some archives.
+    Repository.PathPermissionDenied rc: 21 traceback: no
+        Permission denied to {}.
 
 
     MandatoryFeatureUnsupported rc: 25 traceback: no
     MandatoryFeatureUnsupported rc: 25 traceback: no
         Unsupported repository feature(s) {}. A newer version of borg is required to access this repository.
         Unsupported repository feature(s) {}. A newer version of borg is required to access this repository.
@@ -697,6 +699,8 @@ Errors
     UnexpectedRPCDataFormatFromServer rc: 86 traceback: no
     UnexpectedRPCDataFormatFromServer rc: 86 traceback: no
         Got unexpected RPC data format from server:
         Got unexpected RPC data format from server:
         {}
         {}
+    ConnectionBrokenWithHint rc: 87 traceback: no
+        Connection to remote host is broken. {}
 
 
     IntegrityError rc: 90 traceback: yes
     IntegrityError rc: 90 traceback: yes
         Data integrity error: {}
         Data integrity error: {}

+ 12 - 1
src/borg/remote.py

@@ -112,6 +112,12 @@ class UnexpectedRPCDataFormatFromServer(Error):
         super().__init__(data)
         super().__init__(data)
 
 
 
 
+class ConnectionBrokenWithHint(Error):
+    """Connection to remote host is broken. {}"""
+
+    exit_mcode = 87
+
+
 # Protocol compatibility:
 # Protocol compatibility:
 # In general the server is responsible for rejecting too old clients and the client it responsible for rejecting
 # In general the server is responsible for rejecting too old clients and the client it responsible for rejecting
 # too old servers. This ensures that the knowledge what is compatible is always held by the newer component.
 # too old servers. This ensures that the knowledge what is compatible is always held by the newer component.
@@ -428,7 +434,10 @@ class SleepingBandwidthLimiter:
                 self.ratelimit_last = time.monotonic()
                 self.ratelimit_last = time.monotonic()
             if len(to_send) > self.ratelimit_quota:
             if len(to_send) > self.ratelimit_quota:
                 to_send = to_send[: self.ratelimit_quota]
                 to_send = to_send[: self.ratelimit_quota]
-        written = os.write(fd, to_send)
+        try:
+            written = os.write(fd, to_send)
+        except BrokenPipeError:
+            raise ConnectionBrokenWithHint("Broken Pipe") from None
         if self.ratelimit:
         if self.ratelimit:
             self.ratelimit_quota -= written
             self.ratelimit_quota -= written
         return written
         return written
@@ -780,6 +789,8 @@ class RemoteRepository:
                 raise IntegrityError(args[0])
                 raise IntegrityError(args[0])
             elif error == "PathNotAllowed":
             elif error == "PathNotAllowed":
                 raise PathNotAllowed(args[0])
                 raise PathNotAllowed(args[0])
+            elif error == "PathPermissionDenied":
+                raise Repository.PathPermissionDenied(args[0])
             elif error == "ParentPathDoesNotExist":
             elif error == "ParentPathDoesNotExist":
                 raise Repository.ParentPathDoesNotExist(args[0])
                 raise Repository.ParentPathDoesNotExist(args[0])
             elif error == "ObjectNotFound":
             elif error == "ObjectNotFound":

+ 17 - 2
src/borg/repository.py

@@ -188,6 +188,11 @@ class Repository:
 
 
         exit_mcode = 20
         exit_mcode = 20
 
 
+    class PathPermissionDenied(Error):
+        """Permission denied to {}."""
+
+        exit_mcode = 21
+
     def __init__(
     def __init__(
         self,
         self,
         path,
         path,
@@ -299,13 +304,23 @@ class Repository:
             st = os.stat(path)
             st = os.stat(path)
         except FileNotFoundError:
         except FileNotFoundError:
             pass  # nothing there!
             pass  # nothing there!
+        except PermissionError:
+            raise self.PathPermissionDenied(path) from None
         else:
         else:
             # there is something already there!
             # there is something already there!
             if self.is_repository(path):
             if self.is_repository(path):
                 raise self.AlreadyExists(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)
                 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:
         while True:
             # Check all parent directories for Borg's repository README
             # Check all parent directories for Borg's repository README