* UnixPath.cs: Add ReadLink() and TryReadLink() methods.
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / StdioFileStream.cs
index 10e907240690a3deaae38fcfcabfcbb6fb6ebb0e..ee2436a9f2be24cbec6b9debdd0b1b65327721db 100644 (file)
@@ -4,7 +4,7 @@
 // Authors:
 //   Jonathan Pryor (jonpryor@vt.edu)
 //
-// (C) 2005 Jonathan Pryor
+// (C) 2005-2006 Jonathan Pryor
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -37,9 +37,9 @@ namespace Mono.Unix {
        public class StdioFileStream : Stream
        {
                public static readonly IntPtr InvalidFileStream  = IntPtr.Zero;
-               public static readonly IntPtr StandardInput  = Stdlib.stdin;
-               public static readonly IntPtr StandardOutput = Stdlib.stdout;
-               public static readonly IntPtr StandardError  = Stdlib.stderr;
+               public static readonly IntPtr StandardInput  = Native.Stdlib.stdin;
+               public static readonly IntPtr StandardOutput = Native.Stdlib.stdout;
+               public static readonly IntPtr StandardError  = Native.Stdlib.stderr;
 
                public StdioFileStream (IntPtr fileStream)
                        : this (fileStream, true) {}
@@ -60,7 +60,7 @@ namespace Mono.Unix {
 
                public StdioFileStream (string path)
                {
-                       InitStream (Fopen (path, "r"), true);
+                       InitStream (Fopen (path, "rb"), true);
                }
 
                public StdioFileStream (string path, string mode)
@@ -92,8 +92,8 @@ namespace Mono.Unix {
                        if (path.Length == 0)
                                throw new ArgumentException ("path");
                        if (mode == null)
-                               throw new ArgumentNullException ("path");
-                       IntPtr f = Stdlib.fopen (path, mode);
+                               throw new ArgumentNullException ("mode");
+                       IntPtr f = Native.Stdlib.fopen (path, mode);
                        if (f == IntPtr.Zero)
                                throw new DirectoryNotFoundException ("path", 
                                                UnixMarshal.CreateExceptionForLastError ());
@@ -109,20 +109,21 @@ namespace Mono.Unix {
                        this.owner = ownsHandle;
                        
                        try {
-                               long offset = Stdlib.fseek (file, 0, SeekFlags.SEEK_CUR);
+                               long offset = Native.Stdlib.fseek (file, 0, Native.SeekFlags.SEEK_CUR);
                                if (offset != -1)
                                        canSeek = true;
-                               Stdlib.fread (IntPtr.Zero, 0, 0, file);
-                               if (Stdlib.ferror (file) == 0)
+                               Native.Stdlib.fread (IntPtr.Zero, 0, 0, file);
+                               if (Native.Stdlib.ferror (file) == 0)
                                        canRead = true;
-                               Stdlib.fwrite (IntPtr.Zero, 0, 0, file);
-                               if (Stdlib.ferror (file) == 0)
+                               Native.Stdlib.fwrite (IntPtr.Zero, 0, 0, file);
+                               if (Native.Stdlib.ferror (file) == 0)
                                        canWrite = true;  
-                               Stdlib.clearerr (file);
+                               Native.Stdlib.clearerr (file);
                        }
                        catch (Exception e) {
                                throw new ArgumentException (Locale.GetText ("Invalid file stream"), "fileStream");
                        }
+                       GC.KeepAlive (this);
                }
 
                private void InitCanReadWrite (FileAccess access)
@@ -135,19 +136,19 @@ namespace Mono.Unix {
 
                private static string ToFopenMode (string file, FileMode mode)
                {
-                       string cmode = UnixConvert.ToFopenMode (mode);
+                       string cmode = Native.NativeConvert.ToFopenMode (mode);
                        AssertFileMode (file, mode);
                        return cmode;
                }
 
                private static string ToFopenMode (string file, FileAccess access)
                {
-                       return UnixConvert.ToFopenMode (access);
+                       return Native.NativeConvert.ToFopenMode (access);
                }
 
                private static string ToFopenMode (string file, FileMode mode, FileAccess access)
                {
-                       string cmode = UnixConvert.ToFopenMode (mode, access);
+                       string cmode = Native.NativeConvert.ToFopenMode (mode, access);
                        bool exists = AssertFileMode (file, mode);
                        // HACK: for open-or-create & read, mode is "rb", which doesn't create
                        // files.  If the file doesn't exist, we need to use "w+b" to ensure
@@ -170,10 +171,10 @@ namespace Mono.Unix {
                private static bool FileExists (string file)
                {
                        bool found = false;
-                       IntPtr f = Stdlib.fopen (file, "r");
+                       IntPtr f = Native.Stdlib.fopen (file, "r");
                        found = f != IntPtr.Zero;
                        if (f != IntPtr.Zero)
-                               Stdlib.fclose (f);
+                               Native.Stdlib.fclose (f);
                        return found;
                }
 
@@ -181,10 +182,15 @@ namespace Mono.Unix {
                {
                        if (file == InvalidFileStream)
                                throw new ObjectDisposedException ("Invalid File Stream");
+                       GC.KeepAlive (this);
                }
 
                public IntPtr Handle {
-                       get {AssertNotDisposed (); return file;}
+                       get {
+                               AssertNotDisposed (); 
+                               GC.KeepAlive (this);
+                               return file;
+                       }
                }
 
                public override bool CanRead {
@@ -204,19 +210,20 @@ namespace Mono.Unix {
                                AssertNotDisposed ();
                                if (!CanSeek)
                                        throw new NotSupportedException ("File Stream doesn't support seeking");
-                               long curPos = Stdlib.ftell (file);
+                               long curPos = Native.Stdlib.ftell (file);
                                if (curPos == -1)
                                        throw new NotSupportedException ("Unable to obtain current file position");
-                               int r = Stdlib.fseek (file, 0, SeekFlags.SEEK_END);
+                               int r = Native.Stdlib.fseek (file, 0, Native.SeekFlags.SEEK_END);
                                UnixMarshal.ThrowExceptionForLastErrorIf (r);
 
-                               long endPos = Stdlib.ftell (file);
+                               long endPos = Native.Stdlib.ftell (file);
                                if (endPos == -1)
                                        UnixMarshal.ThrowExceptionForLastError ();
 
-                               r = Stdlib.fseek (file, curPos, SeekFlags.SEEK_SET);
+                               r = Native.Stdlib.fseek (file, curPos, Native.SeekFlags.SEEK_SET);
                                UnixMarshal.ThrowExceptionForLastErrorIf (r);
 
+                               GC.KeepAlive (this);
                                return endPos;
                        }
                }
@@ -226,9 +233,10 @@ namespace Mono.Unix {
                                AssertNotDisposed ();
                                if (!CanSeek)
                                        throw new NotSupportedException ("The stream does not support seeking");
-                               long pos = Stdlib.ftell (file);
+                               long pos = Native.Stdlib.ftell (file);
                                if (pos == -1)
                                        UnixMarshal.ThrowExceptionForLastError ();
+                               GC.KeepAlive (this);
                                return (long) pos;
                        }
                        set {
@@ -237,29 +245,31 @@ namespace Mono.Unix {
                        }
                }
 
-               public FilePosition FilePosition {
-                       get {
-                               AssertNotDisposed ();
-                               FilePosition pos = new FilePosition ();
-                               int r = Stdlib.fgetpos (file, pos);
-                               UnixMarshal.ThrowExceptionForLastErrorIf (r);
-                               return pos;
-                       }
-                       set {
-                               AssertNotDisposed ();
-                               if (value == null)
-                                       throw new ArgumentNullException ("value");
-                               int r = Stdlib.fsetpos (file, value);
-                               UnixMarshal.ThrowExceptionForLastErrorIf (r);
-                       }
+               public void SaveFilePosition (Native.FilePosition pos)
+               {
+                       AssertNotDisposed ();
+                       int r = Native.Stdlib.fgetpos (file, pos);
+                       UnixMarshal.ThrowExceptionForLastErrorIf (r);
+                       GC.KeepAlive (this);
+               }
+
+               public void RestoreFilePosition (Native.FilePosition pos)
+               {
+                       AssertNotDisposed ();
+                       if (pos == null)
+                               throw new ArgumentNullException ("value");
+                       int r = Native.Stdlib.fsetpos (file, pos);
+                       UnixMarshal.ThrowExceptionForLastErrorIf (r);
+                       GC.KeepAlive (this);
                }
 
                public override void Flush ()
                {
                        AssertNotDisposed ();
-                       int r = Stdlib.fflush (file);
+                       int r = Native.Stdlib.fflush (file);
                        if (r != 0)
                                UnixMarshal.ThrowExceptionForLastError ();
+                       GC.KeepAlive (this);
                }
 
                public override unsafe int Read ([In, Out] byte[] buffer, int offset, int count)
@@ -271,12 +281,13 @@ namespace Mono.Unix {
                                 
                        ulong r = 0;
                        fixed (byte* buf = &buffer[offset]) {
-                               r = Stdlib.fread (buf, 1, (ulong) count, file);
+                               r = Native.Stdlib.fread (buf, 1, (ulong) count, file);
                        }
                        if (r != (ulong) count) {
-                               if (Stdlib.ferror (file) != 0)
+                               if (Native.Stdlib.ferror (file) != 0)
                                        throw new IOException ();
                        }
+                       GC.KeepAlive (this);
                        return (int) r;
                }
 
@@ -297,7 +308,8 @@ namespace Mono.Unix {
                public void Rewind ()
                {
                        AssertNotDisposed ();
-                       Stdlib.rewind (file);
+                       Native.Stdlib.rewind (file);
+                       GC.KeepAlive (this);
                }
 
                public override long Seek (long offset, SeekOrigin origin)
@@ -306,24 +318,25 @@ namespace Mono.Unix {
                        if (!CanSeek)
                                throw new NotSupportedException ("The File Stream does not support seeking");
 
-                       SeekFlags sf = SeekFlags.SEEK_CUR;
+                       Native.SeekFlags sf = Native.SeekFlags.SEEK_CUR;
                        switch (origin) {
-                               case SeekOrigin.Begin:   sf = SeekFlags.SEEK_SET; break;
-                               case SeekOrigin.Current: sf = SeekFlags.SEEK_CUR; break;
-                               case SeekOrigin.End:     sf = SeekFlags.SEEK_END; break;
+                               case SeekOrigin.Begin:   sf = Native.SeekFlags.SEEK_SET; break;
+                               case SeekOrigin.Current: sf = Native.SeekFlags.SEEK_CUR; break;
+                               case SeekOrigin.End:     sf = Native.SeekFlags.SEEK_END; break;
                                default: throw new ArgumentException ("origin");
                        }
 
-                       int r = Stdlib.fseek (file, offset, sf);
+                       int r = Native.Stdlib.fseek (file, offset, sf);
                        if (r != 0)
                                throw new IOException ("Unable to seek",
                                                UnixMarshal.CreateExceptionForLastError ());
 
-                       long pos = Stdlib.ftell (file);
+                       long pos = Native.Stdlib.ftell (file);
                        if (pos == -1)
                                throw new IOException ("Unable to get current file position",
                                                UnixMarshal.CreateExceptionForLastError ());
 
+                       GC.KeepAlive (this);
                        return pos;
                }
 
@@ -341,10 +354,11 @@ namespace Mono.Unix {
 
                        ulong r = 0;
                        fixed (byte* buf = &buffer[offset]) {
-                               r = Stdlib.fwrite (buf, (ulong) 1, (ulong) count, file);
+                               r = Native.Stdlib.fwrite (buf, (ulong) 1, (ulong) count, file);
                        }
                        if (r != (ulong) count)
                                UnixMarshal.ThrowExceptionForLastError ();
+                       GC.KeepAlive (this);
                }
                
                ~StdioFileStream ()
@@ -357,18 +371,20 @@ namespace Mono.Unix {
                        if (file == InvalidFileStream)
                                return;
 
-                       GC.SuppressFinalize (this);
-                               
-                       Flush ();
                        if (owner) {
-                               int r = Stdlib.fclose (file);
+                               int r = Native.Stdlib.fclose (file);
                                if (r != 0)
                                        UnixMarshal.ThrowExceptionForLastError ();
-                       }
+                       } else
+                               Flush ();
+                               
                        file = InvalidFileStream;
                        canRead = false;
                        canSeek = false;
                        canWrite = false;
+
+                       GC.SuppressFinalize (this);
+                       GC.KeepAlive (this);
                }
                
                private bool canSeek  = false;