hbkit 0.5.0__tar.gz → 0.5.2__tar.gz

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.
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.2
4
+
5
+ No change to how hbkit reads or restores archives.
6
+
7
+ - CI now restores the synthetic test archives on Windows too, with liblz4 built by vcpkg.
8
+ The README says what that does and doesn't prove.
9
+ - The project page links the new site guides: restoring without a NAS, damaged backups,
10
+ and Apple silicon Macs.
11
+ - PyPI metadata: the homepage is the site, Python 3.10 to 3.13 are listed, more keywords.
12
+
13
+ ## 0.5.1
14
+
15
+ ### Fixed
16
+
17
+ - The test suite no longer needs `/bin/bash`, so it runs in Nix and other build sandboxes.
18
+ The closed-pipe test now closes the pipe itself, before hbk writes anything.
19
+
3
20
  ## 0.5.0
4
21
 
5
22
  ### New
@@ -1,3 +1,37 @@
1
+ Metadata-Version: 2.5
2
+ Name: hbkit
3
+ Version: 0.5.2
4
+ Summary: Recover files from Synology Hyper Backup (.hbk) archives without Synology software
5
+ Project-URL: Homepage, https://yordilorenzo.github.io/hbkit/
6
+ Project-URL: Documentation, https://yordilorenzo.github.io/hbkit/restore-without-nas/
7
+ Project-URL: Source, https://github.com/YordiLorenzo/hbkit
8
+ Project-URL: Issues, https://github.com/YordiLorenzo/hbkit/issues
9
+ Project-URL: Format spec, https://github.com/YordiLorenzo/hbkit/blob/main/FORMAT.md
10
+ Author-email: YordiLorenzo <yordilorenzo@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: backup,data-recovery,dsm,extract,hbk,hyper-backup,hyper-backup-explorer,hyperbackup,nas,recovery,synology
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: End Users/Desktop
17
+ Classifier: Intended Audience :: System Administrators
18
+ Classifier: Operating System :: MacOS
19
+ Classifier: Operating System :: POSIX :: Linux
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: System :: Archiving :: Backup
26
+ Classifier: Topic :: System :: Recovery Tools
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: cryptography>=41
29
+ Requires-Dist: pynacl>=1.5
30
+ Requires-Dist: textual>=0.80
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
1
35
  <p align="center">
2
36
  <img src="https://raw.githubusercontent.com/YordiLorenzo/hbkit/main/docs/images/banner.png" alt="hbkit: your backup, without the NAS" width="100%">
3
37
  </p>
@@ -9,7 +43,7 @@
9
43
  Recover files from **Synology Hyper Backup (`.hbk`)** archives without any Synology software.
10
44
 
11
45
  Point it at a backup on a local disk, an external drive, or a network mount, browse it as
12
- a tree, and pull out what you want. Works headless on Linux and macOS, including Apple Silicon, where Synology's
46
+ a tree, and pull out what you want. Works headless on Linux and macOS, including Apple silicon, where Synology's
13
47
  own Hyper Backup Explorer is awkward or unavailable.
14
48
 
15
49
  Website: **[yordilorenzo.github.io/hbkit](https://yordilorenzo.github.io/hbkit/)**
@@ -23,6 +57,10 @@ hbk-tui /Volumes/Backup # browse and select interactively
23
57
  hbk /Volumes/Backup get "/Photos/*" ~/restore
24
58
  ```
25
59
 
60
+ ![hbk doctor, versions and get, run on a test archive](https://raw.githubusercontent.com/YordiLorenzo/hbkit/main/docs/images/demo.gif)
61
+
62
+ *Real output on a small test archive that hbkit's own tests build, not a backup from a NAS.*
63
+
26
64
  ### Other ways to install
27
65
 
28
66
  ```sh
@@ -38,6 +76,20 @@ missing library only shows up when you extract something. The Homebrew formula i
38
76
  for you. Otherwise: `brew install lz4`, `sudo apt install liblz4-1`, or
39
77
  `sudo pacman -S lz4`. Set `HBK_LZ4` if yours lives somewhere unusual.
40
78
 
79
+ ### Restore without a NAS
80
+
81
+ The step-by-step guide is on the site:
82
+ [Restore a Hyper Backup without a Synology NAS](https://yordilorenzo.github.io/hbkit/restore-without-nas/).
83
+ If Hyper Backup says the backup is corrupted, start with
84
+ [what you can still recover](https://yordilorenzo.github.io/hbkit/damaged-backup/).
85
+
86
+ hbkit never writes to the archive. If it is your only copy, copy the whole `.hbk` folder
87
+ to another disk first and run hbkit on the copy.
88
+
89
+ Got your files back? [Tell us in Discussions](https://github.com/YordiLorenzo/hbkit/discussions/categories/recovered-with-hbkit).
90
+ To hear about new versions, watch the repo's releases or follow
91
+ [Announcements](https://github.com/YordiLorenzo/hbkit/discussions/categories/announcements).
92
+
41
93
  ---
42
94
 
43
95
  ## Why
@@ -322,6 +374,9 @@ Read this before trusting it with the only copy of anything.
322
374
  archive (unencrypted, LZ4, single version, single pool) and a small encrypted one from
323
375
  the same DSM version, both verified byte-exact, plus a 7-version encrypted archive from
324
376
  Hyper Backup 4.2.2 reported in [#4](https://github.com/YordiLorenzo/hbkit/issues/4).
377
+ In [#6](https://github.com/YordiLorenzo/hbkit/issues/6), a user restored 465,000 files
378
+ (754 GB) from a backup on a NAS hit by C3RB3R ransomware: it had locked only small
379
+ files that hbkit doesn't read.
325
380
  Version selection was checked byte-exact on a small two-version encrypted Hyper Backup
326
381
  4.2.2 archive (each version's copy of a changed file, by number and by date), and on
327
382
  synthetic archives; the version list comes from `Config/version_info.db`, whose layout
@@ -333,8 +388,11 @@ Read this before trusting it with the only copy of anything.
333
388
  bytes, which is the one thing a recovery tool must never do.
334
389
  - **Whole-file dedup** (`off_virtual_file = -1`, files living in `Pool/file_pool`) is not
335
390
  decoded. One file in 501,278 in the reference archive.
336
- - **Windows is untested for extraction.** CI installs the package and checks that it
337
- imports, but no archive has been rebuilt on Windows. Linux and macOS are verified.
391
+ - **Synology C2 is not tested.** Use Hyper Backup Explorer for a backup kept in C2.
392
+ - **Windows: tested on synthetic archives only.** On every push, CI restores plain and
393
+ encrypted test archives byte-exact on Windows, with an `lz4.dll` built by
394
+ `vcpkg install lz4:x64-windows` and `HBK_LZ4` set to its full path. No archive from a
395
+ real NAS has been restored on Windows yet. Linux and macOS are verified on real archives.
338
396
 
339
397
  ## The format
340
398
 
@@ -355,6 +413,7 @@ offsets. Where the two disagreed, the empirical result won.
355
413
  ## Prior art
356
414
 
357
415
  - [TeamDman/teamy-hyper-backup-explorer](https://github.com/TeamDman/teamy-hyper-backup-explorer) — independent Rust implementation (MPL-2.0). Its constants agree with what we derived separately.
416
+ - [Callido Restore](https://github.com/Niels-van-Haren-Holding-B-V/callido-restore): a separate macOS app (MIT) that restores `.hbk` archives, started 2026-10-30. We have not reviewed its code.
358
417
  - [mistersandman/hyperbackup_decrypt](https://github.com/mistersandman/hyperbackup_decrypt) — 2016 Python 2 script, and the only public reference for the **encrypted** variant.
359
418
 
360
419
  ## Development
@@ -1,32 +1,3 @@
1
- Metadata-Version: 2.5
2
- Name: hbkit
3
- Version: 0.5.0
4
- Summary: Recover files from Synology Hyper Backup (.hbk) archives without Synology software
5
- Project-URL: Homepage, https://github.com/YordiLorenzo/hbkit
6
- Project-URL: Source, https://github.com/YordiLorenzo/hbkit
7
- Project-URL: Issues, https://github.com/YordiLorenzo/hbkit/issues
8
- Project-URL: Format spec, https://github.com/YordiLorenzo/hbkit/blob/main/FORMAT.md
9
- Author-email: YordiLorenzo <yordilorenzo@gmail.com>
10
- License-Expression: MIT
11
- License-File: LICENSE
12
- Keywords: backup,data-recovery,dsm,extract,hbk,hyper-backup,nas,recovery,synology
13
- Classifier: Development Status :: 4 - Beta
14
- Classifier: Environment :: Console
15
- Classifier: Intended Audience :: End Users/Desktop
16
- Classifier: Intended Audience :: System Administrators
17
- Classifier: Operating System :: MacOS
18
- Classifier: Operating System :: POSIX :: Linux
19
- Classifier: Programming Language :: Python :: 3
20
- Classifier: Topic :: System :: Archiving :: Backup
21
- Classifier: Topic :: System :: Recovery Tools
22
- Requires-Python: >=3.10
23
- Requires-Dist: cryptography>=41
24
- Requires-Dist: pynacl>=1.5
25
- Requires-Dist: textual>=0.80
26
- Provides-Extra: dev
27
- Requires-Dist: pytest>=7; extra == 'dev'
28
- Description-Content-Type: text/markdown
29
-
30
1
  <p align="center">
31
2
  <img src="https://raw.githubusercontent.com/YordiLorenzo/hbkit/main/docs/images/banner.png" alt="hbkit: your backup, without the NAS" width="100%">
32
3
  </p>
@@ -38,7 +9,7 @@ Description-Content-Type: text/markdown
38
9
  Recover files from **Synology Hyper Backup (`.hbk`)** archives without any Synology software.
39
10
 
40
11
  Point it at a backup on a local disk, an external drive, or a network mount, browse it as
41
- a tree, and pull out what you want. Works headless on Linux and macOS, including Apple Silicon, where Synology's
12
+ a tree, and pull out what you want. Works headless on Linux and macOS, including Apple silicon, where Synology's
42
13
  own Hyper Backup Explorer is awkward or unavailable.
43
14
 
44
15
  Website: **[yordilorenzo.github.io/hbkit](https://yordilorenzo.github.io/hbkit/)**
@@ -52,6 +23,10 @@ hbk-tui /Volumes/Backup # browse and select interactively
52
23
  hbk /Volumes/Backup get "/Photos/*" ~/restore
53
24
  ```
54
25
 
26
+ ![hbk doctor, versions and get, run on a test archive](https://raw.githubusercontent.com/YordiLorenzo/hbkit/main/docs/images/demo.gif)
27
+
28
+ *Real output on a small test archive that hbkit's own tests build, not a backup from a NAS.*
29
+
55
30
  ### Other ways to install
56
31
 
57
32
  ```sh
@@ -67,6 +42,20 @@ missing library only shows up when you extract something. The Homebrew formula i
67
42
  for you. Otherwise: `brew install lz4`, `sudo apt install liblz4-1`, or
68
43
  `sudo pacman -S lz4`. Set `HBK_LZ4` if yours lives somewhere unusual.
69
44
 
45
+ ### Restore without a NAS
46
+
47
+ The step-by-step guide is on the site:
48
+ [Restore a Hyper Backup without a Synology NAS](https://yordilorenzo.github.io/hbkit/restore-without-nas/).
49
+ If Hyper Backup says the backup is corrupted, start with
50
+ [what you can still recover](https://yordilorenzo.github.io/hbkit/damaged-backup/).
51
+
52
+ hbkit never writes to the archive. If it is your only copy, copy the whole `.hbk` folder
53
+ to another disk first and run hbkit on the copy.
54
+
55
+ Got your files back? [Tell us in Discussions](https://github.com/YordiLorenzo/hbkit/discussions/categories/recovered-with-hbkit).
56
+ To hear about new versions, watch the repo's releases or follow
57
+ [Announcements](https://github.com/YordiLorenzo/hbkit/discussions/categories/announcements).
58
+
70
59
  ---
71
60
 
72
61
  ## Why
@@ -351,6 +340,9 @@ Read this before trusting it with the only copy of anything.
351
340
  archive (unencrypted, LZ4, single version, single pool) and a small encrypted one from
352
341
  the same DSM version, both verified byte-exact, plus a 7-version encrypted archive from
353
342
  Hyper Backup 4.2.2 reported in [#4](https://github.com/YordiLorenzo/hbkit/issues/4).
343
+ In [#6](https://github.com/YordiLorenzo/hbkit/issues/6), a user restored 465,000 files
344
+ (754 GB) from a backup on a NAS hit by C3RB3R ransomware: it had locked only small
345
+ files that hbkit doesn't read.
354
346
  Version selection was checked byte-exact on a small two-version encrypted Hyper Backup
355
347
  4.2.2 archive (each version's copy of a changed file, by number and by date), and on
356
348
  synthetic archives; the version list comes from `Config/version_info.db`, whose layout
@@ -362,8 +354,11 @@ Read this before trusting it with the only copy of anything.
362
354
  bytes, which is the one thing a recovery tool must never do.
363
355
  - **Whole-file dedup** (`off_virtual_file = -1`, files living in `Pool/file_pool`) is not
364
356
  decoded. One file in 501,278 in the reference archive.
365
- - **Windows is untested for extraction.** CI installs the package and checks that it
366
- imports, but no archive has been rebuilt on Windows. Linux and macOS are verified.
357
+ - **Synology C2 is not tested.** Use Hyper Backup Explorer for a backup kept in C2.
358
+ - **Windows: tested on synthetic archives only.** On every push, CI restores plain and
359
+ encrypted test archives byte-exact on Windows, with an `lz4.dll` built by
360
+ `vcpkg install lz4:x64-windows` and `HBK_LZ4` set to its full path. No archive from a
361
+ real NAS has been restored on Windows yet. Linux and macOS are verified on real archives.
367
362
 
368
363
  ## The format
369
364
 
@@ -384,6 +379,7 @@ offsets. Where the two disagreed, the empirical result won.
384
379
  ## Prior art
385
380
 
386
381
  - [TeamDman/teamy-hyper-backup-explorer](https://github.com/TeamDman/teamy-hyper-backup-explorer) — independent Rust implementation (MPL-2.0). Its constants agree with what we derived separately.
382
+ - [Callido Restore](https://github.com/Niels-van-Haren-Holding-B-V/callido-restore): a separate macOS app (MIT) that restores `.hbk` archives, started 2026-10-30. We have not reviewed its code.
387
383
  - [mistersandman/hyperbackup_decrypt](https://github.com/mistersandman/hyperbackup_decrypt) — 2016 Python 2 script, and the only public reference for the **encrypted** variant.
388
384
 
389
385
  ## Development
@@ -4,15 +4,15 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hbkit"
7
- version = "0.5.0"
7
+ version = "0.5.2"
8
8
  description = "Recover files from Synology Hyper Backup (.hbk) archives without Synology software"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = "MIT"
12
12
  license-files = ["LICENSE"]
13
13
  authors = [{ name = "YordiLorenzo", email = "yordilorenzo@gmail.com" }]
14
- keywords = ["synology", "hyper-backup", "hbk", "backup", "recovery",
15
- "data-recovery", "nas", "dsm", "extract"]
14
+ keywords = ["synology", "hyper-backup", "hyperbackup", "hyper-backup-explorer", "hbk",
15
+ "backup", "recovery", "data-recovery", "nas", "dsm", "extract"]
16
16
  classifiers = [
17
17
  "Development Status :: 4 - Beta",
18
18
  "Environment :: Console",
@@ -21,6 +21,10 @@ classifiers = [
21
21
  "Operating System :: MacOS",
22
22
  "Operating System :: POSIX :: Linux",
23
23
  "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
24
28
  "Topic :: System :: Archiving :: Backup",
25
29
  "Topic :: System :: Recovery Tools",
26
30
  ]
@@ -30,7 +34,8 @@ dependencies = ["textual>=0.80", "pynacl>=1.5", "cryptography>=41"]
30
34
  dev = ["pytest>=7"]
31
35
 
32
36
  [project.urls]
33
- Homepage = "https://github.com/YordiLorenzo/hbkit"
37
+ Homepage = "https://yordilorenzo.github.io/hbkit/"
38
+ Documentation = "https://yordilorenzo.github.io/hbkit/restore-without-nas/"
34
39
  Source = "https://github.com/YordiLorenzo/hbkit"
35
40
  Issues = "https://github.com/YordiLorenzo/hbkit/issues"
36
41
  "Format spec" = "https://github.com/YordiLorenzo/hbkit/blob/main/FORMAT.md"
@@ -1,6 +1,6 @@
1
1
  """hbkit - recover files from Synology Hyper Backup (.hbk) archives without Synology software."""
2
2
 
3
- __version__ = "0.5.0"
3
+ __version__ = "0.5.2"
4
4
 
5
5
  from .archive import (Archive, NeedPassword, UnsupportedArchive, # noqa: F401
6
6
  find_archive_root, is_archive)
@@ -1380,15 +1380,17 @@ def test_unusual_digits_are_a_usage_error(tmp_path):
1380
1380
  assert r.returncode == 2 and "Traceback" not in r.stderr, r.stderr
1381
1381
 
1382
1382
 
1383
- @pytest.mark.skipif(sys.platform == "win32", reason="needs bash; see the in-process pipe test")
1383
+ @pytest.mark.skipif(sys.platform == "win32",
1384
+ reason="a closed pipe is EINVAL there; see the in-process pipe test")
1384
1385
  def test_a_closed_pipe_is_not_an_internal_error(tmp_path):
1385
1386
  root, _ = _three_versions(tmp_path)
1386
1387
  env = {**os.environ, "HBK_CACHE": str(tmp_path / "cache")}
1387
- p = subprocess.run(f'"{sys.executable}" -m hbkit.cli "{root}" list / | head -c 1 >/dev/null; '
1388
- 'exit ${PIPESTATUS[0]}', shell=True, executable="/bin/bash",
1389
- capture_output=True, text=True, env=env)
1390
- assert "Traceback" not in p.stderr and "please report" not in p.stderr, p.stderr
1391
- assert p.returncode == 0, p.stderr # list: the reader had enough
1388
+ p = subprocess.Popen([sys.executable, "-m", "hbkit.cli", str(root), "list", "/"],
1389
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
1390
+ p.stdout.close() # the reader is gone before hbk writes a byte
1391
+ err = p.stderr.read().decode()
1392
+ assert p.wait(timeout=60) == 0, err # list: the reader had enough
1393
+ assert "Traceback" not in err and "please report" not in err, err
1392
1394
 
1393
1395
 
1394
1396
  # ------------------------------------------------------------- review round 3
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes