# The Plan

## Goal

- all operations require the users' passphrase
- arq version >=7 is required, Arq 6 seems also okay, hard to test for me
  - I -think- that older blobs/data can be referenced, it's very difficult to test, so I won't support it for now

- CLI ergonomic inspired by restic:
  - https://restic.readthedocs.io/en/latest/050_restore.html
  - https://restic.readthedocs.io/en/latest/045_working_with_repos.html

```terminal
# List backups for the given plan (with timestamp and backup folders?)
arq-restore ls --repository=/tmp/backup/D7E09473-74BF-4E6D-86C3-43A033570D80

# list 

# List backup folders for given plan and backup record
arq-restore ls --repository=/tmp/backup/D7E09473-74BF-4E6D-86C3-43A033570D80 --record=1763107319

# List files found in backup, with
# - name
# - for directories: total size down the tree (should be in itemSize) and how many items are under a tree (containedFilesCount)
# - for files: size
arq-restore ls --repository=/tmp/backup/D7E09473-74BF-4E6D-86C3-43A033570D80 --record=1763107319 /Users/basti/Documents/src/arq-restore/testdata/source/foo

# Restore a directory or file, recursively into a destination
arq-restore restore --repository=/tmp/backup/D7E09473-74BF-4E6D-86C3-43A033570D80 --record=1763107319 /Users/basti/Documents/src/arq-restore/testdata/source/foo /tmp/restore-foo

# --------

arq-restore info --repository=/tmp/backup/D7E09473-74BF-4E6D-86C3-43A033570D80

# To inspect files in the repository, you can use "inspect"
arq-restore inspect --repository=/tmp/backup/D7E09473-74BF-4E6D-86C3-43A033570D80 --record=1763107319



# Restore Syntax

arq-restore --repository=/my/repo restore DD994AEF-F9CB-4D39-B12D-1EF5305103C8@1763107319:/path/in/backup /tmp/restore-to


```


## TODO

- figure out, how password changes work; add to test data

- BlobLoc: is_packed=false
  - I think "is_packed=false" just means, that the entire pack file is used as the encrypted object, basically offset=0 and length="length of file"
  - Might be related to `maxPackedItemLength` (apparently 256000), see `backupconfig.json`
- BlobLoc: compression_type: Only Type 2 (LZ4) is implemented
  - look if I have anything using compression_type=1 GZip. If I have, implement it.
- KeySet: What is "blob salt" used for?


- BackupFolders: location ending in the same name
  - what happens with multiple backup folders, ending in the same name /foo/foo/bar and /foo/bar? It looks like the `name` should be `bar` in both cases?



- `Node` could be split into `TreeNode` and `FileNode` (or maybe as an enum?). That would make it more clear in many cases what is being dealt with.

- treepack missing: `time cargo run --release restore --password-file=.password --repository=tmp/test/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1 --dry-run --record 1560285591 CCEEBB74-3869-4D68-BAA6-892A49364777 tmp/restore`
- `tmp/test/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1/backupfolders/CCEEBB74-3869-4D68-BAA6-892A49364777/backuprecords/00159/9685207.backuprecord` was created with 6.2.54.
  - restore fails, because `Bool:aclBlobLocIsNotNil` is not a boolean, `BlobLoc { offset: 5876, length: 404, relative_path: "/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1/treepacks/C1/0841D3-E761-45AA-AD90-13579B934C26.pack", blob_id: "d6d0023836c37dacd184764cacfe20f280d258fb", compression_type: 2, stretch_encryption_key: true, is_packed: true }`
  - tree version is 1, not 2 as for Arq 7. So maybe the issue is with the tree? Unlikely, because the "childName" String before the childNode seems to be okay
  - `RUST_LOG=trace RUST_BACKTRACE=1 cargo run -- restore --password-file=.password --repository=tmp/test/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1 --dry-run --record 1599685207 CCEEBB74-3869-4D68-BAA6-892A49364777 tmp/restore`
  - it looks like for tree version 1, the BlocLoc does not seem to have the extra byte
- `cargo run --release restore --password-file=.password --repository=tmp/test/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1 --dry-run --record 1560285591 CCEEBB74-3869-4D68-BAA6-892A49364777 tmp/restore` the record (`tmp/test/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1/backupfolders/CCEEBB74-3869-4D68-BAA6-892A49364777/backuprecords/00156/0285591.backuprecord`) is "version=1" and missing various fields.
  - aside from that, the root treepack is missing
- I found "snapshot" files in my repository (e.g. `06DEFBFC-907F-4918-8F7B-A21D6E56DEF1/snapshots/00156/0285591.snapshot`), can be decrypted with the Arq 7 scheme and it is compressed JSON. Looks like a backup record...
- objects/<hash> files look like pack files, at least they have the same header `ARQO`
  - is this maybe `isPacked=false` case?

- the oldest backup to test for me that has still the root treepack is `cargo run --release restore --password-file=.password --repository=tmp/test/06DEFBFC-907F-4918-8F7B-A21D6E56DEF1 --dry-run --record 1586340007 CCEEBB74-3869-4D68-BAA6-892A49364777 tmp/restore` (Arq 6.0.221)

## Questions

- BlobLoc: `stretchEncryptionKey`: When is this exactly `false`. And what does this mean? key stretching is not used for blobs, but this is `true` for Arq 7.
- BlocLoc: There is an undocumented, extra byte between `[Bool:isPacked]` and `[String:relativePath]`. In my testing I can only see 0 and 1, so maybe a boolean? It seems to be mostly 0 (false).



tests/data/source/c/compressible.bin --> 1048576 Bytes

* The Node looks correct (item size is correct)

```
-> Node { name: "compressible.bin", is_tree: false, item_size: 1048576, contained_files_count: 1, tree_loc: None, data_locs: Some([BlobLoc { offset: 0, length: 4244, relative_path: "/EE16685F-FEC5-4A13-A7F8-5296E2EF75B9/largeblobpacks/C9/4BEEF8-2FD7-4EFE-8E18-06CC261102F9.pack", blob_id: "90330147671aa3de729b8db5e70e50901842aadbc85473ef512d47df04b1aad0", compression_type: 2, stretch_encryption_key: true, is_packed: true }]), computer_os_type: 1, deleted: false, creation_time: Some(2026-01-07T15:00:23.804585747Z), ctime_sec: Some(1767798023), ctime_nsec: Some(808428685), mtime_sec: Some(1767798023), mtime_nsec: Some(808428685), user_name: Some("basti"), uid: 501, group_name: Some("staff"), gid: 20, mode: 33188 }
```

* still error, when trying to decompress

```
Could not restore tmp/restore/c/compressible.bin: provided output is too small for the decompressed data, actual 4096, expected 1048571
```

* The "expected" is off by 5 - (actual item size, 1048576 - "expected" decompressed size?! 1048571)
* lz4 blocks are prefixed by 4 bytes length prefix
* the decrypted, but compressed data is 4126 bytes, first 4 bytes: 0x00100000 -> 1048576 Bytes
* Arq: Can restore the file correctly, size (1048576 bytes), and md5sum checks out, compared to the original
