Skip to content

Commit a0ae647

Browse files
committed
Added optional name parameter to AndroidFile
1 parent 3011661 commit a0ae647

1 file changed

Lines changed: 20 additions & 3 deletions

File tree

  • src/Platforms/SecureFolderFS.Maui/Platforms/Android/Storage

src/Platforms/SecureFolderFS.Maui/Platforms/Android/Storage/AndroidFile.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using OwlCore.Storage;
77
using SecureFolderFS.Core.MobileFS.Platforms.Android.Streams;
88
using SecureFolderFS.Maui.Platforms.Android.Storage.StorageProperties;
9+
using SecureFolderFS.Shared.Helpers;
910
using SecureFolderFS.Storage.StorageProperties;
1011
using AndroidUri = Android.Net.Uri;
1112

@@ -26,11 +27,11 @@ internal sealed class AndroidFile : AndroidStorable, IChildFile, ILastModifiedAt
2627
/// <inheritdoc/>
2728
public ISizeOfProperty SizeOf => field ??= new AndroidSizeOfProperty(Id, Document ?? throw new ArgumentNullException(nameof(Document)));
2829

29-
public AndroidFile(AndroidUri uri, Activity activity, AndroidFolder? parent = null, AndroidUri? permissionRoot = null, string? bookmarkId = null)
30+
public AndroidFile(AndroidUri uri, Activity activity, AndroidFolder? parent = null, AndroidUri? permissionRoot = null, string? bookmarkId = null, string? name = null)
3031
: base(uri, activity, parent, permissionRoot, bookmarkId)
3132
{
3233
Document = DocumentFile.FromSingleUri(activity, uri);
33-
Name = Document?.Name ?? base.Name;
34+
Name = name ?? Document?.Name ?? base.Name;
3435
}
3536

3637
/// <inheritdoc/>
@@ -47,6 +48,20 @@ public Task<Stream> OpenStreamAsync(FileAccess accessMode, CancellationToken can
4748

4849
if (accessMode == FileAccess.Read)
4950
{
51+
// Prefer a file-descriptor-backed stream which is seekable - random access
52+
// is required both by the crypto layer and by consumers seeking within files
53+
var readFd = SafetyHelpers.NoFailureResult(() => activity.ContentResolver?.OpenFileDescriptor(Inner, "r"));
54+
if (readFd is not null)
55+
{
56+
var readChannel = new FileInputStream(readFd.FileDescriptor).Channel;
57+
if (readChannel is not null)
58+
return Task.FromResult<Stream>(new ChannelledStream(readChannel, null, readFd));
59+
60+
readFd.Close();
61+
}
62+
63+
// Fall back to a plain (forward-only) input stream for providers
64+
// that cannot supply a seekable file descriptor
5065
var inStream = activity.ContentResolver?.OpenInputStream(Inner);
5166
if (inStream is null)
5267
return Task.FromException<Stream>(new UnauthorizedAccessException("Could not open input stream."));
@@ -55,7 +70,9 @@ public Task<Stream> OpenStreamAsync(FileAccess accessMode, CancellationToken can
5570
}
5671
else
5772
{
58-
var fd = activity.ContentResolver?.OpenFileDescriptor(Inner, "rwt");
73+
// Open in "rw" mode - "rwt" would truncate the existing content on open.
74+
// Truncation is a deliberate operation performed by the caller, never a side effect
75+
var fd = activity.ContentResolver?.OpenFileDescriptor(Inner, "rw");
5976
if (fd is null)
6077
return Task.FromException<Stream>(new UnauthorizedAccessException("Could not open file descriptor."));
6178

0 commit comments

Comments
 (0)