Jelajahi Sumber

Require the runtime directory to be an absolute path.

Dan Helfman 6 bulan lalu
induk
melakukan
84f611ae4f
3 mengubah file dengan 67 tambahan dan 0 penghapusan
  1. 1 0
      NEWS
  2. 7 0
      borgmatic/config/paths.py
  3. 59 0
      tests/unit/config/test_paths.py

+ 1 - 0
NEWS

@@ -6,6 +6,7 @@
  * Deprecate the "store_config_files" option at the global scope and move it under the "bootstrap"
    hook. See the documentation for more information:
    https://torsion.org/borgmatic/docs/how-to/extract-a-backup/#extract-the-configuration-files-used-to-create-an-archive
+ * Require the runtime directory to be an absolute path.
  * Add a "--deleted" flag to the "repo-list" action for listing deleted archives that haven't
    yet been compacted (Borg 2 only).
 

+ 7 - 0
borgmatic/config/paths.py

@@ -96,9 +96,16 @@ class Runtime_directory:
         )
 
         if runtime_directory:
+            if not runtime_directory.startswith(os.path.sep):
+                raise ValueError('The runtime directory must be an absolute path')
+
             self.temporary_directory = None
         else:
             base_directory = os.environ.get('TMPDIR') or os.environ.get('TEMP') or '/tmp'
+
+            if not base_directory.startswith(os.path.sep):
+                raise ValueError('The runtime directory must be an absolute path')
+
             os.makedirs(base_directory, mode=0o700, exist_ok=True)
             self.temporary_directory = tempfile.TemporaryDirectory(
                 prefix=TEMPORARY_DIRECTORY_PREFIX,

+ 59 - 0
tests/unit/config/test_paths.py

@@ -63,6 +63,15 @@ def test_runtime_directory_uses_config_option_without_adding_duplicate_borgmatic
         assert borgmatic_runtime_directory == '/run/./borgmatic'
 
 
+def test_runtime_directory_with_relative_config_option_errors():
+    flexmock(module.os).should_receive('makedirs').never()
+    config = {'user_runtime_directory': 'run', 'borgmatic_source_directory': '/nope'}
+
+    with pytest.raises(ValueError):
+        with module.Runtime_directory(config, 'prefix') as borgmatic_runtime_directory:
+            pass
+
+
 def test_runtime_directory_falls_back_to_xdg_runtime_dir():
     flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
     flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(
@@ -85,6 +94,15 @@ def test_runtime_directory_falls_back_to_xdg_runtime_dir_without_adding_duplicat
         assert borgmatic_runtime_directory == '/run/./borgmatic'
 
 
+def test_runtime_directory_with_relative_xdg_runtime_dir_errors():
+    flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return('run')
+    flexmock(module.os).should_receive('makedirs').never()
+
+    with pytest.raises(ValueError):
+        with module.Runtime_directory({}, 'prefix') as borgmatic_runtime_directory:
+            pass
+
+
 def test_runtime_directory_falls_back_to_runtime_directory():
     flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
     flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
@@ -109,6 +127,18 @@ def test_runtime_directory_falls_back_to_runtime_directory_without_adding_duplic
         assert borgmatic_runtime_directory == '/run/./borgmatic'
 
 
+def test_runtime_directory_falls_back_to_runtime_directory():
+    flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('RUNTIME_DIRECTORY').and_return(
+        'run'
+    )
+    flexmock(module.os).should_receive('makedirs').never()
+
+    with pytest.raises(ValueError):
+        with module.Runtime_directory({}, 'prefix') as borgmatic_runtime_directory:
+            pass
+
+
 def test_runtime_directory_falls_back_to_tmpdir_and_adds_temporary_subdirectory_that_get_cleaned_up():
     flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
     flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
@@ -127,6 +157,20 @@ def test_runtime_directory_falls_back_to_tmpdir_and_adds_temporary_subdirectory_
         assert borgmatic_runtime_directory == '/run/borgmatic-1234/./borgmatic'
 
 
+def test_runtime_directory_with_relative_tmpdir_errors():
+    flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('RUNTIME_DIRECTORY').and_return(
+        None
+    )
+    flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return('run')
+    flexmock(module.tempfile).should_receive('TemporaryDirectory').never()
+    flexmock(module.os).should_receive('makedirs').never()
+
+    with pytest.raises(ValueError):
+        with module.Runtime_directory({}, 'prefix') as borgmatic_runtime_directory:
+            pass
+
+
 def test_runtime_directory_falls_back_to_temp_and_adds_temporary_subdirectory_that_get_cleaned_up():
     flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
     flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
@@ -146,6 +190,21 @@ def test_runtime_directory_falls_back_to_temp_and_adds_temporary_subdirectory_th
         assert borgmatic_runtime_directory == '/run/borgmatic-1234/./borgmatic'
 
 
+def test_runtime_directory_with_relative_temp_errors():
+    flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('RUNTIME_DIRECTORY').and_return(
+        None
+    )
+    flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return('run')
+    flexmock(module.tempfile).should_receive('TemporaryDirectory').never()
+    flexmock(module.os).should_receive('makedirs')
+
+    with pytest.raises(ValueError):
+        with module.Runtime_directory({}, 'prefix') as borgmatic_runtime_directory:
+            pass
+
+
 def test_runtime_directory_falls_back_to_hard_coded_tmp_path_and_adds_temporary_subdirectory_that_get_cleaned_up():
     flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
     flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)