This PR adds guards to prevent creating filesets with multiple files that have the same path.
While it should technically be impossible to have multiple entries that have the same path, it could happend either due to glitches or because the source data (manual lists, remote sources, etc) returns duplicates.
This PR adds a simple check for each folder to ensure that on a folder-level, duplicate paths cannot be introduced.
There is also a post-backup check to evict any duplicates, and the recreate process will reject duplicate paths.
Finally, the repair command will remove duplicates if they somehow manage to get into the database anyway.
A database-level prevention is not currently feasible as it needs a cross-table check for uniqueness, which requires more work from the database to check for each added file. Since this is expected to be a very rare event, the added processing was not justified.
Renamed the options to be more descriptive.
Rewrote the dependency query to be more readable and also check for metadata dependency.
Fixed an edge case where there were no modified files, and no new backup is created.
Fixed some issues with local/utc datetime compares.
Fixed logic for deleting filesets to only look at the filesets themselves. This makes the version lock follow the dlist file, and can create "dangling" volumes that have no filesets, but these will be picked up by compaction.
Updated tests to work correctly.
Added lock-info update option for the backup recreate call, so the UI can also re-create lock information on database rebuilds.
This PR adds support for locking files if the backend supports it.
To activate locking, set the option `--file-lock-duration=30D` and the backup will lock the files.
If the database is rebuilt with the intention of continuing the backups, use the option `--repair-refresh-lock-info` which will update lock information in the database after recreating the database.
The locking works by asking the backend to lock files after a backup has completed.
The implementation keeps track of which files are currently assigned a lock and prevents attempting to delete the files that are currently locked.
Note that the bucket should not have a default lock policy as Duplicati needs to finish the backup before the locking is applied.
In this initial version, Azure Blob Storage, B2, S3 and iDrive are supported with locking.
The CLI is updated to allow setting locks on a specific version. The backend tool is updated to allow setting locks on specific files.
This PR adds detection of the MacOS Photos folder, and intercepts reads and replaces them with PhotoKit calls.
With this, it is possible to make backups of all MacOS Photos, even if they are not stored locally.
The previous versions would just make a backup of the on-disk structure, which was not guaranteed to contain all photos, but instead has various indexing for finding photos, and may contain some original photos.
The option `--photos-handling` controls how Duplicati now deals with the Photos folder. The options are:
- `LibraryOnly`: Same as before, just treat it as a folder
- `PhotosOnly`: Ignore the folder contents and just back up the actual photos
- `PhotosAndLibrary` (default): Make a backup of the photos and the library on-disk. This may cause images to be stored twice, but de-duplication will usually limit the storage increase.
The option `--photos-library-path` can be used to point to the on-disk Photo library that should be handled, in case the auto-detection does not pick it up. If this does not point to a valid Photoslibrary, or the path is not being backed up, no special handling will be done.
Note that the restore is not restoring into Photos itself, but instead restores into a sub-folder in the Photolibrary that is called `dup_backup`. To get the photos out after a restore, one needs to right-click the Photolibrary folder, and choose "Show package contents" and then the `dup_backup` folder is revealed.
This is done to keep all photos in the same folder, but avoid messing with the structure of the on-disk Photolibrary.
A future update could allow restoring back into Photos, and metadata is captured for each image to eventually allow this.
This fixes#6381
This updates VSS to default use Vanara in favor of AlphaVSS which is no longer maintained.
The build for Vanara requires targeting `net8.0-windows7.0`, which will cause significant build overhead and complexity for cross platform builds.
To counter this, the setup is to have a single project, `Duplicati.Library.WindowsModules`, that is targeting `net8.0-windows7.0`.
The output from this project is then hoisted into the TrayIcon project for Windows builds so the files are available when debugging on Windows.
A top-level dummy executable project is added to ensure the project always builds.
The built modules are then loaded with reflection when requested.
With the use of Vanara there is now also support for using BackupRead to read files without making a VSS snapshot.
With BackupRead, it is possible to read locked files, but it still requires the SeBackupPrivilege as VSS does as well.
Unfortunately, the `vssapi.dll` file is not shipped for Arm64 on Windows, so even with Vanara this will not work, and only WMIC is supported on Arm64.
A workaround is to run Duplicati with x64 emulation if more advanced VSS features are needed (HyperV and MSSQL support).
This PR also updates options and filters out unsupported options for each operating system, so options that are not supported by the current OS are not reported and will give warnings if they are used, as opposed to just being ignored.
The release builder project has been updated to exclude the unused project, and purge unwanted outputs.
Since index files only contains information related to recreating the database, they can be recreated directly from a working database.
This PR adds an automatic repair feature that replaces index files if they are missing content. This will gradually repair remote index files if they are affected by the compact bug that re-wrote index files without the blocklists.
To fully repair, it is possible to run the `Test` command with the option `--full-remote-verification=indexonly` and a large number of samples. Since the new option `--replace-faulty-index-files` is default set to `true` this will repair any defective index files and ignore all others.
This update uncovered that the Test method would previously not verify the presence of blocklists in the index files. This is likely a very old bug, caused by the fact that the original implementation did not place blocklisthashes in the index files. The omission of this check is the reason the extent of the compact issue was not discovered earlier.
With this PR it is now also visible that there is ample room for error in creating the index files during the backup process. This is caused by the parallel processing and carry-over, where the index files are created on-the-go, so they are ready to upload once the blocks are filled.
While this is likely good for performance, it has some drawbacks.
- A failed block upload will cause a rewrite of the index file
- An elaborate callback system is needed to update the index file
- It is possible to race against the database and create extra blocklist hashes, bloating the index files (causes problems on verification)
A subsequent task is to rewrite the logic to not touch the index files outside the backend manager, so the backend manager will just use the database to create the index file. This means the same code will be invoked for both the create, the recreate, and the replacement.
For now, extra content in index files is logged with the verbose log level.
This fixes#6296
If the upload of the dlist fails, the filename will be incremented with one second. This causes validation errors when running repair, because it compares the fileset times (when the backup actually started) with the timestamp in the filename.
This PR updates the check to look only at the filename timestamp so the comparison is accurate even in the failure scenario.
This fixes#6235
This repair will leave the database in a still-broken state, but if this is run prior to purge-broken-files, less data will be lost.
Also updated the purge-broken-files operation to keep files and directories in the set, if they are only missing metadata.
This adds a number of additional features to the repair process so it can actually fully recover if all data is present.
Also added a several tests to ensure that the functionality works in multiple scenarios.
This fixes#5987