@@ -34,18 +34,9 @@ internal static unsafe int ReadAtOffset(SafeFileHandle handle, Span<byte> buffer
34
34
{
35
35
// Try pread for seekable files.
36
36
result = Interop . Sys . PRead ( handle , bufPtr , buffer . Length , fileOffset ) ;
37
- if ( result == - 1 )
37
+ if ( result == - 1 && NeedsNonOffsetFallback ( handle ) )
38
38
{
39
- // We need to fallback to the non-offset version for certain file types
40
- // e.g: character devices (such as /dev/tty), pipes, and sockets.
41
- Interop . ErrorInfo errorInfo = Interop . Sys . GetLastErrorInfo ( ) ;
42
-
43
- if ( errorInfo . Error == Interop . Error . ENXIO ||
44
- errorInfo . Error == Interop . Error . ESPIPE )
45
- {
46
- handle . SupportsRandomAccess = false ;
47
- result = Interop . Sys . Read ( handle , bufPtr , buffer . Length ) ;
48
- }
39
+ result = Interop . Sys . Read ( handle , bufPtr , buffer . Length ) ;
49
40
}
50
41
}
51
42
else
@@ -77,7 +68,18 @@ internal static unsafe long ReadScatterAtOffset(SafeFileHandle handle, IReadOnly
77
68
78
69
fixed ( Interop . Sys . IOVector * pinnedVectors = & MemoryMarshal . GetReference ( vectors ) )
79
70
{
80
- result = Interop . Sys . PReadV ( handle , pinnedVectors , buffers . Count , fileOffset ) ;
71
+ if ( handle . SupportsRandomAccess )
72
+ {
73
+ result = Interop . Sys . PReadV ( handle , pinnedVectors , buffers . Count , fileOffset ) ;
74
+ if ( result == - 1 && NeedsNonOffsetFallback ( handle ) )
75
+ {
76
+ result = Interop . Sys . ReadV ( handle , pinnedVectors , buffers . Count ) ;
77
+ }
78
+ }
79
+ else
80
+ {
81
+ result = Interop . Sys . ReadV ( handle , pinnedVectors , buffers . Count ) ;
82
+ }
81
83
}
82
84
}
83
85
finally
@@ -111,18 +113,9 @@ internal static unsafe void WriteAtOffset(SafeFileHandle handle, ReadOnlySpan<by
111
113
if ( handle . SupportsRandomAccess )
112
114
{
113
115
bytesWritten = Interop . Sys . PWrite ( handle , bufPtr , bytesToWrite , fileOffset ) ;
114
- if ( bytesWritten == - 1 )
116
+ if ( bytesWritten == - 1 && NeedsNonOffsetFallback ( handle ) )
115
117
{
116
- // We need to fallback to the non-offset version for certain file types
117
- // e.g: character devices (such as /dev/tty), pipes, and sockets.
118
- Interop . ErrorInfo errorInfo = Interop . Sys . GetLastErrorInfo ( ) ;
119
-
120
- if ( errorInfo . Error == Interop . Error . ENXIO ||
121
- errorInfo . Error == Interop . Error . ESPIPE )
122
- {
123
- handle . SupportsRandomAccess = false ;
124
- bytesWritten = Interop . Sys . Write ( handle , bufPtr , bytesToWrite ) ;
125
- }
118
+ bytesWritten = Interop . Sys . Write ( handle , bufPtr , bytesToWrite ) ;
126
119
}
127
120
}
128
121
else
@@ -198,7 +191,18 @@ internal static unsafe void WriteGatherAtOffset(SafeFileHandle handle, IReadOnly
198
191
long bytesWritten ;
199
192
fixed ( Interop . Sys . IOVector * pinnedVectors = & MemoryMarshal . GetReference ( vectors ) )
200
193
{
201
- bytesWritten = Interop . Sys . PWriteV ( handle , pinnedVectors , buffersCount , fileOffset ) ;
194
+ if ( handle . SupportsRandomAccess )
195
+ {
196
+ bytesWritten = Interop . Sys . PWriteV ( handle , pinnedVectors , buffersCount , fileOffset ) ;
197
+ if ( bytesWritten == - 1 && NeedsNonOffsetFallback ( handle ) )
198
+ {
199
+ bytesWritten = Interop . Sys . WriteV ( handle , pinnedVectors , buffersCount ) ;
200
+ }
201
+ }
202
+ else
203
+ {
204
+ bytesWritten = Interop . Sys . WriteV ( handle , pinnedVectors , buffersCount ) ;
205
+ }
202
206
}
203
207
204
208
FileStreamHelpers . CheckFileCall ( bytesWritten , handle . Path ) ;
@@ -243,5 +247,21 @@ internal static ValueTask WriteAtOffsetAsync(SafeFileHandle handle, ReadOnlyMemo
243
247
244
248
private static ValueTask WriteGatherAtOffsetAsync ( SafeFileHandle handle , IReadOnlyList < ReadOnlyMemory < byte > > buffers , long fileOffset , CancellationToken cancellationToken )
245
249
=> handle . GetThreadPoolValueTaskSource ( ) . QueueWriteGather ( buffers , fileOffset , cancellationToken ) ;
250
+
251
+ private static bool NeedsNonOffsetFallback ( SafeFileHandle handle )
252
+ {
253
+ // We need to fallback to the non-offset version for certain file types
254
+ // e.g: character devices (such as /dev/tty), pipes, and sockets.
255
+ Interop . ErrorInfo errorInfo = Interop . Sys . GetLastErrorInfo ( ) ;
256
+
257
+ if ( errorInfo . Error == Interop . Error . ENXIO ||
258
+ errorInfo . Error == Interop . Error . ESPIPE )
259
+ {
260
+ handle . SupportsRandomAccess = false ;
261
+ return true ;
262
+ }
263
+
264
+ return false ;
265
+ }
246
266
}
247
267
}
0 commit comments