Skip to content

Commit 4650882

Browse files
committed
Improved VolumeName handling for WebDav on macOS
1 parent 074e2c3 commit 4650882

16 files changed

Lines changed: 143 additions & 27 deletions

File tree

src/Core/SecureFolderFS.Core.Dokany/DokanyFileSystem.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ public sealed partial class DokanyFileSystem : IFileSystemInfo
3232
/// <inheritdoc/>
3333
public partial Task<FileSystemAvailability> GetStatusAsync(CancellationToken cancellationToken = default);
3434

35+
/// <inheritdoc/>
36+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
37+
{
38+
return Task.FromResult(candidateName);
39+
}
40+
3541
/// <inheritdoc/>
3642
public async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unlockContract, IDictionary<string, object> options, CancellationToken cancellationToken = default)
3743
{

src/Core/SecureFolderFS.Core.FUSE/FuseFileSystem.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace SecureFolderFS.Core.FUSE
1515
{
16-
/// <inheritdoc cref="IFileSystem"/>
16+
/// <inheritdoc cref="IFileSystemInfo"/>
1717
public sealed partial class FuseFileSystem : IFileSystemInfo
1818
{
1919
/// <inheritdoc/>
@@ -25,6 +25,12 @@ public sealed partial class FuseFileSystem : IFileSystemInfo
2525
/// <inheritdoc/>
2626
public partial Task<FileSystemAvailability> GetStatusAsync(CancellationToken cancellationToken = default);
2727

28+
/// <inheritdoc/>
29+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
30+
{
31+
return Task.FromResult(candidateName);
32+
}
33+
2834
/// <inheritdoc/>
2935
public async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unlockContract, IDictionary<string, object> options, CancellationToken cancellationToken = default)
3036
{

src/Core/SecureFolderFS.Core.FileSystem/LocalFileSystem.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ public Task<FileSystemAvailability> GetStatusAsync(CancellationToken cancellatio
2929
return Task.FromResult(FileSystemAvailability.Available);
3030
}
3131

32+
/// <inheritdoc/>
33+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
34+
{
35+
return Task.FromResult(candidateName);
36+
}
37+
3238
/// <inheritdoc/>
3339
public async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unlockContract, IDictionary<string, object> options, CancellationToken cancellationToken = default)
3440
{

src/Core/SecureFolderFS.Core.MobileFS/Platforms/Android/AndroidFileSystem.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ public Task<FileSystemAvailability> GetStatusAsync(CancellationToken cancellatio
2525
return Task.FromResult(FileSystemAvailability.Available);
2626
}
2727

28+
/// <inheritdoc/>
29+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
30+
{
31+
return Task.FromResult(candidateName);
32+
}
33+
2834
/// <inheritdoc/>
2935
public async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unlockContract, IDictionary<string, object> options, CancellationToken cancellationToken = default)
3036
{

src/Core/SecureFolderFS.Core.MobileFS/Platforms/iOS/IOSFileSystem.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ public Task<FileSystemAvailability> GetStatusAsync(CancellationToken cancellatio
2424
return Task.FromResult(FileSystemAvailability.Available);
2525
}
2626

27+
/// <inheritdoc/>
28+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
29+
{
30+
return Task.FromResult(candidateName);
31+
}
32+
2733
/// <inheritdoc/>
2834
public async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unlockContract, IDictionary<string, object> options, CancellationToken cancellationToken = default)
2935
{

src/Core/SecureFolderFS.Core.WebDav/WebDavFileSystem.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ public virtual async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unloc
6868
cancellationToken);
6969
}
7070

71+
/// <inheritdoc/>
72+
public abstract Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default);
73+
74+
/// <summary>
75+
/// Mounts the WebDAV file system and initializes the provided HTTP listener, request dispatcher, and file system settings.
76+
/// </summary>
77+
/// <param name="specifics">Provides encryption specifics for the file system.</param>
78+
/// <param name="listener">The HTTP listener to handle WebDAV requests.</param>
79+
/// <param name="options">The configuration options for the WebDAV file system.</param>
80+
/// <param name="requestDispatcher">The dispatcher responsible for handling WebDAV requests.</param>
81+
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that cancels this action.</param>
82+
/// <returns>A <see cref="Task"/> that represents the asynchronous operation. Value is the initialized virtual file system root.</returns>
7183
protected abstract Task<IVfsRoot> MountAsync(
7284
FileSystemSpecifics specifics,
7385
HttpListener listener,

src/Core/SecureFolderFS.Core.WinFsp/Callbacks/OnDeviceWinFsp.Helpers.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ namespace SecureFolderFS.Core.WinFsp.Callbacks
88
{
99
public sealed partial class OnDeviceWinFsp
1010
{
11+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1112
private string GetCiphertextPath(string plaintextName)
1213
{
1314
return NativePathHelpers.GetCiphertextPath(plaintextName, _specifics);
1415
}
1516

17+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1618
private static bool IsDirectory(string ciphertextPath)
1719
{
1820
return Directory.Exists(ciphertextPath) && !File.Exists(ciphertextPath);
@@ -71,9 +73,8 @@ private static FileOptions ToFileOptions(uint createOptions)
7173
if ((createOptions & FILE_RANDOM_ACCESS) != 0)
7274
options |= FileOptions.RandomAccess;
7375

74-
// Never handle DELETE_ON_CLOSE
75-
// WinFsp already tracks the delete disposition and will call Cleanup with CleanupDelete.
76-
// Letting the real FileStream have DeleteOnClose bypasses your custom DeleteOrRecycle logic.
76+
// Never handle FILE_DELETE_ON_CLOSE
77+
// WinFsp already tracks the delete disposition and will call Cleanup with CleanupDelete
7778

7879
return options;
7980
}
@@ -83,7 +84,7 @@ private static int Trace(int status, string? fileName = null, [CallerMemberName]
8384
#if !DEBUG
8485
return status;
8586
#endif
86-
if (!Core.FileSystem.Constants.OPT_IN_FOR_OPTIONAL_DEBUG_TRACING)
87+
if (!FileSystem.Constants.OPT_IN_FOR_OPTIONAL_DEBUG_TRACING)
8788
return status;
8889

8990
if (!Debugger.IsAttached)

src/Core/SecureFolderFS.Core.WinFsp/WinFspFileSystem.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public sealed partial class WinFspFileSystem : IFileSystemInfo
3333
/// <inheritdoc/>
3434
public partial Task<FileSystemAvailability> GetStatusAsync(CancellationToken cancellationToken = default);
3535

36+
/// <inheritdoc/>
37+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
38+
{
39+
return Task.FromResult(candidateName);
40+
}
41+
3642
/// <inheritdoc/>
3743
public async Task<IVfsRoot> MountAsync(IFolder folder, IDisposable unlockContract, IDictionary<string, object> options, CancellationToken cancellationToken = default)
3844
{

src/Platforms/SecureFolderFS.Cli/CliWebDavFileSystem.cs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
using System.IO;
21
using System.Net;
3-
using System.Threading;
4-
using System.Threading.Tasks;
52
using NWebDav.Server.Dispatching;
63
using OwlCore.Storage.Memory;
74
using SecureFolderFS.Core.FileSystem;
@@ -10,22 +7,32 @@
107
using SecureFolderFS.Core.WebDav.AppModels;
118
using SecureFolderFS.Storage.VirtualFileSystem;
129

13-
namespace SecureFolderFS.Cli;
14-
15-
internal sealed class CliWebDavFileSystem : WebDavFileSystem
10+
namespace SecureFolderFS.Cli
1611
{
17-
protected override async Task<IVfsRoot> MountAsync(FileSystemSpecifics specifics, HttpListener listener, WebDavOptions options,
18-
IRequestDispatcher requestDispatcher, CancellationToken cancellationToken)
12+
/// <inheritdoc cref="IFileSystemInfo"/>
13+
internal sealed class CliWebDavFileSystem : WebDavFileSystem
1914
{
20-
await Task.CompletedTask;
15+
/// <inheritdoc/>
16+
public override Task<string> GetVolumeNameAsync(string candidateName,
17+
CancellationToken cancellationToken = default)
18+
{
19+
return Task.FromResult(candidateName);
20+
}
21+
22+
/// <inheritdoc/>
23+
protected override async Task<IVfsRoot> MountAsync(FileSystemSpecifics specifics, HttpListener listener,
24+
WebDavOptions options,
25+
IRequestDispatcher requestDispatcher, CancellationToken cancellationToken)
26+
{
27+
await Task.CompletedTask;
2128

22-
var remotePath = $"{options.Protocol}://{options.Domain}:{options.Port}/";
23-
var webDavWrapper = new WebDavWrapper(listener, requestDispatcher, remotePath);
24-
webDavWrapper.StartFileSystem();
29+
var remotePath = $"{options.Protocol}://{options.Domain}:{options.Port}/";
30+
var webDavWrapper = new WebDavWrapper(listener, requestDispatcher, remotePath);
31+
webDavWrapper.StartFileSystem();
2532

26-
var virtualizedRoot = new MemoryFolder(remotePath, options.VolumeName);
27-
var plaintextRoot = new CryptoFolder(Path.DirectorySeparatorChar.ToString(), specifics.ContentFolder, specifics);
28-
return new WebDavVfsRoot(webDavWrapper, virtualizedRoot, plaintextRoot, specifics);
33+
var virtualizedRoot = new MemoryFolder(remotePath, options.VolumeName);
34+
var plaintextRoot = new CryptoFolder(Path.DirectorySeparatorChar.ToString(), specifics.ContentFolder, specifics);
35+
return new WebDavVfsRoot(webDavWrapper, virtualizedRoot, plaintextRoot, specifics);
36+
}
2937
}
3038
}
31-

src/Platforms/SecureFolderFS.Uno/Platforms/Desktop/SkiaWebDavFileSystem.Linux.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22

33
namespace SecureFolderFS.Uno.Platforms.Desktop
44
{
5-
/// <inheritdoc cref="IFileSystem"/>
5+
/// <inheritdoc cref="IFileSystemInfo"/>
66
internal sealed partial class SkiaWebDavFileSystem
77
{
88
#if HAS_UNO_SKIA && !__MACCATALYST__ && !__UNO_SKIA_MACOS__
9+
/// <inheritdoc/>
10+
public Task<string> GetVolumeNameAsync(string candidateName, CancellationToken cancellationToken = default)
11+
{
12+
return Task.FromResult(candidateName);
13+
}
14+
915
/// <inheritdoc/>
1016
protected override async Task<IVFSRoot> MountAsync(
1117
FileSystemSpecifics specifics,

0 commit comments

Comments
 (0)