diff options
Diffstat (limited to 'src/mscorlib/shared/Interop/Unix')
30 files changed, 1224 insertions, 0 deletions
diff --git a/src/mscorlib/shared/Interop/Unix/Interop.Errors.cs b/src/mscorlib/shared/Interop/Unix/Interop.Errors.cs new file mode 100644 index 0000000000..4248434db3 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/Interop.Errors.cs @@ -0,0 +1,207 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + /// <summary>Common Unix errno error codes.</summary> + internal enum Error + { + // These values were defined in src/Native/System.Native/fxerrno.h + // + // They compare against values obtained via Interop.Sys.GetLastError() not Marshal.GetLastWin32Error() + // which obtains the raw errno that varies between unixes. The strong typing as an enum is meant to + // prevent confusing the two. Casting to or from int is suspect. Use GetLastErrorInfo() if you need to + // correlate these to the underlying platform values or obtain the corresponding error message. + // + + SUCCESS = 0, + + E2BIG = 0x10001, // Argument list too long. + EACCES = 0x10002, // Permission denied. + EADDRINUSE = 0x10003, // Address in use. + EADDRNOTAVAIL = 0x10004, // Address not available. + EAFNOSUPPORT = 0x10005, // Address family not supported. + EAGAIN = 0x10006, // Resource unavailable, try again (same value as EWOULDBLOCK), + EALREADY = 0x10007, // Connection already in progress. + EBADF = 0x10008, // Bad file descriptor. + EBADMSG = 0x10009, // Bad message. + EBUSY = 0x1000A, // Device or resource busy. + ECANCELED = 0x1000B, // Operation canceled. + ECHILD = 0x1000C, // No child processes. + ECONNABORTED = 0x1000D, // Connection aborted. + ECONNREFUSED = 0x1000E, // Connection refused. + ECONNRESET = 0x1000F, // Connection reset. + EDEADLK = 0x10010, // Resource deadlock would occur. + EDESTADDRREQ = 0x10011, // Destination address required. + EDOM = 0x10012, // Mathematics argument out of domain of function. + EDQUOT = 0x10013, // Reserved. + EEXIST = 0x10014, // File exists. + EFAULT = 0x10015, // Bad address. + EFBIG = 0x10016, // File too large. + EHOSTUNREACH = 0x10017, // Host is unreachable. + EIDRM = 0x10018, // Identifier removed. + EILSEQ = 0x10019, // Illegal byte sequence. + EINPROGRESS = 0x1001A, // Operation in progress. + EINTR = 0x1001B, // Interrupted function. + EINVAL = 0x1001C, // Invalid argument. + EIO = 0x1001D, // I/O error. + EISCONN = 0x1001E, // Socket is connected. + EISDIR = 0x1001F, // Is a directory. + ELOOP = 0x10020, // Too many levels of symbolic links. + EMFILE = 0x10021, // File descriptor value too large. + EMLINK = 0x10022, // Too many links. + EMSGSIZE = 0x10023, // Message too large. + EMULTIHOP = 0x10024, // Reserved. + ENAMETOOLONG = 0x10025, // Filename too long. + ENETDOWN = 0x10026, // Network is down. + ENETRESET = 0x10027, // Connection aborted by network. + ENETUNREACH = 0x10028, // Network unreachable. + ENFILE = 0x10029, // Too many files open in system. + ENOBUFS = 0x1002A, // No buffer space available. + ENODEV = 0x1002C, // No such device. + ENOENT = 0x1002D, // No such file or directory. + ENOEXEC = 0x1002E, // Executable file format error. + ENOLCK = 0x1002F, // No locks available. + ENOLINK = 0x10030, // Reserved. + ENOMEM = 0x10031, // Not enough space. + ENOMSG = 0x10032, // No message of the desired type. + ENOPROTOOPT = 0x10033, // Protocol not available. + ENOSPC = 0x10034, // No space left on device. + ENOSYS = 0x10037, // Function not supported. + ENOTCONN = 0x10038, // The socket is not connected. + ENOTDIR = 0x10039, // Not a directory or a symbolic link to a directory. + ENOTEMPTY = 0x1003A, // Directory not empty. + ENOTSOCK = 0x1003C, // Not a socket. + ENOTSUP = 0x1003D, // Not supported (same value as EOPNOTSUP). + ENOTTY = 0x1003E, // Inappropriate I/O control operation. + ENXIO = 0x1003F, // No such device or address. + EOVERFLOW = 0x10040, // Value too large to be stored in data type. + EPERM = 0x10042, // Operation not permitted. + EPIPE = 0x10043, // Broken pipe. + EPROTO = 0x10044, // Protocol error. + EPROTONOSUPPORT = 0x10045, // Protocol not supported. + EPROTOTYPE = 0x10046, // Protocol wrong type for socket. + ERANGE = 0x10047, // Result too large. + EROFS = 0x10048, // Read-only file system. + ESPIPE = 0x10049, // Invalid seek. + ESRCH = 0x1004A, // No such process. + ESTALE = 0x1004B, // Reserved. + ETIMEDOUT = 0x1004D, // Connection timed out. + ETXTBSY = 0x1004E, // Text file busy. + EXDEV = 0x1004F, // Cross-device link. + ESOCKTNOSUPPORT = 0x1005E, // Socket type not supported. + EPFNOSUPPORT = 0x10060, // Protocol family not supported. + ESHUTDOWN = 0x1006C, // Socket shutdown. + EHOSTDOWN = 0x10070, // Host is down. + ENODATA = 0x10071, // No data available. + + // POSIX permits these to have the same value and we make them always equal so + // that CoreFX cannot introduce a dependency on distinguishing between them that + // would not work on all platforms. + EOPNOTSUPP = ENOTSUP, // Operation not supported on socket. + EWOULDBLOCK = EAGAIN, // Operation would block. + } + + + // Represents a platform-agnostic Error and underlying platform-specific errno + internal struct ErrorInfo + { + private Error _error; + private int _rawErrno; + + internal ErrorInfo(int errno) + { + _error = Interop.Sys.ConvertErrorPlatformToPal(errno); + _rawErrno = errno; + } + + internal ErrorInfo(Error error) + { + _error = error; + _rawErrno = -1; + } + + internal Error Error + { + get { return _error; } + } + + internal int RawErrno + { + get { return _rawErrno == -1 ? (_rawErrno = Interop.Sys.ConvertErrorPalToPlatform(_error)) : _rawErrno; } + } + + internal string GetErrorMessage() + { + return Interop.Sys.StrError(RawErrno); + } + + public override string ToString() + { + return string.Format( + "RawErrno: {0} Error: {1} GetErrorMessage: {2}", // No localization required; text is member names used for debugging purposes + RawErrno, Error, GetErrorMessage()); + } + } + + internal partial class Sys + { + internal static Error GetLastError() + { + return ConvertErrorPlatformToPal(Marshal.GetLastWin32Error()); + } + + internal static ErrorInfo GetLastErrorInfo() + { + return new ErrorInfo(Marshal.GetLastWin32Error()); + } + + internal static unsafe string StrError(int platformErrno) + { + int maxBufferLength = 1024; // should be long enough for most any UNIX error + byte* buffer = stackalloc byte[maxBufferLength]; + byte* message = StrErrorR(platformErrno, buffer, maxBufferLength); + + if (message == null) + { + // This means the buffer was not large enough, but still contains + // as much of the error message as possible and is guaranteed to + // be null-terminated. We're not currently resizing/retrying because + // maxBufferLength is large enough in practice, but we could do + // so here in the future if necessary. + message = buffer; + } + + return Marshal.PtrToStringAnsi((IntPtr)message); + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPlatformToPal")] + internal static extern Error ConvertErrorPlatformToPal(int platformErrno); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPalToPlatform")] + internal static extern int ConvertErrorPalToPlatform(Error error); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StrErrorR")] + private static unsafe extern byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize); + } +} + +// NOTE: extension method can't be nested inside Interop class. +internal static class InteropErrorExtensions +{ + // Intended usage is e.g. Interop.Error.EFAIL.Info() for brevity + // vs. new Interop.ErrorInfo(Interop.Error.EFAIL) for synthesizing + // errors. Errors originated from the system should be obtained + // via GetLastErrorInfo(), not GetLastError().Info() as that will + // convert twice, which is not only inefficient but also lossy if + // we ever encounter a raw errno that no equivalent in the Error + // enum. + public static Interop.ErrorInfo Info(this Interop.Error error) + { + return new Interop.ErrorInfo(error); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs b/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs new file mode 100644 index 0000000000..e9d6ce61d6 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string path, bool isDirectory, Func<ErrorInfo, ErrorInfo> errorRewriter) + { + Debug.Assert(errorInfo.Error != Error.SUCCESS); + Debug.Assert(errorInfo.Error != Error.EINTR, "EINTR errors should be handled by the native shim and never bubble up to managed code"); + + if (errorRewriter != null) + { + errorInfo = errorRewriter(errorInfo); + } + + throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory); + } + + internal static void CheckIo(Error error, string path = null, bool isDirectory = false, Func<ErrorInfo, ErrorInfo> errorRewriter = null) + { + if (error != Interop.Error.SUCCESS) + { + ThrowExceptionForIoErrno(error.Info(), path, isDirectory, errorRewriter); + } + } + + /// <summary> + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// </summary> + /// <param name="result">The result of the system call.</param> + /// <param name="path">The path with which this error is associated. This may be null.</param> + /// <param name="isDirectory">true if the <paramref name="path"/> is known to be a directory; otherwise, false.</param> + /// <param name="errorRewriter">Optional function to change an error code prior to processing it.</param> + /// <returns> + /// On success, returns the non-negative result long that was validated. + /// </returns> + internal static long CheckIo(long result, string path = null, bool isDirectory = false, Func<ErrorInfo, ErrorInfo> errorRewriter = null) + { + if (result < 0) + { + ThrowExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirectory, errorRewriter); + } + + return result; + } + + /// <summary> + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// </summary> + /// <returns> + /// On success, returns the non-negative result int that was validated. + /// </returns> + internal static int CheckIo(int result, string path = null, bool isDirectory = false, Func<ErrorInfo, ErrorInfo> errorRewriter = null) + { + CheckIo((long)result, path, isDirectory, errorRewriter); + + return result; + } + + /// <summary> + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// </summary> + /// <returns> + /// On success, returns the non-negative result IntPtr that was validated. + /// </returns> + internal static IntPtr CheckIo(IntPtr result, string path = null, bool isDirectory = false, Func<ErrorInfo, ErrorInfo> errorRewriter = null) + { + CheckIo((long)result, path, isDirectory, errorRewriter); + + return result; + } + + /// <summary> + /// Validates the result of system call that returns greater than or equal to 0 on success + /// and less than 0 on failure, with errno set to the error code. + /// If the system call failed for any reason, an exception is thrown. Otherwise, the system call succeeded. + /// </summary> + /// <returns> + /// On success, returns the valid SafeFileHandle that was validated. + /// </returns> + internal static TSafeHandle CheckIo<TSafeHandle>(TSafeHandle handle, string path = null, bool isDirectory = false, Func<ErrorInfo, ErrorInfo> errorRewriter = null) + where TSafeHandle : SafeHandle + { + if (handle.IsInvalid) + { + ThrowExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirectory, errorRewriter); + } + + return handle; + } + + /// <summary> + /// Gets an Exception to represent the supplied error info. + /// </summary> + /// <param name="error">The error info</param> + /// <param name="path">The path with which this error is associated. This may be null.</param> + /// <param name="isDirectory">true if the <paramref name="path"/> is known to be a directory; otherwise, false.</param> + /// <returns></returns> + internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string path = null, bool isDirectory = false) + { + // Translate the errno into a known set of exception types. For cases where multiple errnos map + // to the same exception type, include an inner exception with the details. + switch (errorInfo.Error) + { + case Error.ENOENT: + if (isDirectory) + { + return !string.IsNullOrEmpty(path) ? + new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)) : + new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName); + } + else + { + return !string.IsNullOrEmpty(path) ? + new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path) : + new FileNotFoundException(SR.IO_FileNotFound); + } + + case Error.EACCES: + case Error.EBADF: + case Error.EPERM: + Exception inner = GetIOException(errorInfo); + return !string.IsNullOrEmpty(path) ? + new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path), inner) : + new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName, inner); + + case Error.ENAMETOOLONG: + return new PathTooLongException(SR.IO_PathTooLong); + + case Error.EWOULDBLOCK: + return !string.IsNullOrEmpty(path) ? + new IOException(SR.Format(SR.IO_SharingViolation_File, path), errorInfo.RawErrno) : + new IOException(SR.IO_SharingViolation_NoFileName, errorInfo.RawErrno); + + case Error.ECANCELED: + return new OperationCanceledException(); + + case Error.EFBIG: + return new ArgumentOutOfRangeException("value", SR.ArgumentOutOfRange_FileLengthTooBig); + + case Error.EEXIST: + if (!string.IsNullOrEmpty(path)) + { + return new IOException(SR.Format(SR.IO_FileExists_Name, path), errorInfo.RawErrno); + } + goto default; + + default: + return GetIOException(errorInfo); + } + } + + internal static Exception GetIOException(Interop.ErrorInfo errorInfo) + { + return new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/Interop.Libraries.cs b/src/mscorlib/shared/Interop/Unix/Interop.Libraries.cs new file mode 100644 index 0000000000..7b3dea453d --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/Interop.Libraries.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class Libraries + { + internal const string GlobalizationInterop = "System.Globalization.Native"; + internal const string SystemNative = "System.Native"; + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs new file mode 100644 index 0000000000..7b3caeabdd --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Text; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + internal delegate void EnumCalendarInfoCallback( + [MarshalAs(UnmanagedType.LPWStr)] string calendarString, + IntPtr context); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetCalendars")] + internal static extern int GetCalendars(string localeName, CalendarId[] calendars, int calendarsCapacity); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetCalendarInfo")] + internal static extern ResultCode GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType calendarDataType, [Out] StringBuilder result, int resultCapacity); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_EnumCalendarInfo")] + internal static extern bool EnumCalendarInfo(EnumCalendarInfoCallback callback, string localeName, CalendarId calendarId, CalendarDataType calendarDataType, IntPtr context); + + [DllImport(Libraries.GlobalizationInterop, EntryPoint = "GlobalizationNative_GetLatestJapaneseEra")] + internal static extern int GetLatestJapaneseEra(); + + [DllImport(Libraries.GlobalizationInterop, EntryPoint = "GlobalizationNative_GetJapaneseEraStartDate")] + internal static extern bool GetJapaneseEraStartDate(int era, out int startYear, out int startMonth, out int startDay); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs new file mode 100644 index 0000000000..769506b8f6 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCase")] + internal unsafe static extern void ChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCaseInvariant")] + internal unsafe static extern void ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCaseTurkish")] + internal unsafe static extern void ChangeCaseTurkish(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs new file mode 100644 index 0000000000..43c72281ae --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + internal const int AllowUnassigned = 0x1; + internal const int UseStd3AsciiRules = 0x2; + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToAscii")] + internal static unsafe extern int ToAscii(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToUnicode")] + internal static unsafe extern int ToUnicode(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs new file mode 100644 index 0000000000..fcea708ee8 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Text; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleName")] + [return: MarshalAs(UnmanagedType.Bool)] + internal unsafe static extern bool GetLocaleName(string localeName, [Out] StringBuilder value, int valueLength); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoString")] + [return: MarshalAs(UnmanagedType.Bool)] + internal unsafe static extern bool GetLocaleInfoString(string localeName, uint localeStringData, [Out] StringBuilder value, int valueLength); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetDefaultLocaleName")] + [return: MarshalAs(UnmanagedType.Bool)] + internal unsafe static extern bool GetDefaultLocaleName([Out] StringBuilder value, int valueLength); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleTimeFormat")] + [return: MarshalAs(UnmanagedType.Bool)] + internal unsafe static extern bool GetLocaleTimeFormat(string localeName, bool shortFormat, [Out] StringBuilder value, int valueLength); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoInt")] + [return: MarshalAs(UnmanagedType.Bool)] + internal unsafe static extern bool GetLocaleInfoInt(string localeName, uint localeNumberData, ref int value); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoGroupingSizes")] + [return: MarshalAs(UnmanagedType.Bool)] + internal unsafe static extern bool GetLocaleInfoGroupingSizes(string localeName, uint localeGroupingData, ref int primaryGroupSize, ref int secondaryGroupSize); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocales")] + internal unsafe static extern int GetLocales([Out] Char[] value, int valueLength); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs new file mode 100644 index 0000000000..c4cb9fb851 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Normalization.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Text; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IsNormalized")] + internal static extern int IsNormalized(NormalizationForm normalizationForm, string src, int srcLen); + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_NormalizeString")] + internal static extern int NormalizeString(NormalizationForm normalizationForm, string src, int srcLen, [Out] char[] dstBuffer, int dstBufferCapacity); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs new file mode 100644 index 0000000000..cca6ae4dcb --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + // needs to be kept in sync with ResultCode in System.Globalization.Native + internal enum ResultCode + { + Success = 0, + UnknownError = 1, + InsufficentBuffer = 2, + OutOfMemory = 3 + } + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs new file mode 100644 index 0000000000..26a9fe0579 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using System.Text; + +internal static partial class Interop +{ + internal static partial class GlobalizationInterop + { + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Ansi, EntryPoint = "GlobalizationNative_ReadLink")] // readlink requires char* + internal static extern bool ReadLink(string filePath, [Out] StringBuilder result, uint resultCapacity); + + // needs to be kept in sync with TimeZoneDisplayNameType in System.Globalization.Native + internal enum TimeZoneDisplayNameType + { + Generic = 0, + Standard = 1, + DaylightSavings = 2, + } + + [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetTimeZoneDisplayName")] + internal static extern ResultCode GetTimeZoneDisplayName( + string localeName, + string timeZoneId, + TimeZoneDisplayNameType type, + [Out] StringBuilder result, + int resultLength); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs new file mode 100644 index 0000000000..33b10c0d74 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Globalization.Native/Interop.Utils.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; + +internal static partial class Interop +{ + /// <summary> + /// Helper for making interop calls that return a string, but we don't know + /// the correct size of buffer to make. So invoke the interop call with an + /// increasing buffer until the size is big enough. + /// </summary> + internal static bool CallStringMethod<TArg1, TArg2, TArg3>( + Func<TArg1, TArg2, TArg3, StringBuilder, GlobalizationInterop.ResultCode> interopCall, + TArg1 arg1, + TArg2 arg2, + TArg3 arg3, + out string result) + { + const int initialStringSize = 80; + const int maxDoubleAttempts = 5; + + StringBuilder stringBuilder = StringBuilderCache.Acquire(initialStringSize); + + for (int i = 0; i < maxDoubleAttempts; i++) + { + GlobalizationInterop.ResultCode resultCode = interopCall(arg1, arg2, arg3, stringBuilder); + + if (resultCode == GlobalizationInterop.ResultCode.Success) + { + result = StringBuilderCache.GetStringAndRelease(stringBuilder); + return true; + } + else if (resultCode == GlobalizationInterop.ResultCode.InsufficentBuffer) + { + // increase the string size and loop + stringBuilder.EnsureCapacity(stringBuilder.Capacity * 2); + } + else + { + // if there is an unknown error, don't proceed + break; + } + } + + StringBuilderCache.Release(stringBuilder); + result = null; + return false; + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Close.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Close.cs new file mode 100644 index 0000000000..8d192398a0 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Close.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Close", SetLastError = true)] + internal static extern int Close(IntPtr fd); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FLock.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FLock.cs new file mode 100644 index 0000000000..22934a3e77 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FLock.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum LockOperations : int + { + LOCK_SH = 1, /* shared lock */ + LOCK_EX = 2, /* exclusive lock */ + LOCK_NB = 4, /* don't block when locking*/ + LOCK_UN = 8, /* unlock */ + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] + internal static extern int FLock(SafeFileHandle fd, LockOperations operation); + + /// <summary> + /// Exposing this for SafeFileHandle.ReleaseHandle() to call. + /// Normal callers should use FLock(SafeFileHandle fd). + /// </summary> + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] + internal static extern int FLock(IntPtr fd, LockOperations operation); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FSync.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FSync.cs new file mode 100644 index 0000000000..e3ab970931 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FSync.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FSync", SetLastError = true)] + internal static extern int FSync(SafeFileHandle fd); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FTruncate.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FTruncate.cs new file mode 100644 index 0000000000..5dad650362 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.FTruncate.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FTruncate", SetLastError = true)] + internal static extern int FTruncate(SafeFileHandle fd, long length); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.GetCwd.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.GetCwd.cs new file mode 100644 index 0000000000..a27a35c9f5 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.GetCwd.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetCwd", SetLastError = true)] + private static unsafe extern byte* GetCwd(byte* buffer, int bufferLength); + + internal static unsafe string GetCwd() + { + const int StackLimit = 256; + + // First try to get the path into a buffer on the stack + byte* stackBuf = stackalloc byte[StackLimit]; + string result = GetCwdHelper(stackBuf, StackLimit); + if (result != null) + { + return result; + } + + // If that was too small, try increasing large buffer sizes + // until we get one that works or until we hit MaxPath. + int maxPath = Interop.Sys.MaxPath; + if (StackLimit < maxPath) + { + int bufferSize = StackLimit; + do + { + checked { bufferSize *= 2; } + var buf = new byte[Math.Min(bufferSize, maxPath)]; + fixed (byte* ptr = &buf[0]) + { + result = GetCwdHelper(ptr, buf.Length); + if (result != null) + { + return result; + } + } + } + while (bufferSize < maxPath); + } + + // If we couldn't get the cwd with a MaxPath-sized buffer, something's wrong. + throw Interop.GetExceptionForIoErrno(new ErrorInfo(Interop.Error.ENAMETOOLONG)); + } + + private static unsafe string GetCwdHelper(byte* ptr, int bufferSize) + { + // Call the real getcwd + byte* result = GetCwd(ptr, bufferSize); + + // If it returned non-null, the null-terminated path is in the buffer + if (result != null) + { + return Marshal.PtrToStringAnsi((IntPtr)ptr); + } + + // Otherwise, if it failed due to the buffer being too small, return null; + // for anything else, throw. + ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + if (errorInfo.Error == Interop.Error.ERANGE) + { + return null; + } + throw Interop.GetExceptionForIoErrno(errorInfo); + } + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs new file mode 100644 index 0000000000..62156e8d8e --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +internal partial class Interop +{ + internal unsafe partial class Sys + { + [DllImport(Interop.Libraries.SystemNative, EntryPoint = "SystemNative_GetNonCryptographicallySecureRandomBytes")] + internal static unsafe extern void GetNonCryptographicallySecureRandomBytes(byte* buffer, int length); + } + + internal static unsafe void GetRandomBytes(byte* buffer, int length) + { + Sys.GetNonCryptographicallySecureRandomBytes(buffer, length); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.LSeek.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.LSeek.cs new file mode 100644 index 0000000000..7f8df7c6bf --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.LSeek.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum SeekWhence + { + SEEK_SET = 0, + SEEK_CUR = 1, + SEEK_END = 2 + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LSeek", SetLastError = true)] + internal static extern long LSeek(SafeFileHandle fd, long offset, SeekWhence whence); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.LockFileRegion.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.LockFileRegion.cs new file mode 100644 index 0000000000..23b48a4f5d --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.LockFileRegion.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum LockType : short + { + F_WRLCK = 1, // exclusive or write lock + F_UNLCK = 2 // unlock + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LockFileRegion", SetLastError=true)] + internal static extern int LockFileRegion(SafeHandle fd, long offset, long length, LockType lockType); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.MksTemps.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.MksTemps.cs new file mode 100644 index 0000000000..b8694d9007 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.MksTemps.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MksTemps", SetLastError = true)] + internal static extern IntPtr MksTemps( + byte[] template, + int suffixlen); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Open.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Open.cs new file mode 100644 index 0000000000..a9a994c78c --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Open.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Open", SetLastError = true)] + internal static extern SafeFileHandle Open(string filename, OpenFlags flags, int mode); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.OpenFlags.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.OpenFlags.cs new file mode 100644 index 0000000000..f9e54c3cbc --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.OpenFlags.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +internal static partial class Interop +{ + internal static partial class Sys + { + [Flags] + internal enum OpenFlags + { + // Access modes (mutually exclusive) + O_RDONLY = 0x0000, + O_WRONLY = 0x0001, + O_RDWR = 0x0002, + + // Flags (combinable) + O_CLOEXEC = 0x0010, + O_CREAT = 0x0020, + O_EXCL = 0x0040, + O_TRUNC = 0x0080, + O_SYNC = 0x0100, + } + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PathConf.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PathConf.cs new file mode 100644 index 0000000000..4a1fcf67d0 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PathConf.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal static int DEFAULT_PC_NAME_MAX = 255; + + internal enum PathConfName : int + { + PC_LINK_MAX = 1, + PC_MAX_CANON = 2, + PC_MAX_INPUT = 3, + PC_NAME_MAX = 4, + PC_PATH_MAX = 5, + PC_PIPE_BUF = 6, + PC_CHOWN_RESTRICTED = 7, + PC_NO_TRUNC = 8, + PC_VDISABLE = 9, + } + + /// <summary>The maximum path length for the system. -1 if it hasn't yet been initialized.</summary> + private static int s_maxPath = -1; + + /// <summary>The maximum name length for the system. -1 if it hasn't yet been initialized.</summary> + private static int s_maxName = -1; + + internal static int MaxPath + { + get + { + // Benign race condition on cached value + if (s_maxPath < 0) + { + // GetMaximumPath returns a long from PathConf + // but our callers expect an int so we need to convert. + long temp = GetMaximumPath(); + if (temp > int.MaxValue) + s_maxPath = int.MaxValue; + else + s_maxPath = Convert.ToInt32(temp); + } + return s_maxPath; + } + } + + internal static int MaxName + { + get + { + // Benign race condition on cached value + if (s_maxName < 0) + { + int result = PathConf("/", PathConfName.PC_NAME_MAX); + s_maxName = result >= 0 ? result : DEFAULT_PC_NAME_MAX; + } + + return s_maxName; + } + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PathConf", SetLastError = true)] + private static extern int PathConf(string path, PathConfName name); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetMaximumPath")] + private static extern long GetMaximumPath(); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Permissions.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Permissions.cs new file mode 100644 index 0000000000..f1d13787d2 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Permissions.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +internal static partial class Interop +{ + internal static partial class Sys + { + [Flags] + internal enum Permissions + { + Mask = S_IRWXU | S_IRWXG | S_IRWXO, + + S_IRWXU = S_IRUSR | S_IWUSR | S_IXUSR, + S_IRUSR = 0x100, + S_IWUSR = 0x80, + S_IXUSR = 0x40, + + S_IRWXG = S_IRGRP | S_IWGRP | S_IXGRP, + S_IRGRP = 0x20, + S_IWGRP = 0x10, + S_IXGRP = 0x8, + + S_IRWXO = S_IROTH | S_IWOTH | S_IXOTH, + S_IROTH = 0x4, + S_IWOTH = 0x2, + S_IXOTH = 0x1, + } + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs new file mode 100644 index 0000000000..69e39b30d2 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.PosixFAdvise.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum FileAdvice : int + { + POSIX_FADV_NORMAL = 0, /* no special advice, the default value */ + POSIX_FADV_RANDOM = 1, /* random I/O access */ + POSIX_FADV_SEQUENTIAL = 2, /* sequential I/O access */ + POSIX_FADV_WILLNEED = 3, /* will need specified pages */ + POSIX_FADV_DONTNEED = 4, /* don't need the specified pages */ + POSIX_FADV_NOREUSE = 5, /* data will only be acessed once */ + } + + /// <summary> + /// Notifies the OS kernel that the specified file will be accessed in a particular way soon; this allows the kernel to + /// potentially optimize the access pattern of the file. + /// </summary> + /// <param name="fd">The file descriptor of the file</param> + /// <param name="offset">The start of the region to advise about</param> + /// <param name="length">The number of bytes of the region (until the end of the file if 0)</param> + /// <param name="advice">The type of advice to give the kernel about the specified region</param> + /// <returns> + /// Returns 0 on success; otherwise, the error code is returned + /// </returns> + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PosixFAdvise", SetLastError = false /* this is explicitly called out in the man page */)] + internal static extern int PosixFAdvise(SafeFileHandle fd, long offset, long length, FileAdvice advice); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Read.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Read.cs new file mode 100644 index 0000000000..812ae348dc --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Read.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + /// <summary> + /// Reads a number of bytes from an open file descriptor into a specified buffer. + /// </summary> + /// <param name="fd">The open file descriptor to try to read from</param> + /// <param name="buffer">The buffer to read info into</param> + /// <param name="count">The size of the buffer</param> + /// <returns> + /// Returns the number of bytes read on success; otherwise, -1 is returned + /// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info + /// </returns> + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)] + internal static unsafe extern int Read(SafeFileHandle fd, byte* buffer, int count); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs new file mode 100644 index 0000000000..a8bc2ec7d1 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + // Even though csc will by default use a sequential layout, a CS0649 warning as error + // is produced for un-assigned fields when no StructLayout is specified. + // + // Explicitly saying Sequential disables that warning/error for consumers which only + // use Stat in debug builds. + [StructLayout(LayoutKind.Sequential)] + internal struct FileStatus + { + internal FileStatusFlags Flags; + internal int Mode; + internal uint Uid; + internal uint Gid; + internal long Size; + internal long ATime; + internal long MTime; + internal long CTime; + internal long BirthTime; + } + + internal static class FileTypes + { + internal const int S_IFMT = 0xF000; + internal const int S_IFIFO = 0x1000; + internal const int S_IFCHR = 0x2000; + internal const int S_IFDIR = 0x4000; + internal const int S_IFREG = 0x8000; + internal const int S_IFLNK = 0xA000; + internal const int S_IFSOCK = 0xC000; + } + + [Flags] + internal enum FileStatusFlags + { + None = 0, + HasBirthTime = 1, + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] + internal static extern int FStat(SafeFileHandle fd, out FileStatus output); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", SetLastError = true)] + internal static extern int Stat(string path, out FileStatus output); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", SetLastError = true)] + internal static extern int LStat(string path, out FileStatus output); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.SysLog.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.SysLog.cs new file mode 100644 index 0000000000..6b6a74b743 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.SysLog.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal enum SysLogPriority : int + { + // Priorities + LOG_EMERG = 0, /* system is unusable */ + LOG_ALERT = 1, /* action must be taken immediately */ + LOG_CRIT = 2, /* critical conditions */ + LOG_ERR = 3, /* error conditions */ + LOG_WARNING = 4, /* warning conditions */ + LOG_NOTICE = 5, /* normal but significant condition */ + LOG_INFO = 6, /* informational */ + LOG_DEBUG = 7, /* debug-level messages */ + // Facilities + LOG_KERN = (0<<3), /* kernel messages */ + LOG_USER = (1<<3), /* random user-level messages */ + LOG_MAIL = (2<<3), /* mail system */ + LOG_DAEMON = (3<<3), /* system daemons */ + LOG_AUTH = (4<<3), /* authorization messages */ + LOG_SYSLOG = (5<<3), /* messages generated internally by syslogd */ + LOG_LPR = (6<<3), /* line printer subsystem */ + LOG_NEWS = (7<<3), /* network news subsystem */ + LOG_UUCP = (8<<3), /* UUCP subsystem */ + LOG_CRON = (9<<3), /* clock daemon */ + LOG_AUTHPRIV = (10<<3), /* authorization messages (private) */ + LOG_FTP = (11<<3), /* ftp daemon */ + // Between FTP and Local is reserved for system use + LOG_LOCAL0 = (16<<3), /* reserved for local use */ + LOG_LOCAL1 = (17<<3), /* reserved for local use */ + LOG_LOCAL2 = (18<<3), /* reserved for local use */ + LOG_LOCAL3 = (19<<3), /* reserved for local use */ + LOG_LOCAL4 = (20<<3), /* reserved for local use */ + LOG_LOCAL5 = (21<<3), /* reserved for local use */ + LOG_LOCAL6 = (22<<3), /* reserved for local use */ + LOG_LOCAL7 = (23<<3), /* reserved for local use */ + } + + /// <summary> + /// Write a message to the system logger, which in turn writes the message to the system console, log files, etc. + /// See man 3 syslog for more info + /// </summary> + /// <param name="priority"> + /// The OR of a priority and facility in the SysLogPriority enum to declare the priority and facility of the log entry + /// </param> + /// <param name="message">The message to put in the log entry</param> + /// <param name="arg1">Like printf, the argument is passed to the variadic part of the C++ function to wildcards in the message</param> + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SysLog")] + internal static extern void SysLog(SysLogPriority priority, string message, string arg1); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Unlink.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Unlink.cs new file mode 100644 index 0000000000..829210fa7e --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Unlink.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Unlink", SetLastError = true)] + internal static extern int Unlink(string pathname); + } +} diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Write.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Write.cs new file mode 100644 index 0000000000..c14fc26263 --- /dev/null +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Write.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + /// <summary> + /// Writes the specified buffer to the provided open file descriptor + /// </summary> + /// <param name="fd">The file descriptor to try and write to</param> + /// <param name="buffer">The data to attempt to write</param> + /// <param name="bufferSize">The amount of data to write, in bytes</param> + /// <returns> + /// Returns the number of bytes written on success; otherwise, returns -1 and sets errno + /// </returns> + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe extern int Write(SafeFileHandle fd, byte* buffer, int bufferSize); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe extern int Write(int fd, byte* buffer, int bufferSize); + } +} |