/
FileStreamHelpers.Unix.cs
79 lines (67 loc) · 3.54 KB
/
FileStreamHelpers.Unix.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Win32.SafeHandles;
namespace System.IO.Strategies
{
// this type defines a set of stateless FileStream/FileStreamStrategy helper methods
internal static partial class FileStreamHelpers
{
#pragma warning disable IDE0060
private static UnixFileStreamStrategy ChooseStrategyCore(SafeFileHandle handle, FileAccess access, bool isAsync) =>
new UnixFileStreamStrategy(handle, access);
#pragma warning restore IDE0060
private static UnixFileStreamStrategy ChooseStrategyCore(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize, UnixFileMode? unixCreateMode) =>
new UnixFileStreamStrategy(path, mode, access, share, options, preallocationSize, unixCreateMode);
internal static long CheckFileCall(long result, string? path, bool ignoreNotSupported = false)
{
if (result < 0)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
if (!(ignoreNotSupported && errorInfo.Error == Interop.Error.ENOTSUP))
{
throw Interop.GetExceptionForIoErrno(errorInfo, path);
}
}
return result;
}
internal static long Seek(SafeFileHandle handle, long offset, SeekOrigin origin) =>
CheckFileCall(Interop.Sys.LSeek(handle, offset, (Interop.Sys.SeekWhence)(int)origin), handle.Path); // SeekOrigin values are the same as Interop.libc.SeekWhence values
internal static void ThrowInvalidArgument(SafeFileHandle handle) =>
throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(Interop.Error.EINVAL), handle.Path);
/// <summary>Flushes the file's OS buffer.</summary>
internal static void FlushToDisk(SafeFileHandle handle)
{
if (Interop.Sys.FSync(handle) < 0)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
switch (errorInfo.Error)
{
case Interop.Error.EROFS:
case Interop.Error.EINVAL:
case Interop.Error.ENOTSUP:
// Ignore failures for special files that don't support synchronization.
// In such cases there's nothing to flush.
break;
default:
throw Interop.GetExceptionForIoErrno(errorInfo, handle.Path);
}
}
}
internal static void Lock(SafeFileHandle handle, bool canWrite, long position, long length)
{
if (OperatingSystem.IsApplePlatform() || OperatingSystem.IsFreeBSD())
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_OSXFileLocking);
}
CheckFileCall(Interop.Sys.LockFileRegion(handle, position, length, canWrite ? Interop.Sys.LockType.F_WRLCK : Interop.Sys.LockType.F_RDLCK), handle.Path);
}
internal static void Unlock(SafeFileHandle handle, long position, long length)
{
if (OperatingSystem.IsApplePlatform() || OperatingSystem.IsFreeBSD())
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_OSXFileLocking);
}
CheckFileCall(Interop.Sys.LockFileRegion(handle, position, length, Interop.Sys.LockType.F_UNLCK), handle.Path);
}
}
}