Browse Source

Merge pull request #5774 from ThomasWaldmann/backports1

Fixes BORG_CACHE_DIR crashing borg if empty, fixes #5216
TW 4 years ago
parent
commit
31f95162d4
1 changed files with 31 additions and 17 deletions
  1. 31 17
      src/borg/helpers.py

+ 31 - 17
src/borg/helpers.py

@@ -513,6 +513,26 @@ def prune_split(archives, pattern, n, skip=[]):
     return keep
 
 
+def ensure_dir(path, mode=stat.S_IRWXU, pretty_deadly=True):
+    """
+    Ensures that the dir exists with the right permissions.
+    1) Make sure the directory exists in a race-free operation
+    2) If mode is not None and the directory has been created, give the right
+    permissions to the leaf directory
+    3) If pretty_deadly is True, catch exceptions, reraise them with a pretty
+    message.
+    Returns if the directory has been created and has the right permissions,
+    An exception otherwise. If a deadly exception happened it is reraised.
+    """
+    try:
+        os.makedirs(path, mode=mode, exist_ok=True)
+    except OSError as e:
+        if pretty_deadly:
+            raise Error(e.args[1])
+        else:
+            raise
+
+
 def get_base_dir():
     """Get home directory / base directory for borg:
 
@@ -535,9 +555,7 @@ def get_keys_dir():
     """Determine where to repository keys and cache"""
 
     keys_dir = os.environ.get('BORG_KEYS_DIR', os.path.join(get_config_dir(), 'keys'))
-    if not os.path.exists(keys_dir):
-        os.makedirs(keys_dir)
-        os.chmod(keys_dir, stat.S_IRWXU)
+    ensure_dir(keys_dir)
     return keys_dir
 
 
@@ -546,9 +564,7 @@ def get_security_dir(repository_id=None):
     security_dir = os.environ.get('BORG_SECURITY_DIR', os.path.join(get_config_dir(), 'security'))
     if repository_id:
         security_dir = os.path.join(security_dir, repository_id)
-    if not os.path.exists(security_dir):
-        os.makedirs(security_dir)
-        os.chmod(security_dir, stat.S_IRWXU)
+    ensure_dir(security_dir)
     return security_dir
 
 
@@ -562,16 +578,16 @@ def get_cache_dir():
     # Use BORG_CACHE_DIR if set, otherwise assemble final path from cache home path
     cache_dir = os.environ.get('BORG_CACHE_DIR', os.path.join(cache_home, 'borg'))
     # Create path if it doesn't exist yet
-    if not os.path.exists(cache_dir):
-        os.makedirs(cache_dir)
-        os.chmod(cache_dir, stat.S_IRWXU)
-        with open(os.path.join(cache_dir, CACHE_TAG_NAME), 'wb') as fd:
+    ensure_dir(cache_dir)
+    cache_fn = os.path.join(cache_dir, CACHE_TAG_NAME)
+    if not os.path.exists(cache_fn):
+        with open(cache_fn, 'wb') as fd:
             fd.write(CACHE_TAG_CONTENTS)
             fd.write(textwrap.dedent("""
-                # This file is a cache directory tag created by Borg.
-                # For information about cache directory tags, see:
-                #       http://www.bford.info/cachedir/spec.html
-                """).encode('ascii'))
+            # This file is a cache directory tag created by Borg.
+            # For information about cache directory tags, see:
+            #       http://www.bford.info/cachedir/spec.html
+            """).encode('ascii'))
     return cache_dir
 
 
@@ -585,9 +601,7 @@ def get_config_dir():
     # Use BORG_CONFIG_DIR if set, otherwise assemble final path from config home path
     config_dir = os.environ.get('BORG_CONFIG_DIR', os.path.join(config_home, 'borg'))
     # Create path if it doesn't exist yet
-    if not os.path.exists(config_dir):
-        os.makedirs(config_dir)
-        os.chmod(config_dir, stat.S_IRWXU)
+    ensure_dir(config_dir)
     return config_dir