* Makefile: Build the make-map.exe in Mono.Unix.Native; add /nowarn:0618 to
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / Stdlib.cs
index 7ccab030fc69b3119cd57e8ac7be4b55ae5cefeb..0eda499976ac5cef2b5905c3e5b6f0361663fee4 100644 (file)
@@ -5,6 +5,20 @@
 //   Jonathan Pryor (jonpryor@vt.edu)
 //
 // (C) 2004-2005 Jonathan Pryor
+//
+
+// Deprecated Warning:
+//
+//    This class is deprecated, and exists only for backward compatibility
+//    with development versions of Mono 1.1.x.  It will be removed with 
+//    Mono 1.2.  Migrate to the Mono.Unix.Native types, or use the Unix*
+//    wrapper classes instead.
+//
+//    The [Map] attributes have been removed.  However, since the type names
+//    are identical to those in Mono.Unix.Native, the MonoPosixHelper methods
+//    will continue to exist and function correctly.
+//
+
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -27,6 +41,7 @@
 //
 
 using System;
+using System.Collections;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -36,6 +51,7 @@ namespace Mono.Unix {
 
        #region Enumerations
 
+       [Obsolete ("Use Mono.Unix.Native.Errno")]
        [Map]
        public enum Error : int {
                // errors & their values liberally copied from
@@ -174,8 +190,12 @@ namespace Mono.Unix {
 
        #region Classes
 
+       [Obsolete ("Use Mono.Unix.Native.FilePosition")]
        public sealed class FilePosition : IDisposable {
 
+               private static readonly int FilePositionDumpSize = 
+                       Stdlib.DumpFilePosition (null, new HandleRef (null, IntPtr.Zero), 0);
+
                private HandleRef pos;
 
                public FilePosition ()
@@ -192,8 +212,8 @@ namespace Mono.Unix {
 
                public void Dispose ()
                {
-                       GC.SuppressFinalize (this);
                        Cleanup ();
+                       GC.SuppressFinalize (this);
                }
 
                private void Cleanup ()
@@ -204,17 +224,64 @@ namespace Mono.Unix {
                        }
                }
 
+               public override string ToString ()
+               {
+                       return "(" + base.ToString () + " " + GetDump () + ")";
+               }
+
+               private string GetDump ()
+               {
+                       if (FilePositionDumpSize <= 0)
+                               return "internal error";
+
+                       StringBuilder buf = new StringBuilder (FilePositionDumpSize+1);
+
+                       if (Stdlib.DumpFilePosition (buf, Handle, FilePositionDumpSize+1) <= 0)
+                               return "internal error dumping fpos_t";
+
+                       return buf.ToString ();
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj == null || GetType() != obj.GetType())
+                               return false;
+                       return ToString().Equals (obj.ToString());
+               }
+
+               public override int GetHashCode ()
+               {
+                       return ToString ().GetHashCode ();
+               }
+
                ~FilePosition ()
                {
                        Cleanup ();
                }
+
+               public static bool operator== (FilePosition lhs, FilePosition rhs)
+               {
+                       return Object.Equals (lhs, rhs);
+               }
+
+               public static bool operator!= (FilePosition lhs, FilePosition rhs)
+               {
+                       return !Object.Equals (lhs, rhs);
+               }
        }
 
-#if NET_2_0
+
+       //
+       // Right now using this attribute gives an assert because it
+       // isn't implemented.
+       //
+#if NET_2_0 && UNMANAGED_FN_PTR_SUPPORT_FIXED
        [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
 #endif
+       [Obsolete ("Use Mono.Unix.Native.SignalHandler")]
        public delegate void SignalHandler (int signal);
 
+#if !NET_2_0
        internal sealed class SignalWrapper {
                private IntPtr handler;
 
@@ -228,6 +295,7 @@ namespace Mono.Unix {
                        Stdlib.InvokeSignalHandler (signum, handler);
                }
        }
+#endif
 
        internal class XPrintfFunctions
        {
@@ -268,6 +336,8 @@ namespace Mono.Unix {
        // anything from Syscall is non-portable, but restricting yourself to just
        // Stdlib is intended to be portable.
        //
+       [CLSCompliant (false)]
+       [Obsolete ("Use Mono.Unix.Native.Stdlib")]
        public class Stdlib
        {
                internal const string LIBC = "msvcrt";
@@ -301,7 +371,7 @@ namespace Mono.Unix {
                // <signal.h>
                //
                [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
-                               EntryPoint="Mono_Posix_Syscall_InvokeSignalHandler")]
+                               EntryPoint="Mono_Posix_Stdlib_InvokeSignalHandler")]
                internal static extern void InvokeSignalHandler (int signum, IntPtr handler);
 
                [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
@@ -342,6 +412,14 @@ namespace Mono.Unix {
                public static readonly SignalHandler SIG_ERR = new SignalHandler (_ErrorHandler);
                public static readonly SignalHandler SIG_IGN = new SignalHandler (_IgnoreHandler);
 
+               private static readonly SignalHandler[] registered_signals;
+
+               static Stdlib ()
+               {
+                       Array signals = Enum.GetValues(typeof(Signum));
+                       registered_signals = new SignalHandler [(int) signals.GetValue (signals.Length-1)];
+               }
+
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
                                SetLastError=true, EntryPoint="signal")]
                private static extern IntPtr sys_signal (int signum, SignalHandler handler);
@@ -353,6 +431,11 @@ namespace Mono.Unix {
                public static SignalHandler signal (Signum signum, SignalHandler handler)
                {
                        int _sig = UnixConvert.FromSignum (signum);
+
+                       lock (registered_signals) {
+                               registered_signals [(int) signum] = handler;
+                       }
+
                        IntPtr r;
                        if (handler == SIG_DFL)
                                r = sys_signal (_sig, _SIG_DFL);
@@ -373,7 +456,11 @@ namespace Mono.Unix {
                                return SIG_ERR;
                        if (handler == _SIG_IGN)
                                return SIG_IGN;
+#if NET_2_0
+                       return (SignalHandler) Marshal.GetDelegateForFunctionPointer (handler, typeof(SignalHandler));
+#else
                        return new SignalHandler (new SignalWrapper (handler).InvokeSignalHandler);
+#endif
                }
 
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="raise")]
@@ -411,6 +498,10 @@ namespace Mono.Unix {
                                EntryPoint="Mono_Posix_Stdlib_CreateFilePosition")]
                internal static extern IntPtr CreateFilePosition ();
 
+               [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
+                               EntryPoint="Mono_Posix_Stdlib_DumpFilePosition")]
+               internal static extern int DumpFilePosition (StringBuilder buf, HandleRef handle, int len);
+
                [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
                                EntryPoint="Mono_Posix_Stdlib_EOF")]
                private static extern int GetEOF ();
@@ -465,6 +556,8 @@ namespace Mono.Unix {
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
                public static extern IntPtr tmpfile ();
 
+               private static object tmpnam_lock = new object ();
+
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
                                SetLastError=true, EntryPoint="tmpnam")]
                private static extern IntPtr sys_tmpnam (StringBuilder s);
@@ -474,15 +567,19 @@ namespace Mono.Unix {
                {
                        if (s != null && s.Capacity < L_tmpnam)
                                throw new ArgumentOutOfRangeException ("s", "s.Capacity < L_tmpnam");
-                       IntPtr r = sys_tmpnam (s);
-                       return UnixMarshal.PtrToString (r);
+                       lock (tmpnam_lock) {
+                               IntPtr r = sys_tmpnam (s);
+                               return UnixMarshal.PtrToString (r);
+                       }
                }
 
                [Obsolete ("Syscall.mkstemp() should be preferred.")]
                public static string tmpnam ()
                {
-                       IntPtr r = sys_tmpnam (null);
-                       return UnixMarshal.PtrToString (r);
+                       lock (tmpnam_lock) {
+                               IntPtr r = sys_tmpnam (null);
+                               return UnixMarshal.PtrToString (r);
+                       }
                }
 
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
@@ -564,6 +661,8 @@ namespace Mono.Unix {
 
                public static int snprintf (StringBuilder s, ulong n, string message)
                {
+                       if (n > (ulong) s.Capacity)
+                               throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
                        return sys_snprintf (s, n, "%s", message);
                }
 
@@ -577,6 +676,9 @@ namespace Mono.Unix {
                public static int snprintf (StringBuilder s, ulong n, 
                                string format, params object[] parameters)
                {
+                       if (n > (ulong) 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;
@@ -810,7 +912,8 @@ namespace Mono.Unix {
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
                public static extern void abort ();
 
-               /* SKIP: atexit(3) */
+               /* 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)]
                public static extern void exit (int status);
@@ -834,6 +937,8 @@ namespace Mono.Unix {
                // <string.h>
                //
 
+               private static object strerror_lock = new object ();
+
                [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
                                SetLastError=true, EntryPoint="strerror")]
                private static extern IntPtr sys_strerror (int errnum);
@@ -841,8 +946,10 @@ namespace Mono.Unix {
                public static string strerror (Error errnum)
                {
                        int e = UnixConvert.FromError (errnum);
-                       IntPtr r = sys_strerror (e);
-                       return UnixMarshal.PtrToString (r);
+                       lock (strerror_lock) {
+                               IntPtr r = sys_strerror (e);
+                               return UnixMarshal.PtrToString (r);
+                       }
                }
        }