Under Windows, strip paths of any `\\?\` prefix to prevent Duplicati
from storing paths prefixed with `\\?\`.
This fixes an inconsistency in the stored data where, if the user
provided a prefixed path to back up (e.g., `\\?\C:\Temp`), Duplicati
would store an entry with the prefixed path (e.g., `\\?\C:\Temp`)
along with entries with paths stripped of their prefix (e.g.,
`C:\Temp\file.txt`). By only storing non-prefixed paths, this also
avoids an error reported by the GUI when it would encounter a prefixed
path:
```
Filter for list-folder-contents must be a path prefix with no wildcards Parameter name: filter
```
Add comment in `WindowsSnapshot.ConvertToSnapshotPath()` warning how
replacing some manual path construction code with Path.Combine() alone
can lead to invalid snapshot paths.
Revert the change made to `WindowsSnapshot.ConvertToSnapshotPath()`
by pull request #4256.
The change in #4256 replaced some existing manual path construction
code with a call to `SystemIO.IO_WIN.PathCombine()`, but calling
`SystemIO.IO_WIN.PathCombine()` this way did not always result in
valid VSS paths. For example, trying to back up a root volume like
"C:\" would result in the following error:
```
The filename, directory name, or volume label syntax is incorrect.
```
Fix pull request string comparisons in SystemIOWindows.cs to use
StringComparison.Ordinal.
Fix pull request to use SystemIO.IO_WIN.PathCombine() in
WindowsSnapshot.cs.
Allow historically problematic Windows paths (i.e., files or
directories that end in a dot or a space) to be backed up with
Duplicati in Windows.
This fixes#3839.
This is inspired largely by the new (/ returning) feature of OneDrive in Windows 10 Fall Creator's Update, which downloads files on-demand.
A side effect of that change is that the OneDrive folder (and subfolders of it) are marked as reparse points, even though they are not technically standard symlinks.
With this change, a new extension method IsSymlink is added for ISnapshotService and ISystemIO, which checks both the file attributes (for reparse point) and the symlink target path (if null, the path is not treated as a symlink).
All places that previously checked only the file attributes have been updated to use either this method (or at least the same logic, in the case of the core BackupHandler file check).
One side effect of this change is that '--symlink-policy=store' no longer ignores empty symlinks - they are now treated as regular files.
If there are empty symlinks, they will now be backed up as if they were regular files, but I don't know what the conditions are that create symlinks like that, so this might not effect anything in practice.