* UnixMarshal.cs: Errno.EBADF should also trigger a ArgumentException.
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / Stdlib.cs
1 //
2 // Mono.Unix/Stdlib.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //
7 // (C) 2004-2005 Jonathan Pryor
8 //
9
10 // Deprecated Warning:
11 //
12 //    This class is deprecated, and exists only for backward compatibility
13 //    with development versions of Mono 1.1.x.  It will be removed with 
14 //    Mono 1.2.  Migrate to the Mono.Unix.Native types, or use the Unix*
15 //    wrapper classes instead.
16 //
17 //    The [Map] attributes have been removed.  However, since the type names
18 //    are identical to those in Mono.Unix.Native, the MonoPosixHelper methods
19 //    will continue to exist and function correctly.
20 //
21
22 //
23 // Permission is hereby granted, free of charge, to any person obtaining
24 // a copy of this software and associated documentation files (the
25 // "Software"), to deal in the Software without restriction, including
26 // without limitation the rights to use, copy, modify, merge, publish,
27 // distribute, sublicense, and/or sell copies of the Software, and to
28 // permit persons to whom the Software is furnished to do so, subject to
29 // the following conditions:
30 // 
31 // The above copyright notice and this permission notice shall be
32 // included in all copies or substantial portions of the Software.
33 // 
34 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
38 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
39 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
40 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 //
42
43 using System;
44 using System.Collections;
45 using System.IO;
46 using System.Runtime.InteropServices;
47 using System.Text;
48 using Mono.Unix;
49
50 using FileNameMarshaler = Mono.Unix.Native.FileNameMarshaler;
51
52 namespace Mono.Unix {
53
54         #region Enumerations
55
56         [Obsolete ("Use Mono.Unix.Native.Errno", true)]
57         [Map]
58         public enum Error : int {
59                 // errors & their values liberally copied from
60                 // FC2 /usr/include/asm/errno.h
61                 
62                 EPERM           =   1, // Operation not permitted 
63                 ENOENT          =   2, // No such file or directory 
64                 ESRCH           =   3, // No such process 
65                 EINTR           =   4, // Interrupted system call 
66                 EIO             =   5, // I/O error 
67                 ENXIO           =   6, // No such device or address 
68                 E2BIG           =   7, // Arg list too long 
69                 ENOEXEC         =   8, // Exec format error 
70                 EBADF           =   9, // Bad file number 
71                 ECHILD          =  10, // No child processes 
72                 EAGAIN          =  11, // Try again 
73                 ENOMEM          =  12, // Out of memory 
74                 EACCES          =  13, // Permission denied 
75                 EFAULT          =  14, // Bad address 
76                 ENOTBLK         =  15, // Block device required 
77                 EBUSY           =  16, // Device or resource busy 
78                 EEXIST          =  17, // File exists 
79                 EXDEV           =  18, // Cross-device link 
80                 ENODEV          =  19, // No such device 
81                 ENOTDIR         =  20, // Not a directory 
82                 EISDIR          =  21, // Is a directory 
83                 EINVAL          =  22, // Invalid argument 
84                 ENFILE          =  23, // File table overflow 
85                 EMFILE          =  24, // Too many open files 
86                 ENOTTY          =  25, // Not a typewriter 
87                 ETXTBSY         =  26, // Text file busy 
88                 EFBIG           =  27, // File too large 
89                 ENOSPC          =  28, // No space left on device 
90                 ESPIPE          =  29, // Illegal seek 
91                 EROFS           =  30, // Read-only file system 
92                 EMLINK          =  31, // Too many links 
93                 EPIPE           =  32, // Broken pipe 
94                 EDOM            =  33, // Math argument out of domain of func 
95                 ERANGE          =  34, // Math result not representable 
96                 EDEADLK         =  35, // Resource deadlock would occur 
97                 ENAMETOOLONG    =  36, // File name too long 
98                 ENOLCK          =  37, // No record locks available 
99                 ENOSYS          =  38, // Function not implemented 
100                 ENOTEMPTY       =  39, // Directory not empty 
101                 ELOOP           =  40, // Too many symbolic links encountered 
102                 EWOULDBLOCK     =  EAGAIN, // Operation would block 
103                 ENOMSG          =  42, // No message of desired type 
104                 EIDRM           =  43, // Identifier removed 
105                 ECHRNG          =  44, // Channel number out of range 
106                 EL2NSYNC        =  45, // Level 2 not synchronized 
107                 EL3HLT          =  46, // Level 3 halted 
108                 EL3RST          =  47, // Level 3 reset 
109                 ELNRNG          =  48, // Link number out of range 
110                 EUNATCH         =  49, // Protocol driver not attached 
111                 ENOCSI          =  50, // No CSI structure available 
112                 EL2HLT          =  51, // Level 2 halted 
113                 EBADE           =  52, // Invalid exchange 
114                 EBADR           =  53, // Invalid request descriptor 
115                 EXFULL          =  54, // Exchange full 
116                 ENOANO          =  55, // No anode 
117                 EBADRQC         =  56, // Invalid request code 
118                 EBADSLT         =  57, // Invalid slot 
119                       
120                 EDEADLOCK             =  EDEADLK,
121                       
122                 EBFONT          =  59, // Bad font file format 
123                 ENOSTR          =  60, // Device not a stream 
124                 ENODATA         =  61, // No data available 
125                 ETIME           =  62, // Timer expired 
126                 ENOSR           =  63, // Out of streams resources 
127                 ENONET          =  64, // Machine is not on the network 
128                 ENOPKG          =  65, // Package not installed 
129                 EREMOTE         =  66, // Object is remote 
130                 ENOLINK         =  67, // Link has been severed 
131                 EADV            =  68, // Advertise error 
132                 ESRMNT          =  69, // Srmount error 
133                 ECOMM           =  70, // Communication error on send 
134                 EPROTO          =  71, // Protocol error 
135                 EMULTIHOP       =  72, // Multihop attempted 
136                 EDOTDOT         =  73, // RFS specific error 
137                 EBADMSG         =  74, // Not a data message 
138                 EOVERFLOW       =  75, // Value too large for defined data type 
139                 ENOTUNIQ        =  76, // Name not unique on network 
140                 EBADFD          =  77, // File descriptor in bad state 
141                 EREMCHG         =  78, // Remote address changed 
142                 ELIBACC         =  79, // Can not access a needed shared library 
143                 ELIBBAD         =  80, // Accessing a corrupted shared library 
144                 ELIBSCN         =  81, // .lib section in a.out corrupted 
145                 ELIBMAX         =  82, // Attempting to link in too many shared libraries 
146                 ELIBEXEC        =  83, // Cannot exec a shared library directly 
147                 EILSEQ          =  84, // Illegal byte sequence 
148                 ERESTART        =  85, // Interrupted system call should be restarted 
149                 ESTRPIPE        =  86, // Streams pipe error 
150                 EUSERS          =  87, // Too many users 
151                 ENOTSOCK        =  88, // Socket operation on non-socket 
152                 EDESTADDRREQ    =  89, // Destination address required 
153                 EMSGSIZE        =  90, // Message too long 
154                 EPROTOTYPE      =  91, // Protocol wrong type for socket 
155                 ENOPROTOOPT     =  92, // Protocol not available 
156                 EPROTONOSUPPORT =  93, // Protocol not supported 
157                 ESOCKTNOSUPPORT =  94, // Socket type not supported 
158                 EOPNOTSUPP      =  95, // Operation not supported on transport endpoint 
159                 EPFNOSUPPORT    =  96, // Protocol family not supported 
160                 EAFNOSUPPORT    =  97, // Address family not supported by protocol 
161                 EADDRINUSE      =  98, // Address already in use 
162                 EADDRNOTAVAIL   =  99, // Cannot assign requested address 
163                 ENETDOWN        = 100, // Network is down 
164                 ENETUNREACH     = 101, // Network is unreachable 
165                 ENETRESET       = 102, // Network dropped connection because of reset 
166                 ECONNABORTED    = 103, // Software caused connection abort 
167                 ECONNRESET      = 104, // Connection reset by peer 
168                 ENOBUFS         = 105, // No buffer space available 
169                 EISCONN         = 106, // Transport endpoint is already connected 
170                 ENOTCONN        = 107, // Transport endpoint is not connected 
171                 ESHUTDOWN       = 108, // Cannot send after transport endpoint shutdown 
172                 ETOOMANYREFS    = 109, // Too many references: cannot splice 
173                 ETIMEDOUT       = 110, // Connection timed out 
174                 ECONNREFUSED    = 111, // Connection refused 
175                 EHOSTDOWN       = 112, // Host is down 
176                 EHOSTUNREACH    = 113, // No route to host 
177                 EALREADY        = 114, // Operation already in progress 
178                 EINPROGRESS     = 115, // Operation now in progress 
179                 ESTALE          = 116, // Stale NFS file handle 
180                 EUCLEAN         = 117, // Structure needs cleaning 
181                 ENOTNAM         = 118, // Not a XENIX named type file 
182                 ENAVAIL         = 119, // No XENIX semaphores available 
183                 EISNAM          = 120, // Is a named type file 
184                 EREMOTEIO       = 121, // Remote I/O error 
185                 EDQUOT          = 122, // Quota exceeded 
186
187                 ENOMEDIUM       = 123, // No medium found 
188                 EMEDIUMTYPE     = 124, // Wrong medium type 
189         }
190
191         #endregion
192
193         #region Classes
194
195         [Obsolete ("Use Mono.Unix.Native.FilePosition", true)]
196         public sealed class FilePosition : IDisposable {
197
198                 private static readonly int FilePositionDumpSize = 
199                         Stdlib.DumpFilePosition (null, new HandleRef (null, IntPtr.Zero), 0);
200
201                 private HandleRef pos;
202
203                 public FilePosition ()
204                 {
205                         IntPtr p = Stdlib.CreateFilePosition ();
206                         if (p == IntPtr.Zero)
207                                 throw new OutOfMemoryException ("Unable to malloc fpos_t!");
208                         pos = new HandleRef (this, p);
209                 }
210
211                 internal HandleRef Handle {
212                         get {return pos;}
213                 }
214
215                 public void Dispose ()
216                 {
217                         Cleanup ();
218                         GC.SuppressFinalize (this);
219                 }
220
221                 private void Cleanup ()
222                 {
223                         if (pos.Handle != IntPtr.Zero) {
224                                 Stdlib.free (pos.Handle);
225                                 pos = new HandleRef (this, IntPtr.Zero);
226                         }
227                 }
228
229                 public override string ToString ()
230                 {
231                         return "(" + base.ToString () + " " + GetDump () + ")";
232                 }
233
234                 private string GetDump ()
235                 {
236                         if (FilePositionDumpSize <= 0)
237                                 return "internal error";
238
239                         StringBuilder buf = new StringBuilder (FilePositionDumpSize+1);
240
241                         if (Stdlib.DumpFilePosition (buf, Handle, FilePositionDumpSize+1) <= 0)
242                                 return "internal error dumping fpos_t";
243
244                         return buf.ToString ();
245                 }
246
247                 public override bool Equals (object obj)
248                 {
249                         if (obj == null || GetType() != obj.GetType())
250                                 return false;
251                         return ToString().Equals (obj.ToString());
252                 }
253
254                 public override int GetHashCode ()
255                 {
256                         return ToString ().GetHashCode ();
257                 }
258
259                 ~FilePosition ()
260                 {
261                         Cleanup ();
262                 }
263
264                 public static bool operator== (FilePosition lhs, FilePosition rhs)
265                 {
266                         return Object.Equals (lhs, rhs);
267                 }
268
269                 public static bool operator!= (FilePosition lhs, FilePosition rhs)
270                 {
271                         return !Object.Equals (lhs, rhs);
272                 }
273         }
274
275
276         //
277         // Right now using this attribute gives an assert because it
278         // isn't implemented.
279         //
280 #if NET_2_0 && UNMANAGED_FN_PTR_SUPPORT_FIXED
281         [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
282 #endif
283         [Obsolete ("Use Mono.Unix.Native.SignalHandler", true)]
284         public delegate void SignalHandler (int signal);
285
286 #if !NET_2_0
287         [Obsolete ("Use Mono.Unix.Native.SignalWrapper", true)]
288         internal sealed class SignalWrapper {
289                 private IntPtr handler;
290
291                 internal SignalWrapper (IntPtr handler)
292                 {
293                         this.handler = handler;
294                 }
295
296                 public void InvokeSignalHandler (int signum)
297                 {
298                         Stdlib.InvokeSignalHandler (signum, handler);
299                 }
300         }
301 #endif
302
303         [Obsolete ("Use Mono.Unix.Native.XPrintfFunctions", true)]
304         internal class XPrintfFunctions
305         {
306                 internal delegate object XPrintf (object[] parameters);
307
308                 internal static XPrintf printf;
309                 internal static XPrintf fprintf;
310                 internal static XPrintf snprintf;
311                 internal static XPrintf syslog;
312
313                 static XPrintfFunctions ()
314                 {
315                         CdeclFunction _printf = new CdeclFunction (Stdlib.LIBC, "printf", typeof(int));
316                         printf = new XPrintf (_printf.Invoke);
317
318                         CdeclFunction _fprintf = new CdeclFunction (Stdlib.LIBC, "fprintf", typeof(int));
319                         fprintf = new XPrintf (_fprintf.Invoke);
320
321                         CdeclFunction _snprintf = new CdeclFunction (Stdlib.MPH, 
322                                         "Mono_Posix_Stdlib_snprintf", typeof(int));
323                         snprintf = new XPrintf (_snprintf.Invoke);
324
325                         CdeclFunction _syslog = new CdeclFunction (Syscall.LIBC, "syslog", typeof(void));
326                         syslog = new XPrintf (_syslog.Invoke);
327                 }
328         }
329
330         //
331         // Convention: Functions that are part of the C standard library go here.
332         //
333         // For example, the man page should say something similar to:
334         //
335         //    CONFORMING TO
336         //           ISO 9899 (''ANSI C'')
337         //
338         // The intent is that members of this class should be portable to any system
339         // supporting the C runtime (read: non-Unix, including Windows).  Using
340         // anything from Syscall is non-portable, but restricting yourself to just
341         // Stdlib is intended to be portable.
342         //
343         [CLSCompliant (false)]
344         [Obsolete ("Use Mono.Unix.Native.Stdlib", true)]
345         public class Stdlib
346         {
347                 internal const string LIBC = "msvcrt";
348                 internal const string MPH  = "MonoPosixHelper";
349
350                 internal Stdlib () {}
351
352                 #region <errno.h> Declarations
353                 //
354                 // <errno.h>  -- COMPLETE
355                 //
356
357                 public static Error GetLastError ()
358                 {
359                         int errno = Marshal.GetLastWin32Error ();
360                         return UnixConvert.ToError (errno);
361                 }
362
363                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
364                                 EntryPoint="Mono_Posix_Stdlib_SetLastError")]
365                 private static extern void SetLastError (int error);
366
367                 public static void SetLastError (Error error)
368                 {
369                         int _error = UnixConvert.FromError (error);
370                         SetLastError (_error);
371                 }
372                 #endregion
373
374                 //
375                 // <signal.h>
376                 //
377                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
378                                 EntryPoint="Mono_Posix_Stdlib_InvokeSignalHandler")]
379                 internal static extern void InvokeSignalHandler (int signum, IntPtr handler);
380
381                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
382                                 EntryPoint="Mono_Posix_Stdlib_SIG_DFL")]
383                 private static extern IntPtr GetDefaultSignal ();
384
385                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
386                                 EntryPoint="Mono_Posix_Stdlib_SIG_ERR")]
387                 private static extern IntPtr GetErrorSignal ();
388
389                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
390                                 EntryPoint="Mono_Posix_Stdlib_SIG_IGN")]
391                 private static extern IntPtr GetIgnoreSignal ();
392
393                 private static readonly IntPtr _SIG_DFL = GetDefaultSignal ();
394                 private static readonly IntPtr _SIG_ERR = GetErrorSignal ();
395                 private static readonly IntPtr _SIG_IGN = GetIgnoreSignal ();
396
397                 private static void _ErrorHandler (int signum)
398                 {
399                         Console.Error.WriteLine ("Error handler invoked for signum " + 
400                                         signum + ".  Don't do that.");
401                 }
402
403                 private static void _DefaultHandler (int signum)
404                 {
405                         Console.Error.WriteLine ("Default handler invoked for signum " + 
406                                         signum + ".  Don't do that.");
407                 }
408
409                 private static void _IgnoreHandler (int signum)
410                 {
411                         Console.Error.WriteLine ("Ignore handler invoked for signum " + 
412                                         signum + ".  Don't do that.");
413                 }
414
415                 public static readonly SignalHandler SIG_DFL = new SignalHandler (_DefaultHandler);
416                 public static readonly SignalHandler SIG_ERR = new SignalHandler (_ErrorHandler);
417                 public static readonly SignalHandler SIG_IGN = new SignalHandler (_IgnoreHandler);
418
419                 private static readonly SignalHandler[] registered_signals;
420
421                 static Stdlib ()
422                 {
423                         Array signals = Enum.GetValues(typeof(Signum));
424                         registered_signals = new SignalHandler [(int) signals.GetValue (signals.Length-1)];
425                 }
426
427                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
428                                 SetLastError=true, EntryPoint="signal")]
429                 private static extern IntPtr sys_signal (int signum, SignalHandler handler);
430
431                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
432                                 SetLastError=true, EntryPoint="signal")]
433                 private static extern IntPtr sys_signal (int signum, IntPtr handler);
434
435                 public static SignalHandler signal (Signum signum, SignalHandler handler)
436                 {
437                         int _sig = UnixConvert.FromSignum (signum);
438
439                         lock (registered_signals) {
440                                 registered_signals [(int) signum] = handler;
441                         }
442
443                         IntPtr r;
444                         if (handler == SIG_DFL)
445                                 r = sys_signal (_sig, _SIG_DFL);
446                         else if (handler == SIG_ERR)
447                                 r = sys_signal (_sig, _SIG_ERR);
448                         else if (handler == SIG_IGN)
449                                 r = sys_signal (_sig, _SIG_IGN);
450                         else
451                                 r = sys_signal (_sig, handler);
452                         return TranslateHandler (r);
453                 }
454
455                 private static SignalHandler TranslateHandler (IntPtr handler)
456                 {
457                         if (handler == _SIG_DFL)
458                                 return SIG_DFL;
459                         if (handler == _SIG_ERR)
460                                 return SIG_ERR;
461                         if (handler == _SIG_IGN)
462                                 return SIG_IGN;
463 #if NET_2_0
464                         return (SignalHandler) Marshal.GetDelegateForFunctionPointer (handler, typeof(SignalHandler));
465 #else
466                         return new SignalHandler (new SignalWrapper (handler).InvokeSignalHandler);
467 #endif
468                 }
469
470                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="raise")]
471                 private static extern int sys_raise (int sig);
472
473                 public static int raise (Signum sig)
474                 {
475                         int _sig = UnixConvert.FromSignum (sig);
476                         return sys_raise (_sig);
477                 }
478
479                 //
480                 // <stdio.h> -- COMPLETE except for :
481                 //    - the scanf(3) family .
482                 //    - vararg functions.
483                 //    - Horribly unsafe functions (gets(3)).
484                 //
485                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
486                                 EntryPoint="Mono_Posix_Stdlib__IOFBF")]
487                 private static extern int GetFullyBuffered ();
488
489                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
490                                 EntryPoint="Mono_Posix_Stdlib__IOLBF")]
491                 private static extern int GetLineBuffered ();
492
493                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
494                                 EntryPoint="Mono_Posix_Stdlib__IONBF")]
495                 private static extern int GetNonBuffered ();
496
497                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
498                                 EntryPoint="Mono_Posix_Stdlib_BUFSIZ")]
499                 private static extern int GetBufferSize ();
500
501                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
502                                 EntryPoint="Mono_Posix_Stdlib_CreateFilePosition")]
503                 internal static extern IntPtr CreateFilePosition ();
504
505                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
506                                 EntryPoint="Mono_Posix_Stdlib_DumpFilePosition")]
507                 internal static extern int DumpFilePosition (StringBuilder buf, HandleRef handle, int len);
508
509                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
510                                 EntryPoint="Mono_Posix_Stdlib_EOF")]
511                 private static extern int GetEOF ();
512
513                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
514                                 EntryPoint="Mono_Posix_Stdlib_FILENAME_MAX")]
515                 private static extern int GetFilenameMax ();
516
517                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
518                                 EntryPoint="Mono_Posix_Stdlib_FOPEN_MAX")]
519                 private static extern int GetFopenMax ();
520
521                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
522                                 EntryPoint="Mono_Posix_Stdlib_L_tmpnam")]
523                 private static extern int GetTmpnamLength ();
524
525                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
526                                 EntryPoint="Mono_Posix_Stdlib_stdin")]
527                 private static extern IntPtr GetStandardInput ();
528
529                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
530                                 EntryPoint="Mono_Posix_Stdlib_stdout")]
531                 private static extern IntPtr GetStandardOutput ();
532
533                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
534                                 EntryPoint="Mono_Posix_Stdlib_stderr")]
535                 private static extern IntPtr GetStandardError ();
536
537                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
538                                 EntryPoint="Mono_Posix_Stdlib_TMP_MAX")]
539                 private static extern int GetTmpMax ();
540
541                 public static readonly int    _IOFBF       = GetFullyBuffered ();
542                 public static readonly int    _IOLBF       = GetLineBuffered ();
543                 public static readonly int    _IONBF       = GetNonBuffered ();
544                 public static readonly int    BUFSIZ       = GetBufferSize ();
545                 public static readonly int    EOF          = GetEOF ();
546                 public static readonly int    FOPEN_MAX    = GetFopenMax ();
547                 public static readonly int    FILENAME_MAX = GetFilenameMax ();
548                 public static readonly int    L_tmpnam     = GetTmpnamLength ();
549                 public static readonly IntPtr stderr       = GetStandardError ();
550                 public static readonly IntPtr stdin        = GetStandardInput ();
551                 public static readonly IntPtr stdout       = GetStandardOutput ();
552                 public static readonly int    TMP_MAX      = GetTmpMax ();
553
554                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
555                 public static extern int remove (
556                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
557                                 string filename);
558
559                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
560                 public static extern int rename (
561                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
562                                 string oldpath, 
563                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
564                                 string newpath);
565
566                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
567                 public static extern IntPtr tmpfile ();
568
569                 private static object tmpnam_lock = new object ();
570
571                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
572                                 SetLastError=true, EntryPoint="tmpnam")]
573                 private static extern IntPtr sys_tmpnam (StringBuilder s);
574
575                 [Obsolete ("Syscall.mkstemp() should be preferred.", true)]
576                 public static string tmpnam (StringBuilder s)
577                 {
578                         if (s != null && s.Capacity < L_tmpnam)
579                                 throw new ArgumentOutOfRangeException ("s", "s.Capacity < L_tmpnam");
580                         lock (tmpnam_lock) {
581                                 IntPtr r = sys_tmpnam (s);
582                                 return UnixMarshal.PtrToString (r);
583                         }
584                 }
585
586                 [Obsolete ("Syscall.mkstemp() should be preferred.", true)]
587                 public static string tmpnam ()
588                 {
589                         lock (tmpnam_lock) {
590                                 IntPtr r = sys_tmpnam (null);
591                                 return UnixMarshal.PtrToString (r);
592                         }
593                 }
594
595                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
596                 public static extern int fclose (IntPtr stream);
597
598                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
599                 public static extern int fflush (IntPtr stream);
600
601                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
602                 public static extern IntPtr fopen (
603                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
604                                 string path, string mode);
605
606                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
607                 public static extern IntPtr freopen (
608                                 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))]
609                                 string path, string mode, IntPtr stream);
610
611                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
612                 public static extern void setbuf (IntPtr stream, IntPtr buf);
613
614                 public static unsafe void setbuf (IntPtr stream, byte* buf)
615                 {
616                         setbuf (stream, (IntPtr) buf);
617                 }
618
619                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
620                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_setvbuf")]
621                 public static extern int setvbuf (IntPtr stream, IntPtr buf, int mode, ulong size);
622
623                 public static unsafe int setvbuf (IntPtr stream, byte* buf, int mode, ulong size)
624                 {
625                         return setvbuf (stream, (IntPtr) buf, mode, size);
626                 }
627
628                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
629                                 EntryPoint="fprintf")]
630                 private static extern int sys_fprintf (IntPtr stream, string format, string message);
631
632                 public static int fprintf (IntPtr stream, string message)
633                 {
634                         return sys_fprintf (stream, "%s", message);
635                 }
636
637                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
638                                 "Use fprintf (IntPtr, string) instead.", true)]
639                 public static int fprintf (IntPtr stream, string format, params object[] parameters)
640                 {
641                         object[] _parameters = new object[checked(parameters.Length+2)];
642                         _parameters [0] = stream;
643                         _parameters [1] = format;
644                         Array.Copy (parameters, 0, _parameters, 2, parameters.Length);
645                         return (int) XPrintfFunctions.fprintf (_parameters);
646                 }
647
648                 /* SKIP: fscanf(3) */
649
650                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
651                                 EntryPoint="printf")]
652                 private static extern int sys_printf (string format, string message);
653
654                 public static int printf (string message)
655                 {
656                         return sys_printf ("%s", message);
657                 }
658
659                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
660                                 "Use printf (string) instead.", true)]
661                 public static int printf (string format, params object[] parameters)
662                 {
663                         object[] _parameters = new object[checked(parameters.Length+1)];
664                         _parameters [0] = format;
665                         Array.Copy (parameters, 0, _parameters, 1, parameters.Length);
666                         return (int) XPrintfFunctions.printf (_parameters);
667                 }
668
669                 /* SKIP: scanf(3) */
670
671                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
672                                 EntryPoint="Mono_Posix_Stdlib_snprintf")]
673                 private static extern int sys_snprintf (StringBuilder s, ulong n, 
674                                 string format, string message);
675
676                 public static int snprintf (StringBuilder s, ulong n, string message)
677                 {
678                         if (n > (ulong) s.Capacity)
679                                 throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
680                         return sys_snprintf (s, n, "%s", message);
681                 }
682
683                 public static int snprintf (StringBuilder s, string message)
684                 {
685                         return sys_snprintf (s, (ulong) s.Capacity, "%s", message);
686                 }
687
688                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
689                                 "Use snprintf (StringBuilder, string) instead.", true)]
690                 public static int snprintf (StringBuilder s, ulong n, 
691                                 string format, params object[] parameters)
692                 {
693                         if (n > (ulong) s.Capacity)
694                                 throw new ArgumentOutOfRangeException ("n", "n must be <= s.Capacity");
695
696                         object[] _parameters = new object[checked(parameters.Length+3)];
697                         _parameters [0] = s;
698                         _parameters [1] = n;
699                         _parameters [2] = format;
700                         Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
701                         return (int) XPrintfFunctions.snprintf (_parameters);
702                 }
703
704                 [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
705                                 "Use snprintf (StringBuilder, string) instead.", true)]
706                 public static int snprintf (StringBuilder s,
707                                 string format, params object[] parameters)
708                 {
709                         object[] _parameters = new object[checked(parameters.Length+3)];
710                         _parameters [0] = s;
711                         _parameters [1] = (ulong) s.Capacity;
712                         _parameters [2] = format;
713                         Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
714                         return (int) XPrintfFunctions.snprintf (_parameters);
715                 }
716
717                 /*
718                  * SKIP:
719                  *    sprintf(3)
720                  *    sscanf(3)
721                  *    vfprintf(3)
722                  *    vfscanf(3)
723                  *    vprintf(3)
724                  *    vscanf(3)
725                  *    vsnprintf(3)
726                  *    vsprint(3)
727                  *    vsscanf(3)
728                  */
729
730                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
731                 public static extern int fgetc (IntPtr stream);
732
733                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
734                                 SetLastError=true, EntryPoint="fgets")]
735                 private static extern IntPtr sys_fgets (StringBuilder sb, int size, IntPtr stream);
736
737                 public static StringBuilder fgets (StringBuilder sb, int size, IntPtr stream)
738                 {
739                         IntPtr r = sys_fgets (sb, size, stream);
740                         if (r == IntPtr.Zero)
741                                 return null;
742                         return sb;
743                 }
744
745                 public static StringBuilder fgets (StringBuilder sb, IntPtr stream)
746                 {
747                         return fgets (sb, sb.Capacity, stream);
748                 }
749
750                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
751                 public static extern int fputc (int c, IntPtr stream);
752
753                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
754                 public static extern int fputs (string s, IntPtr stream);
755
756                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
757                 public static extern int getc (IntPtr stream);
758
759                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
760                 public static extern int getchar ();
761
762                 /* SKIP: gets(3) */
763
764                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
765                 public static extern int putc (int c, IntPtr stream);
766
767                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
768                 public static extern int putchar (int c);
769
770                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
771                 public static extern int puts (string s);
772
773                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
774                 public static extern int ungetc (int c, IntPtr stream);
775
776                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
777                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
778                 public static extern ulong fread (IntPtr ptr, ulong size, ulong nmemb, IntPtr stream);
779
780                 public static unsafe ulong fread (void* ptr, ulong size, ulong nmemb, IntPtr stream)
781                 {
782                         return fread ((IntPtr) ptr, size, nmemb, stream);
783                 }
784
785                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
786                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fread")]
787                 private static extern ulong sys_fread ([Out] byte[] ptr, 
788                                 ulong size, ulong nmemb, IntPtr stream);
789
790                 public static ulong fread (byte[] ptr, ulong size, ulong nmemb, IntPtr stream)
791                 {
792                         if ((size * nmemb) > (ulong) ptr.Length)
793                                 throw new ArgumentOutOfRangeException ("nmemb");
794                         return sys_fread (ptr, size, nmemb, stream);
795                 }
796
797                 public static ulong fread (byte[] ptr, IntPtr stream)
798                 {
799                         return fread (ptr, 1, (ulong) ptr.Length, stream);
800                 }
801
802                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
803                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
804                 public static extern ulong fwrite (IntPtr ptr, ulong size, ulong nmemb, IntPtr stream);
805
806                 public static unsafe ulong fwrite (void* ptr, ulong size, ulong nmemb, IntPtr stream)
807                 {
808                         return fwrite ((IntPtr) ptr, size, nmemb, stream);
809                 }
810
811                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
812                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fwrite")]
813                 private static extern ulong sys_fwrite (byte[] ptr, 
814                                 ulong size, ulong nmemb, IntPtr stream);
815
816                 public static ulong fwrite (byte[] ptr, ulong size, ulong nmemb, IntPtr stream)
817                 {
818                         if ((size * nmemb) > (ulong) ptr.Length)
819                                 throw new ArgumentOutOfRangeException ("nmemb");
820                         return sys_fwrite (ptr, size, nmemb, stream);
821                 }
822
823                 public static ulong fwrite (byte[] ptr, IntPtr stream)
824                 {
825                         return fwrite (ptr, 1, (ulong) ptr.Length, stream);
826                 }
827
828                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
829                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fgetpos")]
830                 private static extern int sys_fgetpos (IntPtr stream, HandleRef pos);
831
832                 public static int fgetpos (IntPtr stream, FilePosition pos)
833                 {
834                         return sys_fgetpos (stream, pos.Handle);
835                 }
836
837                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
838                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fseek")]
839                 private static extern int sys_fseek (IntPtr stream, long offset, int origin);
840
841                 public static int fseek (IntPtr stream, long offset, SeekFlags origin)
842                 {
843                         int _origin = UnixConvert.FromSeekFlags (origin);
844                         return sys_fseek (stream, offset, _origin);
845                 }
846
847                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
848                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_fsetpos")]
849                 private static extern int sys_fsetpos (IntPtr stream, HandleRef pos);
850
851                 public static int fsetpos (IntPtr stream, FilePosition pos)
852                 {
853                         return sys_fsetpos (stream, pos.Handle);
854                 }
855
856                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
857                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_ftell")]
858                 public static extern long ftell (IntPtr stream);
859
860                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
861                 public static extern void rewind (IntPtr stream);
862
863                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
864                 public static extern void clearerr (IntPtr stream);
865
866                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
867                 public static extern int feof (IntPtr stream);
868
869                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
870                 public static extern int ferror (IntPtr stream);
871
872                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
873                 public static extern void perror (string s);
874
875                 //
876                 // <stdlib.h>
877                 //
878                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
879                                 EntryPoint="Mono_Posix_Stdlib_EXIT_FAILURE")]
880                 private static extern int GetExitFailure();
881
882                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
883                                 EntryPoint="Mono_Posix_Stdlib_EXIT_SUCCESS")]
884                 private static extern int GetExitSuccess ();
885
886                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
887                                 EntryPoint="Mono_Posix_Stdlib_MB_CUR_MAX")]
888                 private static extern int GetMbCurMax ();
889
890                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
891                                 EntryPoint="Mono_Posix_Stdlib_RAND_MAX")]
892                 private static extern int GetRandMax ();
893
894                 public static readonly int  EXIT_FAILURE = GetExitFailure ();
895                 public static readonly int  EXIT_SUCCESS = GetExitSuccess ();
896                 public static readonly int  MB_CUR_MAX   = GetMbCurMax ();
897                 public static readonly int  RAND_MAX     = GetRandMax ();
898
899                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
900                 public static extern int rand ();
901
902                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
903                 public static extern void srand (uint seed);
904
905                 // calloc(3):
906                 //    void *calloc (size_t nmemb, size_t size);
907                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
908                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_calloc")]
909                 public static extern IntPtr calloc (ulong nmemb, ulong size);
910
911                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
912                 public static extern void free (IntPtr ptr);
913
914                 // malloc(3):
915                 //    void *malloc(size_t size);
916                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
917                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_malloc")]
918                 public static extern IntPtr malloc (ulong size);
919
920                 // realloc(3):
921                 //    void *realloc(void *ptr, size_t size);
922                 [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,
923                                 SetLastError=true, EntryPoint="Mono_Posix_Stdlib_realloc")]
924                 public static extern IntPtr realloc (IntPtr ptr, ulong size);
925
926                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
927                 public static extern void abort ();
928
929                 /* SKIP: atexit(3) -- the GC should have collected most references by the
930                  * time this runs, so no delegates should exist, making it pointless. */
931
932                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
933                 public static extern void exit (int status);
934
935                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl)]
936                 public static extern void _Exit (int status);
937
938                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, EntryPoint="getenv")]
939                 private static extern IntPtr sys_getenv (string name);
940
941                 public static string getenv (string name)
942                 {
943                         IntPtr r = sys_getenv (name);
944                         return UnixMarshal.PtrToString (r);
945                 }
946
947                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl, SetLastError=true)]
948                 public static extern int system (string @string);
949
950                 //
951                 // <string.h>
952                 //
953
954                 private static object strerror_lock = new object ();
955
956                 [DllImport (LIBC, CallingConvention=CallingConvention.Cdecl,
957                                 SetLastError=true, EntryPoint="strerror")]
958                 private static extern IntPtr sys_strerror (int errnum);
959
960                 public static string strerror (Error errnum)
961                 {
962                         int e = UnixConvert.FromError (errnum);
963                         lock (strerror_lock) {
964                                 IntPtr r = sys_strerror (e);
965                                 return UnixMarshal.PtrToString (r);
966                         }
967                 }
968         }
969
970         #endregion // Classes
971 }
972
973 // vim: noexpandtab