[corlib] Fixed FileStream Write after Read issue
[mono.git] / mcs / class / corlib / System.IO / FileStream.cs
index f68f53610a5e547806b45968571e9dc0f470b711..42a3984b11d2261adaef4c71aff20ccb7fa47de2 100644 (file)
@@ -58,64 +58,31 @@ namespace System.IO
                
                [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access) instead")]
                public FileStream (IntPtr handle, FileAccess access)
-                       : this (handle, access, true, DefaultBufferSize, false) {}
+                       : this (handle, access, true, DefaultBufferSize, false, false) {}
 
                [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access) instead")]
                public FileStream (IntPtr handle, FileAccess access, bool ownsHandle)
-                       : this (handle, access, ownsHandle, DefaultBufferSize, false) {}
+                       : this (handle, access, ownsHandle, DefaultBufferSize, false, false) {}
                
                [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead")]
                public FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize)
-                       : this (handle, access, ownsHandle, bufferSize, false) {}
+                       : this (handle, access, ownsHandle, bufferSize, false, false) {}
 
                [Obsolete ("Use FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead")]
                public FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync)
                        : this (handle, access, ownsHandle, bufferSize, isAsync, false) {}
 
                [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
-               internal FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync, bool isZeroSize)
+               internal FileStream (IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync, bool isConsoleWrapper)
                {
-                       this.handle = MonoIO.InvalidHandle;
-                       if (handle == this.handle)
+                       if (handle == MonoIO.InvalidHandle)
                                throw new ArgumentException ("handle", Locale.GetText ("Invalid."));
 
-                       if (access < FileAccess.Read || access > FileAccess.ReadWrite)
-                               throw new ArgumentOutOfRangeException ("access");
-
-                       MonoIOError error;
-                       MonoFileType ftype = MonoIO.GetFileType (handle, out error);
-
-                       if (error != MonoIOError.ERROR_SUCCESS) {
-                               throw MonoIO.GetException (name, error);
-                       }
-                       
-                       if (ftype == MonoFileType.Unknown) {
-                               throw new IOException ("Invalid handle.");
-                       } else if (ftype == MonoFileType.Disk) {
-                               this.canseek = true;
-                       } else {
-                               this.canseek = false;
-                       }
-
-                       this.handle = handle;
-                       ExposeHandle ();
-                       this.access = access;
-                       this.owner = ownsHandle;
-                       this.async = isAsync;
-                       this.anonymous = false;
-                       if (canseek) {
-                               buf_start = MonoIO.Seek (handle, 0, SeekOrigin.Current, out error);
-                               if (error != MonoIOError.ERROR_SUCCESS) {
-                                       throw MonoIO.GetException (name, error);
-                               }
-                       }
-
-                       /* Can't set append mode */
-                       this.append_startpos=0;
+                       Init (new SafeFileHandle (handle, false), access, ownsHandle, bufferSize, isAsync, isConsoleWrapper);
                }
 
                // construct from filename
-               
+
                public FileStream (string path, FileMode mode)
                        : this (path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, false, FileOptions.None)
                {
@@ -146,7 +113,6 @@ namespace System.IO
                {
                }
 
-#if !NET_2_1
                public FileStream (SafeFileHandle handle, FileAccess access)
                        :this(handle, access, DefaultBufferSize, false)
                {
@@ -157,15 +123,13 @@ namespace System.IO
                        :this(handle, access, bufferSize, false)
                {
                }
-               
-               [MonoLimitationAttribute("Need to use SafeFileHandle instead of underlying handle")]
-               public FileStream (SafeFileHandle handle, FileAccess access,
-                                  int bufferSize, bool isAsync)
-                       :this (handle.DangerousGetHandle (), access, false, bufferSize, isAsync)
+
+               public FileStream (SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync)
                {
-                       this.safeHandle = handle;
+                       Init (handle, access, false, bufferSize, isAsync, false);
                }
 
+#if !MOBILE
                [MonoLimitation ("This ignores the rights parameter")]
                public FileStream (string path, FileMode mode,
                                   FileSystemRights rights, FileShare share,
@@ -184,6 +148,11 @@ namespace System.IO
                }
 #endif
 
+               internal FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy, bool useLongPath = false, bool checkHost = false)
+                       : this (path, mode, access, share, bufferSize, false, options)
+               {
+               }
+
                internal FileStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool isAsync, bool anonymous)
                        : this (path, mode, access, share, bufferSize, anonymous, isAsync ? FileOptions.Asynchronous : FileOptions.None)
                {
@@ -281,18 +250,21 @@ namespace System.IO
 
                        MonoIOError error;
 
-                       this.handle = MonoIO.Open (path, mode, access, share, options, out error);
-                       if (handle == MonoIO.InvalidHandle) {
+                       var nativeHandle = MonoIO.Open (path, mode, access, share, options, out error);
+
+                       if (nativeHandle == MonoIO.InvalidHandle) {
                                // don't leak the path information for isolated storage
                                throw MonoIO.GetException (GetSecureFileName (path), error);
                        }
 
+                       this.safeHandle = new SafeFileHandle (nativeHandle, false);
+
                        this.access = access;
                        this.owner = true;
 
                        /* Can we open non-files by name? */
-                       
-                       if (MonoIO.GetFileType (handle, out error) == MonoFileType.Disk) {
+
+                       if (MonoIO.GetFileType (safeHandle, out error) == MonoFileType.Disk) {
                                this.canseek = true;
                                this.async = (options & FileOptions.Asynchronous) != 0;
                        } else {
@@ -319,6 +291,48 @@ namespace System.IO
                        }
                }
 
+               private void Init (SafeFileHandle safeHandle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync, bool isConsoleWrapper)
+               {
+                       if (!isConsoleWrapper && safeHandle.IsInvalid)
+                               throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHandle"), "handle");
+                       if (access < FileAccess.Read || access > FileAccess.ReadWrite)
+                               throw new ArgumentOutOfRangeException ("access");
+                       if (!isConsoleWrapper && bufferSize <= 0)
+                               throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+
+                       MonoIOError error;
+                       MonoFileType ftype = MonoIO.GetFileType (safeHandle, out error);
+
+                       if (error != MonoIOError.ERROR_SUCCESS) {
+                               throw MonoIO.GetException (name, error);
+                       }
+
+                       if (ftype == MonoFileType.Unknown) {
+                               throw new IOException ("Invalid handle.");
+                       } else if (ftype == MonoFileType.Disk) {
+                               this.canseek = true;
+                       } else {
+                               this.canseek = false;
+                       }
+
+                       this.safeHandle = safeHandle;
+                       ExposeHandle ();
+                       this.access = access;
+                       this.owner = ownsHandle;
+                       this.async = isAsync;
+                       this.anonymous = false;
+
+                       if (canseek) {
+                               buf_start = MonoIO.Seek (safeHandle, 0, SeekOrigin.Current, out error);
+                               if (error != MonoIOError.ERROR_SUCCESS) {
+                                       throw MonoIO.GetException (name, error);
+                               }
+                       }
+
+                       /* Can't set append mode */
+                       this.append_startpos=0;
+               }
+
                // properties
                
                public override bool CanRead {
@@ -355,7 +369,7 @@ namespace System.IO
 
                public override long Length {
                        get {
-                               if (handle == MonoIO.InvalidHandle)
+                               if (safeHandle.IsClosed)
                                        throw new ObjectDisposedException ("Stream has been closed");
 
                                if (!CanSeek)
@@ -365,9 +379,9 @@ namespace System.IO
                                FlushBufferIfDirty ();
 
                                MonoIOError error;
-                               long length;
-                               
-                               length = MonoIO.GetLength (handle, out error);
+
+                               long length = MonoIO.GetLength (safeHandle, out error);
+
                                if (error != MonoIOError.ERROR_SUCCESS) {
                                        // don't leak the path information for isolated storage
                                        throw MonoIO.GetException (GetSecureFileName (name), error);
@@ -379,33 +393,30 @@ namespace System.IO
 
                public override long Position {
                        get {
-                               if (handle == MonoIO.InvalidHandle)
+                               if (safeHandle.IsClosed)
                                        throw new ObjectDisposedException ("Stream has been closed");
 
                                if (CanSeek == false)
                                        throw new NotSupportedException("The stream does not support seeking");
 
-                               if (safeHandle != null) {
-                                       // If the handle was leaked outside we always ask the real handle
-                                       MonoIOError error;
+                               if (!isExposed)
+                                       return(buf_start + buf_offset);
 
-                                       long ret = MonoIO.Seek (handle, 0,SeekOrigin.Current,out error);
+                               // If the handle was leaked outside we always ask the real handle
+                               MonoIOError error;
 
-                                       if (error != MonoIOError.ERROR_SUCCESS) {
-                                               // don't leak the path information for isolated storage
-                                               throw MonoIO.GetException (GetSecureFileName (name), error);
-                                       }
+                               long ret = MonoIO.Seek (safeHandle, 0, SeekOrigin.Current, out error);
 
-                                       return ret;
+                               if (error != MonoIOError.ERROR_SUCCESS) {
+                                       // don't leak the path information for isolated storage
+                                       throw MonoIO.GetException (GetSecureFileName (name), error);
                                }
-       
-                               return(buf_start + buf_offset);
+
+                               return ret;
                        }
                        set {
-                               if(value < 0) {
-                                       throw new ArgumentOutOfRangeException("Attempt to set the position to a negative value");
-                               }
-                               
+                               if (value < 0) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
                                Seek (value, SeekOrigin.Begin);
                        }
                }
@@ -415,9 +426,9 @@ namespace System.IO
                        [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                        [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
                        get {
-                               if (safeHandle == null) {
+                               var handle = safeHandle.DangerousGetHandle ();
+                               if (!isExposed)
                                        ExposeHandle ();
-                               }
                                return handle;
                        }
                }
@@ -426,32 +437,31 @@ namespace System.IO
                        [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
                        [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
                        get {
-                               if (safeHandle == null) {
+                               if (!isExposed)
                                        ExposeHandle ();
-                               }
                                return safeHandle;
                        }
                }
 
-               // methods
-
-         void ExposeHandle ()
+               void ExposeHandle ()
                {
-                       safeHandle = new SafeFileHandle (handle, false);
+                       isExposed = true;
                        FlushBuffer ();
                        InitBuffer (0, true);
                }
 
+               // methods
+
                public override int ReadByte ()
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
 
                        if (!CanRead)
                                throw new NotSupportedException ("Stream does not support reading");
-                       
+
                        if (buf_size == 0) {
-                               int n = ReadData (handle, buf, 0, 1);
+                               int n = ReadData (safeHandle, buf, 0, 1);
                                if (n == 0) return -1;
                                else return buf[0];
                        }
@@ -467,7 +477,7 @@ namespace System.IO
 
                public override void WriteByte (byte value)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
 
                        if (!CanWrite)
@@ -493,7 +503,7 @@ namespace System.IO
 
                public override int Read ([In,Out] byte[] array, int offset, int count)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
                        if (array == null)
                                throw new ArgumentNullException ("array");
@@ -527,24 +537,21 @@ namespace System.IO
                        
                        int copied = n;
                        count -= n;
+
                        if (count > buf_size) {
                                /* Read as much as we can, up
                                 * to count bytes
                                 */
                                FlushBuffer();
-                               n = ReadData (handle, dest,
-                                             offset+n,
-                                             count);
-                       
+                               n = ReadData (safeHandle, dest, offset+n, count);
+
                                /* Make the next buffer read
                                 * start from the right place
                                 */
                                buf_start += n;
                        } else {
                                RefillBuffer ();
-                               n = ReadSegment (dest,
-                                                offset+copied,
-                                                count);
+                               n = ReadSegment (dest, offset+copied, count);
                        }
 
                        return copied + n;
@@ -555,7 +562,7 @@ namespace System.IO
                public override IAsyncResult BeginRead (byte [] array, int offset, int numBytes,
                                                        AsyncCallback userCallback, object stateObject)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
 
                        if (!CanRead)
@@ -602,7 +609,7 @@ namespace System.IO
 
                public override void Write (byte[] array, int offset, int count)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
                        if (array == null)
                                throw new ArgumentNullException ("array");
@@ -632,16 +639,23 @@ namespace System.IO
                                MonoIOError error;
 
                                FlushBuffer ();
+
+                               if (CanSeek && !isExposed) {
+                                       MonoIO.Seek (safeHandle, buf_start, SeekOrigin.Begin, out error);
+                                       if (error != MonoIOError.ERROR_SUCCESS)
+                                               throw MonoIO.GetException (GetSecureFileName (name), error);
+                               }
+
                                int wcount = count;
-                               
+
                                while (wcount > 0){
-                                       int n = MonoIO.Write (handle, src, offset, wcount, out error);
+                                       int n = MonoIO.Write (safeHandle, src, offset, wcount, out error);
                                        if (error != MonoIOError.ERROR_SUCCESS)
                                                throw MonoIO.GetException (GetSecureFileName (name), error);
-                                       
+
                                        wcount -= n;
                                        offset += n;
-                               } 
+                               }
                                buf_start += count;
                        } else {
 
@@ -666,7 +680,7 @@ namespace System.IO
                public override IAsyncResult BeginWrite (byte [] array, int offset, int numBytes,
                                                        AsyncCallback userCallback, object stateObject)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
 
                        if (!CanWrite)
@@ -692,7 +706,7 @@ namespace System.IO
                        result.BytesRead = -1;
                        result.Count = numBytes;
                        result.OriginalCount = numBytes;
-
+/*
                        if (buf_dirty) {
                                MemoryStream ms = new MemoryStream ();
                                FlushBuffer (ms);
@@ -703,9 +717,9 @@ namespace System.IO
                                array = ms.ToArray ();
                                numBytes = array.Length;
                        }
-
+*/
                        WriteDelegate w = WriteInternal;
-                       return w.BeginInvoke (array, offset, numBytes, userCallback, stateObject);                      
+                       return w.BeginInvoke (array, offset, numBytes, userCallback, stateObject);      
                }
                
                public override void EndWrite (IAsyncResult asyncResult)
@@ -734,7 +748,7 @@ namespace System.IO
                {
                        long pos;
 
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
                        
                        // make absolute
@@ -775,10 +789,8 @@ namespace System.IO
                        FlushBuffer ();
 
                        MonoIOError error;
-               
-                       buf_start = MonoIO.Seek (handle, pos,
-                                                SeekOrigin.Begin,
-                                                out error);
+
+                       buf_start = MonoIO.Seek (safeHandle, pos, SeekOrigin.Begin, out error);
 
                        if (error != MonoIOError.ERROR_SUCCESS) {
                                // don't leak the path information for isolated storage
@@ -790,7 +802,7 @@ namespace System.IO
 
                public override void SetLength (long value)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
 
                        if(CanSeek == false)
@@ -802,11 +814,11 @@ namespace System.IO
                        if(value < 0)
                                throw new ArgumentOutOfRangeException("value is less than 0");
                        
-                       Flush ();
+                       FlushBuffer ();
 
                        MonoIOError error;
-                       
-                       MonoIO.SetLength (handle, value, out error);
+
+                       MonoIO.SetLength (safeHandle, value, out error);
                        if (error != MonoIOError.ERROR_SUCCESS) {
                                // don't leak the path information for isolated storage
                                throw MonoIO.GetException (GetSecureFileName (name), error);
@@ -818,7 +830,7 @@ namespace System.IO
 
                public override void Flush ()
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
 
                        FlushBuffer ();
@@ -826,18 +838,21 @@ namespace System.IO
 
                public virtual void Flush (bool flushToDisk)
                {
+                       if (safeHandle.IsClosed)
+                               throw new ObjectDisposedException ("Stream has been closed");
+
                        FlushBuffer ();
 
                        // This does the fsync
                        if (flushToDisk){
                                MonoIOError error;
-                               MonoIO.Flush (handle, out error);
+                               MonoIO.Flush (safeHandle, out error);
                        }
                }
 
                public virtual void Lock (long position, long length)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
                        if (position < 0) {
                                throw new ArgumentOutOfRangeException ("position must not be negative");
@@ -845,13 +860,10 @@ namespace System.IO
                        if (length < 0) {
                                throw new ArgumentOutOfRangeException ("length must not be negative");
                        }
-                       if (handle == MonoIO.InvalidHandle) {
-                               throw new ObjectDisposedException ("Stream has been closed");
-                       }
-                               
+
                        MonoIOError error;
 
-                       MonoIO.Lock (handle, position, length, out error);
+                       MonoIO.Lock (safeHandle, position, length, out error);
                        if (error != MonoIOError.ERROR_SUCCESS) {
                                // don't leak the path information for isolated storage
                                throw MonoIO.GetException (GetSecureFileName (name), error);
@@ -860,7 +872,7 @@ namespace System.IO
 
                public virtual void Unlock (long position, long length)
                {
-                       if (handle == MonoIO.InvalidHandle)
+                       if (safeHandle.IsClosed)
                                throw new ObjectDisposedException ("Stream has been closed");
                        if (position < 0) {
                                throw new ArgumentOutOfRangeException ("position must not be negative");
@@ -868,10 +880,10 @@ namespace System.IO
                        if (length < 0) {
                                throw new ArgumentOutOfRangeException ("length must not be negative");
                        }
-                               
+
                        MonoIOError error;
 
-                       MonoIO.Unlock (handle, position, length, out error);
+                       MonoIO.Unlock (safeHandle, position, length, out error);
                        if (error != MonoIOError.ERROR_SUCCESS) {
                                // don't leak the path information for isolated storage
                                throw MonoIO.GetException (GetSecureFileName (name), error);
@@ -888,7 +900,7 @@ namespace System.IO
                protected override void Dispose (bool disposing)
                {
                        Exception exc = null;
-                       if (handle != MonoIO.InvalidHandle) {
+                       if (safeHandle != null && !safeHandle.IsClosed) {
                                try {
                                        // If the FileStream is in "exposed" status
                                        // it means that we do not have a buffer(we write the data without buffering)
@@ -900,14 +912,14 @@ namespace System.IO
 
                                if (owner) {
                                        MonoIOError error;
-                               
-                                       MonoIO.Close (handle, out error);
+
+                                       MonoIO.Close (safeHandle.DangerousGetHandle (), out error);
                                        if (error != MonoIOError.ERROR_SUCCESS) {
                                                // don't leak the path information for isolated storage
                                                throw MonoIO.GetException (GetSecureFileName (name), error);
                                        }
 
-                                       handle = MonoIO.InvalidHandle;
+                                       safeHandle.DangerousRelease ();
                                }
                        }
 
@@ -933,6 +945,9 @@ namespace System.IO
 #if !NET_2_1
                public FileSecurity GetAccessControl ()
                {
+                       if (safeHandle.IsClosed)
+                               throw new ObjectDisposedException ("Stream has been closed");
+
                        return new FileSecurity (SafeFileHandle,
                                                 AccessControlSections.Owner |
                                                 AccessControlSections.Group |
@@ -941,6 +956,9 @@ namespace System.IO
                
                public void SetAccessControl (FileSecurity fileSecurity)
                {
+                       if (safeHandle.IsClosed)
+                               throw new ObjectDisposedException ("Stream has been closed");
+
                        if (null == fileSecurity)
                                throw new ArgumentNullException ("fileSecurity");
                                
@@ -950,6 +968,9 @@ namespace System.IO
 
                public override Task FlushAsync (CancellationToken cancellationToken)
                {
+                       if (safeHandle.IsClosed)
+                               throw new ObjectDisposedException ("Stream has been closed");
+
                        return base.FlushAsync (cancellationToken);
                }
 
@@ -976,7 +997,7 @@ namespace System.IO
                        
                        if (count > 0) {
                                // Use the fastest method, all range checks has been done
-                               Buffer.BlockCopyInternal (buf, buf_offset, dest, dest_offset, count);
+                               Buffer.InternalBlockCopy (buf, buf_offset, dest, dest_offset, count);
                                buf_offset += count;
                        }
                        
@@ -1005,25 +1026,25 @@ namespace System.IO
                        return(count);
                }
 
-               void FlushBuffer (Stream st)
+               void FlushBuffer ()
                {
                        if (buf_dirty) {
-                               MonoIOError error;
+//                             if (st == null) {
+                                       MonoIOError error;
 
-                               if (CanSeek == true && safeHandle == null) {
-                                       MonoIO.Seek (handle, buf_start,
-                                                    SeekOrigin.Begin,
-                                                    out error);
-                                       if (error != MonoIOError.ERROR_SUCCESS) {
-                                               // don't leak the path information for isolated storage
-                                               throw MonoIO.GetException (GetSecureFileName (name), error);
+                                       if (CanSeek == true && !isExposed) {
+                                               MonoIO.Seek (safeHandle, buf_start, SeekOrigin.Begin, out error);
+
+                                               if (error != MonoIOError.ERROR_SUCCESS) {
+                                                       // don't leak the path information for isolated storage
+                                                       throw MonoIO.GetException (GetSecureFileName (name), error);
+                                               }
                                        }
-                               }
-                               if (st == null) {
+
                                        int wcount = buf_length;
                                        int offset = 0;
                                        while (wcount > 0){
-                                               int n = MonoIO.Write (handle, buf, 0, buf_length, out error);
+                                               int n = MonoIO.Write (safeHandle, buf, 0, buf_length, out error);
                                                if (error != MonoIOError.ERROR_SUCCESS) {
                                                        // don't leak the path information for isolated storage
                                                        throw MonoIO.GetException (GetSecureFileName (name), error);
@@ -1031,9 +1052,9 @@ namespace System.IO
                                                wcount -= n;
                                                offset += n;
                                        }
-                               } else {
-                                       st.Write (buf, 0, buf_length);
-                               }
+//                             } else {
+//                                     st.Write (buf, 0, buf_length);
+//                             }
                        }
 
                        buf_start += buf_offset;
@@ -1041,26 +1062,20 @@ namespace System.IO
                        buf_dirty = false;
                }
 
-               private void FlushBuffer ()
-               {
-                       FlushBuffer (null);
-               }
-
                private void FlushBufferIfDirty ()
                {
                        if (buf_dirty)
-                               FlushBuffer (null);
+                               FlushBuffer ();
                }
 
                private void RefillBuffer ()
                {
-                       FlushBuffer (null);
-                       
-                       buf_length = ReadData (handle, buf, 0,
-                                              buf_size);
+                       FlushBuffer ();
+
+                       buf_length = ReadData (safeHandle, buf, 0, buf_size);
                }
 
-               private int ReadData (IntPtr handle, byte[] buf, int offset,
+               private int ReadData (SafeHandle safeHandle, byte[] buf, int offset,
                                      int count)
                {
                        MonoIOError error;
@@ -1068,7 +1083,7 @@ namespace System.IO
 
                        /* when async == true, if we get here we don't suport AIO or it's disabled
                         * and we're using the threadpool */
-                       amount = MonoIO.Read (handle, buf, offset, count, out error);
+                       amount = MonoIO.Read (safeHandle, buf, offset, count, out error);
                        if (error == MonoIOError.ERROR_BROKEN_PIPE) {
                                amount = 0; // might not be needed, but well...
                        } else if (error != MonoIOError.ERROR_SUCCESS) {
@@ -1142,11 +1157,10 @@ namespace System.IO
                private byte [] buf;                    // the buffer
                private string name = "[Unknown]";      // name of file.
 
-               SafeFileHandle safeHandle;              // set only when using one of the
-                                                       // constructors taking SafeFileHandle
+               private SafeFileHandle safeHandle;
+               private bool isExposed;
 
                private long append_startpos;
-               IntPtr handle;                          // handle to underlying file
 
                private FileAccess access;
                private bool owner;