dar-backup 0.7.2__py3-none-any.whl → 0.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dar_backup/Changelog.md CHANGED
@@ -1,6 +1,23 @@
1
1
  <!-- markdownlint-disable MD024 -->
2
2
  # dar-backup Changelog
3
3
 
4
+ ## v2-beta-0.8.1 - 2025-07-16
5
+
6
+ Github link: [v2-beta-0.8.1](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.8.1/v2)
7
+
8
+ ### Added
9
+
10
+ - FIX: runner now logs an error and fills more data into the returned CommandResult.
11
+
12
+ ## v2-beta-0.8.0 - 2025-06-13
13
+
14
+ Github link: [v2-beta-0.8.0](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.8.0/v2)
15
+
16
+ ### Added
17
+
18
+ - Modified clone dashboard generator to produce easier to read dashboard and be more robust.
19
+ - Dir_traversal sanitation: clean_log.py now only accepts files in configured log directory to `--file` option.
20
+
4
21
  ## v2-beta-0.7.2 - 2025-06-07
5
22
 
6
23
  Github link: [v2-beta-0.7.2](https://github.com/per2jensen/dar-backup/tree/v2-beta-0.7.2/v2)
@@ -16,7 +33,7 @@ Github link: [v2-beta-0.7.2](https://github.com/per2jensen/dar-backup/tree/v2-be
16
33
  - Enrolling into [Snyk code checker](https://snyk.io/code-checker/) and learning how to work with it.
17
34
 
18
35
  - Snyk helped pointing out vulnerable versions of some packages used.
19
- - Input sanitization started, there is room for improvement.
36
+ - Input sanitation started, there is room for improvement.
20
37
 
21
38
  ## v2-beta-0.7.1 - 2025-05-22
22
39
 
dar_backup/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![PyPI version](https://img.shields.io/pypi/v/dar-backup.svg)](https://pypi.org/project/dar-backup/)
10
10
  [![PyPI downloads](https://img.shields.io/badge/dynamic/json?color=blue&label=PyPI%20downloads&query=total&url=https%3A%2F%2Fraw.githubusercontent.com%2Fper2jensen%2Fdar-backup%2Fmain%2Fdownloads.json)](https://pypi.org/project/dar-backup/)
11
11
  [![# clones](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/per2jensen/dar-backup/main/v2/doc/badges/badge_clones.json)](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
12
- [![Milestone](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/per2jensen/dar-backup/main/v2/doc/badges/milestone_badge.json)](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
12
+ [![Milestone](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/per2jensen/dar-backup/main/v2/doc/badges/milestone_badge.json)](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png) <sub>🎯 Stats powered by [ClonePulse](https://github.com/per2jensen/clonepulse)</sub>
13
13
 
14
14
  The wonderful 'dar' [Disk Archiver](https://github.com/Edrusb/DAR) is used for
15
15
  the heavy lifting, together with the [parchive](https://github.com/Parchive/par2cmdline) suite in these scripts.
dar_backup/__about__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.7.2"
1
+ __version__ = "0.8.1"
2
2
 
3
3
  __license__ = '''Licensed under GNU GENERAL PUBLIC LICENSE v3, see the supplied file "LICENSE" for details.
4
4
  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
dar_backup/clean_log.py CHANGED
@@ -138,6 +138,18 @@ def main():
138
138
 
139
139
  for file_path in args.file:
140
140
 
141
+ if ".." in os.path.normpath(file_path).split(os.sep):
142
+ print(f"Error: Path traversal is not allowed: '{file_path}'")
143
+ sys.exit(1)
144
+
145
+ logfile_dir = os.path.dirname(os.path.realpath(config_settings.logfile_location))
146
+ resolved_path = os.path.realpath(file_path)
147
+
148
+ if not resolved_path.startswith(logfile_dir + os.sep):
149
+ print(f"Error: File is outside allowed directory: '{file_path}'")
150
+ sys.exit(1)
151
+
152
+ # Validate the file path type and existence
141
153
  if not isinstance(file_path, (str, bytes, os.PathLike)):
142
154
  print(f"Error: Invalid file path type: {file_path}")
143
155
  sys.exit(1)
@@ -2,6 +2,7 @@
2
2
 
3
3
  import subprocess
4
4
  import logging
5
+ import traceback
5
6
  import threading
6
7
  import os
7
8
  import sys
@@ -12,14 +13,24 @@ from dar_backup.util import get_logger
12
13
 
13
14
 
14
15
  class CommandResult:
15
- def __init__(self, returncode: int, stdout: str, stderr: str):
16
+ def __init__(self, returncode: int, stdout: str, stderr: str, stack: str = None):
16
17
  self.returncode = returncode
17
18
  self.stdout = stdout
18
19
  self.stderr = stderr
20
+ self.stack = stack
19
21
 
20
22
  def __repr__(self):
21
- return f"<CommandResult returncode={self.returncode}>"
22
-
23
+ return f"<CommandResult returncode={self.returncode}\nstdout={self.stdout}\nstderr={self.stderr}\nstack={self.stack}>"
24
+
25
+
26
+ def __str__(self):
27
+ return (
28
+ f"CommandResult:\n"
29
+ f" Return code: {self.returncode}\n"
30
+ f" STDOUT:\n{self.stdout}\n"
31
+ f" STDERR:\n{self.stderr}\n"
32
+ f" Stacktrace:\n{self.stack if self.stack else '<none>'}"
33
+ )
23
34
 
24
35
  class CommandRunner:
25
36
  def __init__(
@@ -74,22 +85,29 @@ class CommandRunner:
74
85
  ) -> CommandResult:
75
86
  timeout = timeout or self.default_timeout
76
87
 
77
- #log the command to be executed
78
88
  command = f"Executing command: {' '.join(cmd)} (timeout={timeout}s)"
79
- self.command_logger.info(command) # log to command logger
80
- self.logger.debug(command) # log to main logger if "--log-level debug"
81
-
82
- process = subprocess.Popen(
83
- cmd,
84
- stdout=subprocess.PIPE if capture_output else None,
85
- stderr=subprocess.PIPE if capture_output else None,
86
- text=False,
87
- bufsize=-1
88
- )
89
+ self.command_logger.info(command)
90
+ self.logger.debug(command)
89
91
 
90
92
  stdout_lines = []
91
93
  stderr_lines = []
92
94
 
95
+ try:
96
+ process = subprocess.Popen(
97
+ cmd,
98
+ stdout=subprocess.PIPE if capture_output else None,
99
+ stderr=subprocess.PIPE if capture_output else None,
100
+ text=False,
101
+ bufsize=-1
102
+ )
103
+ except Exception as e:
104
+ stack = traceback.format_exc()
105
+ return CommandResult(
106
+ returncode=-1,
107
+ stdout='',
108
+ stderr=str(e),
109
+ stack=stack
110
+ )
93
111
 
94
112
  def stream_output(stream, lines, level):
95
113
  try:
@@ -123,11 +141,27 @@ class CommandRunner:
123
141
  process.kill()
124
142
  self.logger.error(f"Command timed out: {' '.join(cmd)}")
125
143
  return CommandResult(-1, ''.join(stdout_lines), ''.join(stderr_lines))
144
+ except Exception as e:
145
+ stack = traceback.format_exc()
146
+ self.logger.error(f"Command execution failed: {' '.join(cmd)} with error: {e}")
147
+ return CommandResult(-1, ''.join(stdout_lines), ''.join(stderr_lines), stack)
126
148
 
127
149
  for t in threads:
128
150
  t.join()
129
151
 
152
+
130
153
  if check and process.returncode != 0:
131
154
  self.logger.error(f"Command failed with exit code {process.returncode}")
155
+ return CommandResult(
156
+ process.returncode,
157
+ ''.join(stdout_lines),
158
+ ''.join(stderr_lines),
159
+ stack=traceback.format_stack()
160
+ )
161
+
162
+ return CommandResult(
163
+ process.returncode,
164
+ ''.join(stdout_lines),
165
+ ''.join(stderr_lines),
166
+ )
132
167
 
133
- return CommandResult(process.returncode, ''.join(stdout_lines), ''.join(stderr_lines))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dar-backup
3
- Version: 0.7.2
3
+ Version: 0.8.1
4
4
  Summary: A script to do full, differential and incremental backups using dar. Some files are restored from the backups during verification, after which par2 redundancy files are created. The script also has a cleanup feature to remove old backups and par2 files.
5
5
  Project-URL: GPG Public Key, https://keys.openpgp.org/search?q=dar-backup@pm.me
6
6
  Project-URL: Homepage, https://github.com/per2jensen/dar-backup/tree/main/v2
@@ -699,6 +699,8 @@ Requires-Dist: black>=25.1.0; extra == 'dev'
699
699
  Requires-Dist: coverage>=7.8.2; extra == 'dev'
700
700
  Requires-Dist: h11>=0.16.0; extra == 'dev'
701
701
  Requires-Dist: httpcore>=0.17.3; extra == 'dev'
702
+ Requires-Dist: matplotlib>=3.10.3; extra == 'dev'
703
+ Requires-Dist: pandas>=2.3.0; extra == 'dev'
702
704
  Requires-Dist: psutil>=7.0.0; extra == 'dev'
703
705
  Requires-Dist: pytest; extra == 'dev'
704
706
  Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
@@ -725,7 +727,7 @@ Description-Content-Type: text/markdown
725
727
  [![PyPI version](https://img.shields.io/pypi/v/dar-backup.svg)](https://pypi.org/project/dar-backup/)
726
728
  [![PyPI downloads](https://img.shields.io/badge/dynamic/json?color=blue&label=PyPI%20downloads&query=total&url=https%3A%2F%2Fraw.githubusercontent.com%2Fper2jensen%2Fdar-backup%2Fmain%2Fdownloads.json)](https://pypi.org/project/dar-backup/)
727
729
  [![# clones](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/per2jensen/dar-backup/main/v2/doc/badges/badge_clones.json)](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
728
- [![Milestone](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/per2jensen/dar-backup/main/v2/doc/badges/milestone_badge.json)](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png)
730
+ [![Milestone](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/per2jensen/dar-backup/main/v2/doc/badges/milestone_badge.json)](https://github.com/per2jensen/dar-backup/blob/main/v2/doc/weekly_clones.png) <sub>🎯 Stats powered by [ClonePulse](https://github.com/per2jensen/clonepulse)</sub>
729
731
 
730
732
  The wonderful 'dar' [Disk Archiver](https://github.com/Edrusb/DAR) is used for
731
733
  the heavy lifting, together with the [parchive](https://github.com/Parchive/par2cmdline) suite in these scripts.
@@ -1,11 +1,11 @@
1
1
  dar_backup/.darrc,sha256=-aerqivZmOsW_XBCh9IfbYTUvw0GkzDSr3Vx4GcNB1g,2113
2
- dar_backup/Changelog.md,sha256=9zNIpgLQUpa3_QG172ZR-Bz7Uf5ngnhpW_GQw7GGJu4,11532
3
- dar_backup/README.md,sha256=HWrcpd_nhzhL2quLlxp7Xd0i05GxZvJMu5nSw8lJKLk,59901
4
- dar_backup/__about__.py,sha256=za-A4zLS5L2_gT8XDhJozoBlWjX9ihNSMrswofJc5dE,344
2
+ dar_backup/Changelog.md,sha256=T6w4NGFjBg2rgyTmgScKPFwdJx_M3XkEnU7aG3NQMyo,12094
3
+ dar_backup/README.md,sha256=S8wpgaqa2LzXXZiQEzoOV1qjrpf9m1baYmvzGYtgEcE,59990
4
+ dar_backup/__about__.py,sha256=SSWyynCpdSF2lIcROjGdr29Z-m523S9BbEc-ytO_L30,344
5
5
  dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- dar_backup/clean_log.py,sha256=JVrc3VArmKOxr3n5P3u_9hB4G6nsabkR3o7cRIAZ7FI,5493
6
+ dar_backup/clean_log.py,sha256=pmmyPmLWbm3_3sHwJt9V_xBwUF8v015iS17ypJAGAZ4,6023
7
7
  dar_backup/cleanup.py,sha256=_ggDcpMCB1MhXStvYussp_PdGfhIFtEutT5BNrNkMSY,13297
8
- dar_backup/command_runner.py,sha256=IUPYYBsaDFBp0q81Rt2xB9ucuK9eu5bXziRKXhI5YZM,4500
8
+ dar_backup/command_runner.py,sha256=_aaLk8j44tFNYBv9FJTpUaIFE_iIKEO1W1xDaiO5HJg,5599
9
9
  dar_backup/config_settings.py,sha256=2UAHvatrVO4ark6lCn2Q7qBvZN6DUMK2ftlNrKpzlWc,5792
10
10
  dar_backup/dar-backup.conf,sha256=46V2zdvjj_aThFY11wWlffjmoiChYmatdf5DXCsmmao,1208
11
11
  dar_backup/dar-backup.conf.j2,sha256=z3epGo6nB_Jh3liTOp93wJO_HKUsf7qghe9cdtFH7cY,2021
@@ -18,8 +18,8 @@ dar_backup/installer.py,sha256=xSXh77qquIZbUTSY3AbhERQbS7bnrPE__M_yqpszdhM,6883
18
18
  dar_backup/manager.py,sha256=d1zliFpSuWc8JhjKqLMC-xOhp5kSIcfeGkMZOVuZcM0,27143
19
19
  dar_backup/rich_progress.py,sha256=SfwFxebBl6jnDQMUQr4McknkW1yQWaJVo1Ju1OD3okA,3221
20
20
  dar_backup/util.py,sha256=iTOGsZyIdkvh9tIu7hD_IXi-9HO6GhVgqact5GGInEY,26063
21
- dar_backup-0.7.2.dist-info/METADATA,sha256=IRUzpVBrqUEvX1-glxHhwt-B288N3EfjYOAxoau-M4E,102497
22
- dar_backup-0.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
- dar_backup-0.7.2.dist-info/entry_points.txt,sha256=pOK9M8cHeAcGIatrYzkm_1O89kPk0enyYONALYjFBx4,286
24
- dar_backup-0.7.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
25
- dar_backup-0.7.2.dist-info/RECORD,,
21
+ dar_backup-0.8.1.dist-info/METADATA,sha256=UPCRBCwXlLLjGVGZC-BVqCZXOCYa82lccd8W16I2sCg,102681
22
+ dar_backup-0.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ dar_backup-0.8.1.dist-info/entry_points.txt,sha256=pOK9M8cHeAcGIatrYzkm_1O89kPk0enyYONALYjFBx4,286
24
+ dar_backup-0.8.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
25
+ dar_backup-0.8.1.dist-info/RECORD,,