// // Mono.Unix/Stdlib.cs // // Authors: // Jonathan Pryor (jonpryor@vt.edu) // // (C) 2004-2006 Jonathan Pryor // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Text; using Mono.Unix.Native; namespace Mono.Unix.Native { #region Enumerations [Map] public enum Errno : Int32 { // errors & their values liberally copied from // FC2 /usr/include/asm/errno.h EPERM = 1, // Operation not permitted ENOENT = 2, // No such file or directory ESRCH = 3, // No such process EINTR = 4, // Interrupted system call EIO = 5, // I/O error ENXIO = 6, // No such device or address E2BIG = 7, // Arg list too long ENOEXEC = 8, // Exec format error EBADF = 9, // Bad file number ECHILD = 10, // No child processes EAGAIN = 11, // Try again ENOMEM = 12, // Out of memory EACCES = 13, // Permission denied EFAULT = 14, // Bad address ENOTBLK = 15, // Block device required EBUSY = 16, // Device or resource busy EEXIST = 17, // File exists EXDEV = 18, // Cross-device link ENODEV = 19, // No such device ENOTDIR = 20, // Not a directory EISDIR = 21, // Is a directory EINVAL = 22, // Invalid argument ENFILE = 23, // File table overflow EMFILE = 24, // Too many open files ENOTTY = 25, // Not a typewriter ETXTBSY = 26, // Text file busy EFBIG = 27, // File too large ENOSPC = 28, // No space left on device ESPIPE = 29, // Illegal seek EROFS = 30, // Read-only file system EMLINK = 31, // Too many links EPIPE = 32, // Broken pipe EDOM = 33, // Math argument out of domain of func ERANGE = 34, // Math result not representable EDEADLK = 35, // Resource deadlock would occur ENAMETOOLONG = 36, // File name too long ENOLCK = 37, // No record locks available ENOSYS = 38, // Function not implemented ENOTEMPTY = 39, // Directory not empty ELOOP = 40, // Too many symbolic links encountered EWOULDBLOCK = EAGAIN, // Operation would block ENOMSG = 42, // No message of desired type EIDRM = 43, // Identifier removed ECHRNG = 44, // Channel number out of range EL2NSYNC = 45, // Level 2 not synchronized EL3HLT = 46, // Level 3 halted EL3RST = 47, // Level 3 reset ELNRNG = 48, // Link number out of range EUNATCH = 49, // Protocol driver not attached ENOCSI = 50, // No CSI structure available EL2HLT = 51, // Level 2 halted EBADE = 52, // Invalid exchange EBADR = 53, // Invalid request descriptor EXFULL = 54, // Exchange full ENOANO = 55, // No anode EBADRQC = 56, // Invalid request code EBADSLT = 57, // Invalid slot EDEADLOCK = EDEADLK, EBFONT = 59, // Bad font file format ENOSTR = 60, // Device not a stream ENODATA = 61, // No data available ETIME = 62, // Timer expired ENOSR = 63, // Out of streams resources ENONET = 64, // Machine is not on the network ENOPKG = 65, // Package not installed EREMOTE = 66, // Object is remote ENOLINK = 67, // Link has been severed EADV = 68, // Advertise error ESRMNT = 69, // Srmount error ECOMM = 70, // Communication error on send EPROTO = 71, // Protocol error EMULTIHOP = 72, // Multihop attempted EDOTDOT = 73, // RFS specific error EBADMSG = 74, // Not a data message EOVERFLOW = 75, // Value too large for defined data type ENOTUNIQ = 76, // Name not unique on network EBADFD = 77, // File descriptor in bad state EREMCHG = 78, // Remote address changed ELIBACC = 79, // Can not access a needed shared library ELIBBAD = 80, // Accessing a corrupted shared library ELIBSCN = 81, // .lib section in a.out corrupted ELIBMAX = 82, // Attempting to link in too many shared libraries ELIBEXEC = 83, // Cannot exec a shared library directly EILSEQ = 84, // Illegal byte sequence ERESTART = 85, // Interrupted system call should be restarted ESTRPIPE = 86, // Streams pipe error EUSERS = 87, // Too many users ENOTSOCK = 88, // Socket operation on non-socket EDESTADDRREQ = 89, // Destination address required EMSGSIZE = 90, // Message too long EPROTOTYPE = 91, // Protocol wrong type for socket ENOPROTOOPT = 92, // Protocol not available EPROTONOSUPPORT = 93, // Protocol not supported ESOCKTNOSUPPORT = 94, // Socket type not supported EOPNOTSUPP = 95, // Operation not supported on transport endpoint EPFNOSUPPORT = 96, // Protocol family not supported EAFNOSUPPORT = 97, // Address family not supported by protocol EADDRINUSE = 98, // Address already in use EADDRNOTAVAIL = 99, // Cannot assign requested address ENETDOWN = 100, // Network is down ENETUNREACH = 101, // Network is unreachable ENETRESET = 102, // Network dropped connection because of reset ECONNABORTED = 103, // Software caused connection abort ECONNRESET = 104, // Connection reset by peer ENOBUFS = 105, // No buffer space available EISCONN = 106, // Transport endpoint is already connected ENOTCONN = 107, // Transport endpoint is not connected ESHUTDOWN = 108, // Cannot send after transport endpoint shutdown ETOOMANYREFS = 109, // Too many references: cannot splice ETIMEDOUT = 110, // Connection timed out ECONNREFUSED = 111, // Connection refused EHOSTDOWN = 112, // Host is down EHOSTUNREACH = 113, // No route to host EALREADY = 114, // Operation already in progress EINPROGRESS = 115, // Operation now in progress ESTALE = 116, // Stale NFS file handle EUCLEAN = 117, // Structure needs cleaning ENOTNAM = 118, // Not a XENIX named type file ENAVAIL = 119, // No XENIX semaphores available EISNAM = 120, // Is a named type file EREMOTEIO = 121, // Remote I/O error EDQUOT = 122, // Quota exceeded ENOMEDIUM = 123, // No medium found EMEDIUMTYPE = 124, // Wrong medium type ECANCELED = 125, ENOKEY = 126, EKEYEXPIRED = 127, EKEYREVOKED = 128, EKEYREJECTED = 129, EOWNERDEAD = 130, ENOTRECOVERABLE = 131, // OS X-specific values: OS X value + 1000 EPROCLIM = 1067, // Too many processes EBADRPC = 1072, // RPC struct is bad ERPCMISMATCH = 1073, // RPC version wrong EPROGUNAVAIL = 1074, // RPC prog. not avail EPROGMISMATCH = 1075, // Program version wrong EPROCUNAVAIL = 1076, // Bad procedure for program EFTYPE = 1079, // Inappropriate file type or format EAUTH = 1080, // Authentication error ENEEDAUTH = 1081, // Need authenticator EPWROFF = 1082, // Device power is off EDEVERR = 1083, // Device error, e.g. paper out EBADEXEC = 1085, // Bad executable EBADARCH = 1086, // Bad CPU type in executable ESHLIBVERS = 1087, // Shared library version mismatch EBADMACHO = 1088, // Malformed Macho file ENOATTR = 1093, // Attribute not found ENOPOLICY = 1103, // No such policy registered } #endregion #region Classes public sealed class FilePosition : MarshalByRefObject, IDisposable , IEquatable { private static readonly Int32 FilePositionDumpSize = Stdlib.DumpFilePosition (null, new HandleRef (null, IntPtr.Zero), 0); private HandleRef pos; public FilePosition () { IntPtr p = Stdlib.CreateFilePosition (); if (p == IntPtr.Zero) { throw new OutOfMemoryException ("Unable to malloc fpos_t!"); } this.pos = new HandleRef (this, p); } internal HandleRef Handle => this.pos; public void Dispose () { this.Cleanup (); GC.SuppressFinalize (this); } private void Cleanup () { if (this.pos.Handle != IntPtr.Zero) { Stdlib.free (this.pos.Handle); this.pos = new HandleRef (this, IntPtr.Zero); } } public override String ToString() => "(" + base.ToString() + " " + this.GetDump() + ")"; private String GetDump () { if (FilePositionDumpSize <= 0) { return "internal error"; } StringBuilder buf = new StringBuilder (FilePositionDumpSize+1); return Stdlib.DumpFilePosition (buf, this.Handle, FilePositionDumpSize+1) <= 0 ? "internal error dumping fpos_t" : buf.ToString (); } public override Boolean Equals (Object obj) { FilePosition fp = obj as FilePosition; return obj == null || fp == null ? false : this.ToString().Equals (obj.ToString()); } public Boolean Equals(FilePosition value) => Object.ReferenceEquals(this, value) ? true : this.ToString().Equals(value.ToString()); public override Int32 GetHashCode() => this.ToString().GetHashCode(); ~FilePosition () { this.Cleanup (); } public static Boolean operator ==(FilePosition lhs, FilePosition rhs) => Object.Equals(lhs, rhs); public static Boolean operator !=(FilePosition lhs, FilePosition rhs) => !Object.Equals(lhs, rhs); } public enum SignalAction { Default, Ignore, Error } // // Right now using this attribute gives an assert because it // isn't implemented. // #if UNMANAGED_FN_PTR_SUPPORT_FIXED [UnmanagedFunctionPointer (CallingConvention.Cdecl)] #endif public delegate void SignalHandler (Int32 signal); #if !NETSTANDARD2_0 internal class XPrintfFunctions { internal delegate Object XPrintf (Object[] parameters); internal static XPrintf printf; internal static XPrintf fprintf; internal static XPrintf snprintf; internal static XPrintf syslog; static XPrintfFunctions () { CdeclFunction _printf = new CdeclFunction (Stdlib.LIBC, "printf", typeof(Int32)); printf = new XPrintf (_printf.Invoke); CdeclFunction _fprintf = new CdeclFunction (Stdlib.LIBC, "fprintf", typeof(Int32)); fprintf = new XPrintf (_fprintf.Invoke); CdeclFunction _snprintf = new CdeclFunction (Stdlib.MPH, "Mono_Posix_Stdlib_snprintf", typeof(Int32)); snprintf = new XPrintf (_snprintf.Invoke); CdeclFunction _syslog = new CdeclFunction (Syscall.MPH, "Mono_Posix_Stdlib_syslog2", typeof(Int32)); syslog = new XPrintf (_syslog.Invoke); } } #endif // // Convention: Functions that are part of the C standard library go here. // // For example, the man page should say something similar to: // // CONFORMING TO // ISO 9899 (''ANSI C'') // // The intent is that members of this class should be portable to any system // supporting the C runtime (read: non-Unix, including Windows). Using // anything from Syscall is non-portable, but restricting yourself to just // Stdlib is intended to be portable. // // The only methods in here should be: // (1) low-level functions (as defined above). // (2) "Trivial" function overloads. For example, if the parameters to a // function are related (e.g. fwrite(3)) // (3) The return type SHOULD NOT be changed. If you want to provide a // convenience function with a nicer return type, place it into one of // the Mono.Unix.Std* wrapper classes, and give it a .NET-styled name. // - EXCEPTION: No public functions should have a `void' return type. // `void' return types should be replaced with `int'. // Rationality: `void'-return functions typically require a // complicated call sequence, such as clear errno, then call, then // check errno to see if any errors occurred. This sequence can't // be done safely in managed code, as errno may change as part of // the P/Invoke mechanism. // Instead, add a MonoPosixHelper export which does: // errno = 0; // INVOKE SYSCALL; // return errno == 0 ? 0 : -1; // This lets managed code check the return value in the usual manner. // (4) Exceptions SHOULD NOT be thrown. EXCEPTIONS: // - If you're wrapping *broken* methods which make assumptions about // input data, such as that an argument refers to N bytes of data. // This is currently limited to cuserid(3) and encrypt(3). // - If you call functions which themselves generate exceptions. // This is the case for using NativeConvert, which will throw an // exception if an invalid/unsupported value is used. // public class Stdlib { #if FORCE_USE_LIBC_NOT_MSVC internal const string LIBC = "c"; #else internal const String LIBC = "msvcrt"; #endif internal const String MPH = "MonoPosixHelper"; // It is possible for Mono.Posix and MonoPosixHelper to get out of sync, // for example if NuGet does something weird. To mitigate this, anyone // editing Mono.Posix needs to observe two rules: // 1. When introducing C-interface changes to MonoPosixHelper, update // the version strings in VersionCheck below and also // Mono_Unix_VersionString in the C sources. // 2. Any class which performs a DllImport on Stdlib.MPH needs to call // Stdlib.VersionCheck in its static constructor. [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Unix_VersionString")] private static extern IntPtr VersionStringPtr (); private static Boolean versionCheckPerformed = false; internal static void VersionCheck () { if (versionCheckPerformed) { return; } // This string is arbitrary; it matters only that it is unique. String assemblyVersion = "MonoProject-2015-12-1"; String nativeVersion = Marshal.PtrToStringAnsi (VersionStringPtr ()); if (assemblyVersion != nativeVersion) { throw new Exception ("Mono.Posix assembly loaded with a different version (\"" + assemblyVersion + "\") than MonoPosixHelper (\"" + nativeVersion + "\"). You may need to reinstall Mono.Posix."); } versionCheckPerformed = true; } static Stdlib() => VersionCheck(); internal Stdlib () {} #region Declarations // // -- COMPLETE // public static Errno GetLastError () { // Always call Marshal.GetLastWin32Error() before the OS check, // even on Windows where we don't use the return value. If we do // the OS check first Environment.OSVersion (if it happens to be // the first ever access) will clobber Marshal.GetLastWin32Error() // and we won't get the desired errno value on non-Windows platforms. Int32 errno = Marshal.GetLastWin32Error (); if (Environment.OSVersion.Platform != PlatformID.Unix) { // On Windows Marshal.GetLastWin32Error() doesn't take errno // into account so we need to call Mono_Posix_Stdlib_GetLastError() // which returns the value of errno in the C runtime // libMonoPosixHelper.dll was linked against. errno = _GetLastError (); } return NativeConvert.ToErrno (errno); } [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_GetLastError")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 _GetLastError (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_SetLastError")] private static extern void SetLastError (Int32 error); protected static void SetLastError (Errno error) { Int32 _error = NativeConvert.FromErrno (error); SetLastError (_error); } #endregion // // // [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_InvokeSignalHandler")] internal static extern void InvokeSignalHandler (Int32 signum, IntPtr handler); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_SIG_DFL")] private static extern IntPtr GetDefaultSignal (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_SIG_ERR")] private static extern IntPtr GetErrorSignal (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_SIG_IGN")] private static extern IntPtr GetIgnoreSignal (); private static readonly IntPtr _SIG_DFL = GetDefaultSignal (); private static readonly IntPtr _SIG_ERR = GetErrorSignal (); private static readonly IntPtr _SIG_IGN = GetIgnoreSignal (); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static void _ErrorHandler(Int32 signum) => Console.Error.WriteLine("Error handler invoked for signum " + signum + ". Don't do that."); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static void _DefaultHandler(Int32 signum) => Console.Error.WriteLine("Default handler invoked for signum " + signum + ". Don't do that."); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static void _IgnoreHandler(Int32 signum) => Console.Error.WriteLine("Ignore handler invoked for signum " + signum + ". Don't do that."); //[CLSCompliant (false)] public static readonly SignalHandler SIG_DFL = new SignalHandler (_DefaultHandler); //[CLSCompliant (false)] public static readonly SignalHandler SIG_ERR = new SignalHandler (_ErrorHandler); //[CLSCompliant (false)] public static readonly SignalHandler SIG_IGN = new SignalHandler (_IgnoreHandler); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="signal")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern IntPtr sys_signal (Int32 signum, SignalHandler handler); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="signal")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern IntPtr sys_signal (Int32 signum, IntPtr handler); //[CLSCompliant (false)] [Obsolete ("This is not safe; " + "use Mono.Unix.UnixSignal for signal delivery or SetSignalAction()")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static SignalHandler signal (Signum signum, SignalHandler handler) { Int32 _sig = NativeConvert.FromSignum (signum); Delegate[] handlers = handler.GetInvocationList (); for (Int32 i = 0; i < handlers.Length; ++i) { Marshal.Prelink (handlers [i].Method); } IntPtr r = handler == SIG_DFL ? sys_signal (_sig, _SIG_DFL) : handler == SIG_ERR ? sys_signal(_sig, _SIG_ERR) : handler == SIG_IGN ? sys_signal(_sig, _SIG_IGN) : sys_signal(_sig, handler); return TranslateHandler (r); } private static SignalHandler TranslateHandler(IntPtr handler) => handler == _SIG_DFL ? SIG_DFL : handler == _SIG_ERR ? SIG_ERR : handler == _SIG_IGN ? SIG_IGN : (SignalHandler)Marshal.GetDelegateForFunctionPointer(handler, typeof(SignalHandler)); public static Int32 SetSignalAction(Signum signal, SignalAction action) => SetSignalAction(NativeConvert.FromSignum(signal), action); public static Int32 SetSignalAction(RealTimeSignum rts, SignalAction action) => SetSignalAction(NativeConvert.FromRealTimeSignum(rts), action); private static Int32 SetSignalAction (Int32 signum, SignalAction action) { IntPtr handler; switch (action) { case SignalAction.Default: handler = _SIG_DFL; break; case SignalAction.Ignore: handler = _SIG_IGN; break; case SignalAction.Error: handler = _SIG_ERR; break; default: throw new ArgumentException ("Invalid action value.", "action"); } IntPtr r = sys_signal (signum, handler); return r == _SIG_ERR ? -1 : 0; } [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="raise")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_raise (Int32 sig); //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 raise(Signum sig) => sys_raise(NativeConvert.FromSignum(sig)); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 raise(RealTimeSignum rts) => sys_raise(NativeConvert.FromRealTimeSignum(rts)); // // -- COMPLETE except for : // - the scanf(3) family . // - vararg functions. // - Horribly unsafe functions (gets(3)). // [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib__IOFBF")] private static extern Int32 GetFullyBuffered (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib__IOLBF")] private static extern Int32 GetLineBuffered (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib__IONBF")] private static extern Int32 GetNonBuffered (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_BUFSIZ")] private static extern Int32 GetBufferSize (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_CreateFilePosition")] internal static extern IntPtr CreateFilePosition (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_DumpFilePosition")] internal static extern Int32 DumpFilePosition (StringBuilder buf, HandleRef handle, Int32 len); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_EOF")] private static extern Int32 GetEOF (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_FILENAME_MAX")] private static extern Int32 GetFilenameMax (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_FOPEN_MAX")] private static extern Int32 GetFopenMax (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_L_tmpnam")] private static extern Int32 GetTmpnamLength (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_stdin")] private static extern IntPtr GetStandardInput (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_stdout")] private static extern IntPtr GetStandardOutput (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_stderr")] private static extern IntPtr GetStandardError (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_TMP_MAX")] private static extern Int32 GetTmpMax (); //[CLSCompliant (false)] public static readonly Int32 _IOFBF = GetFullyBuffered (); //[CLSCompliant (false)] public static readonly Int32 _IOLBF = GetLineBuffered (); //[CLSCompliant (false)] public static readonly Int32 _IONBF = GetNonBuffered (); //[CLSCompliant (false)] public static readonly Int32 BUFSIZ = GetBufferSize (); //[CLSCompliant (false)] public static readonly Int32 EOF = GetEOF (); //[CLSCompliant (false)] public static readonly Int32 FOPEN_MAX = GetFopenMax (); //[CLSCompliant (false)] public static readonly Int32 FILENAME_MAX = GetFilenameMax (); //[CLSCompliant (false)] public static readonly Int32 L_tmpnam = GetTmpnamLength (); public static readonly IntPtr stderr = GetStandardError (); public static readonly IntPtr stdin = GetStandardInput (); public static readonly IntPtr stdout = GetStandardOutput (); //[CLSCompliant (false)] public static readonly Int32 TMP_MAX = GetTmpMax (); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 remove ( [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] String filename); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 rename ( [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] String oldpath, [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] String newpath); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_tmpfile")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern IntPtr tmpfile (); private static readonly Object tmpnam_lock = new Object(); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="tmpnam")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern IntPtr sys_tmpnam (StringBuilder s); [Obsolete ("Syscall.mkstemp() should be preferred.")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static String tmpnam (StringBuilder s) { if (s != null && s.Capacity < L_tmpnam) { throw new ArgumentOutOfRangeException ("s", "s.Capacity < L_tmpnam"); } lock (tmpnam_lock) { IntPtr r = sys_tmpnam (s); return UnixMarshal.PtrToString (r); } } [Obsolete ("Syscall.mkstemp() should be preferred.")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static String tmpnam () { lock (tmpnam_lock) { IntPtr r = sys_tmpnam (null); return UnixMarshal.PtrToString (r); } } [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fclose")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 fclose (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fflush")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 fflush (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fopen")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern IntPtr fopen ( [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] String path, String mode); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_freopen")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern IntPtr freopen ( [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] String path, String mode, IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_setbuf")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 setbuf (IntPtr stream, IntPtr buf); //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static unsafe Int32 setbuf(IntPtr stream, Byte* buf) => setbuf(stream, (IntPtr)buf); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_setvbuf")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 setvbuf (IntPtr stream, IntPtr buf, Int32 mode, UInt64 size); //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static unsafe Int32 setvbuf(IntPtr stream, Byte* buf, Int32 mode, UInt64 size) => setvbuf(stream, (IntPtr)buf, mode, size); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_fprintf")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_fprintf (IntPtr stream, String format, String message); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 fprintf(IntPtr stream, String message) => sys_fprintf(stream, "%s", message); #if !NETSTANDARD2_0 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" + "Use fprintf (IntPtr, string) instead.")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 fprintf (IntPtr stream, String format, params Object[] parameters) { Object[] _parameters = new Object[checked(parameters.Length+2)]; _parameters [0] = stream; _parameters [1] = format; Array.Copy (parameters, 0, _parameters, 2, parameters.Length); return (Int32) XPrintfFunctions.fprintf (_parameters); } #endif /* SKIP: fscanf(3) */ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="printf")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_printf (String format, String message); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 printf(String message) => sys_printf("%s", message); #if !NETSTANDARD2_0 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" + "Use printf (string) instead.")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 printf (String format, params Object[] parameters) { Object[] _parameters = new Object[checked(parameters.Length+1)]; _parameters [0] = format; Array.Copy (parameters, 0, _parameters, 1, parameters.Length); return (Int32) XPrintfFunctions.printf (_parameters); } #endif /* SKIP: scanf(3) */ [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_snprintf")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_snprintf (StringBuilder s, UInt64 n, String format, String message); //[CLSCompliant (false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 snprintf (StringBuilder s, UInt64 n, String message) { if (n > (UInt64) s.Capacity) { throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity"); } return sys_snprintf (s, n, "%s", message); } [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 snprintf(StringBuilder s, String message) => sys_snprintf(s, (UInt64)s.Capacity, "%s", message); #if !NETSTANDARD2_0 //[CLSCompliant (false)] [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" + "Use snprintf (StringBuilder, string) instead.")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 snprintf (StringBuilder s, UInt64 n, String format, params Object[] parameters) { if (n > (UInt64) s.Capacity) { throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity"); } Object[] _parameters = new Object[checked(parameters.Length+3)]; _parameters [0] = s; _parameters [1] = n; _parameters [2] = format; Array.Copy (parameters, 0, _parameters, 3, parameters.Length); return (Int32) XPrintfFunctions.snprintf (_parameters); } //[CLSCompliant (false)] [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" + "Use snprintf (StringBuilder, string) instead.")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 snprintf (StringBuilder s, String format, params Object[] parameters) { Object[] _parameters = new Object[checked(parameters.Length+3)]; _parameters [0] = s; _parameters [1] = (UInt64) s.Capacity; _parameters [2] = format; Array.Copy (parameters, 0, _parameters, 3, parameters.Length); return (Int32) XPrintfFunctions.snprintf (_parameters); } #endif /* * SKIP: * sprintf(3) * sscanf(3) * vfprintf(3) * vfscanf(3) * vprintf(3) * vscanf(3) * vsnprintf(3) * vsprint(3) * vsscanf(3) */ [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgetc")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 fgetc (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgets")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern IntPtr sys_fgets (StringBuilder sb, Int32 size, IntPtr stream); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static StringBuilder fgets (StringBuilder sb, Int32 size, IntPtr stream) { IntPtr r = sys_fgets (sb, size, stream); return r == IntPtr.Zero ? null : sb; } [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static StringBuilder fgets(StringBuilder sb, IntPtr stream) => fgets(sb, sb.Capacity, stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fputc")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 fputc (Int32 c, IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fputs")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 fputs (String s, IntPtr stream); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 getc(IntPtr stream) => fgetc(stream); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 getchar (); /* SKIP: gets(3) */ [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 putc(Int32 c, IntPtr stream) => fputc(c, stream); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)] public static extern Int32 putchar (Int32 c); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 puts (String s); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ungetc")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 ungetc (Int32 c, IntPtr stream); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern UInt64 fread (IntPtr ptr, UInt64 size, UInt64 nmemb, IntPtr stream); //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static unsafe UInt64 fread(void* ptr, UInt64 size, UInt64 nmemb, IntPtr stream) => fread((IntPtr)ptr, size, nmemb, stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern UInt64 sys_fread ([Out] Byte[] ptr, UInt64 size, UInt64 nmemb, IntPtr stream); //[CLSCompliant (false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static UInt64 fread (Byte[] ptr, UInt64 size, UInt64 nmemb, IntPtr stream) { if (size * nmemb > (UInt64) ptr.Length) { throw new ArgumentOutOfRangeException ("nmemb"); } return sys_fread (ptr, size, nmemb, stream); } //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static UInt64 fread(Byte[] ptr, IntPtr stream) => fread(ptr, 1, (UInt64)ptr.Length, stream); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern UInt64 fwrite (IntPtr ptr, UInt64 size, UInt64 nmemb, IntPtr stream); //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static unsafe UInt64 fwrite(void* ptr, UInt64 size, UInt64 nmemb, IntPtr stream) => fwrite((IntPtr)ptr, size, nmemb, stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern UInt64 sys_fwrite (Byte[] ptr, UInt64 size, UInt64 nmemb, IntPtr stream); //[CLSCompliant (false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static UInt64 fwrite (Byte[] ptr, UInt64 size, UInt64 nmemb, IntPtr stream) { if (size * nmemb > (UInt64) ptr.Length) { throw new ArgumentOutOfRangeException ("nmemb"); } return sys_fwrite (ptr, size, nmemb, stream); } //[CLSCompliant(false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static UInt64 fwrite(Byte[] ptr, IntPtr stream) => fwrite(ptr, 1, (UInt64)ptr.Length, stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgetpos")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_fgetpos (IntPtr stream, HandleRef pos); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 fgetpos(IntPtr stream, FilePosition pos) => sys_fgetpos(stream, pos.Handle); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fseek")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_fseek (IntPtr stream, Int64 offset, Int32 origin); //[CLSCompliant (false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 fseek (IntPtr stream, Int64 offset, SeekFlags origin) { Int32 _origin = NativeConvert.FromSeekFlags (origin); return sys_fseek (stream, offset, _origin); } [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fsetpos")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 sys_fsetpos (IntPtr stream, HandleRef pos); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 fsetpos(IntPtr stream, FilePosition pos) => sys_fsetpos(stream, pos.Handle); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ftell")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int64 ftell (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_rewind")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 rewind (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_clearerr")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 clearerr (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_feof")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 feof (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ferror")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 ferror (IntPtr stream); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_perror")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern Int32 perror (String s, Int32 err); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static Int32 perror(String s) => perror(s, Marshal.GetLastWin32Error()); // // // [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_EXIT_FAILURE")] private static extern Int32 GetExitFailure(); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_EXIT_SUCCESS")] private static extern Int32 GetExitSuccess (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_MB_CUR_MAX")] private static extern Int32 GetMbCurMax (); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_RAND_MAX")] private static extern Int32 GetRandMax (); //[CLSCompliant (false)] public static readonly Int32 EXIT_FAILURE = GetExitFailure (); //[CLSCompliant (false)] public static readonly Int32 EXIT_SUCCESS = GetExitSuccess (); //[CLSCompliant (false)] public static readonly Int32 MB_CUR_MAX = GetMbCurMax (); //[CLSCompliant (false)] public static readonly Int32 RAND_MAX = GetRandMax (); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 rand (); //[CLSCompliant (false)] [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern void srand (UInt32 seed); // calloc(3): // void *calloc (size_t nmemb, size_t size); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_calloc")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern IntPtr calloc (UInt64 nmemb, UInt64 size); [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, EntryPoint="Mono_Posix_Stdlib_free")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern void free (IntPtr ptr); // malloc(3): // void *malloc(size_t size); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_malloc")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern IntPtr malloc (UInt64 size); // realloc(3): // void *realloc(void *ptr, size_t size); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_realloc")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern IntPtr realloc (IntPtr ptr, UInt64 size); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern void abort (); /* SKIP: atexit(3) -- the GC should have collected most references by the * time this runs, so no delegates should exist, making it pointless. */ [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern void exit (Int32 status); //[CLSCompliant (false)] [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern void _Exit (Int32 status); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="getenv")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern IntPtr sys_getenv (String name); [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static String getenv (String name) { IntPtr r = sys_getenv (name); return UnixMarshal.PtrToString (r); } //[CLSCompliant (false)] [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern Int32 system (String @string); // // // private static readonly Object strerror_lock = new Object(); [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="strerror")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] private static extern IntPtr sys_strerror (Int32 errnum); //[CLSCompliant (false)] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static String strerror (Errno errnum) { Int32 e = NativeConvert.FromErrno (errnum); lock (strerror_lock) { IntPtr r = sys_strerror (e); return UnixMarshal.PtrToString (r); } } // strlen(3): // size_t strlen(const char *s); //[CLSCompliant (false)] [DllImport (MPH, CallingConvention=CallingConvention.Cdecl, SetLastError=true, EntryPoint="Mono_Posix_Stdlib_strlen")] [SuppressMessage("Microsoft.Design", "IDE1006", Justification = "Can not change name!")] public static extern UInt64 strlen (IntPtr s); } #endregion // Classes } // vim: noexpandtab